From 462b0b052c25b56024dc05bd9f5822fa3ea5eb83 Mon Sep 17 00:00:00 2001 From: Kevin Rocard Date: Fri, 23 Feb 2018 15:19:28 -0800 Subject: [PATCH 001/718] Audio V4: Remove system only enum values Some enum values only used by the system were exposed to the vendor for legacy reason. Remove them. Bug: 38184704 Test: compile Change-Id: I78254047a74d08bcdf2d7b285e874dbd497d5407 Signed-off-by: Kevin Rocard --- audio/common/4.0/types.hal | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/audio/common/4.0/types.hal b/audio/common/4.0/types.hal index 4efdea3fa4..0adff734d3 100644 --- a/audio/common/4.0/types.hal +++ b/audio/common/4.0/types.hal @@ -104,8 +104,6 @@ enum AudioStreamType : int32_t { TTS = 9, // Transmitted Through Speaker. Plays over speaker // only, silent on other devices ACCESSIBILITY = 10, // For accessibility talk back prompts - REROUTING = 11, // For dynamic policy output mixes - PATCH = 12, // For internal audio flinger tracks. Fixed volume }; @export(name="audio_source_t", value_prefix="AUDIO_SOURCE_") @@ -657,6 +655,8 @@ enum AudioUsage : int32_t { /** Type of audio generated by an application. */ @export(name="audio_content_type_t", value_prefix="AUDIO_CONTENT_TYPE_") enum AudioContentType : uint32_t { + // Do not change these values without updating their counterparts + // in frameworks/base/media/java/android/media/AudioAttributes.java UNKNOWN = 0, SPEECH = 1, MUSIC = 2, From 97331361d06ed94e0bd71c15edb4cbabe2d0221d Mon Sep 17 00:00:00 2001 From: Kevin Rocard Date: Fri, 23 Feb 2018 18:43:39 -0800 Subject: [PATCH 002/718] Audio V4: Do not forward notification detail Those values are only for the framework, thus they should not be available to the vendor. Bug: 38184704 Test: compile Change-Id: I05d3e506a85dbe66d51b7024fa9de45865bcf9db Signed-off-by: Kevin Rocard --- .../common/all-versions/default/HidlUtils.h | 2 ++ .../all-versions/default/HidlUtils.impl.h | 20 +++++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.h b/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.h index 1654ac6e34..f9a5697418 100644 --- a/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.h +++ b/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.h @@ -47,6 +47,8 @@ class HidlUtils { struct audio_gain_config* halConfig); static void audioGainFromHal(const struct audio_gain& halGain, AudioGain* gain); static void audioGainToHal(const AudioGain& gain, struct audio_gain* halGain); + static AudioUsage audioUsageFromHal(const audio_usage_t halUsage); + static audio_usage_t audioUsageToHal(const AudioUsage usage); static void audioOffloadInfoFromHal(const audio_offload_info_t& halOffload, AudioOffloadInfo* offload); static void audioOffloadInfoToHal(const AudioOffloadInfo& offload, diff --git a/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.impl.h b/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.impl.h index 935f307cdc..26ad51824f 100644 --- a/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.impl.h +++ b/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.impl.h @@ -100,6 +100,22 @@ void HidlUtils::audioGainToHal(const AudioGain& gain, struct audio_gain* halGain halGain->max_ramp_ms = gain.maxRampMs; } +AudioUsage HidlUtils::audioUsageFromHal(const audio_usage_t halUsage) { + switch (halUsage) { + case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST: + case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT: + case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED: + case AUDIO_USAGE_NOTIFICATION_EVENT: + return AudioUsage::NOTIFICATION; + default: + return static_cast(halUsage); + } +} + +audio_usage_t HidlUtils::audioUsageToHal(const AudioUsage usage) { + return static_cast(usage); +} + void HidlUtils::audioOffloadInfoFromHal(const audio_offload_info_t& halOffload, AudioOffloadInfo* offload) { offload->sampleRateHz = halOffload.sample_rate; @@ -112,7 +128,7 @@ void HidlUtils::audioOffloadInfoFromHal(const audio_offload_info_t& halOffload, offload->isStreaming = halOffload.is_streaming; offload->bitWidth = halOffload.bit_width; offload->bufferSize = halOffload.offload_buffer_size; - offload->usage = static_cast(halOffload.usage); + offload->usage = audioUsageFromHal(halOffload.usage); } void HidlUtils::audioOffloadInfoToHal(const AudioOffloadInfo& offload, @@ -128,7 +144,7 @@ void HidlUtils::audioOffloadInfoToHal(const AudioOffloadInfo& offload, halOffload->is_streaming = offload.isStreaming; halOffload->bit_width = offload.bitWidth; halOffload->offload_buffer_size = offload.bufferSize; - halOffload->usage = static_cast(offload.usage); + halOffload->usage = audioUsageToHal(offload.usage); } void HidlUtils::audioPortConfigFromHal(const struct audio_port_config& halConfig, From bac56be1aecd7306e9a01d2ebab0dff0d8405901 Mon Sep 17 00:00:00 2001 From: Kevin Rocard Date: Fri, 23 Feb 2018 18:45:58 -0800 Subject: [PATCH 003/718] Audio V4: Add V4 common utils Bug: 38184704 Test: compile Change-Id: I935fe4343ab517f7a8dc65e1b9720097a3ab34da Signed-off-by: Kevin Rocard --- audio/common/2.0/default/OWNERS | 3 ++ audio/common/4.0/default/Android.bp | 47 ++++++++++++++++++++++++++ audio/common/4.0/default/HidlUtils.cpp | 21 ++++++++++++ audio/common/4.0/default/HidlUtils.h | 26 ++++++++++++++ audio/common/4.0/default/OWNERS | 3 ++ 5 files changed, 100 insertions(+) create mode 100644 audio/common/2.0/default/OWNERS create mode 100644 audio/common/4.0/default/Android.bp create mode 100644 audio/common/4.0/default/HidlUtils.cpp create mode 100644 audio/common/4.0/default/HidlUtils.h create mode 100644 audio/common/4.0/default/OWNERS diff --git a/audio/common/2.0/default/OWNERS b/audio/common/2.0/default/OWNERS new file mode 100644 index 0000000000..6fdc97ca29 --- /dev/null +++ b/audio/common/2.0/default/OWNERS @@ -0,0 +1,3 @@ +elaurent@google.com +krocard@google.com +mnaganov@google.com diff --git a/audio/common/4.0/default/Android.bp b/audio/common/4.0/default/Android.bp new file mode 100644 index 0000000000..57b2e01f3d --- /dev/null +++ b/audio/common/4.0/default/Android.bp @@ -0,0 +1,47 @@ +// +// Copyright (C) 2018 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +cc_library_shared { + name: "android.hardware.audio.common@4.0-util", + defaults: ["hidl_defaults"], + vendor_available: true, + vndk: { + enabled: true, + }, + srcs: [ + "HidlUtils.cpp", + ], + + export_include_dirs: ["."], + + static_libs: [ + ], + + shared_libs: [ + "liblog", + "libutils", + "libhidlbase", + "android.hardware.audio.common-util", + "android.hardware.audio.common@4.0", + ], + export_shared_lib_headers: [ + "android.hardware.audio.common-util" + ], + + header_libs: [ + "libaudio_system_headers", + "libhardware_headers", + ], +} diff --git a/audio/common/4.0/default/HidlUtils.cpp b/audio/common/4.0/default/HidlUtils.cpp new file mode 100644 index 0000000000..b66eff975a --- /dev/null +++ b/audio/common/4.0/default/HidlUtils.cpp @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "HidlUtils.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION diff --git a/audio/common/4.0/default/HidlUtils.h b/audio/common/4.0/default/HidlUtils.h new file mode 100644 index 0000000000..91e6a9e121 --- /dev/null +++ b/audio/common/4.0/default/HidlUtils.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_audio_V4_0_Hidl_Utils_H_ +#define android_hardware_audio_V4_0_Hidl_Utils_H_ + +#include + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION + +#endif // android_hardware_audio_V4_0_Hidl_Utils_H_ diff --git a/audio/common/4.0/default/OWNERS b/audio/common/4.0/default/OWNERS new file mode 100644 index 0000000000..6fdc97ca29 --- /dev/null +++ b/audio/common/4.0/default/OWNERS @@ -0,0 +1,3 @@ +elaurent@google.com +krocard@google.com +mnaganov@google.com From b3f36c07376acc07eb8f6144bd15e27d8ec6d6fc Mon Sep 17 00:00:00 2001 From: Kevin Rocard Date: Mon, 26 Feb 2018 18:45:07 -0800 Subject: [PATCH 004/718] Audio V4: Cast conversion now deduce both types That avoids to repeat the destination type which can change between versions. Bug: 38184704 Test: compile Change-Id: I55c881afe5f6fc511ea01b19c5d46de12fb1e0d2 Signed-off-by: Kevin Rocard --- audio/common/all-versions/default/Android.bp | 4 ++ .../all-versions/default/HidlUtils.impl.h | 21 ++++--- .../common/all-versions/VersionUtils.h | 61 +++++++++++++++++++ 3 files changed, 77 insertions(+), 9 deletions(-) create mode 100644 audio/common/all-versions/util/include/common/all-versions/VersionUtils.h diff --git a/audio/common/all-versions/default/Android.bp b/audio/common/all-versions/default/Android.bp index 8f6b74c96e..4a27bb76cb 100644 --- a/audio/common/all-versions/default/Android.bp +++ b/audio/common/all-versions/default/Android.bp @@ -33,7 +33,11 @@ cc_library_shared { ], header_libs: [ + "android.hardware.audio.common.util@all-versions", "libaudio_system_headers", "libhardware_headers", ], + export_header_lib_headers: [ + "android.hardware.audio.common.util@all-versions", + ] } diff --git a/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.impl.h b/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.impl.h index 26ad51824f..d6f8d3e57d 100644 --- a/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.impl.h +++ b/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.impl.h @@ -18,6 +18,7 @@ #error "AUDIO_HAL_VERSION must be set before including this file." #endif +#include #include using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioChannelMask; @@ -32,6 +33,8 @@ using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioSource; using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioStreamType; using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioUsage; +using ::android::hardware::audio::common::utils::mkEnumConverter; + namespace android { namespace hardware { namespace audio { @@ -40,7 +43,7 @@ namespace AUDIO_HAL_VERSION { void HidlUtils::audioConfigFromHal(const audio_config_t& halConfig, AudioConfig* config) { config->sampleRateHz = halConfig.sample_rate; - config->channelMask = AudioChannelMask(halConfig.channel_mask); + config->channelMask = mkEnumConverter(halConfig.channel_mask); config->format = AudioFormat(halConfig.format); audioOffloadInfoFromHal(halConfig.offload_info, &config->offloadInfo); config->frameCount = halConfig.frame_count; @@ -58,8 +61,8 @@ void HidlUtils::audioConfigToHal(const AudioConfig& config, audio_config_t* halC void HidlUtils::audioGainConfigFromHal(const struct audio_gain_config& halConfig, AudioGainConfig* config) { config->index = halConfig.index; - config->mode = AudioGainMode(halConfig.mode); - config->channelMask = AudioChannelMask(halConfig.channel_mask); + config->mode = mkEnumConverter(halConfig.mode); + config->channelMask = mkEnumConverter(halConfig.channel_mask); for (size_t i = 0; i < sizeof(audio_channel_mask_t) * 8; ++i) { config->values[i] = halConfig.values[i]; } @@ -79,8 +82,8 @@ void HidlUtils::audioGainConfigToHal(const AudioGainConfig& config, } void HidlUtils::audioGainFromHal(const struct audio_gain& halGain, AudioGain* gain) { - gain->mode = AudioGainMode(halGain.mode); - gain->channelMask = AudioChannelMask(halGain.channel_mask); + gain->mode = mkEnumConverter(halGain.mode); + gain->channelMask = mkEnumConverter(halGain.channel_mask); gain->minValue = halGain.min_value; gain->maxValue = halGain.max_value; gain->defaultValue = halGain.default_value; @@ -119,7 +122,7 @@ audio_usage_t HidlUtils::audioUsageToHal(const AudioUsage usage) { void HidlUtils::audioOffloadInfoFromHal(const audio_offload_info_t& halOffload, AudioOffloadInfo* offload) { offload->sampleRateHz = halOffload.sample_rate; - offload->channelMask = AudioChannelMask(halOffload.channel_mask); + offload->channelMask = mkEnumConverter(halOffload.channel_mask); offload->format = AudioFormat(halOffload.format); offload->streamType = AudioStreamType(halOffload.stream_type); offload->bitRatePerSecond = halOffload.bit_rate; @@ -152,9 +155,9 @@ void HidlUtils::audioPortConfigFromHal(const struct audio_port_config& halConfig config->id = halConfig.id; config->role = AudioPortRole(halConfig.role); config->type = AudioPortType(halConfig.type); - config->configMask = AudioPortConfigMask(halConfig.config_mask); + config->configMask = mkEnumConverter(halConfig.config_mask); config->sampleRateHz = halConfig.sample_rate; - config->channelMask = AudioChannelMask(halConfig.channel_mask); + config->channelMask = mkEnumConverter(halConfig.channel_mask); config->format = AudioFormat(halConfig.format); audioGainConfigFromHal(halConfig.gain, &config->gain); switch (halConfig.type) { @@ -254,7 +257,7 @@ void HidlUtils::audioPortFromHal(const struct audio_port& halPort, AudioPort* po } port->channelMasks.resize(halPort.num_channel_masks); for (size_t i = 0; i < halPort.num_channel_masks; ++i) { - port->channelMasks[i] = AudioChannelMask(halPort.channel_masks[i]); + port->channelMasks[i] = mkEnumConverter(halPort.channel_masks[i]); } port->formats.resize(halPort.num_formats); for (size_t i = 0; i < halPort.num_formats; ++i) { diff --git a/audio/common/all-versions/util/include/common/all-versions/VersionUtils.h b/audio/common/all-versions/util/include/common/all-versions/VersionUtils.h new file mode 100644 index 0000000000..a998b0675c --- /dev/null +++ b/audio/common/all-versions/util/include/common/all-versions/VersionUtils.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_audio_common_VersionUtils_H_ +#define android_hardware_audio_common_VersionUtils_H_ + +#include +#include + +namespace android { +namespace hardware { +namespace audio { +namespace common { +namespace utils { + +/** Similar to static_cast but also casts to hidl_bitfield depending on + * return type inference (emulated through user-define conversion). + */ +template +class EnumConverter { + public: + static_assert(std::is_enum::value || std::is_enum::value, + "Source or destination should be an enum"); + + explicit EnumConverter(Source source) : mSource(source) {} + + operator Destination() const { return static_cast(mSource); } + + template ::value>> + operator ::android::hardware::hidl_bitfield() { + return static_cast>(mSource); + } + + private: + const Source mSource; +}; +template +auto mkEnumConverter(Source source) { + return EnumConverter{source}; +} + +} // namespace utils +} // namespace common +} // namespace audio +} // namespace hardware +} // namespace android + +#endif // android_hardware_audio_common_VersionUtils_H_ From 7ee6feee9f21ee803f10341d6901c59f6fd4c5fd Mon Sep 17 00:00:00 2001 From: Kevin Rocard Date: Tue, 27 Feb 2018 10:56:32 -0800 Subject: [PATCH 005/718] Fix potential missing '\0' when wrapping to legacy The HAL API for port name is a C++ string of arbitrary length. Nevertheless the legacy API name had a maximum length. Thus when wrapping from the new to legacy, the string was truncated but no '\0' was added. Bug: 38184704 Test: compile Change-Id: I482363809718281e022041c2d5042e5800c5a617 Signed-off-by: Kevin Rocard --- .../include/common/all-versions/default/HidlUtils.impl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.impl.h b/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.impl.h index d6f8d3e57d..8ab73501bc 100644 --- a/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.impl.h +++ b/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.impl.h @@ -296,8 +296,8 @@ void HidlUtils::audioPortToHal(const AudioPort& port, struct audio_port* halPort halPort->id = port.id; halPort->role = static_cast(port.role); halPort->type = static_cast(port.type); - memcpy(halPort->name, port.name.c_str(), - std::min(port.name.size(), static_cast(AUDIO_PORT_MAX_NAME_LEN))); + strncpy(halPort->name, port.name.c_str(), AUDIO_PORT_MAX_NAME_LEN); + halPort->name[AUDIO_PORT_MAX_NAME_LEN - 1] = '\0'; halPort->num_sample_rates = std::min(port.sampleRates.size(), static_cast(AUDIO_PORT_MAX_SAMPLING_RATES)); for (size_t i = 0; i < halPort->num_sample_rates; ++i) { From f6637595aa52b10bdcb4738f35fa4c196f86bc74 Mon Sep 17 00:00:00 2001 From: Kevin Rocard Date: Wed, 28 Feb 2018 15:15:07 -0800 Subject: [PATCH 006/718] Audio V4: Use string to identify audio Device The name of an audio device is an opaque string that the framework does not interpret (there are exceptions, see documentation) and only uses as an ID to link the audio_policy_configuration.xml and the audio device factory. Previously it was an enum which meant that the vendors could not implement the interface more than a set number of time and that generic meaningless (secondary, auxiliary) names had to be introduced. Bug: 38184704 Test: compile Change-Id: I9f3ac1928de8116974257951e016108c5820eded Signed-off-by: Kevin Rocard --- audio/4.0/IDevicesFactory.hal | 45 +++++++++---------- .../4.0/config/audio_policy_configuration.xsd | 31 +------------ 2 files changed, 21 insertions(+), 55 deletions(-) diff --git a/audio/4.0/IDevicesFactory.hal b/audio/4.0/IDevicesFactory.hal index c552c6ddd2..987fd68e5c 100644 --- a/audio/4.0/IDevicesFactory.hal +++ b/audio/4.0/IDevicesFactory.hal @@ -19,41 +19,36 @@ package android.hardware.audio@4.0; import android.hardware.audio.common@4.0; import IDevice; +/** This factory allows a HAL implementation to be split in multiple independent + * devices (called module in the pre-treble API). + * Note that this division is arbitrary and implementation are free + * to only have a Primary. + * The framework will query the devices according to audio_policy_configuration.xml + * + * Each device name is arbitrary, provided by the vendor's audio_policy_configuration.xml + * and only used to identify a device in this factory. + * The framework must not interpret the name, treating it as a vendor opaque data + * with the following exceptions: + * - the "primary" device must always be present and is the device used by the telephony framework. + * - the "r_submix" device that must be present to support policyMixes (Eg: Android projected). + * Note that this Device is included by default in a build derived from AOSP. + * + * Note that on AOSP Oreo (including MR1) the "a2dp" module is not using this API + * but is loaded directly from the system partition using the legacy API + * due to limitations with the Bluetooth framework. + */ interface IDevicesFactory { - /** Allows a HAL implementation to be split in multiple independent - * devices (called module in the pre-treble API). - * Note that this division is arbitrary and implementation are free - * to only have a Primary. - * The framework will query the devices according to audio_policy_configuration.xml - * - * Each Device value is interchangeable with any other and the framework - * does not differentiate between values with the following exceptions: - * - the Primary device must always be present - * - the R_SUBMIX that is used to forward audio of REMOTE_SUBMIX DEVICES - */ - enum Device : int32_t { - PRIMARY, - A2DP, - USB, - R_SUBMIX, - STUB, - CODEC_OFFLOAD, - SECONDARY, - AUXILIARY, - /** Multi Stream Decoder */ - MSD - }; /** * Opens an audio device. To close the device, it is necessary to release * references to the returned device object. * - * @param device device type. + * @param device device name. * @return retval operation completion status. Returns INVALID_ARGUMENTS * if there is no corresponding hardware module found, * NOT_INITIALIZED if an error occured while opening the hardware * module. * @return result the interface for the created device. */ - openDevice(Device device) generates (Result retval, IDevice result); + openDevice(string device) generates (Result retval, IDevice result); }; diff --git a/audio/4.0/config/audio_policy_configuration.xsd b/audio/4.0/config/audio_policy_configuration.xsd index 924fb4715b..e5b444994a 100644 --- a/audio/4.0/config/audio_policy_configuration.xsd +++ b/audio/4.0/config/audio_policy_configuration.xsd @@ -66,35 +66,6 @@ - - - - - - - - - - - - - - - - - Vendor eXtension names must be in the vx namespace. - Vendor are encouraged to namespace their module names. - Example for an hypothetical Google virtual reality HAL: - - - - - - - - - @@ -133,7 +104,7 @@ - + From ab1f548cf13a7619175360bb2c563f28414fe84a Mon Sep 17 00:00:00 2001 From: Kevin Rocard Date: Wed, 28 Feb 2018 21:46:26 -0800 Subject: [PATCH 007/718] Audio V4: Update .hal doc to removal of audioSource As multiple tracks can be connected to the same stream, the audio source list can be found in metadata. Bug: 38184704 Test: none Change-Id: I63e75fd4049fbe469b78cacf0adf44e9597cb422 Signed-off-by: Kevin Rocard --- audio/4.0/IDevice.hal | 1 - 1 file changed, 1 deletion(-) diff --git a/audio/4.0/IDevice.hal b/audio/4.0/IDevice.hal index 7eb03c8d95..1bb5abaa61 100644 --- a/audio/4.0/IDevice.hal +++ b/audio/4.0/IDevice.hal @@ -132,7 +132,6 @@ interface IDevice { * @param device device type and (if needed) address. * @param config stream configuration. * @param flags additional flags. - * @param source source specification. * @param sinkMetadata Description of the audio that is suggested by the client. * May be used by implementations to configure hardware effects. * @return retval operation completion status. From 30a7fcca2922536c0a1f402c3c21bdf3a2008514 Mon Sep 17 00:00:00 2001 From: Kevin Rocard Date: Thu, 1 Mar 2018 15:08:07 -0800 Subject: [PATCH 008/718] Audio V4: Implement the shim effect 4.0 -> legacy All the new files added are a copy of the 2.0 ones, with just the version 2 that was changed to 4. Due to the rollback on the retrocompatiblity breakage, the split of implementation is not strictly needed any more. This makes the current split in .impl.h and double include unnecessary complicated. This will need to be factorized in a future patch. Bug: 38184704 Test: compile Change-Id: If412eb55ebf6afc773593547af9395a09b6825c2 Signed-off-by: Kevin Rocard --- audio/common/2.0/default/VersionUtils.h | 39 +++++++++++++++ audio/common/4.0/default/VersionUtils.h | 39 +++++++++++++++ .../default/AcousticEchoCancelerEffect.cpp | 23 +++++++++ .../4.0/default/AcousticEchoCancelerEffect.h | 28 +++++++++++ audio/effect/4.0/default/Android.bp | 50 +++++++++++++++++++ .../effect/4.0/default/AudioBufferManager.cpp | 21 ++++++++ audio/effect/4.0/default/AudioBufferManager.h | 26 ++++++++++ .../default/AutomaticGainControlEffect.cpp | 23 +++++++++ .../4.0/default/AutomaticGainControlEffect.h | 28 +++++++++++ audio/effect/4.0/default/BassBoostEffect.cpp | 23 +++++++++ audio/effect/4.0/default/BassBoostEffect.h | 30 +++++++++++ audio/effect/4.0/default/Conversions.cpp | 24 +++++++++ audio/effect/4.0/default/Conversions.h | 26 ++++++++++ audio/effect/4.0/default/DownmixEffect.cpp | 23 +++++++++ audio/effect/4.0/default/DownmixEffect.h | 28 +++++++++++ audio/effect/4.0/default/Effect.cpp | 28 +++++++++++ audio/effect/4.0/default/Effect.h | 28 +++++++++++ audio/effect/4.0/default/EffectsFactory.cpp | 39 +++++++++++++++ audio/effect/4.0/default/EffectsFactory.h | 29 +++++++++++ .../4.0/default/EnvironmentalReverbEffect.cpp | 24 +++++++++ .../4.0/default/EnvironmentalReverbEffect.h | 30 +++++++++++ audio/effect/4.0/default/EqualizerEffect.cpp | 23 +++++++++ audio/effect/4.0/default/EqualizerEffect.h | 28 +++++++++++ .../4.0/default/LoudnessEnhancerEffect.cpp | 23 +++++++++ .../4.0/default/LoudnessEnhancerEffect.h | 28 +++++++++++ .../4.0/default/NoiseSuppressionEffect.cpp | 23 +++++++++ .../4.0/default/NoiseSuppressionEffect.h | 28 +++++++++++ audio/effect/4.0/default/OWNERS | 3 ++ .../effect/4.0/default/PresetReverbEffect.cpp | 23 +++++++++ audio/effect/4.0/default/PresetReverbEffect.h | 28 +++++++++++ .../effect/4.0/default/VirtualizerEffect.cpp | 23 +++++++++ audio/effect/4.0/default/VirtualizerEffect.h | 28 +++++++++++ audio/effect/4.0/default/VisualizerEffect.cpp | 23 +++++++++ audio/effect/4.0/default/VisualizerEffect.h | 28 +++++++++++ .../default/AcousticEchoCancelerEffect.h | 6 ++- .../default/AcousticEchoCancelerEffect.impl.h | 6 ++- .../default/AutomaticGainControlEffect.h | 6 ++- .../default/AutomaticGainControlEffect.impl.h | 6 ++- .../all-versions/default/BassBoostEffect.h | 6 ++- .../default/BassBoostEffect.impl.h | 6 ++- .../all-versions/default/DownmixEffect.h | 6 ++- .../all-versions/default/DownmixEffect.impl.h | 6 ++- .../effect/all-versions/default/Effect.h | 7 ++- .../effect/all-versions/default/Effect.impl.h | 15 +++--- .../all-versions/default/EffectsFactory.h | 2 +- .../default/EnvironmentalReverbEffect.h | 6 ++- .../default/EnvironmentalReverbEffect.impl.h | 6 ++- .../all-versions/default/EqualizerEffect.h | 6 ++- .../default/EqualizerEffect.impl.h | 6 ++- .../default/LoudnessEnhancerEffect.h | 6 ++- .../default/LoudnessEnhancerEffect.impl.h | 6 ++- .../default/NoiseSuppressionEffect.h | 6 ++- .../default/NoiseSuppressionEffect.impl.h | 6 ++- .../all-versions/default/PresetReverbEffect.h | 6 ++- .../default/PresetReverbEffect.impl.h | 6 ++- .../all-versions/default/VirtualizerEffect.h | 9 ++-- .../default/VirtualizerEffect.impl.h | 11 ++-- .../all-versions/default/VisualizerEffect.h | 6 ++- .../default/VisualizerEffect.impl.h | 6 ++- 59 files changed, 1026 insertions(+), 56 deletions(-) create mode 100644 audio/common/2.0/default/VersionUtils.h create mode 100644 audio/common/4.0/default/VersionUtils.h create mode 100644 audio/effect/4.0/default/AcousticEchoCancelerEffect.cpp create mode 100644 audio/effect/4.0/default/AcousticEchoCancelerEffect.h create mode 100644 audio/effect/4.0/default/Android.bp create mode 100644 audio/effect/4.0/default/AudioBufferManager.cpp create mode 100644 audio/effect/4.0/default/AudioBufferManager.h create mode 100644 audio/effect/4.0/default/AutomaticGainControlEffect.cpp create mode 100644 audio/effect/4.0/default/AutomaticGainControlEffect.h create mode 100644 audio/effect/4.0/default/BassBoostEffect.cpp create mode 100644 audio/effect/4.0/default/BassBoostEffect.h create mode 100644 audio/effect/4.0/default/Conversions.cpp create mode 100644 audio/effect/4.0/default/Conversions.h create mode 100644 audio/effect/4.0/default/DownmixEffect.cpp create mode 100644 audio/effect/4.0/default/DownmixEffect.h create mode 100644 audio/effect/4.0/default/Effect.cpp create mode 100644 audio/effect/4.0/default/Effect.h create mode 100644 audio/effect/4.0/default/EffectsFactory.cpp create mode 100644 audio/effect/4.0/default/EffectsFactory.h create mode 100644 audio/effect/4.0/default/EnvironmentalReverbEffect.cpp create mode 100644 audio/effect/4.0/default/EnvironmentalReverbEffect.h create mode 100644 audio/effect/4.0/default/EqualizerEffect.cpp create mode 100644 audio/effect/4.0/default/EqualizerEffect.h create mode 100644 audio/effect/4.0/default/LoudnessEnhancerEffect.cpp create mode 100644 audio/effect/4.0/default/LoudnessEnhancerEffect.h create mode 100644 audio/effect/4.0/default/NoiseSuppressionEffect.cpp create mode 100644 audio/effect/4.0/default/NoiseSuppressionEffect.h create mode 100644 audio/effect/4.0/default/OWNERS create mode 100644 audio/effect/4.0/default/PresetReverbEffect.cpp create mode 100644 audio/effect/4.0/default/PresetReverbEffect.h create mode 100644 audio/effect/4.0/default/VirtualizerEffect.cpp create mode 100644 audio/effect/4.0/default/VirtualizerEffect.h create mode 100644 audio/effect/4.0/default/VisualizerEffect.cpp create mode 100644 audio/effect/4.0/default/VisualizerEffect.h diff --git a/audio/common/2.0/default/VersionUtils.h b/audio/common/2.0/default/VersionUtils.h new file mode 100644 index 0000000000..fef468080e --- /dev/null +++ b/audio/common/2.0/default/VersionUtils.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_VERSION_UTILS_H +#define ANDROID_HARDWARE_AUDIO_EFFECT_VERSION_UTILS_H + +#include + +namespace android { +namespace hardware { +namespace audio { +namespace common { +namespace V2_0 { +namespace implementation { + +typedef common::V2_0::AudioDevice AudioDeviceBitfield; +typedef common::V2_0::AudioChannelMask AudioChannelBitfield; + +} // namespace implementation +} // namespace V2_0 +} // namespace common +} // namespace audio +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_AUDIO_EFFECT_VERSION_UTILS_H diff --git a/audio/common/4.0/default/VersionUtils.h b/audio/common/4.0/default/VersionUtils.h new file mode 100644 index 0000000000..515c792222 --- /dev/null +++ b/audio/common/4.0/default/VersionUtils.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_VERSION_UTILS_H +#define ANDROID_HARDWARE_AUDIO_EFFECT_VERSION_UTILS_H + +#include + +namespace android { +namespace hardware { +namespace audio { +namespace common { +namespace V4_0 { +namespace implementation { + +typedef hidl_bitfield AudioDeviceBitfield; +typedef hidl_bitfield AudioChannelBitfield; + +} // namespace implementation +} // namespace V4_0 +} // namespace common +} // namespace audio +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_AUDIO_EFFECT_VERSION_UTILS_H diff --git a/audio/effect/4.0/default/AcousticEchoCancelerEffect.cpp b/audio/effect/4.0/default/AcousticEchoCancelerEffect.cpp new file mode 100644 index 0000000000..242740e582 --- /dev/null +++ b/audio/effect/4.0/default/AcousticEchoCancelerEffect.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "AEC_Effect_HAL" + +#include "AcousticEchoCancelerEffect.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION diff --git a/audio/effect/4.0/default/AcousticEchoCancelerEffect.h b/audio/effect/4.0/default/AcousticEchoCancelerEffect.h new file mode 100644 index 0000000000..0ac0a1e0df --- /dev/null +++ b/audio/effect/4.0/default/AcousticEchoCancelerEffect.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_ACOUSTICECHOCANCELEREFFECT_H +#define ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_ACOUSTICECHOCANCELEREFFECT_H + +#include + +#include "Effect.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION + +#endif // ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_ACOUSTICECHOCANCELEREFFECT_H diff --git a/audio/effect/4.0/default/Android.bp b/audio/effect/4.0/default/Android.bp new file mode 100644 index 0000000000..dcb2269a9b --- /dev/null +++ b/audio/effect/4.0/default/Android.bp @@ -0,0 +1,50 @@ +cc_library_shared { + name: "android.hardware.audio.effect@4.0-impl", + defaults: ["hidl_defaults"], + vendor: true, + relative_install_path: "hw", + srcs: [ + "AcousticEchoCancelerEffect.cpp", + "AudioBufferManager.cpp", + "AutomaticGainControlEffect.cpp", + "BassBoostEffect.cpp", + "Conversions.cpp", + "DownmixEffect.cpp", + "Effect.cpp", + "EffectsFactory.cpp", + "EnvironmentalReverbEffect.cpp", + "EqualizerEffect.cpp", + "LoudnessEnhancerEffect.cpp", + "NoiseSuppressionEffect.cpp", + "PresetReverbEffect.cpp", + "VirtualizerEffect.cpp", + "VisualizerEffect.cpp", + ], + + shared_libs: [ + "libbase", + "libcutils", + "libeffects", + "libfmq", + "libhidlbase", + "libhidlmemory", + "libhidltransport", + "liblog", + "libutils", + "android.hardware.audio.common-util", + "android.hardware.audio.common@4.0", + "android.hardware.audio.common@4.0-util", + "android.hardware.audio.effect@4.0", + "android.hidl.memory@1.0", + ], + + header_libs: [ + "android.hardware.audio.common.util@all-versions", + "android.hardware.audio.effect@all-versions-impl", + "libaudio_system_headers", + "libaudioclient_headers", + "libeffects_headers", + "libhardware_headers", + "libmedia_headers", + ], +} diff --git a/audio/effect/4.0/default/AudioBufferManager.cpp b/audio/effect/4.0/default/AudioBufferManager.cpp new file mode 100644 index 0000000000..2d75f3fdbb --- /dev/null +++ b/audio/effect/4.0/default/AudioBufferManager.cpp @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "AudioBufferManager.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION diff --git a/audio/effect/4.0/default/AudioBufferManager.h b/audio/effect/4.0/default/AudioBufferManager.h new file mode 100644 index 0000000000..1f151e6b99 --- /dev/null +++ b/audio/effect/4.0/default/AudioBufferManager.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_AUDIO_BUFFER_MANAGER_H_ +#define ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_AUDIO_BUFFER_MANAGER_H_ + +#include + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION + +#endif // ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_AUDIO_BUFFER_MANAGER_H_ diff --git a/audio/effect/4.0/default/AutomaticGainControlEffect.cpp b/audio/effect/4.0/default/AutomaticGainControlEffect.cpp new file mode 100644 index 0000000000..9d21c8ae6b --- /dev/null +++ b/audio/effect/4.0/default/AutomaticGainControlEffect.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "AGC_Effect_HAL" + +#include "AutomaticGainControlEffect.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION diff --git a/audio/effect/4.0/default/AutomaticGainControlEffect.h b/audio/effect/4.0/default/AutomaticGainControlEffect.h new file mode 100644 index 0000000000..7f12007f8f --- /dev/null +++ b/audio/effect/4.0/default/AutomaticGainControlEffect.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_AUTOMATICGAINCONTROLEFFECT_H +#define ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_AUTOMATICGAINCONTROLEFFECT_H + +#include + +#include "Effect.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION + +#endif // ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_AUTOMATICGAINCONTROLEFFECT_H diff --git a/audio/effect/4.0/default/BassBoostEffect.cpp b/audio/effect/4.0/default/BassBoostEffect.cpp new file mode 100644 index 0000000000..74a626b79e --- /dev/null +++ b/audio/effect/4.0/default/BassBoostEffect.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "BassBoost_HAL" + +#include "BassBoostEffect.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION diff --git a/audio/effect/4.0/default/BassBoostEffect.h b/audio/effect/4.0/default/BassBoostEffect.h new file mode 100644 index 0000000000..206a75fab4 --- /dev/null +++ b/audio/effect/4.0/default/BassBoostEffect.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_BASSBOOSTEFFECT_H +#define ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_BASSBOOSTEFFECT_H + +#include + +#include + +#include "Effect.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION + +#endif // ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_BASSBOOSTEFFECT_H diff --git a/audio/effect/4.0/default/Conversions.cpp b/audio/effect/4.0/default/Conversions.cpp new file mode 100644 index 0000000000..91285ae6b8 --- /dev/null +++ b/audio/effect/4.0/default/Conversions.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Conversions.h" +#include "HidlUtils.h" + +using ::android::hardware::audio::common::V4_0::HidlUtils; + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION diff --git a/audio/effect/4.0/default/Conversions.h b/audio/effect/4.0/default/Conversions.h new file mode 100644 index 0000000000..50e380fe2e --- /dev/null +++ b/audio/effect/4.0/default/Conversions.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_CONVERSIONS_H_ +#define ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_CONVERSIONS_H_ + +#include + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION + +#endif // ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_CONVERSIONS_H_ diff --git a/audio/effect/4.0/default/DownmixEffect.cpp b/audio/effect/4.0/default/DownmixEffect.cpp new file mode 100644 index 0000000000..07fcab2f1c --- /dev/null +++ b/audio/effect/4.0/default/DownmixEffect.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "Downmix_HAL" + +#include "DownmixEffect.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION diff --git a/audio/effect/4.0/default/DownmixEffect.h b/audio/effect/4.0/default/DownmixEffect.h new file mode 100644 index 0000000000..5ae820b76f --- /dev/null +++ b/audio/effect/4.0/default/DownmixEffect.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_DOWNMIXEFFECT_H +#define ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_DOWNMIXEFFECT_H + +#include + +#include "Effect.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION + +#endif // ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_DOWNMIXEFFECT_H diff --git a/audio/effect/4.0/default/Effect.cpp b/audio/effect/4.0/default/Effect.cpp new file mode 100644 index 0000000000..707044bff0 --- /dev/null +++ b/audio/effect/4.0/default/Effect.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#define LOG_TAG "EffectHAL" +#define ATRACE_TAG ATRACE_TAG_AUDIO + +#include "Conversions.h" +#include "Effect.h" +#include "common/all-versions/default/EffectMap.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION diff --git a/audio/effect/4.0/default/Effect.h b/audio/effect/4.0/default/Effect.h new file mode 100644 index 0000000000..9ca79c4596 --- /dev/null +++ b/audio/effect/4.0/default/Effect.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_EFFECT_H +#define ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_EFFECT_H + +#include + +#include "AudioBufferManager.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION + +#endif // ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_EFFECT_H diff --git a/audio/effect/4.0/default/EffectsFactory.cpp b/audio/effect/4.0/default/EffectsFactory.cpp new file mode 100644 index 0000000000..ee0413df8f --- /dev/null +++ b/audio/effect/4.0/default/EffectsFactory.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "EffectFactoryHAL" +#include "EffectsFactory.h" +#include "AcousticEchoCancelerEffect.h" +#include "AutomaticGainControlEffect.h" +#include "BassBoostEffect.h" +#include "Conversions.h" +#include "DownmixEffect.h" +#include "Effect.h" +#include "EnvironmentalReverbEffect.h" +#include "EqualizerEffect.h" +#include "HidlUtils.h" +#include "LoudnessEnhancerEffect.h" +#include "NoiseSuppressionEffect.h" +#include "PresetReverbEffect.h" +#include "VirtualizerEffect.h" +#include "VisualizerEffect.h" +#include "common/all-versions/default/EffectMap.h" + +using ::android::hardware::audio::common::V4_0::HidlUtils; + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION diff --git a/audio/effect/4.0/default/EffectsFactory.h b/audio/effect/4.0/default/EffectsFactory.h new file mode 100644 index 0000000000..48e4b4cb9f --- /dev/null +++ b/audio/effect/4.0/default/EffectsFactory.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_EFFECTSFACTORY_H +#define ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_EFFECTSFACTORY_H + +#include + +#include + +#include +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION + +#endif // ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_EFFECTSFACTORY_H diff --git a/audio/effect/4.0/default/EnvironmentalReverbEffect.cpp b/audio/effect/4.0/default/EnvironmentalReverbEffect.cpp new file mode 100644 index 0000000000..cc3102d1f8 --- /dev/null +++ b/audio/effect/4.0/default/EnvironmentalReverbEffect.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "EnvReverb_HAL" +#include + +#include "EnvironmentalReverbEffect.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION diff --git a/audio/effect/4.0/default/EnvironmentalReverbEffect.h b/audio/effect/4.0/default/EnvironmentalReverbEffect.h new file mode 100644 index 0000000000..c0fb25c02c --- /dev/null +++ b/audio/effect/4.0/default/EnvironmentalReverbEffect.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_ENVIRONMENTALREVERBEFFECT_H +#define ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_ENVIRONMENTALREVERBEFFECT_H + +#include + +#include + +#include "Effect.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION + +#endif // ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_ENVIRONMENTALREVERBEFFECT_H diff --git a/audio/effect/4.0/default/EqualizerEffect.cpp b/audio/effect/4.0/default/EqualizerEffect.cpp new file mode 100644 index 0000000000..d0a40bc3cd --- /dev/null +++ b/audio/effect/4.0/default/EqualizerEffect.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "Equalizer_HAL" + +#include "EqualizerEffect.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION diff --git a/audio/effect/4.0/default/EqualizerEffect.h b/audio/effect/4.0/default/EqualizerEffect.h new file mode 100644 index 0000000000..7c9463b01e --- /dev/null +++ b/audio/effect/4.0/default/EqualizerEffect.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_EQUALIZEREFFECT_H +#define ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_EQUALIZEREFFECT_H + +#include + +#include "Effect.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION + +#endif // ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_EQUALIZEREFFECT_H diff --git a/audio/effect/4.0/default/LoudnessEnhancerEffect.cpp b/audio/effect/4.0/default/LoudnessEnhancerEffect.cpp new file mode 100644 index 0000000000..e3c5184225 --- /dev/null +++ b/audio/effect/4.0/default/LoudnessEnhancerEffect.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "LoudnessEnhancer_HAL" + +#include "LoudnessEnhancerEffect.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION diff --git a/audio/effect/4.0/default/LoudnessEnhancerEffect.h b/audio/effect/4.0/default/LoudnessEnhancerEffect.h new file mode 100644 index 0000000000..64fa26add8 --- /dev/null +++ b/audio/effect/4.0/default/LoudnessEnhancerEffect.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_LOUDNESSENHANCEREFFECT_H +#define ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_LOUDNESSENHANCEREFFECT_H + +#include + +#include "Effect.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION + +#endif // ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_LOUDNESSENHANCEREFFECT_H diff --git a/audio/effect/4.0/default/NoiseSuppressionEffect.cpp b/audio/effect/4.0/default/NoiseSuppressionEffect.cpp new file mode 100644 index 0000000000..e83a8e3373 --- /dev/null +++ b/audio/effect/4.0/default/NoiseSuppressionEffect.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "NS_Effect_HAL" + +#include "NoiseSuppressionEffect.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION diff --git a/audio/effect/4.0/default/NoiseSuppressionEffect.h b/audio/effect/4.0/default/NoiseSuppressionEffect.h new file mode 100644 index 0000000000..36d45afaf7 --- /dev/null +++ b/audio/effect/4.0/default/NoiseSuppressionEffect.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_NOISESUPPRESSIONEFFECT_H +#define ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_NOISESUPPRESSIONEFFECT_H + +#include + +#include "Effect.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION + +#endif // ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_NOISESUPPRESSIONEFFECT_H diff --git a/audio/effect/4.0/default/OWNERS b/audio/effect/4.0/default/OWNERS new file mode 100644 index 0000000000..6fdc97ca29 --- /dev/null +++ b/audio/effect/4.0/default/OWNERS @@ -0,0 +1,3 @@ +elaurent@google.com +krocard@google.com +mnaganov@google.com diff --git a/audio/effect/4.0/default/PresetReverbEffect.cpp b/audio/effect/4.0/default/PresetReverbEffect.cpp new file mode 100644 index 0000000000..0c23be73af --- /dev/null +++ b/audio/effect/4.0/default/PresetReverbEffect.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "PresetReverb_HAL" + +#include "PresetReverbEffect.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION diff --git a/audio/effect/4.0/default/PresetReverbEffect.h b/audio/effect/4.0/default/PresetReverbEffect.h new file mode 100644 index 0000000000..3eeae0a04b --- /dev/null +++ b/audio/effect/4.0/default/PresetReverbEffect.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_PRESETREVERBEFFECT_H +#define ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_PRESETREVERBEFFECT_H + +#include + +#include "Effect.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION + +#endif // ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_PRESETREVERBEFFECT_H diff --git a/audio/effect/4.0/default/VirtualizerEffect.cpp b/audio/effect/4.0/default/VirtualizerEffect.cpp new file mode 100644 index 0000000000..f50e8adb7b --- /dev/null +++ b/audio/effect/4.0/default/VirtualizerEffect.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "Virtualizer_HAL" + +#include "VirtualizerEffect.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION diff --git a/audio/effect/4.0/default/VirtualizerEffect.h b/audio/effect/4.0/default/VirtualizerEffect.h new file mode 100644 index 0000000000..8e7114e569 --- /dev/null +++ b/audio/effect/4.0/default/VirtualizerEffect.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_VIRTUALIZEREFFECT_H +#define ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_VIRTUALIZEREFFECT_H + +#include + +#include "Effect.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION + +#endif // ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_VIRTUALIZEREFFECT_H diff --git a/audio/effect/4.0/default/VisualizerEffect.cpp b/audio/effect/4.0/default/VisualizerEffect.cpp new file mode 100644 index 0000000000..8d4f100ced --- /dev/null +++ b/audio/effect/4.0/default/VisualizerEffect.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "Visualizer_HAL" + +#include "VisualizerEffect.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION diff --git a/audio/effect/4.0/default/VisualizerEffect.h b/audio/effect/4.0/default/VisualizerEffect.h new file mode 100644 index 0000000000..6b5ab9c393 --- /dev/null +++ b/audio/effect/4.0/default/VisualizerEffect.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_VISUALIZEREFFECT_H +#define ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_VISUALIZEREFFECT_H + +#include + +#include "Effect.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION + +#endif // ANDROID_HARDWARE_AUDIO_EFFECT_V4_0_VISUALIZEREFFECT_H diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/AcousticEchoCancelerEffect.h b/audio/effect/all-versions/default/include/effect/all-versions/default/AcousticEchoCancelerEffect.h index b63f2fb937..852cb3fd15 100644 --- a/audio/effect/all-versions/default/include/effect/all-versions/default/AcousticEchoCancelerEffect.h +++ b/audio/effect/all-versions/default/include/effect/all-versions/default/AcousticEchoCancelerEffect.h @@ -20,6 +20,8 @@ #include +#include "VersionUtils.h" + namespace android { namespace hardware { namespace audio { @@ -46,7 +48,7 @@ struct AcousticEchoCancelerEffect : public IAcousticEchoCancelerEffect { Return reset() override; Return enable() override; Return disable() override; - Return setDevice(AudioDevice device) override; + Return setDevice(AudioDeviceBitfield device) override; Return setAndGetVolume(const hidl_vec& volumes, setAndGetVolume_cb _hidl_cb) override; Return volumeChangeNotification(const hidl_vec& volumes) override; @@ -54,7 +56,7 @@ struct AcousticEchoCancelerEffect : public IAcousticEchoCancelerEffect { Return setConfigReverse( const EffectConfig& config, const sp& inputBufferProvider, const sp& outputBufferProvider) override; - Return setInputDevice(AudioDevice device) override; + Return setInputDevice(AudioDeviceBitfield device) override; Return getConfig(getConfig_cb _hidl_cb) override; Return getConfigReverse(getConfigReverse_cb _hidl_cb) override; Return getSupportedAuxChannelsConfigs( diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/AcousticEchoCancelerEffect.impl.h b/audio/effect/all-versions/default/include/effect/all-versions/default/AcousticEchoCancelerEffect.impl.h index bee3607854..8ad80a22a0 100644 --- a/audio/effect/all-versions/default/include/effect/all-versions/default/AcousticEchoCancelerEffect.impl.h +++ b/audio/effect/all-versions/default/include/effect/all-versions/default/AcousticEchoCancelerEffect.impl.h @@ -19,6 +19,8 @@ #include #include +#include "VersionUtils.h" + namespace android { namespace hardware { namespace audio { @@ -54,7 +56,7 @@ Return AcousticEchoCancelerEffect::disable() { return mEffect->disable(); } -Return AcousticEchoCancelerEffect::setDevice(AudioDevice device) { +Return AcousticEchoCancelerEffect::setDevice(AudioDeviceBitfield device) { return mEffect->setDevice(device); } @@ -78,7 +80,7 @@ Return AcousticEchoCancelerEffect::setConfigReverse( return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider); } -Return AcousticEchoCancelerEffect::setInputDevice(AudioDevice device) { +Return AcousticEchoCancelerEffect::setInputDevice(AudioDeviceBitfield device) { return mEffect->setInputDevice(device); } diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/AutomaticGainControlEffect.h b/audio/effect/all-versions/default/include/effect/all-versions/default/AutomaticGainControlEffect.h index 941f45da3c..5ac43eb9bc 100644 --- a/audio/effect/all-versions/default/include/effect/all-versions/default/AutomaticGainControlEffect.h +++ b/audio/effect/all-versions/default/include/effect/all-versions/default/AutomaticGainControlEffect.h @@ -22,6 +22,8 @@ #include +#include "VersionUtils.h" + namespace android { namespace hardware { namespace audio { @@ -48,7 +50,7 @@ struct AutomaticGainControlEffect : public IAutomaticGainControlEffect { Return reset() override; Return enable() override; Return disable() override; - Return setDevice(AudioDevice device) override; + Return setDevice(AudioDeviceBitfield device) override; Return setAndGetVolume(const hidl_vec& volumes, setAndGetVolume_cb _hidl_cb) override; Return volumeChangeNotification(const hidl_vec& volumes) override; @@ -56,7 +58,7 @@ struct AutomaticGainControlEffect : public IAutomaticGainControlEffect { Return setConfigReverse( const EffectConfig& config, const sp& inputBufferProvider, const sp& outputBufferProvider) override; - Return setInputDevice(AudioDevice device) override; + Return setInputDevice(AudioDeviceBitfield device) override; Return getConfig(getConfig_cb _hidl_cb) override; Return getConfigReverse(getConfigReverse_cb _hidl_cb) override; Return getSupportedAuxChannelsConfigs( diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/AutomaticGainControlEffect.impl.h b/audio/effect/all-versions/default/include/effect/all-versions/default/AutomaticGainControlEffect.impl.h index af05d9b780..e2e751e86b 100644 --- a/audio/effect/all-versions/default/include/effect/all-versions/default/AutomaticGainControlEffect.impl.h +++ b/audio/effect/all-versions/default/include/effect/all-versions/default/AutomaticGainControlEffect.impl.h @@ -18,6 +18,8 @@ #include +#include "VersionUtils.h" + namespace android { namespace hardware { namespace audio { @@ -67,7 +69,7 @@ Return AutomaticGainControlEffect::disable() { return mEffect->disable(); } -Return AutomaticGainControlEffect::setDevice(AudioDevice device) { +Return AutomaticGainControlEffect::setDevice(AudioDeviceBitfield device) { return mEffect->setDevice(device); } @@ -91,7 +93,7 @@ Return AutomaticGainControlEffect::setConfigReverse( return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider); } -Return AutomaticGainControlEffect::setInputDevice(AudioDevice device) { +Return AutomaticGainControlEffect::setInputDevice(AudioDeviceBitfield device) { return mEffect->setInputDevice(device); } diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/BassBoostEffect.h b/audio/effect/all-versions/default/include/effect/all-versions/default/BassBoostEffect.h index 00926217b5..29173ddebe 100644 --- a/audio/effect/all-versions/default/include/effect/all-versions/default/BassBoostEffect.h +++ b/audio/effect/all-versions/default/include/effect/all-versions/default/BassBoostEffect.h @@ -20,6 +20,8 @@ #include +#include "VersionUtils.h" + namespace android { namespace hardware { namespace audio { @@ -46,7 +48,7 @@ struct BassBoostEffect : public IBassBoostEffect { Return reset() override; Return enable() override; Return disable() override; - Return setDevice(AudioDevice device) override; + Return setDevice(AudioDeviceBitfield device) override; Return setAndGetVolume(const hidl_vec& volumes, setAndGetVolume_cb _hidl_cb) override; Return volumeChangeNotification(const hidl_vec& volumes) override; @@ -54,7 +56,7 @@ struct BassBoostEffect : public IBassBoostEffect { Return setConfigReverse( const EffectConfig& config, const sp& inputBufferProvider, const sp& outputBufferProvider) override; - Return setInputDevice(AudioDevice device) override; + Return setInputDevice(AudioDeviceBitfield device) override; Return getConfig(getConfig_cb _hidl_cb) override; Return getConfigReverse(getConfigReverse_cb _hidl_cb) override; Return getSupportedAuxChannelsConfigs( diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/BassBoostEffect.impl.h b/audio/effect/all-versions/default/include/effect/all-versions/default/BassBoostEffect.impl.h index 1fc8d1b428..7bcb4a3497 100644 --- a/audio/effect/all-versions/default/include/effect/all-versions/default/BassBoostEffect.impl.h +++ b/audio/effect/all-versions/default/include/effect/all-versions/default/BassBoostEffect.impl.h @@ -19,6 +19,8 @@ #include #include +#include "VersionUtils.h" + namespace android { namespace hardware { namespace audio { @@ -53,7 +55,7 @@ Return BassBoostEffect::disable() { return mEffect->disable(); } -Return BassBoostEffect::setDevice(AudioDevice device) { +Return BassBoostEffect::setDevice(AudioDeviceBitfield device) { return mEffect->setDevice(device); } @@ -76,7 +78,7 @@ Return BassBoostEffect::setConfigReverse( return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider); } -Return BassBoostEffect::setInputDevice(AudioDevice device) { +Return BassBoostEffect::setInputDevice(AudioDeviceBitfield device) { return mEffect->setInputDevice(device); } diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/DownmixEffect.h b/audio/effect/all-versions/default/include/effect/all-versions/default/DownmixEffect.h index e461ca80b7..3e3aa78477 100644 --- a/audio/effect/all-versions/default/include/effect/all-versions/default/DownmixEffect.h +++ b/audio/effect/all-versions/default/include/effect/all-versions/default/DownmixEffect.h @@ -20,6 +20,8 @@ #include +#include "VersionUtils.h" + namespace android { namespace hardware { namespace audio { @@ -46,7 +48,7 @@ struct DownmixEffect : public IDownmixEffect { Return reset() override; Return enable() override; Return disable() override; - Return setDevice(AudioDevice device) override; + Return setDevice(AudioDeviceBitfield device) override; Return setAndGetVolume(const hidl_vec& volumes, setAndGetVolume_cb _hidl_cb) override; Return volumeChangeNotification(const hidl_vec& volumes) override; @@ -54,7 +56,7 @@ struct DownmixEffect : public IDownmixEffect { Return setConfigReverse( const EffectConfig& config, const sp& inputBufferProvider, const sp& outputBufferProvider) override; - Return setInputDevice(AudioDevice device) override; + Return setInputDevice(AudioDeviceBitfield device) override; Return getConfig(getConfig_cb _hidl_cb) override; Return getConfigReverse(getConfigReverse_cb _hidl_cb) override; Return getSupportedAuxChannelsConfigs( diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/DownmixEffect.impl.h b/audio/effect/all-versions/default/include/effect/all-versions/default/DownmixEffect.impl.h index 98710f89dc..abef10ea09 100644 --- a/audio/effect/all-versions/default/include/effect/all-versions/default/DownmixEffect.impl.h +++ b/audio/effect/all-versions/default/include/effect/all-versions/default/DownmixEffect.impl.h @@ -19,6 +19,8 @@ #include #include +#include "VersionUtils.h" + namespace android { namespace hardware { namespace audio { @@ -53,7 +55,7 @@ Return DownmixEffect::disable() { return mEffect->disable(); } -Return DownmixEffect::setDevice(AudioDevice device) { +Return DownmixEffect::setDevice(AudioDeviceBitfield device) { return mEffect->setDevice(device); } @@ -76,7 +78,7 @@ Return DownmixEffect::setConfigReverse( return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider); } -Return DownmixEffect::setInputDevice(AudioDevice device) { +Return DownmixEffect::setInputDevice(AudioDeviceBitfield device) { return mEffect->setInputDevice(device); } diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/Effect.h b/audio/effect/all-versions/default/include/effect/all-versions/default/Effect.h index 81b0b24425..b546e0eb32 100644 --- a/audio/effect/all-versions/default/include/effect/all-versions/default/Effect.h +++ b/audio/effect/all-versions/default/include/effect/all-versions/default/Effect.h @@ -28,6 +28,8 @@ #include +#include "VersionUtils.h" + namespace android { namespace hardware { namespace audio { @@ -39,6 +41,7 @@ using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioDevice; using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioMode; using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioSource; using ::android::hardware::audio::common::AUDIO_HAL_VERSION::Uuid; +using ::android::hardware::audio::common::AUDIO_HAL_VERSION::implementation::AudioDeviceBitfield; using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::AudioBuffer; using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectAuxChannelsConfig; using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectConfig; @@ -69,7 +72,7 @@ struct Effect : public IEffect { Return reset() override; Return enable() override; Return disable() override; - Return setDevice(AudioDevice device) override; + Return setDevice(AudioDeviceBitfield device) override; Return setAndGetVolume(const hidl_vec& volumes, setAndGetVolume_cb _hidl_cb) override; Return volumeChangeNotification(const hidl_vec& volumes) override; @@ -77,7 +80,7 @@ struct Effect : public IEffect { Return setConfigReverse( const EffectConfig& config, const sp& inputBufferProvider, const sp& outputBufferProvider) override; - Return setInputDevice(AudioDevice device) override; + Return setInputDevice(AudioDeviceBitfield device) override; Return getConfig(getConfig_cb _hidl_cb) override; Return getConfigReverse(getConfigReverse_cb _hidl_cb) override; Return getSupportedAuxChannelsConfigs( diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/Effect.impl.h b/audio/effect/all-versions/default/include/effect/all-versions/default/Effect.impl.h index d3761464be..61c9805663 100644 --- a/audio/effect/all-versions/default/include/effect/all-versions/default/Effect.impl.h +++ b/audio/effect/all-versions/default/include/effect/all-versions/default/Effect.impl.h @@ -24,6 +24,8 @@ #include #include +#include "VersionUtils.h" + namespace android { namespace hardware { namespace audio { @@ -33,6 +35,7 @@ namespace implementation { using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioChannelMask; using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioFormat; +using ::android::hardware::audio::common::AUDIO_HAL_VERSION::implementation::AudioChannelBitfield; using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::MessageQueueFlagBits; namespace { @@ -174,8 +177,8 @@ std::unique_ptr Effect::hidlVecToHal(const hidl_vec& vec, uint32_t // static void Effect::effectAuxChannelsConfigFromHal(const channel_config_t& halConfig, EffectAuxChannelsConfig* config) { - config->mainChannels = AudioChannelMask(halConfig.main_channels); - config->auxChannels = AudioChannelMask(halConfig.aux_channels); + config->mainChannels = AudioChannelBitfield(halConfig.main_channels); + config->auxChannels = AudioChannelBitfield(halConfig.aux_channels); } // static @@ -191,10 +194,10 @@ void Effect::effectBufferConfigFromHal(const buffer_config_t& halConfig, config->buffer.id = 0; config->buffer.frameCount = 0; config->samplingRateHz = halConfig.samplingRate; - config->channels = AudioChannelMask(halConfig.channels); + config->channels = AudioChannelBitfield(halConfig.channels); config->format = AudioFormat(halConfig.format); config->accessMode = EffectBufferAccess(halConfig.accessMode); - config->mask = EffectConfigParameters(halConfig.mask); + config->mask = static_castmask)>(halConfig.mask); } // static @@ -500,7 +503,7 @@ Return Effect::disable() { return sendCommandReturningStatus(EFFECT_CMD_DISABLE, "DISABLE"); } -Return Effect::setDevice(AudioDevice device) { +Return Effect::setDevice(AudioDeviceBitfield device) { uint32_t halDevice = static_cast(device); return sendCommand(EFFECT_CMD_SET_DEVICE, "SET_DEVICE", sizeof(uint32_t), &halDevice); } @@ -539,7 +542,7 @@ Return Effect::setConfigReverse( inputBufferProvider, outputBufferProvider); } -Return Effect::setInputDevice(AudioDevice device) { +Return Effect::setInputDevice(AudioDeviceBitfield device) { uint32_t halDevice = static_cast(device); return sendCommand(EFFECT_CMD_SET_INPUT_DEVICE, "SET_INPUT_DEVICE", sizeof(uint32_t), &halDevice); diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/EffectsFactory.h b/audio/effect/all-versions/default/include/effect/all-versions/default/EffectsFactory.h index e586abb807..313c8c2df6 100644 --- a/audio/effect/all-versions/default/include/effect/all-versions/default/EffectsFactory.h +++ b/audio/effect/all-versions/default/include/effect/all-versions/default/EffectsFactory.h @@ -46,7 +46,7 @@ struct EffectsFactory : public IEffectsFactory { Return getDescriptor(const Uuid& uid, getDescriptor_cb _hidl_cb) override; Return createEffect(const Uuid& uid, int32_t session, int32_t ioHandle, createEffect_cb _hidl_cb) override; - Return debugDump(const hidl_handle& fd) override; + Return debugDump(const hidl_handle& fd); private: static sp dispatchEffectInstanceCreation(const effect_descriptor_t& halDescriptor, diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/EnvironmentalReverbEffect.h b/audio/effect/all-versions/default/include/effect/all-versions/default/EnvironmentalReverbEffect.h index 8351e5517a..d2f8cc3a84 100644 --- a/audio/effect/all-versions/default/include/effect/all-versions/default/EnvironmentalReverbEffect.h +++ b/audio/effect/all-versions/default/include/effect/all-versions/default/EnvironmentalReverbEffect.h @@ -22,6 +22,8 @@ #include +#include "VersionUtils.h" + namespace android { namespace hardware { namespace audio { @@ -58,7 +60,7 @@ struct EnvironmentalReverbEffect : public IEnvironmentalReverbEffect { Return reset() override; Return enable() override; Return disable() override; - Return setDevice(AudioDevice device) override; + Return setDevice(AudioDeviceBitfield device) override; Return setAndGetVolume(const hidl_vec& volumes, setAndGetVolume_cb _hidl_cb) override; Return volumeChangeNotification(const hidl_vec& volumes) override; @@ -66,7 +68,7 @@ struct EnvironmentalReverbEffect : public IEnvironmentalReverbEffect { Return setConfigReverse( const EffectConfig& config, const sp& inputBufferProvider, const sp& outputBufferProvider) override; - Return setInputDevice(AudioDevice device) override; + Return setInputDevice(AudioDeviceBitfield device) override; Return getConfig(getConfig_cb _hidl_cb) override; Return getConfigReverse(getConfigReverse_cb _hidl_cb) override; Return getSupportedAuxChannelsConfigs( diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/EnvironmentalReverbEffect.impl.h b/audio/effect/all-versions/default/include/effect/all-versions/default/EnvironmentalReverbEffect.impl.h index 9090b8ab78..39a4092e8c 100644 --- a/audio/effect/all-versions/default/include/effect/all-versions/default/EnvironmentalReverbEffect.impl.h +++ b/audio/effect/all-versions/default/include/effect/all-versions/default/EnvironmentalReverbEffect.impl.h @@ -18,6 +18,8 @@ #include +#include "VersionUtils.h" + namespace android { namespace hardware { namespace audio { @@ -81,7 +83,7 @@ Return EnvironmentalReverbEffect::disable() { return mEffect->disable(); } -Return EnvironmentalReverbEffect::setDevice(AudioDevice device) { +Return EnvironmentalReverbEffect::setDevice(AudioDeviceBitfield device) { return mEffect->setDevice(device); } @@ -105,7 +107,7 @@ Return EnvironmentalReverbEffect::setConfigReverse( return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider); } -Return EnvironmentalReverbEffect::setInputDevice(AudioDevice device) { +Return EnvironmentalReverbEffect::setInputDevice(AudioDeviceBitfield device) { return mEffect->setInputDevice(device); } diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/EqualizerEffect.h b/audio/effect/all-versions/default/include/effect/all-versions/default/EqualizerEffect.h index c2b8ef8b52..de520521fa 100644 --- a/audio/effect/all-versions/default/include/effect/all-versions/default/EqualizerEffect.h +++ b/audio/effect/all-versions/default/include/effect/all-versions/default/EqualizerEffect.h @@ -24,6 +24,8 @@ #include +#include "VersionUtils.h" + namespace android { namespace hardware { namespace audio { @@ -60,7 +62,7 @@ struct EqualizerEffect : public IEqualizerEffect { Return reset() override; Return enable() override; Return disable() override; - Return setDevice(AudioDevice device) override; + Return setDevice(AudioDeviceBitfield device) override; Return setAndGetVolume(const hidl_vec& volumes, setAndGetVolume_cb _hidl_cb) override; Return volumeChangeNotification(const hidl_vec& volumes) override; @@ -68,7 +70,7 @@ struct EqualizerEffect : public IEqualizerEffect { Return setConfigReverse( const EffectConfig& config, const sp& inputBufferProvider, const sp& outputBufferProvider) override; - Return setInputDevice(AudioDevice device) override; + Return setInputDevice(AudioDeviceBitfield device) override; Return getConfig(getConfig_cb _hidl_cb) override; Return getConfigReverse(getConfigReverse_cb _hidl_cb) override; Return getSupportedAuxChannelsConfigs( diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/EqualizerEffect.impl.h b/audio/effect/all-versions/default/include/effect/all-versions/default/EqualizerEffect.impl.h index 78485e48fd..db6bed8d2e 100644 --- a/audio/effect/all-versions/default/include/effect/all-versions/default/EqualizerEffect.impl.h +++ b/audio/effect/all-versions/default/include/effect/all-versions/default/EqualizerEffect.impl.h @@ -20,6 +20,8 @@ #include +#include "VersionUtils.h" + namespace android { namespace hardware { namespace audio { @@ -76,7 +78,7 @@ Return EqualizerEffect::disable() { return mEffect->disable(); } -Return EqualizerEffect::setDevice(AudioDevice device) { +Return EqualizerEffect::setDevice(AudioDeviceBitfield device) { return mEffect->setDevice(device); } @@ -99,7 +101,7 @@ Return EqualizerEffect::setConfigReverse( return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider); } -Return EqualizerEffect::setInputDevice(AudioDevice device) { +Return EqualizerEffect::setInputDevice(AudioDeviceBitfield device) { return mEffect->setInputDevice(device); } diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/LoudnessEnhancerEffect.h b/audio/effect/all-versions/default/include/effect/all-versions/default/LoudnessEnhancerEffect.h index e4f1bd5e93..b59b077e76 100644 --- a/audio/effect/all-versions/default/include/effect/all-versions/default/LoudnessEnhancerEffect.h +++ b/audio/effect/all-versions/default/include/effect/all-versions/default/LoudnessEnhancerEffect.h @@ -20,6 +20,8 @@ #include +#include "VersionUtils.h" + namespace android { namespace hardware { namespace audio { @@ -56,7 +58,7 @@ struct LoudnessEnhancerEffect : public ILoudnessEnhancerEffect { Return reset() override; Return enable() override; Return disable() override; - Return setDevice(AudioDevice device) override; + Return setDevice(AudioDeviceBitfield device) override; Return setAndGetVolume(const hidl_vec& volumes, setAndGetVolume_cb _hidl_cb) override; Return volumeChangeNotification(const hidl_vec& volumes) override; @@ -64,7 +66,7 @@ struct LoudnessEnhancerEffect : public ILoudnessEnhancerEffect { Return setConfigReverse( const EffectConfig& config, const sp& inputBufferProvider, const sp& outputBufferProvider) override; - Return setInputDevice(AudioDevice device) override; + Return setInputDevice(AudioDeviceBitfield device) override; Return getConfig(getConfig_cb _hidl_cb) override; Return getConfigReverse(getConfigReverse_cb _hidl_cb) override; Return getSupportedAuxChannelsConfigs( diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/LoudnessEnhancerEffect.impl.h b/audio/effect/all-versions/default/include/effect/all-versions/default/LoudnessEnhancerEffect.impl.h index 3f4f379a27..88210e954b 100644 --- a/audio/effect/all-versions/default/include/effect/all-versions/default/LoudnessEnhancerEffect.impl.h +++ b/audio/effect/all-versions/default/include/effect/all-versions/default/LoudnessEnhancerEffect.impl.h @@ -21,6 +21,8 @@ #include #include +#include "VersionUtils.h" + namespace android { namespace hardware { namespace audio { @@ -56,7 +58,7 @@ Return LoudnessEnhancerEffect::disable() { return mEffect->disable(); } -Return LoudnessEnhancerEffect::setDevice(AudioDevice device) { +Return LoudnessEnhancerEffect::setDevice(AudioDeviceBitfield device) { return mEffect->setDevice(device); } @@ -79,7 +81,7 @@ Return LoudnessEnhancerEffect::setConfigReverse( return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider); } -Return LoudnessEnhancerEffect::setInputDevice(AudioDevice device) { +Return LoudnessEnhancerEffect::setInputDevice(AudioDeviceBitfield device) { return mEffect->setInputDevice(device); } diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/NoiseSuppressionEffect.h b/audio/effect/all-versions/default/include/effect/all-versions/default/NoiseSuppressionEffect.h index 7b64ba015a..af1635b717 100644 --- a/audio/effect/all-versions/default/include/effect/all-versions/default/NoiseSuppressionEffect.h +++ b/audio/effect/all-versions/default/include/effect/all-versions/default/NoiseSuppressionEffect.h @@ -22,6 +22,8 @@ #include +#include "VersionUtils.h" + namespace android { namespace hardware { namespace audio { @@ -58,7 +60,7 @@ struct NoiseSuppressionEffect : public INoiseSuppressionEffect { Return reset() override; Return enable() override; Return disable() override; - Return setDevice(AudioDevice device) override; + Return setDevice(AudioDeviceBitfield device) override; Return setAndGetVolume(const hidl_vec& volumes, setAndGetVolume_cb _hidl_cb) override; Return volumeChangeNotification(const hidl_vec& volumes) override; @@ -66,7 +68,7 @@ struct NoiseSuppressionEffect : public INoiseSuppressionEffect { Return setConfigReverse( const EffectConfig& config, const sp& inputBufferProvider, const sp& outputBufferProvider) override; - Return setInputDevice(AudioDevice device) override; + Return setInputDevice(AudioDeviceBitfield device) override; Return getConfig(getConfig_cb _hidl_cb) override; Return getConfigReverse(getConfigReverse_cb _hidl_cb) override; Return getSupportedAuxChannelsConfigs( diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/NoiseSuppressionEffect.impl.h b/audio/effect/all-versions/default/include/effect/all-versions/default/NoiseSuppressionEffect.impl.h index e5fc454a44..f32399c51c 100644 --- a/audio/effect/all-versions/default/include/effect/all-versions/default/NoiseSuppressionEffect.impl.h +++ b/audio/effect/all-versions/default/include/effect/all-versions/default/NoiseSuppressionEffect.impl.h @@ -18,6 +18,8 @@ #include +#include "VersionUtils.h" + namespace android { namespace hardware { namespace audio { @@ -65,7 +67,7 @@ Return NoiseSuppressionEffect::disable() { return mEffect->disable(); } -Return NoiseSuppressionEffect::setDevice(AudioDevice device) { +Return NoiseSuppressionEffect::setDevice(AudioDeviceBitfield device) { return mEffect->setDevice(device); } @@ -88,7 +90,7 @@ Return NoiseSuppressionEffect::setConfigReverse( return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider); } -Return NoiseSuppressionEffect::setInputDevice(AudioDevice device) { +Return NoiseSuppressionEffect::setInputDevice(AudioDeviceBitfield device) { return mEffect->setInputDevice(device); } diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/PresetReverbEffect.h b/audio/effect/all-versions/default/include/effect/all-versions/default/PresetReverbEffect.h index 3114acd8d7..1a91ab49b2 100644 --- a/audio/effect/all-versions/default/include/effect/all-versions/default/PresetReverbEffect.h +++ b/audio/effect/all-versions/default/include/effect/all-versions/default/PresetReverbEffect.h @@ -20,6 +20,8 @@ #include +#include "VersionUtils.h" + namespace android { namespace hardware { namespace audio { @@ -56,7 +58,7 @@ struct PresetReverbEffect : public IPresetReverbEffect { Return reset() override; Return enable() override; Return disable() override; - Return setDevice(AudioDevice device) override; + Return setDevice(AudioDeviceBitfield device) override; Return setAndGetVolume(const hidl_vec& volumes, setAndGetVolume_cb _hidl_cb) override; Return volumeChangeNotification(const hidl_vec& volumes) override; @@ -64,7 +66,7 @@ struct PresetReverbEffect : public IPresetReverbEffect { Return setConfigReverse( const EffectConfig& config, const sp& inputBufferProvider, const sp& outputBufferProvider) override; - Return setInputDevice(AudioDevice device) override; + Return setInputDevice(AudioDeviceBitfield device) override; Return getConfig(getConfig_cb _hidl_cb) override; Return getConfigReverse(getConfigReverse_cb _hidl_cb) override; Return getSupportedAuxChannelsConfigs( diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/PresetReverbEffect.impl.h b/audio/effect/all-versions/default/include/effect/all-versions/default/PresetReverbEffect.impl.h index 32198d50e5..eab68fb703 100644 --- a/audio/effect/all-versions/default/include/effect/all-versions/default/PresetReverbEffect.impl.h +++ b/audio/effect/all-versions/default/include/effect/all-versions/default/PresetReverbEffect.impl.h @@ -19,6 +19,8 @@ #include #include +#include "VersionUtils.h" + namespace android { namespace hardware { namespace audio { @@ -53,7 +55,7 @@ Return PresetReverbEffect::disable() { return mEffect->disable(); } -Return PresetReverbEffect::setDevice(AudioDevice device) { +Return PresetReverbEffect::setDevice(AudioDeviceBitfield device) { return mEffect->setDevice(device); } @@ -76,7 +78,7 @@ Return PresetReverbEffect::setConfigReverse( return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider); } -Return PresetReverbEffect::setInputDevice(AudioDevice device) { +Return PresetReverbEffect::setInputDevice(AudioDeviceBitfield device) { return mEffect->setInputDevice(device); } diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/VirtualizerEffect.h b/audio/effect/all-versions/default/include/effect/all-versions/default/VirtualizerEffect.h index 371589488f..c0d5a0034d 100644 --- a/audio/effect/all-versions/default/include/effect/all-versions/default/VirtualizerEffect.h +++ b/audio/effect/all-versions/default/include/effect/all-versions/default/VirtualizerEffect.h @@ -20,6 +20,8 @@ #include +#include "VersionUtils.h" + namespace android { namespace hardware { namespace audio { @@ -31,6 +33,7 @@ using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioChannelMask; using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioDevice; using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioMode; using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioSource; +using ::android::hardware::audio::common::AUDIO_HAL_VERSION::implementation::AudioChannelBitfield; using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::AudioBuffer; using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectAuxChannelsConfig; using ::android::hardware::audio::effect::AUDIO_HAL_VERSION::EffectConfig; @@ -57,7 +60,7 @@ struct VirtualizerEffect : public IVirtualizerEffect { Return reset() override; Return enable() override; Return disable() override; - Return setDevice(AudioDevice device) override; + Return setDevice(AudioDeviceBitfield device) override; Return setAndGetVolume(const hidl_vec& volumes, setAndGetVolume_cb _hidl_cb) override; Return volumeChangeNotification(const hidl_vec& volumes) override; @@ -65,7 +68,7 @@ struct VirtualizerEffect : public IVirtualizerEffect { Return setConfigReverse( const EffectConfig& config, const sp& inputBufferProvider, const sp& outputBufferProvider) override; - Return setInputDevice(AudioDevice device) override; + Return setInputDevice(AudioDeviceBitfield device) override; Return getConfig(getConfig_cb _hidl_cb) override; Return getConfigReverse(getConfigReverse_cb _hidl_cb) override; Return getSupportedAuxChannelsConfigs( @@ -98,7 +101,7 @@ struct VirtualizerEffect : public IVirtualizerEffect { Return isStrengthSupported() override; Return setStrength(uint16_t strength) override; Return getStrength(getStrength_cb _hidl_cb) override; - Return getVirtualSpeakerAngles(AudioChannelMask mask, AudioDevice device, + Return getVirtualSpeakerAngles(AudioChannelBitfield mask, AudioDevice device, getVirtualSpeakerAngles_cb _hidl_cb) override; Return forceVirtualizationMode(AudioDevice device) override; Return getVirtualizationMode(getVirtualizationMode_cb _hidl_cb) override; diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/VirtualizerEffect.impl.h b/audio/effect/all-versions/default/include/effect/all-versions/default/VirtualizerEffect.impl.h index 6fb8005590..23b09a89dd 100644 --- a/audio/effect/all-versions/default/include/effect/all-versions/default/VirtualizerEffect.impl.h +++ b/audio/effect/all-versions/default/include/effect/all-versions/default/VirtualizerEffect.impl.h @@ -21,6 +21,8 @@ #include #include +#include "VersionUtils.h" + namespace android { namespace hardware { namespace audio { @@ -36,7 +38,7 @@ void VirtualizerEffect::speakerAnglesFromHal(const int32_t* halAngles, uint32_t hidl_vec& speakerAngles) { speakerAngles.resize(channelCount); for (uint32_t i = 0; i < channelCount; ++i) { - speakerAngles[i].mask = AudioChannelMask(*halAngles++); + speakerAngles[i].mask = AudioChannelBitfield(*halAngles++); speakerAngles[i].azimuth = *halAngles++; speakerAngles[i].elevation = *halAngles++; } @@ -65,7 +67,7 @@ Return VirtualizerEffect::disable() { return mEffect->disable(); } -Return VirtualizerEffect::setDevice(AudioDevice device) { +Return VirtualizerEffect::setDevice(AudioDeviceBitfield device) { return mEffect->setDevice(device); } @@ -88,7 +90,7 @@ Return VirtualizerEffect::setConfigReverse( return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider); } -Return VirtualizerEffect::setInputDevice(AudioDevice device) { +Return VirtualizerEffect::setInputDevice(AudioDeviceBitfield device) { return mEffect->setInputDevice(device); } @@ -184,7 +186,8 @@ Return VirtualizerEffect::getStrength(getStrength_cb _hidl_cb) { return mEffect->getIntegerParam(VIRTUALIZER_PARAM_STRENGTH, _hidl_cb); } -Return VirtualizerEffect::getVirtualSpeakerAngles(AudioChannelMask mask, AudioDevice device, +Return VirtualizerEffect::getVirtualSpeakerAngles(AudioChannelBitfield mask, + AudioDevice device, getVirtualSpeakerAngles_cb _hidl_cb) { uint32_t channelCount = audio_channel_count_from_out_mask(static_cast(mask)); diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/VisualizerEffect.h b/audio/effect/all-versions/default/include/effect/all-versions/default/VisualizerEffect.h index 80502210cf..114d3b7ae5 100644 --- a/audio/effect/all-versions/default/include/effect/all-versions/default/VisualizerEffect.h +++ b/audio/effect/all-versions/default/include/effect/all-versions/default/VisualizerEffect.h @@ -20,6 +20,8 @@ #include +#include "VersionUtils.h" + namespace android { namespace hardware { namespace audio { @@ -56,7 +58,7 @@ struct VisualizerEffect : public IVisualizerEffect { Return reset() override; Return enable() override; Return disable() override; - Return setDevice(AudioDevice device) override; + Return setDevice(AudioDeviceBitfield device) override; Return setAndGetVolume(const hidl_vec& volumes, setAndGetVolume_cb _hidl_cb) override; Return volumeChangeNotification(const hidl_vec& volumes) override; @@ -64,7 +66,7 @@ struct VisualizerEffect : public IVisualizerEffect { Return setConfigReverse( const EffectConfig& config, const sp& inputBufferProvider, const sp& outputBufferProvider) override; - Return setInputDevice(AudioDevice device) override; + Return setInputDevice(AudioDeviceBitfield device) override; Return getConfig(getConfig_cb _hidl_cb) override; Return getConfigReverse(getConfigReverse_cb _hidl_cb) override; Return getSupportedAuxChannelsConfigs( diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/VisualizerEffect.impl.h b/audio/effect/all-versions/default/include/effect/all-versions/default/VisualizerEffect.impl.h index 035145368b..9f2195b5cb 100644 --- a/audio/effect/all-versions/default/include/effect/all-versions/default/VisualizerEffect.impl.h +++ b/audio/effect/all-versions/default/include/effect/all-versions/default/VisualizerEffect.impl.h @@ -19,6 +19,8 @@ #include #include +#include "VersionUtils.h" + namespace android { namespace hardware { namespace audio { @@ -54,7 +56,7 @@ Return VisualizerEffect::disable() { return mEffect->disable(); } -Return VisualizerEffect::setDevice(AudioDevice device) { +Return VisualizerEffect::setDevice(AudioDeviceBitfield device) { return mEffect->setDevice(device); } @@ -77,7 +79,7 @@ Return VisualizerEffect::setConfigReverse( return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider); } -Return VisualizerEffect::setInputDevice(AudioDevice device) { +Return VisualizerEffect::setInputDevice(AudioDeviceBitfield device) { return mEffect->setInputDevice(device); } From 68c5532d62502e1f29cf38052ad693ce25f2a7f1 Mon Sep 17 00:00:00 2001 From: Kevin Rocard Date: Thu, 1 Mar 2018 18:32:43 -0800 Subject: [PATCH 009/718] Audio V4: Move service entry point to common The HAL audio service entry point is not version dependant and is common to core and effect. Bug: 38184704 Test: compile Change-Id: I143cf28490afc978791ccd7e8aeee2106cbb2ebd Signed-off-by: Kevin Rocard --- .../default => common/all-versions/default/service}/Android.mk | 0 .../default/service}/android.hardware.audio@2.0-service.rc | 0 .../default => common/all-versions/default/service}/service.cpp | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename audio/{2.0/default => common/all-versions/default/service}/Android.mk (100%) rename audio/{2.0/default => common/all-versions/default/service}/android.hardware.audio@2.0-service.rc (100%) rename audio/{2.0/default => common/all-versions/default/service}/service.cpp (100%) diff --git a/audio/2.0/default/Android.mk b/audio/common/all-versions/default/service/Android.mk similarity index 100% rename from audio/2.0/default/Android.mk rename to audio/common/all-versions/default/service/Android.mk diff --git a/audio/2.0/default/android.hardware.audio@2.0-service.rc b/audio/common/all-versions/default/service/android.hardware.audio@2.0-service.rc similarity index 100% rename from audio/2.0/default/android.hardware.audio@2.0-service.rc rename to audio/common/all-versions/default/service/android.hardware.audio@2.0-service.rc diff --git a/audio/2.0/default/service.cpp b/audio/common/all-versions/default/service/service.cpp similarity index 100% rename from audio/2.0/default/service.cpp rename to audio/common/all-versions/default/service/service.cpp From 4e914ffb1ad9ca621438623ad69af6498ff570e7 Mon Sep 17 00:00:00 2001 From: Kevin Rocard Date: Fri, 2 Mar 2018 13:27:14 -0800 Subject: [PATCH 010/718] Audio V4: Add its own function to open the primary device The primary device has its own type and a fixed name and is not optional. By having its own getter, the client does not have to downcast it. Bug: 38184704 Test: compile Change-Id: I7b22eb0e12bddabfe966a20fbeab37d974306b12 Signed-off-by: Kevin Rocard --- audio/4.0/IDevicesFactory.hal | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/audio/4.0/IDevicesFactory.hal b/audio/4.0/IDevicesFactory.hal index 987fd68e5c..489294e5cd 100644 --- a/audio/4.0/IDevicesFactory.hal +++ b/audio/4.0/IDevicesFactory.hal @@ -18,6 +18,7 @@ package android.hardware.audio@4.0; import android.hardware.audio.common@4.0; import IDevice; +import IPrimaryDevice; /** This factory allows a HAL implementation to be split in multiple independent * devices (called module in the pre-treble API). @@ -28,8 +29,7 @@ import IDevice; * Each device name is arbitrary, provided by the vendor's audio_policy_configuration.xml * and only used to identify a device in this factory. * The framework must not interpret the name, treating it as a vendor opaque data - * with the following exceptions: - * - the "primary" device must always be present and is the device used by the telephony framework. + * with the following exception: * - the "r_submix" device that must be present to support policyMixes (Eg: Android projected). * Note that this Device is included by default in a build derived from AOSP. * @@ -51,4 +51,20 @@ interface IDevicesFactory { * @return result the interface for the created device. */ openDevice(string device) generates (Result retval, IDevice result); + + /** + * Opens the Primary audio device that must be present. + * This function is not optional and must return successfully the primary device. + * + * This device must have the name "primary". + * + * The telephony stack uses this device to control the audio during a voice call. + * + * @return retval operation completion status. Must be SUCCESS. + * For debuging, return INVALID_ARGUMENTS if there is no corresponding + * hardware module found, NOT_INITIALIZED if an error occurred + * while opening the hardware module. + * @return result the interface for the created device. + */ + openPrimaryDevice() generates (Result retval, IPrimaryDevice result); }; From 4fa9ca1337a426eb8217129b01a80f01bc9229ce Mon Sep 17 00:00:00 2001 From: Kevin Rocard Date: Thu, 1 Mar 2018 15:08:07 -0800 Subject: [PATCH 011/718] Audio V4: Implement the shim core 4.0 -> legacy All the new files added are a copy of the 2.0 ones, with just the version 2 that was changed to 4. Due to the rollback on the retrocompatiblity breakage, the split of implementation is not strictly needed any more. This makes the current split in .impl.h and double include unnecessary complicated. This will need to be factorized in a future patch. Bug: 38184704 Test: compile Change-Id: I0d699ade7558ed68125b300f8522e2767ae1ee37 Signed-off-by: Kevin Rocard --- audio/common/2.0/default/VersionUtils.h | 2 + audio/common/4.0/default/VersionUtils.h | 4 +- audio/core/2.0/default/Android.bp | 4 + audio/core/4.0/default/Android.bp | 53 ++++++ audio/core/4.0/default/Conversions.cpp | 21 +++ audio/core/4.0/default/Device.cpp | 28 +++ audio/core/4.0/default/DevicesFactory.cpp | 25 +++ audio/core/4.0/default/OWNERS | 3 + audio/core/4.0/default/ParametersUtil.cpp | 21 +++ audio/core/4.0/default/PrimaryDevice.cpp | 24 +++ audio/core/4.0/default/Stream.cpp | 25 +++ audio/core/4.0/default/StreamIn.cpp | 24 +++ audio/core/4.0/default/StreamOut.cpp | 24 +++ .../include/core/4.0/default/Conversions.h | 26 +++ .../default/include/core/4.0/default/Device.h | 28 +++ .../include/core/4.0/default/DevicesFactory.h | 26 +++ .../include/core/4.0/default/ParametersUtil.h | 26 +++ .../include/core/4.0/default/PrimaryDevice.h | 28 +++ .../default/include/core/4.0/default/Stream.h | 28 +++ .../include/core/4.0/default/StreamIn.h | 29 ++++ .../include/core/4.0/default/StreamOut.h | 29 ++++ audio/core/all-versions/default/Android.bp | 1 - .../core/all-versions/default/Device.h | 47 +++++- .../core/all-versions/default/Device.impl.h | 69 +++++++- .../all-versions/default/DevicesFactory.h | 12 +- .../default/DevicesFactory.impl.h | 73 ++++---- .../all-versions/default/ParametersUtil.h | 11 +- .../default/ParametersUtil.impl.h | 29 +++- .../core/all-versions/default/PrimaryDevice.h | 44 ++++- .../all-versions/default/PrimaryDevice.impl.h | 80 ++++++++- .../core/all-versions/default/Stream.h | 33 +++- .../core/all-versions/default/Stream.impl.h | 159 ++++++++++++------ .../core/all-versions/default/StreamIn.h | 34 +++- .../core/all-versions/default/StreamIn.impl.h | 72 ++++++-- .../core/all-versions/default/StreamOut.h | 34 +++- .../all-versions/default/StreamOut.impl.h | 71 ++++++-- 36 files changed, 1087 insertions(+), 160 deletions(-) create mode 100644 audio/core/4.0/default/Android.bp create mode 100644 audio/core/4.0/default/Conversions.cpp create mode 100644 audio/core/4.0/default/Device.cpp create mode 100644 audio/core/4.0/default/DevicesFactory.cpp create mode 100644 audio/core/4.0/default/OWNERS create mode 100644 audio/core/4.0/default/ParametersUtil.cpp create mode 100644 audio/core/4.0/default/PrimaryDevice.cpp create mode 100644 audio/core/4.0/default/Stream.cpp create mode 100644 audio/core/4.0/default/StreamIn.cpp create mode 100644 audio/core/4.0/default/StreamOut.cpp create mode 100644 audio/core/4.0/default/include/core/4.0/default/Conversions.h create mode 100644 audio/core/4.0/default/include/core/4.0/default/Device.h create mode 100644 audio/core/4.0/default/include/core/4.0/default/DevicesFactory.h create mode 100644 audio/core/4.0/default/include/core/4.0/default/ParametersUtil.h create mode 100644 audio/core/4.0/default/include/core/4.0/default/PrimaryDevice.h create mode 100644 audio/core/4.0/default/include/core/4.0/default/Stream.h create mode 100644 audio/core/4.0/default/include/core/4.0/default/StreamIn.h create mode 100644 audio/core/4.0/default/include/core/4.0/default/StreamOut.h diff --git a/audio/common/2.0/default/VersionUtils.h b/audio/common/2.0/default/VersionUtils.h index fef468080e..60d1f9cb6d 100644 --- a/audio/common/2.0/default/VersionUtils.h +++ b/audio/common/2.0/default/VersionUtils.h @@ -28,6 +28,8 @@ namespace implementation { typedef common::V2_0::AudioDevice AudioDeviceBitfield; typedef common::V2_0::AudioChannelMask AudioChannelBitfield; +typedef common::V2_0::AudioOutputFlag AudioOutputFlagBitfield; +typedef common::V2_0::AudioInputFlag AudioInputFlagBitfield; } // namespace implementation } // namespace V2_0 diff --git a/audio/common/4.0/default/VersionUtils.h b/audio/common/4.0/default/VersionUtils.h index 515c792222..b7f2aec8f9 100644 --- a/audio/common/4.0/default/VersionUtils.h +++ b/audio/common/4.0/default/VersionUtils.h @@ -17,7 +17,7 @@ #ifndef ANDROID_HARDWARE_AUDIO_EFFECT_VERSION_UTILS_H #define ANDROID_HARDWARE_AUDIO_EFFECT_VERSION_UTILS_H -#include +#include namespace android { namespace hardware { @@ -28,6 +28,8 @@ namespace implementation { typedef hidl_bitfield AudioDeviceBitfield; typedef hidl_bitfield AudioChannelBitfield; +typedef hidl_bitfield AudioOutputFlagBitfield; +typedef hidl_bitfield AudioInputFlagBitfield; } // namespace implementation } // namespace V4_0 diff --git a/audio/core/2.0/default/Android.bp b/audio/core/2.0/default/Android.bp index 98478860c2..625df74a88 100644 --- a/audio/core/2.0/default/Android.bp +++ b/audio/core/2.0/default/Android.bp @@ -14,6 +14,10 @@ cc_library_shared { "StreamOut.cpp", ], + cflags: [ + "-DAUDIO_HAL_VERSION_2_0", + ], + defaults: ["hidl_defaults"], export_include_dirs: ["include"], diff --git a/audio/core/4.0/default/Android.bp b/audio/core/4.0/default/Android.bp new file mode 100644 index 0000000000..8e415459be --- /dev/null +++ b/audio/core/4.0/default/Android.bp @@ -0,0 +1,53 @@ +cc_library_shared { + name: "android.hardware.audio@4.0-impl", + relative_install_path: "hw", + proprietary: true, + vendor: true, + srcs: [ + "Conversions.cpp", + "Device.cpp", + "DevicesFactory.cpp", + "ParametersUtil.cpp", + "PrimaryDevice.cpp", + "Stream.cpp", + "StreamIn.cpp", + "StreamOut.cpp", + ], + + cflags: [ + "-DAUDIO_HAL_VERSION_4_0", + ], + + defaults: ["hidl_defaults"], + + export_include_dirs: ["include"], + + shared_libs: [ + "libbase", + "libcutils", + "libfmq", + "libhardware", + "libhidlbase", + "libhidltransport", + "liblog", + "libutils", + "android.hardware.audio@4.0", + "android.hardware.audio.common@4.0", + "android.hardware.audio.common@4.0-util", + "android.hardware.audio.common-util", + ], + + header_libs: [ + "android.hardware.audio.common.util@all-versions", + "android.hardware.audio.core@all-versions-impl", + "libaudioclient_headers", + "libaudio_system_headers", + "libhardware_headers", + "libmedia_headers", + ], + + whole_static_libs: [ + "libmedia_helper", + ], + +} diff --git a/audio/core/4.0/default/Conversions.cpp b/audio/core/4.0/default/Conversions.cpp new file mode 100644 index 0000000000..4f1874412c --- /dev/null +++ b/audio/core/4.0/default/Conversions.cpp @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "core/4.0/default/Conversions.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION diff --git a/audio/core/4.0/default/Device.cpp b/audio/core/4.0/default/Device.cpp new file mode 100644 index 0000000000..26f9ab4a70 --- /dev/null +++ b/audio/core/4.0/default/Device.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "DeviceHAL" + +#include "core/4.0/default/Device.h" +#include +#include "core/4.0/default/Conversions.h" +#include "core/4.0/default/StreamIn.h" +#include "core/4.0/default/StreamOut.h" +#include "core/all-versions/default/Util.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION diff --git a/audio/core/4.0/default/DevicesFactory.cpp b/audio/core/4.0/default/DevicesFactory.cpp new file mode 100644 index 0000000000..cb8a3c3e97 --- /dev/null +++ b/audio/core/4.0/default/DevicesFactory.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "DevicesFactoryHAL" + +#include "core/4.0/default/DevicesFactory.h" +#include "core/4.0/default/Device.h" +#include "core/4.0/default/PrimaryDevice.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION diff --git a/audio/core/4.0/default/OWNERS b/audio/core/4.0/default/OWNERS new file mode 100644 index 0000000000..6fdc97ca29 --- /dev/null +++ b/audio/core/4.0/default/OWNERS @@ -0,0 +1,3 @@ +elaurent@google.com +krocard@google.com +mnaganov@google.com diff --git a/audio/core/4.0/default/ParametersUtil.cpp b/audio/core/4.0/default/ParametersUtil.cpp new file mode 100644 index 0000000000..5c1b1c4b18 --- /dev/null +++ b/audio/core/4.0/default/ParametersUtil.cpp @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "core/4.0/default/ParametersUtil.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION diff --git a/audio/core/4.0/default/PrimaryDevice.cpp b/audio/core/4.0/default/PrimaryDevice.cpp new file mode 100644 index 0000000000..0294b4d0d4 --- /dev/null +++ b/audio/core/4.0/default/PrimaryDevice.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "PrimaryDeviceHAL" + +#include "core/4.0/default/PrimaryDevice.h" +#include "core/all-versions/default/Util.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION diff --git a/audio/core/4.0/default/Stream.cpp b/audio/core/4.0/default/Stream.cpp new file mode 100644 index 0000000000..30b34544d6 --- /dev/null +++ b/audio/core/4.0/default/Stream.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "StreamHAL" + +#include "core/4.0/default/Stream.h" +#include "common/all-versions/default/EffectMap.h" +#include "core/4.0/default/Conversions.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION diff --git a/audio/core/4.0/default/StreamIn.cpp b/audio/core/4.0/default/StreamIn.cpp new file mode 100644 index 0000000000..18719b5da2 --- /dev/null +++ b/audio/core/4.0/default/StreamIn.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "StreamInHAL" + +#include "core/4.0/default/StreamIn.h" +#include "core/all-versions/default/Util.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION diff --git a/audio/core/4.0/default/StreamOut.cpp b/audio/core/4.0/default/StreamOut.cpp new file mode 100644 index 0000000000..11c8fde663 --- /dev/null +++ b/audio/core/4.0/default/StreamOut.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "StreamOutHAL" + +#include "core/4.0/default/StreamOut.h" +#include "core/all-versions/default/Util.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION diff --git a/audio/core/4.0/default/include/core/4.0/default/Conversions.h b/audio/core/4.0/default/include/core/4.0/default/Conversions.h new file mode 100644 index 0000000000..32c2f887ee --- /dev/null +++ b/audio/core/4.0/default/include/core/4.0/default/Conversions.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_AUDIO_V4_0_CONVERSIONS_H_ +#define ANDROID_HARDWARE_AUDIO_V4_0_CONVERSIONS_H_ + +#include + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION + +#endif // ANDROID_HARDWARE_AUDIO_V4_0_CONVERSIONS_H_ diff --git a/audio/core/4.0/default/include/core/4.0/default/Device.h b/audio/core/4.0/default/include/core/4.0/default/Device.h new file mode 100644 index 0000000000..770d606720 --- /dev/null +++ b/audio/core/4.0/default/include/core/4.0/default/Device.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_AUDIO_V4_0_DEVICE_H +#define ANDROID_HARDWARE_AUDIO_V4_0_DEVICE_H + +#include + +#include "ParametersUtil.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION + +#endif // ANDROID_HARDWARE_AUDIO_V4_0_DEVICE_H diff --git a/audio/core/4.0/default/include/core/4.0/default/DevicesFactory.h b/audio/core/4.0/default/include/core/4.0/default/DevicesFactory.h new file mode 100644 index 0000000000..200e59d96f --- /dev/null +++ b/audio/core/4.0/default/include/core/4.0/default/DevicesFactory.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_AUDIO_V4_0_DEVICESFACTORY_H +#define ANDROID_HARDWARE_AUDIO_V4_0_DEVICESFACTORY_H + +#include + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION + +#endif // ANDROID_HARDWARE_AUDIO_V4_0_DEVICESFACTORY_H diff --git a/audio/core/4.0/default/include/core/4.0/default/ParametersUtil.h b/audio/core/4.0/default/include/core/4.0/default/ParametersUtil.h new file mode 100644 index 0000000000..fa31ee9dd3 --- /dev/null +++ b/audio/core/4.0/default/include/core/4.0/default/ParametersUtil.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_AUDIO_V4_0_PARAMETERS_UTIL_H_ +#define ANDROID_HARDWARE_AUDIO_V4_0_PARAMETERS_UTIL_H_ + +#include + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION + +#endif // ANDROID_HARDWARE_AUDIO_V4_0_PARAMETERS_UTIL_H_ diff --git a/audio/core/4.0/default/include/core/4.0/default/PrimaryDevice.h b/audio/core/4.0/default/include/core/4.0/default/PrimaryDevice.h new file mode 100644 index 0000000000..e7f846b622 --- /dev/null +++ b/audio/core/4.0/default/include/core/4.0/default/PrimaryDevice.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_AUDIO_V4_0_PRIMARYDEVICE_H +#define ANDROID_HARDWARE_AUDIO_V4_0_PRIMARYDEVICE_H + +#include + +#include "Device.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION + +#endif // ANDROID_HARDWARE_AUDIO_V4_0_PRIMARYDEVICE_H diff --git a/audio/core/4.0/default/include/core/4.0/default/Stream.h b/audio/core/4.0/default/include/core/4.0/default/Stream.h new file mode 100644 index 0000000000..afad80fe53 --- /dev/null +++ b/audio/core/4.0/default/include/core/4.0/default/Stream.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_AUDIO_V4_0_STREAM_H +#define ANDROID_HARDWARE_AUDIO_V4_0_STREAM_H + +#include + +#include "ParametersUtil.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION + +#endif // ANDROID_HARDWARE_AUDIO_V4_0_STREAM_H diff --git a/audio/core/4.0/default/include/core/4.0/default/StreamIn.h b/audio/core/4.0/default/include/core/4.0/default/StreamIn.h new file mode 100644 index 0000000000..151f03fc2b --- /dev/null +++ b/audio/core/4.0/default/include/core/4.0/default/StreamIn.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_AUDIO_V4_0_STREAMIN_H +#define ANDROID_HARDWARE_AUDIO_V4_0_STREAMIN_H + +#include + +#include "Device.h" +#include "Stream.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION + +#endif // ANDROID_HARDWARE_AUDIO_V4_0_STREAMIN_H diff --git a/audio/core/4.0/default/include/core/4.0/default/StreamOut.h b/audio/core/4.0/default/include/core/4.0/default/StreamOut.h new file mode 100644 index 0000000000..dbf3bd16ce --- /dev/null +++ b/audio/core/4.0/default/include/core/4.0/default/StreamOut.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_AUDIO_V4_0_STREAMOUT_H +#define ANDROID_HARDWARE_AUDIO_V4_0_STREAMOUT_H + +#include + +#include "Device.h" +#include "Stream.h" + +#define AUDIO_HAL_VERSION V4_0 +#include +#undef AUDIO_HAL_VERSION + +#endif // ANDROID_HARDWARE_AUDIO_V4_0_STREAMOUT_H diff --git a/audio/core/all-versions/default/Android.bp b/audio/core/all-versions/default/Android.bp index 214b8d5b26..bb02863ba6 100644 --- a/audio/core/all-versions/default/Android.bp +++ b/audio/core/all-versions/default/Android.bp @@ -1,7 +1,6 @@ cc_library_headers { name: "android.hardware.audio.core@all-versions-impl", relative_install_path: "hw", - proprietary: true, vendor: true, defaults: ["hidl_defaults"], diff --git a/audio/core/all-versions/default/include/core/all-versions/default/Device.h b/audio/core/all-versions/default/include/core/all-versions/default/Device.h index 224823c8aa..eb53b482b2 100644 --- a/audio/core/all-versions/default/include/core/all-versions/default/Device.h +++ b/audio/core/all-versions/default/include/core/all-versions/default/Device.h @@ -25,6 +25,8 @@ #include +#include + namespace android { namespace hardware { namespace audio { @@ -39,6 +41,9 @@ using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioPatchHandle; using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioPort; using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioPortConfig; using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioSource; +using ::android::hardware::audio::common::AUDIO_HAL_VERSION::implementation::AudioInputFlagBitfield; +using ::android::hardware::audio::common::AUDIO_HAL_VERSION::implementation:: + AudioOutputFlagBitfield; using ::android::hardware::audio::AUDIO_HAL_VERSION::DeviceAddress; using ::android::hardware::audio::AUDIO_HAL_VERSION::IDevice; using ::android::hardware::audio::AUDIO_HAL_VERSION::IStreamIn; @@ -51,6 +56,11 @@ using ::android::hardware::hidl_vec; using ::android::hardware::hidl_string; using ::android::sp; +#ifdef AUDIO_HAL_VERSION_4_0 +using ::android::hardware::audio::AUDIO_HAL_VERSION::SourceMetadata; +using ::android::hardware::audio::AUDIO_HAL_VERSION::SinkMetadata; +#endif + struct Device : public IDevice, public ParametersUtil { explicit Device(audio_hw_device_t* device); @@ -64,12 +74,26 @@ struct Device : public IDevice, public ParametersUtil { Return getMasterMute(getMasterMute_cb _hidl_cb) override; Return getInputBufferSize(const AudioConfig& config, getInputBufferSize_cb _hidl_cb) override; + + // V2 openInputStream is called by V4 input stream thus present in both versions + Return openInputStream(int32_t ioHandle, const DeviceAddress& device, + const AudioConfig& config, AudioInputFlagBitfield flags, + AudioSource source, openInputStream_cb _hidl_cb); +#ifdef AUDIO_HAL_VERSION_2_0 Return openOutputStream(int32_t ioHandle, const DeviceAddress& device, - const AudioConfig& config, AudioOutputFlag flags, + const AudioConfig& config, AudioOutputFlagBitfield flags, + openOutputStream_cb _hidl_cb) override; +#elif defined(AUDIO_HAL_VERSION_4_0) + Return openOutputStream(int32_t ioHandle, const DeviceAddress& device, + const AudioConfig& config, AudioOutputFlagBitfield flags, + const SourceMetadata& sourceMetadata, openOutputStream_cb _hidl_cb) override; Return openInputStream(int32_t ioHandle, const DeviceAddress& device, - const AudioConfig& config, AudioInputFlag flags, - AudioSource source, openInputStream_cb _hidl_cb) override; + const AudioConfig& config, AudioInputFlagBitfield flags, + const SinkMetadata& sinkMetadata, + openInputStream_cb _hidl_cb) override; +#endif + Return supportsAudioPatches() override; Return createAudioPatch(const hidl_vec& sources, const hidl_vec& sinks, @@ -77,12 +101,27 @@ struct Device : public IDevice, public ParametersUtil { Return releaseAudioPatch(int32_t patch) override; Return getAudioPort(const AudioPort& port, getAudioPort_cb _hidl_cb) override; Return setAudioPortConfig(const AudioPortConfig& config) override; - Return getHwAvSync() override; + Return setScreenState(bool turnedOn) override; + +#ifdef AUDIO_HAL_VERSION_2_0 + Return getHwAvSync() override; Return getParameters(const hidl_vec& keys, getParameters_cb _hidl_cb) override; Return setParameters(const hidl_vec& parameters) override; Return debugDump(const hidl_handle& fd) override; +#elif defined(AUDIO_HAL_VERSION_4_0) + Return getHwAvSync(getHwAvSync_cb _hidl_cb) override; + Return getParameters(const hidl_vec& context, + const hidl_vec& keys, + getParameters_cb _hidl_cb) override; + Return setParameters(const hidl_vec& context, + const hidl_vec& parameters) override; + Return getMicrophones(getMicrophones_cb _hidl_cb) override; + Return setConnectedState(const DeviceAddress& address, bool connected) override; +#endif + + Return debug(const hidl_handle& fd, const hidl_vec& options) override; // Utility methods for extending interfaces. Result analyzeStatus(const char* funcName, int status); diff --git a/audio/core/all-versions/default/include/core/all-versions/default/Device.impl.h b/audio/core/all-versions/default/include/core/all-versions/default/Device.impl.h index b2950825ba..fb4b686c43 100644 --- a/audio/core/all-versions/default/include/core/all-versions/default/Device.impl.h +++ b/audio/core/all-versions/default/include/core/all-versions/default/Device.impl.h @@ -147,7 +147,10 @@ Return Device::getInputBufferSize(const AudioConfig& config, getInputBuffe } Return Device::openOutputStream(int32_t ioHandle, const DeviceAddress& device, - const AudioConfig& config, AudioOutputFlag flags, + const AudioConfig& config, AudioOutputFlagBitfield flags, +#ifdef AUDIO_HAL_VERSION_4_0 + const SourceMetadata& /* sourceMetadata */, +#endif openOutputStream_cb _hidl_cb) { audio_config_t halConfig; HidlUtils::audioConfigToHal(config, &halConfig); @@ -174,7 +177,7 @@ Return Device::openOutputStream(int32_t ioHandle, const DeviceAddress& dev } Return Device::openInputStream(int32_t ioHandle, const DeviceAddress& device, - const AudioConfig& config, AudioInputFlag flags, + const AudioConfig& config, AudioInputFlagBitfield flags, AudioSource source, openInputStream_cb _hidl_cb) { audio_config_t halConfig; HidlUtils::audioConfigToHal(config, &halConfig); @@ -201,6 +204,24 @@ Return Device::openInputStream(int32_t ioHandle, const DeviceAddress& devi return Void(); } +#ifdef AUDIO_HAL_VERSION_4_0 +Return Device::openInputStream(int32_t ioHandle, const DeviceAddress& device, + const AudioConfig& config, AudioInputFlagBitfield flags, + const SinkMetadata& sinkMetadata, + openInputStream_cb _hidl_cb) { + if (sinkMetadata.tracks.size() == 0) { + // This should never happen, the framework must not create as stream + // if there is no client + ALOGE("openInputStream called without tracks connected"); + _hidl_cb(Result::INVALID_ARGUMENTS, nullptr, AudioConfig()); + return Void(); + } + // Pick the first one as the main until the legacy API is update + AudioSource source = sinkMetadata.tracks[0].source; + return openInputStream(ioHandle, device, config, flags, source, _hidl_cb); +} +#endif + Return Device::supportsAudioPatches() { return version() >= AUDIO_DEVICE_API_VERSION_3_0; } @@ -256,32 +277,72 @@ Return Device::setAudioPortConfig(const AudioPortConfig& config) { return Result::NOT_SUPPORTED; } +#ifdef AUDIO_HAL_VERSION_2_0 Return Device::getHwAvSync() { int halHwAvSync; Result retval = getParam(AudioParameter::keyHwAvSync, &halHwAvSync); return retval == Result::OK ? halHwAvSync : AUDIO_HW_SYNC_INVALID; } +#elif defined(AUDIO_HAL_VERSION_4_0) +Return Device::getHwAvSync(getHwAvSync_cb _hidl_cb) { + int halHwAvSync; + Result retval = getParam(AudioParameter::keyHwAvSync, &halHwAvSync); + _hidl_cb(retval, halHwAvSync); + return Void(); +} +#endif Return Device::setScreenState(bool turnedOn) { return setParam(AudioParameter::keyScreenState, turnedOn); } +#ifdef AUDIO_HAL_VERSION_2_0 Return Device::getParameters(const hidl_vec& keys, getParameters_cb _hidl_cb) { - getParametersImpl(keys, _hidl_cb); + getParametersImpl({}, keys, _hidl_cb); return Void(); } Return Device::setParameters(const hidl_vec& parameters) { - return setParametersImpl(parameters); + return setParametersImpl({} /* context */, parameters); } +#elif defined(AUDIO_HAL_VERSION_4_0) +Return Device::getParameters(const hidl_vec& context, + const hidl_vec& keys, getParameters_cb _hidl_cb) { + getParametersImpl(context, keys, _hidl_cb); + return Void(); +} +Return Device::setParameters(const hidl_vec& context, + const hidl_vec& parameters) { + return setParametersImpl(context, parameters); +} +#endif +#ifdef AUDIO_HAL_VERSION_2_0 Return Device::debugDump(const hidl_handle& fd) { + return debug(fd, {}); +} +#endif + +Return Device::debug(const hidl_handle& fd, const hidl_vec& /* options */) { if (fd.getNativeHandle() != nullptr && fd->numFds == 1) { analyzeStatus("dump", mDevice->dump(mDevice, fd->data[0])); } return Void(); } +#ifdef AUDIO_HAL_VERSION_4_0 +Return Device::getMicrophones(getMicrophones_cb _hidl_cb) { + // TODO return device microphones + _hidl_cb(Result::NOT_SUPPORTED, {}); + return Void(); +} + +Return Device::setConnectedState(const DeviceAddress& address, bool connected) { + auto key = connected ? AudioParameter::keyStreamConnect : AudioParameter::keyStreamDisconnect; + return setParam(key, address); +} +#endif + } // namespace implementation } // namespace AUDIO_HAL_VERSION } // namespace audio diff --git a/audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.h b/audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.h index 769adaa1e9..1509ad170c 100644 --- a/audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.h +++ b/audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.h @@ -37,11 +37,19 @@ using ::android::hardware::hidl_string; using ::android::sp; struct DevicesFactory : public IDevicesFactory { - // Methods from ::android::hardware::audio::AUDIO_HAL_VERSION::IDevicesFactory follow. +#ifdef AUDIO_HAL_VERSION_2_0 Return openDevice(IDevicesFactory::Device device, openDevice_cb _hidl_cb) override; +#endif +#ifdef AUDIO_HAL_VERSION_4_0 + Return openDevice(const hidl_string& device, openDevice_cb _hidl_cb) override; + Return openPrimaryDevice(openPrimaryDevice_cb _hidl_cb) override; +#endif private: - static const char* deviceToString(IDevicesFactory::Device device); + template + Return openDevice(const char* moduleName, Callback _hidl_cb); + Return openDevice(const char* moduleName, openDevice_cb _hidl_cb); + static int loadAudioInterface(const char* if_name, audio_hw_device_t** dev); }; diff --git a/audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.impl.h b/audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.impl.h index 014b4d8043..43e5d6eaed 100644 --- a/audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.impl.h +++ b/audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.impl.h @@ -26,21 +26,54 @@ namespace audio { namespace AUDIO_HAL_VERSION { namespace implementation { -// static -const char* DevicesFactory::deviceToString(IDevicesFactory::Device device) { +#ifdef AUDIO_HAL_VERSION_2_0 +Return DevicesFactory::openDevice(IDevicesFactory::Device device, openDevice_cb _hidl_cb) { switch (device) { case IDevicesFactory::Device::PRIMARY: - return AUDIO_HARDWARE_MODULE_ID_PRIMARY; + return openDevice(AUDIO_HARDWARE_MODULE_ID_PRIMARY, _hidl_cb); case IDevicesFactory::Device::A2DP: - return AUDIO_HARDWARE_MODULE_ID_A2DP; + return openDevice(AUDIO_HARDWARE_MODULE_ID_A2DP, _hidl_cb); case IDevicesFactory::Device::USB: - return AUDIO_HARDWARE_MODULE_ID_USB; + return openDevice(AUDIO_HARDWARE_MODULE_ID_USB, _hidl_cb); case IDevicesFactory::Device::R_SUBMIX: - return AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX; + return openDevice(AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX, _hidl_cb); case IDevicesFactory::Device::STUB: - return AUDIO_HARDWARE_MODULE_ID_STUB; + return openDevice(AUDIO_HARDWARE_MODULE_ID_STUB, _hidl_cb); } - return nullptr; + _hidl_cb(Result::INVALID_ARGUMENTS, nullptr); + return Void(); +} +#endif +#ifdef AUDIO_HAL_VERSION_4_0 +Return DevicesFactory::openDevice(const hidl_string& moduleName, openDevice_cb _hidl_cb) { + if (moduleName == AUDIO_HARDWARE_MODULE_ID_PRIMARY) { + return openDevice(moduleName.c_str(), _hidl_cb); + } + return openDevice(moduleName.c_str(), _hidl_cb); +} +Return DevicesFactory::openPrimaryDevice(openPrimaryDevice_cb _hidl_cb) { + return openDevice(AUDIO_HARDWARE_MODULE_ID_PRIMARY, _hidl_cb); +} +#endif + +Return DevicesFactory::openDevice(const char* moduleName, openDevice_cb _hidl_cb) { + return openDevice(moduleName, _hidl_cb); +} + +template +Return DevicesFactory::openDevice(const char* moduleName, Callback _hidl_cb) { + audio_hw_device_t* halDevice; + Result retval(Result::INVALID_ARGUMENTS); + sp result; + int halStatus = loadAudioInterface(moduleName, &halDevice); + if (halStatus == OK) { + result = new DeviceShim(halDevice); + retval = Result::OK; + } else if (halStatus == -EINVAL) { + retval = Result::NOT_INITIALIZED; + } + _hidl_cb(retval, result); + return Void(); } // static @@ -73,30 +106,6 @@ out: return rc; } -// Methods from ::android::hardware::audio::AUDIO_HAL_VERSION::IDevicesFactory follow. -Return DevicesFactory::openDevice(IDevicesFactory::Device device, openDevice_cb _hidl_cb) { - audio_hw_device_t* halDevice; - Result retval(Result::INVALID_ARGUMENTS); - sp result; - const char* moduleName = deviceToString(device); - if (moduleName != nullptr) { - int halStatus = loadAudioInterface(moduleName, &halDevice); - if (halStatus == OK) { - if (device == IDevicesFactory::Device::PRIMARY) { - result = new PrimaryDevice(halDevice); - } else { - result = new ::android::hardware::audio::AUDIO_HAL_VERSION::implementation::Device( - halDevice); - } - retval = Result::OK; - } else if (halStatus == -EINVAL) { - retval = Result::NOT_INITIALIZED; - } - } - _hidl_cb(retval, result); - return Void(); -} - IDevicesFactory* HIDL_FETCH_IDevicesFactory(const char* /* name */) { return new DevicesFactory(); } diff --git a/audio/core/all-versions/default/include/core/all-versions/default/ParametersUtil.h b/audio/core/all-versions/default/include/core/all-versions/default/ParametersUtil.h index df5adeefc1..a27ac25d43 100644 --- a/audio/core/all-versions/default/include/core/all-versions/default/ParametersUtil.h +++ b/audio/core/all-versions/default/include/core/all-versions/default/ParametersUtil.h @@ -28,6 +28,7 @@ namespace audio { namespace AUDIO_HAL_VERSION { namespace implementation { +using ::android::hardware::audio::AUDIO_HAL_VERSION::DeviceAddress; using ::android::hardware::audio::AUDIO_HAL_VERSION::ParameterValue; using ::android::hardware::audio::AUDIO_HAL_VERSION::Result; using ::android::hardware::hidl_string; @@ -37,16 +38,18 @@ class ParametersUtil { public: Result getParam(const char* name, bool* value); Result getParam(const char* name, int* value); - Result getParam(const char* name, String8* value); + Result getParam(const char* name, String8* value, AudioParameter context = {}); void getParametersImpl( - const hidl_vec& keys, + const hidl_vec& context, const hidl_vec& keys, std::function& parameters)> cb); std::unique_ptr getParams(const AudioParameter& keys); Result setParam(const char* name, bool value); Result setParam(const char* name, int value); - Result setParam(const char* name, const char* value); - Result setParametersImpl(const hidl_vec& parameters); + Result setParam(const char* name, float value); + Result setParametersImpl(const hidl_vec& context, + const hidl_vec& parameters); Result setParams(const AudioParameter& param); + Result setParam(const char* name, const DeviceAddress& address); protected: virtual ~ParametersUtil() {} diff --git a/audio/core/all-versions/default/include/core/all-versions/default/ParametersUtil.impl.h b/audio/core/all-versions/default/include/core/all-versions/default/ParametersUtil.impl.h index a858a488eb..3907284048 100644 --- a/audio/core/all-versions/default/include/core/all-versions/default/ParametersUtil.impl.h +++ b/audio/core/all-versions/default/include/core/all-versions/default/ParametersUtil.impl.h @@ -15,6 +15,8 @@ */ #include +#include +#include namespace android { namespace hardware { @@ -62,18 +64,20 @@ Result ParametersUtil::getParam(const char* name, int* value) { return getHalStatusToResult(params->getInt(halName, *value)); } -Result ParametersUtil::getParam(const char* name, String8* value) { +Result ParametersUtil::getParam(const char* name, String8* value, AudioParameter context) { const String8 halName(name); - AudioParameter keys; - keys.addKey(halName); - std::unique_ptr params = getParams(keys); + context.addKey(halName); + std::unique_ptr params = getParams(context); return getHalStatusToResult(params->get(halName, *value)); } void ParametersUtil::getParametersImpl( - const hidl_vec& keys, + const hidl_vec& context, const hidl_vec& keys, std::function& parameters)> cb) { AudioParameter halKeys; + for (auto& pair : context) { + halKeys.add(String8(pair.key.c_str()), String8(pair.value.c_str())); + } for (size_t i = 0; i < keys.size(); ++i) { halKeys.addKey(String8(keys[i].c_str())); } @@ -120,19 +124,28 @@ Result ParametersUtil::setParam(const char* name, int value) { return setParams(param); } -Result ParametersUtil::setParam(const char* name, const char* value) { +Result ParametersUtil::setParam(const char* name, float value) { AudioParameter param; - param.add(String8(name), String8(value)); + param.addFloat(String8(name), value); return setParams(param); } -Result ParametersUtil::setParametersImpl(const hidl_vec& parameters) { +Result ParametersUtil::setParametersImpl(const hidl_vec& context, + const hidl_vec& parameters) { AudioParameter params; + for (auto& pair : context) { + params.add(String8(pair.key.c_str()), String8(pair.value.c_str())); + } for (size_t i = 0; i < parameters.size(); ++i) { params.add(String8(parameters[i].key.c_str()), String8(parameters[i].value.c_str())); } return setParams(params); } +Result ParametersUtil::setParam(const char* name, const DeviceAddress& address) { + AudioParameter params(String8(deviceAddressToHal(address).c_str())); + params.addInt(String8(name), int(address.device)); + return setParams(params); +} Result ParametersUtil::setParams(const AudioParameter& param) { int halStatus = halSetParameters(param.toString().string()); diff --git a/audio/core/all-versions/default/include/core/all-versions/default/PrimaryDevice.h b/audio/core/all-versions/default/include/core/all-versions/default/PrimaryDevice.h index 240b2212a2..42996d703e 100644 --- a/audio/core/all-versions/default/include/core/all-versions/default/PrimaryDevice.h +++ b/audio/core/all-versions/default/include/core/all-versions/default/PrimaryDevice.h @@ -59,12 +59,24 @@ struct PrimaryDevice : public IPrimaryDevice { Return getMasterMute(getMasterMute_cb _hidl_cb) override; Return getInputBufferSize(const AudioConfig& config, getInputBufferSize_cb _hidl_cb) override; + Return openOutputStream(int32_t ioHandle, const DeviceAddress& device, - const AudioConfig& config, AudioOutputFlag flags, + const AudioConfig& config, AudioOutputFlagBitfield flags, +#ifdef AUDIO_HAL_VERSION_4_0 + const SourceMetadata& sourceMetadata, +#endif openOutputStream_cb _hidl_cb) override; + Return openInputStream(int32_t ioHandle, const DeviceAddress& device, - const AudioConfig& config, AudioInputFlag flags, - AudioSource source, openInputStream_cb _hidl_cb) override; + const AudioConfig& config, AudioInputFlagBitfield flags, + AudioSource source, openInputStream_cb _hidl_cb); +#ifdef AUDIO_HAL_VERSION_4_0 + Return openInputStream(int32_t ioHandle, const DeviceAddress& device, + const AudioConfig& config, AudioInputFlagBitfield flags, + const SinkMetadata& sinkMetadata, + openInputStream_cb _hidl_cb) override; +#endif + Return supportsAudioPatches() override; Return createAudioPatch(const hidl_vec& sources, const hidl_vec& sinks, @@ -72,12 +84,27 @@ struct PrimaryDevice : public IPrimaryDevice { Return releaseAudioPatch(int32_t patch) override; Return getAudioPort(const AudioPort& port, getAudioPort_cb _hidl_cb) override; Return setAudioPortConfig(const AudioPortConfig& config) override; - Return getHwAvSync() override; + Return setScreenState(bool turnedOn) override; + +#ifdef AUDIO_HAL_VERSION_2_0 + Return getHwAvSync() override; Return getParameters(const hidl_vec& keys, getParameters_cb _hidl_cb) override; Return setParameters(const hidl_vec& parameters) override; Return debugDump(const hidl_handle& fd) override; +#elif defined(AUDIO_HAL_VERSION_4_0) + Return getHwAvSync(getHwAvSync_cb _hidl_cb) override; + Return getParameters(const hidl_vec& context, + const hidl_vec& keys, + getParameters_cb _hidl_cb) override; + Return setParameters(const hidl_vec& context, + const hidl_vec& parameters) override; + Return getMicrophones(getMicrophones_cb _hidl_cb) override; + Return setConnectedState(const DeviceAddress& address, bool connected) override; +#endif + + Return debug(const hidl_handle& fd, const hidl_vec& options) override; // Methods from ::android::hardware::audio::AUDIO_HAL_VERSION::IPrimaryDevice follow. Return setVoiceVolume(float volume) override; @@ -91,6 +118,15 @@ struct PrimaryDevice : public IPrimaryDevice { Return getHacEnabled(getHacEnabled_cb _hidl_cb) override; Return setHacEnabled(bool enabled) override; +#ifdef AUDIO_HAL_VERSION_4_0 + Return setBtScoHeadsetDebugName(const hidl_string& name) override; + Return getBtHfpEnabled(getBtHfpEnabled_cb _hidl_cb) override; + Return setBtHfpEnabled(bool enabled) override; + Return setBtHfpSampleRate(uint32_t sampleRateHz) override; + Return setBtHfpVolume(float volume) override; + Return updateRotation(IPrimaryDevice::Rotation rotation) override; +#endif + private: sp mDevice; diff --git a/audio/core/all-versions/default/include/core/all-versions/default/PrimaryDevice.impl.h b/audio/core/all-versions/default/include/core/all-versions/default/PrimaryDevice.impl.h index 3ce047ac07..f00cac4ee1 100644 --- a/audio/core/all-versions/default/include/core/all-versions/default/PrimaryDevice.impl.h +++ b/audio/core/all-versions/default/include/core/all-versions/default/PrimaryDevice.impl.h @@ -60,17 +60,35 @@ Return PrimaryDevice::getInputBufferSize(const AudioConfig& config, return mDevice->getInputBufferSize(config, _hidl_cb); } +#ifdef AUDIO_HAL_VERSION_2_0 Return PrimaryDevice::openOutputStream(int32_t ioHandle, const DeviceAddress& device, - const AudioConfig& config, AudioOutputFlag flags, + const AudioConfig& config, + AudioOutputFlagBitfield flags, openOutputStream_cb _hidl_cb) { return mDevice->openOutputStream(ioHandle, device, config, flags, _hidl_cb); } Return PrimaryDevice::openInputStream(int32_t ioHandle, const DeviceAddress& device, - const AudioConfig& config, AudioInputFlag flags, + const AudioConfig& config, AudioInputFlagBitfield flags, AudioSource source, openInputStream_cb _hidl_cb) { return mDevice->openInputStream(ioHandle, device, config, flags, source, _hidl_cb); } +#elif defined(AUDIO_HAL_VERSION_4_0) +Return PrimaryDevice::openOutputStream(int32_t ioHandle, const DeviceAddress& device, + const AudioConfig& config, + AudioOutputFlagBitfield flags, + const SourceMetadata& sourceMetadata, + openOutputStream_cb _hidl_cb) { + return mDevice->openOutputStream(ioHandle, device, config, flags, sourceMetadata, _hidl_cb); +} + +Return PrimaryDevice::openInputStream(int32_t ioHandle, const DeviceAddress& device, + const AudioConfig& config, AudioInputFlagBitfield flags, + const SinkMetadata& sinkMetadata, + openInputStream_cb _hidl_cb) { + return mDevice->openInputStream(ioHandle, device, config, flags, sinkMetadata, _hidl_cb); +} +#endif Return PrimaryDevice::supportsAudioPatches() { return mDevice->supportsAudioPatches(); @@ -94,14 +112,15 @@ Return PrimaryDevice::setAudioPortConfig(const AudioPortConfig& config) return mDevice->setAudioPortConfig(config); } -Return PrimaryDevice::getHwAvSync() { - return mDevice->getHwAvSync(); -} - Return PrimaryDevice::setScreenState(bool turnedOn) { return mDevice->setScreenState(turnedOn); } +#ifdef AUDIO_HAL_VERSION_2_0 +Return PrimaryDevice::getHwAvSync() { + return mDevice->getHwAvSync(); +} + Return PrimaryDevice::getParameters(const hidl_vec& keys, getParameters_cb _hidl_cb) { return mDevice->getParameters(keys, _hidl_cb); @@ -114,6 +133,26 @@ Return PrimaryDevice::setParameters(const hidl_vec& para Return PrimaryDevice::debugDump(const hidl_handle& fd) { return mDevice->debugDump(fd); } +#elif defined(AUDIO_HAL_VERSION_4_0) +Return PrimaryDevice::getHwAvSync(getHwAvSync_cb _hidl_cb) { + return mDevice->getHwAvSync(_hidl_cb); +} +Return PrimaryDevice::getParameters(const hidl_vec& context, + const hidl_vec& keys, + getParameters_cb _hidl_cb) { + return mDevice->getParameters(context, keys, _hidl_cb); +} +Return PrimaryDevice::setParameters(const hidl_vec& context, + const hidl_vec& parameters) { + return mDevice->setParameters(context, parameters); +} +Return PrimaryDevice::getMicrophones(getMicrophones_cb _hidl_cb) { + return mDevice->getMicrophones(_hidl_cb); +} +Return PrimaryDevice::setConnectedState(const DeviceAddress& address, bool connected) { + return mDevice->setConnectedState(address, connected); +} +#endif // Methods from ::android::hardware::audio::AUDIO_HAL_VERSION::IPrimaryDevice follow. Return PrimaryDevice::setVoiceVolume(float volume) { @@ -188,6 +227,35 @@ Return PrimaryDevice::setHacEnabled(bool enabled) { return mDevice->setParam(AUDIO_PARAMETER_KEY_HAC, enabled); } +#ifdef AUDIO_HAL_VERSION_4_0 +Return PrimaryDevice::setBtScoHeadsetDebugName(const hidl_string& name) { + return mDevice->setParam(AUDIO_PARAMETER_KEY_BT_SCO_HEADSET_NAME, name.c_str()); +} +Return PrimaryDevice::getBtHfpEnabled(getBtHfpEnabled_cb _hidl_cb) { + bool enabled; + Result retval = mDevice->getParam(AUDIO_PARAMETER_KEY_HFP_ENABLE, &enabled); + _hidl_cb(retval, enabled); + return Void(); +} +Return PrimaryDevice::setBtHfpEnabled(bool enabled) { + return mDevice->setParam(AUDIO_PARAMETER_KEY_HFP_ENABLE, enabled); +} +Return PrimaryDevice::setBtHfpSampleRate(uint32_t sampleRateHz) { + return mDevice->setParam(AUDIO_PARAMETER_KEY_HFP_SET_SAMPLING_RATE, int(sampleRateHz)); +} +Return PrimaryDevice::setBtHfpVolume(float volume) { + return mDevice->setParam(AUDIO_PARAMETER_KEY_HFP_VOLUME, volume); +} +Return PrimaryDevice::updateRotation(IPrimaryDevice::Rotation rotation) { + // legacy API expects the rotation in degree + return mDevice->setParam(AUDIO_PARAMETER_KEY_ROTATION, int(rotation) * 90); +} +#endif + +Return PrimaryDevice::debug(const hidl_handle& fd, const hidl_vec& options) { + return mDevice->debug(fd, options); +} + } // namespace implementation } // namespace AUDIO_HAL_VERSION } // namespace audio diff --git a/audio/core/all-versions/default/include/core/all-versions/default/Stream.h b/audio/core/all-versions/default/include/core/all-versions/default/Stream.h index 4196dec7df..6f79429c61 100644 --- a/audio/core/all-versions/default/include/core/all-versions/default/Stream.h +++ b/audio/core/all-versions/default/include/core/all-versions/default/Stream.h @@ -23,6 +23,8 @@ #include +#include + namespace android { namespace hardware { namespace audio { @@ -32,6 +34,7 @@ namespace implementation { using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioChannelMask; using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioDevice; using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioFormat; +using ::android::hardware::audio::common::AUDIO_HAL_VERSION::implementation::AudioChannelBitfield; using ::android::hardware::audio::AUDIO_HAL_VERSION::DeviceAddress; using ::android::hardware::audio::AUDIO_HAL_VERSION::IStream; using ::android::hardware::audio::AUDIO_HAL_VERSION::ParameterValue; @@ -57,11 +60,15 @@ struct Stream : public IStream, public ParametersUtil { Return getFrameCount() override; Return getBufferSize() override; Return getSampleRate() override; +#ifdef AUDIO_HAL_VERSION_2_0 Return getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) override; - Return setSampleRate(uint32_t sampleRateHz) override; - Return getChannelMask() override; Return getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) override; - Return setChannelMask(AudioChannelMask mask) override; +#endif + Return getSupportedSampleRates(AudioFormat format, getSupportedSampleRates_cb _hidl_cb); + Return getSupportedChannelMasks(AudioFormat format, getSupportedChannelMasks_cb _hidl_cb); + Return setSampleRate(uint32_t sampleRateHz) override; + Return getChannelMask() override; + Return setChannelMask(AudioChannelBitfield mask) override; Return getFormat() override; Return getSupportedFormats(getSupportedFormats_cb _hidl_cb) override; Return setFormat(AudioFormat format) override; @@ -69,20 +76,34 @@ struct Stream : public IStream, public ParametersUtil { Return addEffect(uint64_t effectId) override; Return removeEffect(uint64_t effectId) override; Return standby() override; +#ifdef AUDIO_HAL_VERSION_2_0 Return getDevice() override; Return setDevice(const DeviceAddress& address) override; - Return setConnectedState(const DeviceAddress& address, bool connected) override; - Return setHwAvSync(uint32_t hwAvSync) override; Return getParameters(const hidl_vec& keys, getParameters_cb _hidl_cb) override; Return setParameters(const hidl_vec& parameters) override; - Return debugDump(const hidl_handle& fd) override; + Return setConnectedState(const DeviceAddress& address, bool connected) override; +#elif defined(AUDIO_HAL_VERSION_4_0) + Return getDevices(getDevices_cb _hidl_cb) override; + Return setDevices(const hidl_vec& devices) override; + Return getParameters(const hidl_vec& context, + const hidl_vec& keys, + getParameters_cb _hidl_cb) override; + Return setParameters(const hidl_vec& context, + const hidl_vec& parameters) override; +#endif + Return setHwAvSync(uint32_t hwAvSync) override; Return start() override; Return stop() override; Return createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) override; Return getMmapPosition(getMmapPosition_cb _hidl_cb) override; Return close() override; + Return debug(const hidl_handle& fd, const hidl_vec& options) override; +#ifdef AUDIO_HAL_VERSION_2_0 + Return debugDump(const hidl_handle& fd) override; +#endif + // Utility methods for extending interfaces. static Result analyzeStatus(const char* funcName, int status); static Result analyzeStatus(const char* funcName, int status, diff --git a/audio/core/all-versions/default/include/core/all-versions/default/Stream.impl.h b/audio/core/all-versions/default/include/core/all-versions/default/Stream.impl.h index 92cff72642..fa0ef45bec 100644 --- a/audio/core/all-versions/default/include/core/all-versions/default/Stream.impl.h +++ b/audio/core/all-versions/default/include/core/all-versions/default/Stream.impl.h @@ -100,9 +100,22 @@ Return Stream::getSampleRate() { return mStream->get_sample_rate(mStream); } +#ifdef AUDIO_HAL_VERSION_2_0 Return Stream::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) { + return getSupportedSampleRates(getFormat(), _hidl_cb); +} +Return Stream::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) { + return getSupportedChannelMasks(getFormat(), _hidl_cb); +} +#endif + +Return Stream::getSupportedSampleRates(AudioFormat format, + getSupportedSampleRates_cb _hidl_cb) { + AudioParameter context; + context.addInt(String8(AUDIO_PARAMETER_STREAM_FORMAT), int(format)); String8 halListValue; - Result result = getParam(AudioParameter::keyStreamSupportedSamplingRates, &halListValue); + Result result = + getParam(AudioParameter::keyStreamSupportedSamplingRates, &halListValue, context); hidl_vec sampleRates; SortedVector halSampleRates; if (result == Result::OK) { @@ -110,7 +123,36 @@ Return Stream::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb samplingRatesFromString(halListValue.string(), AudioParameter::valueListSeparator); sampleRates.setToExternal(halSampleRates.editArray(), halSampleRates.size()); } +#ifdef AUDIO_HAL_VERSION_2_0 _hidl_cb(sampleRates); +#endif +#ifdef AUDIO_HAL_VERSION_4_0 + _hidl_cb(result, sampleRates); +#endif + return Void(); +} + +Return Stream::getSupportedChannelMasks(AudioFormat format, + getSupportedChannelMasks_cb _hidl_cb) { + AudioParameter context; + context.addInt(String8(AUDIO_PARAMETER_STREAM_FORMAT), int(format)); + String8 halListValue; + Result result = getParam(AudioParameter::keyStreamSupportedChannels, &halListValue, context); + hidl_vec channelMasks; + SortedVector halChannelMasks; + if (result == Result::OK) { + halChannelMasks = + channelMasksFromString(halListValue.string(), AudioParameter::valueListSeparator); + channelMasks.resize(halChannelMasks.size()); + for (size_t i = 0; i < halChannelMasks.size(); ++i) { + channelMasks[i] = AudioChannelBitfield(halChannelMasks[i]); + } + } +#ifdef AUDIO_HAL_VERSION_2_0 + _hidl_cb(channelMasks); +#elif defined(AUDIO_HAL_VERSION_4_0) + _hidl_cb(result, channelMasks); +#endif return Void(); } @@ -118,28 +160,11 @@ Return Stream::setSampleRate(uint32_t sampleRateHz) { return setParam(AudioParameter::keySamplingRate, static_cast(sampleRateHz)); } -Return Stream::getChannelMask() { - return AudioChannelMask(mStream->get_channels(mStream)); +Return Stream::getChannelMask() { + return AudioChannelBitfield(mStream->get_channels(mStream)); } -Return Stream::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) { - String8 halListValue; - Result result = getParam(AudioParameter::keyStreamSupportedChannels, &halListValue); - hidl_vec channelMasks; - SortedVector halChannelMasks; - if (result == Result::OK) { - halChannelMasks = - channelMasksFromString(halListValue.string(), AudioParameter::valueListSeparator); - channelMasks.resize(halChannelMasks.size()); - for (size_t i = 0; i < halChannelMasks.size(); ++i) { - channelMasks[i] = AudioChannelMask(halChannelMasks[i]); - } - } - _hidl_cb(channelMasks); - return Void(); -} - -Return Stream::setChannelMask(AudioChannelMask mask) { +Return Stream::setChannelMask(AudioChannelBitfield mask) { return setParam(AudioParameter::keyChannels, static_cast(mask)); } @@ -171,7 +196,7 @@ Return Stream::getAudioProperties(getAudioProperties_cb _hidl_cb) { uint32_t halSampleRate = mStream->get_sample_rate(mStream); audio_channel_mask_t halMask = mStream->get_channels(mStream); audio_format_t halFormat = mStream->get_format(mStream); - _hidl_cb(halSampleRate, AudioChannelMask(halMask), AudioFormat(halFormat)); + _hidl_cb(halSampleRate, AudioChannelBitfield(halMask), AudioFormat(halFormat)); return Void(); } @@ -200,48 +225,73 @@ Return Stream::standby() { return analyzeStatus("standby", mStream->standby(mStream)); } +Return Stream::setHwAvSync(uint32_t hwAvSync) { + return setParam(AudioParameter::keyStreamHwAvSync, static_cast(hwAvSync)); +} + +#ifdef AUDIO_HAL_VERSION_2_0 Return Stream::getDevice() { - int device; + int device = 0; Result retval = getParam(AudioParameter::keyRouting, &device); return retval == Result::OK ? static_cast(device) : AudioDevice::NONE; } Return Stream::setDevice(const DeviceAddress& address) { - char* halDeviceAddress = audio_device_address_to_parameter( - static_cast(address.device), deviceAddressToHal(address).c_str()); - AudioParameter params((String8(halDeviceAddress))); - free(halDeviceAddress); - params.addInt(String8(AudioParameter::keyRouting), - static_cast(address.device)); - return setParams(params); + return setParam(AudioParameter::keyRouting, address); +} + +Return Stream::getParameters(const hidl_vec& keys, getParameters_cb _hidl_cb) { + getParametersImpl({} /* context */, keys, _hidl_cb); + return Void(); +} + +Return Stream::setParameters(const hidl_vec& parameters) { + return setParametersImpl({} /* context */, parameters); } Return Stream::setConnectedState(const DeviceAddress& address, bool connected) { return setParam( connected ? AudioParameter::keyStreamConnect : AudioParameter::keyStreamDisconnect, - deviceAddressToHal(address).c_str()); + address); } - -Return Stream::setHwAvSync(uint32_t hwAvSync) { - return setParam(AudioParameter::keyStreamHwAvSync, static_cast(hwAvSync)); -} - -Return Stream::getParameters(const hidl_vec& keys, getParameters_cb _hidl_cb) { - getParametersImpl(keys, _hidl_cb); - return Void(); -} - -Return Stream::setParameters(const hidl_vec& parameters) { - return setParametersImpl(parameters); -} - -Return Stream::debugDump(const hidl_handle& fd) { - if (fd.getNativeHandle() != nullptr && fd->numFds == 1) { - analyzeStatus("dump", mStream->dump(mStream, fd->data[0])); +#elif defined(AUDIO_HAL_VERSION_4_0) +Return Stream::getDevices(getDevices_cb _hidl_cb) { + int device = 0; + Result retval = getParam(AudioParameter::keyRouting, &device); + hidl_vec devices; + if (retval == Result::OK) { + devices.resize(1); + devices[0].device = static_cast(device); } + _hidl_cb(retval, devices); return Void(); } +Return Stream::setDevices(const hidl_vec& devices) { + // FIXME: can the legacy API set multiple device with address ? + if (devices.size() > 1) { + return Result::NOT_SUPPORTED; + } + DeviceAddress address; + if (devices.size() == 1) { + address = devices[0]; + } else { + address.device = AudioDevice::NONE; + } + return setParam(AudioParameter::keyRouting, address); +} +Return Stream::getParameters(const hidl_vec& context, + const hidl_vec& keys, getParameters_cb _hidl_cb) { + getParametersImpl(context, keys, _hidl_cb); + return Void(); +} + +Return Stream::setParameters(const hidl_vec& context, + const hidl_vec& parameters) { + return setParametersImpl(context, parameters); +} +#endif + Return Stream::start() { return Result::NOT_SUPPORTED; } @@ -269,6 +319,19 @@ Return Stream::close() { return Result::NOT_SUPPORTED; } +Return Stream::debug(const hidl_handle& fd, const hidl_vec& /* options */) { + if (fd.getNativeHandle() != nullptr && fd->numFds == 1) { + analyzeStatus("dump", mStream->dump(mStream, fd->data[0])); + } + return Void(); +} + +#ifdef AUDIO_HAL_VERSION_2_0 +Return Stream::debugDump(const hidl_handle& fd) { + return debug(fd, {} /* options */); +} +#endif + } // namespace implementation } // namespace AUDIO_HAL_VERSION } // namespace audio diff --git a/audio/core/all-versions/default/include/core/all-versions/default/StreamIn.h b/audio/core/all-versions/default/include/core/all-versions/default/StreamIn.h index 7380dae108..f226e63f70 100644 --- a/audio/core/all-versions/default/include/core/all-versions/default/StreamIn.h +++ b/audio/core/all-versions/default/include/core/all-versions/default/StreamIn.h @@ -58,11 +58,15 @@ struct StreamIn : public IStreamIn { Return getFrameCount() override; Return getBufferSize() override; Return getSampleRate() override; +#ifdef AUDIO_HAL_VERSION_2_0 Return getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) override; - Return setSampleRate(uint32_t sampleRateHz) override; - Return getChannelMask() override; Return getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) override; - Return setChannelMask(AudioChannelMask mask) override; +#endif + Return getSupportedSampleRates(AudioFormat format, getSupportedSampleRates_cb _hidl_cb); + Return getSupportedChannelMasks(AudioFormat format, getSupportedChannelMasks_cb _hidl_cb); + Return setSampleRate(uint32_t sampleRateHz) override; + Return getChannelMask() override; + Return setChannelMask(AudioChannelBitfield mask) override; Return getFormat() override; Return getSupportedFormats(getSupportedFormats_cb _hidl_cb) override; Return setFormat(AudioFormat format) override; @@ -70,16 +74,30 @@ struct StreamIn : public IStreamIn { Return addEffect(uint64_t effectId) override; Return removeEffect(uint64_t effectId) override; Return standby() override; +#ifdef AUDIO_HAL_VERSION_2_0 Return getDevice() override; Return setDevice(const DeviceAddress& address) override; - Return setConnectedState(const DeviceAddress& address, bool connected) override; - Return setHwAvSync(uint32_t hwAvSync) override; Return getParameters(const hidl_vec& keys, getParameters_cb _hidl_cb) override; Return setParameters(const hidl_vec& parameters) override; - Return debugDump(const hidl_handle& fd) override; + Return setConnectedState(const DeviceAddress& address, bool connected) override; +#elif defined(AUDIO_HAL_VERSION_4_0) + Return getDevices(getDevices_cb _hidl_cb) override; + Return setDevices(const hidl_vec& devices) override; + Return getParameters(const hidl_vec& context, + const hidl_vec& keys, + getParameters_cb _hidl_cb) override; + Return setParameters(const hidl_vec& context, + const hidl_vec& parameters) override; +#endif + Return setHwAvSync(uint32_t hwAvSync) override; Return close() override; + Return debug(const hidl_handle& fd, const hidl_vec& options) override; +#ifdef AUDIO_HAL_VERSION_2_0 + Return debugDump(const hidl_handle& fd) override; +#endif + // Methods from ::android::hardware::audio::AUDIO_HAL_VERSION::IStreamIn follow. Return getAudioSource(getAudioSource_cb _hidl_cb) override; Return setGain(float gain) override; @@ -91,6 +109,10 @@ struct StreamIn : public IStreamIn { Return stop() override; Return createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) override; Return getMmapPosition(getMmapPosition_cb _hidl_cb) override; +#ifdef AUDIO_HAL_VERSION_4_0 + Return updateSinkMetadata(const SinkMetadata& sinkMetadata) override; + Return getActiveMicrophones(getActiveMicrophones_cb _hidl_cb) override; +#endif static Result getCapturePositionImpl(audio_stream_in_t* stream, uint64_t* frames, uint64_t* time); diff --git a/audio/core/all-versions/default/include/core/all-versions/default/StreamIn.impl.h b/audio/core/all-versions/default/include/core/all-versions/default/StreamIn.impl.h index abee225dc7..dcd3df19e6 100644 --- a/audio/core/all-versions/default/include/core/all-versions/default/StreamIn.impl.h +++ b/audio/core/all-versions/default/include/core/all-versions/default/StreamIn.impl.h @@ -179,23 +179,33 @@ Return StreamIn::getSampleRate() { return mStreamCommon->getSampleRate(); } +#ifdef AUDIO_HAL_VERSION_2_0 +Return StreamIn::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) { + return mStreamCommon->getSupportedChannelMasks(_hidl_cb); +} Return StreamIn::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) { return mStreamCommon->getSupportedSampleRates(_hidl_cb); } +#endif + +Return StreamIn::getSupportedChannelMasks(AudioFormat format, + getSupportedChannelMasks_cb _hidl_cb) { + return mStreamCommon->getSupportedChannelMasks(format, _hidl_cb); +} +Return StreamIn::getSupportedSampleRates(AudioFormat format, + getSupportedSampleRates_cb _hidl_cb) { + return mStreamCommon->getSupportedSampleRates(format, _hidl_cb); +} Return StreamIn::setSampleRate(uint32_t sampleRateHz) { return mStreamCommon->setSampleRate(sampleRateHz); } -Return StreamIn::getChannelMask() { +Return StreamIn::getChannelMask() { return mStreamCommon->getChannelMask(); } -Return StreamIn::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) { - return mStreamCommon->getSupportedChannelMasks(_hidl_cb); -} - -Return StreamIn::setChannelMask(AudioChannelMask mask) { +Return StreamIn::setChannelMask(AudioChannelBitfield mask) { return mStreamCommon->setChannelMask(mask); } @@ -227,6 +237,15 @@ Return StreamIn::standby() { return mStreamCommon->standby(); } +Return StreamIn::setHwAvSync(uint32_t hwAvSync) { + return mStreamCommon->setHwAvSync(hwAvSync); +} + +#ifdef AUDIO_HAL_VERSION_2_0 +Return StreamIn::setConnectedState(const DeviceAddress& address, bool connected) { + return mStreamCommon->setConnectedState(address, connected); +} + Return StreamIn::getDevice() { return mStreamCommon->getDevice(); } @@ -235,14 +254,6 @@ Return StreamIn::setDevice(const DeviceAddress& address) { return mStreamCommon->setDevice(address); } -Return StreamIn::setConnectedState(const DeviceAddress& address, bool connected) { - return mStreamCommon->setConnectedState(address, connected); -} - -Return StreamIn::setHwAvSync(uint32_t hwAvSync) { - return mStreamCommon->setHwAvSync(hwAvSync); -} - Return StreamIn::getParameters(const hidl_vec& keys, getParameters_cb _hidl_cb) { return mStreamCommon->getParameters(keys, _hidl_cb); } @@ -254,6 +265,24 @@ Return StreamIn::setParameters(const hidl_vec& parameter Return StreamIn::debugDump(const hidl_handle& fd) { return mStreamCommon->debugDump(fd); } +#elif defined(AUDIO_HAL_VERSION_4_0) +Return StreamIn::getDevices(getDevices_cb _hidl_cb) { + return mStreamCommon->getDevices(_hidl_cb); +} + +Return StreamIn::setDevices(const hidl_vec& devices) { + return mStreamCommon->setDevices(devices); +} +Return StreamIn::getParameters(const hidl_vec& context, + const hidl_vec& keys, getParameters_cb _hidl_cb) { + return mStreamCommon->getParameters(context, keys, _hidl_cb); +} + +Return StreamIn::setParameters(const hidl_vec& context, + const hidl_vec& parameters) { + return mStreamCommon->setParameters(context, parameters); +} +#endif Return StreamIn::start() { return mStreamMmap->start(); @@ -415,6 +444,21 @@ Return StreamIn::getCapturePosition(getCapturePosition_cb _hidl_cb) { return Void(); } +Return StreamIn::debug(const hidl_handle& fd, const hidl_vec& options) { + return mStreamCommon->debug(fd, options); +} + +#ifdef AUDIO_HAL_VERSION_4_0 +Return StreamIn::updateSinkMetadata(const SinkMetadata& /*sinkMetadata*/) { + return Void(); // TODO: propagate to legacy +} + +Return StreamIn::getActiveMicrophones(getActiveMicrophones_cb _hidl_cb) { + _hidl_cb(Result::NOT_SUPPORTED, {}); // TODO: retrieve from legacy + return Void(); +} +#endif + } // namespace implementation } // namespace AUDIO_HAL_VERSION } // namespace audio diff --git a/audio/core/all-versions/default/include/core/all-versions/default/StreamOut.h b/audio/core/all-versions/default/include/core/all-versions/default/StreamOut.h index 4cfe2e33f1..134d7b9bbe 100644 --- a/audio/core/all-versions/default/include/core/all-versions/default/StreamOut.h +++ b/audio/core/all-versions/default/include/core/all-versions/default/StreamOut.h @@ -60,11 +60,15 @@ struct StreamOut : public IStreamOut { Return getFrameCount() override; Return getBufferSize() override; Return getSampleRate() override; +#ifdef AUDIO_HAL_VERSION_2_0 Return getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) override; - Return setSampleRate(uint32_t sampleRateHz) override; - Return getChannelMask() override; Return getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) override; - Return setChannelMask(AudioChannelMask mask) override; +#endif + Return getSupportedSampleRates(AudioFormat format, getSupportedSampleRates_cb _hidl_cb); + Return getSupportedChannelMasks(AudioFormat format, getSupportedChannelMasks_cb _hidl_cb); + Return setSampleRate(uint32_t sampleRateHz) override; + Return getChannelMask() override; + Return setChannelMask(AudioChannelBitfield mask) override; Return getFormat() override; Return getSupportedFormats(getSupportedFormats_cb _hidl_cb) override; Return setFormat(AudioFormat format) override; @@ -72,16 +76,30 @@ struct StreamOut : public IStreamOut { Return addEffect(uint64_t effectId) override; Return removeEffect(uint64_t effectId) override; Return standby() override; +#ifdef AUDIO_HAL_VERSION_2_0 Return getDevice() override; Return setDevice(const DeviceAddress& address) override; - Return setConnectedState(const DeviceAddress& address, bool connected) override; - Return setHwAvSync(uint32_t hwAvSync) override; Return getParameters(const hidl_vec& keys, getParameters_cb _hidl_cb) override; Return setParameters(const hidl_vec& parameters) override; - Return debugDump(const hidl_handle& fd) override; + Return setConnectedState(const DeviceAddress& address, bool connected) override; +#elif defined(AUDIO_HAL_VERSION_4_0) + Return getDevices(getDevices_cb _hidl_cb) override; + Return setDevices(const hidl_vec& devices) override; + Return getParameters(const hidl_vec& context, + const hidl_vec& keys, + getParameters_cb _hidl_cb) override; + Return setParameters(const hidl_vec& context, + const hidl_vec& parameters) override; +#endif + Return setHwAvSync(uint32_t hwAvSync) override; Return close() override; + Return debug(const hidl_handle& fd, const hidl_vec& options) override; +#ifdef AUDIO_HAL_VERSION_2_0 + Return debugDump(const hidl_handle& fd) override; +#endif + // Methods from ::android::hardware::audio::AUDIO_HAL_VERSION::IStreamOut follow. Return getLatency() override; Return setVolume(float left, float right) override; @@ -102,6 +120,10 @@ struct StreamOut : public IStreamOut { Return stop() override; Return createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) override; Return getMmapPosition(getMmapPosition_cb _hidl_cb) override; +#ifdef AUDIO_HAL_VERSION_4_0 + Return updateSourceMetadata(const SourceMetadata& sourceMetadata) override; + Return selectPresentation(int32_t presentationId, int32_t programId) override; +#endif static Result getPresentationPositionImpl(audio_stream_out_t* stream, uint64_t* frames, TimeSpec* timeStamp); diff --git a/audio/core/all-versions/default/include/core/all-versions/default/StreamOut.impl.h b/audio/core/all-versions/default/include/core/all-versions/default/StreamOut.impl.h index bdbeb38288..605b824196 100644 --- a/audio/core/all-versions/default/include/core/all-versions/default/StreamOut.impl.h +++ b/audio/core/all-versions/default/include/core/all-versions/default/StreamOut.impl.h @@ -183,23 +183,33 @@ Return StreamOut::getSampleRate() { return mStreamCommon->getSampleRate(); } +#ifdef AUDIO_HAL_VERSION_2_0 +Return StreamOut::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) { + return mStreamCommon->getSupportedChannelMasks(_hidl_cb); +} Return StreamOut::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) { return mStreamCommon->getSupportedSampleRates(_hidl_cb); } +#endif + +Return StreamOut::getSupportedChannelMasks(AudioFormat format, + getSupportedChannelMasks_cb _hidl_cb) { + return mStreamCommon->getSupportedChannelMasks(format, _hidl_cb); +} +Return StreamOut::getSupportedSampleRates(AudioFormat format, + getSupportedSampleRates_cb _hidl_cb) { + return mStreamCommon->getSupportedSampleRates(format, _hidl_cb); +} Return StreamOut::setSampleRate(uint32_t sampleRateHz) { return mStreamCommon->setSampleRate(sampleRateHz); } -Return StreamOut::getChannelMask() { +Return StreamOut::getChannelMask() { return mStreamCommon->getChannelMask(); } -Return StreamOut::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) { - return mStreamCommon->getSupportedChannelMasks(_hidl_cb); -} - -Return StreamOut::setChannelMask(AudioChannelMask mask) { +Return StreamOut::setChannelMask(AudioChannelBitfield mask) { return mStreamCommon->setChannelMask(mask); } @@ -231,6 +241,15 @@ Return StreamOut::standby() { return mStreamCommon->standby(); } +Return StreamOut::setHwAvSync(uint32_t hwAvSync) { + return mStreamCommon->setHwAvSync(hwAvSync); +} + +#ifdef AUDIO_HAL_VERSION_2_0 +Return StreamOut::setConnectedState(const DeviceAddress& address, bool connected) { + return mStreamCommon->setConnectedState(address, connected); +} + Return StreamOut::getDevice() { return mStreamCommon->getDevice(); } @@ -239,14 +258,6 @@ Return StreamOut::setDevice(const DeviceAddress& address) { return mStreamCommon->setDevice(address); } -Return StreamOut::setConnectedState(const DeviceAddress& address, bool connected) { - return mStreamCommon->setConnectedState(address, connected); -} - -Return StreamOut::setHwAvSync(uint32_t hwAvSync) { - return mStreamCommon->setHwAvSync(hwAvSync); -} - Return StreamOut::getParameters(const hidl_vec& keys, getParameters_cb _hidl_cb) { return mStreamCommon->getParameters(keys, _hidl_cb); @@ -259,6 +270,25 @@ Return StreamOut::setParameters(const hidl_vec& paramete Return StreamOut::debugDump(const hidl_handle& fd) { return mStreamCommon->debugDump(fd); } +#elif defined(AUDIO_HAL_VERSION_4_0) +Return StreamOut::getDevices(getDevices_cb _hidl_cb) { + return mStreamCommon->getDevices(_hidl_cb); +} + +Return StreamOut::setDevices(const hidl_vec& devices) { + return mStreamCommon->setDevices(devices); +} +Return StreamOut::getParameters(const hidl_vec& context, + const hidl_vec& keys, + getParameters_cb _hidl_cb) { + return mStreamCommon->getParameters(context, keys, _hidl_cb); +} + +Return StreamOut::setParameters(const hidl_vec& context, + const hidl_vec& parameters) { + return mStreamCommon->setParameters(context, parameters); +} +#endif Return StreamOut::close() { if (mIsClosed) return Result::INVALID_STATE; @@ -512,6 +542,19 @@ Return StreamOut::getMmapPosition(getMmapPosition_cb _hidl_cb) { return mStreamMmap->getMmapPosition(_hidl_cb); } +Return StreamOut::debug(const hidl_handle& fd, const hidl_vec& options) { + return mStreamCommon->debug(fd, options); +} + +#ifdef AUDIO_HAL_VERSION_4_0 +Return StreamOut::updateSourceMetadata(const SourceMetadata& /*sourceMetadata*/) { + return Void(); // TODO: propagate to legacy +} +Return StreamOut::selectPresentation(int32_t /*presentationId*/, int32_t /*programId*/) { + return Result::NOT_SUPPORTED; // TODO: propagate to legacy +} +#endif + } // namespace implementation } // namespace AUDIO_HAL_VERSION } // namespace audio From 91a73b4a839d792db0e105c61f23786930efb003 Mon Sep 17 00:00:00 2001 From: Kevin Rocard Date: Thu, 1 Mar 2018 18:56:58 -0800 Subject: [PATCH 012/718] Audio V4: Declare support for 4.0 interface Declare that the audio HAL service supports 4.0 as well as 2.0 interface. Formatting done by clang-format. Test: compile Bug: 38184704 Change-Id: Iee842b141e1218f4f3779187339bde40680ec78a Signed-off-by: Kevin Rocard --- .../all-versions/default/service/Android.mk | 3 ++ .../all-versions/default/service/service.cpp | 37 ++++++++----------- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/audio/common/all-versions/default/service/Android.mk b/audio/common/all-versions/default/service/Android.mk index edf1761b7f..f502dfd430 100644 --- a/audio/common/all-versions/default/service/Android.mk +++ b/audio/common/all-versions/default/service/Android.mk @@ -38,8 +38,11 @@ LOCAL_SHARED_LIBRARIES := \ libutils \ libhardware \ android.hardware.audio@2.0 \ + android.hardware.audio@4.0 \ android.hardware.audio.common@2.0 \ + android.hardware.audio.common@4.0 \ android.hardware.audio.effect@2.0 \ + android.hardware.audio.effect@4.0 \ android.hardware.soundtrigger@2.0 \ android.hardware.soundtrigger@2.1 diff --git a/audio/common/all-versions/default/service/service.cpp b/audio/common/all-versions/default/service/service.cpp index d554481291..f6e4353598 100644 --- a/audio/common/all-versions/default/service/service.cpp +++ b/audio/common/all-versions/default/service/service.cpp @@ -17,23 +17,16 @@ #define LOG_TAG "audiohalservice" #include +#include #include +#include #include #include #include #include #include -using android::hardware::configureRpcThreadpool; -using android::hardware::joinRpcThreadpool; -using android::hardware::registerPassthroughServiceImplementation; - -using android::hardware::audio::effect::V2_0::IEffectsFactory; -using android::hardware::audio::V2_0::IDevicesFactory; -using V2_0_ISoundTriggerHw = android::hardware::soundtrigger::V2_0::ISoundTriggerHw; -using V2_1_ISoundTriggerHw = android::hardware::soundtrigger::V2_1::ISoundTriggerHw; -using android::hardware::registerPassthroughServiceImplementation; - +using namespace android::hardware; using android::OK; int main(int /* argc */, char* /* argv */ []) { @@ -41,16 +34,18 @@ int main(int /* argc */, char* /* argv */ []) { // start a threadpool for vndbinder interactions android::ProcessState::self()->startThreadPool(); configureRpcThreadpool(16, true /*callerWillJoin*/); - android::status_t status; - status = registerPassthroughServiceImplementation(); - LOG_ALWAYS_FATAL_IF(status != OK, "Error while registering audio service: %d", status); - status = registerPassthroughServiceImplementation(); - LOG_ALWAYS_FATAL_IF(status != OK, "Error while registering audio effects service: %d", status); - // Soundtrigger might be not present. - status = registerPassthroughServiceImplementation(); - ALOGW_IF(status != OK, "Registering soundtrigger V2.1 service was unsuccessful: %d", status); - status = registerPassthroughServiceImplementation(); - ALOGW_IF(status != OK, "Registering soundtrigger V2.0 service was unsuccessful: %d", status); + + bool fail = registerPassthroughServiceImplementation() != OK && + registerPassthroughServiceImplementation() != OK; + LOG_ALWAYS_FATAL_IF(fail, "Could not register audio core API 2.0 nor 4.0"); + + fail = registerPassthroughServiceImplementation() != OK && + registerPassthroughServiceImplementation() != OK, + LOG_ALWAYS_FATAL_IF(fail, "Could not register audio effect API 2.0 nor 4.0"); + + fail = registerPassthroughServiceImplementation() != OK && + registerPassthroughServiceImplementation() != OK, + ALOGW_IF(fail, "Could not register soundtrigger API 2.0 nor 2.1"); + joinRpcThreadpool(); - return status; } From cfdf3690f8c2005718dcfb61f73e87cf65c0ff9e Mon Sep 17 00:00:00 2001 From: Yu-Han Yang Date: Thu, 1 Mar 2018 16:10:27 -0800 Subject: [PATCH 013/718] Implement Gnss::start() and Gnss::stop() - calling start() creates a thread that periodically receives locations Bug: 73845705 Test: ran VtsHalGnssV1_1TargetTest. SetCallbackResponses and GetLocationLowPower are passing Change-Id: I6a544c2832037a8b507c0ab030a8b766be499669 --- gnss/1.1/default/Gnss.cpp | 107 +++++++++++++++--- gnss/1.1/default/Gnss.h | 18 +++ gnss/1.1/vts/functional/gnss_hal_test.cpp | 2 + .../vts/functional/gnss_hal_test_cases.cpp | 2 + 4 files changed, 113 insertions(+), 16 deletions(-) diff --git a/gnss/1.1/default/Gnss.cpp b/gnss/1.1/default/Gnss.cpp index 308ba70550..98a79ee27f 100644 --- a/gnss/1.1/default/Gnss.cpp +++ b/gnss/1.1/default/Gnss.cpp @@ -1,7 +1,8 @@ #define LOG_TAG "Gnss" -#include "Gnss.h" #include + +#include "Gnss.h" #include "GnssConfiguration.h" #include "GnssMeasurement.h" @@ -11,20 +12,46 @@ namespace gnss { namespace V1_1 { namespace implementation { +const uint32_t MIN_INTERVAL_MILLIS = 100; +sp<::android::hardware::gnss::V1_1::IGnssCallback> Gnss::sGnssCallback = nullptr; + +Gnss::Gnss() : mMinIntervalMs(1000) {} + +Gnss::~Gnss() { + stop(); +} + // Methods from ::android::hardware::gnss::V1_0::IGnss follow. Return Gnss::setCallback(const sp<::android::hardware::gnss::V1_0::IGnssCallback>&) { - // TODO implement - return bool{}; + // Mock handles only new callback (see setCallback1_1) coming from Android P+ + return false; } Return Gnss::start() { - // TODO implement - return bool{}; + if (mIsActive) { + ALOGW("Gnss has started. Restarting..."); + stop(); + } + + mIsActive = true; + mThread = std::thread([this]() { + while (mIsActive == true) { + V1_0::GnssLocation location = this->getMockLocation(); + this->reportLocation(location); + + std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMs)); + } + }); + + return true; } Return Gnss::stop() { - // TODO implement - return bool{}; + mIsActive = false; + if (mThread.joinable()) { + mThread.join(); + } + return true; } Return Gnss::cleanup() { @@ -107,18 +134,43 @@ Return> Gnss::getExtensionGns } // Methods from ::android::hardware::gnss::V1_1::IGnss follow. -Return Gnss::setCallback_1_1(const sp<::android::hardware::gnss::V1_1::IGnssCallback>&) { - ALOGI("Gnss::setCallback_1_1"); - // TODO implement - return bool{}; +Return Gnss::setCallback_1_1( + const sp<::android::hardware::gnss::V1_1::IGnssCallback>& callback) { + if (callback == nullptr) { + ALOGE("%s: Null callback ignored", __func__); + return false; + } + + sGnssCallback = callback; + + uint32_t capabilities = 0x0; + auto ret = sGnssCallback->gnssSetCapabilitesCb(capabilities); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + } + + IGnssCallback::GnssSystemInfo gnssInfo = {.yearOfHw = 2018}; + + ret = sGnssCallback->gnssSetSystemInfoCb(gnssInfo); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + } + + auto gnssName = "Google Mock GNSS Implementation v1.1"; + ret = sGnssCallback->gnssNameCb(gnssName); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + } + + return true; } Return Gnss::setPositionMode_1_1( ::android::hardware::gnss::V1_0::IGnss::GnssPositionMode, - ::android::hardware::gnss::V1_0::IGnss::GnssPositionRecurrence, uint32_t, uint32_t, uint32_t, - bool) { - // TODO implement - return bool{}; + ::android::hardware::gnss::V1_0::IGnss::GnssPositionRecurrence, uint32_t minIntervalMs, + uint32_t, uint32_t, bool) { + mMinIntervalMs = (minIntervalMs < MIN_INTERVAL_MILLIS) ? MIN_INTERVAL_MILLIS : minIntervalMs; + return true; } Return> @@ -138,7 +190,30 @@ Return Gnss::injectBestLocation(const ::android::hardware::gnss::V1_0::Gns return bool{}; } -// Methods from ::android::hidl::base::V1_0::IBase follow. +Return Gnss::getMockLocation() { + V1_0::GnssLocation location = {.gnssLocationFlags = 0xFF, + .latitudeDegrees = 37.4219999, + .longitudeDegrees = -122.0840575, + .altitudeMeters = 1.60062531, + .speedMetersPerSec = 0, + .bearingDegrees = 0, + .horizontalAccuracyMeters = 5, + .verticalAccuracyMeters = 5, + .speedAccuracyMetersPerSecond = 1, + .bearingAccuracyDegrees = 90, + .timestamp = 1519930775453L}; + return location; +} + +Return Gnss::reportLocation(const V1_0::GnssLocation& location) { + std::unique_lock lock(mMutex); + if (sGnssCallback == nullptr) { + ALOGE("%s: sGnssCallback is null.", __func__); + return Void(); + } + sGnssCallback->gnssLocationCb(location); + return Void(); +} } // namespace implementation } // namespace V1_1 diff --git a/gnss/1.1/default/Gnss.h b/gnss/1.1/default/Gnss.h index e9ad34ba95..68c3498b79 100644 --- a/gnss/1.1/default/Gnss.h +++ b/gnss/1.1/default/Gnss.h @@ -4,6 +4,9 @@ #include #include #include +#include +#include +#include namespace android { namespace hardware { @@ -19,7 +22,13 @@ using ::android::hardware::Return; using ::android::hardware::Void; using ::android::sp; +/** + * Unlike the gnss/1.0/default implementation, which is a shim layer to the legacy gps.h, this + * default implementation serves as a mock implementation for emulators + */ struct Gnss : public IGnss { + Gnss(); + ~Gnss(); // Methods from ::android::hardware::gnss::V1_0::IGnss follow. Return setCallback( const sp<::android::hardware::gnss::V1_0::IGnssCallback>& callback) override; @@ -68,6 +77,15 @@ struct Gnss : public IGnss { const ::android::hardware::gnss::V1_0::GnssLocation& location) override; // Methods from ::android::hidl::base::V1_0::IBase follow. + private: + Return getMockLocation(); + Return reportLocation(const V1_0::GnssLocation& location); + + static sp<::android::hardware::gnss::V1_1::IGnssCallback> sGnssCallback; + std::atomic mIsActive; + std::thread mThread; + std::mutex mMutex; + std::atomic mMinIntervalMs; }; } // namespace implementation diff --git a/gnss/1.1/vts/functional/gnss_hal_test.cpp b/gnss/1.1/vts/functional/gnss_hal_test.cpp index 23b73171c0..9c5ac2d7ef 100644 --- a/gnss/1.1/vts/functional/gnss_hal_test.cpp +++ b/gnss/1.1/vts/functional/gnss_hal_test.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#define LOG_TAG "GnssHalTest" + #include #include diff --git a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp index a0a1c7361e..63b6c78f06 100644 --- a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp +++ b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#define LOG_TAG "GnssHalTestCases" + #include #include From 6ffde44e359c188116d4c108370ac68b542b40cf Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Wed, 7 Mar 2018 09:55:06 -0800 Subject: [PATCH 014/718] audio hal default impl: Check for "default" instance name With MSD it's possible to have another instance of IDeviceFactory. For passthrough implementations it's necessary to check whether the instance name is "default" because otherwise HIDL framework will attempt to use the default implementation for MSD. Do the same for effects in case some special effects will be needed for MSD. Bug: 38184704 Bug: 63901775 Change-Id: I18044f3a97e3f6ec4dc3f35b3a9300ea404fc07e Test: audio works, effects work --- .../include/core/all-versions/default/DevicesFactory.impl.h | 4 ++-- .../include/effect/all-versions/default/EffectsFactory.impl.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.impl.h b/audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.impl.h index 43e5d6eaed..a9f59fbfec 100644 --- a/audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.impl.h +++ b/audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.impl.h @@ -106,8 +106,8 @@ out: return rc; } -IDevicesFactory* HIDL_FETCH_IDevicesFactory(const char* /* name */) { - return new DevicesFactory(); +IDevicesFactory* HIDL_FETCH_IDevicesFactory(const char* name) { + return strcmp(name, "default") == 0 ? new DevicesFactory() : nullptr; } } // namespace implementation diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/EffectsFactory.impl.h b/audio/effect/all-versions/default/include/effect/all-versions/default/EffectsFactory.impl.h index b2a36a96f8..066a6a613c 100644 --- a/audio/effect/all-versions/default/include/effect/all-versions/default/EffectsFactory.impl.h +++ b/audio/effect/all-versions/default/include/effect/all-versions/default/EffectsFactory.impl.h @@ -178,8 +178,8 @@ Return EffectsFactory::debugDump(const hidl_handle& fd) { return Void(); } -IEffectsFactory* HIDL_FETCH_IEffectsFactory(const char* /* name */) { - return new EffectsFactory(); +IEffectsFactory* HIDL_FETCH_IEffectsFactory(const char* name) { + return strcmp(name, "default") == 0 ? new EffectsFactory() : nullptr; } } // namespace implementation From 8df876f0d67dd1428ec9ce53dc77c289e768b1a3 Mon Sep 17 00:00:00 2001 From: Daniel Cardenas Date: Fri, 2 Mar 2018 17:10:45 -0800 Subject: [PATCH 015/718] Increase default timeout for changeStateIdletoExecute() from 100ms to 400ms Bug: 70933963 Test: vts-tradefed run vts -m VtsHalMediaOmxV1_0Host Change-Id: I2f01b5fcd72b03148750589a8eabbc8037f61e6f --- .../1.0/vts/functional/common/media_hidl_test_common.cpp | 2 +- .../omx/1.0/vts/functional/common/media_hidl_test_common.h | 2 ++ .../component/VtsHalMediaOmxV1_0TargetComponentTest.cpp | 6 ++---- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp b/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp index 34a96a0ce7..88a9e2612e 100644 --- a/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp +++ b/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp @@ -470,7 +470,7 @@ void changeStateIdletoExecute(sp omxNode, status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet), OMX_StateExecuting); ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); - status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT); + status = observer->dequeueMessage(&msg, RELAXED_TIMEOUT); ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); ASSERT_EQ(msg.type, Message::Type::EVENT); ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete); diff --git a/media/omx/1.0/vts/functional/common/media_hidl_test_common.h b/media/omx/1.0/vts/functional/common/media_hidl_test_common.h index c1863d5469..1575ba252e 100644 --- a/media/omx/1.0/vts/functional/common/media_hidl_test_common.h +++ b/media/omx/1.0/vts/functional/common/media_hidl_test_common.h @@ -41,6 +41,8 @@ /* As component is switching states (loaded<->idle<->execute), dequeueMessage() * expects the events to be received within this duration */ #define DEFAULT_TIMEOUT 100000 +// b/70933963 +#define RELAXED_TIMEOUT 400000 /* Time interval between successive Input/Output enqueues */ #define DEFAULT_TIMEOUT_Q 2000 /* While the component is amidst a process call, asynchronous commands like diff --git a/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp b/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp index f7c843363c..c37f7aef40 100644 --- a/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp +++ b/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp @@ -1144,15 +1144,13 @@ TEST_F(ComponentHidlTest, PortEnableDisable_Execute) { ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); // do not enable the port until all the buffers are supplied - status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, - &pBuffer[0], &pBuffer[1]); + status = observer->dequeueMessage(&msg, RELAXED_TIMEOUT, &pBuffer[0], &pBuffer[1]); ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT); ASSERT_NO_FATAL_FAILURE(allocatePortBuffers( omxNode, &pBuffer[i - portBase], i, portMode[i - portBase])); - status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, - &pBuffer[0], &pBuffer[1]); + status = observer->dequeueMessage(&msg, RELAXED_TIMEOUT, &pBuffer[0], &pBuffer[1]); ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); ASSERT_EQ(msg.type, Message::Type::EVENT); ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortEnable); From 4e95d81ef048bfdc33cee7cf8bdbe66603b30f96 Mon Sep 17 00:00:00 2001 From: Sunny Kapdi Date: Wed, 7 Feb 2018 15:08:01 -0800 Subject: [PATCH 016/718] Bluetooth: A2DP offload HIDL Interface for Bluetooth A2DP offload feature. Bug: 72242910 Test: Manual; TestTracker/148125 Change-Id: I3649800dfe3e1a2d66b76859be87e01ee58d2de0 --- bluetooth/a2dp/1.0/Android.bp | 27 +++++ bluetooth/a2dp/1.0/IBluetoothAudioHost.hal | 61 ++++++++++++ bluetooth/a2dp/1.0/IBluetoothAudioOffload.hal | 85 ++++++++++++++++ bluetooth/a2dp/1.0/default/Android.bp | 14 +++ .../1.0/default/BluetoothAudioOffload.cpp | 74 ++++++++++++++ .../a2dp/1.0/default/BluetoothAudioOffload.h | 60 +++++++++++ bluetooth/a2dp/1.0/types.hal | 99 +++++++++++++++++++ 7 files changed, 420 insertions(+) create mode 100644 bluetooth/a2dp/1.0/Android.bp create mode 100644 bluetooth/a2dp/1.0/IBluetoothAudioHost.hal create mode 100644 bluetooth/a2dp/1.0/IBluetoothAudioOffload.hal create mode 100644 bluetooth/a2dp/1.0/default/Android.bp create mode 100644 bluetooth/a2dp/1.0/default/BluetoothAudioOffload.cpp create mode 100644 bluetooth/a2dp/1.0/default/BluetoothAudioOffload.h create mode 100644 bluetooth/a2dp/1.0/types.hal diff --git a/bluetooth/a2dp/1.0/Android.bp b/bluetooth/a2dp/1.0/Android.bp new file mode 100644 index 0000000000..5e852901ae --- /dev/null +++ b/bluetooth/a2dp/1.0/Android.bp @@ -0,0 +1,27 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +hidl_interface { + name: "android.hardware.bluetooth.a2dp@1.0", + root: "android.hardware", + vndk: { + enabled: true, + }, + srcs: [ + "types.hal", + "IBluetoothAudioHost.hal", + "IBluetoothAudioOffload.hal", + ], + interfaces: [ + "android.hidl.base@1.0", + ], + types: [ + "BitsPerSample", + "ChannelMode", + "CodecConfiguration", + "CodecType", + "SampleRate", + "Status", + ], + gen_java: false, +} + diff --git a/bluetooth/a2dp/1.0/IBluetoothAudioHost.hal b/bluetooth/a2dp/1.0/IBluetoothAudioHost.hal new file mode 100644 index 0000000000..666419dbd5 --- /dev/null +++ b/bluetooth/a2dp/1.0/IBluetoothAudioHost.hal @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.bluetooth.a2dp@1.0; + +/** + * HAL interface for Bluetooth A2DP Offload functionality where + * the encoding of the A2DP data packets is offloaded to platform + * specific encoders. The A2DP control path is maintained in the + * Bluetooth stack. + * + * This interface is from HAL server to HAL client. + * + * The HAL server must call into the IBluetoothAudioHost to initiate + * the start, suspend and stop of the streaming operation. These + * calls return immediately and the results, if any, are send over + * the IBluetoothAudioOffload interface. + */ + +interface IBluetoothAudioHost { + /** + * Invoked when the start stream is requested from HAL server + * to HAL client. This indicates that the HAL server + * has initialized the platform for streaming use case, and the + * HAL client can proceed with the streaming procedure. The + * result of the operation must be provided by the HAL + * client using the IBluetoothAudioOffload interface. + */ + oneway startStream(); + + /** + * Invoked when the suspend stream is requested from HAL server + * to HAL client. This indicates that the HAL server + * wants to suspend the streaming procedure. The result of the + * operation must be provided by the HAL client using the + * IBluetoothAudioOffload interface. + */ + oneway suspendStream(); + + /** + * Invoked when the stop stream is requested from HAL server + * to HAL client. This indicates that the HAL server wants to + * stop and reset the streaming procedure. There is no result + * provided by the HAL client for this call. + */ + oneway stopStream(); + +}; diff --git a/bluetooth/a2dp/1.0/IBluetoothAudioOffload.hal b/bluetooth/a2dp/1.0/IBluetoothAudioOffload.hal new file mode 100644 index 0000000000..52a580f848 --- /dev/null +++ b/bluetooth/a2dp/1.0/IBluetoothAudioOffload.hal @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.bluetooth.a2dp@1.0; + +import IBluetoothAudioHost; + +/** + * HAL interface for Bluetooth A2DP Offload functionality where + * the encoding of the A2DP data packets is offloaded to platform + * specific encoders. The A2DP control path is maintained in the + * Bluetooth stack. + * + * This interface is from HAL client to HAL server. + * + * The HAL client must provide the handle of IBluetoothAudioHost as well + * as codec configuration to the HAL server, when its connected to an + * active A2DP Sink device. HAL Server, based on the feedback from the Audio + * framework must call into the commands provided by the IBluetoothAudioHost. + * HAL client must call into IBluetoothAudioOffload to provide the status of + * these commands. Once the device becomes inactive, the HAL client must + * call the endSession to terminate the session with the HAL server. + */ +interface IBluetoothAudioOffload { + + /** + * Indicates that the HAL client is connected to an A2DP Sink device + * and is ready to stream audio. This function is also used to register + * the BluetoothAudioHost interface and the provide the current negotiated + * codec. + * + * |endSession| must be called to unregister the interface. + * + * @param hostIf interface used to request stream control + * @param codecConfig Codec configuration as negotiated with the A2DP Sink + * device + * @return status one of the following + * SUCCESS if HAL server successfully initializes the platform with the + * given codec configuration + * UNSUPPORTED_CODEC_CONFIGURATION if HAL server cannot initialize the + * platform with the given codec configuration + * FAILURE if HAL server cannot initialize the platform for any other + * reason + */ + startSession(IBluetoothAudioHost hostIf, CodecConfiguration codecConfig) generates (Status status); + + /** + * Updates status for start stream request. The HAL client may need + * to communicate to Bluetooth Controller and remote Sink device, in which + * case it must update with PENDING status. Once the operation is + * completed, it must return with either SUCCESS or FAILURE. + * + * @param status SUCCESS, FAILURE or PENDING + */ + oneway streamStarted(Status status); + + /** + * Updates status for suspend stream request. The HAL client may need + * to communicate to Bluetooth Controller and remote device, in which case + * it must update with PENDING status. Once the operation is completed, it + * must return with either SUCCESS or FAILURE. + * + * @param status SUCCESS, FAILURE or PENDING + */ + oneway streamSuspended(Status status); + + /** + * Ends the current A2DP offload session and unregisters the + * BluetoothAudioHost interface. + */ + oneway endSession(); +}; diff --git a/bluetooth/a2dp/1.0/default/Android.bp b/bluetooth/a2dp/1.0/default/Android.bp new file mode 100644 index 0000000000..8e6f32db49 --- /dev/null +++ b/bluetooth/a2dp/1.0/default/Android.bp @@ -0,0 +1,14 @@ +cc_library_shared { + name: "android.hardware.bluetooth.a2dp@1.0-impl", + relative_install_path: "hw", + vendor: true, + srcs: [ + "BluetoothAudioOffload.cpp", + ], + shared_libs: [ + "libhidlbase", + "libhidltransport", + "libutils", + "android.hardware.bluetooth.a2dp@1.0", + ], +} diff --git a/bluetooth/a2dp/1.0/default/BluetoothAudioOffload.cpp b/bluetooth/a2dp/1.0/default/BluetoothAudioOffload.cpp new file mode 100644 index 0000000000..2a66abe685 --- /dev/null +++ b/bluetooth/a2dp/1.0/default/BluetoothAudioOffload.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "BluetoothAudioOffload.h" + +namespace android { +namespace hardware { +namespace bluetooth { +namespace a2dp { +namespace V1_0 { +namespace implementation { + +IBluetoothAudioOffload* HIDL_FETCH_IBluetoothAudioOffload(const char* /* name */) { + return new BluetoothAudioOffload(); +} + +// Methods from ::android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioOffload follow. +Return<::android::hardware::bluetooth::a2dp::V1_0::Status> BluetoothAudioOffload::startSession( + const sp<::android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioHost>& hostIf __unused, + const ::android::hardware::bluetooth::a2dp::V1_0::CodecConfiguration& codecConfig __unused) { + /** + * Initialize the audio platform if codecConfiguration is supported. + * Save the the IBluetoothAudioHost interface, so that it can be used + * later to send stream control commands to the HAL client, based on + * interaction with Audio framework. + */ + return ::android::hardware::bluetooth::a2dp::V1_0::Status::FAILURE; +} + +Return BluetoothAudioOffload::streamStarted( + ::android::hardware::bluetooth::a2dp::V1_0::Status status __unused) { + /** + * Streaming on control path has started, + * HAL server should start the streaming on data path. + */ + return Void(); +} + +Return BluetoothAudioOffload::streamSuspended( + ::android::hardware::bluetooth::a2dp::V1_0::Status status __unused) { + /** + * Streaming on control path has suspend, + * HAL server should suspend the streaming on data path. + */ + return Void(); +} + +Return BluetoothAudioOffload::endSession() { + /** + * Cleanup the audio platform as remote A2DP Sink device is no + * longer active + */ + return Void(); +} + +} // namespace implementation +} // namespace V1_0 +} // namespace a2dp +} // namespace bluetooth +} // namespace hardware +} // namespace android diff --git a/bluetooth/a2dp/1.0/default/BluetoothAudioOffload.h b/bluetooth/a2dp/1.0/default/BluetoothAudioOffload.h new file mode 100644 index 0000000000..5d07b5bca3 --- /dev/null +++ b/bluetooth/a2dp/1.0/default/BluetoothAudioOffload.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_BLUETOOTH_A2DP_V1_0_BLUETOOTHAUDIOOFFLOAD_H +#define ANDROID_HARDWARE_BLUETOOTH_A2DP_V1_0_BLUETOOTHAUDIOOFFLOAD_H + +#include +#include +#include + +namespace android { +namespace hardware { +namespace bluetooth { +namespace a2dp { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::hidl_array; +using ::android::hardware::hidl_memory; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::sp; + +struct BluetoothAudioOffload : public IBluetoothAudioOffload { + BluetoothAudioOffload() {} + // Methods from ::android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioOffload follow. + Return<::android::hardware::bluetooth::a2dp::V1_0::Status> startSession( + const sp<::android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioHost>& hostIf, + const ::android::hardware::bluetooth::a2dp::V1_0::CodecConfiguration& codecConfig) override; + Return streamStarted(::android::hardware::bluetooth::a2dp::V1_0::Status status) override; + Return streamSuspended( + ::android::hardware::bluetooth::a2dp::V1_0::Status status) override; + Return endSession() override; +}; + +extern "C" IBluetoothAudioOffload* HIDL_FETCH_IBluetoothAudioOffload(const char* name); + +} // namespace implementation +} // namespace V1_0 +} // namespace a2dp +} // namespace bluetooth +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_BLUETOOTH_A2DP_V1_0_BLUETOOTHAUDIOOFFLOAD_H diff --git a/bluetooth/a2dp/1.0/types.hal b/bluetooth/a2dp/1.0/types.hal new file mode 100644 index 0000000000..6a430f05af --- /dev/null +++ b/bluetooth/a2dp/1.0/types.hal @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.bluetooth.a2dp@1.0; + +enum Status : uint8_t { + SUCCESS, + FAILURE, + /** codec configuration not supported by the audio platform */ + UNSUPPORTED_CODEC_CONFIGURATION , + /** operation is pending */ + PENDING, +}; + +enum CodecType : uint32_t { + UNKNOWN = 0x00, + SBC = 0x01, + AAC = 0x02, + APTX = 0x04, + APTX_HD = 0x08, + LDAC = 0x10, +}; +enum SampleRate : uint32_t { + RATE_UNKNOWN = 0x00, + RATE_44100 = 0x01, + RATE_48000 = 0x02, + RATE_88200 = 0x04, + RATE_96000 = 0x08, + RATE_176400 = 0x10, + RATE_192000 = 0x20, +}; +enum BitsPerSample : uint8_t { + BITS_UNKNOWN = 0x00, + BITS_16 = 0x01, + BITS_24 = 0x02, + BITS_32 = 0x04, +}; +enum ChannelMode : uint8_t { + UNKNOWN = 0x00, + MONO = 0x01, + STEREO = 0x02, +}; +struct CodecConfiguration { + /** Bluetooth A2DP codec */ + CodecType codecType; + /** Sampling rate for encoder */ + SampleRate sampleRate; + /** Bits per sample for encoder */ + BitsPerSample bitsPerSample; + /** Channel mode for encoder */ + ChannelMode channelMode; + /** + * The encoded audio bitrate in bits / second. + * 0x00000000 - The audio bitrate is not specified / unused + * 0x00000001 - 0x00FFFFFF - Encoded audio bitrate in bits/second + * 0x01000000 - 0xFFFFFFFF - Reserved + */ + uint32_t encodedAudioBitrate; + /** Peer MTU (in octets) */ + uint16_t peerMtu; + union CodecSpecific { + /** + * SBC Codec specific information + * Refer to SBC Codec specific information elements in A2DP v1.3 + * Profile Specification. + */ + struct SbcData { + /** Block length: 4 bits | Subbands: 2 bits | Allocation Method: 2 bits */ + uint8_t codecParameters; + /** Minimum bitpool value */ + uint8_t minBitpool; + /** Maximum bitpool value */ + uint8_t maxBitpool; + } sbcData; + struct LdacData { + /** + * LDAC bitrate index value: + * 0x00 - High + * 0x01 - Mid + * 0x02 - Low + * 0x7F - ABR (Adaptive Bit Rate) + */ + uint8_t bitrateIndex; + } ldacData; + } codecSpecific; +}; From c5a5203114b7696f5287c0ebada84b35df1be0f7 Mon Sep 17 00:00:00 2001 From: Aniket Kumar Lata Date: Wed, 31 Jan 2018 20:17:30 -0800 Subject: [PATCH 017/718] audio: Register Bluetooth service with audio HAL Register Bluetooth audio library with audio HIDL service. Changes required for A2DP offload implementation. Bug: 68824150 Test: A2DP offload verified on supported codecs Change-Id: Idd89f0d28903579d42bd0f33b0194fb8dc2ceaaa --- audio/common/all-versions/default/service/Android.mk | 1 + audio/common/all-versions/default/service/service.cpp | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/audio/common/all-versions/default/service/Android.mk b/audio/common/all-versions/default/service/Android.mk index f502dfd430..43d7fe19c5 100644 --- a/audio/common/all-versions/default/service/Android.mk +++ b/audio/common/all-versions/default/service/Android.mk @@ -43,6 +43,7 @@ LOCAL_SHARED_LIBRARIES := \ android.hardware.audio.common@4.0 \ android.hardware.audio.effect@2.0 \ android.hardware.audio.effect@4.0 \ + android.hardware.bluetooth.a2dp@1.0 \ android.hardware.soundtrigger@2.0 \ android.hardware.soundtrigger@2.1 diff --git a/audio/common/all-versions/default/service/service.cpp b/audio/common/all-versions/default/service/service.cpp index f6e4353598..c7ce638e7f 100644 --- a/audio/common/all-versions/default/service/service.cpp +++ b/audio/common/all-versions/default/service/service.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -47,5 +48,10 @@ int main(int /* argc */, char* /* argv */ []) { registerPassthroughServiceImplementation() != OK, ALOGW_IF(fail, "Could not register soundtrigger API 2.0 nor 2.1"); + fail = + registerPassthroughServiceImplementation() != + OK; + ALOGW_IF(fail, "Could not register Bluetooth audio offload 1.0"); + joinRpcThreadpool(); } From efbb9c3f59777dace6491ddaa2e67218eba92ec2 Mon Sep 17 00:00:00 2001 From: Bernie Innocenti Date: Wed, 7 Mar 2018 00:17:50 +0900 Subject: [PATCH 018/718] Wire readApfPacketFilterData() to the legacy hal Change-Id: If5d9d3afd40758aea98832e4b350216f496fc3bd Test: built and flashed, verified boot --- .../default/tests/wifi_chip_unit_tests.cpp | 2 +- wifi/1.2/default/wifi_legacy_hal.cpp | 22 +++++++++++++++++++ wifi/1.2/default/wifi_legacy_hal.h | 4 +++- wifi/1.2/default/wifi_sta_iface.cpp | 16 ++++++++++++++ wifi/1.2/default/wifi_sta_iface.h | 8 +++++-- 5 files changed, 48 insertions(+), 4 deletions(-) diff --git a/wifi/1.2/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.2/default/tests/wifi_chip_unit_tests.cpp index 27c8d60b97..3928c9ab0a 100644 --- a/wifi/1.2/default/tests/wifi_chip_unit_tests.cpp +++ b/wifi/1.2/default/tests/wifi_chip_unit_tests.cpp @@ -146,7 +146,7 @@ class WifiChipTest : public Test { } else if (type == IfaceType::STA) { chip_->createStaIface( [&iface_name](const WifiStatus& status, - const sp& iface) { + const sp& iface) { if (WifiStatusCode::SUCCESS == status.code) { ASSERT_NE(iface.get(), nullptr); iface->getName([&iface_name](const WifiStatus& status, diff --git a/wifi/1.2/default/wifi_legacy_hal.cpp b/wifi/1.2/default/wifi_legacy_hal.cpp index 84af9c4808..c314e6451a 100644 --- a/wifi/1.2/default/wifi_legacy_hal.cpp +++ b/wifi/1.2/default/wifi_legacy_hal.cpp @@ -492,6 +492,28 @@ wifi_error WifiLegacyHal::setPacketFilter(const std::string& iface_name, getIfaceHandle(iface_name), program.data(), program.size()); } +std::pair> +WifiLegacyHal::readApfPacketFilterData(const std::string& iface_name) { + if (global_func_table_.wifi_read_packet_filter == nullptr) { + return {WIFI_ERROR_NOT_SUPPORTED, {}}; + } + + PacketFilterCapabilities caps; + wifi_error status = global_func_table_.wifi_get_packet_filter_capabilities( + getIfaceHandle(iface_name), &caps.version, &caps.max_len); + if (status != WIFI_SUCCESS) { + return {status, {}}; + } + + // Size the buffer to read the entire program & work memory. + std::vector buffer(caps.max_len); + + status = global_func_table_.wifi_read_packet_filter( + getIfaceHandle(iface_name), /*src_offset=*/0, buffer.data(), + buffer.size()); + return {status, move(buffer)}; +} + std::pair WifiLegacyHal::getGscanCapabilities(const std::string& iface_name) { wifi_gscan_capabilities caps; diff --git a/wifi/1.2/default/wifi_legacy_hal.h b/wifi/1.2/default/wifi_legacy_hal.h index dedbbf8279..60905ab399 100644 --- a/wifi/1.2/default/wifi_legacy_hal.h +++ b/wifi/1.2/default/wifi_legacy_hal.h @@ -156,7 +156,7 @@ using on_radio_mode_change_callback = * Class that encapsulates all legacy HAL interactions. * This class manages the lifetime of the event loop thread used by legacy HAL. * - * Note: aThere will only be a single instance of this class created in the Wifi + * Note: There will only be a single instance of this class created in the Wifi * object and will be valid for the lifetime of the process. */ class WifiLegacyHal { @@ -188,6 +188,8 @@ class WifiLegacyHal { const std::string& iface_name); wifi_error setPacketFilter(const std::string& iface_name, const std::vector& program); + std::pair> readApfPacketFilterData( + const std::string& iface_name); // Gscan functions. std::pair getGscanCapabilities( const std::string& iface_name); diff --git a/wifi/1.2/default/wifi_sta_iface.cpp b/wifi/1.2/default/wifi_sta_iface.cpp index 6faf009379..ab99daa24a 100644 --- a/wifi/1.2/default/wifi_sta_iface.cpp +++ b/wifi/1.2/default/wifi_sta_iface.cpp @@ -94,6 +94,13 @@ Return WifiStaIface::installApfPacketFilter( hidl_status_cb, cmd_id, program); } +Return WifiStaIface::readApfPacketFilterData( + readApfPacketFilterData_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::readApfPacketFilterDataInternal, + hidl_status_cb); +} + Return WifiStaIface::getBackgroundScanCapabilities( getBackgroundScanCapabilities_cb hidl_status_cb) { return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, @@ -297,6 +304,15 @@ WifiStatus WifiStaIface::installApfPacketFilterInternal( return createWifiStatusFromLegacyError(legacy_status); } +std::pair> +WifiStaIface::readApfPacketFilterDataInternal() { + const std::pair> + legacy_status_and_data = + legacy_hal_.lock()->readApfPacketFilterData(ifname_); + return {createWifiStatusFromLegacyError(legacy_status_and_data.first), + std::move(legacy_status_and_data.second)}; +} + std::pair WifiStaIface::getBackgroundScanCapabilitiesInternal() { legacy_hal::wifi_error legacy_status; diff --git a/wifi/1.2/default/wifi_sta_iface.h b/wifi/1.2/default/wifi_sta_iface.h index 423365cfbd..a2128882f5 100644 --- a/wifi/1.2/default/wifi_sta_iface.h +++ b/wifi/1.2/default/wifi_sta_iface.h @@ -18,8 +18,8 @@ #define WIFI_STA_IFACE_H_ #include -#include #include +#include #include "hidl_callback_util.h" #include "wifi_legacy_hal.h" @@ -34,7 +34,7 @@ using namespace android::hardware::wifi::V1_0; /** * HIDL interface object used to control a STA Iface instance. */ -class WifiStaIface : public V1_0::IWifiStaIface { +class WifiStaIface : public V1_2::IWifiStaIface { public: WifiStaIface(const std::string& ifname, const std::weak_ptr legacy_hal); @@ -56,6 +56,8 @@ class WifiStaIface : public V1_0::IWifiStaIface { Return installApfPacketFilter( uint32_t cmd_id, const hidl_vec& program, installApfPacketFilter_cb hidl_status_cb) override; + Return readApfPacketFilterData( + readApfPacketFilterData_cb hidl_status_cb) override; Return getBackgroundScanCapabilities( getBackgroundScanCapabilities_cb hidl_status_cb) override; Return getValidFrequenciesForBand( @@ -113,6 +115,8 @@ class WifiStaIface : public V1_0::IWifiStaIface { getApfPacketFilterCapabilitiesInternal(); WifiStatus installApfPacketFilterInternal( uint32_t cmd_id, const std::vector& program); + std::pair> + readApfPacketFilterDataInternal(); std::pair getBackgroundScanCapabilitiesInternal(); std::pair> From 1840be6d356c54c47b1c2e6d0e3275d9fa659eea Mon Sep 17 00:00:00 2001 From: Brian Young Date: Fri, 23 Feb 2018 18:03:43 +0000 Subject: [PATCH 019/718] Add "Unlocked device required" key API Add a keymaster parameter for keys that should be inaccessible when the device screen is locked. "Locked" here is a state where the device can be used or accessed without any further trust factor such as a PIN, password, fingerprint, or trusted face or voice. This parameter is added to the Java keystore interface for key creation and import, as well as enums specified by and for the native keystore process. Test: CTS tests in I8a5affd1eaed176756175158e3057e44934fffed Bug: 67752510 Change-Id: Id19d19b19532ac8d4c52aad46a954faa4515289d --- current.txt | 2 +- .../functional/keymaster_hidl_hal_test.cpp | 22 +++++++++++++++ .../include/keymasterV4_0/keymaster_tags.h | 28 +++++++++++-------- keymaster/4.0/types.hal | 7 ++++- 4 files changed, 46 insertions(+), 13 deletions(-) diff --git a/current.txt b/current.txt index e351d224aa..1782492c39 100644 --- a/current.txt +++ b/current.txt @@ -328,7 +328,7 @@ dd83be076b6b3f10ed62ab34d8c8b95f2415961fb785200eb842e7bfb2b0ee92 android.hardwar 434c4c32c00b0e54bb05e40c79503208b40f786a318029a2a4f66e34f10f2a76 android.hardware.health@2.0::IHealthInfoCallback c9e498f1ade5e26f00d290b4763a9671ec6720f915e7d592844b62e8cb1f9b5c android.hardware.health@2.0::types a6cf986593c6ad15fe2ae3a1995d2cae233500bc32c055912a42723bdc076868 android.hardware.keymaster@4.0::IKeymasterDevice -3ce01f7a38013f15d2ffc9c66a81eb85061ab6585fb1e659fe6da36bdcbfa9cf android.hardware.keymaster@4.0::types +e15ebdf1e0a326ff5b8a59668d4d8cd3852bd88388eae91de13f5f7e1af50ed1 android.hardware.keymaster@4.0::types 6d5c646a83538f0f9d8438c259932509f4353410c6c76e56db0d6ca98b69c3bb android.hardware.media.bufferpool@1.0::IAccessor b8c7ed58aa8740361e63d0ce9e7c94227572a629f356958840b34809d2393a7c android.hardware.media.bufferpool@1.0::IClientManager 4a2c0dc82780e6c90731725a103feab8ab6ecf85a64e049b9cbd2b2c61620fe1 android.hardware.media.bufferpool@1.0::IConnection diff --git a/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp index 3a181a96b7..fbe5237ade 100644 --- a/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp +++ b/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp @@ -2917,6 +2917,28 @@ TEST_F(EncryptionOperationsTest, AesEcbRoundTripSuccess) { EXPECT_EQ(message, plaintext); } +/* + * EncryptionOperationsTest.AesEcbWithUserId + * + * Verifies that AES ECB mode works when Tag::USER_ID is specified. + */ +TEST_F(EncryptionOperationsTest, AesEcbWithUserId) { + string key = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder() + .Authorization(TAG_NO_AUTH_REQUIRED) + .Authorization(TAG_USER_ID, 0) + .AesEncryptionKey(key.size() * 8) + .EcbMode() + .Padding(PaddingMode::PKCS7), + KeyFormat::RAW, key)); + + string message = "Hello World!"; + auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7); + string ciphertext = EncryptMessage(message, params); + string plaintext = DecryptMessage(ciphertext, params); + EXPECT_EQ(message, plaintext); +} + /* * EncryptionOperationsTest.AesEcbRoundTripSuccess * diff --git a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h index 9d6501b862..ce213bc127 100644 --- a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h +++ b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h @@ -142,24 +142,28 @@ DECLARE_TYPED_TAG(ROOT_OF_TRUST); DECLARE_TYPED_TAG(RSA_PUBLIC_EXPONENT); DECLARE_TYPED_TAG(TRUSTED_CONFIRMATION_REQUIRED); DECLARE_TYPED_TAG(UNIQUE_ID); +DECLARE_TYPED_TAG(UNLOCKED_DEVICE_REQUIRED); DECLARE_TYPED_TAG(USAGE_EXPIRE_DATETIME); DECLARE_TYPED_TAG(USER_AUTH_TYPE); +DECLARE_TYPED_TAG(USER_ID); DECLARE_TYPED_TAG(USER_SECURE_ID); template struct MetaList {}; -using all_tags_t = MetaList< - TAG_INVALID_t, TAG_KEY_SIZE_t, TAG_MAC_LENGTH_t, TAG_CALLER_NONCE_t, TAG_MIN_MAC_LENGTH_t, - TAG_RSA_PUBLIC_EXPONENT_t, TAG_INCLUDE_UNIQUE_ID_t, TAG_ACTIVE_DATETIME_t, - TAG_ORIGINATION_EXPIRE_DATETIME_t, TAG_USAGE_EXPIRE_DATETIME_t, TAG_MIN_SECONDS_BETWEEN_OPS_t, - TAG_MAX_USES_PER_BOOT_t, TAG_USER_SECURE_ID_t, TAG_NO_AUTH_REQUIRED_t, TAG_AUTH_TIMEOUT_t, - TAG_ALLOW_WHILE_ON_BODY_t, TAG_APPLICATION_ID_t, TAG_APPLICATION_DATA_t, - TAG_CREATION_DATETIME_t, TAG_ROLLBACK_RESISTANCE_t, TAG_ROOT_OF_TRUST_t, TAG_ASSOCIATED_DATA_t, - TAG_NONCE_t, TAG_BOOTLOADER_ONLY_t, TAG_OS_VERSION_t, TAG_OS_PATCHLEVEL_t, TAG_UNIQUE_ID_t, - TAG_ATTESTATION_CHALLENGE_t, TAG_ATTESTATION_APPLICATION_ID_t, TAG_RESET_SINCE_ID_ROTATION_t, - TAG_PURPOSE_t, TAG_ALGORITHM_t, TAG_BLOCK_MODE_t, TAG_DIGEST_t, TAG_PADDING_t, - TAG_BLOB_USAGE_REQUIREMENTS_t, TAG_ORIGIN_t, TAG_USER_AUTH_TYPE_t, TAG_EC_CURVE_t>; +using all_tags_t = + MetaList; template struct TypedTag2ValueType; @@ -343,6 +347,7 @@ inline bool operator==(const KeyParameter& a, const KeyParameter& b) { case Tag::BOOTLOADER_ONLY: case Tag::NO_AUTH_REQUIRED: case Tag::ALLOW_WHILE_ON_BODY: + case Tag::UNLOCKED_DEVICE_REQUIRED: case Tag::ROLLBACK_RESISTANCE: case Tag::RESET_SINCE_ID_ROTATION: case Tag::TRUSTED_CONFIRMATION_REQUIRED: @@ -357,6 +362,7 @@ inline bool operator==(const KeyParameter& a, const KeyParameter& b) { case Tag::OS_VERSION: case Tag::OS_PATCHLEVEL: case Tag::MAC_LENGTH: + case Tag::USER_ID: case Tag::AUTH_TIMEOUT: case Tag::VENDOR_PATCHLEVEL: case Tag::BOOT_PATCHLEVEL: diff --git a/keymaster/4.0/types.hal b/keymaster/4.0/types.hal index 91ec9bf576..47fd1ed00e 100644 --- a/keymaster/4.0/types.hal +++ b/keymaster/4.0/types.hal @@ -118,7 +118,8 @@ enum Tag : uint32_t { * boot. */ /* User authentication */ - // 500-501 reserved + // 500 reserved + USER_ID = TagType:UINT | 501, /* Android ID of authorized user or authenticator(s), */ USER_SECURE_ID = TagType:ULONG_REP | 502, /* Secure ID of authorized user or authenticator(s). * Disallowed if NO_AUTH_REQUIRED is present. */ NO_AUTH_REQUIRED = TagType:BOOL | 503, /* If key is usable without authentication. */ @@ -191,6 +192,9 @@ enum Tag : uint32_t { * match the data described in the token, keymaster must return NO_USER_CONFIRMATION. */ TRUSTED_CONFIRMATION_REQUIRED = TagType:BOOL | 508, + UNLOCKED_DEVICE_REQUIRED = TagType:BOOL | 509, /* Require the device screen to be unlocked if + * the key is used. */ + /* Application access control */ APPLICATION_ID = TagType:BYTES | 601, /* Byte string identifying the authorized application. */ @@ -471,6 +475,7 @@ enum ErrorCode : int32_t { PROOF_OF_PRESENCE_REQUIRED = -69, CONCURRENT_PROOF_OF_PRESENCE_REQUESTED = -70, NO_USER_CONFIRMATION = -71, + DEVICE_LOCKED = -72, UNIMPLEMENTED = -100, VERSION_MISMATCH = -101, From d98dcfb331c8e81a4aff2d61252f8bb1965e4920 Mon Sep 17 00:00:00 2001 From: "Brian C. Young" Date: Tue, 27 Mar 2018 17:31:29 -0700 Subject: [PATCH 020/718] Filter USER_ID tag from the hardware keystore An as-yet-undiscovered mismatch between authorization sets that do or don't have the USER_ID tag applied are causing failures for PIN setting on the secondary account. This changes makes sure those tags are not sent to the underlying keystore to fix the PIN failure, while we diagnose the underlying cause. Bug: 76460912 Test: Switch to guest account, set PIN, lock and unlock. Change-Id: I880899af5095a95ae41b7a64c5a76329f0f78f4a --- keymaster/4.0/support/Keymaster3.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/keymaster/4.0/support/Keymaster3.cpp b/keymaster/4.0/support/Keymaster3.cpp index b2cdbd9263..84b3ee1f60 100644 --- a/keymaster/4.0/support/Keymaster3.cpp +++ b/keymaster/4.0/support/Keymaster3.cpp @@ -61,9 +61,12 @@ KeyParameter convert(const V3_0::KeyParameter& param) { } hidl_vec convert(const hidl_vec& params) { - hidl_vec converted(params.size()); - for (size_t i = 0; i < params.size(); ++i) { - converted[i] = convert(params[i]); + std::vector converted; + converted.reserve(params.size()); + for (const auto& param : params) { + // Qualcomm's Keymaster3 implementation behaves oddly if Tag::USER_ID is provided. Filter it + // out. Revert this change when b/73286437 is fixed. + if (param.tag != Tag::USER_ID) converted.push_back(convert(param)); } return converted; } From 1ae66d80848cbaa6cb2bf9459f49d073e499022f Mon Sep 17 00:00:00 2001 From: Brian Young Date: Thu, 29 Mar 2018 16:36:22 +0000 Subject: [PATCH 021/718] Revert "Filter USER_ID tag from the hardware keystore" This reverts commit d98dcfb331c8e81a4aff2d61252f8bb1965e4920. Reason for revert: Found a better fix on the Java side. Change-Id: If4244df5c292eb79baf612fd52f75fbfd20c6f6c --- keymaster/4.0/support/Keymaster3.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/keymaster/4.0/support/Keymaster3.cpp b/keymaster/4.0/support/Keymaster3.cpp index 84b3ee1f60..b2cdbd9263 100644 --- a/keymaster/4.0/support/Keymaster3.cpp +++ b/keymaster/4.0/support/Keymaster3.cpp @@ -61,12 +61,9 @@ KeyParameter convert(const V3_0::KeyParameter& param) { } hidl_vec convert(const hidl_vec& params) { - std::vector converted; - converted.reserve(params.size()); - for (const auto& param : params) { - // Qualcomm's Keymaster3 implementation behaves oddly if Tag::USER_ID is provided. Filter it - // out. Revert this change when b/73286437 is fixed. - if (param.tag != Tag::USER_ID) converted.push_back(convert(param)); + hidl_vec converted(params.size()); + for (size_t i = 0; i < params.size(); ++i) { + converted[i] = convert(params[i]); } return converted; } From 0c41558bdf72307e15657f3aba6c963cd8123d18 Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Mon, 2 Apr 2018 15:35:00 -0700 Subject: [PATCH 022/718] graphics: Clean up VTS boilerplate for composer This CL makes the V2_1::vts::Composer class more reusable, and cleans up the 2.2 boilerplate. Bug: 74619554 Test: VtsHalGraphicsComposerV2_2TargetTest Change-Id: Iff2905d40afe16a0b9ce735f1285d5bdc6b4cec7 --- .../composer/2.1/utils/vts/ComposerVts.cpp | 22 ++-- .../include/composer-vts/2.1/ComposerVts.h | 8 +- .../composer/2.2/utils/vts/ComposerVts.cpp | 111 +++++++++--------- .../include/composer-vts/2.2/ComposerVts.h | 37 +++--- .../VtsHalGraphicsComposerV2_2TargetTest.cpp | 34 +++--- 5 files changed, 99 insertions(+), 113 deletions(-) diff --git a/graphics/composer/2.1/utils/vts/ComposerVts.cpp b/graphics/composer/2.1/utils/vts/ComposerVts.cpp index 2f531b419f..43a5378bfb 100644 --- a/graphics/composer/2.1/utils/vts/ComposerVts.cpp +++ b/graphics/composer/2.1/utils/vts/ComposerVts.cpp @@ -25,21 +25,19 @@ namespace composer { namespace V2_1 { namespace vts { -Composer::Composer() { - mComposer = ::testing::VtsHalHidlTargetTestBase::getService(); - init(); -} +Composer::Composer() : Composer(::testing::VtsHalHidlTargetTestBase::getService()) {} -Composer::Composer(const std::string& name) { - mComposer = ::testing::VtsHalHidlTargetTestBase::getService(name); - init(); -} +Composer::Composer(const std::string& name) + : Composer(::testing::VtsHalHidlTargetTestBase::getService(name)) {} -void Composer::init() { - ASSERT_NE(nullptr, mComposer.get()) << "failed to get composer service"; +Composer::Composer(const sp& composer) : mComposer(composer) { + // ASSERT_* can only be used in functions returning void. + [this] { + ASSERT_NE(nullptr, mComposer.get()) << "failed to get composer service"; - std::vector capabilities = getCapabilities(); - mCapabilities.insert(capabilities.begin(), capabilities.end()); + std::vector capabilities = getCapabilities(); + mCapabilities.insert(capabilities.begin(), capabilities.end()); + }(); } sp Composer::getRaw() const { diff --git a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h index 8d5493e8a5..c97be76d9a 100644 --- a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h +++ b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h @@ -57,10 +57,10 @@ class Composer { std::unique_ptr createClient(); protected: - sp mComposer; + explicit Composer(const sp& composer); private: - void init(); + const sp mComposer; std::unordered_set mCapabilities; }; @@ -68,7 +68,7 @@ class Composer { // A wrapper to IComposerClient. class ComposerClient { public: - ComposerClient(const sp& client); + explicit ComposerClient(const sp& client); ~ComposerClient(); sp getRaw() const; @@ -116,7 +116,7 @@ class ComposerClient { std::unordered_map mDisplayResources; private: - sp mClient; + const sp mClient; }; } // namespace vts diff --git a/graphics/composer/2.2/utils/vts/ComposerVts.cpp b/graphics/composer/2.2/utils/vts/ComposerVts.cpp index 357c7725af..ae9e430545 100644 --- a/graphics/composer/2.2/utils/vts/ComposerVts.cpp +++ b/graphics/composer/2.2/utils/vts/ComposerVts.cpp @@ -27,28 +27,27 @@ namespace composer { namespace V2_2 { namespace vts { -using android::hardware::details::canCastInterface; -using android::hardware::details::getDescriptor; -using android::hardware::graphics::composer::V2_2::IComposerClient; +using details::canCastInterface; +using details::getDescriptor; -std::unique_ptr Composer_v2_2::createClient_v2_2() { - std::unique_ptr client; - mComposer->createClient([&](const auto& tmpError, const auto& tmpClient) { +std::unique_ptr Composer::createClient() { + std::unique_ptr client; + getRaw()->createClient([&](const auto& tmpError, const auto& tmpClient) { ASSERT_EQ(Error::NONE, tmpError) << "failed to create client"; ALOGV("tmpClient is a %s", getDescriptor(&(*tmpClient)).c_str()); ASSERT_TRUE(canCastInterface( &(*tmpClient), "android.hardware.graphics.composer@2.2::IComposerClient", false)) << "Cannot create 2.2 IComposerClient"; - client = std::make_unique(IComposerClient::castFrom(tmpClient, true)); + client = std::make_unique(IComposerClient::castFrom(tmpClient, true)); }); return client; } -std::vector ComposerClient_v2_2::getPerFrameMetadataKeys( +std::vector ComposerClient::getPerFrameMetadataKeys( Display display) { std::vector keys; - mClient_v2_2->getPerFrameMetadataKeys(display, [&](const auto& tmpError, const auto& tmpKeys) { + mClient->getPerFrameMetadataKeys(display, [&](const auto& tmpError, const auto& tmpKeys) { ASSERT_EQ(Error::NONE, tmpError) << "failed to get HDR metadata keys"; keys = tmpKeys; }); @@ -56,43 +55,42 @@ std::vector ComposerClient_v2_2::getPerFra return keys; } -void ComposerClient_v2_2::execute_v2_2(V2_1::vts::TestCommandReader* reader, - V2_2::CommandWriterBase* writer) { +void ComposerClient::execute(V2_1::vts::TestCommandReader* reader, CommandWriterBase* writer) { bool queueChanged = false; uint32_t commandLength = 0; hidl_vec commandHandles; ASSERT_TRUE(writer->writeQueue(&queueChanged, &commandLength, &commandHandles)); if (queueChanged) { - auto ret = mClient_v2_2->setInputCommandQueue(*writer->getMQDescriptor()); + auto ret = mClient->setInputCommandQueue(*writer->getMQDescriptor()); ASSERT_EQ(Error::NONE, static_cast(ret)); return; } - mClient_v2_2->executeCommands(commandLength, commandHandles, - [&](const auto& tmpError, const auto& tmpOutQueueChanged, - const auto& tmpOutLength, const auto& tmpOutHandles) { - ASSERT_EQ(Error::NONE, tmpError); + mClient->executeCommands(commandLength, commandHandles, + [&](const auto& tmpError, const auto& tmpOutQueueChanged, + const auto& tmpOutLength, const auto& tmpOutHandles) { + ASSERT_EQ(Error::NONE, tmpError); - if (tmpOutQueueChanged) { - mClient_v2_2->getOutputCommandQueue( - [&](const auto& tmpError, const auto& tmpDescriptor) { - ASSERT_EQ(Error::NONE, tmpError); - reader->setMQDescriptor(tmpDescriptor); - }); - } + if (tmpOutQueueChanged) { + mClient->getOutputCommandQueue( + [&](const auto& tmpError, const auto& tmpDescriptor) { + ASSERT_EQ(Error::NONE, tmpError); + reader->setMQDescriptor(tmpDescriptor); + }); + } - ASSERT_TRUE(reader->readQueue(tmpOutLength, tmpOutHandles)); - reader->parse(); - }); + ASSERT_TRUE(reader->readQueue(tmpOutLength, tmpOutHandles)); + reader->parse(); + }); } -Display ComposerClient_v2_2::createVirtualDisplay_2_2(uint32_t width, uint32_t height, - PixelFormat formatHint, - uint32_t outputBufferSlotCount, - PixelFormat* outFormat) { +Display ComposerClient::createVirtualDisplay_2_2(uint32_t width, uint32_t height, + PixelFormat formatHint, + uint32_t outputBufferSlotCount, + PixelFormat* outFormat) { Display display = 0; - mClient_v2_2->createVirtualDisplay_2_2( + mClient->createVirtualDisplay_2_2( width, height, formatHint, outputBufferSlotCount, [&](const auto& tmpError, const auto& tmpDisplay, const auto& tmpFormat) { ASSERT_EQ(Error::NONE, tmpError) << "failed to create virtual display"; @@ -106,29 +104,27 @@ Display ComposerClient_v2_2::createVirtualDisplay_2_2(uint32_t width, uint32_t h return display; } -bool ComposerClient_v2_2::getClientTargetSupport_2_2(Display display, uint32_t width, - uint32_t height, PixelFormat format, - Dataspace dataspace) { - Error error = - mClient_v2_2->getClientTargetSupport_2_2(display, width, height, format, dataspace); +bool ComposerClient::getClientTargetSupport_2_2(Display display, uint32_t width, uint32_t height, + PixelFormat format, Dataspace dataspace) { + Error error = mClient->getClientTargetSupport_2_2(display, width, height, format, dataspace); return error == Error::NONE; } -void ComposerClient_v2_2::setPowerMode_2_2(Display display, V2_2::IComposerClient::PowerMode mode) { - Error error = mClient_v2_2->setPowerMode_2_2(display, mode); +void ComposerClient::setPowerMode_2_2(Display display, IComposerClient::PowerMode mode) { + Error error = mClient->setPowerMode_2_2(display, mode); ASSERT_TRUE(error == Error::NONE || error == Error::UNSUPPORTED) << "failed to set power mode"; } -void ComposerClient_v2_2::setReadbackBuffer(Display display, const native_handle_t* buffer, - int32_t /* releaseFence */) { +void ComposerClient::setReadbackBuffer(Display display, const native_handle_t* buffer, + int32_t /* releaseFence */) { // Ignoring fence, HIDL doesn't care - Error error = mClient_v2_2->setReadbackBuffer(display, buffer, nullptr); + Error error = mClient->setReadbackBuffer(display, buffer, nullptr); ASSERT_EQ(Error::NONE, error) << "failed to setReadbackBuffer"; } -void ComposerClient_v2_2::getReadbackBufferAttributes(Display display, PixelFormat* outPixelFormat, - Dataspace* outDataspace) { - mClient_v2_2->getReadbackBufferAttributes( +void ComposerClient::getReadbackBufferAttributes(Display display, PixelFormat* outPixelFormat, + Dataspace* outDataspace) { + mClient->getReadbackBufferAttributes( display, [&](const auto& tmpError, const auto& tmpOutPixelFormat, const auto& tmpOutDataspace) { ASSERT_EQ(Error::NONE, tmpError) << "failed to get readback buffer attributes"; @@ -137,42 +133,41 @@ void ComposerClient_v2_2::getReadbackBufferAttributes(Display display, PixelForm }); } -void ComposerClient_v2_2::getReadbackBufferFence(Display display, int32_t* outFence) { +void ComposerClient::getReadbackBufferFence(Display display, int32_t* outFence) { hidl_handle handle; - mClient_v2_2->getReadbackBufferFence(display, [&](const auto& tmpError, const auto& tmpHandle) { + mClient->getReadbackBufferFence(display, [&](const auto& tmpError, const auto& tmpHandle) { ASSERT_EQ(Error::NONE, tmpError) << "failed to get readback fence"; handle = tmpHandle; }); *outFence = 0; } -std::vector ComposerClient_v2_2::getColorModes(Display display) { +std::vector ComposerClient::getColorModes(Display display) { std::vector modes; - mClient_v2_2->getColorModes_2_2(display, [&](const auto& tmpError, const auto& tmpModes) { + mClient->getColorModes_2_2(display, [&](const auto& tmpError, const auto& tmpModes) { ASSERT_EQ(Error::NONE, tmpError) << "failed to get color modes"; modes = tmpModes; }); return modes; } -std::vector ComposerClient_v2_2::getRenderIntents(Display display, ColorMode mode) { +std::vector ComposerClient::getRenderIntents(Display display, ColorMode mode) { std::vector intents; - mClient_v2_2->getRenderIntents( - display, mode, [&](const auto& tmpError, const auto& tmpIntents) { - ASSERT_EQ(Error::NONE, tmpError) << "failed to get render intents"; - intents = tmpIntents; - }); + mClient->getRenderIntents(display, mode, [&](const auto& tmpError, const auto& tmpIntents) { + ASSERT_EQ(Error::NONE, tmpError) << "failed to get render intents"; + intents = tmpIntents; + }); return intents; } -void ComposerClient_v2_2::setColorMode(Display display, ColorMode mode, RenderIntent intent) { - Error error = mClient_v2_2->setColorMode_2_2(display, mode, intent); +void ComposerClient::setColorMode(Display display, ColorMode mode, RenderIntent intent) { + Error error = mClient->setColorMode_2_2(display, mode, intent); ASSERT_TRUE(error == Error::NONE || error == Error::UNSUPPORTED) << "failed to set color mode"; } -std::array ComposerClient_v2_2::getDataspaceSaturationMatrix(Dataspace dataspace) { +std::array ComposerClient::getDataspaceSaturationMatrix(Dataspace dataspace) { std::array matrix; - mClient_v2_2->getDataspaceSaturationMatrix( + mClient->getDataspaceSaturationMatrix( dataspace, [&](const auto& tmpError, const auto& tmpMatrix) { ASSERT_EQ(Error::NONE, tmpError) << "failed to get datasapce saturation matrix"; std::copy_n(tmpMatrix.data(), matrix.size(), matrix.begin()); diff --git a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h index 62ab83f3f2..f8bc1d9465 100644 --- a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h +++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h @@ -36,34 +36,29 @@ namespace composer { namespace V2_2 { namespace vts { -using android::hardware::graphics::common::V1_0::Hdr; -using android::hardware::graphics::common::V1_1::ColorMode; -using android::hardware::graphics::common::V1_1::Dataspace; -using android::hardware::graphics::common::V1_1::PixelFormat; -using android::hardware::graphics::common::V1_1::RenderIntent; -using android::hardware::graphics::composer::V2_2::IComposer; -using android::hardware::graphics::composer::V2_2::IComposerClient; +using common::V1_0::Hdr; +using common::V1_1::ColorMode; +using common::V1_1::Dataspace; +using common::V1_1::PixelFormat; +using common::V1_1::RenderIntent; -class ComposerClient_v2_2; +class ComposerClient; -// Only thing I need for Composer_v2_2 is to create a v2_2 ComposerClient -// Everything else is the same -class Composer_v2_2 : public V2_1::vts::Composer { +// A wrapper to IComposer. +class Composer : public V2_1::vts::Composer { public: - Composer_v2_2() : V2_1::vts::Composer(){}; - explicit Composer_v2_2(const std::string& name) : V2_1::vts::Composer(name){}; + using V2_1::vts::Composer::Composer; - std::unique_ptr createClient_v2_2(); + std::unique_ptr createClient(); }; // A wrapper to IComposerClient. -class ComposerClient_v2_2 - : public android::hardware::graphics::composer::V2_1::vts::ComposerClient { +class ComposerClient : public V2_1::vts::ComposerClient { public: - ComposerClient_v2_2(const sp& client) - : V2_1::vts::ComposerClient(client), mClient_v2_2(client){}; + explicit ComposerClient(const sp& client) + : V2_1::vts::ComposerClient(client), mClient(client) {} - void execute_v2_2(V2_1::vts::TestCommandReader* reader, V2_2::CommandWriterBase* writer); + void execute(V2_1::vts::TestCommandReader* reader, CommandWriterBase* writer); std::vector getPerFrameMetadataKeys(Display display); @@ -71,7 +66,7 @@ class ComposerClient_v2_2 uint32_t outputBufferSlotCount, PixelFormat* outFormat); bool getClientTargetSupport_2_2(Display display, uint32_t width, uint32_t height, PixelFormat format, Dataspace dataspace); - void setPowerMode_2_2(Display display, V2_2::IComposerClient::PowerMode mode); + void setPowerMode_2_2(Display display, IComposerClient::PowerMode mode); void setReadbackBuffer(Display display, const native_handle_t* buffer, int32_t releaseFence); void getReadbackBufferAttributes(Display display, PixelFormat* outPixelFormat, Dataspace* outDataspace); @@ -84,7 +79,7 @@ class ComposerClient_v2_2 std::array getDataspaceSaturationMatrix(Dataspace dataspace); private: - sp mClient_v2_2; + const sp mClient; }; } // namespace vts diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp index 4e41333e58..342b215c53 100644 --- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp +++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp @@ -32,17 +32,15 @@ namespace V2_2 { namespace vts { namespace { -using android::hardware::graphics::common::V1_0::BufferUsage; -using android::hardware::graphics::common::V1_0::ColorTransform; -using android::hardware::graphics::common::V1_0::Transform; -using android::hardware::graphics::common::V1_1::ColorMode; -using android::hardware::graphics::common::V1_1::Dataspace; -using android::hardware::graphics::common::V1_1::PixelFormat; -using android::hardware::graphics::common::V1_1::RenderIntent; -using android::hardware::graphics::composer::V2_2::IComposerClient; -using android::hardware::graphics::mapper::V2_1::IMapper; -using android::hardware::graphics::mapper::V2_1::vts::Gralloc; -using GrallocError = android::hardware::graphics::mapper::V2_0::Error; +using common::V1_0::BufferUsage; +using common::V1_0::ColorTransform; +using common::V1_0::Transform; +using common::V1_1::ColorMode; +using common::V1_1::Dataspace; +using common::V1_1::PixelFormat; +using common::V1_1::RenderIntent; +using mapper::V2_1::IMapper; +using mapper::V2_1::vts::Gralloc; // Test environment for graphics.composer class GraphicsComposerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { @@ -65,9 +63,9 @@ class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase { protected: void SetUp() override { ASSERT_NO_FATAL_FAILURE( - mComposer = std::make_unique( + mComposer = std::make_unique( GraphicsComposerHidlEnvironment::Instance()->getServiceName())); - ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient_v2_2()); + ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient()); mComposerCallback = new V2_1::vts::GraphicsComposerCallback; mComposerClient->registerCallback(mComposerCallback); @@ -91,8 +89,8 @@ class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase { // use the slot count usually set by SF static constexpr uint32_t kBufferSlotCount = 64; - std::unique_ptr mComposer; - std::unique_ptr mComposerClient; + std::unique_ptr mComposer; + std::unique_ptr mComposerClient; sp mComposerCallback; // the first display and is assumed never to be removed Display mPrimaryDisplay; @@ -119,7 +117,7 @@ class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest { ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique()); - mWriter = std::make_unique(1024); + mWriter = std::make_unique(1024); mReader = std::make_unique(); } @@ -137,9 +135,9 @@ class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest { return mGralloc->allocate(info); } - void execute() { mComposerClient->execute_v2_2(mReader.get(), mWriter.get()); } + void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); } - std::unique_ptr mWriter; + std::unique_ptr mWriter; std::unique_ptr mReader; private: From 9fb3c20bc62a3b2977cf2028cfa1c8c4938ee5b2 Mon Sep 17 00:00:00 2001 From: Jiyong Park Date: Mon, 9 Apr 2018 12:19:43 +0900 Subject: [PATCH 023/718] Mark configstore-utils as double_loadable configstore-utils is explicitly marked as double_loadable since it is one of the (indirect) dependencies of the LLNDK library libvulkan and at the same time the lib itself is marked as VNDK. Such lib can be double loaded inside a vendor process. Note: even without this change, the library is already capable of being double loaded due to the dependency graph around it. This change is to make it explicit so that double loading of a library is carefully tracked and signed-off by the owner of the lib. Bug: 77155589 Test: m -j Change-Id: Ibece0476b819e3387836305ee3b1c9dbf614920b --- configstore/utils/Android.bp | 1 + 1 file changed, 1 insertion(+) diff --git a/configstore/utils/Android.bp b/configstore/utils/Android.bp index 93e52f1d4e..0d626a50b2 100644 --- a/configstore/utils/Android.bp +++ b/configstore/utils/Android.bp @@ -20,6 +20,7 @@ cc_library_shared { vndk: { enabled: true, }, + double_loadable: true, defaults: ["hidl_defaults"], srcs: [ "ConfigStoreUtils.cpp" ], From cd2e9f587d9d24fc0e5b1058e8a05c573714ec02 Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Mon, 12 Mar 2018 19:41:03 -0700 Subject: [PATCH 024/718] graphics: Add composer 2.3 The 2.3 interface adds IComposerClient.getDisplayIdentificationData, which enables display identification for generalized multi-display support. Bug: 74619554 Test: VtsHalGraphicsComposerV2_3TargetTest Change-Id: I303e722ce938fe0af4fc77da812e3525d8c90251 --- graphics/composer/2.3/Android.bp | 21 +++ graphics/composer/2.3/IComposer.hal | 37 +++++ graphics/composer/2.3/IComposerClient.hal | 45 ++++++ graphics/composer/2.3/default/Android.bp | 45 ++++++ graphics/composer/2.3/default/OWNERS | 4 + ....hardware.graphics.composer@2.3-service.rc | 6 + graphics/composer/2.3/default/service.cpp | 55 ++++++++ graphics/composer/2.3/utils/OWNERS | 7 + graphics/composer/2.3/utils/hal/Android.bp | 34 +++++ .../hal/include/composer-hal/2.3/Composer.h | 89 ++++++++++++ .../include/composer-hal/2.3/ComposerClient.h | 74 ++++++++++ .../include/composer-hal/2.3/ComposerHal.h | 42 ++++++ .../composer/2.3/utils/passthrough/Android.bp | 30 ++++ .../include/composer-passthrough/2.3/HwcHal.h | 99 +++++++++++++ .../composer-passthrough/2.3/HwcLoader.h | 79 +++++++++++ graphics/composer/2.3/utils/vts/Android.bp | 41 ++++++ .../composer/2.3/utils/vts/ComposerVts.cpp | 72 ++++++++++ .../include/composer-vts/2.3/ComposerVts.h | 74 ++++++++++ .../composer/2.3/vts/functional/Android.bp | 44 ++++++ graphics/composer/2.3/vts/functional/OWNERS | 7 + .../VtsHalGraphicsComposerV2_3TargetTest.cpp | 133 ++++++++++++++++++ 21 files changed, 1038 insertions(+) create mode 100644 graphics/composer/2.3/Android.bp create mode 100644 graphics/composer/2.3/IComposer.hal create mode 100644 graphics/composer/2.3/IComposerClient.hal create mode 100644 graphics/composer/2.3/default/Android.bp create mode 100644 graphics/composer/2.3/default/OWNERS create mode 100644 graphics/composer/2.3/default/android.hardware.graphics.composer@2.3-service.rc create mode 100644 graphics/composer/2.3/default/service.cpp create mode 100644 graphics/composer/2.3/utils/OWNERS create mode 100644 graphics/composer/2.3/utils/hal/Android.bp create mode 100644 graphics/composer/2.3/utils/hal/include/composer-hal/2.3/Composer.h create mode 100644 graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h create mode 100644 graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h create mode 100644 graphics/composer/2.3/utils/passthrough/Android.bp create mode 100644 graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h create mode 100644 graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcLoader.h create mode 100644 graphics/composer/2.3/utils/vts/Android.bp create mode 100644 graphics/composer/2.3/utils/vts/ComposerVts.cpp create mode 100644 graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h create mode 100644 graphics/composer/2.3/vts/functional/Android.bp create mode 100644 graphics/composer/2.3/vts/functional/OWNERS create mode 100644 graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp diff --git a/graphics/composer/2.3/Android.bp b/graphics/composer/2.3/Android.bp new file mode 100644 index 0000000000..23061dda5b --- /dev/null +++ b/graphics/composer/2.3/Android.bp @@ -0,0 +1,21 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +hidl_interface { + name: "android.hardware.graphics.composer@2.3", + root: "android.hardware", + vndk: { + enabled: true, + }, + srcs: [ + "IComposer.hal", + "IComposerClient.hal", + ], + interfaces: [ + "android.hardware.graphics.common@1.0", + "android.hardware.graphics.composer@2.1", + "android.hardware.graphics.composer@2.2", + "android.hidl.base@1.0", + ], + gen_java: false, +} + diff --git a/graphics/composer/2.3/IComposer.hal b/graphics/composer/2.3/IComposer.hal new file mode 100644 index 0000000000..90b2427c7c --- /dev/null +++ b/graphics/composer/2.3/IComposer.hal @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.graphics.composer@2.3; + +import IComposerClient; + +import @2.1::Error; +import @2.2::IComposer; + +interface IComposer extends @2.2::IComposer { + + /** + * Creates a v2.3 client of the composer. Supersedes @2.1::createClient. + * + * @return error is NONE upon success. Otherwise, + * NO_RESOURCES when the client could not be created. + * @return client is the newly created client. + */ + @entry + @callflow(next="*") + createClient_2_3() generates (Error error, IComposerClient client); + +}; diff --git a/graphics/composer/2.3/IComposerClient.hal b/graphics/composer/2.3/IComposerClient.hal new file mode 100644 index 0000000000..77dd3eed72 --- /dev/null +++ b/graphics/composer/2.3/IComposerClient.hal @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.graphics.composer@2.3; + +import @2.2::IComposerClient; +import @2.1::Display; +import @2.1::Error; + +interface IComposerClient extends @2.2::IComposerClient { + + /** + * Returns the port and data that describe a physical display. The port is + * a unique number that identifies a physical connector (e.g. eDP, HDMI) + * for display output. The data blob is parsed to determine its format, + * typically EDID 1.3 as specified in VESA E-EDID Standard Release A + * Revision 1. + * + * @param display is the display to query. + * @return error is NONE upon success. Otherwise, + * BAD_DISPLAY when an invalid display handle was passed in. + * UNSUPPORTED when identification data is unavailable. + * @return port is the connector to which the display is connected. + * @return data is the EDID 1.3 blob identifying the display. + */ + @callflow(next="*") + getDisplayIdentificationData(Display display) + generates (Error error, + uint8_t port, + vec data); + +}; diff --git a/graphics/composer/2.3/default/Android.bp b/graphics/composer/2.3/default/Android.bp new file mode 100644 index 0000000000..ad49ec3adf --- /dev/null +++ b/graphics/composer/2.3/default/Android.bp @@ -0,0 +1,45 @@ +// +// Copyright (C) 2018 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +cc_binary { + name: "android.hardware.graphics.composer@2.3-service", + defaults: ["hidl_defaults"], + vendor: true, + relative_install_path: "hw", + srcs: ["service.cpp"], + init_rc: ["android.hardware.graphics.composer@2.3-service.rc"], + header_libs: [ + "android.hardware.graphics.composer@2.3-passthrough", + ], + shared_libs: [ + "android.hardware.graphics.composer@2.1", + "android.hardware.graphics.composer@2.2", + "android.hardware.graphics.composer@2.3", + "android.hardware.graphics.mapper@2.0", + "libbase", + "libbinder", + "libcutils", + "libfmq", + "libhardware", + "libhidlbase", + "libhidltransport", + "libhwc2on1adapter", + "libhwc2onfbadapter", + "liblog", + "libsync", + "libutils", + ], +} diff --git a/graphics/composer/2.3/default/OWNERS b/graphics/composer/2.3/default/OWNERS new file mode 100644 index 0000000000..3aa5fa1ffd --- /dev/null +++ b/graphics/composer/2.3/default/OWNERS @@ -0,0 +1,4 @@ +# Graphics team +jessehall@google.com +olv@google.com +stoza@google.com diff --git a/graphics/composer/2.3/default/android.hardware.graphics.composer@2.3-service.rc b/graphics/composer/2.3/default/android.hardware.graphics.composer@2.3-service.rc new file mode 100644 index 0000000000..08e32d8f13 --- /dev/null +++ b/graphics/composer/2.3/default/android.hardware.graphics.composer@2.3-service.rc @@ -0,0 +1,6 @@ +service vendor.hwcomposer-2-3 /vendor/bin/hw/android.hardware.graphics.composer@2.3-service + class hal animation + user system + group graphics drmrpc + capabilities SYS_NICE + onrestart restart surfaceflinger diff --git a/graphics/composer/2.3/default/service.cpp b/graphics/composer/2.3/default/service.cpp new file mode 100644 index 0000000000..347d8be278 --- /dev/null +++ b/graphics/composer/2.3/default/service.cpp @@ -0,0 +1,55 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include + +using android::hardware::graphics::composer::V2_3::IComposer; +using android::hardware::graphics::composer::V2_3::passthrough::HwcLoader; + +int main() { + // the conventional HAL might start binder services + android::ProcessState::initWithDriver("/dev/vndbinder"); + android::ProcessState::self()->setThreadPoolMaxThreadCount(4); + android::ProcessState::self()->startThreadPool(); + + // same as SF main thread + struct sched_param param = {0}; + param.sched_priority = 2; + if (sched_setscheduler(0, SCHED_FIFO | SCHED_RESET_ON_FORK, ¶m) != 0) { + ALOGE("Couldn't set SCHED_FIFO: %d", errno); + } + + android::hardware::configureRpcThreadpool(4, true /* will join */); + + android::sp composer = HwcLoader::load(); + if (composer == nullptr) { + return 1; + } + if (composer->registerAsService() != android::NO_ERROR) { + ALOGE("failed to register service"); + return 1; + } + + android::hardware::joinRpcThreadpool(); + + ALOGE("service is terminating"); + return 1; +} diff --git a/graphics/composer/2.3/utils/OWNERS b/graphics/composer/2.3/utils/OWNERS new file mode 100644 index 0000000000..234bc7559f --- /dev/null +++ b/graphics/composer/2.3/utils/OWNERS @@ -0,0 +1,7 @@ +# Graphics team +olv@google.com +stoza@google.com + +# VTS team +yim@google.com +zhuoyao@google.com diff --git a/graphics/composer/2.3/utils/hal/Android.bp b/graphics/composer/2.3/utils/hal/Android.bp new file mode 100644 index 0000000000..aa46df1ebb --- /dev/null +++ b/graphics/composer/2.3/utils/hal/Android.bp @@ -0,0 +1,34 @@ +// +// Copyright (C) 2018 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +cc_library_headers { + name: "android.hardware.graphics.composer@2.3-hal", + defaults: ["hidl_defaults"], + vendor_available: true, + shared_libs: [ + "android.hardware.graphics.composer@2.3", + ], + export_shared_lib_headers: [ + "android.hardware.graphics.composer@2.3", + ], + header_libs: [ + "android.hardware.graphics.composer@2.2-hal", + ], + export_header_lib_headers: [ + "android.hardware.graphics.composer@2.2-hal", + ], + export_include_dirs: ["include"], +} diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/Composer.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/Composer.h new file mode 100644 index 0000000000..8e11a5ae1a --- /dev/null +++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/Composer.h @@ -0,0 +1,89 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#ifndef LOG_TAG +#warning "Composer.h included without LOG_TAG" +#endif + +#include +#include +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace composer { +namespace V2_3 { +namespace hal { + +namespace detail { + +// ComposerImpl implements V2_*::IComposer on top of V2_*::ComposerHal +template +class ComposerImpl : public V2_2::hal::detail::ComposerImpl { + public: + static std::unique_ptr create(std::unique_ptr hal) { + return std::make_unique(std::move(hal)); + } + + explicit ComposerImpl(std::unique_ptr hal) : BaseType2_2(std::move(hal)) {} + + // IComposer 2.3 interface + + Return createClient_2_3(IComposer::createClient_2_3_cb hidl_cb) override { + std::unique_lock lock(mClientMutex); + if (!waitForClientDestroyedLocked(lock)) { + hidl_cb(Error::NO_RESOURCES, nullptr); + return Void(); + } + + sp client = ComposerClient::create(mHal.get()).release(); + if (!client) { + hidl_cb(Error::NO_RESOURCES, nullptr); + return Void(); + } + + auto clientDestroyed = [this]() { onClientDestroyed(); }; + client->setOnClientDestroyed(clientDestroyed); + + mClient = client; + hidl_cb(Error::NONE, client); + return Void(); + } + + private: + using BaseType2_2 = V2_2::hal::detail::ComposerImpl; + using BaseType2_1 = V2_1::hal::detail::ComposerImpl; + + using BaseType2_1::mClient; + using BaseType2_1::mClientMutex; + using BaseType2_1::mHal; + using BaseType2_1::onClientDestroyed; + using BaseType2_1::waitForClientDestroyedLocked; +}; + +} // namespace detail + +using Composer = detail::ComposerImpl; + +} // namespace hal +} // namespace V2_3 +} // namespace composer +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h new file mode 100644 index 0000000000..e717d84ba8 --- /dev/null +++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h @@ -0,0 +1,74 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#ifndef LOG_TAG +#warning "ComposerClient.h included without LOG_TAG" +#endif + +#include +#include +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace composer { +namespace V2_3 { +namespace hal { + +namespace detail { + +// ComposerClientImpl implements V2_*::IComposerClient on top of V2_*::ComposerHal +template +class ComposerClientImpl : public V2_2::hal::detail::ComposerClientImpl { + public: + static std::unique_ptr create(Hal* hal) { + auto client = std::make_unique(hal); + return client->init() ? std::move(client) : nullptr; + } + + ComposerClientImpl(Hal* hal) : BaseType2_2(hal) {} + + // IComposerClient 2.3 interface + + Return getDisplayIdentificationData( + Display display, IComposerClient::getDisplayIdentificationData_cb hidl_cb) override { + uint8_t port = 0; + std::vector data; + Error error = mHal->getDisplayIdentificationData(display, &port, &data); + hidl_cb(error, port, data); + return Void(); + } + + private: + using BaseType2_2 = V2_2::hal::detail::ComposerClientImpl; + using BaseType2_1 = V2_1::hal::detail::ComposerClientImpl; + + using BaseType2_1::mHal; +}; + +} // namespace detail + +using ComposerClient = detail::ComposerClientImpl; + +} // namespace hal +} // namespace V2_3 +} // namespace composer +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h new file mode 100644 index 0000000000..37ea0a3c46 --- /dev/null +++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h @@ -0,0 +1,42 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace composer { +namespace V2_3 { +namespace hal { + +using V2_1::Display; +using V2_1::Error; + +class ComposerHal : public V2_2::hal::ComposerHal { + public: + virtual Error getDisplayIdentificationData(Display display, uint8_t* outPort, + std::vector* outData) = 0; +}; + +} // namespace hal +} // namespace V2_3 +} // namespace composer +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/graphics/composer/2.3/utils/passthrough/Android.bp b/graphics/composer/2.3/utils/passthrough/Android.bp new file mode 100644 index 0000000000..3ae6b1648d --- /dev/null +++ b/graphics/composer/2.3/utils/passthrough/Android.bp @@ -0,0 +1,30 @@ +// +// Copyright (C) 2018 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +cc_library_headers { + name: "android.hardware.graphics.composer@2.3-passthrough", + defaults: ["hidl_defaults"], + vendor: true, + header_libs: [ + "android.hardware.graphics.composer@2.2-passthrough", + "android.hardware.graphics.composer@2.3-hal", + ], + export_header_lib_headers: [ + "android.hardware.graphics.composer@2.2-passthrough", + "android.hardware.graphics.composer@2.3-hal", + ], + export_include_dirs: ["include"], +} diff --git a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h new file mode 100644 index 0000000000..53f2d1b254 --- /dev/null +++ b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h @@ -0,0 +1,99 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#ifndef LOG_TAG +#warning "HwcHal.h included without LOG_TAG" +#endif + +#include + +#include +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace composer { +namespace V2_3 { +namespace passthrough { + +namespace detail { + +using V2_1::Display; +using V2_1::Error; + +// HwcHalImpl implements V2_*::hal::ComposerHal on top of hwcomposer2 +template +class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl { + public: + Error getDisplayIdentificationData(Display display, uint8_t* outPort, + std::vector* outData) override { + if (!mDispatch.getDisplayIdentificationData) { + return Error::UNSUPPORTED; + } + + uint32_t size = 0; + int32_t error = + mDispatch.getDisplayIdentificationData(mDevice, display, outPort, &size, nullptr); + if (error != HWC2_ERROR_NONE) { + return static_cast(error); + } + + std::vector data(size); + error = + mDispatch.getDisplayIdentificationData(mDevice, display, outPort, &size, data.data()); + if (error != HWC2_ERROR_NONE) { + return static_cast(error); + } + + data.resize(size); + *outData = std::move(data); + return Error::NONE; + } + + protected: + bool initDispatch() override { + if (!BaseType2_2::initDispatch()) { + return false; + } + + this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAY_IDENTIFICATION_DATA, + &mDispatch.getDisplayIdentificationData); + return true; + } + + private: + struct { + HWC2_PFN_GET_DISPLAY_IDENTIFICATION_DATA getDisplayIdentificationData; + } mDispatch = {}; + + using BaseType2_2 = V2_2::passthrough::detail::HwcHalImpl; + using BaseType2_1 = V2_1::passthrough::detail::HwcHalImpl; + using BaseType2_1::mDevice; +}; + +} // namespace detail + +using HwcHal = detail::HwcHalImpl; + +} // namespace passthrough +} // namespace V2_3 +} // namespace composer +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcLoader.h b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcLoader.h new file mode 100644 index 0000000000..afef475e78 --- /dev/null +++ b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcLoader.h @@ -0,0 +1,79 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#ifndef LOG_TAG +#warning "HwcLoader.h included without LOG_TAG" +#endif + +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace composer { +namespace V2_3 { +namespace passthrough { + +class HwcLoader : public V2_2::passthrough::HwcLoader { + public: + static IComposer* load() { + const hw_module_t* module = loadModule(); + if (!module) { + return nullptr; + } + + auto hal = createHalWithAdapter(module); + if (!hal) { + return nullptr; + } + + return createComposer(std::move(hal)).release(); + } + + // create a ComposerHal instance + static std::unique_ptr createHal(const hw_module_t* module) { + auto hal = std::make_unique(); + return hal->initWithModule(module) ? std::move(hal) : nullptr; + } + + // create a ComposerHal instance, insert an adapter if necessary + static std::unique_ptr createHalWithAdapter(const hw_module_t* module) { + bool adapted; + hwc2_device_t* device = openDeviceWithAdapter(module, &adapted); + if (!device) { + return nullptr; + } + auto hal = std::make_unique(); + return hal->initWithDevice(std::move(device), !adapted) ? std::move(hal) : nullptr; + } + + // create an IComposer instance + static std::unique_ptr createComposer(std::unique_ptr hal) { + return hal::Composer::create(std::move(hal)); + } +}; + +} // namespace passthrough +} // namespace V2_3 +} // namespace composer +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/graphics/composer/2.3/utils/vts/Android.bp b/graphics/composer/2.3/utils/vts/Android.bp new file mode 100644 index 0000000000..05532586ef --- /dev/null +++ b/graphics/composer/2.3/utils/vts/Android.bp @@ -0,0 +1,41 @@ +// +// Copyright (C) 2018 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +cc_library_static { + name: "android.hardware.graphics.composer@2.3-vts", + defaults: ["hidl_defaults"], + srcs: [ + "ComposerVts.cpp", + ], + static_libs: [ + "VtsHalHidlTargetTestBase", + "android.hardware.graphics.composer@2.1", + "android.hardware.graphics.composer@2.1-vts", + "android.hardware.graphics.composer@2.2", + "android.hardware.graphics.composer@2.2-vts", + "android.hardware.graphics.composer@2.3", + ], + header_libs: [ + "android.hardware.graphics.composer@2.1-command-buffer", + "android.hardware.graphics.composer@2.2-command-buffer", + ], + cflags: [ + "-O0", + "-g", + "-DLOG_TAG=\"ComposerVts\"", + ], + export_include_dirs: ["include"], +} diff --git a/graphics/composer/2.3/utils/vts/ComposerVts.cpp b/graphics/composer/2.3/utils/vts/ComposerVts.cpp new file mode 100644 index 0000000000..f1d3a5093a --- /dev/null +++ b/graphics/composer/2.3/utils/vts/ComposerVts.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace composer { +namespace V2_3 { +namespace vts { + +using V2_1::Error; + +Composer::Composer() : Composer(::testing::VtsHalHidlTargetTestBase::getService()) {} + +Composer::Composer(const std::string& name) + : Composer(::testing::VtsHalHidlTargetTestBase::getService(name)) {} + +Composer::Composer(const sp& composer) + : V2_2::vts::Composer(composer), mComposer(composer) {} + +std::unique_ptr Composer::createClient() { + std::unique_ptr client; + mComposer->createClient_2_3([&client](const auto& tmpError, const auto& tmpClient) { + ASSERT_EQ(Error::NONE, tmpError) << "failed to create client"; + client = std::make_unique(tmpClient); + }); + + return client; +} + +bool ComposerClient::getDisplayIdentificationData(Display display, uint8_t* outPort, + std::vector* outData) { + bool supported = true; + mClient->getDisplayIdentificationData( + display, [&](const auto& tmpError, const auto& tmpPort, const auto& tmpData) { + if (tmpError == Error::UNSUPPORTED) { + supported = false; + return; + } + ASSERT_EQ(Error::NONE, tmpError) << "failed to get display identification data"; + + *outPort = tmpPort; + *outData = tmpData; + ASSERT_FALSE(outData->empty()) << "data is empty"; + }); + + return supported; +} + +} // namespace vts +} // namespace V2_3 +} // namespace composer +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h b/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h new file mode 100644 index 0000000000..103b85a830 --- /dev/null +++ b/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace composer { +namespace V2_3 { +namespace vts { + +using V2_1::Display; +using V2_3::IComposer; +using V2_3::IComposerClient; + +class ComposerClient; + +// A wrapper to IComposer. +class Composer : public V2_2::vts::Composer { + public: + Composer(); + explicit Composer(const std::string& name); + + std::unique_ptr createClient(); + + protected: + explicit Composer(const sp& composer); + + private: + const sp mComposer; +}; + +// A wrapper to IComposerClient. +class ComposerClient : public V2_2::vts::ComposerClient { + public: + explicit ComposerClient(const sp& client) + : V2_2::vts::ComposerClient(client), mClient(client) {} + + bool getDisplayIdentificationData(Display display, uint8_t* outPort, + std::vector* outData); + + private: + const sp mClient; +}; + +} // namespace vts +} // namespace V2_3 +} // namespace composer +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/graphics/composer/2.3/vts/functional/Android.bp b/graphics/composer/2.3/vts/functional/Android.bp new file mode 100644 index 0000000000..df696c9273 --- /dev/null +++ b/graphics/composer/2.3/vts/functional/Android.bp @@ -0,0 +1,44 @@ +// +// Copyright (C) 2018 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +cc_test { + name: "VtsHalGraphicsComposerV2_3TargetTest", + defaults: ["VtsHalTargetTestDefaults"], + srcs: ["VtsHalGraphicsComposerV2_3TargetTest.cpp"], + + // TODO(b/64437680): Assume these libs are always available on the device. + shared_libs: [ + "libfmq", + "libhidltransport", + "libsync", + ], + static_libs: [ + "android.hardware.graphics.allocator@2.0", + "android.hardware.graphics.composer@2.1", + "android.hardware.graphics.composer@2.1-vts", + "android.hardware.graphics.composer@2.2", + "android.hardware.graphics.composer@2.2-vts", + "android.hardware.graphics.composer@2.3", + "android.hardware.graphics.composer@2.3-vts", + "android.hardware.graphics.mapper@2.0", + "android.hardware.graphics.mapper@2.0-vts", + "android.hardware.graphics.mapper@2.1", + ], + header_libs: [ + "android.hardware.graphics.composer@2.1-command-buffer", + "android.hardware.graphics.composer@2.2-command-buffer", + ], +} diff --git a/graphics/composer/2.3/vts/functional/OWNERS b/graphics/composer/2.3/vts/functional/OWNERS new file mode 100644 index 0000000000..234bc7559f --- /dev/null +++ b/graphics/composer/2.3/vts/functional/OWNERS @@ -0,0 +1,7 @@ +# Graphics team +olv@google.com +stoza@google.com + +# VTS team +yim@google.com +zhuoyao@google.com diff --git a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp new file mode 100644 index 0000000000..f4e34f08ff --- /dev/null +++ b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "graphics_composer_hidl_hal_test@2.3" + +#include + +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace composer { +namespace V2_3 { +namespace vts { +namespace { + +// Test environment for graphics.composer +class GraphicsComposerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { + public: + // get the test environment singleton + static GraphicsComposerHidlEnvironment* Instance() { + static GraphicsComposerHidlEnvironment* instance = new GraphicsComposerHidlEnvironment; + return instance; + } + + virtual void registerTestServices() override { registerTestService(); } + + private: + GraphicsComposerHidlEnvironment() {} + + GTEST_DISALLOW_COPY_AND_ASSIGN_(GraphicsComposerHidlEnvironment); +}; + +class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase { + protected: + void SetUp() override { + ASSERT_NO_FATAL_FAILURE( + mComposer = std::make_unique( + GraphicsComposerHidlEnvironment::Instance()->getServiceName())); + ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient()); + + mComposerCallback = new V2_1::vts::GraphicsComposerCallback; + mComposerClient->registerCallback(mComposerCallback); + + // assume the first display is primary and is never removed + mPrimaryDisplay = waitForFirstDisplay(); + + // explicitly disable vsync + mComposerClient->setVsyncEnabled(mPrimaryDisplay, false); + mComposerCallback->setVsyncAllowed(false); + } + + void TearDown() override { + if (mComposerCallback != nullptr) { + EXPECT_EQ(0, mComposerCallback->getInvalidHotplugCount()); + EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount()); + EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount()); + } + } + + std::unique_ptr mComposer; + std::unique_ptr mComposerClient; + sp mComposerCallback; + // the first display and is assumed never to be removed + Display mPrimaryDisplay; + + private: + Display waitForFirstDisplay() { + while (true) { + std::vector displays = mComposerCallback->getDisplays(); + if (displays.empty()) { + usleep(5 * 1000); + continue; + } + + return displays[0]; + } + } +}; + +/** + * Test IComposerClient::getDisplayIdentificationData. + * + * TODO: Check that ports are unique for multiple displays. + */ +TEST_F(GraphicsComposerHidlTest, GetDisplayIdentificationData) { + uint8_t port0; + std::vector data0; + if (mComposerClient->getDisplayIdentificationData(mPrimaryDisplay, &port0, &data0)) { + uint8_t port1; + std::vector data1; + ASSERT_TRUE(mComposerClient->getDisplayIdentificationData(mPrimaryDisplay, &port1, &data1)); + + ASSERT_EQ(port0, port1) << "ports are not stable"; + ASSERT_TRUE(data0.size() == data1.size() && + std::equal(data0.begin(), data0.end(), data1.begin())) + << "data is not stable"; + } +} + +} // namespace +} // namespace vts +} // namespace V2_3 +} // namespace composer +} // namespace graphics +} // namespace hardware +} // namespace android + +int main(int argc, char** argv) { + using android::hardware::graphics::composer::V2_3::vts::GraphicsComposerHidlEnvironment; + ::testing::AddGlobalTestEnvironment(GraphicsComposerHidlEnvironment::Instance()); + ::testing::InitGoogleTest(&argc, argv); + GraphicsComposerHidlEnvironment::Instance()->init(&argc, argv); + int status = RUN_ALL_TESTS(); + return status; +} From 2d2e2d5c05cd53572805a4cd1a1d6af893d05b5a Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Mon, 30 Apr 2018 13:02:02 -0700 Subject: [PATCH 025/718] Add compatibility_matrix.current.xml for Android Q. HAL development is starting for Andorid Q, so we need this. Test: m compatibility_matrix.current.xml Test: assemble_vintf (but b/78895849) Test: boot a Pixel device after setting its target-level to 4 and verify that the compatibility check passes, and the file is in the correct location (system/etc/vintf) and that the dependencies are setup properly. Change-Id: I42426d0145a97c719092306abc4f7ce8fa2b51bd --- compatibility_matrices/Android.mk | 13 + .../compatibility_matrix.current.xml | 458 ++++++++++++++++++ 2 files changed, 471 insertions(+) create mode 100644 compatibility_matrices/compatibility_matrix.current.xml diff --git a/compatibility_matrices/Android.mk b/compatibility_matrices/Android.mk index 9e48588e2f..26603e728d 100644 --- a/compatibility_matrices/Android.mk +++ b/compatibility_matrices/Android.mk @@ -70,6 +70,18 @@ LOCAL_KERNEL_CONFIG_DATA_PATHS := \ include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX) +include $(CLEAR_VARS) +include $(LOCAL_PATH)/clear_vars.mk +LOCAL_MODULE := framework_compatibility_matrix.current.xml +LOCAL_MODULE_STEM := compatibility_matrix.current.xml +LOCAL_SRC_FILES := $(LOCAL_MODULE_STEM) +LOCAL_KERNEL_CONFIG_DATA_PATHS := \ + 4.4.0:$(my_kernel_config_data)/android-4.4 \ + 4.9.0:$(my_kernel_config_data)/android-4.9 \ + 4.14.0:$(my_kernel_config_data)/android-4.14 \ + +include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX) + my_kernel_config_data := # Framework Compatibility Matrix (common to all FCM versions) @@ -131,6 +143,7 @@ LOCAL_REQUIRED_MODULES := \ framework_compatibility_matrix.1.xml \ framework_compatibility_matrix.2.xml \ framework_compatibility_matrix.3.xml \ + framework_compatibility_matrix.current.xml \ framework_compatibility_matrix.device.xml LOCAL_GENERATED_SOURCES := $(call module-installed-files,$(LOCAL_REQUIRED_MODULES)) diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml new file mode 100644 index 0000000000..3b7c90d4ed --- /dev/null +++ b/compatibility_matrices/compatibility_matrix.current.xml @@ -0,0 +1,458 @@ + + + android.hardware.audio + 4.0 + + IDevicesFactory + default + + + + android.hardware.audio.effect + 4.0 + + IEffectsFactory + default + + + + android.hardware.authsecret + 1.0 + + IAuthSecret + default + + + + android.hardware.automotive.audiocontrol + 1.0 + + IAudioControl + default + + + + android.hardware.automotive.evs + 1.0 + + IEvsEnumerator + default + + + + android.hardware.automotive.vehicle + 2.0 + + IVehicle + default + + + + android.hardware.biometrics.fingerprint + 2.1 + + IBiometricsFingerprint + default + + + + android.hardware.bluetooth + 1.0 + + IBluetoothHci + default + + + + android.hardware.bluetooth.a2dp + 1.0 + + IBluetoothAudioOffload + default + + + + android.hardware.boot + 1.0 + + IBootControl + default + + + + android.hardware.broadcastradio + 1.0-1 + + IBroadcastRadioFactory + default + + + + android.hardware.camera.provider + 2.4 + + ICameraProvider + [^/]+/[0-9]+ + + + + android.hardware.cas + 1.0 + + IMediaCasService + default + + + + android.hardware.configstore + 1.0 + + ISurfaceFlingerConfigs + default + + + + android.hardware.confirmationui + 1.0 + + IConfirmationUI + default + + + + android.hardware.contexthub + 1.0 + + IContexthub + default + + + + android.hardware.drm + 1.0 + + ICryptoFactory + .* + + + IDrmFactory + .* + + + + android.hardware.drm + 1.1 + + ICryptoFactory + .* + + + IDrmFactory + .* + + + + android.hardware.dumpstate + 1.0 + + IDumpstateDevice + default + + + + android.hardware.gatekeeper + 1.0 + + IGatekeeper + default + + + + android.hardware.gnss + 1.0-1 + + IGnss + default + + + + android.hardware.graphics.allocator + 2.0 + + IAllocator + default + + + + android.hardware.graphics.composer + 2.1 + + IComposer + default + + + + android.hardware.graphics.mapper + 2.0 + + IMapper + default + + + + android.hardware.health + 2.0 + + IHealth + default + + + + android.hardware.ir + 1.0 + + + android.hardware.keymaster + 3.0 + 4.0 + + IKeymasterDevice + default + + + + android.hardware.keymaster + 4.0 + + IKeymasterDevice + strongbox + + + + android.hardware.light + 2.0 + + ILight + default + + + + android.hardware.media.omx + 1.0 + + IOmx + default + + + IOmxStore + default + + + + android.hardware.memtrack + 1.0 + + IMemtrack + default + + + + android.hardware.neuralnetworks + 1.0 + + IDevice + .* + + + + android.hardware.nfc + 1.1 + + INfc + default + + + + android.hardware.oemlock + 1.0 + + IOemLock + default + + + + android.hardware.power + 1.0-2 + + IPower + default + + + + android.hardware.radio + 1.0-2 + + IRadio + slot1 + slot2 + slot3 + + + ISap + slot1 + + + + android.hardware.radio.config + 1.0 + + IRadioConfig + default + + + + android.hardware.renderscript + 1.0 + + IDevice + default + + + + android.hardware.secure_element + 1.0 + + ISecureElement + eSE[1-9][0-9]* + SIM[1-9][0-9]* + + + + android.hardware.sensors + 1.0 + + ISensors + default + + + + android.hardware.soundtrigger + 2.0-1 + + ISoundTriggerHw + default + + + + android.hardware.tetheroffload.config + 1.0 + + IOffloadConfig + default + + + + android.hardware.tetheroffload.control + 1.0 + + IOffloadControl + default + + + + android.hardware.thermal + 1.0-1 + + IThermal + default + + + + android.hardware.tv.cec + 1.0 + + IHdmiCec + default + + + + android.hardware.tv.input + 1.0 + + ITvInput + default + + + + android.hardware.usb + 1.0-1 + + IUsb + default + + + + android.hardware.usb.gadget + 1.0 + + IUsbGadget + default + + + + android.hardware.vibrator + 1.0-2 + + IVibrator + default + + + + android.hardware.vr + 1.0 + + IVr + default + + + + android.hardware.weaver + 1.0 + + IWeaver + default + + + + android.hardware.wifi + 1.0-2 + + IWifi + default + + + + android.hardware.wifi.hostapd + 1.0 + + IHostapd + default + + + + android.hardware.wifi.offload + 1.0 + + IOffload + default + + + + android.hardware.wifi.supplicant + 1.0-1 + + ISupplicant + default + + + From ae005c46101883a9c7938de9bc0286cfc4e7b7b8 Mon Sep 17 00:00:00 2001 From: Yifan Hong Date: Fri, 27 Apr 2018 15:04:52 -0700 Subject: [PATCH 026/718] healthd use vintf_fragments This encourages device manufacturers to use service.override over service and to remove healthd on device, because it is one less step to do. Test: make VINTF metadata Bug: 66917623 Change-Id: I447395450060cdf17731514bb9a5e3ed912bbc66 --- health/2.0/README | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/health/2.0/README b/health/2.0/README index 11e6a7aaf1..9f77b8372f 100644 --- a/health/2.0/README +++ b/health/2.0/README @@ -6,12 +6,7 @@ Upgrading from health@1.0 HAL 1. If the device does not have a vendor-specific libhealthd AND does not implement storage-related APIs, just do the following: - 1.1 (recommended) To remove healthd from the build, - PRODUCT_PACKAGES += android.hardware.health@2.0-service.override - DEVICE_FRAMEWORK_MANIFEST_FILE += \ - system/libhidl/vintfdata/manifest_healthd_exclude.xml - 1.2 To keep healthd in the build, - PRODUCT_PACKAGES += android.hardware.health@2.0-service + PRODUCT_PACKAGES += android.hardware.health@2.0-service Otherwise, continue to Step 2. @@ -53,16 +48,12 @@ cc_binary { header_libs: ["libhealthd_headers"], - // Uncomment the following to remove healthd from the build. - // overrides: [ - // "healthd", - // ], + overrides: [ + "healthd", + ], } - 3.1 (recommended) To remove healthd from the build, keep "overrides" - section, and include the following in device.mk: - DEVICE_FRAMEWORK_MANIFEST_FILE += \ - system/libhidl/vintfdata/manifest_healthd_exclude.xml + 3.1 (recommended) To remove healthd from the build, keep "overrides" section. 3.2 To keep healthd in the build, remove "overrides" section. 4. Create device///health/android.hardware.health@2.0-service..rc From 76630c6567ba8de44afac957fa6d6f7360120ea7 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Tue, 22 May 2018 12:52:36 -0700 Subject: [PATCH 027/718] graphics: fix readback buffer tests Make readback buffer support optional. Fix incorrect use of setReadbackBuffer and getReadbackBufferFence. Bug: 80030364 Test: VTS Change-Id: I278a031c3c086ac38c460b7076a2952db57a91a4 --- .../composer/2.2/utils/vts/ComposerVts.cpp | 4 ++ .../include/composer-vts/2.2/ComposerVts.h | 2 + .../VtsHalGraphicsComposerV2_2TargetTest.cpp | 48 +++++++++++++++---- 3 files changed, 46 insertions(+), 8 deletions(-) diff --git a/graphics/composer/2.2/utils/vts/ComposerVts.cpp b/graphics/composer/2.2/utils/vts/ComposerVts.cpp index ae9e430545..f2596a462a 100644 --- a/graphics/composer/2.2/utils/vts/ComposerVts.cpp +++ b/graphics/composer/2.2/utils/vts/ComposerVts.cpp @@ -44,6 +44,10 @@ std::unique_ptr Composer::createClient() { return client; } +sp ComposerClient::getRaw() const { + return mClient; +} + std::vector ComposerClient::getPerFrameMetadataKeys( Display display) { std::vector keys; diff --git a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h index f8bc1d9465..263302124f 100644 --- a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h +++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h @@ -58,6 +58,8 @@ class ComposerClient : public V2_1::vts::ComposerClient { explicit ComposerClient(const sp& client) : V2_1::vts::ComposerClient(client), mClient(client) {} + sp getRaw() const; + void execute(V2_1::vts::TestCommandReader* reader, CommandWriterBase* writer); std::vector getPerFrameMetadataKeys(Display display); diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp index 342b215c53..2f1c66eae3 100644 --- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp +++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp @@ -76,6 +76,11 @@ class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase { // explicitly disable vsync mComposerClient->setVsyncEnabled(mPrimaryDisplay, false); mComposerCallback->setVsyncAllowed(false); + + mComposerClient->getRaw()->getReadbackBufferAttributes( + mPrimaryDisplay, [&](const auto& tmpError, const auto&, const auto&) { + mHasReadbackBuffer = tmpError == Error::NONE; + }); } void TearDown() override { @@ -94,6 +99,7 @@ class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase { sp mComposerCallback; // the first display and is assumed never to be removed Display mPrimaryDisplay; + bool mHasReadbackBuffer; private: Display waitForFirstDisplay() { @@ -255,18 +261,44 @@ TEST_F(GraphicsComposerHidlTest, setPowerMode_2_2) { } TEST_F(GraphicsComposerHidlTest, setReadbackBuffer) { - mComposerClient->setReadbackBuffer(mPrimaryDisplay, nullptr, -1); -} + if (!mHasReadbackBuffer) { + return; + } -TEST_F(GraphicsComposerHidlTest, getReadbackBufferFence) { - int32_t fence; - mComposerClient->getReadbackBufferFence(mPrimaryDisplay, &fence); -} - -TEST_F(GraphicsComposerHidlTest, getReadbackBufferAttributes) { PixelFormat pixelFormat; Dataspace dataspace; mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay, &pixelFormat, &dataspace); + ASSERT_LT(static_cast(0), pixelFormat); + ASSERT_NE(Dataspace::UNKNOWN, dataspace); + + IMapper::BufferDescriptorInfo info{}; + Config config = mComposerClient->getActiveConfig(mPrimaryDisplay); + info.width = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config, + IComposerClient::Attribute::WIDTH); + info.height = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config, + IComposerClient::Attribute::HEIGHT); + info.layerCount = 1; + info.format = pixelFormat; + // BufferUsage::COMPOSER_OUTPUT is missing + info.usage = static_cast(BufferUsage::COMPOSER_OVERLAY | BufferUsage::CPU_READ_OFTEN); + + std::unique_ptr gralloc; + const native_handle_t* buffer; + ASSERT_NO_FATAL_FAILURE(gralloc = std::make_unique()); + ASSERT_NO_FATAL_FAILURE(buffer = gralloc->allocate(info)); + + mComposerClient->setReadbackBuffer(mPrimaryDisplay, buffer, -1); +} + +TEST_F(GraphicsComposerHidlTest, getReadbackBufferFenceInactive) { + if (!mHasReadbackBuffer) { + return; + } + + mComposerClient->getRaw()->getReadbackBufferFence( + mPrimaryDisplay, [&](const auto& tmpError, const auto&) { + ASSERT_EQ(Error::UNSUPPORTED, tmpError) << "readback buffer is active"; + }); } /** From 74274cfbc61dc396c5588adf52ac557086a2134f Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Wed, 23 May 2018 13:35:08 -0700 Subject: [PATCH 028/718] Add configstore@1.1 to current matrix. This was added late in P. Go ahead and require configstore@1.1 since it is built from a universal source for all devices as well. Bug: 69691076 Test: N/A Change-Id: I0203ecc2e70127c11f596896f71c869d12cd3973 --- compatibility_matrices/compatibility_matrix.current.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml index 3b7c90d4ed..1b9ab33d9e 100644 --- a/compatibility_matrices/compatibility_matrix.current.xml +++ b/compatibility_matrices/compatibility_matrix.current.xml @@ -105,7 +105,7 @@ android.hardware.configstore - 1.0 + 1.1 ISurfaceFlingerConfigs default From 513e4e1008742ae5c10649acb7dca4ba72ad4869 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Tue, 29 May 2018 13:24:44 -0700 Subject: [PATCH 029/718] graphics: COLORIMETRIC is optional for HDR modes Bug: 80030364 Test: VTS Change-Id: I2180f18e8742850f728491887475f16b1cad4791 --- current.txt | 2 +- .../VtsHalGraphicsComposerV2_1TargetTest.cpp | 9 ++++++++- graphics/composer/2.2/IComposerClient.hal | 3 ++- .../VtsHalGraphicsComposerV2_2TargetTest.cpp | 19 ++++++++++++++++--- 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/current.txt b/current.txt index f45af27393..413efae211 100644 --- a/current.txt +++ b/current.txt @@ -342,7 +342,7 @@ a830336ac8627d6432cfafb1b884343ad9f885dee0a5323e380e6d3c519156b8 android.hardwar 0b96e0254e2168cfecb30c1ed5fb42681652cc00faa68c6e07568fafe64d1d50 android.hardware.graphics.common@1.1::types 7d2cef99c838fb58038de8bbfd3cdb76ff4797241987077721715297f8d45e34 android.hardware.graphics.common@1.1::types # b/78135149 d9b40a5b09962a5a0780b10fe33a4e607e69e2e088fc83de88a584115b7cb1c0 android.hardware.graphics.composer@2.2::IComposer -e7717f2ff2f6db43b24370ff08e14cd353da3004b32b17740e4a7ed4894b7e45 android.hardware.graphics.composer@2.2::IComposerClient +a2f183f7fcc79aabedaef11095ab223aac0ed5ef984d850893872515e7f560c7 android.hardware.graphics.composer@2.2::IComposerClient dd83be076b6b3f10ed62ab34d8c8b95f2415961fb785200eb842e7bfb2b0ee92 android.hardware.graphics.mapper@2.1::IMapper 675682dd3007805c985eaaec91612abc88f4c25b3431fb84070b7584a1a741fb android.hardware.health@2.0::IHealth 434c4c32c00b0e54bb05e40c79503208b40f786a318029a2a4f66e34f10f2a76 android.hardware.health@2.0::IHealthInfoCallback diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp index 8b8b530a86..72f3f1b4bf 100644 --- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp +++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp @@ -292,9 +292,16 @@ TEST_F(GraphicsComposerHidlTest, SetActiveConfig) { * Test that IComposerClient::setColorMode succeeds for all color modes. */ TEST_F(GraphicsComposerHidlTest, SetColorMode) { + std::unordered_set validModes; + for (auto mode : hidl_enum_range()) { + validModes.insert(mode); + } + std::vector modes = mComposerClient->getColorModes(mPrimaryDisplay); for (auto mode : modes) { - mComposerClient->setColorMode(mPrimaryDisplay, mode); + if (validModes.count(mode)) { + mComposerClient->setColorMode(mPrimaryDisplay, mode); + } } } diff --git a/graphics/composer/2.2/IComposerClient.hal b/graphics/composer/2.2/IComposerClient.hal index 2f0a3cca70..d4a87e6f82 100644 --- a/graphics/composer/2.2/IComposerClient.hal +++ b/graphics/composer/2.2/IComposerClient.hal @@ -355,7 +355,8 @@ interface IComposerClient extends @2.1::IComposerClient { * Returns the render intents supported by the specified display and color * mode. * - * RenderIntent::COLORIMETRIC is always supported. + * For SDR color modes, RenderIntent::COLORIMETRIC must be supported. For + * HDR color modes, RenderIntent::TONE_MAP_COLORIMETRIC must be supported. * * @param display is the display to query. * @param mode is the color mode to query. diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp index 2f1c66eae3..e3b7f55451 100644 --- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp +++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp @@ -345,9 +345,22 @@ TEST_F(GraphicsComposerHidlTest, GetRenderIntent) { for (auto mode : modes) { std::vector intents = mComposerClient->getRenderIntents(mPrimaryDisplay, mode); - auto colorimetricIntent = - std::find(intents.cbegin(), intents.cend(), RenderIntent::COLORIMETRIC); - EXPECT_NE(intents.cend(), colorimetricIntent); + + bool isHdr; + switch (mode) { + case ColorMode::BT2100_PQ: + case ColorMode::BT2100_HLG: + isHdr = true; + break; + default: + isHdr = false; + break; + } + RenderIntent requiredIntent = + isHdr ? RenderIntent::TONE_MAP_COLORIMETRIC : RenderIntent::COLORIMETRIC; + + auto iter = std::find(intents.cbegin(), intents.cend(), requiredIntent); + EXPECT_NE(intents.cend(), iter); } } From a568e530b6e9e19853a421cb64380dba883f59d8 Mon Sep 17 00:00:00 2001 From: Josh Gao Date: Mon, 4 Jun 2018 18:16:00 -0700 Subject: [PATCH 030/718] Fix leaks in wifi_chip.cpp. Use closedir on DIR*, instead of close(dirfd(DIR*)). Bug: http://b/109702699 Test: mma Change-Id: I827d3a414761bb836d5360221296823fcb34cd6b --- wifi/1.2/default/wifi_chip.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/wifi/1.2/default/wifi_chip.cpp b/wifi/1.2/default/wifi_chip.cpp index 3bd05570f6..c4da184884 100644 --- a/wifi/1.2/default/wifi_chip.cpp +++ b/wifi/1.2/default/wifi_chip.cpp @@ -111,16 +111,16 @@ std::string getP2pIfaceName() { bool removeOldFilesInternal() { time_t now = time(0); const time_t delete_files_before = now - kMaxRingBufferFileAgeSeconds; - DIR* dir_dump = opendir(kTombstoneFolderPath); + std::unique_ptr dir_dump( + opendir(kTombstoneFolderPath), closedir); if (!dir_dump) { LOG(ERROR) << "Failed to open directory: " << strerror(errno); return false; } - unique_fd dir_auto_closer(dirfd(dir_dump)); struct dirent* dp; bool success = true; std::list> valid_files; - while ((dp = readdir(dir_dump))) { + while ((dp = readdir(dir_dump.get()))) { if (dp->d_type != DT_REG) { continue; } @@ -246,13 +246,13 @@ bool cpioWriteFileTrailer(int out_fd) { size_t cpioArchiveFilesInDir(int out_fd, const char* input_dir) { struct dirent* dp; size_t n_error = 0; - DIR* dir_dump = opendir(input_dir); + std::unique_ptr dir_dump(opendir(input_dir), + closedir); if (!dir_dump) { LOG(ERROR) << "Failed to open directory: " << strerror(errno); return ++n_error; } - unique_fd dir_auto_closer(dirfd(dir_dump)); - while ((dp = readdir(dir_dump))) { + while ((dp = readdir(dir_dump.get()))) { if (dp->d_type != DT_REG) { continue; } From 0f85dd168438304c40c238dc4a631e2630606bad Mon Sep 17 00:00:00 2001 From: Chao Yan Date: Mon, 4 Jun 2018 14:03:02 -0700 Subject: [PATCH 031/718] Added support for multiple VHAL generators Using priority queue to schedule multiple VHAL event generators Bug: 76017041 Test: atest VehicleHALTest Change-Id: I6bc8071cafd12334dfe37d4f3808530836aec4df --- automotive/vehicle/2.0/default/Android.bp | 1 + .../default/impl/vhal_v2_0/DefaultConfig.h | 22 ++-- .../impl/vhal_v2_0/EmulatedVehicleHal.cpp | 49 +++++-- .../impl/vhal_v2_0/EmulatedVehicleHal.h | 6 +- .../impl/vhal_v2_0/FakeValueGenerator.h | 28 ++-- .../default/impl/vhal_v2_0/GeneratorHub.cpp | 105 +++++++++++++++ .../2.0/default/impl/vhal_v2_0/GeneratorHub.h | 97 ++++++++++++++ .../impl/vhal_v2_0/JsonFakeValueGenerator.cpp | 93 +++++-------- .../impl/vhal_v2_0/JsonFakeValueGenerator.h | 24 +--- .../vhal_v2_0/LinearFakeValueGenerator.cpp | 123 +++++------------- .../impl/vhal_v2_0/LinearFakeValueGenerator.h | 23 ++-- 11 files changed, 352 insertions(+), 219 deletions(-) create mode 100644 automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.cpp create mode 100644 automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.h diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp index 22ab079f33..65e9133b0a 100644 --- a/automotive/vehicle/2.0/default/Android.bp +++ b/automotive/vehicle/2.0/default/Android.bp @@ -64,6 +64,7 @@ cc_library_static { "impl/vhal_v2_0/SocketComm.cpp", "impl/vhal_v2_0/LinearFakeValueGenerator.cpp", "impl/vhal_v2_0/JsonFakeValueGenerator.cpp", + "impl/vhal_v2_0/GeneratorHub.cpp", ], local_include_dirs: ["common/include/vhal_v2_0"], export_include_dirs: ["impl"], 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 4ae94c0011..77885c5341 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 @@ -68,33 +68,39 @@ const int32_t kGenerateFakeDataControllingProperty = enum class FakeDataCommand : int32_t { /** * Starts linear fake data generation. Caller must provide additional data: - * int32Values[1] - VehicleProperty to which command applies + * int32Values[1] - vehicle property to which command applies * int64Values[0] - periodic interval in nanoseconds * floatValues[0] - initial value * floatValues[1] - dispersion defines the min/max value relative to initial value, where * max = initial_value + dispersion, min = initial_value - dispersion. * Dispersion should be non-negative, otherwise the behavior is undefined. * floatValues[2] - increment, with every timer tick the value will be incremented by this - * amount. When reaching to max value, the current value will be set to min. - * It should be non-negative, otherwise the behavior is undefined. + * amount. When reaching to max value, the current value will be set to + * min. It should be non-negative, otherwise the behavior is undefined. */ StartLinear = 0, - /** Stops generating of fake data that was triggered by Start commands. - * int32Values[1] - VehicleProperty to which command applies. VHAL will stop the + /** Stops linear fake data generation that was triggered by StartLinear commands. + * int32Values[1] - vehicle property to which command applies. VHAL will stop the * corresponding linear generation for that property. */ StopLinear = 1, /** - * Starts JSON-based fake data generation. Caller must provide a string value specifying - * the path to fake value JSON file: + * Starts JSON-based fake data generation. It iterates through JSON-encoded VHAL events from a + * file and inject them to VHAL. The iteration can be repeated multiple times or infinitely. + * Caller must provide additional data: + * int32Values[1] - number of iterations. If it is not provided or -1. The iteration will be + * repeated infinite times. * stringValue - path to the fake values JSON file */ StartJson = 2, /** - * Stops JSON-based fake data generation. No additional arguments needed. + * Stops JSON-based fake data generation. As multiple JSON-based generation can happen at the + * same time. Caller must provide the path of fake value JSON file to stop the corresponding + * generation: + * stringValue - path to the fake values JSON file */ StopJson = 3, diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp index 07695bfe7e..0e5897a08c 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp @@ -92,10 +92,8 @@ EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore) mHvacPowerProps(std::begin(kHvacPowerProperties), std::end(kHvacPowerProperties)), mRecurrentTimer( std::bind(&EmulatedVehicleHal::onContinuousPropertyTimer, this, std::placeholders::_1)), - mLinearFakeValueGenerator(std::make_unique( - std::bind(&EmulatedVehicleHal::onFakeValueGenerated, this, std::placeholders::_1))), - mJsonFakeValueGenerator(std::make_unique( - std::bind(&EmulatedVehicleHal::onFakeValueGenerated, this, std::placeholders::_1))) { + mGeneratorHub( + std::bind(&EmulatedVehicleHal::onFakeValueGenerated, this, std::placeholders::_1)) { initStaticConfig(); for (size_t i = 0; i < arraysize(kVehicleProperties); i++) { mPropStore->registerProperty(kVehicleProperties[i].config); @@ -343,19 +341,54 @@ StatusCode EmulatedVehicleHal::handleGenerateFakeDataRequest(const VehiclePropVa switch (command) { case FakeDataCommand::StartLinear: { ALOGI("%s, FakeDataCommand::StartLinear", __func__); - return mLinearFakeValueGenerator->start(request); + if (v.int32Values.size() < 2) { + ALOGE("%s: expected property ID in int32Values", __func__); + return StatusCode::INVALID_ARG; + } + if (!v.int64Values.size()) { + ALOGE("%s: interval is not provided in int64Values", __func__); + return StatusCode::INVALID_ARG; + } + if (v.floatValues.size() < 3) { + ALOGE("%s: expected at least 3 elements in floatValues, got: %zu", __func__, + v.floatValues.size()); + return StatusCode::INVALID_ARG; + } + int32_t cookie = v.int32Values[1]; + mGeneratorHub.registerGenerator(cookie, + std::make_unique(request)); + break; } case FakeDataCommand::StartJson: { ALOGI("%s, FakeDataCommand::StartJson", __func__); - return mJsonFakeValueGenerator->start(request); + if (v.stringValue.empty()) { + ALOGE("%s: path to JSON file is missing", __func__); + return StatusCode::INVALID_ARG; + } + int32_t cookie = std::hash()(v.stringValue); + mGeneratorHub.registerGenerator(cookie, + std::make_unique(request)); + break; } case FakeDataCommand::StopLinear: { ALOGI("%s, FakeDataCommand::StopLinear", __func__); - return mLinearFakeValueGenerator->stop(request); + if (v.int32Values.size() < 2) { + ALOGE("%s: expected property ID in int32Values", __func__); + return StatusCode::INVALID_ARG; + } + int32_t cookie = v.int32Values[1]; + mGeneratorHub.unregisterGenerator(cookie); + break; } case FakeDataCommand::StopJson: { ALOGI("%s, FakeDataCommand::StopJson", __func__); - return mJsonFakeValueGenerator->stop(request); + if (v.stringValue.empty()) { + ALOGE("%s: path to JSON file is missing", __func__); + return StatusCode::INVALID_ARG; + } + int32_t cookie = std::hash()(v.stringValue); + mGeneratorHub.unregisterGenerator(cookie); + break; } case FakeDataCommand::KeyPress: { ALOGI("%s, FakeDataCommand::KeyPress", __func__); diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h index c188aefe20..ec59690ff9 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h @@ -30,8 +30,7 @@ #include "vhal_v2_0/VehiclePropertyStore.h" #include "DefaultConfig.h" -#include "FakeValueGenerator.h" - +#include "GeneratorHub.h" #include "VehicleEmulator.h" namespace android { @@ -85,8 +84,7 @@ private: VehiclePropertyStore* mPropStore; std::unordered_set mHvacPowerProps; RecurrentTimer mRecurrentTimer; - std::unique_ptr mLinearFakeValueGenerator; - std::unique_ptr mJsonFakeValueGenerator; + GeneratorHub mGeneratorHub; }; } // impl diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeValueGenerator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeValueGenerator.h index 1eeb88dffe..d6ad77df73 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeValueGenerator.h +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeValueGenerator.h @@ -27,28 +27,22 @@ namespace V2_0 { namespace impl { -using OnHalEvent = std::function; -using MuxGuard = std::lock_guard; - class FakeValueGenerator { public: virtual ~FakeValueGenerator() = default; - /** - * Starts generating VHAL events - * - * @param request in VehiclePropValue with required information to start fake data generation - * @return StatusCode of the start request - */ - virtual StatusCode start(const VehiclePropValue& request) = 0; - /** - * Stops generating VHAL events - * @param request in VehiclePropValue with required information to stop fake data generation - * @return StatusCode of the stop request - */ - virtual StatusCode stop(const VehiclePropValue& request) = 0; + + virtual VehiclePropValue nextEvent() = 0; + + virtual bool hasNext() = 0; }; -} // impl +using Clock = std::chrono::steady_clock; +using Nanos = std::chrono::nanoseconds; +using TimePoint = std::chrono::time_point; + +using FakeValueGeneratorPtr = std::unique_ptr; + +} // namespace impl } // namespace V2_0 } // namespace vehicle diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.cpp new file mode 100644 index 0000000000..548285abfb --- /dev/null +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.cpp @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "GeneratorHub" + +#include + +#include "GeneratorHub.h" + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace V2_0 { + +namespace impl { + +GeneratorHub::GeneratorHub(const OnHalEvent& onHalEvent) + : mOnHalEvent(onHalEvent), mThread(&GeneratorHub::run, this) {} + +void GeneratorHub::registerGenerator(int32_t cookie, FakeValueGeneratorPtr generator) { + { + std::lock_guard g(mLock); + // Register only if the generator can produce event + if (generator->hasNext()) { + // Push the next event if it is a new generator + if (mGenerators.find(cookie) == mGenerators.end()) { + ALOGI("%s: Registering new generator, cookie: %d", __func__, cookie); + mEventQueue.push({cookie, generator->nextEvent()}); + } + mGenerators[cookie] = std::move(generator); + ALOGI("%s: Registered generator, cookie: %d", __func__, cookie); + } + } + mCond.notify_one(); +} + +void GeneratorHub::unregisterGenerator(int32_t cookie) { + { + std::lock_guard g(mLock); + mGenerators.erase(cookie); + } + mCond.notify_one(); + ALOGI("%s: Unregistered generator, cookie: %d", __func__, cookie); +} + +void GeneratorHub::run() { + while (true) { + std::unique_lock g(mLock); + // Pop events whose generator does not exist (may be already unregistered) + while (!mEventQueue.empty() + && mGenerators.find(mEventQueue.top().cookie) == mGenerators.end()) { + mEventQueue.pop(); + } + // Wait until event queue is not empty + mCond.wait(g, [this] { return !mEventQueue.empty(); }); + + const VhalEvent& curEvent = mEventQueue.top(); + + TimePoint eventTime(Nanos(curEvent.val.timestamp)); + // Wait until the soonest event happen + if (mCond.wait_until(g, eventTime) != std::cv_status::timeout) { + // It is possible that a new generator is registered and produced a sooner event, or current + // generator is unregistered, in this case the thread will re-evaluate the soonest event + ALOGI("Something happened while waiting"); + continue; + } + // Now it's time to handle current event. + mOnHalEvent(curEvent.val); + // Update queue by popping current event and producing next event from the same generator + int32_t cookie = curEvent.cookie; + mEventQueue.pop(); + if (hasNext(cookie)) { + mEventQueue.push({cookie, mGenerators[cookie]->nextEvent()}); + } else { + ALOGI("%s: Generator ended, unregister it, cookie: %d", __func__, cookie); + mGenerators.erase(cookie); + } + } +} + +bool GeneratorHub::hasNext(int32_t cookie) { + return mGenerators.find(cookie) != mGenerators.end() && mGenerators[cookie]->hasNext(); +} + +} // namespace impl + +} // namespace V2_0 +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.h new file mode 100644 index 0000000000..dcf6a4f06e --- /dev/null +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.h @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_automotive_vehicle_V2_0_impl_GeneratorHub_H_ +#define android_hardware_automotive_vehicle_V2_0_impl_GeneratorHub_H_ + +#include +#include +#include +#include +#include +#include +#include + +#include "FakeValueGenerator.h" + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace V2_0 { + +namespace impl { + +/** + * This is the scheduler for all VHAL event generators. It manages all generators and uses priority + * queue to maintain generated events ordered by timestamp. The scheduler uses a single thread to + * keep querying and updating the event queue to make sure events from all generators are produced + * in order. + */ +class GeneratorHub { +private: + struct VhalEvent { + int32_t cookie; // Cookie is used to find the associated generator. + VehiclePropValue val; + }; + // Comparator used by priority queue to keep track of soonest event. + struct GreaterByTime { + bool operator()(const VhalEvent& lhs, const VhalEvent& rhs) const { + return lhs.val.timestamp > rhs.val.timestamp; + } + }; + + using OnHalEvent = std::function; + +public: + GeneratorHub(const OnHalEvent& onHalEvent); + ~GeneratorHub() = default; + + /** + * Register a new generator. The generator will be discarded if it could not produce next event. + * The existing generator will be overridden if it has the same cookie. + */ + void registerGenerator(int32_t cookie, FakeValueGeneratorPtr generator); + + void unregisterGenerator(int32_t cookie); + +private: + /** + * Main loop of the single thread to producing event and updating event queue. + */ + void run(); + + bool hasNext(int32_t cookie); + +private: + std::priority_queue, GreaterByTime> mEventQueue; + std::unordered_map mGenerators; + OnHalEvent mOnHalEvent; + + mutable std::mutex mLock; + std::condition_variable mCond; + std::thread mThread; +}; + +} // namespace impl + +} // namespace V2_0 +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_automotive_vehicle_V2_0_impl_GeneratorHub_H_ diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp index 88b8f865c5..c293c0af44 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp @@ -31,57 +31,48 @@ namespace V2_0 { namespace impl { -JsonFakeValueGenerator::JsonFakeValueGenerator(const OnHalEvent& onHalEvent) - : mOnHalEvent(onHalEvent), mThread(&JsonFakeValueGenerator::loop, this) {} - -JsonFakeValueGenerator::~JsonFakeValueGenerator() { - mStopRequested = true; - { - MuxGuard g(mLock); - mGenCfg.index = 0; - mGenCfg.events.clear(); - } - mCond.notify_one(); - if (mThread.joinable()) { - mThread.join(); - } -} - -StatusCode JsonFakeValueGenerator::start(const VehiclePropValue& request) { +JsonFakeValueGenerator::JsonFakeValueGenerator(const VehiclePropValue& request) { const auto& v = request.value; - if (v.stringValue.empty()) { - ALOGE("%s: path to JSON file is missing", __func__); - return StatusCode::INVALID_ARG; - } const char* file = v.stringValue.c_str(); std::ifstream ifs(file); if (!ifs) { ALOGE("%s: couldn't open %s for parsing.", __func__, file); - return StatusCode::INTERNAL_ERROR; } - std::vector fakeVhalEvents = parseFakeValueJson(ifs); - - { - MuxGuard g(mLock); - mGenCfg = {0, fakeVhalEvents}; - } - mCond.notify_one(); - return StatusCode::OK; + mGenCfg = { + .index = 0, + .events = parseFakeValueJson(ifs), + }; + // Iterate infinitely if repetition number is not provided + mNumOfIterations = v.int32Values.size() < 2 ? -1 : v.int32Values[1]; } -StatusCode JsonFakeValueGenerator::stop(const VehiclePropValue& request) { - const auto& v = request.value; - if (!v.stringValue.empty()) { - ALOGI("%s: %s", __func__, v.stringValue.c_str()); +VehiclePropValue JsonFakeValueGenerator::nextEvent() { + VehiclePropValue generatedValue; + if (!hasNext()) { + return generatedValue; } + TimePoint eventTime = Clock::now(); + if (mGenCfg.index != 0) { + // All events (start from 2nd one) are supposed to happen in the future with a delay + // equals to the duration between previous and current event. + eventTime += Nanos(mGenCfg.events[mGenCfg.index].timestamp - + mGenCfg.events[mGenCfg.index - 1].timestamp); + } + generatedValue = mGenCfg.events[mGenCfg.index]; + generatedValue.timestamp = eventTime.time_since_epoch().count(); - { - MuxGuard g(mLock); + mGenCfg.index++; + if (mGenCfg.index == mGenCfg.events.size()) { mGenCfg.index = 0; - mGenCfg.events.clear(); + if (mNumOfIterations > 0) { + mNumOfIterations--; + } } - mCond.notify_one(); - return StatusCode::OK; + return generatedValue; +} + +bool JsonFakeValueGenerator::hasNext() { + return mNumOfIterations != 0 && mGenCfg.events.size() > 0; } std::vector JsonFakeValueGenerator::parseFakeValueJson(std::istream& is) { @@ -141,30 +132,6 @@ std::vector JsonFakeValueGenerator::parseFakeValueJson(std::is return fakeVhalEvents; } -void JsonFakeValueGenerator::loop() { - static constexpr auto kInvalidTime = TimePoint(Nanos::max()); - - while (!mStopRequested) { - auto nextEventTime = kInvalidTime; - { - MuxGuard g(mLock); - if (mGenCfg.index < mGenCfg.events.size()) { - mOnHalEvent(mGenCfg.events[mGenCfg.index]); - } - if (!mGenCfg.events.empty() && mGenCfg.index < mGenCfg.events.size() - 1) { - Nanos intervalNano = - static_cast(mGenCfg.events[mGenCfg.index + 1].timestamp - - mGenCfg.events[mGenCfg.index].timestamp); - nextEventTime = Clock::now() + intervalNano; - } - mGenCfg.index++; - } - - std::unique_lock g(mLock); - mCond.wait_until(g, nextEventTime); - } -} - } // namespace impl } // namespace V2_0 diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h index 51da4c5383..43c8b9dc53 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h @@ -17,11 +17,8 @@ #ifndef android_hardware_automotive_vehicle_V2_0_impl_JsonFakeValueGenerator_H_ #define android_hardware_automotive_vehicle_V2_0_impl_JsonFakeValueGenerator_H_ -#include #include -#include #include -#include #include @@ -37,32 +34,25 @@ namespace impl { class JsonFakeValueGenerator : public FakeValueGenerator { private: - using Nanos = std::chrono::nanoseconds; - using Clock = std::chrono::steady_clock; - using TimePoint = std::chrono::time_point; - struct GeneratorCfg { size_t index; std::vector events; }; public: - JsonFakeValueGenerator(const OnHalEvent& onHalEvent); - ~JsonFakeValueGenerator(); - StatusCode start(const VehiclePropValue& request) override; - StatusCode stop(const VehiclePropValue& request) override; + JsonFakeValueGenerator(const VehiclePropValue& request); + ~JsonFakeValueGenerator() = default; + + VehiclePropValue nextEvent(); + + bool hasNext(); private: std::vector parseFakeValueJson(std::istream& is); - void loop(); private: - OnHalEvent mOnHalEvent; - std::thread mThread; - mutable std::mutex mLock; - std::condition_variable mCond; GeneratorCfg mGenCfg; - std::atomic_bool mStopRequested{false}; + int32_t mNumOfIterations; }; } // namespace impl diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp index 8cb9322fa6..7bdc97cd2b 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp @@ -29,101 +29,48 @@ namespace V2_0 { namespace impl { -LinearFakeValueGenerator::LinearFakeValueGenerator(const OnHalEvent& onHalEvent) - : mOnHalEvent(onHalEvent), - mRecurrentTimer(std::bind(&LinearFakeValueGenerator::onTimer, this, std::placeholders::_1)) {} - -StatusCode LinearFakeValueGenerator::start(const VehiclePropValue& request) { +LinearFakeValueGenerator::LinearFakeValueGenerator(const VehiclePropValue& request) { const auto& v = request.value; - if (v.int32Values.size() < 2) { - ALOGE("%s: expected property ID in int32Values", __func__); - return StatusCode::INVALID_ARG; - } - int32_t propId = v.int32Values[1]; - - if (!v.int64Values.size()) { - ALOGE("%s: interval is not provided in int64Values", __func__); - return StatusCode::INVALID_ARG; - } - auto interval = std::chrono::nanoseconds(v.int64Values[0]); - - if (v.floatValues.size() < 3) { - ALOGE("%s: expected at least 3 elements in floatValues, got: %zu", __func__, - v.floatValues.size()); - return StatusCode::INVALID_ARG; - } - float initialValue = v.floatValues[0]; - float dispersion = v.floatValues[1]; - float increment = v.floatValues[2]; - - MuxGuard g(mLock); - removeLocked(propId); - mGenCfg.insert({propId, GeneratorCfg{ - .initialValue = initialValue, - .currentValue = initialValue, - .dispersion = dispersion, - .increment = increment,}}); - - mRecurrentTimer.registerRecurrentEvent(interval, propId); - return StatusCode::OK; + mGenCfg = GeneratorCfg{ + .propId = v.int32Values[1], + .initialValue = v.floatValues[0], + .currentValue = v.floatValues[0], + .dispersion = v.floatValues[1], + .increment = v.floatValues[2], + .interval = Nanos(v.int64Values[0]), + }; } -StatusCode LinearFakeValueGenerator::stop(const VehiclePropValue& request) { - const auto& v = request.value; - if (v.int32Values.size() < 2) { - ALOGE("%s: expected property ID in int32Values", __func__); - return StatusCode::INVALID_ARG; +VehiclePropValue LinearFakeValueGenerator::nextEvent() { + mGenCfg.currentValue += mGenCfg.increment; + if (mGenCfg.currentValue > mGenCfg.initialValue + mGenCfg.dispersion) { + mGenCfg.currentValue = mGenCfg.initialValue - mGenCfg.dispersion; } - int32_t propId = v.int32Values[1]; - - MuxGuard g(mLock); - if (propId == 0) { - // Remove all. - for (auto&& it : mGenCfg) { - removeLocked(it.first); - } - } else { - removeLocked(propId); + VehiclePropValue event = {.prop = mGenCfg.propId}; + auto& value = event.value; + switch (getPropType(event.prop)) { + case VehiclePropertyType::INT32: + value.int32Values.resize(1); + value.int32Values[0] = static_cast(mGenCfg.currentValue); + break; + case VehiclePropertyType::INT64: + value.int64Values.resize(1); + value.int64Values[0] = static_cast(mGenCfg.currentValue); + break; + case VehiclePropertyType::FLOAT: + value.floatValues.resize(1); + value.floatValues[0] = mGenCfg.currentValue; + break; + default: + ALOGE("%s: unsupported property type for 0x%x", __func__, event.prop); } - return StatusCode::OK; + TimePoint eventTime = Clock::now() + mGenCfg.interval; + event.timestamp = eventTime.time_since_epoch().count(); + return event; } -void LinearFakeValueGenerator::removeLocked(int propId) { - if (mGenCfg.erase(propId)) { - mRecurrentTimer.unregisterRecurrentEvent(propId); - } -} - -void LinearFakeValueGenerator::onTimer(const std::vector& properties) { - MuxGuard g(mLock); - - for (int32_t propId : properties) { - auto& cfg = mGenCfg[propId]; - cfg.currentValue += cfg.increment; - if (cfg.currentValue > cfg.initialValue + cfg.dispersion) { - cfg.currentValue = cfg.initialValue - cfg.dispersion; - } - VehiclePropValue event = {.prop = propId}; - auto& value = event.value; - switch (getPropType(event.prop)) { - case VehiclePropertyType::INT32: - value.int32Values.resize(1); - value.int32Values[0] = static_cast(cfg.currentValue); - break; - case VehiclePropertyType::INT64: - value.int64Values.resize(1); - value.int64Values[0] = static_cast(cfg.currentValue); - break; - case VehiclePropertyType::FLOAT: - value.floatValues.resize(1); - value.floatValues[0] = cfg.currentValue; - break; - default: - ALOGE("%s: unsupported property type for 0x%x", __func__, event.prop); - continue; - } - mOnHalEvent(event); - } +bool LinearFakeValueGenerator::hasNext() { + return true; } } // namespace impl diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.h index fe6d097962..d3b666dd9d 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.h +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.h @@ -17,8 +17,6 @@ #ifndef android_hardware_automotive_vehicle_V2_0_impl_LinearFakeValueGenerator_H_ #define android_hardware_automotive_vehicle_V2_0_impl_LinearFakeValueGenerator_H_ -#include - #include "FakeValueGenerator.h" namespace android { @@ -36,27 +34,24 @@ private: // to the client. struct GeneratorCfg { - float initialValue; // + int32_t propId; + float initialValue; float currentValue; // Should be in range (initialValue +/- dispersion). float dispersion; // Defines minimum and maximum value based on initial value. float increment; // Value that we will be added to currentValue with each timer tick. + Nanos interval; }; public: - LinearFakeValueGenerator(const OnHalEvent& onHalEvent); + LinearFakeValueGenerator(const VehiclePropValue& request); ~LinearFakeValueGenerator() = default; - StatusCode start(const VehiclePropValue& request) override; - StatusCode stop(const VehiclePropValue& request) override; + + VehiclePropValue nextEvent(); + + bool hasNext(); private: - void removeLocked(int propId); - void onTimer(const std::vector& properties); - -private: - mutable std::mutex mLock; - OnHalEvent mOnHalEvent; - RecurrentTimer mRecurrentTimer; - std::unordered_map mGenCfg; + GeneratorCfg mGenCfg; }; } // namespace impl From ae3196f7578877f00c7529d36e0a4dc207287574 Mon Sep 17 00:00:00 2001 From: jiabin Date: Fri, 8 Jun 2018 14:05:12 -0700 Subject: [PATCH 032/718] Fix getActiveMicrophones vts failure. As there could be no mic on the device, the active microphones may not always exist. With currently implementation in qcom hal, we need to start the stream to have active microphones. In that case, just check the return value of the call. Bug: 109787938 Test: vts-tradefed run vts --module VtsHalAudioV4_0Target Change-Id: Ia9f5160a278d6c788f8f5eb17b8b276fe1d66076 --- audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp b/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp index dab9f7c44e..9be9b12bfd 100644 --- a/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp +++ b/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp @@ -1100,11 +1100,10 @@ TEST_P(InputStreamTest, updateSinkMetadata) { } TEST_P(InputStreamTest, getActiveMicrophones) { - doc::test("Getting active microphones should always succeed"); + doc::test("Active microphones of a non started stream may not be retrievable"); hidl_vec microphones; - ASSERT_OK(device->getMicrophones(returnIn(res, microphones))); - ASSERT_OK(res); - ASSERT_TRUE(microphones.size() > 0); + ASSERT_OK(stream->getActiveMicrophones(returnIn(res, microphones))); + ASSERT_RESULT(okOrNotSupported, res); } ////////////////////////////////////////////////////////////////////////////// From b7dc1331e75a94ece0c3c84e20b6ab299102e857 Mon Sep 17 00:00:00 2001 From: Vishal Agarwal Date: Tue, 5 Jun 2018 18:42:01 -0700 Subject: [PATCH 033/718] Add VTS test to verify scheduling capability 2018+ devices must support GNSS capability scheduling Test results: go/vts-review-bucket/pi-dev/4267645 Bug: 109642198 Test: atest VtsHalGnssV1_0TargetTest Change-Id: I7394674abca8f8c40ab30403be6b41bbbb279956 --- gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp b/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp index 010a46dbc2..608ee70065 100644 --- a/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp +++ b/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp @@ -472,6 +472,16 @@ TEST_F(GnssHalTest, MeasurementCapabilites) { } } +/* + * SchedulingCapabilities: + * Verifies that 2018+ hardware supports Scheduling capabilities. + */ +TEST_F(GnssHalTest, SchedulingCapabilities) { + if (info_called_count_ > 0 && last_info_.yearOfHw >= 2018) { + EXPECT_TRUE(last_capabilities_ & IGnssCallback::Capabilities::SCHEDULING); + } +} + int main(int argc, char** argv) { ::testing::AddGlobalTestEnvironment(GnssHidlEnvironment::Instance()); ::testing::InitGoogleTest(&argc, argv); From e3e4a4f9279728abc1d7918e14366eaf37a96d21 Mon Sep 17 00:00:00 2001 From: David Gross Date: Wed, 6 Jun 2018 19:57:27 -0700 Subject: [PATCH 034/718] Documentation improvements. Fix Model::pools documentation. Specify that an output cannot overlap with an output/input/constant. Document circumstances under which a prepared model should be expected to execute correctly. Bug: 87805381 Bug: 79888238 Bug: 77237715 Test: mma at tree root Change-Id: Ibf3daacad79f1d7e6127acf3887bd98b7c6bdf4e (cherry picked from commit 2c030290542bdefe0494d2fd9b6f2315b9e12b68) --- current.txt | 5 +++++ neuralnetworks/1.0/IPreparedModel.hal | 6 ++++++ neuralnetworks/1.0/types.hal | 6 ++++-- neuralnetworks/1.1/types.hal | 3 +-- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/current.txt b/current.txt index cc15322b83..f9d7b6e87e 100644 --- a/current.txt +++ b/current.txt @@ -380,3 +380,8 @@ e362203b941f18bd4cba29a62adfa02453ed00d6be5b72cdb6c4d7e0bf394a40 android.hardwar 21757d0e5dd4b7e4bd981a4a20531bca3c32271ad9777b17b74eb5a1ea508384 android.hardware.wifi.supplicant@1.1::ISupplicantStaIface cd4330c3196bda1d642a32abfe23a7d64ebfbda721940643af6867af3b3f0aa9 android.hardware.wifi.supplicant@1.1::ISupplicantStaIfaceCallback 10ff2fae516346b86121368ce5790d5accdfcb73983246b813f3d488b66db45a android.hardware.wifi.supplicant@1.1::ISupplicantStaNetwork + +# ABI preserving changes to HALs during Android Q +574e8f1499436fb4075894dcae0b36682427956ecb114f17f1fe22d116a83c6b android.hardware.neuralnetworks@1.0::IPreparedModel +b07802a3433a9abec67a41525dc04eab9efb62760414e1d37e2f72cc5ae9cb8a android.hardware.neuralnetworks@1.0::types +bf18f51bfee84461f9831f3754f5c68ce2b29e42fe9d59ef8a33163e77f8edbf android.hardware.neuralnetworks@1.1::types diff --git a/neuralnetworks/1.0/IPreparedModel.hal b/neuralnetworks/1.0/IPreparedModel.hal index ee406fb79b..ecaa7f830a 100644 --- a/neuralnetworks/1.0/IPreparedModel.hal +++ b/neuralnetworks/1.0/IPreparedModel.hal @@ -42,6 +42,12 @@ interface IPreparedModel { * execute function. This callback must be provided with the ErrorStatus of * the execution. * + * If the prepared model was prepared from a model wherein all + * tensor operands have fully specified dimensions, and the inputs + * to the function are valid, then the execution should launch + * and complete successfully (ErrorStatus::NONE). There must be + * no failure unless the device itself is in a bad state. + * * Multiple threads can call the execute function on the same IPreparedModel * object concurrently with different requests. * diff --git a/neuralnetworks/1.0/types.hal b/neuralnetworks/1.0/types.hal index 1ae1726ca3..5a40e4e289 100644 --- a/neuralnetworks/1.0/types.hal +++ b/neuralnetworks/1.0/types.hal @@ -1668,8 +1668,7 @@ struct Model { vec operandValues; /** - * A collection of shared memory pools containing operand data that were - * registered by the model. + * A collection of shared memory pools containing operand values. * * An operand's value must be located here if and only if Operand::lifetime * equals OperandLifeTime::CONSTANT_REFERENCE. @@ -1721,6 +1720,9 @@ struct RequestArgument { * 1) Provides the input and output data to be used when executing the model. * 2) Specifies any updates to the input operand metadata that were left * unspecified at model preparation time. + * + * An output must not overlap with any other output, with an input, or + * with an operand of lifetime CONSTANT_REFERENCE. */ struct Request { /** diff --git a/neuralnetworks/1.1/types.hal b/neuralnetworks/1.1/types.hal index e4c656db44..b5718f352c 100644 --- a/neuralnetworks/1.1/types.hal +++ b/neuralnetworks/1.1/types.hal @@ -404,8 +404,7 @@ struct Model { vec operandValues; /** - * A collection of shared memory pools containing operand data that were - * registered by the model. + * A collection of shared memory pools containing operand values. * * An operand's value must be located here if and only if Operand::lifetime * equals OperandLifeTime::CONSTANT_REFERENCE. From 5aa15880139dc3ddf928bb3ab6d52f975bb83c61 Mon Sep 17 00:00:00 2001 From: David Gross Date: Thu, 7 Jun 2018 16:09:59 -0700 Subject: [PATCH 035/718] Documentation improvements. Document that every model must have at least one input and one output. Document graph constraints. Elaborate a bit on "execution order". Indicate how operands of different lifetimes are defined (or not). Fix ANEURALNETWORKS_L2_NORMALIZATION documentation for output shape. ANEURALNETWORKS_SPACE_TO_DEPTH has inconsistent names for dimensions. ANEURALNETWORKS_PAD documentation doesn't clearly describe rank or dimensions of output tensor. Bug: 66478689 Bug: 67601776 Bug: 69631404 Bug: 79482779 Bug: 79539157 Bug: 79539928 Test: mma at tree root Change-Id: I6227bea2a486d4b45022d590915e10a124d323d4 (cherry picked from commit aeb1a6cb0160b00ecd5e321f01d8722482c221a7) --- current.txt | 4 ++-- neuralnetworks/1.0/types.hal | 36 +++++++++++++++++++++++------------- neuralnetworks/1.1/types.hal | 20 ++++++++++++++------ 3 files changed, 39 insertions(+), 21 deletions(-) diff --git a/current.txt b/current.txt index f9d7b6e87e..978f6c6aae 100644 --- a/current.txt +++ b/current.txt @@ -383,5 +383,5 @@ cd4330c3196bda1d642a32abfe23a7d64ebfbda721940643af6867af3b3f0aa9 android.hardwar # ABI preserving changes to HALs during Android Q 574e8f1499436fb4075894dcae0b36682427956ecb114f17f1fe22d116a83c6b android.hardware.neuralnetworks@1.0::IPreparedModel -b07802a3433a9abec67a41525dc04eab9efb62760414e1d37e2f72cc5ae9cb8a android.hardware.neuralnetworks@1.0::types -bf18f51bfee84461f9831f3754f5c68ce2b29e42fe9d59ef8a33163e77f8edbf android.hardware.neuralnetworks@1.1::types +1a5ae9793223658174258b523763c557abad6fb917df0b8e3cc097fc89035811 android.hardware.neuralnetworks@1.0::types +4310eb8272f085914952f3bfb73a8f8bb477a80e8b93596f0ea5acb58546b66d android.hardware.neuralnetworks@1.1::types diff --git a/neuralnetworks/1.0/types.hal b/neuralnetworks/1.0/types.hal index 5a40e4e289..887fdf1b84 100644 --- a/neuralnetworks/1.0/types.hal +++ b/neuralnetworks/1.0/types.hal @@ -596,8 +596,8 @@ enum OperationType : int32_t { * * 0: A 4-D tensor, of shape [batches, height, width, depth]. * * Outputs: - * * 0: The output 4-D tensor, of shape - * [batches, out_height, out_width, depth]. + * * 0: The output 4-D tensor, of the same shape as input + * [batches, height, width, depth]. */ L2_NORMALIZATION = 11, @@ -1282,8 +1282,8 @@ enum OperationType : int32_t { * input height and width. * * Outputs: - * * 0: The output 4-D tensor, of shape [batch, height/block_size, - * width/block_size, depth*block_size*block_size]. + * * 0: The output 4-D tensor, of shape [batches, height/block_size, + * width/block_size, depth_in*block_size*block_size]. */ SPACE_TO_DEPTH = 26, @@ -1410,28 +1410,36 @@ enum FusedActivationFunc : int32_t { enum OperandLifeTime : int32_t { /** * The operand is internal to the model. It's created by an operation and - * consumed by other operations. + * consumed by other operations. It must be an output operand of + * exactly one operation. */ TEMPORARY_VARIABLE, /** - * The operand is an input of the model. An operand can't be both - * input and output of a model. + * The operand is an input of the model. It must not be an output + * operand of any operation. + * + * An operand can't be both input and output of a model. */ MODEL_INPUT, /** - * The operand is an output of the model. + * The operand is an output of the model. It must be an output + * operand of exactly one operation. + * + * An operand can't be both input and output of a model. */ MODEL_OUTPUT, /** - * The operand is a constant found in Model.operandValues. + * The operand is a constant found in Model.operandValues. It must + * not be an output operand of any operation. */ CONSTANT_COPY, /** - * The operand is a constant that was specified via a Memory object. + * The operand is a constant that was specified via a Memory + * object. It must not be an output operand of any operation. */ CONSTANT_REFERENCE, @@ -1641,19 +1649,21 @@ struct Model { /** * All operations included in the model. * - * The operations are sorted into execution order. + * The operations are sorted into execution order. Every operand + * with lifetime MODEL_OUTPUT or TEMPORARY_VARIABLE must be + * written before it is read. */ vec operations; /** - * Input indexes of the model. + * Input indexes of the model. There must be at least one. * * Each value corresponds to the index of the operand in "operands". */ vec inputIndexes; /** - * Output indexes of the model. + * Output indexes of the model. There must be at least one. * * Each value corresponds to the index of the operand in "operands". */ diff --git a/neuralnetworks/1.1/types.hal b/neuralnetworks/1.1/types.hal index b5718f352c..7b2a21a8c8 100644 --- a/neuralnetworks/1.1/types.hal +++ b/neuralnetworks/1.1/types.hal @@ -137,13 +137,19 @@ enum OperationType : @1.0::OperationType { * * 1: A 2-D Tensor of {@link OperandType::TENSOR_INT32}, the paddings * for each spatial dimension of the input tensor. The shape of the * tensor must be {rank(input0), 2}. - * padding[i, 0] specifies the number of element to be padded in the + * padding[i, 0] specifies the number of elements to be padded in the * front of dimension i. - * padding[i, 1] specifies the number of element to be padded after the + * padding[i, 1] specifies the number of elements to be padded after the * end of dimension i. * * Outputs: - * * 0: A tensor of the same {@link OperandType} as input0. + * * 0: A tensor of the same {@link OperandType} as input0. The + * output tensor has the same rank as input0, and each + * dimension of the output tensor has the same size as the + * corresponding dimension of the input tensor plus the size + * of the padding: + * output0.dimension[i] = + * padding[i, 0] + input0.dimension[i] + padding[i, 1] */ PAD = 32, @@ -377,19 +383,21 @@ struct Model { /** * All operations included in the model. * - * The operations are sorted into execution order. + * The operations are sorted into execution order. Every operand + * with lifetime MODEL_OUTPUT or TEMPORARY_VARIABLE must be + * written before it is read. */ vec operations; /** - * Input indexes of the model. + * Input indexes of the model. There must be at least one. * * Each value corresponds to the index of the operand in "operands". */ vec inputIndexes; /** - * Output indexes of the model. + * Output indexes of the model. There must be at least one. * * Each value corresponds to the index of the operand in "operands". */ From 1f7007465ddcacd4ff45f46ff8c4381507a96607 Mon Sep 17 00:00:00 2001 From: Zachary Iqbal Date: Tue, 24 Apr 2018 23:42:21 -0700 Subject: [PATCH 036/718] Added initial HIDL interface for the biometric face HAL. Notes: - Added a basic interface, a stub callback interface and a stubs for needed public types. - Ran make hidl-gen -j64 && hardware/interfaces/update-makefiles.sh to create build files for the interface. Bug: 79577138 Test: None added. This commit simply adds a new interface. Change-Id: I14b7238dd9ee1076f77c1b60117bdaa156a4f0f5 --- biometrics/face/1.0/Android.bp | 26 ++ biometrics/face/1.0/IBiometricsFace.hal | 191 +++++++++++++ .../1.0/IBiometricsFaceClientCallback.hal | 116 ++++++++ biometrics/face/1.0/types.hal | 255 ++++++++++++++++++ 4 files changed, 588 insertions(+) create mode 100644 biometrics/face/1.0/Android.bp create mode 100644 biometrics/face/1.0/IBiometricsFace.hal create mode 100644 biometrics/face/1.0/IBiometricsFaceClientCallback.hal create mode 100644 biometrics/face/1.0/types.hal diff --git a/biometrics/face/1.0/Android.bp b/biometrics/face/1.0/Android.bp new file mode 100644 index 0000000000..61bf247786 --- /dev/null +++ b/biometrics/face/1.0/Android.bp @@ -0,0 +1,26 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +hidl_interface { + name: "android.hardware.biometrics.face@1.0", + root: "android.hardware", + vndk: { + enabled: true, + }, + srcs: [ + "types.hal", + "IBiometricsFace.hal", + "IBiometricsFaceClientCallback.hal", + ], + interfaces: [ + "android.hidl.base@1.0", + ], + types: [ + "FaceAcquiredInfo", + "FaceError", + "OptionalUint64", + "Status", + "UserHandle", + ], + gen_java: true, +} + diff --git a/biometrics/face/1.0/IBiometricsFace.hal b/biometrics/face/1.0/IBiometricsFace.hal new file mode 100644 index 0000000000..fbdb210694 --- /dev/null +++ b/biometrics/face/1.0/IBiometricsFace.hal @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics.face@1.0; + +import IBiometricsFaceClientCallback; + +// TODO(b/78538290): Update comments with state machine transitions when ready. +// TODO(b/78537981): Update comments with callback interaction contract. +// TODO(b/79496983): Update comments with status returns fully enumerated. +/** + * The HAL interface for biometric face authentication. + */ +interface IBiometricsFace { + + /** + * Sets the current client callback. + * + * Registers a user function that must receive notifications from the HAL. + * There is usually only one client (FaceService). This call must block + * if the HAL state machine is in busy state until the HAL leaves the + * busy state. + * + * All callback methods pass a deviceId to differentiate callback + * invocations in the case where multiple sensors exist. + * + * @param clientCallback The client defined callback to register. + * @return result, with its "value" parameter representing a "deviceId", + * which must be unique for a given sensor. + */ + @callflow(next={"setActiveUser"}) + @entry + setCallback(IBiometricsFaceClientCallback clientCallback) + generates (OptionalUint64 result); + + /** + * Sets the active user, which all subsequent HAL operations are applied to. + * + * HAL service implementors must ensure that operations are restricted to + * the given user. Clients must not call any part of this interface, except + * for setCallback(), without first having set an active user. The + * implementation is responsible for cancelling the current operation and + * returning to the idle state. Calling this method with the same userId + * should have no effect on the state machine. + * + * @param userId A non-negative user identifier that must be unique and + * persistent for a given user. + * @param storePath filesystem path to the template storage directory. + */ + @callflow(next={"authenticate", "preEnroll", "enumerate", "remove"}) + setActiveUser(int32_t userId, string storePath) generates (Status status); + + /** + * Begins a pre-enrollment request. + * + * Generates a unique and cryptographically secure random token used to + * indicate the start of an enrollment transaction. preEnroll() and + * postEnroll() specify a pin/pattern/password cleared time window where + * enrollment is allowed. + * + * preEnroll() generates a challenge which must then be wrapped by the + * gatekeeper after verifying a successful strong authentication attempt, + * which generates a Hardware Authentication Token. The challenge prevents + * spoofing and replay attacks and ensures that we only update a user’s face + * template if the operation was preceded by some kind of strong credential + * confirmation (e.g. device password). + * + * @return result, with its "value" parameter representing a "challenge": a + * unique and cryptographically secure random token. + */ + @callflow(next={"enroll", "postEnroll"}) + preEnroll() generates (OptionalUint64 result); + + /** + * Enrolls a user's face. + * + * Note that this interface permits implementations where multiple faces can + * be enrolled for a single user. However, allowing multiple faces to be + * enrolled can be a severe security vulnerability and hence, most + * implementations must ensure that only a single face be enrolled at a + * given time. Multi-enrollment must only be used where there is a clear + * necessity for a shared use case, e.g. TVs or cars. + * + * Note that the Hardware Authentication Token must still be valid after + * this call, and must be explicitly invalidated by a call to postEnroll(). + * This allows clients to immediately reattempt enrollment (for example, if + * a user wasn’t satisfied with their enrollment) without having to go + * through another strong authentication flow. + * + * This method triggers the IBiometricsFaceClientCallback#onEnrollResult() + * method. + * + * @param hat A valid Hardware Authentication Token, generated as a result + * of a preEnroll() challenge being wrapped by the gatekeeper after a + * sucessful strong authentication request. + * @param timeoutSec A timeout in seconds, after which this enrollment + * attempt is cancelled. Note that the client still needs to + * call postEnroll() to terminate the enrollment session. + * @return status The status of this method call. + */ + @callflow(next={"cancel", "enroll", "postEnroll", "remove"}) + enroll(vec hat, uint32_t timeoutSec) generates (Status status); + + /** + * Finishes the enrollment session and invalidates the challenge generated + * by preEnroll(). + * + * Clients must call this method once enrollment is complete, and the user's + * face template no longer needs to be updated. + * + * @return status The status of this method call. + */ + @callflow(next={"authenticate", "setActiveUser", "enumerate", "remove"}) + postEnroll() generates (Status status); + + /** + * Returns an identifier associated with the current face set. + * + * The authenticator ID must change whenever a new face is enrolled. The + * authenticator ID must not be changed when a face is deleted. The + * authenticator ID must be an entropy-encoded random number which all + * current templates are tied to. The authenticator ID must be immutable + * outside of an active enrollment window to prevent replay attacks. + * + * @return result, with its value parameter representing an + * "authenticatorId": an identifier associated to the user's current + * face enrollment. + */ + @callflow(next={"authenticate"}) + getAuthenticatorId() generates (OptionalUint64 result); + + /** + * Cancels a pending enrollment or authentication request. + * + * @return status The status of this method call. + */ + @callflow(next={"authenticate", "enroll", "enumerate", "remove", + "setActiveUser"}) + cancel() generates (Status status); + + /** + * Enumerates all face templates associated with the active user. + * + * The onEnumerate() callback method is invoked once for each face template + * found. + * + * @return status The status of this method call. + */ + @callflow(next={"remove", "enroll", "authenticate", "setActiveUser"}) + enumerate() generates (Status status); + + /** + * Removes a face template or all face templates associated with the active + * user. + * + * This method triggers the IBiometricsFaceClientCallback#onRemoved() method. + * + * @param faceId The id correpsonding to the face to be removed; or 0 if all + * faces are to be removed. + * @return status The status of this method call. + */ + @callflow(next={"enumerate", "authenticate", "cancel", "getAuthenticatorId", + "setActiveUser"}) + remove(uint32_t faceId) generates (Status status); + + /** + * Authenticates the active user. + * + * An optional operationId can be specified as a token from the transaction + * being authorized. + * + * @param operationId A non-zero operation id associated with a crypto + * object instance; or 0 if not being used. + * @return status The status of this method call. + */ + @callflow(next={"cancel", "preEnroll", "remove"}) + authenticate(uint64_t operationId) generates (Status status); +}; diff --git a/biometrics/face/1.0/IBiometricsFaceClientCallback.hal b/biometrics/face/1.0/IBiometricsFaceClientCallback.hal new file mode 100644 index 0000000000..93848c57bb --- /dev/null +++ b/biometrics/face/1.0/IBiometricsFaceClientCallback.hal @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics.face@1.0; + +/** + * This callback interface is used by clients to recieve updates from the face + * HAL. + */ +interface IBiometricsFaceClientCallback { + + /** + * A callback invoked when one enrollment step has been completed. + * + * @param deviceId A unique id associated with the HAL implementation + * service that processed this enrollment step. + * @param faceId The id of the face template being enrolled. + * @param userId The active user id for the template being enrolled. + * @param remaining The number of remaining steps before enrolllment is + * complete or 0 if enrollment has completed successfully. + */ + oneway onEnrollResult(uint64_t deviceId, uint32_t faceId, int32_t userId, + uint32_t remaining); + + /** + * A callback invoked when a face has been successfully authenticated. + * + * @param deviceId A unique id associated with the HAL implementation + * service that processed this autentication attempt. + * @param faceId The id of the face template that passed the authentication + * challenge. + * @param userId The active user id for the authenticated face. + * @param token The hardware authentication token associated with this + * authenticate operation. + */ + oneway onAuthenticated(uint64_t deviceId, uint32_t faceId, int32_t userId, + vec token); + + /** + * A callback invoked when a face is acquired. + * + * If a non-critical, recoverable error occurs during an enrollment or + * authentication attempt, the HAL implementation must invoke this callback + * to allow clients to inform the user that some actionable change must be + * made. + * + * @param deviceId A unique id associated with the HAL implementation + * service that acquired a face. + * @param userId The id of the active user associated with the attempted + * face acquisition. + * @param acquiredInfo A message about the quality of the acquired image. + * @param vendorCode An optional vendor-specific message. This is only valid + * when acquiredInfo == FaceAcquiredInfo.VENDOR. This message is opaque + * to the framework, and vendors must provide code to handle it. For + * example this can be used to guide enrollment in Settings or provide + * a message during authentication that is vendor-specific. The vendor + * is expected to provide help strings to cover all known values. + */ + oneway onAcquired(uint64_t deviceId, int32_t userId, + FaceAcquiredInfo acquiredInfo, int32_t vendorCode); + + /** + * A callback invoked when an error has occured. + * + * @param deviceId A unique id associated with the HAL implementation + * service where this error occured. + * @param userId The id of the active user when the error occured, or + * UserHandle::NONE if an active user had not been set yet. + * @param error A message about the error that occurred. + * @param vendorCode An optional, vendor-speicifc error message. Only valid + * when error == FaceError.VENDOR. This message is opaque to the + * framework, and vendors must provide code to handle it. For example, + * this scan be used to show the user an error message specific to the + * device. The vendor is expected to provide error strings to cover + * all known values. + */ + oneway onError(uint64_t deviceId, int32_t userId, FaceError error, + int32_t vendorCode); + + /** + * A callback invoked when a face template has been removed. + * + * @param deviceId A unique id associated with the HAL implementation + * service that processed this removal. + * @param faceId The id of the face template that was removed. + * @param userId The active user id for the removed face template. + * @param remaining The number of face templates remaining after this + * removal, or 0 if there are no more. + */ + oneway onRemoved(uint64_t deviceId, uint32_t faceId, int32_t userId, + uint32_t remaining); + + /** + * A callback invoked to enumerate all current face templates. + * + * @param deviceId A unique id associated with the HAL implementation + * service that processed this enumeration. + * @param faceIds A list of ids of all currently enrolled face templates. + * @param userId The active user id for the enumerated face template. + */ + oneway onEnumerate(uint64_t deviceId, vec faceIds, + int32_t userId); +}; diff --git a/biometrics/face/1.0/types.hal b/biometrics/face/1.0/types.hal new file mode 100644 index 0000000000..08af91907b --- /dev/null +++ b/biometrics/face/1.0/types.hal @@ -0,0 +1,255 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics.face@1.0; + +/* + * In the event setActiveUser is not called, all error messages will return + * this userId. + */ +enum UserHandle : int32_t { + NONE = -1 +}; + +/** + * Status codes returned directly by the HIDL method calls upon critical errors + * where the callback cannot be invoked. Most errors should sent through the + * onError callback using one of the FaceErrors below. + */ +enum Status : uint32_t { + /** + * The method was invoked successfully. + */ + OK = 0, + + /** + * One of the arguments to the method call is invalid. + */ + ILLEGAL_ARGUMENT = 1, + + /** + * This face HAL does not support this operation. + */ + OPERATION_NOT_SUPPORTED = 2, + + /** + * The HAL has encountered an internal error and cannot complete the request. + */ + INTERNAL_ERROR = 3 +}; + +/** + * Face errors represent events that can't be immediately recovered by user + * intervention. These are returned in the onError callback. + * + * Upon receiving a face error, clients must terminate the current operation and + * notify the user where possible. + */ +enum FaceError : int32_t { + + /** + * A hardware error has occured that cannot be resolved. Try again later. + */ + HW_UNAVAILABLE = 1, + + /** + * The current enroll or authenticate operation could not be completed; + * the sensor was unable to process the current image. + */ + UNABLE_TO_PROCESS = 2, + + /** + * The current operation took too long to complete. This is intended to + * prevent programs from blocking the face HAL indefinitely. The timeout is + * framework and sensor-specific, but is generally on the order of 30 + * seconds. + */ + TIMEOUT = 3, + + /** + * The current operation could not be completed because there is not enough + * storage space remaining to do so. + */ + NO_SPACE = 4, + + /** + * The current operation has been cancelled. This may happen if a new + * request (authenticate, remove) is initiated while an on-going operation + * is in progress, or if cancel() was called. + */ + CANCELED = 5, + + /** + * The current remove operation could not be completed; the face template + * provided could not be removed. + */ + UNABLE_TO_REMOVE = 6, + + /** + * Face authentication is locked out due to too many unsuccessful attempts. + */ + LOCKOUT = 7, + + /** + * Used to enable a vendor-specific error message. + */ + VENDOR = 8, +}; + +/** + * Face acquisition information provides feedback for the current enrollment + * or authentication operation. + * + * This information indicates that the user can take immediate action to resolve + * an issue, and clients must ensure that this information is surfaced to the + * user. + */ +enum FaceAcquiredInfo : int32_t { + + /** + * The face acquired was good; no further user interaction is necessary. + */ + GOOD = 0, + + /** + * The face data acquired was too noisy or did not have sufficient detail. + * This is a catch-all for all acquisition errors not captured by the other + * constants. + */ + INSUFFICIENT = 1, + + /** + * Because there was too much ambient light, the captured face data was too + * bright. It's reasonable to return this after multiple + * FaceAcquiredInfo.INSUFFICIENT. + * + * The user is expected to take action to retry the operation in better + * lighting conditions when this is returned. + */ + TOO_BRIGHT = 2, + + /** + * Because there was not enough illumination, the captured face data was too + * dark. It's reasonable to return this after multiple + * FaceAcquiredInfo.INSUFFICIENT. + * + * The user is expected to take action to retry the operation in better + * lighting conditions when this is returned. + */ + TOO_DARK = 3, + + /** + * The detected face is too close to the sensor, and the image cannot be + * processed. + * + * The user is expected to be informed to move further from the sensor when + * this is returned. + */ + TOO_CLOSE = 4, + + /** + * The detected face is too small, as the user might be too far away from + * the sensor. + * + * The user is expected to be informed to move closer to the sensor when + * this is returned. + */ + TOO_FAR = 5, + + /** + * Only the upper part of the face was detected. The sensor's field of view + * is too high. + * + * The user should be informed to move up with respect to the sensor when + * this is returned. + */ + FACE_TOO_HIGH = 6, + + /** + * Only the lower part of the face was detected. The sensor's field of view + * is too low. + * + * The user should be informed to move down with respect to the sensor when + * this is returned. + */ + FACE_TOO_LOW = 7, + + /** + * Only the right part of the face was detected. The sensor's field of view + * is too far right. + * + * The user should be informed to move to the right with respect to the + * sensor when this is returned. + */ + FACE_TOO_RIGHT = 8, + + /** + * Only the left part of the face was detected. The sensor's field of view + * is too far left. + * + * The user should be informed to move to the left with respect to the + * sensor when this is returned. + */ + FACE_TOO_LEFT = 9, + + /** + * The user's face was directed away from the sensor. The user should be + * informed to face the sensor when this is returned. + */ + POOR_GAZE = 10, + + /** + * No face was detected within the sensor's field of view. + * + * The user should be informed to point the sensor to a face when this is + * returned. + */ + NOT_DETECTED = 11, + + /** + * Too much motion was detected. + * + * The user should be informed to keep their face steady relative to the + * sensor. + */ + TOO_MUCH_MOTION = 12, + + /** + * The sensor needs to be recalibrated. + */ + RECALIBRATE = 13, + + /** + * Used to enable a vendor-specific acquisition message. + */ + VENDOR = 14 +}; + +/** + * Result structure with an additional uint64_t field. See documentation in + * setCallback(), preEnroll(), and getAuthenticatorId() for usage of the value. + */ +struct OptionalUint64 { + /** + * The return status. + */ + Status status; + + /** + * This value is only meaningful if status is OK. + */ + uint64_t value; +}; From 5fa43c83e90ccd0f852c89feb0e071aad195d7b2 Mon Sep 17 00:00:00 2001 From: Yu-Han Yang Date: Thu, 14 Jun 2018 14:17:58 -0700 Subject: [PATCH 037/718] Set the floor value of time estimate as 2017 Jan 01 00:00:00 GMT - The VTS test checks if the time estimate is a sane value. Thus, any arbitrary sane value is acceptable. Here we make it consistent to IGnssDebug.hal, where a comment mentions 2017 Jan 1 as an example of the value. Bug: 110094003 Test: make vts, and tested on device. Change-Id: Ic4f6b597a718ea3e98a67c7939f9e6930d44d224 --- gnss/1.1/vts/functional/gnss_hal_test_cases.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp index cce46f18e1..eeb9d0322c 100644 --- a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp +++ b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp @@ -428,7 +428,7 @@ TEST_F(GnssHalTest, GnssDebugValuesSanityTest) { EXPECT_GE(data.position.ageSeconds, 0); } - EXPECT_GE(data.time.timeEstimate, 1514764800000); // Jan 01 2018 00:00:00 + EXPECT_GE(data.time.timeEstimate, 1483228800000); // Jan 01 2017 00:00:00 GMT. EXPECT_GT(data.time.timeUncertaintyNs, 0); From 9ab31039e23da77ec969a15bdd791b21da669e90 Mon Sep 17 00:00:00 2001 From: Steve Paik Date: Tue, 19 Jun 2018 10:59:58 -0700 Subject: [PATCH 038/718] Add example vendor extension properties Bug: 110415164 Test: EKS Property Test Change-Id: Ia1815376d96141ef4401eb4784b81ad4ed889c63 --- .../default/impl/vhal_v2_0/DefaultConfig.h | 63 ++++++++++++++++++- 1 file changed, 61 insertions(+), 2 deletions(-) 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 50f36225ba..917fbc3f59 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 @@ -34,6 +34,8 @@ constexpr int AP_POWER_STATE_REQ = (int)VehicleProperty::AP_POWER_STATE_REQ; constexpr int AP_POWER_STATE_REPORT = (int)VehicleProperty::AP_POWER_STATE_REPORT; constexpr int DOOR_1_LEFT = (int)VehicleAreaDoor::ROW_1_LEFT; constexpr int DOOR_1_RIGHT = (int)VehicleAreaDoor::ROW_1_RIGHT; +constexpr int DOOR_2_LEFT = (int)VehicleAreaDoor::ROW_2_LEFT; +constexpr int DOOR_2_RIGHT = (int)VehicleAreaDoor::ROW_2_RIGHT; constexpr int OBD2_LIVE_FRAME = (int)VehicleProperty::OBD2_LIVE_FRAME; constexpr int OBD2_FREEZE_FRAME = (int)VehicleProperty::OBD2_FREEZE_FRAME; constexpr int OBD2_FREEZE_FRAME_INFO = (int)VehicleProperty::OBD2_FREEZE_FRAME_INFO; @@ -48,6 +50,14 @@ constexpr int HVAC_LEFT = (int)(VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::R VehicleAreaSeat::ROW_2_CENTER); constexpr int HVAC_RIGHT = (int)(VehicleAreaSeat::ROW_1_RIGHT | VehicleAreaSeat::ROW_2_RIGHT); constexpr int HVAC_ALL = HVAC_LEFT | HVAC_RIGHT; +constexpr int VENDOR_EXTENSION_BOOLEAN_PROPERTY = + (int)(0x101 | VehiclePropertyGroup::VENDOR | VehiclePropertyType::BOOLEAN | VehicleArea::DOOR); +constexpr int VENDOR_EXTENSION_FLOAT_PROPERTY = + (int)(0x102 | VehiclePropertyGroup::VENDOR | VehiclePropertyType::FLOAT | VehicleArea::SEAT); +constexpr int VENDOR_EXTENSION_INT_PROPERTY = + (int)(0x103 | VehiclePropertyGroup::VENDOR | VehiclePropertyType::INT32 | VehicleArea::WINDOW); +constexpr int VENDOR_EXTENSION_STRING_PROPERTY = + (int)(0x104 | VehiclePropertyGroup::VENDOR | VehiclePropertyType::STRING | VehicleArea::GLOBAL); /** * This property is used for test purpose to generate fake events. Here is the test package that @@ -372,10 +382,14 @@ const ConfigDeclaration kVehicleProperties[]{ .access = VehiclePropertyAccess::READ_WRITE, .changeMode = VehiclePropertyChangeMode::ON_CHANGE, .areaConfigs = {VehicleAreaConfig{ - .areaId = HVAC_LEFT, .minFloatValue = 16, .maxFloatValue = 32, + .areaId = HVAC_LEFT, + .minFloatValue = 16, + .maxFloatValue = 32, }, VehicleAreaConfig{ - .areaId = HVAC_RIGHT, .minFloatValue = 16, .maxFloatValue = 32, + .areaId = HVAC_RIGHT, + .minFloatValue = 16, + .maxFloatValue = 32, }}}, .initialAreaValues = {{HVAC_LEFT, {.floatValues = {16}}}, {HVAC_RIGHT, {.floatValues = {20}}}}}, @@ -529,6 +543,51 @@ const ConfigDeclaration kVehicleProperties[]{ {.config = {.prop = VEHICLE_MAP_SERVICE, .access = VehiclePropertyAccess::READ_WRITE, .changeMode = VehiclePropertyChangeMode::ON_CHANGE}}, + + // Example Vendor Extension properties for testing + {.config = {.prop = VENDOR_EXTENSION_BOOLEAN_PROPERTY, + .access = VehiclePropertyAccess::READ_WRITE, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + .areaConfigs = {VehicleAreaConfig{.areaId = DOOR_1_LEFT}, + VehicleAreaConfig{.areaId = DOOR_1_RIGHT}, + VehicleAreaConfig{.areaId = DOOR_2_LEFT}, + VehicleAreaConfig{.areaId = DOOR_2_RIGHT}}}, + .initialAreaValues = {{DOOR_1_LEFT, {.int32Values = {1}}}, + {DOOR_1_RIGHT, {.int32Values = {1}}}, + {DOOR_2_LEFT, {.int32Values = {0}}}, + {DOOR_2_RIGHT, {.int32Values = {0}}}}}, + + {.config = {.prop = VENDOR_EXTENSION_FLOAT_PROPERTY, + .access = VehiclePropertyAccess::READ_WRITE, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + .areaConfigs = {VehicleAreaConfig{ + .areaId = HVAC_LEFT, .minFloatValue = -10, .maxFloatValue = 10}, + VehicleAreaConfig{.areaId = HVAC_RIGHT, + .minFloatValue = -10, + .maxFloatValue = 10}}}, + .initialAreaValues = {{HVAC_LEFT, {.floatValues = {1}}}, {HVAC_RIGHT, {.floatValues = {2}}}}}, + + {.config = {.prop = VENDOR_EXTENSION_INT_PROPERTY, + .access = VehiclePropertyAccess::READ_WRITE, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + .areaConfigs = {VehicleAreaConfig{ + .areaId = (int)VehicleAreaWindow::FRONT_WINDSHIELD, + .minInt32Value = -100, + .maxInt32Value = 100}, + VehicleAreaConfig{.areaId = (int)VehicleAreaWindow::REAR_WINDSHIELD, + .minInt32Value = -100, + .maxInt32Value = 100}, + VehicleAreaConfig{.areaId = (int)VehicleAreaWindow::ROOF_TOP_1, + .minInt32Value = -100, + .maxInt32Value = 100}}}, + .initialAreaValues = {{(int)VehicleAreaWindow::FRONT_WINDSHIELD, {.int32Values = {1}}}, + {(int)VehicleAreaWindow::REAR_WINDSHIELD, {.int32Values = {0}}}, + {(int)VehicleAreaWindow::ROOF_TOP_1, {.int32Values = {-1}}}}}, + + {.config = {.prop = VENDOR_EXTENSION_STRING_PROPERTY, + .access = VehiclePropertyAccess::READ_WRITE, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE}, + .initialValue = {.stringValue = "Vendor String Property"}}, }; } // impl From 9475cc240b11a120a7d0762aa63df362e0bcbf0d Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Thu, 21 Jun 2018 14:02:13 -0700 Subject: [PATCH 039/718] Update power hidl to version 1.3 in compatibility_matrix.current.xml. BUG: 110112323 Test: adb shell /data/nativetest/VtsHalPowerV1_3TargetTest/VtsHalPowerV1_3TargetTest Change-Id: I397a30044850ffa8d078dce7ef201073ae65c940 --- compatibility_matrices/compatibility_matrix.current.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml index 1b9ab33d9e..f14fceacee 100644 --- a/compatibility_matrices/compatibility_matrix.current.xml +++ b/compatibility_matrices/compatibility_matrix.current.xml @@ -282,7 +282,7 @@ android.hardware.power - 1.0-2 + 1.0-3 IPower default From e8b9386b4586645c032d161e14a21a140132e3b9 Mon Sep 17 00:00:00 2001 From: Etan Cohen Date: Thu, 21 Jun 2018 15:25:32 -0700 Subject: [PATCH 040/718] Update OWNERS file Update OWNERS to reflect all the current directories under Wi-Fi team development. Bug: 110536740 Test: N/A Change-Id: I6f12400b11be0fa92bc09a730dfd567d7702ef7a --- wifi/1.0/vts/OWNERS | 2 ++ wifi/1.1/vts/OWNERS | 2 ++ wifi/1.1/vts/functional/OWNERS | 2 -- wifi/1.2/vts/OWNERS | 4 +--- 4 files changed, 5 insertions(+), 5 deletions(-) create mode 100644 wifi/1.0/vts/OWNERS create mode 100644 wifi/1.1/vts/OWNERS delete mode 100644 wifi/1.1/vts/functional/OWNERS diff --git a/wifi/1.0/vts/OWNERS b/wifi/1.0/vts/OWNERS new file mode 100644 index 0000000000..8bfb14882c --- /dev/null +++ b/wifi/1.0/vts/OWNERS @@ -0,0 +1,2 @@ +rpius@google.com +etancohen@google.com diff --git a/wifi/1.1/vts/OWNERS b/wifi/1.1/vts/OWNERS new file mode 100644 index 0000000000..8bfb14882c --- /dev/null +++ b/wifi/1.1/vts/OWNERS @@ -0,0 +1,2 @@ +rpius@google.com +etancohen@google.com diff --git a/wifi/1.1/vts/functional/OWNERS b/wifi/1.1/vts/functional/OWNERS deleted file mode 100644 index 2878acc7fd..0000000000 --- a/wifi/1.1/vts/functional/OWNERS +++ /dev/null @@ -1,2 +0,0 @@ -rpius@google.com -quiche@google.com diff --git a/wifi/1.2/vts/OWNERS b/wifi/1.2/vts/OWNERS index 811c857946..8bfb14882c 100644 --- a/wifi/1.2/vts/OWNERS +++ b/wifi/1.2/vts/OWNERS @@ -1,4 +1,2 @@ rpius@google.com -quiche@google.com -arabawy@google.com -yim@google.com \ No newline at end of file +etancohen@google.com From 0f8133feeb36725dcffdac1e003dd6b8d0193047 Mon Sep 17 00:00:00 2001 From: Kevin Rocard Date: Wed, 20 Jun 2018 13:51:52 -0700 Subject: [PATCH 041/718] Do not log error on open output/input stream negotiation The HAL has a negotiation mechanism where if an open output/input stream is made with unsupported parameters, it will return a valid config and UNSUPPORTED_PARAMETRS. This negotiation was confusingly logged as error. Test: "adb logcat -s DeviceHAL" show no error on successful playback/capture Change-Id: I5383cdcfdf8a0ca66768ffc106a1b651b9d8b2d1 Signed-off-by: Kevin Rocard --- .../include/core/all-versions/default/Device.h | 3 ++- .../include/core/all-versions/default/Device.impl.h | 11 +++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/audio/core/all-versions/default/include/core/all-versions/default/Device.h b/audio/core/all-versions/default/include/core/all-versions/default/Device.h index eb53b482b2..222d3dedc2 100644 --- a/audio/core/all-versions/default/include/core/all-versions/default/Device.h +++ b/audio/core/all-versions/default/include/core/all-versions/default/Device.h @@ -124,7 +124,8 @@ struct Device : public IDevice, public ParametersUtil { Return debug(const hidl_handle& fd, const hidl_vec& options) override; // Utility methods for extending interfaces. - Result analyzeStatus(const char* funcName, int status); + Result analyzeStatus(const char* funcName, int status, + const std::vector& ignoreErrors = {}); void closeInputStream(audio_stream_in_t* stream); void closeOutputStream(audio_stream_out_t* stream); audio_hw_device_t* device() const { return mDevice; } diff --git a/audio/core/all-versions/default/include/core/all-versions/default/Device.impl.h b/audio/core/all-versions/default/include/core/all-versions/default/Device.impl.h index 230b8de243..52d21869dd 100644 --- a/audio/core/all-versions/default/include/core/all-versions/default/Device.impl.h +++ b/audio/core/all-versions/default/include/core/all-versions/default/Device.impl.h @@ -40,8 +40,9 @@ Device::~Device() { mDevice = nullptr; } -Result Device::analyzeStatus(const char* funcName, int status) { - return util::analyzeStatus("Device", funcName, status); +Result Device::analyzeStatus(const char* funcName, int status, + const std::vector& ignoreErrors) { + return util::analyzeStatus("Device", funcName, status, ignoreErrors); } void Device::closeInputStream(audio_stream_in_t* stream) { @@ -155,7 +156,8 @@ Return Device::openOutputStream(int32_t ioHandle, const DeviceAddress& dev } AudioConfig suggestedConfig; HidlUtils::audioConfigFromHal(halConfig, &suggestedConfig); - _hidl_cb(analyzeStatus("open_output_stream", status), streamOut, suggestedConfig); + _hidl_cb(analyzeStatus("open_output_stream", status, {EINVAL} /* ignore */), streamOut, + suggestedConfig); return Void(); } @@ -183,7 +185,8 @@ Return Device::openInputStream(int32_t ioHandle, const DeviceAddress& devi } AudioConfig suggestedConfig; HidlUtils::audioConfigFromHal(halConfig, &suggestedConfig); - _hidl_cb(analyzeStatus("open_input_stream", status), streamIn, suggestedConfig); + _hidl_cb(analyzeStatus("open_input_stream", status, {EINVAL} /* ignore */), streamIn, + suggestedConfig); return Void(); } From 454d4ef594b930b0464d03343c449c3c4499c544 Mon Sep 17 00:00:00 2001 From: Chao Yan Date: Thu, 21 Jun 2018 19:04:55 -0700 Subject: [PATCH 042/718] Generate VHAL property mixed type from JSON Bug: 76017041 Test: atest VehicleHALTest Change-Id: Iaf2f01f71e2eee6478de0aadd2fe2bd13a385404 --- .../impl/vhal_v2_0/EmulatedVehicleHal.cpp | 2 +- .../impl/vhal_v2_0/JsonFakeValueGenerator.cpp | 65 ++++++++++++++++++- .../impl/vhal_v2_0/JsonFakeValueGenerator.h | 8 +++ 3 files changed, 72 insertions(+), 3 deletions(-) diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp index 0e5897a08c..c6955e03b0 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp @@ -431,7 +431,7 @@ void EmulatedVehicleHal::onFakeValueGenerated(const VehiclePropValue& value) { mPropStore->writeValue(*updatedPropValue, shouldUpdateStatus); auto changeMode = mPropStore->getConfigOrDie(value.prop)->changeMode; if (VehiclePropertyChangeMode::ON_CHANGE == changeMode) { - doHalEvent(move(updatedPropValue)); + doHalEvent(std::move(updatedPropValue)); } } } diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp index c293c0af44..b8fd2babee 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp @@ -17,6 +17,8 @@ #define LOG_TAG "JsonFakeValueGenerator" #include +#include +#include #include #include @@ -122,9 +124,14 @@ std::vector JsonFakeValueGenerator::parseFakeValueJson(std::is case VehiclePropertyType::STRING: value.stringValue = rawEventValue.asString(); break; + case VehiclePropertyType::MIXED: + copyMixedValueJson(value, rawEventValue); + if (isDiagnosticProperty(event.prop)) { + value.bytes = generateDiagnosticBytes(value); + } + break; default: - ALOGE("%s: unsupported type for property: 0x%x with value: %s", __func__, - event.prop, rawEventValue.asString().c_str()); + ALOGE("%s: unsupported type for property: 0x%x", __func__, event.prop); continue; } fakeVhalEvents.push_back(event); @@ -132,6 +139,60 @@ std::vector JsonFakeValueGenerator::parseFakeValueJson(std::is return fakeVhalEvents; } +void JsonFakeValueGenerator::copyMixedValueJson(VehiclePropValue::RawValue& dest, + const Json::Value& jsonValue) { + copyJsonArray(dest.int32Values, jsonValue["int32Values"]); + copyJsonArray(dest.int64Values, jsonValue["int64Values"]); + copyJsonArray(dest.floatValues, jsonValue["floatValues"]); + dest.stringValue = jsonValue["stringValue"].asString(); +} + +template +void JsonFakeValueGenerator::copyJsonArray(hidl_vec& dest, const Json::Value& jsonArray) { + dest.resize(jsonArray.size()); + for (Json::Value::ArrayIndex i = 0; i < jsonArray.size(); i++) { + if (std::is_same::value) { + dest[i] = jsonArray[i].asInt(); + } else if (std::is_same::value) { + dest[i] = jsonArray[i].asInt64(); + } else if (std::is_same::value) { + dest[i] = jsonArray[i].asFloat(); + } + } +} + +bool JsonFakeValueGenerator::isDiagnosticProperty(int32_t prop) { + return prop == (int32_t)VehicleProperty::OBD2_LIVE_FRAME || + prop == (int32_t)VehicleProperty::OBD2_FREEZE_FRAME; +} + +hidl_vec JsonFakeValueGenerator::generateDiagnosticBytes( + const VehiclePropValue::RawValue& diagnosticValue) { + size_t byteSize = ((size_t)DiagnosticIntegerSensorIndex::LAST_SYSTEM_INDEX + + (size_t)DiagnosticFloatSensorIndex::LAST_SYSTEM_INDEX + 2); + hidl_vec bytes(byteSize % 8 == 0 ? byteSize / 8 : byteSize / 8 + 1); + + auto& int32Values = diagnosticValue.int32Values; + for (size_t i = 0; i < int32Values.size(); i++) { + if (int32Values[i] != 0) { + setBit(bytes, i); + } + } + + auto& floatValues = diagnosticValue.floatValues; + for (size_t i = 0; i < floatValues.size(); i++) { + if (floatValues[i] != 0.0) { + setBit(bytes, i + (size_t)DiagnosticIntegerSensorIndex::LAST_SYSTEM_INDEX + 1); + } + } + return bytes; +} + +void JsonFakeValueGenerator::setBit(hidl_vec& bytes, size_t idx) { + uint8_t mask = 1 << (idx % 8); + bytes[idx / 8] |= mask; +} + } // namespace impl } // namespace V2_0 diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h index 43c8b9dc53..70575f77bf 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h @@ -49,6 +49,14 @@ public: private: std::vector parseFakeValueJson(std::istream& is); + void copyMixedValueJson(VehiclePropValue::RawValue& dest, const Json::Value& jsonValue); + + template + void copyJsonArray(hidl_vec& dest, const Json::Value& jsonArray); + + bool isDiagnosticProperty(int32_t prop); + hidl_vec generateDiagnosticBytes(const VehiclePropValue::RawValue& diagnosticValue); + void setBit(hidl_vec& bytes, size_t idx); private: GeneratorCfg mGenCfg; From bea881c9a1df48c08dd11482dd064bde1d1eace1 Mon Sep 17 00:00:00 2001 From: Dean Harding Date: Fri, 15 Jun 2018 13:33:47 -0700 Subject: [PATCH 043/718] Make the emulated VHAL always listen for socket connections. Previously, when running under the emulator, it would only connect to the emulator's qemu pipe and you couldn't script the emulated VHAL. Also changed the logic of SocketComm so that it supports connections from more than one client at a time. Bug: 87643732 Test: tested locally Change-Id: I504cd806f0a95799a68b75c3515c1f230109f1d0 (cherry picked from commit 8dad67a0148114cb60f3567268bc2cf40ff18f82) --- automotive/vehicle/2.0/default/Android.bp | 1 + .../2.0/default/impl/vhal_v2_0/CommConn.cpp | 80 ++++++ .../impl/vhal_v2_0/{CommBase.h => CommConn.h} | 71 ++++-- .../2.0/default/impl/vhal_v2_0/PipeComm.cpp | 37 ++- .../2.0/default/impl/vhal_v2_0/PipeComm.h | 41 ++- .../2.0/default/impl/vhal_v2_0/SocketComm.cpp | 236 ++++++++++-------- .../2.0/default/impl/vhal_v2_0/SocketComm.h | 67 +++-- .../impl/vhal_v2_0/VehicleEmulator.cpp | 158 ++++-------- .../default/impl/vhal_v2_0/VehicleEmulator.h | 44 ++-- 9 files changed, 418 insertions(+), 317 deletions(-) create mode 100644 automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.cpp rename automotive/vehicle/2.0/default/impl/vhal_v2_0/{CommBase.h => CommConn.h} (53%) diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp index 65e9133b0a..7802ef098e 100644 --- a/automotive/vehicle/2.0/default/Android.bp +++ b/automotive/vehicle/2.0/default/Android.bp @@ -58,6 +58,7 @@ cc_library_static { vendor: true, defaults: ["vhal_v2_0_defaults"], srcs: [ + "impl/vhal_v2_0/CommConn.cpp", "impl/vhal_v2_0/EmulatedVehicleHal.cpp", "impl/vhal_v2_0/VehicleEmulator.cpp", "impl/vhal_v2_0/PipeComm.cpp", diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.cpp new file mode 100644 index 0000000000..bf1de8165a --- /dev/null +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "CommConn" + +#include + +#include +#include + +#include "CommConn.h" + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace V2_0 { + +namespace impl { + +void CommConn::start() { + mReadThread = std::make_unique(std::bind(&CommConn::readThread, this)); +} + +void CommConn::stop() { + if (mReadThread->joinable()) { + mReadThread->join(); + } +} + +void CommConn::sendMessage(emulator::EmulatorMessage const& msg) { + int numBytes = msg.ByteSize(); + std::vector buffer(static_cast(numBytes)); + if (!msg.SerializeToArray(buffer.data(), numBytes)) { + ALOGE("%s: SerializeToString failed!", __func__); + return; + } + + write(buffer); +} + +void CommConn::readThread() { + std::vector buffer; + while (isOpen()) { + buffer = read(); + if (buffer.size() == 0) { + ALOGI("%s: Read returned empty message, exiting read loop.", __func__); + break; + } + + emulator::EmulatorMessage rxMsg; + if (rxMsg.ParseFromArray(buffer.data(), static_cast(buffer.size()))) { + emulator::EmulatorMessage respMsg; + mMessageProcessor->processMessage(rxMsg, respMsg); + + sendMessage(respMsg); + } + } +} + +} // namespace impl + +} // namespace V2_0 +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommBase.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.h similarity index 53% rename from automotive/vehicle/2.0/default/impl/vhal_v2_0/CommBase.h rename to automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.h index 6832ad3398..87b0dfc17d 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommBase.h +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.h @@ -17,9 +17,13 @@ #ifndef android_hardware_automotive_vehicle_V2_0_impl_CommBase_H_ #define android_hardware_automotive_vehicle_V2_0_impl_CommBase_H_ +#include #include +#include #include +#include "VehicleHalProto.pb.h" + namespace android { namespace hardware { namespace automotive { @@ -29,32 +33,45 @@ namespace V2_0 { namespace impl { /** - * This is the communications base class. It defines the interface used in DefaultVehicleHal to - * send and receive data to and from the emulator. + * MessageProcess is an interface implemented by VehicleEmulator to process messages received + * over a CommConn. */ -class CommBase { -public: - virtual ~CommBase() = default; +class MessageProcessor { + public: + virtual ~MessageProcessor() = default; + + /** + * Process a single message received over a CommConn. Populate the given respMsg with the reply + * message we should send. + */ + virtual void processMessage(emulator::EmulatorMessage const& rxMsg, + emulator::EmulatorMessage& respMsg) = 0; +}; + +/** + * This is the interface that both PipeComm and SocketComm use to represent a connection. The + * connection will listen for commands on a separate 'read' thread. + */ +class CommConn { + public: + CommConn(MessageProcessor* messageProcessor) : mMessageProcessor(messageProcessor) {} + + virtual ~CommConn() {} + + /** + * Start the read thread reading messages from this connection. + */ + virtual void start(); /** * Closes a connection if it is open. */ - virtual void stop() {} + virtual void stop(); /** - * Creates a connection to the other side. - * - * @return int Returns fd or socket number if connection is successful. - * Otherwise, returns -1 if no connection is availble. + * Returns true if the connection is open and available to send/receive. */ - virtual int connect() { return 0; } - - /** - * Opens the communications channel. - * - * @return int Returns 0 if channel is opened, else -errno if failed. - */ - virtual int open() = 0; + virtual bool isOpen() = 0; /** * Blocking call to read data from the connection. @@ -72,9 +89,24 @@ public: * @return int Number of bytes transmitted, or -1 if failed. */ virtual int write(const std::vector& data) = 0; + + /** + * Serialized and send the given message to the other side. + */ + void sendMessage(emulator::EmulatorMessage const& msg); + + protected: + std::unique_ptr mReadThread; + MessageProcessor* mMessageProcessor; + + /** + * A thread that reads messages in a loop, and responds. You can stop this thread by calling + * stop(). + */ + void readThread(); }; -} // impl +} // namespace impl } // namespace V2_0 } // namespace vehicle @@ -82,5 +114,4 @@ public: } // namespace hardware } // namespace android - #endif // android_hardware_automotive_vehicle_V2_0_impl_CommBase_H_ diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.cpp index 5a9b254594..f0242879bc 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.cpp +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.cpp @@ -33,23 +33,28 @@ namespace V2_0 { namespace impl { -PipeComm::PipeComm() { - // Initialize member vars - mPipeFd = -1; -} +PipeComm::PipeComm(MessageProcessor* messageProcessor) : CommConn(messageProcessor), mPipeFd(-1) {} - -int PipeComm::open() { +void PipeComm::start() { int fd = qemu_pipe_open(CAR_SERVICE_NAME); if (fd < 0) { ALOGE("%s: Could not open connection to service: %s %d", __FUNCTION__, strerror(errno), fd); - return -errno; + return; } - ALOGI("%s: OPENED PIPE, fd=%d", __FUNCTION__, fd); + ALOGI("%s: Starting pipe connection, fd=%d", __FUNCTION__, fd); mPipeFd = fd; - return 0; + + CommConn::start(); +} + +void PipeComm::stop() { + if (mPipeFd > 0) { + ::close(mPipeFd); + mPipeFd = -1; + } + CommConn::stop(); } std::vector PipeComm::read() { @@ -60,16 +65,13 @@ std::vector PipeComm::read() { numBytes = qemu_pipe_frame_recv(mPipeFd, msg.data(), msg.size()); if (numBytes == MAX_RX_MSG_SZ) { - ALOGE("%s: Received max size = %d", __FUNCTION__, MAX_RX_MSG_SZ); + ALOGE("%s: Received max size = %d", __FUNCTION__, MAX_RX_MSG_SZ); } else if (numBytes > 0) { msg.resize(numBytes); return msg; } else { ALOGD("%s: Connection terminated on pipe %d, numBytes=%d", __FUNCTION__, mPipeFd, numBytes); - { - std::lock_guard lock(mMutex); - mPipeFd = -1; - } + mPipeFd = -1; } return std::vector(); @@ -78,11 +80,8 @@ std::vector PipeComm::read() { int PipeComm::write(const std::vector& data) { int retVal = 0; - { - std::lock_guard lock(mMutex); - if (mPipeFd != -1) { - retVal = qemu_pipe_frame_send(mPipeFd, data.data(), data.size()); - } + if (mPipeFd != -1) { + retVal = qemu_pipe_frame_send(mPipeFd, data.data(), data.size()); } if (retVal < 0) { diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.h index bcd32d00d3..c8eabb8aa7 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.h +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.h @@ -19,7 +19,7 @@ #include #include -#include "CommBase.h" +#include "CommConn.h" namespace android { namespace hardware { @@ -30,38 +30,25 @@ namespace V2_0 { namespace impl { /** - * PipeComm uses a qemu pipe interface to connect to the Goldfish Emulator. + * PipeComm opens a qemu pipe to connect to the emulator, allowing the emulator UI to access the + * Vehicle HAL and simulate changing properties. + * + * Since the pipe is a client, it directly implements CommConn, and only one PipeComm can be open + * at a time. */ -class PipeComm : public CommBase { -public: - PipeComm(); +class PipeComm : public CommConn { + public: + PipeComm(MessageProcessor* messageProcessor); - /** - * Opens a pipe and begins listening. - * - * @return int Returns 0 on success. - */ - int open() override; + void start() override; + void stop() override; - /** - * Blocking call to read data from the connection. - * - * @return std::vector Serialized protobuf data received from emulator. This will be - * an empty vector if the connection was closed or some other error occurred. - */ std::vector read() override; - - /** - * Transmits a string of data to the emulator. - * - * @param data Serialized protobuf data to transmit. - * - * @return int Number of bytes transmitted, or -1 if failed. - */ int write(const std::vector& data) override; -private: - std::mutex mMutex; + inline bool isOpen() override { return mPipeFd > 0; } + + private: int mPipeFd; }; diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.cpp index 42c1c780cc..9eb8894385 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.cpp +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -35,45 +36,46 @@ namespace V2_0 { namespace impl { -SocketComm::SocketComm() { - // Initialize member vars - mCurSockFd = -1; - mExit = 0; - mSockFd = -1; -} - +SocketComm::SocketComm(MessageProcessor* messageProcessor) + : mListenFd(-1), mMessageProcessor(messageProcessor) {} SocketComm::~SocketComm() { - stop(); } -int SocketComm::connect() { - sockaddr_in cliAddr; - socklen_t cliLen = sizeof(cliAddr); - int cSockFd = accept(mSockFd, reinterpret_cast(&cliAddr), &cliLen); - - if (cSockFd >= 0) { - { - std::lock_guard lock(mMutex); - mCurSockFd = cSockFd; - } - ALOGD("%s: Incoming connection received on socket %d", __FUNCTION__, cSockFd); - } else { - cSockFd = -1; +void SocketComm::start() { + if (!listen()) { + return; } - return cSockFd; + mListenThread = std::make_unique(std::bind(&SocketComm::listenThread, this)); } -int SocketComm::open() { +void SocketComm::stop() { + if (mListenFd > 0) { + ::close(mListenFd); + if (mListenThread->joinable()) { + mListenThread->join(); + } + mListenFd = -1; + } +} + +void SocketComm::sendMessage(emulator::EmulatorMessage const& msg) { + std::lock_guard lock(mMutex); + for (std::unique_ptr const& conn : mOpenConnections) { + conn->sendMessage(msg); + } +} + +bool SocketComm::listen() { int retVal; struct sockaddr_in servAddr; - mSockFd = socket(AF_INET, SOCK_STREAM, 0); - if (mSockFd < 0) { - ALOGE("%s: socket() failed, mSockFd=%d, errno=%d", __FUNCTION__, mSockFd, errno); - mSockFd = -1; - return -errno; + mListenFd = socket(AF_INET, SOCK_STREAM, 0); + if (mListenFd < 0) { + ALOGE("%s: socket() failed, mSockFd=%d, errno=%d", __FUNCTION__, mListenFd, errno); + mListenFd = -1; + return false; } memset(&servAddr, 0, sizeof(servAddr)); @@ -81,82 +83,114 @@ int SocketComm::open() { servAddr.sin_addr.s_addr = INADDR_ANY; servAddr.sin_port = htons(DEBUG_SOCKET); - retVal = bind(mSockFd, reinterpret_cast(&servAddr), sizeof(servAddr)); + retVal = bind(mListenFd, reinterpret_cast(&servAddr), sizeof(servAddr)); if(retVal < 0) { ALOGE("%s: Error on binding: retVal=%d, errno=%d", __FUNCTION__, retVal, errno); + close(mListenFd); + mListenFd = -1; + return false; + } + + ALOGI("%s: Listening for connections on port %d", __FUNCTION__, DEBUG_SOCKET); + ::listen(mListenFd, 1); + return true; +} + +SocketConn* SocketComm::accept() { + sockaddr_in cliAddr; + socklen_t cliLen = sizeof(cliAddr); + int sfd = ::accept(mListenFd, reinterpret_cast(&cliAddr), &cliLen); + + if (sfd > 0) { + char addr[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &cliAddr.sin_addr, addr, INET_ADDRSTRLEN); + + ALOGD("%s: Incoming connection received from %s:%d", __FUNCTION__, addr, cliAddr.sin_port); + return new SocketConn(mMessageProcessor, sfd); + } + + return nullptr; +} + +void SocketComm::listenThread() { + while (true) { + SocketConn* conn = accept(); + if (conn == nullptr) { + return; + } + + conn->start(); + { + std::lock_guard lock(mMutex); + mOpenConnections.push_back(std::unique_ptr(conn)); + } + } +} + +/** + * Called occasionally to clean up connections that have been closed. + */ +void SocketComm::removeClosedConnections() { + std::lock_guard lock(mMutex); + std::remove_if(mOpenConnections.begin(), mOpenConnections.end(), + [](std::unique_ptr const& c) { return !c->isOpen(); }); +} + +SocketConn::SocketConn(MessageProcessor* messageProcessor, int sfd) + : CommConn(messageProcessor), mSockFd(sfd) {} + +/** + * Reads, in a loop, exactly numBytes from the given fd. If the connection is closed, returns + * an empty buffer, otherwise will return exactly the given number of bytes. + */ +std::vector readExactly(int fd, int numBytes) { + std::vector buffer(numBytes); + int totalRead = 0; + int offset = 0; + while (totalRead < numBytes) { + int numRead = ::read(fd, &buffer.data()[offset], numBytes - offset); + if (numRead == 0) { + buffer.resize(0); + return buffer; + } + + totalRead += numRead; + } + return buffer; +} + +/** + * Reads an int, guaranteed to be non-zero, from the given fd. If the connection is closed, returns + * -1. + */ +int32_t readInt(int fd) { + std::vector buffer = readExactly(fd, sizeof(int32_t)); + if (buffer.size() == 0) { + return -1; + } + + int32_t value = *reinterpret_cast(buffer.data()); + return ntohl(value); +} + +std::vector SocketConn::read() { + int32_t msgSize = readInt(mSockFd); + if (msgSize <= 0) { + ALOGD("%s: Connection terminated on socket %d", __FUNCTION__, mSockFd); + return std::vector(); + } + + return readExactly(mSockFd, msgSize); +} + +void SocketConn::stop() { + if (mSockFd > 0) { close(mSockFd); mSockFd = -1; - return -errno; - } - - listen(mSockFd, 1); - - // Set the socket to be non-blocking so we can poll it continouously - fcntl(mSockFd, F_SETFL, O_NONBLOCK); - - return 0; -} - -std::vector SocketComm::read() { - int32_t msgSize; - int numBytes = 0; - - // This is a variable length message. - // Read the number of bytes to rx over the socket - numBytes = ::read(mCurSockFd, &msgSize, sizeof(msgSize)); - msgSize = ntohl(msgSize); - - if (numBytes != sizeof(msgSize)) { - // This happens when connection is closed - ALOGD("%s: numBytes=%d, expected=4", __FUNCTION__, numBytes); - ALOGD("%s: Connection terminated on socket %d", __FUNCTION__, mCurSockFd); - { - std::lock_guard lock(mMutex); - mCurSockFd = -1; - } - - return std::vector(); - } - - std::vector msg = std::vector(msgSize); - - numBytes = ::read(mCurSockFd, msg.data(), msgSize); - - if ((numBytes == msgSize) && (msgSize > 0)) { - // Received a message. - return msg; - } else { - // This happens when connection is closed - ALOGD("%s: numBytes=%d, msgSize=%d", __FUNCTION__, numBytes, msgSize); - ALOGD("%s: Connection terminated on socket %d", __FUNCTION__, mCurSockFd); - { - std::lock_guard lock(mMutex); - mCurSockFd = -1; - } - - return std::vector(); } } -void SocketComm::stop() { - if (mExit == 0) { - std::lock_guard lock(mMutex); - mExit = 1; - - // Close emulator socket if it is open - if (mCurSockFd != -1) { - close(mCurSockFd); - mCurSockFd = -1; - } - - if (mSockFd != -1) { - close(mSockFd); - mSockFd = -1; - } - } -} - -int SocketComm::write(const std::vector& data) { +int SocketConn::write(const std::vector& data) { static constexpr int MSG_HEADER_LEN = 4; int retVal = 0; union { @@ -168,19 +202,17 @@ int SocketComm::write(const std::vector& data) { msgLen = static_cast(data.size()); msgLen = htonl(msgLen); - std::lock_guard lock(mMutex); - if (mCurSockFd != -1) { - retVal = ::write(mCurSockFd, msgLenBytes, MSG_HEADER_LEN); + if (mSockFd > 0) { + retVal = ::write(mSockFd, msgLenBytes, MSG_HEADER_LEN); if (retVal == MSG_HEADER_LEN) { - retVal = ::write(mCurSockFd, data.data(), data.size()); + retVal = ::write(mSockFd, data.data(), data.size()); } } return retVal; } - } // impl } // namespace V2_0 diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.h index 12cfb29b8a..88b852bb33 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.h +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.h @@ -18,8 +18,9 @@ #define android_hardware_automotive_vehicle_V2_0_impl_SocketComm_H_ #include +#include #include -#include "CommBase.h" +#include "CommConn.h" namespace android { namespace hardware { @@ -29,29 +30,60 @@ namespace V2_0 { namespace impl { +class SocketConn; + /** - * SocketComm opens a socket via adb's TCP port forwarding to enable a Host PC to connect to - * the VehicleHAL. + * SocketComm opens a socket, and listens for connections from clients. Typically the client will be + * adb's TCP port-forwarding to enable a host PC to connect to the VehicleHAL. */ -class SocketComm : public CommBase { -public: - SocketComm(); +class SocketComm { + public: + SocketComm(MessageProcessor* messageProcessor); virtual ~SocketComm(); + void start(); + void stop(); + /** - * Creates a connection to the other side. + * Serialized and send the given message to all connected clients. + */ + void sendMessage(emulator::EmulatorMessage const& msg); + + private: + int mListenFd; + std::unique_ptr mListenThread; + std::vector> mOpenConnections; + MessageProcessor* mMessageProcessor; + std::mutex mMutex; + + /** + * Opens the socket and begins listening. + * + * @return bool Returns true on success. + */ + bool listen(); + + /** + * Blocks and waits for a connection from a client, returns a new SocketConn with the connection + * or null, if the connection has been closed. * * @return int Returns fd or socket number if connection is successful. * Otherwise, returns -1 if no connection is availble. */ - int connect() override; + SocketConn* accept(); - /** - * Opens a socket and begins listening. - * - * @return int Returns 0 on success. - */ - int open() override; + void listenThread(); + + void removeClosedConnections(); +}; + +/** + * SocketConn represents a single connection to a client. + */ +class SocketConn : public CommConn { + public: + SocketConn(MessageProcessor* messageProcessor, int sfd); + virtual ~SocketConn() = default; /** * Blocking call to read data from the connection. @@ -75,10 +107,9 @@ public: */ int write(const std::vector& data) override; -private: - int mCurSockFd; - std::atomic mExit; - std::mutex mMutex; + inline bool isOpen() override { return mSockFd > 0; } + + private: int mSockFd; }; diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp index bf7be09afc..356a6b9568 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp @@ -16,9 +16,10 @@ #define LOG_TAG "VehicleEmulator_v2_0" #include -#include #include +#include #include +#include #include @@ -35,32 +36,45 @@ namespace V2_0 { namespace impl { -std::unique_ptr CommFactory::create() { - bool isEmulator = android::base::GetBoolProperty("ro.kernel.qemu", false); +VehicleEmulator::VehicleEmulator(EmulatedVehicleHalIface* hal) : mHal{hal} { + mHal->registerEmulator(this); - if (isEmulator) { - return std::make_unique(); - } else { - return std::make_unique(); + ALOGI("Starting SocketComm"); + mSocketComm = std::make_unique(this); + mSocketComm->start(); + + if (android::base::GetBoolProperty("ro.kernel.qemu", false)) { + ALOGI("Starting PipeComm"); + mPipeComm = std::make_unique(this); + mPipeComm->start(); } } VehicleEmulator::~VehicleEmulator() { - mExit = true; // Notify thread to finish and wait for it to terminate. - mComm->stop(); // Close emulator socket if it is open. - if (mThread.joinable()) mThread.join(); + mSocketComm->stop(); + if (mPipeComm) { + mPipeComm->stop(); + } } +/** + * This is called by the HAL when a property changes. We need to notify our clients that it has + * changed. + */ void VehicleEmulator::doSetValueFromClient(const VehiclePropValue& propValue) { emulator::EmulatorMessage msg; emulator::VehiclePropValue *val = msg.add_value(); populateProtoVehiclePropValue(val, &propValue); msg.set_status(emulator::RESULT_OK); msg.set_msg_type(emulator::SET_PROPERTY_ASYNC); - txMsg(msg); + + mSocketComm->sendMessage(msg); + if (mPipeComm) { + mPipeComm->sendMessage(msg); + } } -void VehicleEmulator::doGetConfig(VehicleEmulator::EmulatorMessage& rxMsg, +void VehicleEmulator::doGetConfig(VehicleEmulator::EmulatorMessage const& rxMsg, VehicleEmulator::EmulatorMessage& respMsg) { std::vector configs = mHal->listProperties(); emulator::VehiclePropGet getProp = rxMsg.prop(0); @@ -79,7 +93,7 @@ void VehicleEmulator::doGetConfig(VehicleEmulator::EmulatorMessage& rxMsg, } } -void VehicleEmulator::doGetConfigAll(VehicleEmulator::EmulatorMessage& /* rxMsg */, +void VehicleEmulator::doGetConfigAll(VehicleEmulator::EmulatorMessage const& /* rxMsg */, VehicleEmulator::EmulatorMessage& respMsg) { std::vector configs = mHal->listProperties(); @@ -92,8 +106,8 @@ void VehicleEmulator::doGetConfigAll(VehicleEmulator::EmulatorMessage& /* rxMsg } } -void VehicleEmulator::doGetProperty(VehicleEmulator::EmulatorMessage& rxMsg, - VehicleEmulator::EmulatorMessage& respMsg) { +void VehicleEmulator::doGetProperty(VehicleEmulator::EmulatorMessage const& rxMsg, + VehicleEmulator::EmulatorMessage& respMsg) { int32_t areaId = 0; emulator::VehiclePropGet getProp = rxMsg.prop(0); int32_t propId = getProp.prop(); @@ -119,8 +133,8 @@ void VehicleEmulator::doGetProperty(VehicleEmulator::EmulatorMessage& rxMsg, respMsg.set_status(status); } -void VehicleEmulator::doGetPropertyAll(VehicleEmulator::EmulatorMessage& /* rxMsg */, - VehicleEmulator::EmulatorMessage& respMsg) { +void VehicleEmulator::doGetPropertyAll(VehicleEmulator::EmulatorMessage const& /* rxMsg */, + VehicleEmulator::EmulatorMessage& respMsg) { respMsg.set_msg_type(emulator::GET_PROPERTY_ALL_RESP); respMsg.set_status(emulator::RESULT_OK); @@ -132,7 +146,7 @@ void VehicleEmulator::doGetPropertyAll(VehicleEmulator::EmulatorMessage& /* rxMs } } -void VehicleEmulator::doSetProperty(VehicleEmulator::EmulatorMessage& rxMsg, +void VehicleEmulator::doSetProperty(VehicleEmulator::EmulatorMessage const& rxMsg, VehicleEmulator::EmulatorMessage& respMsg) { emulator::VehiclePropValue protoVal = rxMsg.value(0); VehiclePropValue val = { @@ -173,58 +187,28 @@ void VehicleEmulator::doSetProperty(VehicleEmulator::EmulatorMessage& rxMsg, respMsg.set_status(halRes ? emulator::RESULT_OK : emulator::ERROR_INVALID_PROPERTY); } -void VehicleEmulator::txMsg(emulator::EmulatorMessage& txMsg) { - int numBytes = txMsg.ByteSize(); - std::vector msg(static_cast(numBytes)); - - if (!txMsg.SerializeToArray(msg.data(), static_cast(msg.size()))) { - ALOGE("%s: SerializeToString failed!", __func__); - return; - } - - if (mExit) { - ALOGW("%s: unable to transmit a message, connection closed", __func__); - return; - } - - // Send the message - int retVal = mComm->write(msg); - if (retVal < 0) { - ALOGE("%s: Failed to tx message: retval=%d, errno=%d", __func__, retVal, errno); - } -} - -void VehicleEmulator::parseRxProtoBuf(std::vector& msg) { - emulator::EmulatorMessage rxMsg; - emulator::EmulatorMessage respMsg; - - if (rxMsg.ParseFromArray(msg.data(), static_cast(msg.size()))) { - switch (rxMsg.msg_type()) { - case emulator::GET_CONFIG_CMD: - doGetConfig(rxMsg, respMsg); - break; - case emulator::GET_CONFIG_ALL_CMD: - doGetConfigAll(rxMsg, respMsg); - break; - case emulator::GET_PROPERTY_CMD: - doGetProperty(rxMsg, respMsg); - break; - case emulator::GET_PROPERTY_ALL_CMD: - doGetPropertyAll(rxMsg, respMsg); - break; - case emulator::SET_PROPERTY_CMD: - doSetProperty(rxMsg, respMsg); - break; - default: - ALOGW("%s: Unknown message received, type = %d", __func__, rxMsg.msg_type()); - respMsg.set_status(emulator::ERROR_UNIMPLEMENTED_CMD); - break; - } - - // Send the reply - txMsg(respMsg); - } else { - ALOGE("%s: ParseFromString() failed. msgSize=%d", __func__, static_cast(msg.size())); +void VehicleEmulator::processMessage(emulator::EmulatorMessage const& rxMsg, + emulator::EmulatorMessage& respMsg) { + switch (rxMsg.msg_type()) { + case emulator::GET_CONFIG_CMD: + doGetConfig(rxMsg, respMsg); + break; + case emulator::GET_CONFIG_ALL_CMD: + doGetConfigAll(rxMsg, respMsg); + break; + case emulator::GET_PROPERTY_CMD: + doGetProperty(rxMsg, respMsg); + break; + case emulator::GET_PROPERTY_ALL_CMD: + doGetPropertyAll(rxMsg, respMsg); + break; + case emulator::SET_PROPERTY_CMD: + doSetProperty(rxMsg, respMsg); + break; + default: + ALOGW("%s: Unknown message received, type = %d", __func__, rxMsg.msg_type()); + respMsg.set_status(emulator::ERROR_UNIMPLEMENTED_CMD); + break; } } @@ -316,40 +300,6 @@ void VehicleEmulator::populateProtoVehiclePropValue(emulator::VehiclePropValue* } } -void VehicleEmulator::rxMsg() { - while (!mExit) { - std::vector msg = mComm->read(); - - if (msg.size() > 0) { - // Received a message. - parseRxProtoBuf(msg); - } else { - // This happens when connection is closed - ALOGD("%s: msgSize=%zu", __func__, msg.size()); - break; - } - } -} - -void VehicleEmulator::rxThread() { - if (mExit) return; - - int retVal = mComm->open(); - if (retVal != 0) mExit = true; - - // Comms are properly opened - while (!mExit) { - retVal = mComm->connect(); - - if (retVal >= 0) { - rxMsg(); - } - - // Check every 100ms for a new connection - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - } -} - } // impl } // namespace V2_0 diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.h index 1a8cfe2c48..58e387a749 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.h +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.h @@ -24,7 +24,9 @@ #include "vhal_v2_0/VehicleHal.h" -#include "CommBase.h" +#include "CommConn.h" +#include "PipeComm.h" +#include "SocketComm.h" #include "VehicleHalProto.pb.h" namespace android { @@ -61,48 +63,36 @@ private: VehicleEmulator* mEmulator; }; -struct CommFactory { - static std::unique_ptr create(); -}; - /** * Emulates vehicle by providing controlling interface from host side either through ADB or Pipe. */ -class VehicleEmulator { -public: - VehicleEmulator(EmulatedVehicleHalIface* hal, - std::unique_ptr comm = CommFactory::create()) - : mHal { hal }, - mComm(comm.release()), - mThread { &VehicleEmulator::rxThread, this} { - mHal->registerEmulator(this); - } +class VehicleEmulator : public MessageProcessor { + public: + VehicleEmulator(EmulatedVehicleHalIface* hal); virtual ~VehicleEmulator(); void doSetValueFromClient(const VehiclePropValue& propValue); + void processMessage(emulator::EmulatorMessage const& rxMsg, + emulator::EmulatorMessage& respMsg) override; -private: + private: + friend class ConnectionThread; using EmulatorMessage = emulator::EmulatorMessage; - void doGetConfig(EmulatorMessage& rxMsg, EmulatorMessage& respMsg); - void doGetConfigAll(EmulatorMessage& rxMsg, EmulatorMessage& respMsg); - void doGetProperty(EmulatorMessage& rxMsg, EmulatorMessage& respMsg); - void doGetPropertyAll(EmulatorMessage& rxMsg, EmulatorMessage& respMsg); - void doSetProperty(EmulatorMessage& rxMsg, EmulatorMessage& respMsg); - void txMsg(emulator::EmulatorMessage& txMsg); - void parseRxProtoBuf(std::vector& msg); + void doGetConfig(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg); + void doGetConfigAll(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg); + void doGetProperty(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg); + void doGetPropertyAll(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg); + void doSetProperty(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg); void populateProtoVehicleConfig(emulator::VehiclePropConfig* protoCfg, const VehiclePropConfig& cfg); void populateProtoVehiclePropValue(emulator::VehiclePropValue* protoVal, const VehiclePropValue* val); - void rxMsg(); - void rxThread(); private: - std::atomic mExit { false }; EmulatedVehicleHalIface* mHal; - std::unique_ptr mComm; - std::thread mThread; + std::unique_ptr mSocketComm; + std::unique_ptr mPipeComm; }; } // impl From f6d3b2fa3fffd2ff19ec1020e221026dc6ac0ce3 Mon Sep 17 00:00:00 2001 From: chenhg Date: Wed, 20 Jun 2018 14:21:20 -0700 Subject: [PATCH 044/718] Camera: provide thumbnail size for more jpeg aspect ratios. BUG: 110462045 Test: Camera CTS Change-Id: I5f5500a5e4d02c3cbaa127cd9f222d241f047044 --- camera/device/3.4/default/ExternalCameraDevice.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/camera/device/3.4/default/ExternalCameraDevice.cpp b/camera/device/3.4/default/ExternalCameraDevice.cpp index ee7ffaa8d6..15e5106e3a 100644 --- a/camera/device/3.4/default/ExternalCameraDevice.cpp +++ b/camera/device/3.4/default/ExternalCameraDevice.cpp @@ -290,8 +290,14 @@ status_t ExternalCameraDevice::initDefaultCharsKeys( UPDATE(ANDROID_HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES, &hotPixelMode, 1); // android.jpeg - // TODO: b/72261675 See if we can provide thumbnail size for all jpeg aspect ratios - const int32_t jpegAvailableThumbnailSizes[] = {0, 0, 240, 180}; + const int32_t jpegAvailableThumbnailSizes[] = {0, 0, + 176, 144, + 240, 144, + 256, 144, + 240, 160, + 256, 154, + 240, 240, + 320, 240}; UPDATE(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES, jpegAvailableThumbnailSizes, ARRAY_SIZE(jpegAvailableThumbnailSizes)); From 8765444e2013cae6f1036e4b7d591351c4eb97ea Mon Sep 17 00:00:00 2001 From: chenhg Date: Fri, 22 Jun 2018 13:27:50 -0700 Subject: [PATCH 045/718] Camera: allow to configure minimum stream size. HW video encoder usually has limitation to encode very small stream. Camera should avoid to return such streams to avoid video encoding failure. BUG: 110654511 Test: CTS android.hardware.camera2.cts.RecordingTest#testSupportedVideoSizes Change-Id: I6104f2d4efcf7831d1dc6d305c82309e2fd1999d --- camera/device/3.4/default/ExternalCameraDevice.cpp | 12 +++++++++--- camera/device/3.4/default/ExternalCameraUtils.cpp | 12 ++++++++++++ .../ext_device_v3_4_impl/ExternalCameraDevice_3_4.h | 3 ++- .../ext_device_v3_4_impl/ExternalCameraUtils.h | 3 +++ 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/camera/device/3.4/default/ExternalCameraDevice.cpp b/camera/device/3.4/default/ExternalCameraDevice.cpp index ee7ffaa8d6..167b62378b 100644 --- a/camera/device/3.4/default/ExternalCameraDevice.cpp +++ b/camera/device/3.4/default/ExternalCameraDevice.cpp @@ -787,7 +787,8 @@ void ExternalCameraDevice::trimSupportedFormats( std::vector ExternalCameraDevice::getCandidateSupportedFormatsLocked( int fd, CroppingType cropType, - const std::vector& fpsLimits) { + const std::vector& fpsLimits, + const Size& minStreamSize) { std::vector outFmts; struct v4l2_fmtdesc fmtdesc { .index = 0, @@ -822,6 +823,11 @@ ExternalCameraDevice::getCandidateSupportedFormatsLocked( if (frameSize.discrete.height > frameSize.discrete.width) { continue; } + // Discard all formats which is smaller than minStreamSize + if (frameSize.discrete.width < minStreamSize.width + || frameSize.discrete.height < minStreamSize.height) { + continue; + } SupportedV4L2Format format { .width = frameSize.discrete.width, .height = frameSize.discrete.height, @@ -864,9 +870,9 @@ ExternalCameraDevice::getCandidateSupportedFormatsLocked( void ExternalCameraDevice::initSupportedFormatsLocked(int fd) { std::vector horizontalFmts = - getCandidateSupportedFormatsLocked(fd, HORIZONTAL, mCfg.fpsLimits); + getCandidateSupportedFormatsLocked(fd, HORIZONTAL, mCfg.fpsLimits, mCfg.minStreamSize); std::vector verticalFmts = - getCandidateSupportedFormatsLocked(fd, VERTICAL, mCfg.fpsLimits); + getCandidateSupportedFormatsLocked(fd, VERTICAL, mCfg.fpsLimits, mCfg.minStreamSize); size_t horiSize = horizontalFmts.size(); size_t vertSize = verticalFmts.size(); diff --git a/camera/device/3.4/default/ExternalCameraUtils.cpp b/camera/device/3.4/default/ExternalCameraUtils.cpp index 2e2f73b362..680c95ad3b 100644 --- a/camera/device/3.4/default/ExternalCameraUtils.cpp +++ b/camera/device/3.4/default/ExternalCameraUtils.cpp @@ -267,6 +267,15 @@ ExternalCameraConfig ExternalCameraConfig::loadFromCfg(const char* cfgPath) { ret.fpsLimits = limits; } + XMLElement *minStreamSize = deviceCfg->FirstChildElement("MinimumStreamSize"); + if (minStreamSize == nullptr) { + ALOGI("%s: no minimum stream size specified", __FUNCTION__); + } else { + ret.minStreamSize = { + minStreamSize->UnsignedAttribute("width", /*Default*/0), + minStreamSize->UnsignedAttribute("height", /*Default*/0)}; + } + ALOGI("%s: external camera cfg loaded: maxJpgBufSize %d," " num video buffers %d, num still buffers %d", __FUNCTION__, ret.maxJpegBufSize, @@ -275,6 +284,8 @@ ExternalCameraConfig ExternalCameraConfig::loadFromCfg(const char* cfgPath) { ALOGI("%s: fpsLimitList: %dx%d@%f", __FUNCTION__, limit.size.width, limit.size.height, limit.fpsUpperBound); } + ALOGI("%s: minStreamSize: %dx%d" , __FUNCTION__, + ret.minStreamSize.width, ret.minStreamSize.height); return ret; } @@ -285,6 +296,7 @@ ExternalCameraConfig::ExternalCameraConfig() : fpsLimits.push_back({/*Size*/{ 640, 480}, /*FPS upper bound*/30.0}); fpsLimits.push_back({/*Size*/{1280, 720}, /*FPS upper bound*/7.5}); fpsLimits.push_back({/*Size*/{1920, 1080}, /*FPS upper bound*/5.0}); + minStreamSize = {0, 0}; } diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h index a52f0e4ccb..ff0cfb301e 100644 --- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h +++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h @@ -96,7 +96,8 @@ protected: // Get candidate supported formats list of input cropping type. static std::vector getCandidateSupportedFormatsLocked( int fd, CroppingType cropType, - const std::vector& fpsLimits); + const std::vector& fpsLimits, + const Size& minStreamSize); // Trim supported format list by the cropping type. Also sort output formats by width/height static void trimSupportedFormats(CroppingType cropType, /*inout*/std::vector* pFmts); diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h index 37e7cfb32e..5754ccbec3 100644 --- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h +++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h @@ -77,6 +77,9 @@ struct ExternalCameraConfig { }; std::vector fpsLimits; + // Minimum output stream size + Size minStreamSize; + private: ExternalCameraConfig(); }; From 93b5778e9c095bb38be0ecb82bc1fbb762fcc973 Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Mon, 9 Jul 2018 14:28:57 -0700 Subject: [PATCH 046/718] Fix audio port "mix" role parameter conversion 'usecase.source' field is used for AUDIO_PORT_ROLE_SINK, 'usecase.stream' field is used for AUDIO_PORT_ROLE_SOURCE. The HIDL<->legacy conversion code was doing it opposite. Test: make Change-Id: I93722f422a8f226f11a6be97215453af3234029c --- .../common/all-versions/default/HidlUtils.impl.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.impl.h b/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.impl.h index 8ab73501bc..632e816070 100644 --- a/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.impl.h +++ b/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.impl.h @@ -174,9 +174,9 @@ void HidlUtils::audioPortConfigFromHal(const struct audio_port_config& halConfig config->ext.mix.hwModule = halConfig.ext.mix.hw_module; config->ext.mix.ioHandle = halConfig.ext.mix.handle; if (halConfig.role == AUDIO_PORT_ROLE_SOURCE) { - config->ext.mix.useCase.source = AudioSource(halConfig.ext.mix.usecase.source); - } else if (halConfig.role == AUDIO_PORT_ROLE_SINK) { config->ext.mix.useCase.stream = AudioStreamType(halConfig.ext.mix.usecase.stream); + } else if (halConfig.role == AUDIO_PORT_ROLE_SINK) { + config->ext.mix.useCase.source = AudioSource(halConfig.ext.mix.usecase.source); } break; } @@ -212,11 +212,11 @@ void HidlUtils::audioPortConfigToHal(const AudioPortConfig& config, halConfig->ext.mix.hw_module = config.ext.mix.hwModule; halConfig->ext.mix.handle = config.ext.mix.ioHandle; if (config.role == AudioPortRole::SOURCE) { - halConfig->ext.mix.usecase.source = - static_cast(config.ext.mix.useCase.source); - } else if (config.role == AudioPortRole::SINK) { halConfig->ext.mix.usecase.stream = static_cast(config.ext.mix.useCase.stream); + } else if (config.role == AudioPortRole::SINK) { + halConfig->ext.mix.usecase.source = + static_cast(config.ext.mix.useCase.source); } break; } From 1ffc50ad70dea0d1964bd860a2a40bf8fd2682fc Mon Sep 17 00:00:00 2001 From: Yifan Hong Date: Tue, 10 Jul 2018 11:53:58 -0700 Subject: [PATCH 047/718] health: remove unused flag HEALTHD_USE_HEALTH_2_0 Test: boots Change-Id: Idc27ad452b799ef2ce4f18c787f2aa2afd1dd8cf --- health/2.0/default/Android.bp | 2 -- 1 file changed, 2 deletions(-) diff --git a/health/2.0/default/Android.bp b/health/2.0/default/Android.bp index 8eb02e0d76..03aa77bf54 100644 --- a/health/2.0/default/Android.bp +++ b/health/2.0/default/Android.bp @@ -6,8 +6,6 @@ cc_library_static { "healthd_common.cpp", ], - cflags: ["-DHEALTHD_USE_HEALTH_2_0"], - export_include_dirs: ["include"], shared_libs: [ From 14d43837628ee3d1935fb2e33145eff0ba5c0273 Mon Sep 17 00:00:00 2001 From: Yifan Hong Date: Tue, 10 Jul 2018 13:41:04 -0700 Subject: [PATCH 048/718] health: libhealthstoragedefault: recovery_available Test: builds Bug: 80132328 Change-Id: I2c4d880968e6938806cb9a2cf65352c73748f4ce --- health/2.0/utils/libhealthstoragedefault/Android.bp | 1 + 1 file changed, 1 insertion(+) diff --git a/health/2.0/utils/libhealthstoragedefault/Android.bp b/health/2.0/utils/libhealthstoragedefault/Android.bp index cef04fefdf..5bc8b9fdef 100644 --- a/health/2.0/utils/libhealthstoragedefault/Android.bp +++ b/health/2.0/utils/libhealthstoragedefault/Android.bp @@ -21,6 +21,7 @@ cc_library_static { srcs: ["StorageHealthDefault.cpp"], name: "libhealthstoragedefault", vendor_available: true, + recovery_available: true, cflags: ["-Werror"], shared_libs: [ "android.hardware.health@2.0", From 4e40086d39ac31692212ddefafb926dd8894f80c Mon Sep 17 00:00:00 2001 From: Yifan Hong Date: Tue, 10 Jul 2018 11:47:21 -0700 Subject: [PATCH 049/718] health@2.0-impl: recovery_available: true ... so that it can be installed to recovery image. Test: build and inspect out dir Test: boot to recovery and 'adb shell ls /vendor/lib64/hw' Bug: 80132328 Change-Id: Icb33c9e9e648b54db33cac23ed877392cce4e76b --- health/1.0/default/Android.bp | 1 + health/2.0/default/Android.bp | 3 +++ 2 files changed, 4 insertions(+) diff --git a/health/1.0/default/Android.bp b/health/1.0/default/Android.bp index cb2e87d16e..8fbb8c343e 100644 --- a/health/1.0/default/Android.bp +++ b/health/1.0/default/Android.bp @@ -1,6 +1,7 @@ cc_library_static { name: "android.hardware.health@1.0-convert", vendor_available: true, + recovery_available: true, srcs: ["convert.cpp"], include_dirs: [ "system/core/base/include", diff --git a/health/2.0/default/Android.bp b/health/2.0/default/Android.bp index 03aa77bf54..6301a06e3f 100644 --- a/health/2.0/default/Android.bp +++ b/health/2.0/default/Android.bp @@ -1,6 +1,9 @@ +// Helper library for implementing health HAL. It is recommended that a health +// service or passthrough HAL link to this library. cc_library_static { name: "android.hardware.health@2.0-impl", vendor_available: true, + recovery_available: true, srcs: [ "Health.cpp", "healthd_common.cpp", From 339c3c2f1b56b62d9d44b8ca36d7bc59166db631 Mon Sep 17 00:00:00 2001 From: Josh Gao Date: Thu, 19 Jul 2018 11:14:49 -0700 Subject: [PATCH 050/718] Hack around wifi_legacy_hal.h transitive include bug. Bug: http://b/111617490 Test: treehugger Change-Id: Ic98b8f253ae42107cddb90475044a063db2c666c --- wifi/1.2/default/wifi_legacy_hal.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/wifi/1.2/default/wifi_legacy_hal.h b/wifi/1.2/default/wifi_legacy_hal.h index 60905ab399..00dfeefb9a 100644 --- a/wifi/1.2/default/wifi_legacy_hal.h +++ b/wifi/1.2/default/wifi_legacy_hal.h @@ -25,6 +25,12 @@ #include +// HACK: The include inside the namespace below also transitively includes a +// bunch of libc headers into the namespace, which leads to functions like +// socketpair being defined in android::hardware::wifi::V1_1::implementation::legacy_hal. +// Include this one particular header as a hacky workaround until that's fixed. +#include + namespace android { namespace hardware { namespace wifi { From cfb94787eae52b0a32e920d530a1bba68480d99e Mon Sep 17 00:00:00 2001 From: davidln Date: Mon, 2 Jul 2018 17:10:53 -0700 Subject: [PATCH 051/718] Propagate set events in the emulated vehicle HAL. Bug: 110105682 Test: build, deploy, test updating temp via app UI, temp change reflected in subscribed system UI Change-Id: I75e6825ff9450f977c1f5d7f2b97bca6c78f1883 (cherry picked from commit 6d8110ffbf7e964246c13810d909b3a5cf7818b6) --- .../vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp index c6955e03b0..58d8867c30 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp @@ -187,6 +187,7 @@ StatusCode EmulatedVehicleHal::set(const VehiclePropValue& propValue) { } getEmulatorOrDie()->doSetValueFromClient(propValue); + doHalEvent(getValuePool()->obtain(propValue)); return StatusCode::OK; } From ddedf725321905ad399b322c72f9c818ec15c1c6 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Fri, 4 May 2018 13:30:43 -0700 Subject: [PATCH 052/718] wifi(unit-tests): Fix runtests.sh Bug: 79261060 Test: ./hardware/interfaces/wifi/1.2/default/tests/runtests.sh Change-Id: If7d82dcd4186b71a34ae98f2ff130fe5f074db14 --- wifi/1.2/default/Android.mk | 2 +- wifi/1.2/default/tests/runtests.sh | 30 +++--------------------------- 2 files changed, 4 insertions(+), 28 deletions(-) diff --git a/wifi/1.2/default/Android.mk b/wifi/1.2/default/Android.mk index 391969018c..8c5371b883 100644 --- a/wifi/1.2/default/Android.mk +++ b/wifi/1.2/default/Android.mk @@ -107,11 +107,11 @@ LOCAL_SRC_FILES := \ LOCAL_STATIC_LIBRARIES := \ libgmock \ libgtest \ + libhidlbase \ android.hardware.wifi@1.0-service-lib LOCAL_SHARED_LIBRARIES := \ libbase \ libcutils \ - libhidlbase \ libhidltransport \ liblog \ libnl \ diff --git a/wifi/1.2/default/tests/runtests.sh b/wifi/1.2/default/tests/runtests.sh index 966a6a751c..590619367d 100755 --- a/wifi/1.2/default/tests/runtests.sh +++ b/wifi/1.2/default/tests/runtests.sh @@ -18,33 +18,9 @@ if [ -z $ANDROID_BUILD_TOP ]; then echo "You need to source and lunch before you can use this script" exit 1 fi +set -e -echo "Running tests" -set -e # fail early - -#NOTE We can't actually run these commands, since they rely on functions added by -#build / envsetup.sh to the bash shell environment. -echo "+ mmma -j32 $ANDROID_BUILD_TOP/" -make -j32 -C $ANDROID_BUILD_TOP -f build/core/main.mk \ - MODULES-IN-hardware-interfaces-wifi-1.2-default - -set -x # print commands - -adb wait-for-device +$ANDROID_BUILD_TOP/build/soong/soong_ui.bash --make-mode android.hardware.wifi@1.0-service-tests adb root -adb wait-for-device - -#'disable-verity' will appear in 'adb remount' output if -#dm - verity is enabled and needs to be disabled. -if adb remount | grep 'disable-verity'; then - adb disable-verity - adb reboot - adb wait-for-device - adb root - adb wait-for-device - adb remount -fi - -adb sync - +adb sync data adb shell /data/nativetest/vendor/android.hardware.wifi@1.0-service-tests/android.hardware.wifi@1.0-service-tests From 3418cd60774109a24061d8973a0f9e87b81e4c98 Mon Sep 17 00:00:00 2001 From: Jeff Tinker Date: Mon, 30 Jul 2018 12:05:43 -0700 Subject: [PATCH 053/718] Remove spurious error log message In change id Ie2f306bce6aec697ae584da3f55b3cf72edaa07b, a shared memory leak was fixed using a workaround that maintained compatibility with the frozen DRM HAL API 1.1. Unfortunately it triggered an error log message that was no longer an error condition. This change just removes the log line to avoid raising undue concerns. Change-Id: I9abe08ef5ab86b2f8589a5c1e5c5175e19ab09d2 Test: Compiles Bug:111131173 --- drm/1.0/default/CryptoPlugin.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/drm/1.0/default/CryptoPlugin.cpp b/drm/1.0/default/CryptoPlugin.cpp index f9c868db8b..666653b261 100644 --- a/drm/1.0/default/CryptoPlugin.cpp +++ b/drm/1.0/default/CryptoPlugin.cpp @@ -52,7 +52,6 @@ namespace implementation { Return CryptoPlugin::setSharedBufferBase(const hidl_memory& base, uint32_t bufferId) { sp hidlMemory = mapMemory(base); - ALOGE_IF(hidlMemory == nullptr, "mapMemory returns nullptr"); // allow mapMemory to return nullptr mSharedBufferMap[bufferId] = hidlMemory; From 2209bcb1868fad1b1b62233bd750a814674651c7 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Wed, 1 Aug 2018 10:01:02 -0700 Subject: [PATCH 054/718] graphics: test buffer allocation for thread safety Bug: 111604912 Test: VTS Change-Id: I1b6cacc8d6ff5e1c145425ff6f32001090b07b06 --- .../VtsHalGraphicsMapperV2_0TargetTest.cpp | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp index aa9beff735..5ec0af2cda 100644 --- a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp +++ b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp @@ -16,6 +16,10 @@ #define LOG_TAG "VtsHalGraphicsMapperV2_0TargetTest" +#include +#include +#include + #include #include #include @@ -124,6 +128,36 @@ TEST_F(GraphicsMapperHidlTest, AllocatorAllocateNoLeak) { } } +/** + * Test that IAllocator::allocate is thread-safe. + */ +TEST_F(GraphicsMapperHidlTest, AllocatorAllocateThreaded) { + BufferDescriptor descriptor; + ASSERT_NO_FATAL_FAILURE(descriptor = mGralloc->createDescriptor(mDummyDescriptorInfo)); + + std::atomic timeUp(false); + std::atomic allocationCount(0); + auto threadLoop = [&]() { + while (!timeUp) { + mGralloc->getAllocator()->allocate( + descriptor, 1, [&](const auto&, const auto&, const auto&) { allocationCount++; }); + } + }; + + std::vector threads; + for (int i = 0; i < 8; i++) { + threads.push_back(std::thread(threadLoop)); + } + + std::this_thread::sleep_for(std::chrono::seconds(3)); + timeUp = true; + LOG(VERBOSE) << "Made " << allocationCount << " threaded allocations"; + + for (auto& thread : threads) { + thread.join(); + } +} + /** * Test IMapper::createDescriptor with valid descriptor info. */ From 9d7cb65c6bd10319b21feefdda4e74a4830cdecf Mon Sep 17 00:00:00 2001 From: Kevin Rocard Date: Thu, 12 Jul 2018 19:38:35 -0700 Subject: [PATCH 055/718] Aaudio: Implement app shareable flag instead of -size hack Test: adb shell data/nativetest64/write_sine/write_sine -pl -m3 Bug: 38118159 Change-Id: I2e2fc5801ee9f45565be6f989c0d83d0fdf54618 Signed-off-by: Kevin Rocard --- .../include/core/all-versions/default/Stream.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/audio/core/all-versions/default/include/core/all-versions/default/Stream.h b/audio/core/all-versions/default/include/core/all-versions/default/Stream.h index 6f79429c61..375759dcff 100644 --- a/audio/core/all-versions/default/include/core/all-versions/default/Stream.h +++ b/audio/core/all-versions/default/include/core/all-versions/default/Stream.h @@ -163,6 +163,22 @@ Return StreamMmap::createMmapBuffer(int32_t minSizeFrames, size_t frame if (retval == Result::OK) { hidlHandle = native_handle_create(1, 0); hidlHandle->data[0] = halInfo.shared_memory_fd; + + // Negative buffer size frame is a legacy hack to indicate that the buffer + // is shareable to applications before the relevant flag was introduced + bool applicationShareable = + halInfo.flags & AUDIO_MMAP_APPLICATION_SHAREABLE || halInfo.buffer_size_frames < 0; + halInfo.buffer_size_frames = abs(halInfo.buffer_size_frames); +#ifdef AUDIO_HAL_VERSION_2_0 + if (applicationShareable) { + halInfo.buffer_size_frames *= -1; + } +#else + info.flags = + halInfo.flags | (applicationShareable ? MmapBufferFlag::APPLICATION_SHAREABLE + : MmapBufferFlag::NONE); +#endif + info.sharedMemory = hidl_memory("audio_buffer", hidlHandle, frameSize * halInfo.buffer_size_frames); info.bufferSizeFrames = halInfo.buffer_size_frames; From 9667b10cd016ad7ad7542d228acd47375a427c4d Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Mon, 6 Aug 2018 10:13:40 -0700 Subject: [PATCH 056/718] wifi(tests): Run the 64bit version of the unit tests libwifi-hal is only available on /vendor/lib64. Bug: 79261060 Test: ./hardware/interfaces/wifi/1.2/default/tests/runtests.sh Change-Id: Ia35e4246f812ceaf67c93f19101ba6cd77525694 --- wifi/1.2/default/tests/runtests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wifi/1.2/default/tests/runtests.sh b/wifi/1.2/default/tests/runtests.sh index 590619367d..6bce3ef8c4 100755 --- a/wifi/1.2/default/tests/runtests.sh +++ b/wifi/1.2/default/tests/runtests.sh @@ -23,4 +23,4 @@ set -e $ANDROID_BUILD_TOP/build/soong/soong_ui.bash --make-mode android.hardware.wifi@1.0-service-tests adb root adb sync data -adb shell /data/nativetest/vendor/android.hardware.wifi@1.0-service-tests/android.hardware.wifi@1.0-service-tests +adb shell /data/nativetest64/vendor/android.hardware.wifi@1.0-service-tests/android.hardware.wifi@1.0-service-tests From 5845a3f05c1eee410e7f1026bd44d8b6b3ac8831 Mon Sep 17 00:00:00 2001 From: Eino-Ville Talvala Date: Wed, 1 Aug 2018 17:31:44 -0700 Subject: [PATCH 057/718] Camera: Minor doc update Autogenerated from a larger set of total doc changes Test: Builds, manual inspection of docs Bug: 109817371 Change-Id: Ibc2415531a16e42ae81e33c3bdb28aca08e6a5fe --- camera/metadata/3.3/types.hal | 4 ++-- current.txt | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/camera/metadata/3.3/types.hal b/camera/metadata/3.3/types.hal index 04edfe9fb4..a37e132176 100644 --- a/camera/metadata/3.3/types.hal +++ b/camera/metadata/3.3/types.hal @@ -109,8 +109,8 @@ enum CameraMetadataTag : @3.2::CameraMetadataTag { /** android.statistics.oisDataMode [dynamic, enum, public] * - *

A control for selecting whether OIS position information is included in output - * result metadata.

+ *

A control for selecting whether optical stabilization (OIS) position + * information is included in output result metadata.

*/ ANDROID_STATISTICS_OIS_DATA_MODE = android.hardware.camera.metadata@3.2::CameraMetadataTag:ANDROID_STATISTICS_END, diff --git a/current.txt b/current.txt index f1c09fde5d..e66d34576d 100644 --- a/current.txt +++ b/current.txt @@ -384,6 +384,7 @@ cd4330c3196bda1d642a32abfe23a7d64ebfbda721940643af6867af3b3f0aa9 android.hardwar 10ff2fae516346b86121368ce5790d5accdfcb73983246b813f3d488b66db45a android.hardware.wifi.supplicant@1.1::ISupplicantStaNetwork # ABI preserving changes to HALs during Android Q +a95745bbf76aea16a76518bd7efe70cabc5886d09eaeffc993c2e1787a22ed23 android.hardware.camera.metadata@3.3::types 574e8f1499436fb4075894dcae0b36682427956ecb114f17f1fe22d116a83c6b android.hardware.neuralnetworks@1.0::IPreparedModel 1a5ae9793223658174258b523763c557abad6fb917df0b8e3cc097fc89035811 android.hardware.neuralnetworks@1.0::types 4310eb8272f085914952f3bfb73a8f8bb477a80e8b93596f0ea5acb58546b66d android.hardware.neuralnetworks@1.1::types From 61b24e3a44d3aafeab353dd123e74b92eb9c50a9 Mon Sep 17 00:00:00 2001 From: Steve Paik Date: Wed, 1 Aug 2018 15:55:14 -0700 Subject: [PATCH 058/718] Add PERF_VEHICLE_SPEED_DISPLAY Bug: 110881960 Test: none Change-Id: I486d71bb00e2d943293e5e5567f4dbb0c35e39b0 --- automotive/vehicle/2.0/types.hal | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal index 57179dfd67..48b2ec28ea 100644 --- a/automotive/vehicle/2.0/types.hal +++ b/automotive/vehicle/2.0/types.hal @@ -305,6 +305,22 @@ enum VehicleProperty : int32_t { | VehiclePropertyType:FLOAT | VehicleArea:GLOBAL), + /** + * Speed of the vehicle for displays + * + * Some cars display a slightly slower speed than the actual speed. This is + * usually displayed on the speedometer. + * + * @change_mode VehiclePropertyChangeMode:CONTINUOUS + * @access VehiclePropertyAccess:READ + * @unit VehicleUnit:METER_PER_SEC + */ + PERF_VEHICLE_SPEED_DISPLAY = ( + 0x0208 + | VehiclePropertyGroup:SYSTEM + | VehiclePropertyType:FLOAT + | VehicleArea:GLOBAL), + /** * Temperature of engine coolant * From 1c2621bf00b18d1a626cadc65d4af20bfbdae991 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Thu, 9 Aug 2018 10:22:38 -0700 Subject: [PATCH 059/718] graphics: composer@2.2 does not require mapper@2.1 Fix composer@2.2 VTS to not require mapper@2.1. We will need a better test infra before things get too complex. Bug: 112248843 Test: manual Change-Id: Ia71a102742fd26f14e8edf3f43f3351786350ccd --- .../VtsHalGraphicsComposerV2_2TargetTest.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp index e3b7f55451..e40dc22396 100644 --- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp +++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp @@ -18,11 +18,11 @@ #include #include -#include +#include #include #include #include -#include +#include namespace android { namespace hardware { @@ -39,8 +39,8 @@ using common::V1_1::ColorMode; using common::V1_1::Dataspace; using common::V1_1::PixelFormat; using common::V1_1::RenderIntent; -using mapper::V2_1::IMapper; -using mapper::V2_1::vts::Gralloc; +using mapper::V2_0::IMapper; +using mapper::V2_0::vts::Gralloc; // Test environment for graphics.composer class GraphicsComposerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { @@ -134,7 +134,7 @@ class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest { info.width = 64; info.height = 64; info.layerCount = 1; - info.format = PixelFormat::RGBA_8888; + info.format = static_cast(PixelFormat::RGBA_8888); info.usage = static_cast(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN); @@ -278,7 +278,7 @@ TEST_F(GraphicsComposerHidlTest, setReadbackBuffer) { info.height = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config, IComposerClient::Attribute::HEIGHT); info.layerCount = 1; - info.format = pixelFormat; + info.format = static_cast(pixelFormat); // BufferUsage::COMPOSER_OUTPUT is missing info.usage = static_cast(BufferUsage::COMPOSER_OVERLAY | BufferUsage::CPU_READ_OFTEN); From e11cca0ac73a6524cdd2d9b3e091f64a47290803 Mon Sep 17 00:00:00 2001 From: Brian Duddie Date: Thu, 9 Aug 2018 11:53:44 -0700 Subject: [PATCH 060/718] Update OWNERS for contexthub Reflect changes in team. Test: n/a Change-Id: I2fbf83f6fce56e3886a7c09128f1516f38c8cde3 --- contexthub/1.0/default/OWNERS | 4 +++- contexthub/1.0/vts/functional/OWNERS | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/contexthub/1.0/default/OWNERS b/contexthub/1.0/default/OWNERS index 49a3204ac7..5373073cb8 100644 --- a/contexthub/1.0/default/OWNERS +++ b/contexthub/1.0/default/OWNERS @@ -1,2 +1,4 @@ -ashutoshj@google.com +aarossig@google.com +arthuri@google.com bduddie@google.com +bstack@google.com diff --git a/contexthub/1.0/vts/functional/OWNERS b/contexthub/1.0/vts/functional/OWNERS index ad036b4215..ee01441e4f 100644 --- a/contexthub/1.0/vts/functional/OWNERS +++ b/contexthub/1.0/vts/functional/OWNERS @@ -1,6 +1,8 @@ #Context Hub team -ashutoshj@google.com +aarossig@google.com +arthuri@google.com bduddie@google.com +bstack@google.com #VTS team yim@google.com From 70c148b739febfe443ae95891b913e7dcb1c790a Mon Sep 17 00:00:00 2001 From: Brian Duddie Date: Thu, 9 Aug 2018 11:56:39 -0700 Subject: [PATCH 061/718] Update sensors OWNERS files Reflect changes in team membership. Fixes: 74439746 Test: n/a Change-Id: I936b9dd9229024989bc6100a4fe396e822d53369 --- sensors/1.0/default/OWNERS | 4 ++-- sensors/1.0/vts/functional/OWNERS | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sensors/1.0/default/OWNERS b/sensors/1.0/default/OWNERS index 6a38a1ff14..2031d848cf 100644 --- a/sensors/1.0/default/OWNERS +++ b/sensors/1.0/default/OWNERS @@ -1,2 +1,2 @@ -ashutoshj@google.com -pengxu@google.com +bduddie@google.com +bstack@google.com diff --git a/sensors/1.0/vts/functional/OWNERS b/sensors/1.0/vts/functional/OWNERS index 8715e5d787..759d87b482 100644 --- a/sensors/1.0/vts/functional/OWNERS +++ b/sensors/1.0/vts/functional/OWNERS @@ -1,6 +1,6 @@ # Sensors team -ashutoshj@google.com -pengxu@google.com +bduddie@google.com +bstack@google.com # VTS team trong@google.com From a8fc3a2542b9e636bd43a0397f8479ba4734604f Mon Sep 17 00:00:00 2001 From: Yifan Hong Date: Thu, 9 Aug 2018 13:42:33 -0700 Subject: [PATCH 062/718] matrix (current): IR HAL specifies interface/instance This is missing from a very old CL. IR is an optional HAL so specifying interface / instance here doesn't break requirements. Test: builds Change-Id: I3aeab2798ce48cd1851b155fd41194fe70357aa2 --- compatibility_matrices/compatibility_matrix.current.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml index f14fceacee..3d65cc301b 100644 --- a/compatibility_matrices/compatibility_matrix.current.xml +++ b/compatibility_matrices/compatibility_matrix.current.xml @@ -210,6 +210,10 @@ android.hardware.ir 1.0 + + IConsumerIr + default + android.hardware.keymaster From da830c9da771267158ed239d9a6680f723784939 Mon Sep 17 00:00:00 2001 From: Jong Wook Kim Date: Mon, 23 Jul 2018 15:29:38 -0700 Subject: [PATCH 063/718] Uprev Wifi HAL to 1.3 Move Wifi HAL from 1.2 to 1.3 Bug: 111753174 Test: Builds and wifi works Change-Id: I6a2b203997d6328d09065f23636d4ce01420942a --- .../compatibility_matrix.current.xml | 2 +- wifi/1.3/Android.bp | 20 +++++++ wifi/1.3/IWifi.hal | 28 +++++++++ wifi/{1.2 => 1.3}/default/Android.mk | 9 ++- wifi/{1.2 => 1.3}/default/OWNERS | 0 wifi/{1.2 => 1.3}/default/THREADING.README | 0 .../android.hardware.wifi@1.0-service.rc | 0 .../{1.2 => 1.3}/default/hidl_callback_util.h | 4 +- wifi/{1.2 => 1.3}/default/hidl_return_util.h | 4 +- .../{1.2 => 1.3}/default/hidl_struct_util.cpp | 57 ++++++++++--------- wifi/{1.2 => 1.3}/default/hidl_struct_util.h | 17 +++--- wifi/{1.2 => 1.3}/default/hidl_sync_util.cpp | 4 +- wifi/{1.2 => 1.3}/default/hidl_sync_util.h | 4 +- wifi/{1.2 => 1.3}/default/ringbuffer.cpp | 4 +- wifi/{1.2 => 1.3}/default/ringbuffer.h | 4 +- wifi/{1.2 => 1.3}/default/service.cpp | 10 ++-- .../tests/hidl_struct_util_unit_tests.cpp | 32 ++++++----- wifi/{1.2 => 1.3}/default/tests/main.cpp | 0 .../default/tests/mock_wifi_feature_flags.cpp | 4 +- .../default/tests/mock_wifi_feature_flags.h | 4 +- .../default/tests/mock_wifi_legacy_hal.cpp | 4 +- .../default/tests/mock_wifi_legacy_hal.h | 4 +- .../tests/mock_wifi_mode_controller.cpp | 4 +- .../default/tests/mock_wifi_mode_controller.h | 4 +- .../default/tests/ringbuffer_unit_tests.cpp | 4 +- wifi/{1.2 => 1.3}/default/tests/runtests.sh | 0 .../default/tests/wifi_chip_unit_tests.cpp | 38 ++++++------- wifi/{1.2 => 1.3}/default/wifi.cpp | 4 +- wifi/{1.2 => 1.3}/default/wifi.h | 8 +-- wifi/{1.2 => 1.3}/default/wifi_ap_iface.cpp | 4 +- wifi/{1.2 => 1.3}/default/wifi_ap_iface.h | 4 +- wifi/{1.2 => 1.3}/default/wifi_chip.cpp | 47 ++++++++------- wifi/{1.2 => 1.3}/default/wifi_chip.h | 18 +++--- .../default/wifi_feature_flags.cpp | 8 +-- .../{1.2 => 1.3}/default/wifi_feature_flags.h | 4 +- wifi/{1.2 => 1.3}/default/wifi_legacy_hal.cpp | 4 +- wifi/{1.2 => 1.3}/default/wifi_legacy_hal.h | 12 ++-- .../default/wifi_legacy_hal_stubs.cpp | 4 +- .../default/wifi_legacy_hal_stubs.h | 4 +- .../default/wifi_mode_controller.cpp | 4 +- .../default/wifi_mode_controller.h | 4 +- wifi/{1.2 => 1.3}/default/wifi_nan_iface.cpp | 18 +++--- wifi/{1.2 => 1.3}/default/wifi_nan_iface.h | 14 ++--- wifi/{1.2 => 1.3}/default/wifi_p2p_iface.cpp | 4 +- wifi/{1.2 => 1.3}/default/wifi_p2p_iface.h | 4 +- .../default/wifi_rtt_controller.cpp | 4 +- .../default/wifi_rtt_controller.h | 4 +- wifi/{1.2 => 1.3}/default/wifi_sta_iface.cpp | 4 +- wifi/{1.2 => 1.3}/default/wifi_sta_iface.h | 4 +- .../{1.2 => 1.3}/default/wifi_status_util.cpp | 4 +- wifi/{1.2 => 1.3}/default/wifi_status_util.h | 4 +- 51 files changed, 261 insertions(+), 197 deletions(-) create mode 100644 wifi/1.3/Android.bp create mode 100644 wifi/1.3/IWifi.hal rename wifi/{1.2 => 1.3}/default/Android.mk (94%) rename wifi/{1.2 => 1.3}/default/OWNERS (100%) rename wifi/{1.2 => 1.3}/default/THREADING.README (100%) rename wifi/{1.2 => 1.3}/default/android.hardware.wifi@1.0-service.rc (100%) rename wifi/{1.2 => 1.3}/default/hidl_callback_util.h (99%) rename wifi/{1.2 => 1.3}/default/hidl_return_util.h (99%) rename wifi/{1.2 => 1.3}/default/hidl_struct_util.cpp (98%) rename wifi/{1.2 => 1.3}/default/hidl_struct_util.h (95%) rename wifi/{1.2 => 1.3}/default/hidl_sync_util.cpp (96%) rename wifi/{1.2 => 1.3}/default/hidl_sync_util.h (96%) rename wifi/{1.2 => 1.3}/default/ringbuffer.cpp (97%) rename wifi/{1.2 => 1.3}/default/ringbuffer.h (97%) rename wifi/{1.2 => 1.3}/default/service.cpp (83%) rename wifi/{1.2 => 1.3}/default/tests/hidl_struct_util_unit_tests.cpp (84%) rename wifi/{1.2 => 1.3}/default/tests/main.cpp (100%) rename wifi/{1.2 => 1.3}/default/tests/mock_wifi_feature_flags.cpp (96%) rename wifi/{1.2 => 1.3}/default/tests/mock_wifi_feature_flags.h (97%) rename wifi/{1.2 => 1.3}/default/tests/mock_wifi_legacy_hal.cpp (96%) rename wifi/{1.2 => 1.3}/default/tests/mock_wifi_legacy_hal.h (98%) rename wifi/{1.2 => 1.3}/default/tests/mock_wifi_mode_controller.cpp (96%) rename wifi/{1.2 => 1.3}/default/tests/mock_wifi_mode_controller.h (97%) rename wifi/{1.2 => 1.3}/default/tests/ringbuffer_unit_tests.cpp (98%) rename wifi/{1.2 => 1.3}/default/tests/runtests.sh (100%) rename wifi/{1.2 => 1.3}/default/tests/wifi_chip_unit_tests.cpp (96%) rename wifi/{1.2 => 1.3}/default/wifi.cpp (99%) rename wifi/{1.2 => 1.3}/default/wifi.h (96%) rename wifi/{1.2 => 1.3}/default/wifi_ap_iface.cpp (98%) rename wifi/{1.2 => 1.3}/default/wifi_ap_iface.h (98%) rename wifi/{1.2 => 1.3}/default/wifi_chip.cpp (97%) rename wifi/{1.2 => 1.3}/default/wifi_chip.h (95%) rename wifi/{1.2 => 1.3}/default/wifi_feature_flags.cpp (93%) rename wifi/{1.2 => 1.3}/default/wifi_feature_flags.h (96%) rename wifi/{1.2 => 1.3}/default/wifi_legacy_hal.cpp (99%) rename wifi/{1.2 => 1.3}/default/wifi_legacy_hal.h (98%) rename wifi/{1.2 => 1.3}/default/wifi_legacy_hal_stubs.cpp (99%) rename wifi/{1.2 => 1.3}/default/wifi_legacy_hal_stubs.h (96%) rename wifi/{1.2 => 1.3}/default/wifi_mode_controller.cpp (98%) rename wifi/{1.2 => 1.3}/default/wifi_mode_controller.h (98%) rename wifi/{1.2 => 1.3}/default/wifi_nan_iface.cpp (98%) rename wifi/{1.2 => 1.3}/default/wifi_nan_iface.h (95%) rename wifi/{1.2 => 1.3}/default/wifi_p2p_iface.cpp (98%) rename wifi/{1.2 => 1.3}/default/wifi_p2p_iface.h (98%) rename wifi/{1.2 => 1.3}/default/wifi_rtt_controller.cpp (99%) rename wifi/{1.2 => 1.3}/default/wifi_rtt_controller.h (99%) rename wifi/{1.2 => 1.3}/default/wifi_sta_iface.cpp (99%) rename wifi/{1.2 => 1.3}/default/wifi_sta_iface.h (99%) rename wifi/{1.2 => 1.3}/default/wifi_status_util.cpp (99%) rename wifi/{1.2 => 1.3}/default/wifi_status_util.h (97%) diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml index 3d65cc301b..42372feb36 100644 --- a/compatibility_matrices/compatibility_matrix.current.xml +++ b/compatibility_matrices/compatibility_matrix.current.xml @@ -429,7 +429,7 @@ android.hardware.wifi - 1.0-2 + 1.0-3 IWifi default diff --git a/wifi/1.3/Android.bp b/wifi/1.3/Android.bp new file mode 100644 index 0000000000..95fbf8346d --- /dev/null +++ b/wifi/1.3/Android.bp @@ -0,0 +1,20 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +hidl_interface { + name: "android.hardware.wifi@1.3", + root: "android.hardware", + vndk: { + enabled: true, + }, + srcs: [ + "IWifi.hal", + ], + interfaces: [ + "android.hardware.wifi@1.0", + "android.hardware.wifi@1.1", + "android.hardware.wifi@1.2", + "android.hidl.base@1.0", + ], + gen_java: true, +} + diff --git a/wifi/1.3/IWifi.hal b/wifi/1.3/IWifi.hal new file mode 100644 index 0000000000..298e722a7c --- /dev/null +++ b/wifi/1.3/IWifi.hal @@ -0,0 +1,28 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.wifi@1.3; + +import @1.2::IWifi; + +/** + * This is the root of the HAL module and is the interface returned when + * loading an implementation of the Wi-Fi HAL. There must be at most one + * module loaded in the system. + * IWifi.getChip() must return @1.2::IWifiChip + */ +interface IWifi extends @1.2::IWifi { +}; diff --git a/wifi/1.2/default/Android.mk b/wifi/1.3/default/Android.mk similarity index 94% rename from wifi/1.2/default/Android.mk rename to wifi/1.3/default/Android.mk index 8c5371b883..541e5f09f4 100644 --- a/wifi/1.2/default/Android.mk +++ b/wifi/1.3/default/Android.mk @@ -58,7 +58,8 @@ LOCAL_SHARED_LIBRARIES := \ libwifi-system-iface \ android.hardware.wifi@1.0 \ android.hardware.wifi@1.1 \ - android.hardware.wifi@1.2 + android.hardware.wifi@1.2 \ + android.hardware.wifi@1.3 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH) include $(BUILD_STATIC_LIBRARY) @@ -84,7 +85,8 @@ LOCAL_SHARED_LIBRARIES := \ libwifi-system-iface \ android.hardware.wifi@1.0 \ android.hardware.wifi@1.1 \ - android.hardware.wifi@1.2 + android.hardware.wifi@1.2 \ + android.hardware.wifi@1.3 LOCAL_STATIC_LIBRARIES := \ android.hardware.wifi@1.0-service-lib LOCAL_INIT_RC := android.hardware.wifi@1.0-service.rc @@ -120,5 +122,6 @@ LOCAL_SHARED_LIBRARIES := \ libwifi-system-iface \ android.hardware.wifi@1.0 \ android.hardware.wifi@1.1 \ - android.hardware.wifi@1.2 + android.hardware.wifi@1.2 \ + android.hardware.wifi@1.3 include $(BUILD_NATIVE_TEST) diff --git a/wifi/1.2/default/OWNERS b/wifi/1.3/default/OWNERS similarity index 100% rename from wifi/1.2/default/OWNERS rename to wifi/1.3/default/OWNERS diff --git a/wifi/1.2/default/THREADING.README b/wifi/1.3/default/THREADING.README similarity index 100% rename from wifi/1.2/default/THREADING.README rename to wifi/1.3/default/THREADING.README diff --git a/wifi/1.2/default/android.hardware.wifi@1.0-service.rc b/wifi/1.3/default/android.hardware.wifi@1.0-service.rc similarity index 100% rename from wifi/1.2/default/android.hardware.wifi@1.0-service.rc rename to wifi/1.3/default/android.hardware.wifi@1.0-service.rc diff --git a/wifi/1.2/default/hidl_callback_util.h b/wifi/1.3/default/hidl_callback_util.h similarity index 99% rename from wifi/1.2/default/hidl_callback_util.h rename to wifi/1.3/default/hidl_callback_util.h index 97f312a605..a44af79fe3 100644 --- a/wifi/1.2/default/hidl_callback_util.h +++ b/wifi/1.3/default/hidl_callback_util.h @@ -52,7 +52,7 @@ class HidlDeathHandler : public android::hardware::hidl_death_recipient { namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { namespace hidl_callback_util { template @@ -117,7 +117,7 @@ class HidlCallbackHandler { } // namespace hidl_callback_util } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/hidl_return_util.h b/wifi/1.3/default/hidl_return_util.h similarity index 99% rename from wifi/1.2/default/hidl_return_util.h rename to wifi/1.3/default/hidl_return_util.h index 914c1b4ed8..9707444fe6 100644 --- a/wifi/1.2/default/hidl_return_util.h +++ b/wifi/1.3/default/hidl_return_util.h @@ -23,7 +23,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { namespace hidl_return_util { using namespace android::hardware::wifi::V1_0; @@ -113,7 +113,7 @@ Return validateAndCall( } // namespace hidl_return_util } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/hidl_struct_util.cpp b/wifi/1.3/default/hidl_struct_util.cpp similarity index 98% rename from wifi/1.2/default/hidl_struct_util.cpp rename to wifi/1.3/default/hidl_struct_util.cpp index 39ac544e6b..e793236f5e 100644 --- a/wifi/1.2/default/hidl_struct_util.cpp +++ b/wifi/1.3/default/hidl_struct_util.cpp @@ -22,7 +22,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { namespace hidl_struct_util { @@ -69,9 +69,9 @@ convertLegacyLoggerFeatureToHidlStaIfaceCapability(uint32_t feature) { return {}; } -IWifiChip::ChipCapabilityMask convertLegacyFeatureToHidlChipCapability( +V1_2::IWifiChip::ChipCapabilityMask convertLegacyFeatureToHidlChipCapability( uint32_t feature) { - using HidlChipCaps = IWifiChip::ChipCapabilityMask; + using HidlChipCaps = V1_2::IWifiChip::ChipCapabilityMask; switch (feature) { case WIFI_FEATURE_SET_TX_POWER_LIMIT: return HidlChipCaps::SET_TX_POWER_LIMIT; @@ -139,9 +139,9 @@ bool convertLegacyFeaturesToHidlChipCapabilities( convertLegacyLoggerFeatureToHidlChipCapability(feature); } } - for (const auto feature : {WIFI_FEATURE_SET_TX_POWER_LIMIT, - WIFI_FEATURE_USE_BODY_HEAD_SAR, - WIFI_FEATURE_D2D_RTT, WIFI_FEATURE_D2AP_RTT}) { + for (const auto feature : + {WIFI_FEATURE_SET_TX_POWER_LIMIT, WIFI_FEATURE_USE_BODY_HEAD_SAR, + WIFI_FEATURE_D2D_RTT, WIFI_FEATURE_D2AP_RTT}) { if (feature & legacy_feature_set) { *hidl_caps |= convertLegacyFeatureToHidlChipCapability(feature); } @@ -267,26 +267,26 @@ legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy( V1_1::IWifiChip::TxPowerScenario hidl_scenario) { switch (hidl_scenario) { // This is the only supported scenario for V1_1 - case V1_1::IWifiChip::TxPowerScenario::VOICE_CALL: + case V1_1::IWifiChip::TxPowerScenario::VOICE_CALL: return legacy_hal::WIFI_POWER_SCENARIO_VOICE_CALL; }; CHECK(false); } legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy_1_2( - IWifiChip::TxPowerScenario hidl_scenario) { + V1_2::IWifiChip::TxPowerScenario hidl_scenario) { switch (hidl_scenario) { // This is the only supported scenario for V1_1 - case IWifiChip::TxPowerScenario::VOICE_CALL: + case V1_2::IWifiChip::TxPowerScenario::VOICE_CALL: return legacy_hal::WIFI_POWER_SCENARIO_VOICE_CALL; // Those are the supported scenarios for V1_2 - case IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF: + case V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF: return legacy_hal::WIFI_POWER_SCENARIO_ON_HEAD_CELL_OFF; - case IWifiChip::TxPowerScenario::ON_HEAD_CELL_ON: + case V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_ON: return legacy_hal::WIFI_POWER_SCENARIO_ON_HEAD_CELL_ON; - case IWifiChip::TxPowerScenario::ON_BODY_CELL_OFF: + case V1_2::IWifiChip::TxPowerScenario::ON_BODY_CELL_OFF: return legacy_hal::WIFI_POWER_SCENARIO_ON_BODY_CELL_OFF; - case IWifiChip::TxPowerScenario::ON_BODY_CELL_ON: + case V1_2::IWifiChip::TxPowerScenario::ON_BODY_CELL_ON: return legacy_hal::WIFI_POWER_SCENARIO_ON_BODY_CELL_ON; }; CHECK(false); @@ -294,7 +294,7 @@ legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy_1_2( bool convertLegacyWifiMacInfoToHidl( const legacy_hal::WifiMacInfo& legacy_mac_info, - IWifiChipEventCallback::RadioModeInfo* hidl_radio_mode_info) { + V1_2::IWifiChipEventCallback::RadioModeInfo* hidl_radio_mode_info) { if (!hidl_radio_mode_info) { return false; } @@ -313,9 +313,9 @@ bool convertLegacyWifiMacInfoToHidl( } else { hidl_radio_mode_info->bandInfo = WifiBand::BAND_UNSPECIFIED; } - std::vector iface_info_vec; + std::vector iface_info_vec; for (const auto& legacy_iface_info : legacy_mac_info.iface_infos) { - IWifiChipEventCallback::IfaceInfo iface_info; + V1_2::IWifiChipEventCallback::IfaceInfo iface_info; iface_info.name = legacy_iface_info.name; iface_info.channel = legacy_iface_info.channel; iface_info_vec.push_back(iface_info); @@ -326,14 +326,15 @@ bool convertLegacyWifiMacInfoToHidl( bool convertLegacyWifiMacInfosToHidl( const std::vector& legacy_mac_infos, - std::vector* hidl_radio_mode_infos) { + std::vector* + hidl_radio_mode_infos) { if (!hidl_radio_mode_infos) { return false; } *hidl_radio_mode_infos = {}; for (const auto& legacy_mac_info : legacy_mac_infos) { - IWifiChipEventCallback::RadioModeInfo hidl_radio_mode_info; + V1_2::IWifiChipEventCallback::RadioModeInfo hidl_radio_mode_info; if (!convertLegacyWifiMacInfoToHidl(legacy_mac_info, &hidl_radio_mode_info)) { return false; @@ -1197,7 +1198,7 @@ bool convertHidlNanEnableRequestToLegacy( bool convertHidlNanEnableRequest_1_2ToLegacy( const NanEnableRequest& hidl_request1, - const NanConfigRequestSupplemental& hidl_request2, + const V1_2::NanConfigRequestSupplemental& hidl_request2, legacy_hal::NanEnableRequest* legacy_request) { if (!legacy_request) { LOG(ERROR) @@ -1708,7 +1709,7 @@ bool convertHidlNanConfigRequestToLegacy( bool convertHidlNanConfigRequest_1_2ToLegacy( const NanConfigRequest& hidl_request1, - const NanConfigRequestSupplemental& hidl_request2, + const V1_2::NanConfigRequestSupplemental& hidl_request2, legacy_hal::NanConfigRequest* legacy_request) { if (!legacy_request) { LOG(ERROR) << "convertHidlNanConfigRequest_1_2ToLegacy: legacy_request " @@ -2039,7 +2040,7 @@ bool convertLegacyNanDataPathRequestIndToHidl( bool convertLegacyNdpChannelInfoToHidl( const legacy_hal::NanChannelInfo& legacy_struct, - NanDataPathChannelInfo* hidl_struct) { + V1_2::NanDataPathChannelInfo* hidl_struct) { if (!hidl_struct) { LOG(ERROR) << "convertLegacyNdpChannelInfoToHidl: hidl_struct is null"; return false; @@ -2056,7 +2057,7 @@ bool convertLegacyNdpChannelInfoToHidl( bool convertLegacyNanDataPathConfirmIndToHidl( const legacy_hal::NanDataPathConfirmInd& legacy_ind, - NanDataPathConfirmInd* hidl_ind) { + V1_2::NanDataPathConfirmInd* hidl_ind) { if (!hidl_ind) { LOG(ERROR) << "convertLegacyNanDataPathConfirmIndToHidl: hidl_ind is null"; @@ -2077,9 +2078,9 @@ bool convertLegacyNanDataPathConfirmIndToHidl( convertLegacyNanStatusTypeToHidl(legacy_ind.reason_code); hidl_ind->V1_0.status.description = ""; // TODO: b/34059183 - std::vector channelInfo; + std::vector channelInfo; for (unsigned int i = 0; i < legacy_ind.num_channels; ++i) { - NanDataPathChannelInfo hidl_struct; + V1_2::NanDataPathChannelInfo hidl_struct; if (!convertLegacyNdpChannelInfoToHidl(legacy_ind.channel_info[i], &hidl_struct)) { return false; @@ -2093,7 +2094,7 @@ bool convertLegacyNanDataPathConfirmIndToHidl( bool convertLegacyNanDataPathScheduleUpdateIndToHidl( const legacy_hal::NanDataPathScheduleUpdateInd& legacy_ind, - NanDataPathScheduleUpdateInd* hidl_ind) { + V1_2::NanDataPathScheduleUpdateInd* hidl_ind) { if (!hidl_ind) { LOG(ERROR) << "convertLegacyNanDataPathScheduleUpdateIndToHidl: " "hidl_ind is null"; @@ -2103,9 +2104,9 @@ bool convertLegacyNanDataPathScheduleUpdateIndToHidl( hidl_ind->peerDiscoveryAddress = hidl_array(legacy_ind.peer_mac_addr); - std::vector channelInfo; + std::vector channelInfo; for (unsigned int i = 0; i < legacy_ind.num_channels; ++i) { - NanDataPathChannelInfo hidl_struct; + V1_2::NanDataPathChannelInfo hidl_struct; if (!convertLegacyNdpChannelInfoToHidl(legacy_ind.channel_info[i], &hidl_struct)) { return false; @@ -2616,7 +2617,7 @@ bool convertLegacyVectorOfRttResultToHidl( } } // namespace hidl_struct_util } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/hidl_struct_util.h b/wifi/1.3/default/hidl_struct_util.h similarity index 95% rename from wifi/1.2/default/hidl_struct_util.h rename to wifi/1.3/default/hidl_struct_util.h index 3c789c046f..e2ba00c1e8 100644 --- a/wifi/1.2/default/hidl_struct_util.h +++ b/wifi/1.3/default/hidl_struct_util.h @@ -36,7 +36,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { namespace hidl_struct_util { using namespace android::hardware::wifi::V1_0; @@ -57,10 +57,11 @@ bool convertLegacyWakeReasonStatsToHidl( legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy( V1_1::IWifiChip::TxPowerScenario hidl_scenario); legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy_1_2( - IWifiChip::TxPowerScenario hidl_scenario); + V1_2::IWifiChip::TxPowerScenario hidl_scenario); bool convertLegacyWifiMacInfosToHidl( const std::vector& legacy_mac_infos, - std::vector* hidl_radio_mode_infos); + std::vector* + hidl_radio_mode_infos); // STA iface conversion methods. bool convertLegacyFeaturesToHidlStaCapabilities( @@ -115,11 +116,11 @@ bool convertHidlNanConfigRequestToLegacy( legacy_hal::NanConfigRequest* legacy_request); bool convertHidlNanEnableRequest_1_2ToLegacy( const NanEnableRequest& hidl_request1, - const NanConfigRequestSupplemental& hidl_request2, + const V1_2::NanConfigRequestSupplemental& hidl_request2, legacy_hal::NanEnableRequest* legacy_request); bool convertHidlNanConfigRequest_1_2ToLegacy( const NanConfigRequest& hidl_request1, - const NanConfigRequestSupplemental& hidl_request2, + const V1_2::NanConfigRequestSupplemental& hidl_request2, legacy_hal::NanConfigRequest* legacy_request); bool convertHidlNanPublishRequestToLegacy( const NanPublishRequest& hidl_request, @@ -152,10 +153,10 @@ bool convertLegacyNanDataPathRequestIndToHidl( NanDataPathRequestInd* hidl_ind); bool convertLegacyNanDataPathConfirmIndToHidl( const legacy_hal::NanDataPathConfirmInd& legacy_ind, - NanDataPathConfirmInd* hidl_ind); + V1_2::NanDataPathConfirmInd* hidl_ind); bool convertLegacyNanDataPathScheduleUpdateIndToHidl( const legacy_hal::NanDataPathScheduleUpdateInd& legacy_ind, - NanDataPathScheduleUpdateInd* hidl_ind); + V1_2::NanDataPathScheduleUpdateInd* hidl_ind); // RTT controller conversion methods. bool convertHidlVectorOfRttConfigToLegacy( @@ -184,7 +185,7 @@ bool convertLegacyVectorOfRttResultToHidl( std::vector* hidl_results); } // namespace hidl_struct_util } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/hidl_sync_util.cpp b/wifi/1.3/default/hidl_sync_util.cpp similarity index 96% rename from wifi/1.2/default/hidl_sync_util.cpp rename to wifi/1.3/default/hidl_sync_util.cpp index ad8448a17a..160727f609 100644 --- a/wifi/1.2/default/hidl_sync_util.cpp +++ b/wifi/1.3/default/hidl_sync_util.cpp @@ -23,7 +23,7 @@ std::recursive_mutex g_mutex; namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { namespace hidl_sync_util { @@ -33,7 +33,7 @@ std::unique_lock acquireGlobalLock() { } // namespace hidl_sync_util } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/hidl_sync_util.h b/wifi/1.3/default/hidl_sync_util.h similarity index 96% rename from wifi/1.2/default/hidl_sync_util.h rename to wifi/1.3/default/hidl_sync_util.h index 8381862785..ebfb05144b 100644 --- a/wifi/1.2/default/hidl_sync_util.h +++ b/wifi/1.3/default/hidl_sync_util.h @@ -24,13 +24,13 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { namespace hidl_sync_util { std::unique_lock acquireGlobalLock(); } // namespace hidl_sync_util } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/ringbuffer.cpp b/wifi/1.3/default/ringbuffer.cpp similarity index 97% rename from wifi/1.2/default/ringbuffer.cpp rename to wifi/1.3/default/ringbuffer.cpp index c126b36912..1294c52982 100644 --- a/wifi/1.2/default/ringbuffer.cpp +++ b/wifi/1.3/default/ringbuffer.cpp @@ -21,7 +21,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { Ringbuffer::Ringbuffer(size_t maxSize) : size_(0), maxSize_(maxSize) {} @@ -48,7 +48,7 @@ const std::list>& Ringbuffer::getData() const { } } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/ringbuffer.h b/wifi/1.3/default/ringbuffer.h similarity index 97% rename from wifi/1.2/default/ringbuffer.h rename to wifi/1.3/default/ringbuffer.h index 4808e40b78..d9f8df685d 100644 --- a/wifi/1.2/default/ringbuffer.h +++ b/wifi/1.3/default/ringbuffer.h @@ -23,7 +23,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { /** @@ -45,7 +45,7 @@ class Ringbuffer { }; } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/service.cpp b/wifi/1.3/default/service.cpp similarity index 83% rename from wifi/1.2/default/service.cpp rename to wifi/1.3/default/service.cpp index 01d22bd881..5fd83c1aa8 100644 --- a/wifi/1.2/default/service.cpp +++ b/wifi/1.3/default/service.cpp @@ -26,10 +26,10 @@ using android::hardware::configureRpcThreadpool; using android::hardware::joinRpcThreadpool; -using android::hardware::wifi::V1_2::implementation::feature_flags:: +using android::hardware::wifi::V1_3::implementation::feature_flags:: WifiFeatureFlags; -using android::hardware::wifi::V1_2::implementation::legacy_hal::WifiLegacyHal; -using android::hardware::wifi::V1_2::implementation::mode_controller:: +using android::hardware::wifi::V1_3::implementation::legacy_hal::WifiLegacyHal; +using android::hardware::wifi::V1_3::implementation::mode_controller:: WifiModeController; int main(int /*argc*/, char** argv) { @@ -40,8 +40,8 @@ int main(int /*argc*/, char** argv) { configureRpcThreadpool(1, true /* callerWillJoin */); // Setup hwbinder service - android::sp service = - new android::hardware::wifi::V1_2::implementation::Wifi( + android::sp service = + new android::hardware::wifi::V1_3::implementation::Wifi( std::make_shared(), std::make_shared(), std::make_shared()); diff --git a/wifi/1.2/default/tests/hidl_struct_util_unit_tests.cpp b/wifi/1.3/default/tests/hidl_struct_util_unit_tests.cpp similarity index 84% rename from wifi/1.2/default/tests/hidl_struct_util_unit_tests.cpp rename to wifi/1.3/default/tests/hidl_struct_util_unit_tests.cpp index 1d6e9e4a14..4cd3719293 100644 --- a/wifi/1.2/default/tests/hidl_struct_util_unit_tests.cpp +++ b/wifi/1.3/default/tests/hidl_struct_util_unit_tests.cpp @@ -34,7 +34,7 @@ constexpr char kIfaceName2[] = "wlan1"; namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { using namespace android::hardware::wifi::V1_0; @@ -54,7 +54,8 @@ TEST_F(HidlStructUtilTest, CanConvertLegacyWifiMacInfosToHidlWithOneMac) { legacy_mac_info1.iface_infos.push_back(legacy_iface_info2); legacy_mac_infos.push_back(legacy_mac_info1); - std::vector hidl_radio_mode_infos; + std::vector + hidl_radio_mode_infos; ASSERT_TRUE(hidl_struct_util::convertLegacyWifiMacInfosToHidl( legacy_mac_infos, &hidl_radio_mode_infos)); @@ -88,18 +89,20 @@ TEST_F(HidlStructUtilTest, CanConvertLegacyWifiMacInfosToHidlWithTwoMac) { legacy_mac_info2.iface_infos.push_back(legacy_iface_info2); legacy_mac_infos.push_back(legacy_mac_info2); - std::vector hidl_radio_mode_infos; + std::vector + hidl_radio_mode_infos; ASSERT_TRUE(hidl_struct_util::convertLegacyWifiMacInfosToHidl( legacy_mac_infos, &hidl_radio_mode_infos)); ASSERT_EQ(2u, hidl_radio_mode_infos.size()); // Find mac info 1. - const auto hidl_radio_mode_info1 = std::find_if( - hidl_radio_mode_infos.begin(), hidl_radio_mode_infos.end(), - [&legacy_mac_info1](const IWifiChipEventCallback::RadioModeInfo& x) { - return x.radioId == legacy_mac_info1.wlan_mac_id; - }); + const auto hidl_radio_mode_info1 = + std::find_if(hidl_radio_mode_infos.begin(), hidl_radio_mode_infos.end(), + [&legacy_mac_info1]( + const V1_2::IWifiChipEventCallback::RadioModeInfo& x) { + return x.radioId == legacy_mac_info1.wlan_mac_id; + }); ASSERT_NE(hidl_radio_mode_infos.end(), hidl_radio_mode_info1); EXPECT_EQ(WifiBand::BAND_5GHZ, hidl_radio_mode_info1->bandInfo); ASSERT_EQ(1u, hidl_radio_mode_info1->ifaceInfos.size()); @@ -109,11 +112,12 @@ TEST_F(HidlStructUtilTest, CanConvertLegacyWifiMacInfosToHidlWithTwoMac) { hidl_iface_info1.channel); // Find mac info 2. - const auto hidl_radio_mode_info2 = std::find_if( - hidl_radio_mode_infos.begin(), hidl_radio_mode_infos.end(), - [&legacy_mac_info2](const IWifiChipEventCallback::RadioModeInfo& x) { - return x.radioId == legacy_mac_info2.wlan_mac_id; - }); + const auto hidl_radio_mode_info2 = + std::find_if(hidl_radio_mode_infos.begin(), hidl_radio_mode_infos.end(), + [&legacy_mac_info2]( + const V1_2::IWifiChipEventCallback::RadioModeInfo& x) { + return x.radioId == legacy_mac_info2.wlan_mac_id; + }); ASSERT_NE(hidl_radio_mode_infos.end(), hidl_radio_mode_info2); EXPECT_EQ(WifiBand::BAND_24GHZ, hidl_radio_mode_info2->bandInfo); ASSERT_EQ(1u, hidl_radio_mode_info2->ifaceInfos.size()); @@ -123,7 +127,7 @@ TEST_F(HidlStructUtilTest, CanConvertLegacyWifiMacInfosToHidlWithTwoMac) { hidl_iface_info2.channel); } } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/tests/main.cpp b/wifi/1.3/default/tests/main.cpp similarity index 100% rename from wifi/1.2/default/tests/main.cpp rename to wifi/1.3/default/tests/main.cpp diff --git a/wifi/1.2/default/tests/mock_wifi_feature_flags.cpp b/wifi/1.3/default/tests/mock_wifi_feature_flags.cpp similarity index 96% rename from wifi/1.2/default/tests/mock_wifi_feature_flags.cpp rename to wifi/1.3/default/tests/mock_wifi_feature_flags.cpp index 8d0b1921c2..a393fdc539 100644 --- a/wifi/1.2/default/tests/mock_wifi_feature_flags.cpp +++ b/wifi/1.3/default/tests/mock_wifi_feature_flags.cpp @@ -21,7 +21,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { namespace feature_flags { @@ -29,7 +29,7 @@ MockWifiFeatureFlags::MockWifiFeatureFlags() {} } // namespace feature_flags } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/tests/mock_wifi_feature_flags.h b/wifi/1.3/default/tests/mock_wifi_feature_flags.h similarity index 97% rename from wifi/1.2/default/tests/mock_wifi_feature_flags.h rename to wifi/1.3/default/tests/mock_wifi_feature_flags.h index 2a36dd50f4..86c50a72c4 100644 --- a/wifi/1.2/default/tests/mock_wifi_feature_flags.h +++ b/wifi/1.3/default/tests/mock_wifi_feature_flags.h @@ -24,7 +24,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { namespace feature_flags { @@ -39,7 +39,7 @@ class MockWifiFeatureFlags : public WifiFeatureFlags { } // namespace feature_flags } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/tests/mock_wifi_legacy_hal.cpp b/wifi/1.3/default/tests/mock_wifi_legacy_hal.cpp similarity index 96% rename from wifi/1.2/default/tests/mock_wifi_legacy_hal.cpp rename to wifi/1.3/default/tests/mock_wifi_legacy_hal.cpp index 8381ddef4e..4cd279d543 100644 --- a/wifi/1.2/default/tests/mock_wifi_legacy_hal.cpp +++ b/wifi/1.3/default/tests/mock_wifi_legacy_hal.cpp @@ -24,14 +24,14 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { namespace legacy_hal { MockWifiLegacyHal::MockWifiLegacyHal() : WifiLegacyHal() {} } // namespace legacy_hal } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/tests/mock_wifi_legacy_hal.h b/wifi/1.3/default/tests/mock_wifi_legacy_hal.h similarity index 98% rename from wifi/1.2/default/tests/mock_wifi_legacy_hal.h rename to wifi/1.3/default/tests/mock_wifi_legacy_hal.h index 43370b4f5c..deb3a5ae4b 100644 --- a/wifi/1.2/default/tests/mock_wifi_legacy_hal.h +++ b/wifi/1.3/default/tests/mock_wifi_legacy_hal.h @@ -24,7 +24,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { namespace legacy_hal { @@ -49,7 +49,7 @@ class MockWifiLegacyHal : public WifiLegacyHal { }; } // namespace legacy_hal } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/tests/mock_wifi_mode_controller.cpp b/wifi/1.3/default/tests/mock_wifi_mode_controller.cpp similarity index 96% rename from wifi/1.2/default/tests/mock_wifi_mode_controller.cpp rename to wifi/1.3/default/tests/mock_wifi_mode_controller.cpp index 461a581a22..2b0ea366f3 100644 --- a/wifi/1.2/default/tests/mock_wifi_mode_controller.cpp +++ b/wifi/1.3/default/tests/mock_wifi_mode_controller.cpp @@ -24,14 +24,14 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { namespace mode_controller { MockWifiModeController::MockWifiModeController() : WifiModeController() {} } // namespace mode_controller } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/tests/mock_wifi_mode_controller.h b/wifi/1.3/default/tests/mock_wifi_mode_controller.h similarity index 97% rename from wifi/1.2/default/tests/mock_wifi_mode_controller.h rename to wifi/1.3/default/tests/mock_wifi_mode_controller.h index 50c3e35bbc..c204059e67 100644 --- a/wifi/1.2/default/tests/mock_wifi_mode_controller.h +++ b/wifi/1.3/default/tests/mock_wifi_mode_controller.h @@ -24,7 +24,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { namespace mode_controller { @@ -38,7 +38,7 @@ class MockWifiModeController : public WifiModeController { }; } // namespace mode_controller } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/tests/ringbuffer_unit_tests.cpp b/wifi/1.3/default/tests/ringbuffer_unit_tests.cpp similarity index 98% rename from wifi/1.2/default/tests/ringbuffer_unit_tests.cpp rename to wifi/1.3/default/tests/ringbuffer_unit_tests.cpp index ad5289b919..0cf1e4f256 100644 --- a/wifi/1.2/default/tests/ringbuffer_unit_tests.cpp +++ b/wifi/1.3/default/tests/ringbuffer_unit_tests.cpp @@ -24,7 +24,7 @@ using testing::Test; namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { class RingbufferTest : public Test { @@ -91,7 +91,7 @@ TEST_F(RingbufferTest, OversizedAppendDoesNotDropExistingData) { EXPECT_EQ(input, buffer_.getData().front()); } } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/tests/runtests.sh b/wifi/1.3/default/tests/runtests.sh similarity index 100% rename from wifi/1.2/default/tests/runtests.sh rename to wifi/1.3/default/tests/runtests.sh diff --git a/wifi/1.2/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp similarity index 96% rename from wifi/1.2/default/tests/wifi_chip_unit_tests.cpp rename to wifi/1.3/default/tests/wifi_chip_unit_tests.cpp index 8722d0ac4c..2d9050d80e 100644 --- a/wifi/1.2/default/tests/wifi_chip_unit_tests.cpp +++ b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp @@ -38,7 +38,7 @@ constexpr ChipId kFakeChipId = 5; namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { class WifiChipTest : public Test { @@ -542,38 +542,38 @@ TEST_F(WifiChipV2_AwareIfaceCombinationTest, ////////// V1 Iface Combinations when AP creation is disabled ////////// class WifiChipV1_AwareDisabledApIfaceCombinationTest : public WifiChipTest { - public: - void SetUp() override { - setupV1_AwareDisabledApIfaceCombination(); - WifiChipTest::SetUp(); - } + public: + void SetUp() override { + setupV1_AwareDisabledApIfaceCombination(); + WifiChipTest::SetUp(); + } }; TEST_F(WifiChipV1_AwareDisabledApIfaceCombinationTest, StaMode_CreateSta_ShouldSucceed) { - findModeAndConfigureForIfaceType(IfaceType::STA); - ASSERT_FALSE(createIface(IfaceType::STA).empty()); - ASSERT_TRUE(createIface(IfaceType::AP).empty()); + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_FALSE(createIface(IfaceType::STA).empty()); + ASSERT_TRUE(createIface(IfaceType::AP).empty()); } ////////// V2 Iface Combinations when AP creation is disabled ////////// -class WifiChipV2_AwareDisabledApIfaceCombinationTest: public WifiChipTest { - public: - void SetUp() override { - setupV2_AwareDisabledApIfaceCombination(); - WifiChipTest::SetUp(); - } +class WifiChipV2_AwareDisabledApIfaceCombinationTest : public WifiChipTest { + public: + void SetUp() override { + setupV2_AwareDisabledApIfaceCombination(); + WifiChipTest::SetUp(); + } }; TEST_F(WifiChipV2_AwareDisabledApIfaceCombinationTest, CreateSta_ShouldSucceed) { - findModeAndConfigureForIfaceType(IfaceType::STA); - ASSERT_FALSE(createIface(IfaceType::STA).empty()); - ASSERT_TRUE(createIface(IfaceType::AP).empty()); + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_FALSE(createIface(IfaceType::STA).empty()); + ASSERT_TRUE(createIface(IfaceType::AP).empty()); } } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/wifi.cpp b/wifi/1.3/default/wifi.cpp similarity index 99% rename from wifi/1.2/default/wifi.cpp rename to wifi/1.3/default/wifi.cpp index 79f921fa6e..e3af1eab17 100644 --- a/wifi/1.2/default/wifi.cpp +++ b/wifi/1.3/default/wifi.cpp @@ -28,7 +28,7 @@ static constexpr android::hardware::wifi::V1_0::ChipId kChipId = 0; namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { using hidl_return_util::validateAndCall; using hidl_return_util::validateAndCallWithLock; @@ -206,7 +206,7 @@ WifiStatus Wifi::stopLegacyHalAndDeinitializeModeController( return createWifiStatus(WifiStatusCode::SUCCESS); } } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/wifi.h b/wifi/1.3/default/wifi.h similarity index 96% rename from wifi/1.2/default/wifi.h rename to wifi/1.3/default/wifi.h index 86919b194e..e92142492a 100644 --- a/wifi/1.2/default/wifi.h +++ b/wifi/1.3/default/wifi.h @@ -20,7 +20,7 @@ #include #include -#include +#include #include #include "hidl_callback_util.h" @@ -32,13 +32,13 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { /** * Root HIDL interface object used to control the Wifi HAL. */ -class Wifi : public V1_2::IWifi { +class Wifi : public V1_3::IWifi { public: Wifi(const std::shared_ptr legacy_hal, const std::shared_ptr @@ -88,7 +88,7 @@ class Wifi : public V1_2::IWifi { }; } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/wifi_ap_iface.cpp b/wifi/1.3/default/wifi_ap_iface.cpp similarity index 98% rename from wifi/1.2/default/wifi_ap_iface.cpp rename to wifi/1.3/default/wifi_ap_iface.cpp index 92b7b48d98..c203e47b5d 100644 --- a/wifi/1.2/default/wifi_ap_iface.cpp +++ b/wifi/1.3/default/wifi_ap_iface.cpp @@ -24,7 +24,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { using hidl_return_util::validateAndCall; @@ -93,7 +93,7 @@ WifiApIface::getValidFrequenciesForBandInternal(WifiBand band) { return {createWifiStatusFromLegacyError(legacy_status), valid_frequencies}; } } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/wifi_ap_iface.h b/wifi/1.3/default/wifi_ap_iface.h similarity index 98% rename from wifi/1.2/default/wifi_ap_iface.h rename to wifi/1.3/default/wifi_ap_iface.h index 5363ec2586..9f3d870d35 100644 --- a/wifi/1.2/default/wifi_ap_iface.h +++ b/wifi/1.3/default/wifi_ap_iface.h @@ -25,7 +25,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { using namespace android::hardware::wifi::V1_0; @@ -65,7 +65,7 @@ class WifiApIface : public V1_0::IWifiApIface { }; } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/wifi_chip.cpp b/wifi/1.3/default/wifi_chip.cpp similarity index 97% rename from wifi/1.2/default/wifi_chip.cpp rename to wifi/1.3/default/wifi_chip.cpp index c4da184884..cf64e51faa 100644 --- a/wifi/1.2/default/wifi_chip.cpp +++ b/wifi/1.3/default/wifi_chip.cpp @@ -28,13 +28,13 @@ #include "wifi_status_util.h" namespace { +using android::sp; using android::base::unique_fd; using android::hardware::hidl_string; using android::hardware::hidl_vec; using android::hardware::wifi::V1_0::ChipModeId; using android::hardware::wifi::V1_0::IfaceType; using android::hardware::wifi::V1_0::IWifiChip; -using android::sp; constexpr ChipModeId kInvalidModeId = UINT32_MAX; // These mode ID's should be unique (even across combo versions). Refer to @@ -304,7 +304,7 @@ std::vector makeCharVec(const std::string& str) { namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { using hidl_return_util::validateAndCall; using hidl_return_util::validateAndCallWithLock; @@ -335,7 +335,7 @@ void WifiChip::invalidate() { bool WifiChip::isValid() { return is_valid_; } -std::set> WifiChip::getEventCallbacks() { +std::set> WifiChip::getEventCallbacks() { return event_cb_handler_.getCallbacks(); } @@ -344,6 +344,7 @@ Return WifiChip::getId(getId_cb hidl_status_cb) { &WifiChip::getIdInternal, hidl_status_cb); } +// Deprecated support for this callback Return WifiChip::registerEventCallback( const sp& event_callback, registerEventCallback_cb hidl_status_cb) { @@ -546,7 +547,8 @@ Return WifiChip::enableDebugErrorAlerts( } Return WifiChip::selectTxPowerScenario( - V1_1::IWifiChip::TxPowerScenario scenario, selectTxPowerScenario_cb hidl_status_cb) { + V1_1::IWifiChip::TxPowerScenario scenario, + selectTxPowerScenario_cb hidl_status_cb) { return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, &WifiChip::selectTxPowerScenarioInternal, hidl_status_cb, scenario); @@ -560,7 +562,7 @@ Return WifiChip::resetTxPowerScenario( } Return WifiChip::registerEventCallback_1_2( - const sp& event_callback, + const sp& event_callback, registerEventCallback_cb hidl_status_cb) { return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, &WifiChip::registerEventCallbackInternal_1_2, @@ -568,9 +570,10 @@ Return WifiChip::registerEventCallback_1_2( } Return WifiChip::selectTxPowerScenario_1_2( - TxPowerScenario scenario, selectTxPowerScenario_cb hidl_status_cb) { + TxPowerScenario scenario, selectTxPowerScenario_cb hidl_status_cb) { return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, - &WifiChip::selectTxPowerScenarioInternal_1_2, hidl_status_cb, scenario); + &WifiChip::selectTxPowerScenarioInternal_1_2, + hidl_status_cb, scenario); } Return WifiChip::debug(const hidl_handle& handle, @@ -1036,7 +1039,7 @@ WifiStatus WifiChip::enableDebugErrorAlertsInternal(bool enable) { } WifiStatus WifiChip::selectTxPowerScenarioInternal( - V1_1::IWifiChip::TxPowerScenario scenario) { + V1_1::IWifiChip::TxPowerScenario scenario) { auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario( getWlan0IfaceName(), hidl_struct_util::convertHidlTxPowerScenarioToLegacy(scenario)); @@ -1050,14 +1053,15 @@ WifiStatus WifiChip::resetTxPowerScenarioInternal() { } WifiStatus WifiChip::registerEventCallbackInternal_1_2( - const sp& event_callback) { + const sp& event_callback) { if (!event_cb_handler_.addCallback(event_callback)) { return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); } return createWifiStatus(WifiStatusCode::SUCCESS); } -WifiStatus WifiChip::selectTxPowerScenarioInternal_1_2(TxPowerScenario scenario) { +WifiStatus WifiChip::selectTxPowerScenarioInternal_1_2( + TxPowerScenario scenario) { auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario( getWlan0IfaceName(), hidl_struct_util::convertHidlTxPowerScenarioToLegacy_1_2(scenario)); @@ -1156,7 +1160,7 @@ WifiStatus WifiChip::registerRadioModeChangeCallback() { LOG(ERROR) << "Callback invoked on an invalid object"; return; } - std::vector + std::vector hidl_radio_mode_infos; if (!hidl_struct_util::convertLegacyWifiMacInfosToHidl( mac_infos, &hidl_radio_mode_infos)) { @@ -1212,15 +1216,14 @@ void WifiChip::populateModes() { const IWifiChip::ChipIfaceCombination chip_iface_combination_2 = { {chip_iface_combination_limit_1, chip_iface_combination_limit_3}}; if (feature_flags_.lock()->isApDisabled()) { - const IWifiChip::ChipMode chip_mode = { - kV2ChipModeId, - {chip_iface_combination_2}}; - modes_ = {chip_mode}; + const IWifiChip::ChipMode chip_mode = {kV2ChipModeId, + {chip_iface_combination_2}}; + modes_ = {chip_mode}; } else { - const IWifiChip::ChipMode chip_mode = { - kV2ChipModeId, - {chip_iface_combination_1, chip_iface_combination_2}}; - modes_ = {chip_mode}; + const IWifiChip::ChipMode chip_mode = { + kV2ChipModeId, + {chip_iface_combination_1, chip_iface_combination_2}}; + modes_ = {chip_mode}; } } else { // V1 Iface combinations for Mode Id = 0. (STA Mode) @@ -1246,9 +1249,9 @@ void WifiChip::populateModes() { const IWifiChip::ChipMode ap_chip_mode = {kV1ApChipModeId, {ap_chip_iface_combination}}; if (feature_flags_.lock()->isApDisabled()) { - modes_ = {sta_chip_mode}; + modes_ = {sta_chip_mode}; } else { - modes_ = {sta_chip_mode, ap_chip_mode}; + modes_ = {sta_chip_mode, ap_chip_mode}; } } } @@ -1415,7 +1418,7 @@ bool WifiChip::writeRingbufferFilesInternal() { } } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/wifi_chip.h b/wifi/1.3/default/wifi_chip.h similarity index 95% rename from wifi/1.2/default/wifi_chip.h rename to wifi/1.3/default/wifi_chip.h index ada945885e..ba60a8ea33 100644 --- a/wifi/1.2/default/wifi_chip.h +++ b/wifi/1.3/default/wifi_chip.h @@ -37,7 +37,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { using namespace android::hardware::wifi::V1_0; @@ -69,10 +69,11 @@ class WifiChip : public V1_2::IWifiChip { // marked valid before processing them. void invalidate(); bool isValid(); - std::set> getEventCallbacks(); + std::set> getEventCallbacks(); // HIDL methods exposed. Return getId(getId_cb hidl_status_cb) override; + // Deprecated support for this callback Return registerEventCallback( const sp& event_callback, registerEventCallback_cb hidl_status_cb) override; @@ -137,18 +138,20 @@ class WifiChip : public V1_2::IWifiChip { Return resetTxPowerScenario( resetTxPowerScenario_cb hidl_status_cb) override; Return registerEventCallback_1_2( - const sp& event_callback, + const sp& event_callback, registerEventCallback_1_2_cb hidl_status_cb) override; Return selectTxPowerScenario_1_2( TxPowerScenario scenario, selectTxPowerScenario_cb hidl_status_cb) override; Return debug(const hidl_handle& handle, const hidl_vec& options) override; + private: void invalidateAndRemoveAllIfaces(); // Corresponding worker functions for the HIDL methods. std::pair getIdInternal(); + // Deprecated support for this callback WifiStatus registerEventCallbackInternal( const sp& event_callback); std::pair getCapabilitiesInternal(); @@ -195,10 +198,11 @@ class WifiChip : public V1_2::IWifiChip { std::pair getDebugHostWakeReasonStatsInternal(); WifiStatus enableDebugErrorAlertsInternal(bool enable); - WifiStatus selectTxPowerScenarioInternal(V1_1::IWifiChip::TxPowerScenario scenario); + WifiStatus selectTxPowerScenarioInternal( + V1_1::IWifiChip::TxPowerScenario scenario); WifiStatus resetTxPowerScenarioInternal(); WifiStatus registerEventCallbackInternal_1_2( - const sp& event_callback); + const sp& event_callback); WifiStatus selectTxPowerScenarioInternal_1_2(TxPowerScenario scenario); WifiStatus handleChipConfiguration( std::unique_lock* lock, ChipModeId mode_id); @@ -236,14 +240,14 @@ class WifiChip : public V1_2::IWifiChip { // registration mechanism. Use this to check if we have already // registered a callback. bool debug_ring_buffer_cb_registered_; - hidl_callback_util::HidlCallbackHandler + hidl_callback_util::HidlCallbackHandler event_cb_handler_; DISALLOW_COPY_AND_ASSIGN(WifiChip); }; } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/wifi_feature_flags.cpp b/wifi/1.3/default/wifi_feature_flags.cpp similarity index 93% rename from wifi/1.2/default/wifi_feature_flags.cpp rename to wifi/1.3/default/wifi_feature_flags.cpp index 778944dd92..8d48c3628a 100644 --- a/wifi/1.2/default/wifi_feature_flags.cpp +++ b/wifi/1.3/default/wifi_feature_flags.cpp @@ -38,7 +38,7 @@ static const bool wifiHidlFeatureDisableAp = false; namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { namespace feature_flags { @@ -47,13 +47,11 @@ bool WifiFeatureFlags::isAwareSupported() { return wifiHidlFeatureAware; } bool WifiFeatureFlags::isDualInterfaceSupported() { return wifiHidlFeatureDualInterface; } -bool WifiFeatureFlags::isApDisabled() { - return wifiHidlFeatureDisableAp; -} +bool WifiFeatureFlags::isApDisabled() { return wifiHidlFeatureDisableAp; } } // namespace feature_flags } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/wifi_feature_flags.h b/wifi/1.3/default/wifi_feature_flags.h similarity index 96% rename from wifi/1.2/default/wifi_feature_flags.h rename to wifi/1.3/default/wifi_feature_flags.h index 4a7b2d225c..ce74e236b8 100644 --- a/wifi/1.2/default/wifi_feature_flags.h +++ b/wifi/1.3/default/wifi_feature_flags.h @@ -20,7 +20,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { namespace feature_flags { @@ -36,7 +36,7 @@ class WifiFeatureFlags { } // namespace feature_flags } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/wifi_legacy_hal.cpp b/wifi/1.3/default/wifi_legacy_hal.cpp similarity index 99% rename from wifi/1.2/default/wifi_legacy_hal.cpp rename to wifi/1.3/default/wifi_legacy_hal.cpp index 375204c70d..55fe0738cc 100644 --- a/wifi/1.2/default/wifi_legacy_hal.cpp +++ b/wifi/1.3/default/wifi_legacy_hal.cpp @@ -48,7 +48,7 @@ std::vector makeCharVec(const std::string& str) { namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { namespace legacy_hal { // Legacy HAL functions accept "C" style function pointers, so use global @@ -1417,7 +1417,7 @@ void WifiLegacyHal::invalidate() { } // namespace legacy_hal } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/wifi_legacy_hal.h b/wifi/1.3/default/wifi_legacy_hal.h similarity index 98% rename from wifi/1.2/default/wifi_legacy_hal.h rename to wifi/1.3/default/wifi_legacy_hal.h index 00dfeefb9a..af654fa8c7 100644 --- a/wifi/1.2/default/wifi_legacy_hal.h +++ b/wifi/1.3/default/wifi_legacy_hal.h @@ -27,14 +27,15 @@ // HACK: The include inside the namespace below also transitively includes a // bunch of libc headers into the namespace, which leads to functions like -// socketpair being defined in android::hardware::wifi::V1_1::implementation::legacy_hal. -// Include this one particular header as a hacky workaround until that's fixed. +// socketpair being defined in +// android::hardware::wifi::V1_1::implementation::legacy_hal. Include this one +// particular header as a hacky workaround until that's fixed. #include namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { // This is in a separate namespace to prevent typename conflicts between // the legacy HAL types and the HIDL interface types. @@ -106,7 +107,8 @@ struct NanCallbackHandlers { on_event_transmit_follow_up; std::function on_event_range_request; std::function on_event_range_report; - std::function on_event_schedule_update; + std::function + on_event_schedule_update; }; // Full scan results contain IE info and are hence passed by reference, to @@ -389,7 +391,7 @@ class WifiLegacyHal { } // namespace legacy_hal } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/wifi_legacy_hal_stubs.cpp b/wifi/1.3/default/wifi_legacy_hal_stubs.cpp similarity index 99% rename from wifi/1.2/default/wifi_legacy_hal_stubs.cpp rename to wifi/1.3/default/wifi_legacy_hal_stubs.cpp index fc28bb55e8..942df2a632 100644 --- a/wifi/1.2/default/wifi_legacy_hal_stubs.cpp +++ b/wifi/1.3/default/wifi_legacy_hal_stubs.cpp @@ -20,7 +20,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { namespace legacy_hal { template @@ -141,7 +141,7 @@ bool initHalFuncTableWithStubs(wifi_hal_fn* hal_fn) { } } // namespace legacy_hal } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/wifi_legacy_hal_stubs.h b/wifi/1.3/default/wifi_legacy_hal_stubs.h similarity index 96% rename from wifi/1.2/default/wifi_legacy_hal_stubs.h rename to wifi/1.3/default/wifi_legacy_hal_stubs.h index d560dd4e80..64854e00f6 100644 --- a/wifi/1.2/default/wifi_legacy_hal_stubs.h +++ b/wifi/1.3/default/wifi_legacy_hal_stubs.h @@ -20,7 +20,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { namespace legacy_hal { #include @@ -28,7 +28,7 @@ namespace legacy_hal { bool initHalFuncTableWithStubs(wifi_hal_fn* hal_fn); } // namespace legacy_hal } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/wifi_mode_controller.cpp b/wifi/1.3/default/wifi_mode_controller.cpp similarity index 98% rename from wifi/1.2/default/wifi_mode_controller.cpp rename to wifi/1.3/default/wifi_mode_controller.cpp index c286d2439c..c392486f84 100644 --- a/wifi/1.2/default/wifi_mode_controller.cpp +++ b/wifi/1.3/default/wifi_mode_controller.cpp @@ -48,7 +48,7 @@ int convertIfaceTypeToFirmwareMode(IfaceType type) { namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { namespace mode_controller { @@ -85,7 +85,7 @@ bool WifiModeController::deinitialize() { } } // namespace mode_controller } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/wifi_mode_controller.h b/wifi/1.3/default/wifi_mode_controller.h similarity index 98% rename from wifi/1.2/default/wifi_mode_controller.h rename to wifi/1.3/default/wifi_mode_controller.h index 395aa5d9e8..ace5a52839 100644 --- a/wifi/1.2/default/wifi_mode_controller.h +++ b/wifi/1.3/default/wifi_mode_controller.h @@ -24,7 +24,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { namespace mode_controller { using namespace android::hardware::wifi::V1_0; @@ -55,7 +55,7 @@ class WifiModeController { } // namespace mode_controller } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/wifi_nan_iface.cpp b/wifi/1.3/default/wifi_nan_iface.cpp similarity index 98% rename from wifi/1.2/default/wifi_nan_iface.cpp rename to wifi/1.3/default/wifi_nan_iface.cpp index 566d36e72b..4325f44dad 100644 --- a/wifi/1.2/default/wifi_nan_iface.cpp +++ b/wifi/1.3/default/wifi_nan_iface.cpp @@ -24,7 +24,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { using hidl_return_util::validateAndCall; @@ -420,7 +420,7 @@ WifiNanIface::WifiNanIface( LOG(ERROR) << "Callback invoked on an invalid object"; return; } - NanDataPathConfirmInd hidl_struct; + V1_2::NanDataPathConfirmInd hidl_struct; if (!hidl_struct_util::convertLegacyNanDataPathConfirmIndToHidl( msg, &hidl_struct)) { LOG(ERROR) << "Failed to convert nan capabilities response"; @@ -477,7 +477,7 @@ WifiNanIface::WifiNanIface( LOG(ERROR) << "Callback invoked on an invalid object"; return; } - NanDataPathScheduleUpdateInd hidl_struct; + V1_2::NanDataPathScheduleUpdateInd hidl_struct; if (!hidl_struct_util::convertLegacyNanDataPathScheduleUpdateIndToHidl( msg, &hidl_struct)) { LOG(ERROR) << "Failed to convert nan capabilities response"; @@ -655,7 +655,7 @@ Return WifiNanIface::terminateDataPathRequest( } Return WifiNanIface::registerEventCallback_1_2( - const sp& callback, + const sp& callback, registerEventCallback_1_2_cb hidl_status_cb) { return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, &WifiNanIface::registerEventCallback_1_2Internal, @@ -664,7 +664,7 @@ Return WifiNanIface::registerEventCallback_1_2( Return WifiNanIface::enableRequest_1_2( uint16_t cmd_id, const NanEnableRequest& msg1, - const NanConfigRequestSupplemental& msg2, + const V1_2::NanConfigRequestSupplemental& msg2, enableRequest_1_2_cb hidl_status_cb) { return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, &WifiNanIface::enableRequest_1_2Internal, @@ -673,7 +673,7 @@ Return WifiNanIface::enableRequest_1_2( Return WifiNanIface::configRequest_1_2( uint16_t cmd_id, const NanConfigRequest& msg1, - const NanConfigRequestSupplemental& msg2, + const V1_2::NanConfigRequestSupplemental& msg2, configRequest_1_2_cb hidl_status_cb) { return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, &WifiNanIface::configRequest_1_2Internal, @@ -832,7 +832,7 @@ WifiStatus WifiNanIface::registerEventCallback_1_2Internal( WifiStatus WifiNanIface::enableRequest_1_2Internal( uint16_t cmd_id, const NanEnableRequest& msg1, - const NanConfigRequestSupplemental& msg2) { + const V1_2::NanConfigRequestSupplemental& msg2) { legacy_hal::NanEnableRequest legacy_msg; if (!hidl_struct_util::convertHidlNanEnableRequest_1_2ToLegacy( msg1, msg2, &legacy_msg)) { @@ -845,7 +845,7 @@ WifiStatus WifiNanIface::enableRequest_1_2Internal( WifiStatus WifiNanIface::configRequest_1_2Internal( uint16_t cmd_id, const NanConfigRequest& msg1, - const NanConfigRequestSupplemental& msg2) { + const V1_2::NanConfigRequestSupplemental& msg2) { legacy_hal::NanConfigRequest legacy_msg; if (!hidl_struct_util::convertHidlNanConfigRequest_1_2ToLegacy( msg1, msg2, &legacy_msg)) { @@ -857,7 +857,7 @@ WifiStatus WifiNanIface::configRequest_1_2Internal( } } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/wifi_nan_iface.h b/wifi/1.3/default/wifi_nan_iface.h similarity index 95% rename from wifi/1.2/default/wifi_nan_iface.h rename to wifi/1.3/default/wifi_nan_iface.h index dba527b5f5..f735d61cf9 100644 --- a/wifi/1.2/default/wifi_nan_iface.h +++ b/wifi/1.3/default/wifi_nan_iface.h @@ -27,7 +27,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { using namespace android::hardware::wifi::V1_0; @@ -89,15 +89,15 @@ class WifiNanIface : public V1_2::IWifiNanIface { terminateDataPathRequest_cb hidl_status_cb) override; Return registerEventCallback_1_2( - const sp& callback, + const sp& callback, registerEventCallback_1_2_cb hidl_status_cb) override; Return enableRequest_1_2( uint16_t cmd_id, const NanEnableRequest& msg1, - const NanConfigRequestSupplemental& msg2, + const V1_2::NanConfigRequestSupplemental& msg2, enableRequest_1_2_cb hidl_status_cb) override; Return configRequest_1_2( uint16_t cmd_id, const NanConfigRequest& msg1, - const NanConfigRequestSupplemental& msg2, + const V1_2::NanConfigRequestSupplemental& msg2, configRequest_1_2_cb hidl_status_cb) override; private: @@ -135,10 +135,10 @@ class WifiNanIface : public V1_2::IWifiNanIface { const sp& callback); WifiStatus enableRequest_1_2Internal( uint16_t cmd_id, const NanEnableRequest& msg1, - const NanConfigRequestSupplemental& msg2); + const V1_2::NanConfigRequestSupplemental& msg2); WifiStatus configRequest_1_2Internal( uint16_t cmd_id, const NanConfigRequest& msg, - const NanConfigRequestSupplemental& msg2); + const V1_2::NanConfigRequestSupplemental& msg2); // all 1_0 and descendant callbacks std::set> getEventCallbacks(); @@ -157,7 +157,7 @@ class WifiNanIface : public V1_2::IWifiNanIface { }; } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/wifi_p2p_iface.cpp b/wifi/1.3/default/wifi_p2p_iface.cpp similarity index 98% rename from wifi/1.2/default/wifi_p2p_iface.cpp rename to wifi/1.3/default/wifi_p2p_iface.cpp index 92bbaee388..b5d5886f68 100644 --- a/wifi/1.2/default/wifi_p2p_iface.cpp +++ b/wifi/1.3/default/wifi_p2p_iface.cpp @@ -23,7 +23,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { using hidl_return_util::validateAndCall; @@ -60,7 +60,7 @@ std::pair WifiP2pIface::getTypeInternal() { } } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/wifi_p2p_iface.h b/wifi/1.3/default/wifi_p2p_iface.h similarity index 98% rename from wifi/1.2/default/wifi_p2p_iface.h rename to wifi/1.3/default/wifi_p2p_iface.h index 76120b1574..8a7207a412 100644 --- a/wifi/1.2/default/wifi_p2p_iface.h +++ b/wifi/1.3/default/wifi_p2p_iface.h @@ -25,7 +25,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { using namespace android::hardware::wifi::V1_0; @@ -58,7 +58,7 @@ class WifiP2pIface : public V1_0::IWifiP2pIface { }; } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/wifi_rtt_controller.cpp b/wifi/1.3/default/wifi_rtt_controller.cpp similarity index 99% rename from wifi/1.2/default/wifi_rtt_controller.cpp rename to wifi/1.3/default/wifi_rtt_controller.cpp index b68445bf83..fa317e3aeb 100644 --- a/wifi/1.2/default/wifi_rtt_controller.cpp +++ b/wifi/1.3/default/wifi_rtt_controller.cpp @@ -24,7 +24,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { using hidl_return_util::validateAndCall; @@ -269,7 +269,7 @@ WifiStatus WifiRttController::disableResponderInternal(uint32_t cmd_id) { return createWifiStatusFromLegacyError(legacy_status); } } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/wifi_rtt_controller.h b/wifi/1.3/default/wifi_rtt_controller.h similarity index 99% rename from wifi/1.2/default/wifi_rtt_controller.h rename to wifi/1.3/default/wifi_rtt_controller.h index 1ab01e1702..9798b79f8d 100644 --- a/wifi/1.2/default/wifi_rtt_controller.h +++ b/wifi/1.3/default/wifi_rtt_controller.h @@ -27,7 +27,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { /** @@ -97,7 +97,7 @@ class WifiRttController : public V1_0::IWifiRttController { }; } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/wifi_sta_iface.cpp b/wifi/1.3/default/wifi_sta_iface.cpp similarity index 99% rename from wifi/1.2/default/wifi_sta_iface.cpp rename to wifi/1.3/default/wifi_sta_iface.cpp index daa56101c3..63341dfb4a 100644 --- a/wifi/1.2/default/wifi_sta_iface.cpp +++ b/wifi/1.3/default/wifi_sta_iface.cpp @@ -24,7 +24,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { using hidl_return_util::validateAndCall; @@ -622,7 +622,7 @@ WifiStatus WifiStaIface::setMacAddressInternal( } } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/wifi_sta_iface.h b/wifi/1.3/default/wifi_sta_iface.h similarity index 99% rename from wifi/1.2/default/wifi_sta_iface.h rename to wifi/1.3/default/wifi_sta_iface.h index 71cd17d30c..0fc61e2857 100644 --- a/wifi/1.2/default/wifi_sta_iface.h +++ b/wifi/1.3/default/wifi_sta_iface.h @@ -29,7 +29,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { using namespace android::hardware::wifi::V1_0; @@ -163,7 +163,7 @@ class WifiStaIface : public V1_2::IWifiStaIface { }; } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/wifi_status_util.cpp b/wifi/1.3/default/wifi_status_util.cpp similarity index 99% rename from wifi/1.2/default/wifi_status_util.cpp rename to wifi/1.3/default/wifi_status_util.cpp index dd37b6ba80..0a5bb13d4f 100644 --- a/wifi/1.2/default/wifi_status_util.cpp +++ b/wifi/1.3/default/wifi_status_util.cpp @@ -19,7 +19,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { std::string legacyErrorToString(legacy_hal::wifi_error error) { @@ -100,7 +100,7 @@ WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error) { } } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.2/default/wifi_status_util.h b/wifi/1.3/default/wifi_status_util.h similarity index 97% rename from wifi/1.2/default/wifi_status_util.h rename to wifi/1.3/default/wifi_status_util.h index e9136b38ca..bc8baa9fe7 100644 --- a/wifi/1.2/default/wifi_status_util.h +++ b/wifi/1.3/default/wifi_status_util.h @@ -24,7 +24,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_2 { +namespace V1_3 { namespace implementation { using namespace android::hardware::wifi::V1_0; @@ -37,7 +37,7 @@ WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error, WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error); } // namespace implementation -} // namespace V1_2 +} // namespace V1_3 } // namespace wifi } // namespace hardware } // namespace android From bbc5940fe8f63907323612ec8b2b4a7614cd8633 Mon Sep 17 00:00:00 2001 From: Yifan Hong Date: Wed, 8 Aug 2018 17:49:29 -0700 Subject: [PATCH 064/718] Add health.filesystem HAL. Test: builds Bug: 111655771 Change-Id: I29f157912ef74b4efd64def93ea125aa079ac1eb --- health/filesystem/1.0/Android.bp | 21 +++++++++++++++ health/filesystem/1.0/IFileSystem.hal | 33 +++++++++++++++++++++++ health/filesystem/1.0/types.hal | 39 +++++++++++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 health/filesystem/1.0/Android.bp create mode 100644 health/filesystem/1.0/IFileSystem.hal create mode 100644 health/filesystem/1.0/types.hal diff --git a/health/filesystem/1.0/Android.bp b/health/filesystem/1.0/Android.bp new file mode 100644 index 0000000000..74b9bc31e4 --- /dev/null +++ b/health/filesystem/1.0/Android.bp @@ -0,0 +1,21 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +hidl_interface { + name: "android.hardware.health.filesystem@1.0", + root: "android.hardware", + vndk: { + enabled: true, + }, + srcs: [ + "types.hal", + "IFileSystem.hal", + ], + interfaces: [ + "android.hidl.base@1.0", + ], + types: [ + "Result", + ], + gen_java: true, +} + diff --git a/health/filesystem/1.0/IFileSystem.hal b/health/filesystem/1.0/IFileSystem.hal new file mode 100644 index 0000000000..33ea3ff849 --- /dev/null +++ b/health/filesystem/1.0/IFileSystem.hal @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.health.filesystem@1.0; + +/** + * IFileSystem is an interface that provides operations on underlying storage + * devices, including flash memory. + */ +interface IFileSystem { + /** + * Start garbage collection on the driver of storage devices. This function + * must be called at regular intervals when it is a good time for a + * longer-running cleanup tasks. + * + * @return result Execution result. See documentation for Result for + * details. + */ + garbageCollect() generates (Result result); +}; diff --git a/health/filesystem/1.0/types.hal b/health/filesystem/1.0/types.hal new file mode 100644 index 0000000000..00431f7522 --- /dev/null +++ b/health/filesystem/1.0/types.hal @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.health.filesystem@1.0; + +/** + * Status values for HAL methods. + */ +enum Result : uint32_t { + /** + * Execution of the method is successful. + */ + SUCCESS = 0, + /** + * Execution of the method timed out. + */ + TIMEOUT, + /** + * An IO error is encountered when the HAL communicates with the device. + */ + IO_ERROR, + /** + * An unknown error is encountered. + */ + UNKNOWN_ERROR, +}; From 62ca53926e2af578fcca3ce649d621aec39971ec Mon Sep 17 00:00:00 2001 From: Yifan Hong Date: Thu, 9 Aug 2018 13:32:04 -0700 Subject: [PATCH 065/718] Add health filesystem HAL to compatibility matrix Test: no build errors Bug: 111655771 Change-Id: I4cc6308f969840996560ac65143744d37cbf0b14 --- compatibility_matrices/compatibility_matrix.current.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml index f14fceacee..78d1bf69b6 100644 --- a/compatibility_matrices/compatibility_matrix.current.xml +++ b/compatibility_matrices/compatibility_matrix.current.xml @@ -207,6 +207,14 @@ default + + android.hardware.health.filesystem + 1.0 + + IFileSystem + default + + android.hardware.ir 1.0 From 4c64118f605786eaac06823b16fa5cb707709bd4 Mon Sep 17 00:00:00 2001 From: Yin-Chia Yeh Date: Mon, 6 Aug 2018 15:01:20 -0700 Subject: [PATCH 066/718] Camera: plumb blob buffer size from framework Test: blob size is sent from camera service to webcam HAL using TestingCamera2 Bug: 72173567 Change-Id: I9937881d98dd7d984da5e6ec929118f5d8fe7c9e --- .../default/ExternalCameraDeviceSession.cpp | 34 +++++++++++++++---- .../ExternalCameraDeviceSession.h | 9 +++-- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp index 28ca0f351c..350f48bc3f 100644 --- a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp +++ b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp @@ -344,17 +344,31 @@ Return ExternalCameraDeviceSession::configureStreams_3_4( ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb) { V3_2::StreamConfiguration config_v32; V3_3::HalStreamConfiguration outStreams_v33; + V3_4::HalStreamConfiguration outStreams; Mutex::Autolock _il(mInterfaceLock); config_v32.operationMode = requestedConfiguration.operationMode; config_v32.streams.resize(requestedConfiguration.streams.size()); + uint32_t blobBufferSize = 0; + int numStallStream = 0; for (size_t i = 0; i < config_v32.streams.size(); i++) { config_v32.streams[i] = requestedConfiguration.streams[i].v3_2; + if (config_v32.streams[i].format == PixelFormat::BLOB) { + blobBufferSize = requestedConfiguration.streams[i].bufferSize; + numStallStream++; + } } - Status status = configureStreams(config_v32, &outStreams_v33); + // Fail early if there are multiple BLOB streams + if (numStallStream > kMaxStallStream) { + ALOGE("%s: too many stall streams (expect <= %d, got %d)", __FUNCTION__, + kMaxStallStream, numStallStream); + _hidl_cb(Status::ILLEGAL_ARGUMENT, outStreams); + return Void(); + } + + Status status = configureStreams(config_v32, &outStreams_v33, blobBufferSize); - V3_4::HalStreamConfiguration outStreams; outStreams.streams.resize(outStreams_v33.streams.size()); for (size_t i = 0; i < outStreams.streams.size(); i++) { outStreams.streams[i].v3_3 = outStreams_v33.streams[i]; @@ -1592,8 +1606,9 @@ int ExternalCameraDeviceSession::OutputThread::createJpegLocked( * main image needs to hold APP1, headers, and at most a poorly * compressed image */ const ssize_t maxThumbCodeSize = 64 * 1024; - const ssize_t maxJpegCodeSize = parent->getJpegBufferSize(jpegSize.width, - jpegSize.height); + const ssize_t maxJpegCodeSize = mBlobBufferSize == 0 ? + parent->getJpegBufferSize(jpegSize.width, jpegSize.height) : + mBlobBufferSize; /* Check that getJpegBufferSize did not return an error */ if (maxJpegCodeSize < 0) { @@ -1855,7 +1870,8 @@ bool ExternalCameraDeviceSession::OutputThread::threadLoop() { Status ExternalCameraDeviceSession::OutputThread::allocateIntermediateBuffers( const Size& v4lSize, const Size& thumbSize, - const hidl_vec& streams) { + const hidl_vec& streams, + uint32_t blobBufferSize) { std::lock_guard lk(mBufferLock); if (mScaledYu12Frames.size() != 0) { ALOGE("%s: intermediate buffer pool has %zu inflight buffers! (expect 0)", @@ -1924,6 +1940,8 @@ Status ExternalCameraDeviceSession::OutputThread::allocateIntermediateBuffers( it = mIntermediateBuffers.erase(it); } } + + mBlobBufferSize = blobBufferSize; return Status::OK; } @@ -2420,7 +2438,9 @@ void ExternalCameraDeviceSession::enqueueV4l2Frame(const sp& frame) { } Status ExternalCameraDeviceSession::configureStreams( - const V3_2::StreamConfiguration& config, V3_3::HalStreamConfiguration* out) { + const V3_2::StreamConfiguration& config, + V3_3::HalStreamConfiguration* out, + uint32_t blobBufferSize) { ATRACE_CALL(); if (config.operationMode != StreamConfigurationMode::NORMAL_MODE) { ALOGE("%s: unsupported operation mode: %d", __FUNCTION__, config.operationMode); @@ -2582,7 +2602,7 @@ Status ExternalCameraDeviceSession::configureStreams( } status = mOutputThread->allocateIntermediateBuffers(v4lSize, - mMaxThumbResolution, config.streams); + mMaxThumbResolution, config.streams, blobBufferSize); if (status != Status::OK) { ALOGE("%s: allocating intermediate buffers failed!", __FUNCTION__); return status; diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h index 0b94c11222..6e56596fbd 100644 --- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h +++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h @@ -177,7 +177,10 @@ protected: Status initStatus() const; status_t initDefaultRequests(); status_t fillCaptureResult(common::V1_0::helper::CameraMetadata& md, nsecs_t timestamp); - Status configureStreams(const V3_2::StreamConfiguration&, V3_3::HalStreamConfiguration* out); + Status configureStreams(const V3_2::StreamConfiguration&, + V3_3::HalStreamConfiguration* out, + // Only filled by configureStreams_3_4, and only one blob stream supported + uint32_t blobBufferSize = 0); // fps = 0.0 means default, which is // slowest fps that is at least 30, or fastest fps if 30 is not supported int configureV4l2StreamLocked(const SupportedV4L2Format& fmt, double fps = 0.0); @@ -225,7 +228,8 @@ protected: Status allocateIntermediateBuffers( const Size& v4lSize, const Size& thumbSize, - const hidl_vec& streams); + const hidl_vec& streams, + uint32_t blobBufferSize); Status submitRequest(const std::shared_ptr&); void flush(); void dump(int fd); @@ -289,6 +293,7 @@ protected: std::unordered_map, SizeHasher> mScaledYu12Frames; YCbCrLayout mYu12FrameLayout; YCbCrLayout mYu12ThumbFrameLayout; + uint32_t mBlobBufferSize = 0; // 0 -> HAL derive buffer size, else: use given size std::string mExifMake; std::string mExifModel; From d03e8f0848ee464a966cb8f4b6cb78ffaa60f145 Mon Sep 17 00:00:00 2001 From: jiabin Date: Wed, 15 Aug 2018 16:57:54 -0700 Subject: [PATCH 067/718] Test getActiveMicrophones API when mic is found on the device. Before this patch the default microphone was required to have characteristics although it is not always an attached device, thus its characteristics can not be known by the HAL. Additionally, the HAL might not know the active microphone info of a input stream if it has not been started yet. This patch only tests microphones which characteristics are reported by the HAL and start the input stream before requesting active microphones. Bug: 109787938 Test: vts-tradefed run vts --module VtsHalAudioV4_0Target Change-Id: If55bfc8210d4f9443d34951f717c6772b46dde04 --- audio/core/4.0/vts/functional/Android.bp | 3 + .../functional/AudioPrimaryHidlHalTest.cpp | 87 +++++++++++++++++-- 2 files changed, 81 insertions(+), 9 deletions(-) diff --git a/audio/core/4.0/vts/functional/Android.bp b/audio/core/4.0/vts/functional/Android.bp index 22c5493dd8..e3b376ca88 100644 --- a/audio/core/4.0/vts/functional/Android.bp +++ b/audio/core/4.0/vts/functional/Android.bp @@ -29,6 +29,9 @@ cc_test { "libicuuc_stubdata", "libxml2", ], + shared_libs: [ + "libfmq", + ], header_libs: [ "android.hardware.audio.common.util@all-versions", ], diff --git a/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp b/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp index b811c10f64..f4ab542416 100644 --- a/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp +++ b/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp @@ -38,6 +38,8 @@ #include #include #include +#include +#include #include @@ -55,13 +57,16 @@ using std::vector; using std::list; using ::android::sp; -using ::android::hardware::Return; +using ::android::hardware::EventFlag; using ::android::hardware::hidl_bitfield; using ::android::hardware::hidl_enum_range; using ::android::hardware::hidl_handle; using ::android::hardware::hidl_string; using ::android::hardware::hidl_vec; +using ::android::hardware::kSynchronizedReadWrite; +using ::android::hardware::MessageQueue; using ::android::hardware::MQDescriptorSync; +using ::android::hardware::Return; using ::android::hardware::audio::V4_0::AudioDrain; using ::android::hardware::audio::V4_0::DeviceAddress; using ::android::hardware::audio::V4_0::IDevice; @@ -71,6 +76,7 @@ using TtyMode = ::android::hardware::audio::V4_0::IPrimaryDevice::TtyMode; using ::android::hardware::audio::V4_0::IDevicesFactory; using ::android::hardware::audio::V4_0::IStream; using ::android::hardware::audio::V4_0::IStreamIn; +using ::android::hardware::audio::V4_0::MessageQueueFlagBits; using ::android::hardware::audio::V4_0::TimeSpec; using ReadParameters = ::android::hardware::audio::V4_0::IStreamIn::ReadParameters; using ReadStatus = ::android::hardware::audio::V4_0::IStreamIn::ReadStatus; @@ -489,7 +495,7 @@ TEST_F(AudioPrimaryHidlTest, getParameters) { } ////////////////////////////////////////////////////////////////////////////// -/////////////////////////////// getMicrophones /////////////////////////////// +/////////////////////////// get(Active)Microphones /////////////////////////// ////////////////////////////////////////////////////////////////////////////// TEST_F(AudioPrimaryHidlTest, GetMicrophonesTest) { @@ -497,6 +503,76 @@ TEST_F(AudioPrimaryHidlTest, GetMicrophonesTest) { hidl_vec microphones; ASSERT_OK(device->getMicrophones(returnIn(res, microphones))); ASSERT_OK(res); + if (microphones.size() > 0) { + // When there is microphone on the phone, try to open an input stream + // and query for the active microphones. + doc::test( + "Make sure getMicrophones always succeeds" + "and getActiveMicrophones always succeeds when recording from these microphones."); + AudioIoHandle ioHandle = (AudioIoHandle)AudioHandleConsts::AUDIO_IO_HANDLE_NONE; + AudioConfig config{}; + config.channelMask = mkBitfield(AudioChannelMask::IN_MONO); + config.sampleRateHz = 8000; + config.format = AudioFormat::PCM_16_BIT; + auto flags = hidl_bitfield(AudioInputFlag::NONE); + const SinkMetadata initialMetadata = {{{AudioSource::MIC, 1 /* gain */}}}; + EventFlag* efGroup; + for (auto microphone : microphones) { + if (microphone.deviceAddress.device != AudioDevice::IN_BUILTIN_MIC) { + continue; + } + sp stream; + AudioConfig suggestedConfig{}; + ASSERT_OK(device->openInputStream(ioHandle, microphone.deviceAddress, config, flags, + initialMetadata, + returnIn(res, stream, suggestedConfig))); + if (res != Result::OK) { + ASSERT_TRUE(stream == nullptr); + AudioConfig suggestedConfigRetry{}; + ASSERT_OK(device->openInputStream(ioHandle, microphone.deviceAddress, + suggestedConfig, flags, initialMetadata, + returnIn(res, stream, suggestedConfigRetry))); + } + ASSERT_OK(res); + hidl_vec activeMicrophones; + Result readRes; + typedef MessageQueue CommandMQ; + typedef MessageQueue DataMQ; + std::unique_ptr commandMQ; + std::unique_ptr dataMQ; + size_t frameSize = stream->getFrameSize(); + size_t frameCount = stream->getBufferSize() / frameSize; + ASSERT_OK(stream->prepareForReading( + frameSize, frameCount, [&](auto r, auto& c, auto& d, auto&, auto&) { + readRes = r; + if (readRes == Result::OK) { + commandMQ.reset(new CommandMQ(c)); + dataMQ.reset(new DataMQ(d)); + if (dataMQ->isValid() && dataMQ->getEventFlagWord()) { + EventFlag::createEventFlag(dataMQ->getEventFlagWord(), &efGroup); + } + } + })); + ASSERT_OK(readRes); + ReadParameters params; + params.command = IStreamIn::ReadCommand::READ; + ASSERT_TRUE(commandMQ != nullptr); + ASSERT_TRUE(commandMQ->isValid()); + ASSERT_TRUE(commandMQ->write(¶ms)); + efGroup->wake(static_cast(MessageQueueFlagBits::NOT_FULL)); + uint32_t efState = 0; + efGroup->wait(static_cast(MessageQueueFlagBits::NOT_EMPTY), &efState); + if (efState & static_cast(MessageQueueFlagBits::NOT_EMPTY)) { + ASSERT_OK(stream->getActiveMicrophones(returnIn(res, activeMicrophones))); + ASSERT_OK(res); + ASSERT_NE(0U, activeMicrophones.size()); + } + stream->close(); + if (efGroup) { + EventFlag::deleteEventFlag(&efGroup); + } + } + } } ////////////////////////////////////////////////////////////////////////////// @@ -1104,13 +1180,6 @@ TEST_P(InputStreamTest, updateSinkMetadata) { ASSERT_OK(stream->updateSinkMetadata(initialMetadata)); } -TEST_P(InputStreamTest, getActiveMicrophones) { - doc::test("Active microphones of a non started stream may not be retrievable"); - hidl_vec microphones; - ASSERT_OK(stream->getActiveMicrophones(returnIn(res, microphones))); - ASSERT_RESULT(okOrNotSupported, res); -} - ////////////////////////////////////////////////////////////////////////////// ///////////////////////////////// StreamOut ////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// From 7153e81c2fb93572760c94d647f6ec26b7286e33 Mon Sep 17 00:00:00 2001 From: Ahmed ElArabawy Date: Tue, 5 Jun 2018 11:09:39 -0700 Subject: [PATCH 068/718] Wifi: Set wlan.driver.status to 'ok' when ready Currently, the wlan.driver.status property is set to 'ok' once the driver is loaded. This is not accurate, cause having the driver loaded does not necessarily means it is ready for operation. This commit sets the driver to 'ok' state after it is checked for readiness. This implementation of the check is device specific. Bug: 111924712 Test: Manual test Change-Id: I074d819e9acdfdd6f033d85cdd71c0bc3984eb9d Signed-off-by: Ahmed ElArabawy --- wifi/1.3/default/wifi_legacy_hal.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/wifi/1.3/default/wifi_legacy_hal.cpp b/wifi/1.3/default/wifi_legacy_hal.cpp index 55fe0738cc..817c860f58 100644 --- a/wifi/1.3/default/wifi_legacy_hal.cpp +++ b/wifi/1.3/default/wifi_legacy_hal.cpp @@ -18,6 +18,7 @@ #include #include +#include #include "hidl_sync_util.h" #include "wifi_legacy_hal.h" @@ -35,6 +36,7 @@ static constexpr uint32_t kLinkLayerStatsDataMpduSizeThreshold = 128; static constexpr uint32_t kMaxWakeReasonStatsArraySize = 32; static constexpr uint32_t kMaxRingBuffers = 10; static constexpr uint32_t kMaxStopCompleteWaitMs = 100; +static constexpr char kDriverPropName[] = "wlan.driver.status"; // Helper function to create a non-const char* for legacy Hal API's. std::vector makeCharVec(const std::string& str) { @@ -366,6 +368,8 @@ wifi_error WifiLegacyHal::start() { LOG(ERROR) << "Timed out awaiting driver ready"; return status; } + property_set(kDriverPropName, "ok"); + LOG(DEBUG) << "Starting legacy HAL"; if (!iface_tool_.SetWifiUpState(true)) { LOG(ERROR) << "Failed to set WiFi interface up"; From 667f11ab3ae92524ced9da890d91510dee4af48b Mon Sep 17 00:00:00 2001 From: Valerie Hau Date: Wed, 1 Aug 2018 12:58:44 -0700 Subject: [PATCH 069/718] Hardware composer VTS test harness Bug: 111563608 Test: VtsHalGraphicsComposerV2_2TargetTest Change-Id: I965efe8811e45a114978a9c8dd7a440c759787ec --- .../2.1/utils/vts/TestCommandReader.cpp | 32 +- .../composer-vts/2.1/TestCommandReader.h | 2 + .../composer/2.2/utils/vts/ComposerVts.cpp | 5 +- .../composer/2.2/vts/functional/Android.bp | 7 +- ...VtsHalGraphicsComposerV2_2ReadbackTest.cpp | 312 ++++++++++++++++++ 5 files changed, 352 insertions(+), 6 deletions(-) create mode 100644 graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp diff --git a/graphics/composer/2.1/utils/vts/TestCommandReader.cpp b/graphics/composer/2.1/utils/vts/TestCommandReader.cpp index 6f8f1ad480..e1dc5b6ebe 100644 --- a/graphics/composer/2.1/utils/vts/TestCommandReader.cpp +++ b/graphics/composer/2.1/utils/vts/TestCommandReader.cpp @@ -26,23 +26,53 @@ namespace V2_1 { namespace vts { void TestCommandReader::parse() { + mCompositionChanges.clear(); while (!isEmpty()) { IComposerClient::Command command; uint16_t length; ASSERT_TRUE(beginCommand(&command, &length)); switch (command) { + case IComposerClient::Command::SELECT_DISPLAY: + ASSERT_EQ(2, length); + read64(); // display + break; case IComposerClient::Command::SET_ERROR: { ASSERT_EQ(2, length); auto loc = read(); auto err = readSigned(); GTEST_FAIL() << "unexpected error " << err << " at location " << loc; } break; - case IComposerClient::Command::SELECT_DISPLAY: case IComposerClient::Command::SET_CHANGED_COMPOSITION_TYPES: + ASSERT_EQ(0, length % 3); + for (uint16_t count = 0; count < length / 3; ++count) { + uint64_t layerId = read64(); + uint32_t composition = read(); + + std::pair compositionChange(layerId, composition); + mCompositionChanges.push_back(compositionChange); + } + break; case IComposerClient::Command::SET_DISPLAY_REQUESTS: + ASSERT_EQ(1, length % 3); + read(); // displayRequests, ignored for now + for (uint16_t count = 0; count < (length - 1) / 3; ++count) { + read64(); // layer + // silently eat requests to clear the client target, since we won't be testing + // client composition anyway + ASSERT_EQ(1u, read()); + } + break; case IComposerClient::Command::SET_PRESENT_FENCE: + ASSERT_EQ(1, length); + close(readFence()); + break; case IComposerClient::Command::SET_RELEASE_FENCES: + ASSERT_EQ(0, length % 3); + for (uint16_t count = 0; count < length / 3; ++count) { + read64(); + close(readFence()); + } break; default: GTEST_FAIL() << "unexpected return command " << std::hex diff --git a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/TestCommandReader.h b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/TestCommandReader.h index 3888eebebd..b9a4a5c103 100644 --- a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/TestCommandReader.h +++ b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/TestCommandReader.h @@ -32,6 +32,8 @@ class TestCommandReader : public CommandReaderBase { // Parse all commands in the return command queue. Call GTEST_FAIL() for // unexpected errors or commands. void parse(); + + std::vector> mCompositionChanges; }; } // namespace vts diff --git a/graphics/composer/2.2/utils/vts/ComposerVts.cpp b/graphics/composer/2.2/utils/vts/ComposerVts.cpp index f2596a462a..459e0fe2c1 100644 --- a/graphics/composer/2.2/utils/vts/ComposerVts.cpp +++ b/graphics/composer/2.2/utils/vts/ComposerVts.cpp @@ -138,12 +138,11 @@ void ComposerClient::getReadbackBufferAttributes(Display display, PixelFormat* o } void ComposerClient::getReadbackBufferFence(Display display, int32_t* outFence) { - hidl_handle handle; mClient->getReadbackBufferFence(display, [&](const auto& tmpError, const auto& tmpHandle) { ASSERT_EQ(Error::NONE, tmpError) << "failed to get readback fence"; - handle = tmpHandle; + const native_handle_t* nativeFenceHandle = tmpHandle.getNativeHandle(); + *outFence = dup(nativeFenceHandle->data[0]); }); - *outFence = 0; } std::vector ComposerClient::getColorModes(Display display) { diff --git a/graphics/composer/2.2/vts/functional/Android.bp b/graphics/composer/2.2/vts/functional/Android.bp index 669fbaea35..acc9245952 100644 --- a/graphics/composer/2.2/vts/functional/Android.bp +++ b/graphics/composer/2.2/vts/functional/Android.bp @@ -17,12 +17,15 @@ cc_test { name: "VtsHalGraphicsComposerV2_2TargetTest", defaults: ["VtsHalTargetTestDefaults"], - srcs: ["VtsHalGraphicsComposerV2_2TargetTest.cpp"], + srcs: [ + "VtsHalGraphicsComposerV2_2ReadbackTest.cpp", + "VtsHalGraphicsComposerV2_2TargetTest.cpp", + ], // TODO(b/64437680): Assume these libs are always available on the device. shared_libs: [ "libfmq", - "libhidltransport", + "libhidltransport", "libsync", ], static_libs: [ diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp new file mode 100644 index 0000000000..fc32951c00 --- /dev/null +++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp @@ -0,0 +1,312 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "graphics_composer_hidl_hal_readback_tests@2.2" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace composer { +namespace V2_2 { +namespace vts { +namespace { + +using android::hardware::hidl_handle; +using common::V1_1::BufferUsage; +using common::V1_1::Dataspace; +using common::V1_1::PixelFormat; +using mapper::V2_1::IMapper; +using mapper::V2_1::vts::Gralloc; +using V2_1::Display; +using V2_1::Layer; +using V2_1::vts::TestCommandReader; + +// Test environment for graphics.composer +class GraphicsComposerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { + public: + // get the test environment singleton + static GraphicsComposerHidlEnvironment* Instance() { + static GraphicsComposerHidlEnvironment* instance = new GraphicsComposerHidlEnvironment; + return instance; + } + virtual void registerTestServices() override { registerTestService(); } + + private: + GraphicsComposerHidlEnvironment() {} + GTEST_DISALLOW_COPY_AND_ASSIGN_(GraphicsComposerHidlEnvironment); +}; + +class TestLayer { + public: + TestLayer(std::shared_ptr const client, Display display) + : mLayer(client->createLayer(display, kBufferSlotCount)), + mComposerClient(client), + mDisplay(display) {} + + virtual ~TestLayer() { mComposerClient->destroyLayer(mDisplay, mLayer); } + + virtual void write(std::shared_ptr writer) { + writer->selectLayer(mLayer); + writer->setLayerDisplayFrame(mDisplayFrame); + writer->setLayerZOrder(mZOrder); + } + + void setDisplayFrame(IComposerClient::Rect frame) { mDisplayFrame = frame; } + void setZOrder(uint32_t z) { mZOrder = z; } + + protected: + Layer mLayer; + IComposerClient::Rect mDisplayFrame = {0, 0, 0, 0}; + uint32_t mZOrder = 0; + + private: + std::shared_ptr const mComposerClient; + const Display mDisplay; + static constexpr uint32_t kBufferSlotCount = 64; +}; + +class TestColorLayer : public TestLayer { + public: + TestColorLayer(std::shared_ptr const client, Display display) + : TestLayer{client, display} {} + + void write(std::shared_ptr writer) override { + TestLayer::write(writer); + writer->setLayerCompositionType(IComposerClient::Composition::SOLID_COLOR); + writer->setLayerColor(mColor); + } + + void setColor(IComposerClient::Color color) { mColor = color; } + + private: + IComposerClient::Color mColor = {0xff, 0xff, 0xff, 0xff}; +}; + +class GraphicsComposerReadbackTest : public ::testing::VtsHalHidlTargetTestBase { + protected: + using PowerMode = V2_1::IComposerClient::PowerMode; + void SetUp() override { + ASSERT_NO_FATAL_FAILURE( + mComposer = std::make_unique( + GraphicsComposerHidlEnvironment::Instance()->getServiceName())); + ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient()); + mComposerCallback = new V2_1::vts::GraphicsComposerCallback; + mComposerClient->registerCallback(mComposerCallback); + + // assume the first display is primary and is never removed + mPrimaryDisplay = waitForFirstDisplay(); + Config activeConfig = mComposerClient->getActiveConfig(mPrimaryDisplay); + width = mComposerClient->getDisplayAttribute(mPrimaryDisplay, activeConfig, + IComposerClient::Attribute::WIDTH); + height = mComposerClient->getDisplayAttribute(mPrimaryDisplay, activeConfig, + IComposerClient::Attribute::HEIGHT); + + // explicitly disable vsync + mComposerClient->setVsyncEnabled(mPrimaryDisplay, false); + mComposerCallback->setVsyncAllowed(false); + + // set up command writer/reader and gralloc + mWriter = std::make_shared(1024); + mReader = std::make_unique(); + mGralloc = std::make_unique(); + } + + ~GraphicsComposerReadbackTest() override { + if (mComposerCallback != nullptr) { + EXPECT_EQ(0, mComposerCallback->getInvalidHotplugCount()); + EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount()); + EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount()); + } + } + + void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); } + + void render(const std::vector>& layers) { + for (auto layer : layers) { + layer->write(mWriter); + } + execute(); + mWriter->validateDisplay(); + mWriter->presentDisplay(); + execute(); + } + + int32_t GetBytesPerPixel(PixelFormat format) { + switch (format) { + case PixelFormat::RGBA_8888: + return 4; + case PixelFormat::RGB_888: + return 3; + default: + return -1; + } + } + + bool readbackSupported(const PixelFormat& pixelFormat, const Dataspace& dataspace, + const Error& error) { + if (error == Error::UNSUPPORTED) { + return false; + } + // TODO: add support for RGBA_1010102 + if (pixelFormat != PixelFormat::RGB_888 && pixelFormat != PixelFormat::RGBA_8888) { + return false; + } + if (dataspace != Dataspace::V0_SRGB) { + return false; + } + return true; + } + + void getReadbackBufferAttributes(Display display, PixelFormat* outPixelFormat, + Dataspace* outDataspace, Error* outError) { + mComposerClient->getRaw()->getReadbackBufferAttributes( + display, + [&](const auto& tmpError, const auto& tmpOutPixelFormat, const auto& tmpOutDataspace) { + *outError = tmpError; + *outPixelFormat = tmpOutPixelFormat; + *outDataspace = tmpOutDataspace; + }); + + // Not all devices support readback. Pass test if this is the case + if (!readbackSupported(*outPixelFormat, *outDataspace, *outError)) { + GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; + } + } + + void checkReadbackBuffer(IMapper::BufferDescriptorInfo info, uint32_t stride, void* bufferData, + std::vector expectedColors) { + int32_t bytesPerPixel = GetBytesPerPixel(info.format); + ASSERT_NE(-1, bytesPerPixel) + << "unexpected pixel format " << static_cast(info.format) + << "(expected RGBA_8888 or RGB_888)"; + for (int row = 0; row < height; row++) { + for (int col = 0; col < width; col++) { + int pixel = row * width + col; + int offset = (row * stride + col) * bytesPerPixel; + uint8_t* pixelColor = (uint8_t*)bufferData + offset; + + EXPECT_EQ(expectedColors[pixel].r, pixelColor[0]); + EXPECT_EQ(expectedColors[pixel].g, pixelColor[1]); + EXPECT_EQ(expectedColors[pixel].b, pixelColor[2]); + } + } + } + + std::unique_ptr mComposer; + std::shared_ptr mComposerClient; + + sp mComposerCallback; + // the first display and is assumed never to be removed + Display mPrimaryDisplay; + int32_t width; + int32_t height; + std::shared_ptr mWriter; + std::unique_ptr mReader; + std::unique_ptr mGralloc; + + private: + Display waitForFirstDisplay() { + while (true) { + std::vector displays = mComposerCallback->getDisplays(); + if (displays.empty()) { + usleep(5 * 1000); + continue; + } + return displays[0]; + } + } +}; + +TEST_F(GraphicsComposerReadbackTest, SingleSolidColorLayer) { + mWriter->selectDisplay(mPrimaryDisplay); + mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::ON); + mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB, RenderIntent::COLORIMETRIC); + + auto layer = std::make_shared(mComposerClient, mPrimaryDisplay); + IComposerClient::Color color({0, 0, 0xff, 0xff}); + IComposerClient::Rect coloredSquare({100, 100, 500, 500}); + layer->setColor(color); + layer->setDisplayFrame(coloredSquare); + layer->setZOrder(10); + + std::vector> layers = {layer}; + + // expected color for each pixel + std::vector expectedColors(width * height); + for (int row = 0; row < height; row++) { + for (int col = 0; col < width; col++) { + int pixel = row * width + col; + if (row >= coloredSquare.top && row < coloredSquare.bottom && + col >= coloredSquare.left && col < coloredSquare.right) { + expectedColors[pixel] = color; + } else { + expectedColors[pixel] = {0, 0, 0, 0xff}; + } + } + } + + PixelFormat pixelFormat; + Dataspace dataspace; + Error error; + getReadbackBufferAttributes(mPrimaryDisplay, &pixelFormat, &dataspace, &error); + + IMapper::BufferDescriptorInfo info; + info.width = width; + info.height = height; + info.layerCount = 1; + info.format = pixelFormat; + info.usage = static_cast(BufferUsage::CPU_READ_OFTEN | BufferUsage::GPU_TEXTURE); + + uint32_t stride; + const native_handle_t* buffer = mGralloc->allocate(info, /*import*/ true, &stride); + mComposerClient->setReadbackBuffer(mPrimaryDisplay, buffer, -1); + + render(layers); + + int32_t fenceHandle; + mComposerClient->getReadbackBufferFence(mPrimaryDisplay, &fenceHandle); + + base::unique_fd fence(fenceHandle); + + // lock buffer + // Create Rect accessRegion to specify reading the entire buffer + IMapper::Rect accessRegion; + accessRegion.left = 0; + accessRegion.top = 0; + accessRegion.width = info.width; + accessRegion.height = info.height; + + void* bufData = mGralloc->lock(buffer, info.usage, accessRegion, fence); + checkReadbackBuffer(info, stride, bufData, expectedColors); +} + +} // anonymous namespace +} // namespace vts +} // namespace V2_2 +} // namespace composer +} // namespace graphics +} // namespace hardware +} // namespace android From 3ebd7eef797903844c3a9964a6b33630ab444e9c Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Fri, 17 Aug 2018 14:03:35 -0700 Subject: [PATCH 070/718] [ConfigStore] Clarify hasHDRDisplay spec. BUG: 111505327 Test: Build, flash and boot Change-Id: Ie22d4c7b069a918f039a60317a213dc6a7efb205 --- configstore/1.0/ISurfaceFlingerConfigs.hal | 11 ++++++++--- current.txt | 1 + 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/configstore/1.0/ISurfaceFlingerConfigs.hal b/configstore/1.0/ISurfaceFlingerConfigs.hal index 5f975bd7dc..0790905e63 100644 --- a/configstore/1.0/ISurfaceFlingerConfigs.hal +++ b/configstore/1.0/ISurfaceFlingerConfigs.hal @@ -61,11 +61,16 @@ interface ISurfaceFlingerConfigs { hasWideColorDisplay() generates (OptionalBool value); /** - * hwHdrDisplay indicates that the device has - * or can support an HDR (High Dynamic Range) display. - * Typically an HDR display is also wide-color. + * hwHdrDisplay indicates that the device has an High Dynamic Range display. + * A display is considered High Dynamic Range if it + * + * 1. is a wide color gamut display, typically DCI-P3 or lager + * 2. has high luminance capability, typically 540 nits or higher at 10% OPR + * * Indicate support for this feature by setting * TARGET_HAS_HDR_DISPLAY to true in BoardConfig.mk + * TARGET_HAS_WIDE_COLOR_DISPLAY must be set to true when + * TARGET_HAS_HDR_DISPLAY is true. */ hasHDRDisplay() generates (OptionalBool value); diff --git a/current.txt b/current.txt index e92c9a085f..35143af59a 100644 --- a/current.txt +++ b/current.txt @@ -386,6 +386,7 @@ cd4330c3196bda1d642a32abfe23a7d64ebfbda721940643af6867af3b3f0aa9 android.hardwar # ABI preserving changes to HALs during Android Q a95745bbf76aea16a76518bd7efe70cabc5886d09eaeffc993c2e1787a22ed23 android.hardware.camera.metadata@3.3::types +5f936a5befde7af8d2a683670f80a836b4741e94d84b7b39026da3ed78be9906 android.hardware.configstore@1.0::ISurfaceFlingerConfigs 574e8f1499436fb4075894dcae0b36682427956ecb114f17f1fe22d116a83c6b android.hardware.neuralnetworks@1.0::IPreparedModel 1a5ae9793223658174258b523763c557abad6fb917df0b8e3cc097fc89035811 android.hardware.neuralnetworks@1.0::types 4310eb8272f085914952f3bfb73a8f8bb477a80e8b93596f0ea5acb58546b66d android.hardware.neuralnetworks@1.1::types From f8f948930204b14ca898407d922cc84cf7842eee Mon Sep 17 00:00:00 2001 From: Sungtak Lee Date: Fri, 3 Aug 2018 15:55:46 -0700 Subject: [PATCH 071/718] android.hardware.media.bufferpool@2.0 HAL BufferPool HAL 2.0. This is identical to 1.0 HAL now. The update will be applied afterwards. Bug: 112203066 Change-Id: I8f5bbf979116f66357f2bc0f8114697472adf762 --- media/bufferpool/2.0/Android.bp | 26 +++++++ media/bufferpool/2.0/IAccessor.hal | 68 ++++++++++++++++++ media/bufferpool/2.0/IClientManager.hal | 48 +++++++++++++ media/bufferpool/2.0/IConnection.hal | 43 ++++++++++++ media/bufferpool/2.0/README.md | 54 ++++++++++++++ media/bufferpool/2.0/types.hal | 93 +++++++++++++++++++++++++ 6 files changed, 332 insertions(+) create mode 100644 media/bufferpool/2.0/Android.bp create mode 100644 media/bufferpool/2.0/IAccessor.hal create mode 100644 media/bufferpool/2.0/IClientManager.hal create mode 100644 media/bufferpool/2.0/IConnection.hal create mode 100644 media/bufferpool/2.0/README.md create mode 100644 media/bufferpool/2.0/types.hal diff --git a/media/bufferpool/2.0/Android.bp b/media/bufferpool/2.0/Android.bp new file mode 100644 index 0000000000..405990eb93 --- /dev/null +++ b/media/bufferpool/2.0/Android.bp @@ -0,0 +1,26 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +hidl_interface { + name: "android.hardware.media.bufferpool@2.0", + root: "android.hardware", + vndk: { + enabled: true, + }, + srcs: [ + "types.hal", + "IAccessor.hal", + "IClientManager.hal", + "IConnection.hal", + ], + interfaces: [ + "android.hidl.base@1.0", + ], + types: [ + "Buffer", + "BufferStatus", + "BufferStatusMessage", + "ResultStatus", + ], + gen_java: false, +} + diff --git a/media/bufferpool/2.0/IAccessor.hal b/media/bufferpool/2.0/IAccessor.hal new file mode 100644 index 0000000000..07ea99dead --- /dev/null +++ b/media/bufferpool/2.0/IAccessor.hal @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.media.bufferpool@2.0; + +import IConnection; +/** + * IAccessor creates IConnection which is used from IClientManager in order to + * use functionality of the specified buffer pool. + */ +interface IAccessor { + + /** + * Registers a new client and creates IConnection to the buffer pool for + * the client. IConnection and FMQ are used by IClientManager in order to + * communicate with the buffer pool. Via FMQ IClientManager sends + * BufferStatusMesage(s) to the buffer pool. + * + * FMQ is used to send buffer ownership status changes to a buffer pool + * from a buffer pool client. A buffer pool synchronizes FMQ messages when + * there is a hidl request from the clients. Every client has its own + * connection and FMQ to communicate with the buffer pool. So sending an + * FMQ message on behalf of other clients is not possible. + * + * FMQ messages are sent when a buffer is acquired or released. Also, FMQ + * messages are sent when a buffer is transferred from a client to another + * client. FMQ has its own ID from a buffer pool. A client is specified + * with the ID. + * + * To transfer a buffer, a sender must send an FMQ message. The message + * must include a receiver's ID and a transaction ID. A receiver must send + * the transaction ID to fetch a buffer from a buffer pool. Since the + * sender already registered the receiver via an FMQ message, The buffer + * pool must verify the receiver with the transaction ID. In order to + * prevent faking a receiver, a connection to a buffer pool from client is + * made and kept private. Also part of transaction ID is a sender ID in + * order to prevent fake transactions from other clients. This must be + * verified with an FMQ message from a buffer pool. + * + * @return status The status of the call. + * OK - A connection is made successfully. + * NO_MEMORY - Memory allocation failure occurred. + * ALREADY_EXISTS - A connection was already made. + * CRITICAL_ERROR - Other errors. + * @return connection The IConnection have interfaces + * to get shared buffers from the buffer pool. + * @return connectionId Id of IConnection. The Id identifies + * sender and receiver in FMQ messages during buffer transfer. + * @return mqDesc FMQ descriptor. The descriptor can be used to + * send/receive FMQ messages. + */ + connect() + generates (ResultStatus status, IConnection connection, + int64_t connectionId, fmq_sync mqDesc); +}; diff --git a/media/bufferpool/2.0/IClientManager.hal b/media/bufferpool/2.0/IClientManager.hal new file mode 100644 index 0000000000..9253bda90f --- /dev/null +++ b/media/bufferpool/2.0/IClientManager.hal @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.media.bufferpool@2.0; + +import IAccessor; + +/** + * IClientManager manages IConnection(s) inside a process. A locally + * created IConnection represents a communication node(receiver) with the + * specified buffer pool(IAccessor). + * IConnection(s) are not exposed to other processes(IClientManager). + * IClientManager instance must be unique within a process. + */ +interface IClientManager { + + /** + * Sets up a buffer receiving communication node for the specified + * buffer pool. A manager must create a IConnection to the buffer + * pool if it does not already have a connection. + * + * @param bufferPool a buffer pool which is specified with the IAccessor. + * The specified buffer pool is the owner of received buffers. + * @return status The status of the call. + * OK - A sender was set successfully. + * NO_MEMORY - Memory allocation failure occurred. + * ALREADY_EXISTS - A sender was registered already. + * CRITICAL_ERROR - Other errors. + * @return connectionId the Id of the communication node to the buffer pool. + * This id is used in FMQ to notify IAccessor that a buffer has been + * sent to that connection during transfers. + */ + registerSender(IAccessor bufferPool) generates + (ResultStatus status, int64_t connectionId); +}; diff --git a/media/bufferpool/2.0/IConnection.hal b/media/bufferpool/2.0/IConnection.hal new file mode 100644 index 0000000000..629f83c902 --- /dev/null +++ b/media/bufferpool/2.0/IConnection.hal @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.media.bufferpool@2.0; + +/** + * A connection to a buffer pool which handles requests from a buffer pool + * client. The connection must be made in order to receive buffers from + * other buffer pool clients. + */ +interface IConnection { + + /** + * Retrieves a buffer using bufferId. The method must be called from + * receiving side of buffer during transferring only when the specified + * buffer is neither cached nor used. This fails if the specified + * transaction is not valid. + * + * @param transactionId Unique transaction id for buffer transferring. + * @param bufferId Id of the buffer to be fetched. + * @return status The status of the call. + * OK - A buffer was fetched successfully. + * NO_MEMORY - Memory allocation failure occurred. + * NOT_FOUND - A buffer was not found due to invalidation. + * CRITICAL_ERROR - Other errors. + * @return buffer The actual buffer which is specified with bufferId. + */ + fetch(uint64_t transactionId, uint32_t bufferId) generates + (ResultStatus status, Buffer buffer); +}; diff --git a/media/bufferpool/2.0/README.md b/media/bufferpool/2.0/README.md new file mode 100644 index 0000000000..ed985d8291 --- /dev/null +++ b/media/bufferpool/2.0/README.md @@ -0,0 +1,54 @@ +1. Overview + +A buffer pool enables processes to transfer buffers asynchronously. +Without a buffer pool, a process calls a synchronous method of the other +process and waits until the call finishes transferring a buffer. This adds +unwanted latency due to context switching. With help from a buffer pool, a +process can pass buffers asynchronously and reduce context switching latency. + +Passing an interface and a handle adds extra latency also. To mitigate the +latency, passing IDs with local cache is used. For security concerns about +rogue clients, FMQ is used to communicate between a buffer pool and a client +process. FMQ is used to send buffer ownership change status from a client +process to a buffer pool. Except FMQ, a buffer pool does not use any shared +memory. + +2. FMQ + +FMQ is used to send buffer ownership status changes to a buffer pool from a +buffer pool client. A buffer pool synchronizes FMQ messages when there is a +hidl request from the clients. Every client has its own connection and FMQ +to communicate with the buffer pool. So sending an FMQ message on behalf of +other clients is not possible. + +FMQ messages are sent when a buffer is acquired or released. Also, FMQ messages +are sent when a buffer is transferred from a client to another client. FMQ has +its own ID from a buffer pool. A client is specified with the ID. + +To transfer a buffer, a sender must send an FMQ message. The message must +include a receiver's ID and a transaction ID. A receiver must send the +transaction ID to fetch a buffer from a buffer pool. Since the sender already +registered the receiver via an FMQ message, The buffer pool must verify the +receiver with the transaction ID. In order to prevent faking a receiver, a +connection to a buffer pool from client is made and kept privately. Also part of +transaction ID is a sender ID in order to prevent fake transactions from other +clients. This must be verified with an FMQ message from a buffer pool. + +FMQ messages are defined in BufferStatus and BufferStatusMessage of 'types.hal'. + +3. Interfaces + +IConnection +A connection to a buffer pool from a buffer pool client. The connection +provides the functionalities to share buffers between buffer pool clients. +The connection must be unique for each client. + +IAccessor +An accessor to a buffer pool which makes a connection to the buffer pool. +IAccesssor#connect creates an IConnection. + +IClientManager +A manager of buffer pool clients and clients' connections to buffer pools. It +sets up a process to be a receiver of buffers from a buffer pool. The manager +is unique in a process. + diff --git a/media/bufferpool/2.0/types.hal b/media/bufferpool/2.0/types.hal new file mode 100644 index 0000000000..d5b393778e --- /dev/null +++ b/media/bufferpool/2.0/types.hal @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.media.bufferpool@2.0; + +enum ResultStatus : int32_t { + OK = 0, + + NO_MEMORY = 1, + ALREADY_EXISTS = 2, + NOT_FOUND = 3, + CRITICAL_ERROR = 4, +}; + +/** + * Generic buffer for fast recycling for media/stagefright. + * + * During media pipeline buffer references are created, shared and + * destroyed frequently. The underlying buffers are allocated on demand + * by a buffer pool, and are recycled to the buffer pool when they are + * no longer referenced by the clients. + * + * E.g. ion or gralloc buffer + */ +struct Buffer { + uint32_t id; + handle buffer; +}; + +/** + * Buffer ownership status for the specified client. + * Buffer transfer status for the specified buffer transafer transaction. + * BufferStatus is posted along with BufferStatusMessage from a client to + * the buffer pool for synchronization after status change. + */ +enum BufferStatus : int32_t { + /** No longer used by the specified client. */ + NOT_USED = 0, + /** Buffer is acquired by the specified client. */ + USED = 1, + /** Buffer is sent by the specified client. */ + TRANSFER_TO = 2, + /** Buffer transfer is acked by the receiver client. */ + TRANSFER_FROM = 3, + /** Buffer transfer is timed out by receiver client. */ + TRANSFER_TIMEOUT = 4, + /** Buffer transfer is not acked by the receiver. */ + TRANSFER_LOST = 5, + /** Buffer fetch request from the client. */ + TRANSFER_FETCH = 6, + /** Buffer transaction succeeded. */ + TRANSFER_OK = 7, + /** Buffer transaction failure. */ + TRANSFER_ERROR = 8, +}; + +/** + * Buffer ownership status change message. This message is + * sent via fmq to the buffer pool from client processes. + */ +struct BufferStatusMessage { + /** + * Transaction Id = (SenderId : sender local transaction Id) + * Transaction Id is created from sender and posted via fmq within + * TRANSFER_TO message. + */ + uint64_t transactionId; + uint32_t bufferId; + BufferStatus newStatus; + /** Used by the buffer pool. not by client. */ + int64_t connectionId; + /** Valid only when TRANSFER_TO is posted. */ + int64_t targetConnectionId; + /** + * Used by the buffer pool, not by client. + * Monotonic timestamp in Us since fixed point in time as decided + * by the sender of the message + */ + int64_t timestampUs; +}; From c0ce8b2a10356bb56c05323ec86ff5009d843221 Mon Sep 17 00:00:00 2001 From: Jordan Jozwiak Date: Tue, 17 Jul 2018 15:58:22 -0700 Subject: [PATCH 072/718] Add the HVAC_SEAT_TEMPERATURE property. Bug: b/111564723 Test: Build and install. Change-Id: I37184aff227910a91adcb810078b578764fa56ec (cherry picked from commit 7cc52cdaa6c2d37edbdc87a456a59d2e74591f9d) --- .../2.0/default/impl/vhal_v2_0/DefaultConfig.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) 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 917fbc3f59..1a715b2f4f 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 @@ -46,6 +46,8 @@ constexpr int WHEEL_TICK = (int)VehicleProperty::WHEEL_TICK; constexpr int ALL_WHEELS = (int)(VehicleAreaWheel::LEFT_FRONT | VehicleAreaWheel::RIGHT_FRONT | VehicleAreaWheel::LEFT_REAR | VehicleAreaWheel::RIGHT_REAR); +constexpr int SEAT_1_LEFT = (int)(VehicleAreaSeat::ROW_1_LEFT); +constexpr int SEAT_1_RIGHT = (int)(VehicleAreaSeat::ROW_1_RIGHT); constexpr int HVAC_LEFT = (int)(VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_2_LEFT | VehicleAreaSeat::ROW_2_CENTER); constexpr int HVAC_RIGHT = (int)(VehicleAreaSeat::ROW_1_RIGHT | VehicleAreaSeat::ROW_2_RIGHT); @@ -378,6 +380,17 @@ const ConfigDeclaration kVehicleProperties[]{ .areaId = (0), .minInt32Value = -2, .maxInt32Value = 2}}}, .initialValue = {.int32Values = {0}}}, // +ve values for heating and -ve for cooling + {.config = {.prop = toInt(VehicleProperty::HVAC_SEAT_TEMPERATURE), + .access = VehiclePropertyAccess::READ_WRITE, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + .areaConfigs = {VehicleAreaConfig{ + .areaId = SEAT_1_LEFT, .minInt32Value = -2, .maxInt32Value = 2, + }, + VehicleAreaConfig{ + .areaId = SEAT_1_RIGHT, .minInt32Value = -2, .maxInt32Value = 2, + }}}, + .initialValue = {.int32Values = {0}}}, // +ve values for heating and -ve for cooling + {.config = {.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET), .access = VehiclePropertyAccess::READ_WRITE, .changeMode = VehiclePropertyChangeMode::ON_CHANGE, From 782ef26b4125641166e6d2fe3a5673a200f3b8f1 Mon Sep 17 00:00:00 2001 From: Jordan Jozwiak Date: Thu, 2 Aug 2018 11:35:33 -0700 Subject: [PATCH 073/718] Add missing VHAL properties Bug: b/111500076 Test: Build and install. Change-Id: I32bfd33ce050ab6ffc886e2ba63b99bd5a33ad31 (cherry picked from commit 85df08f4fe94fd6dfedd6d7def5192cf1f7ce2c4) --- .../default/impl/vhal_v2_0/DefaultConfig.h | 149 +++++++++++++++++- 1 file changed, 142 insertions(+), 7 deletions(-) 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 917fbc3f59..f13cf8f773 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 @@ -58,6 +58,14 @@ constexpr int VENDOR_EXTENSION_INT_PROPERTY = (int)(0x103 | VehiclePropertyGroup::VENDOR | VehiclePropertyType::INT32 | VehicleArea::WINDOW); constexpr int VENDOR_EXTENSION_STRING_PROPERTY = (int)(0x104 | VehiclePropertyGroup::VENDOR | VehiclePropertyType::STRING | VehicleArea::GLOBAL); +constexpr int FUEL_DOOR_REAR_LEFT = (int)PortLocationType::REAR_LEFT; +constexpr int CHARGE_PORT_FRONT_LEFT = (int)PortLocationType::FRONT_LEFT; +constexpr int LIGHT_STATE_ON = (int)VehicleLightState::ON; +constexpr int LIGHT_SWITCH_AUTO = (int)VehicleLightSwitch::AUTOMATIC; +constexpr int WHEEL_FRONT_LEFT = (int)VehicleAreaWheel::LEFT_FRONT; +constexpr int WHEEL_FRONT_RIGHT = (int)VehicleAreaWheel::RIGHT_FRONT; +constexpr int WHEEL_REAR_LEFT = (int)VehicleAreaWheel::LEFT_REAR; +constexpr int WHEEL_REAR_RIGHT = (int)VehicleAreaWheel::RIGHT_REAR; /** * This property is used for test purpose to generate fake events. Here is the test package that @@ -149,8 +157,9 @@ const ConfigDeclaration kVehicleProperties[]{ .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY), .access = VehiclePropertyAccess::READ, .changeMode = VehiclePropertyChangeMode::STATIC, + .areaConfigs = {VehicleAreaConfig{.areaId = (0)}}, }, - .initialValue = {.floatValues = {15000}}}, + .initialValue = {.floatValues = {15000.0f}}}, {.config = { @@ -165,8 +174,9 @@ const ConfigDeclaration kVehicleProperties[]{ .prop = toInt(VehicleProperty::INFO_EV_BATTERY_CAPACITY), .access = VehiclePropertyAccess::READ, .changeMode = VehiclePropertyChangeMode::STATIC, + .areaConfigs = {VehicleAreaConfig{.areaId = (0)}}, }, - .initialValue = {.floatValues = {150000}}}, + .initialValue = {.floatValues = {150000.0f}}}, {.config = { @@ -176,6 +186,24 @@ const ConfigDeclaration kVehicleProperties[]{ }, .initialValue = {.int32Values = {1}}}, + {.config = + { + .prop = toInt(VehicleProperty::INFO_FUEL_DOOR_LOCATION), + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::STATIC, + .areaConfigs = {VehicleAreaConfig{.areaId = (0)}}, + }, + .initialValue = {.int32Values = {FUEL_DOOR_REAR_LEFT}}}, + + {.config = + { + .prop = toInt(VehicleProperty::INFO_EV_PORT_LOCATION), + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::STATIC, + .areaConfigs = {VehicleAreaConfig{.areaId = (0)}}, + }, + .initialValue = {.int32Values = {CHARGE_PORT_FRONT_LEFT}}}, + {.config = { .prop = toInt(VehicleProperty::INFO_MAKE), @@ -218,14 +246,16 @@ const ConfigDeclaration kVehicleProperties[]{ .prop = toInt(VehicleProperty::FUEL_LEVEL), .access = VehiclePropertyAccess::READ, .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + .areaConfigs = {VehicleAreaConfig{.areaId = (0)}}, }, - .initialValue = {.floatValues = {15000}}}, + .initialValue = {.floatValues = {15000.0f}}}, {.config = { .prop = toInt(VehicleProperty::FUEL_DOOR_OPEN), - .access = VehiclePropertyAccess::READ, + .access = VehiclePropertyAccess::READ_WRITE, .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + .areaConfigs = {VehicleAreaConfig{.areaId = (0)}}, }, .initialValue = {.int32Values = {0}}}, @@ -234,14 +264,16 @@ const ConfigDeclaration kVehicleProperties[]{ .prop = toInt(VehicleProperty::EV_BATTERY_LEVEL), .access = VehiclePropertyAccess::READ, .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + .areaConfigs = {VehicleAreaConfig{.areaId = (0)}}, }, - .initialValue = {.floatValues = {150000}}}, + .initialValue = {.floatValues = {150000.0f}}}, {.config = { .prop = toInt(VehicleProperty::EV_CHARGE_PORT_OPEN), - .access = VehiclePropertyAccess::READ, + .access = VehiclePropertyAccess::READ_WRITE, .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + .areaConfigs = {VehicleAreaConfig{.areaId = (0)}}, }, .initialValue = {.int32Values = {0}}}, @@ -250,6 +282,7 @@ const ConfigDeclaration kVehicleProperties[]{ .prop = toInt(VehicleProperty::EV_CHARGE_PORT_CONNECTED), .access = VehiclePropertyAccess::READ, .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + .areaConfigs = {VehicleAreaConfig{.areaId = (0)}}, }, .initialValue = {.int32Values = {0}}}, @@ -258,8 +291,37 @@ const ConfigDeclaration kVehicleProperties[]{ .prop = toInt(VehicleProperty::EV_BATTERY_INSTANTANEOUS_CHARGE_RATE), .access = VehiclePropertyAccess::READ, .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + .areaConfigs = {VehicleAreaConfig{.areaId = (0)}}, }, - .initialValue = {.floatValues = {0}}}, + .initialValue = {.floatValues = {0.0f}}}, + + {.config = + { + .prop = toInt(VehicleProperty::RANGE_REMAINING), + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::CONTINUOUS, + .areaConfigs = {VehicleAreaConfig{.areaId = (0)}}, + }, + .initialValue = {.floatValues = {100.0f}}}, // units in meters + + {.config = + {.prop = toInt(VehicleProperty::TIRE_PRESSURE), + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::CONTINUOUS, + .areaConfigs = + {VehicleAreaConfig{ + .areaId = WHEEL_FRONT_LEFT, .minFloatValue = 100.0f, .maxFloatValue = 300.0f, + }, + VehicleAreaConfig{ + .areaId = WHEEL_FRONT_RIGHT, .minFloatValue = 100.0f, .maxFloatValue = 300.0f, + }, + VehicleAreaConfig{ + .areaId = WHEEL_REAR_LEFT, .minFloatValue = 100.0f, .maxFloatValue = 300.0f, + }, + VehicleAreaConfig{ + .areaId = WHEEL_REAR_RIGHT, .minFloatValue = 100.0f, .maxFloatValue = 300.0f, + }}}, + .initialValue = {.floatValues = {200}}}, // units in kPa {.config = { @@ -282,6 +344,7 @@ const ConfigDeclaration kVehicleProperties[]{ .prop = toInt(VehicleProperty::FUEL_LEVEL_LOW), .access = VehiclePropertyAccess::READ, .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + .areaConfigs = {VehicleAreaConfig{.areaId = (0)}}, }, .initialValue = {.int32Values = {0}}}, @@ -540,6 +603,78 @@ const ConfigDeclaration kVehicleProperties[]{ .configArray = {1}}, }, + {.config = + { + .prop = toInt(VehicleProperty::HEADLIGHTS_STATE), + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + .areaConfigs = {VehicleAreaConfig{.areaId = (0)}}, + }, + .initialValue = {.int32Values = {LIGHT_STATE_ON}}}, + + {.config = + { + .prop = toInt(VehicleProperty::HIGH_BEAM_LIGHTS_STATE), + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + .areaConfigs = {VehicleAreaConfig{.areaId = (0)}}, + }, + .initialValue = {.int32Values = {LIGHT_STATE_ON}}}, + + {.config = + { + .prop = toInt(VehicleProperty::FOG_LIGHTS_STATE), + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + .areaConfigs = {VehicleAreaConfig{.areaId = (0)}}, + }, + .initialValue = {.int32Values = {LIGHT_STATE_ON}}}, + + {.config = + { + .prop = toInt(VehicleProperty::HAZARD_LIGHTS_STATE), + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + .areaConfigs = {VehicleAreaConfig{.areaId = (0)}}, + }, + .initialValue = {.int32Values = {LIGHT_STATE_ON}}}, + + {.config = + { + .prop = toInt(VehicleProperty::HEADLIGHTS_SWITCH), + .access = VehiclePropertyAccess::READ_WRITE, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + .areaConfigs = {VehicleAreaConfig{.areaId = (0)}}, + }, + .initialValue = {.int32Values = {LIGHT_SWITCH_AUTO}}}, + + {.config = + { + .prop = toInt(VehicleProperty::HIGH_BEAM_LIGHTS_SWITCH), + .access = VehiclePropertyAccess::READ_WRITE, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + .areaConfigs = {VehicleAreaConfig{.areaId = (0)}}, + }, + .initialValue = {.int32Values = {LIGHT_SWITCH_AUTO}}}, + + {.config = + { + .prop = toInt(VehicleProperty::FOG_LIGHTS_SWITCH), + .access = VehiclePropertyAccess::READ_WRITE, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + .areaConfigs = {VehicleAreaConfig{.areaId = (0)}}, + }, + .initialValue = {.int32Values = {LIGHT_SWITCH_AUTO}}}, + + {.config = + { + .prop = toInt(VehicleProperty::HAZARD_LIGHTS_SWITCH), + .access = VehiclePropertyAccess::READ_WRITE, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + .areaConfigs = {VehicleAreaConfig{.areaId = (0)}}, + }, + .initialValue = {.int32Values = {LIGHT_SWITCH_AUTO}}}, + {.config = {.prop = VEHICLE_MAP_SERVICE, .access = VehiclePropertyAccess::READ_WRITE, .changeMode = VehiclePropertyChangeMode::ON_CHANGE}}, From 2b3f82672a8d2d1ba3b0619cdb2fe2777719c206 Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Fri, 20 Jul 2018 16:03:46 -0700 Subject: [PATCH 074/718] [ConfigStore] Add useColorManagement method. Previously we couple wide color gamut display and color management together, which is because we only do color management when we have wide color gamut display. However, we would also want display that doesn't support wide color gamut but is calibrated and is capable of managing sRGB gamut to have color management. This means we will decouple wide color gamut display from color management, a device can indicate that it's color managed without having wide color gamut display and only manage color within sRGB gamut. BUG: 111505327 Test: BUild, flash and check Natural/Boosted mode. Change-Id: If1241ce040a6f691609d8f8d72a2d6f3141557cf --- CleanSpec.mk | 2 + .../compatibility_matrix.current.xml | 2 +- configstore/1.2/Android.bp | 18 ++++++++ configstore/1.2/ISurfaceFlingerConfigs.hal | 33 +++++++++++++++ configstore/{1.1 => 1.2}/default/Android.mk | 15 +++---- .../default/SurfaceFlingerConfigs.cpp | 20 +++++---- .../default/SurfaceFlingerConfigs.h | 41 +++++++++++++------ ...droid.hardware.configstore@1.2-service.rc} | 2 +- .../seccomp_policy/configstore-arm64.policy} | 0 configstore/{1.1 => 1.2}/default/service.cpp | 18 ++++---- .../{1.1 => 1.2}/default/surfaceflinger.mk | 4 ++ configstore/utils/Android.bp | 2 + 12 files changed, 119 insertions(+), 38 deletions(-) create mode 100644 configstore/1.2/Android.bp create mode 100644 configstore/1.2/ISurfaceFlingerConfigs.hal rename configstore/{1.1 => 1.2}/default/Android.mk (67%) rename configstore/{1.1 => 1.2}/default/SurfaceFlingerConfigs.cpp (90%) rename configstore/{1.1 => 1.2}/default/SurfaceFlingerConfigs.h (58%) rename configstore/{1.1/default/android.hardware.configstore@1.1-service.rc => 1.2/default/android.hardware.configstore@1.2-service.rc} (84%) rename configstore/{1.1/default/seccomp_policy/configstore@1.1-arm64.policy => 1.2/default/seccomp_policy/configstore-arm64.policy} (100%) rename configstore/{1.1 => 1.2}/default/service.cpp (80%) rename configstore/{1.1 => 1.2}/default/surfaceflinger.mk (94%) diff --git a/CleanSpec.mk b/CleanSpec.mk index 531e44ec8e..fcaced0df0 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -66,3 +66,5 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/vndk-sp/android.hardware $(call add-clean-step, find $(PRODUCT_OUT)/system $(PRODUCT_OUT)/vendor -type f -name "android\.hardware\.configstore\@1\.1*" -print0 | xargs -0 rm -f) $(call add-clean-step, find $(PRODUCT_OUT)/system $(PRODUCT_OUT)/vendor -type f -name "android\.hardware\.configstore*" -print0 | xargs -0 rm -f) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/seccomp_policy/configstore@1.0.policy) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/seccomp_policy/configstore@1.1.policy) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/bin/hw/android.hardware.configstore@1.1-service) diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml index 8803cdd8cc..b9cb093213 100644 --- a/compatibility_matrices/compatibility_matrix.current.xml +++ b/compatibility_matrices/compatibility_matrix.current.xml @@ -105,7 +105,7 @@ android.hardware.configstore - 1.1 + 1.2 ISurfaceFlingerConfigs default diff --git a/configstore/1.2/Android.bp b/configstore/1.2/Android.bp new file mode 100644 index 0000000000..a20eb34dd8 --- /dev/null +++ b/configstore/1.2/Android.bp @@ -0,0 +1,18 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +hidl_interface { + name: "android.hardware.configstore@1.2", + root: "android.hardware", + vndk: { + enabled: true, + }, + srcs: [ + "ISurfaceFlingerConfigs.hal", + ], + interfaces: [ + "android.hardware.configstore@1.1", + "android.hardware.configstore@1.0", + "android.hidl.base@1.0", + ], + gen_java: true, +} \ No newline at end of file diff --git a/configstore/1.2/ISurfaceFlingerConfigs.hal b/configstore/1.2/ISurfaceFlingerConfigs.hal new file mode 100644 index 0000000000..c32cc82910 --- /dev/null +++ b/configstore/1.2/ISurfaceFlingerConfigs.hal @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.1 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.hardware.configstore@1.2; + +import @1.1::ISurfaceFlingerConfigs; +import @1.0::OptionalBool; + +/** + * New revision of ISurfaceFlingerConfigs + */ +interface ISurfaceFlingerConfigs extends @1.1::ISurfaceFlingerConfigs { + /** + * useColorManagement indicates whether SurfaceFlinger should manage color + * by switching to appropriate color mode automatically depending on the + * Dataspace of the surfaces on screen. + * This function must return true when hasWideColorDisplay or hasHDRDisplay + * return true. + */ + useColorManagement() generates (OptionalBool value); +}; diff --git a/configstore/1.1/default/Android.mk b/configstore/1.2/default/Android.mk similarity index 67% rename from configstore/1.1/default/Android.mk rename to configstore/1.2/default/Android.mk index 40f621b3ad..b807357876 100644 --- a/configstore/1.1/default/Android.mk +++ b/configstore/1.2/default/Android.mk @@ -2,15 +2,15 @@ LOCAL_PATH := $(call my-dir) ################################################################################ include $(CLEAR_VARS) -LOCAL_MODULE := android.hardware.configstore@1.1-service +LOCAL_MODULE := android.hardware.configstore@1.2-service # seccomp is not required for coverage build. ifneq ($(NATIVE_COVERAGE),true) -LOCAL_REQUIRED_MODULES_arm64 := configstore@1.1.policy +LOCAL_REQUIRED_MODULES_arm64 := configstore.policy endif -LOCAL_PROPRIETARY_MODULE := true +LOCAL_VENDOR_MODULE := true LOCAL_MODULE_CLASS := EXECUTABLES LOCAL_MODULE_RELATIVE_PATH := hw -LOCAL_INIT_RC := android.hardware.configstore@1.1-service.rc +LOCAL_INIT_RC := android.hardware.configstore@1.2-service.rc LOCAL_SRC_FILES:= service.cpp include $(LOCAL_PATH)/surfaceflinger.mk @@ -23,16 +23,17 @@ LOCAL_SHARED_LIBRARIES := \ liblog \ libutils \ android.hardware.configstore@1.0 \ - android.hardware.configstore@1.1 + android.hardware.configstore@1.1 \ + android.hardware.configstore@1.2 include $(BUILD_EXECUTABLE) # seccomp filter for configstore ifeq ($(TARGET_ARCH), $(filter $(TARGET_ARCH), arm64)) include $(CLEAR_VARS) -LOCAL_MODULE := configstore@1.1.policy +LOCAL_MODULE := configstore.policy LOCAL_MODULE_CLASS := ETC LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc/seccomp_policy -LOCAL_SRC_FILES := seccomp_policy/configstore@1.1-$(TARGET_ARCH).policy +LOCAL_SRC_FILES := seccomp_policy/configstore-$(TARGET_ARCH).policy include $(BUILD_PREBUILT) endif diff --git a/configstore/1.1/default/SurfaceFlingerConfigs.cpp b/configstore/1.2/default/SurfaceFlingerConfigs.cpp similarity index 90% rename from configstore/1.1/default/SurfaceFlingerConfigs.cpp rename to configstore/1.2/default/SurfaceFlingerConfigs.cpp index da3081c12f..c7bd567fef 100644 --- a/configstore/1.1/default/SurfaceFlingerConfigs.cpp +++ b/configstore/1.2/default/SurfaceFlingerConfigs.cpp @@ -22,11 +22,10 @@ namespace android { namespace hardware { namespace configstore { -namespace V1_1 { +namespace V1_2 { namespace implementation { -// Methods from ::android::hardware::configstore::V1_0::ISurfaceFlingerConfigs -// follow. +// ::android::hardware::configstore::V1_0::ISurfaceFlingerConfigs implementation. Return SurfaceFlingerConfigs::vsyncEventPhaseOffsetNs(vsyncEventPhaseOffsetNs_cb _hidl_cb) { #ifdef VSYNC_EVENT_PHASE_OFFSET_NS _hidl_cb({true, VSYNC_EVENT_PHASE_OFFSET_NS}); @@ -142,8 +141,7 @@ Return SurfaceFlingerConfigs::startGraphicsAllocatorService( return Void(); } -// Methods from ::android::hardware::configstore::V1_1::ISurfaceFlingerConfigs -// follow. +// ::android::hardware::configstore::V1_1::ISurfaceFlingerConfigs implementation. #ifdef PRIMARY_DISPLAY_ORIENTATION static_assert(PRIMARY_DISPLAY_ORIENTATION == 0 || PRIMARY_DISPLAY_ORIENTATION == 90 || @@ -191,10 +189,18 @@ Return SurfaceFlingerConfigs::primaryDisplayOrientation( return Void(); } -// Methods from ::android::hidl::base::V1_0::IBase follow. +// ::android::hardware::configstore::V1_2::ISurfaceFlingerConfigs implementation. +Return SurfaceFlingerConfigs::useColorManagement(useColorManagement_cb _hidl_cb) { +#if defined(USE_COLOR_MANAGEMENT) || defined(HAS_WIDE_COLOR_DISPLAY) || defined(HAS_HDR_DISPLAY) + _hidl_cb({true, true}); +#else + _hidl_cb({true, false}); +#endif + return Void(); +} } // namespace implementation -} // namespace V1_1 +} // namespace V1_2 } // namespace configstore } // namespace hardware } // namespace android diff --git a/configstore/1.1/default/SurfaceFlingerConfigs.h b/configstore/1.2/default/SurfaceFlingerConfigs.h similarity index 58% rename from configstore/1.1/default/SurfaceFlingerConfigs.h rename to configstore/1.2/default/SurfaceFlingerConfigs.h index 3714e81697..fe787890f0 100644 --- a/configstore/1.1/default/SurfaceFlingerConfigs.h +++ b/configstore/1.2/default/SurfaceFlingerConfigs.h @@ -1,24 +1,39 @@ -#ifndef ANDROID_HARDWARE_CONFIGSTORE_V1_1_SURFACEFLINGERCONFIGS_H -#define ANDROID_HARDWARE_CONFIGSTORE_V1_1_SURFACEFLINGERCONFIGS_H +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.1 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ -#include +#ifndef ANDROID_HARDWARE_CONFIGSTORE_V1_2_SURFACEFLINGERCONFIGS_H +#define ANDROID_HARDWARE_CONFIGSTORE_V1_2_SURFACEFLINGERCONFIGS_H + +#include #include #include namespace android { namespace hardware { namespace configstore { -namespace V1_1 { +namespace V1_2 { namespace implementation { -using ::android::hardware::configstore::V1_1::ISurfaceFlingerConfigs; +using ::android::sp; using ::android::hardware::Return; using ::android::hardware::Void; -using ::android::sp; +using ::android::hardware::configstore::V1_2::ISurfaceFlingerConfigs; struct SurfaceFlingerConfigs : public ISurfaceFlingerConfigs { - // Methods from - // ::android::hardware::configstore::V1_0::ISurfaceFlingerConfigs follow. + // ::android::hardware::configstore::V1_0::ISurfaceFlingerConfigs implementation. Return vsyncEventPhaseOffsetNs(vsyncEventPhaseOffsetNs_cb _hidl_cb) override; Return vsyncSfEventPhaseOffsetNs(vsyncSfEventPhaseOffsetNs_cb _hidl_cb) override; Return useContextPriority(useContextPriority_cb _hidl_cb) override; @@ -32,17 +47,17 @@ struct SurfaceFlingerConfigs : public ISurfaceFlingerConfigs { Return maxFrameBufferAcquiredBuffers(maxFrameBufferAcquiredBuffers_cb _hidl_cb) override; Return startGraphicsAllocatorService(startGraphicsAllocatorService_cb _hidl_cb) override; - // Methods from - // ::android::hardware::configstore::V1_1::ISurfaceFlingerConfigs follow. + // ::android::hardware::configstore::V1_1::ISurfaceFlingerConfigs follow implementation. Return primaryDisplayOrientation(primaryDisplayOrientation_cb _hidl_cb) override; - // Methods from ::android::hidl::base::V1_0::IBase follow. + // ::android::hardware::configstore::V1_2::ISurfaceFlingerConfigs follow implementation. + Return useColorManagement(useColorManagement_cb _hidl_cb) override; }; } // namespace implementation -} // namespace V1_1 +} // namespace V1_2 } // namespace configstore } // namespace hardware } // namespace android -#endif // ANDROID_HARDWARE_CONFIGSTORE_V1_1_SURFACEFLINGERCONFIGS_H +#endif // ANDROID_HARDWARE_CONFIGSTORE_V1_2_SURFACEFLINGERCONFIGS_H diff --git a/configstore/1.1/default/android.hardware.configstore@1.1-service.rc b/configstore/1.2/default/android.hardware.configstore@1.2-service.rc similarity index 84% rename from configstore/1.1/default/android.hardware.configstore@1.1-service.rc rename to configstore/1.2/default/android.hardware.configstore@1.2-service.rc index 105678acb2..d6c5d10a71 100644 --- a/configstore/1.1/default/android.hardware.configstore@1.1-service.rc +++ b/configstore/1.2/default/android.hardware.configstore@1.2-service.rc @@ -1,4 +1,4 @@ -service vendor.configstore-hal /vendor/bin/hw/android.hardware.configstore@1.1-service +service vendor.configstore-hal /vendor/bin/hw/android.hardware.configstore@1.2-service class hal animation user system group system diff --git a/configstore/1.1/default/seccomp_policy/configstore@1.1-arm64.policy b/configstore/1.2/default/seccomp_policy/configstore-arm64.policy similarity index 100% rename from configstore/1.1/default/seccomp_policy/configstore@1.1-arm64.policy rename to configstore/1.2/default/seccomp_policy/configstore-arm64.policy diff --git a/configstore/1.1/default/service.cpp b/configstore/1.2/default/service.cpp similarity index 80% rename from configstore/1.1/default/service.cpp rename to configstore/1.2/default/service.cpp index 3b4e7745ee..65a42f5955 100644 --- a/configstore/1.1/default/service.cpp +++ b/configstore/1.2/default/service.cpp @@ -14,27 +14,27 @@ * limitations under the License. */ -#define LOG_TAG "android.hardware.configstore@1.1-service" +#define LOG_TAG "android.hardware.configstore@1.2-service" -#include +#include #include #include #include "SurfaceFlingerConfigs.h" -using android::hardware::configureRpcThreadpool; -using android::hardware::joinRpcThreadpool; -using android::hardware::configstore::V1_1::ISurfaceFlingerConfigs; -using android::hardware::configstore::V1_1::implementation::SurfaceFlingerConfigs; -using android::hardware::SetupMinijail; +using android::OK; using android::sp; using android::status_t; -using android::OK; +using android::hardware::configureRpcThreadpool; +using android::hardware::joinRpcThreadpool; +using android::hardware::SetupMinijail; +using android::hardware::configstore::V1_2::ISurfaceFlingerConfigs; +using android::hardware::configstore::V1_2::implementation::SurfaceFlingerConfigs; int main() { configureRpcThreadpool(10, true); - SetupMinijail("/vendor/etc/seccomp_policy/configstore@1.1.policy"); + SetupMinijail("/vendor/etc/seccomp_policy/configstore.policy"); sp surfaceFlingerConfigs = new SurfaceFlingerConfigs; status_t status = surfaceFlingerConfigs->registerAsService(); diff --git a/configstore/1.1/default/surfaceflinger.mk b/configstore/1.2/default/surfaceflinger.mk similarity index 94% rename from configstore/1.1/default/surfaceflinger.mk rename to configstore/1.2/default/surfaceflinger.mk index 35922ebb09..70be4501e1 100644 --- a/configstore/1.1/default/surfaceflinger.mk +++ b/configstore/1.2/default/surfaceflinger.mk @@ -54,3 +54,7 @@ endif ifneq ($(SF_PRIMARY_DISPLAY_ORIENTATION),) LOCAL_CFLAGS += -DPRIMARY_DISPLAY_ORIENTATION=$(SF_PRIMARY_DISPLAY_ORIENTATION) endif + +ifeq ($(TARGET_USE_COLOR_MANAGEMENT),true) + LOCAL_CFLAGS += -DUSE_COLOR_MANAGEMENT +endif diff --git a/configstore/utils/Android.bp b/configstore/utils/Android.bp index 178f245fd6..e0d4aa8192 100644 --- a/configstore/utils/Android.bp +++ b/configstore/utils/Android.bp @@ -30,12 +30,14 @@ cc_library_shared { shared_libs: [ "android.hardware.configstore@1.0", "android.hardware.configstore@1.1", + "android.hardware.configstore@1.2", "libbase", "libhidlbase" ], export_shared_lib_headers: [ "android.hardware.configstore@1.0", "android.hardware.configstore@1.1", + "android.hardware.configstore@1.2", "libbase", "libhidlbase" ], From a8e73abffe72b8a680f39f83b126cd88fd7362a2 Mon Sep 17 00:00:00 2001 From: Jordan Jozwiak Date: Wed, 18 Jul 2018 15:07:10 -0700 Subject: [PATCH 075/718] Add the HVAC_SEAT_VENTILATION property. Bug: b/111610946 Test: Build and install. Exempt-From-Owner-Approval: Add property for HVAC_SEAT_VENTILATION following existing pattern Change-Id: I71c23d01c35d9db76eb8d4845e6bb9ce4257defb (cherry picked from commit 2158eccd4bd139a29f14a041c6de60831a2405a7) --- .../2.0/default/impl/vhal_v2_0/DefaultConfig.h | 11 +++++++++++ 1 file changed, 11 insertions(+) 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 1c9a627a1b..3a0376ba68 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 @@ -436,6 +436,17 @@ const ConfigDeclaration kVehicleProperties[]{ .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}}, .initialValue = {.int32Values = {toInt(VehicleHvacFanDirection::FACE)}}}, + {.config = {.prop = toInt(VehicleProperty::HVAC_SEAT_VENTILATION), + .access = VehiclePropertyAccess::READ_WRITE, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + .areaConfigs = {VehicleAreaConfig{ + .areaId = SEAT_1_LEFT, .minInt32Value = 0, .maxInt32Value = 3, + }, + VehicleAreaConfig{ + .areaId = SEAT_1_RIGHT, .minInt32Value = 0, .maxInt32Value = 3, + }}}, + .initialValue = {.int32Values = {0}}}, // 0 is off and +ve values indicate ventilation level. + {.config = {.prop = toInt(VehicleProperty::HVAC_STEERING_WHEEL_HEAT), .access = VehiclePropertyAccess::READ_WRITE, .changeMode = VehiclePropertyChangeMode::ON_CHANGE, From c6dd60133c6d34c10a00d5c801e73c78dfd19975 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Fri, 17 Aug 2018 08:32:07 -0700 Subject: [PATCH 076/718] hostapd(interface): Add asynchronous failure callback Adding a callback object to indicate asynchronous events back to framework. Only a failure indication method is added currently. Also, Uprev the hostapd interface to 1.1. Bug: 112705137 Test: Compiles Change-Id: Ib885001e68734caa5ff192721f618010c125e4b7 --- .../compatibility_matrix.3.xml | 2 +- wifi/hostapd/1.1/Android.bp | 20 +++++++++ wifi/hostapd/1.1/IHostapd.hal | 45 +++++++++++++++++++ wifi/hostapd/1.1/IHostapdCallback.hal | 30 +++++++++++++ 4 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 wifi/hostapd/1.1/Android.bp create mode 100644 wifi/hostapd/1.1/IHostapd.hal create mode 100644 wifi/hostapd/1.1/IHostapdCallback.hal diff --git a/compatibility_matrices/compatibility_matrix.3.xml b/compatibility_matrices/compatibility_matrix.3.xml index e13d293b75..fc7bad62de 100644 --- a/compatibility_matrices/compatibility_matrix.3.xml +++ b/compatibility_matrices/compatibility_matrix.3.xml @@ -445,7 +445,7 @@ android.hardware.wifi.hostapd - 1.0 + 1.0-1 IHostapd default diff --git a/wifi/hostapd/1.1/Android.bp b/wifi/hostapd/1.1/Android.bp new file mode 100644 index 0000000000..d4170b678a --- /dev/null +++ b/wifi/hostapd/1.1/Android.bp @@ -0,0 +1,20 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +hidl_interface { + name: "android.hardware.wifi.hostapd@1.1", + root: "android.hardware", + vndk: { + enabled: true, + }, + srcs: [ + "IHostapd.hal", + "IHostapdCallback.hal", + ], + interfaces: [ + "android.hardware.wifi.hostapd@1.0", + "android.hardware.wifi.supplicant@1.0", + "android.hidl.base@1.0", + ], + gen_java: true, +} + diff --git a/wifi/hostapd/1.1/IHostapd.hal b/wifi/hostapd/1.1/IHostapd.hal new file mode 100644 index 0000000000..4e59ffc1c6 --- /dev/null +++ b/wifi/hostapd/1.1/IHostapd.hal @@ -0,0 +1,45 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.wifi.hostapd@1.1; + +import @1.0::IHostapd; +import @1.0::HostapdStatus; + +import IHostapdCallback; + +/** + * Top-level object for managing SoftAPs. + */ +interface IHostapd extends @1.0::IHostapd { + /** + * Register for callbacks from the hostapd service. + * + * These callbacks are invoked for global events that are not specific + * to any interface or network. Registration of multiple callback + * objects is supported. These objects must be deleted when the corresponding + * client process is dead. + * + * @param callback An instance of the |IHostapdCallback| HIDL interface + * object. + * @return status Status of the operation. + * Possible status codes: + * |HostapdStatusCode.SUCCESS|, + * |HostapdStatusCode.FAILURE_UNKNOWN| + */ + registerCallback(IHostapdCallback callback) + generates (HostapdStatus status); +}; diff --git a/wifi/hostapd/1.1/IHostapdCallback.hal b/wifi/hostapd/1.1/IHostapdCallback.hal new file mode 100644 index 0000000000..1d314fe91e --- /dev/null +++ b/wifi/hostapd/1.1/IHostapdCallback.hal @@ -0,0 +1,30 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.wifi.hostapd@1.1; + +/** + * Top-level object for managing SoftAPs. + */ +interface IHostapdCallback { + /** + * Invoked when an asynchronous failure is encountered in one of the access + * points added via |IHostapd.addAccessPoint|. + * + * @param ifaceName Name of the interface. + */ + oneway onFailure(string ifaceName); +}; From 61a7bbcb77d9f0de248b0cb51e2e50d40a0fe4c6 Mon Sep 17 00:00:00 2001 From: Gregory Clark Date: Fri, 20 Jul 2018 16:02:06 -0700 Subject: [PATCH 077/718] Add the HVAC_FAN_DIRECTION_AVAILABLE property. Bug: b/111371726 Test: Build and flash. Change-Id: I586e607e313792dae689b82f411db94bf22982aa (cherry picked from commit a5b4872c616c8f9fa983fad8ed8ef77e1edef618) --- .../vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h | 9 +++++++++ 1 file changed, 9 insertions(+) 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 3a0376ba68..74bbfb44bf 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 @@ -36,6 +36,8 @@ constexpr int DOOR_1_LEFT = (int)VehicleAreaDoor::ROW_1_LEFT; constexpr int DOOR_1_RIGHT = (int)VehicleAreaDoor::ROW_1_RIGHT; constexpr int DOOR_2_LEFT = (int)VehicleAreaDoor::ROW_2_LEFT; constexpr int DOOR_2_RIGHT = (int)VehicleAreaDoor::ROW_2_RIGHT; +constexpr int FAN_DIRECTION_FACE = (int)VehicleHvacFanDirection::FACE; +constexpr int FAN_DIRECTION_FLOOR = (int)VehicleHvacFanDirection::FLOOR; constexpr int OBD2_LIVE_FRAME = (int)VehicleProperty::OBD2_LIVE_FRAME; constexpr int OBD2_FREEZE_FRAME = (int)VehicleProperty::OBD2_FREEZE_FRAME; constexpr int OBD2_FREEZE_FRAME_INFO = (int)VehicleProperty::OBD2_FREEZE_FRAME_INFO; @@ -436,6 +438,13 @@ const ConfigDeclaration kVehicleProperties[]{ .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}}, .initialValue = {.int32Values = {toInt(VehicleHvacFanDirection::FACE)}}}, + {.config = {.prop = toInt(VehicleProperty::HVAC_FAN_DIRECTION_AVAILABLE), + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::STATIC, + .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}}, + .initialValue = {.int32Values = {FAN_DIRECTION_FACE, FAN_DIRECTION_FLOOR, + FAN_DIRECTION_FACE | FAN_DIRECTION_FLOOR}}}, + {.config = {.prop = toInt(VehicleProperty::HVAC_SEAT_VENTILATION), .access = VehiclePropertyAccess::READ_WRITE, .changeMode = VehiclePropertyChangeMode::ON_CHANGE, From defbad198a6ee1a17161bc7512687637ba2a53c2 Mon Sep 17 00:00:00 2001 From: Valerie Hau Date: Mon, 13 Aug 2018 10:18:54 -0700 Subject: [PATCH 078/718] Adding more unit tests for hwc VTS Bug: 111563608 Test: ./VtsHalGraphicsComposerV2_1TargetTest Change-Id: I41a815c3716db9059572a2dbbbc36a90b7e08289 --- .../VtsHalGraphicsComposerV2_1TargetTest.cpp | 317 ++++++++++++++++++ 1 file changed, 317 insertions(+) diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp index 72f3f1b4bf..0607d4d81f 100644 --- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp +++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp @@ -85,6 +85,13 @@ class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase { // explicitly disable vsync mComposerClient->setVsyncEnabled(mPrimaryDisplay, false); mComposerCallback->setVsyncAllowed(false); + + mInvalidDisplayId = GetInvalidDisplayId(); + + // Although 0 could be an invalid display, a return value of 0 + // from GetInvalidDisplayId means all other ids are in use, a condition which + // we are assuming a device will never have + ASSERT_NE(0, mInvalidDisplayId); } void TearDown() override { @@ -95,6 +102,23 @@ class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase { } } + // returns an invalid display id (one that has not been registered to a + // display. Currently assuming that a device will never have close to + // std::numeric_limit::max() displays registered while running tests + Display GetInvalidDisplayId() { + std::vector validDisplays = mComposerCallback->getDisplays(); + + uint64_t id = std::numeric_limits::max(); + while (id > 0) { + if (std::find(validDisplays.begin(), validDisplays.end(), id) == validDisplays.end()) { + return id; + } + id--; + } + + return 0; + } + // use the slot count usually set by SF static constexpr uint32_t kBufferSlotCount = 64; @@ -103,6 +127,7 @@ class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase { sp mComposerCallback; // the first display and is assumed never to be removed Display mPrimaryDisplay; + Display mInvalidDisplayId; private: Display waitForFirstDisplay() { @@ -171,6 +196,22 @@ TEST_F(GraphicsComposerHidlTest, CreateVirtualDisplay) { mComposerClient->destroyVirtualDisplay(display); } +/** + * Test IComposerClient::destroyVirtualDisplay + * + * Test that passing a bad display handle to destroyVirtualDisplay + * returns a BAD_DISPLAY error + */ +TEST_F(GraphicsComposerHidlTest, DestroyVirtualDisplayBadDisplay) { + if (mComposerClient->getMaxVirtualDisplayCount() == 0) { + GTEST_SUCCEED() << "no virtual display support"; + return; + } + + Error error = mComposerClient->getRaw()->destroyVirtualDisplay(mInvalidDisplayId); + ASSERT_EQ(Error::BAD_DISPLAY, error); +} + /** * Test IComposerClient::createLayer and IComposerClient::destroyLayer. * @@ -184,6 +225,89 @@ TEST_F(GraphicsComposerHidlTest, CreateLayer) { mComposerClient->destroyLayer(mPrimaryDisplay, layer); } +/** + * Test IComposerClient::createLayer + * + * Test that passing in an invalid display handle to createLayer returns + * BAD_DISPLAY. + */ +TEST_F(GraphicsComposerHidlTest, CreateLayerBadDisplay) { + Error error; + mComposerClient->getRaw()->createLayer( + mInvalidDisplayId, kBufferSlotCount, + [&](const auto& tmpOutError, const auto&) { error = tmpOutError; }); + ASSERT_EQ(Error::BAD_DISPLAY, error); +} + +/** + * Test IComposerClient::destroyLayer + * + * Test that passing in an invalid display handle to destroyLayer returns + * BAD_DISPLAY + */ +TEST_F(GraphicsComposerHidlTest, DestroyLayerBadDisplay) { + Error error; + Layer layer; + ASSERT_NO_FATAL_FAILURE(layer = + mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); + + error = mComposerClient->getRaw()->destroyLayer(mInvalidDisplayId, layer); + + EXPECT_EQ(Error::BAD_DISPLAY, error); + + ASSERT_NO_FATAL_FAILURE(mComposerClient->destroyLayer(mPrimaryDisplay, layer)); +} + +/** + * Test IComposerClient::destroyLayer + * + * Test that passing in an invalid layer handle to destroyLayer returns + * BAD_LAYER + */ +TEST_F(GraphicsComposerHidlTest, DestroyLayerBadLayerError) { + // We haven't created any layers yet, so any id should be invalid + Error error = mComposerClient->getRaw()->destroyLayer(mPrimaryDisplay, 1); + + EXPECT_EQ(Error::BAD_LAYER, error); +} + +/** + * Test IComposerClient::getActiveConfig + * + * Test that passing in a bad display handle to getActiveConfig generates a + * BAD_DISPLAY error + */ +TEST_F(GraphicsComposerHidlTest, GetActiveConfigBadDisplay) { + Error error; + mComposerClient->getRaw()->getActiveConfig( + mInvalidDisplayId, [&](const auto& tmpOutError, const auto&) { error = tmpOutError; }); + ASSERT_EQ(Error::BAD_DISPLAY, error); +} + +/** + * Test IComposerClient::getDisplayConfigs + * + * Test IComposerClient::getDisplayConfigs returns no error + * when passed in a valid display + */ +TEST_F(GraphicsComposerHidlTest, GetDisplayConfig) { + std::vector configs; + ASSERT_NO_FATAL_FAILURE(configs = mComposerClient->getDisplayConfigs(mPrimaryDisplay)); +} + +/** + * Test IComposerClient::getDisplayConfigs + * + * Test IComposerClient::getDisplayConfigs returns BAD_DISPLAY + * when passed in an invalid display handle + */ +TEST_F(GraphicsComposerHidlTest, GetDisplayConfigBadDisplay) { + Error error; + mComposerClient->getRaw()->getDisplayConfigs( + mInvalidDisplayId, [&](const auto& tmpOutError, const auto&) { error = tmpOutError; }); + ASSERT_EQ(Error::BAD_DISPLAY, error); +} + /** * Test IComposerClient::getDisplayName. */ @@ -225,6 +349,30 @@ TEST_F(GraphicsComposerHidlTest, GetClientTargetSupport) { } } +/** + * Test IComposerClient::getClientTargetSupport + * + * Test that IComposerClient::getClientTargetSupport returns BAD_DISPLAY when + * passed an invalid display handle + */ +TEST_F(GraphicsComposerHidlTest, GetClientTargetSupportBadDisplay) { + std::vector configs = mComposerClient->getDisplayConfigs(mPrimaryDisplay); + for (auto config : configs) { + int32_t width = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config, + IComposerClient::Attribute::WIDTH); + int32_t height = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config, + IComposerClient::Attribute::HEIGHT); + ASSERT_LT(0, width); + ASSERT_LT(0, height); + + mComposerClient->setActiveConfig(mPrimaryDisplay, config); + + Error error = mComposerClient->getRaw()->getClientTargetSupport( + mInvalidDisplayId, width, height, PixelFormat::RGBA_8888, Dataspace::UNKNOWN); + EXPECT_EQ(Error::BAD_DISPLAY, error); + } +} + /** * Test IComposerClient::getDisplayAttribute. * @@ -286,6 +434,43 @@ TEST_F(GraphicsComposerHidlTest, SetActiveConfig) { } } +/** + * Test IComposerClient::setActiveConfig + * + * Test that config set during IComposerClient::setActiveConfig is maintained + * during a display on/off power cycle + */ +TEST_F(GraphicsComposerHidlTest, SetActiveConfigPowerCycle) { + ASSERT_NO_FATAL_FAILURE( + mComposerClient->setPowerMode(mPrimaryDisplay, IComposerClient::PowerMode::OFF)); + ASSERT_NO_FATAL_FAILURE( + mComposerClient->setPowerMode(mPrimaryDisplay, IComposerClient::PowerMode::ON)); + + std::vector configs = mComposerClient->getDisplayConfigs(mPrimaryDisplay); + for (auto config : configs) { + mComposerClient->setActiveConfig(mPrimaryDisplay, config); + ASSERT_EQ(config, mComposerClient->getActiveConfig(mPrimaryDisplay)); + + ASSERT_NO_FATAL_FAILURE( + mComposerClient->setPowerMode(mPrimaryDisplay, IComposerClient::PowerMode::OFF)); + ASSERT_NO_FATAL_FAILURE( + mComposerClient->setPowerMode(mPrimaryDisplay, IComposerClient::PowerMode::ON)); + ASSERT_EQ(config, mComposerClient->getActiveConfig(mPrimaryDisplay)); + } +} + +/** + * Test IComposerClient::getColorMode + * + * Test that IComposerClient::getColorMode always returns ColorMode::NATIVE + */ +TEST_F(GraphicsComposerHidlTest, GetColorModes) { + std::vector modes = mComposerClient->getColorModes(mPrimaryDisplay); + auto nativeModeLocation = std::find(modes.begin(), modes.end(), ColorMode::NATIVE); + + ASSERT_NE(modes.end(), nativeModeLocation); +} + /** * Test IComposerClient::setColorMode. * @@ -305,6 +490,45 @@ TEST_F(GraphicsComposerHidlTest, SetColorMode) { } } +/** + * Test IComposerClient::setColorMode + * + * Test that IComposerClient::setColorMode returns BAD_DISPLAY for + * an invalid display handle + */ +TEST_F(GraphicsComposerHidlTest, SetColorModeBadDisplay) { + std::vector modes = mComposerClient->getColorModes(mPrimaryDisplay); + for (auto mode : modes) { + Error error = mComposerClient->getRaw()->setColorMode(mInvalidDisplayId, mode); + EXPECT_EQ(Error::BAD_DISPLAY, error); + } +} + +/** + * Test IComposerClient::setColorMode + * + * Test that IComposerClient::setColorMode returns BAD_PARAMETER when passed in + * an invalid color mode + */ +TEST_F(GraphicsComposerHidlTest, SetColorModeBadParameter) { + Error error = + mComposerClient->getRaw()->setColorMode(mPrimaryDisplay, static_cast(-1)); + ASSERT_EQ(Error::BAD_PARAMETER, error); +} + +/** + * Test IComposerClient::getDozeSupport + * + * Test that IComposerClient::getDozeSupport returns + * BAD_DISPLAY when passed an invalid display handle + */ +TEST_F(GraphicsComposerHidlTest, GetDozeSupportBadDisplay) { + Error error; + mComposerClient->getRaw()->getDozeSupport( + mInvalidDisplayId, [&](const auto& tmpOutError, const auto&) { error = tmpOutError; }); + ASSERT_EQ(Error::BAD_DISPLAY, error); +} + /** * Test IComposerClient::setPowerMode. * @@ -327,6 +551,99 @@ TEST_F(GraphicsComposerHidlTest, SetPowerMode) { } } +/** + * Test IComposerClient::setPowerMode + * + * Test IComposerClient::setPowerMode succeeds with different + * orderings of power modes + */ +TEST_F(GraphicsComposerHidlTest, SetPowerModeVariations) { + std::vector modes; + modes.push_back(IComposerClient::PowerMode::OFF); + modes.push_back(IComposerClient::PowerMode::ON); + modes.push_back(IComposerClient::PowerMode::OFF); + for (auto mode : modes) { + ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode(mPrimaryDisplay, mode)); + } + + modes.clear(); + + modes.push_back(IComposerClient::PowerMode::OFF); + modes.push_back(IComposerClient::PowerMode::OFF); + for (auto mode : modes) { + ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode(mPrimaryDisplay, mode)); + } + + modes.clear(); + + modes.push_back(IComposerClient::PowerMode::ON); + modes.push_back(IComposerClient::PowerMode::ON); + for (auto mode : modes) { + ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode(mPrimaryDisplay, mode)); + } + + modes.clear(); + if (mComposerClient->getDozeSupport(mPrimaryDisplay)) { + modes.push_back(IComposerClient::PowerMode::DOZE); + modes.push_back(IComposerClient::PowerMode::DOZE); + + for (auto mode : modes) { + ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode(mPrimaryDisplay, mode)); + } + + modes.clear(); + + modes.push_back(IComposerClient::PowerMode::DOZE_SUSPEND); + modes.push_back(IComposerClient::PowerMode::DOZE_SUSPEND); + + for (auto mode : modes) { + ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode(mPrimaryDisplay, mode)); + } + } +} + +/** + * Test IComposerClient::setPowerMode + * + * Test IComposerClient::setPowerMode returns BAD_DISPLAY when passed an invalid + * display handle + */ +TEST_F(GraphicsComposerHidlTest, SetPowerModeBadDisplay) { + Error error = + mComposerClient->getRaw()->setPowerMode(mInvalidDisplayId, IComposerClient::PowerMode::ON); + ASSERT_EQ(Error::BAD_DISPLAY, error); +} + +/** + * Test IComposerClient::setPowerMode + * + * Test that IComposerClient::setPowerMode returns UNSUPPORTED when passed DOZE + * or DOZE_SUSPEND on devices that do not support DOZE/DOZE_SUSPEND + */ +TEST_F(GraphicsComposerHidlTest, SetPowerModeUnsupported) { + if (!mComposerClient->getDozeSupport(mPrimaryDisplay)) { + Error error = mComposerClient->getRaw()->setPowerMode(mPrimaryDisplay, + IComposerClient::PowerMode::DOZE); + EXPECT_EQ(Error::UNSUPPORTED, error); + + error = mComposerClient->getRaw()->setPowerMode(mPrimaryDisplay, + IComposerClient::PowerMode::DOZE_SUSPEND); + EXPECT_EQ(Error::UNSUPPORTED, error); + } +} + +/** + * Test IComposerClient::setPowerMode + * + * Tests that IComposerClient::setPowerMode returns BAD_PARAMETER when passed an invalid + * PowerMode + */ +TEST_F(GraphicsComposerHidlTest, SetPowerModeBadParameter) { + Error error = mComposerClient->getRaw()->setPowerMode( + mPrimaryDisplay, static_cast(-1)); + ASSERT_EQ(Error::BAD_PARAMETER, error); +} + /** * Test IComposerClient::setVsyncEnabled. * From 4569ca2f886310112e6e696062da373e8474bc3a Mon Sep 17 00:00:00 2001 From: Steve Paik Date: Mon, 20 Aug 2018 18:30:12 -0700 Subject: [PATCH 079/718] Add detail to FUEL_LEVEL_LOW to include all energy types Bug: 109700633 Bug: 109740025 Test: Comment change only Change-Id: Ief87c4a82d965187f0d8f00fd226e4d539c58643 (cherry picked from commit 9108bc896655541d087dc3a457e8429f45b9d8eb) --- automotive/vehicle/2.0/types.hal | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal index 48b2ec28ea..7fe8377b5a 100644 --- a/automotive/vehicle/2.0/types.hal +++ b/automotive/vehicle/2.0/types.hal @@ -603,7 +603,13 @@ enum VehicleProperty : int32_t { * * This property corresponds to the low fuel warning on the dashboard. * Once FUEL_LEVEL_LOW is set, it should not be cleared until more fuel is - * added to the vehicle. + * added to the vehicle. This property may take into account all fuel + * sources for a vehicle - for example: + * + * For a gas powered vehicle, this property is based soley on gas level. + * For a battery powered vehicle, this property is based solely on battery level. + * For a hybrid vehicle, this property may be based on the combination of gas and battery + * levels, at the OEM's discretion. * * @change_mode VehiclePropertyChangeMode:ON_CHANGE * @access VehiclePropertyAccess:READ From c64f5f53af1850b2ec53864e5d7090bd13789991 Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Wed, 11 Jul 2018 15:43:59 -0700 Subject: [PATCH 080/718] [Graphics] Only validate display in PresentOrValidateDisplay. Previously we require display to be validated in onRefresh, however, onRefresh can be called while validateDisplay is executing, results in next presentDisplay being skipped. This patch makes sure we don't check validation state when presentDisplay is called. BUG: 80063800 Test: build, flash, boot and play Youtube videos. Change-Id: I3d8686db3274436afb6605812641768296f1af0e --- .../include/composer-hal/2.1/ComposerClient.h | 1 + .../composer-hal/2.1/ComposerCommandEngine.h | 6 ++++- .../composer-hal/2.1/ComposerResources.h | 25 ++++++++++++++++++- .../include/composer-passthrough/2.1/HwcHal.h | 9 ------- 4 files changed, 30 insertions(+), 11 deletions(-) diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h index 86525b87ce..095189f91b 100644 --- a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h +++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h @@ -102,6 +102,7 @@ class ComposerClientImpl : public Interface { } void onRefresh(Display display) { + mResources->setDisplayMustValidateState(display, true); auto ret = mCallback->onRefresh(display); ALOGE_IF(!ret.isOk(), "failed to send onRefresh: %s", ret.description().c_str()); } diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h index 36aa64ef05..d87110a014 100644 --- a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h +++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h @@ -258,6 +258,7 @@ class ComposerCommandEngine : protected CommandReaderBase { auto err = mHal->validateDisplay(mCurrentDisplay, &changedLayers, &compositionTypes, &displayRequestMask, &requestedLayers, &requestMasks); + mResources->setDisplayMustValidateState(mCurrentDisplay, false); if (err == Error::NONE) { mWriter.setChangedCompositionTypes(changedLayers, compositionTypes); mWriter.setDisplayRequests(displayRequestMask, requestedLayers, requestMasks); @@ -278,7 +279,9 @@ class ComposerCommandEngine : protected CommandReaderBase { int presentFence = -1; std::vector layers; std::vector fences; - auto err = mHal->presentDisplay(mCurrentDisplay, &presentFence, &layers, &fences); + auto err = mResources->mustValidateDisplay(mCurrentDisplay) + ? Error::NOT_VALIDATED + : mHal->presentDisplay(mCurrentDisplay, &presentFence, &layers, &fences); if (err == Error::NONE) { mWriter.setPresentOrValidateResult(1); mWriter.setPresentFence(presentFence); @@ -296,6 +299,7 @@ class ComposerCommandEngine : protected CommandReaderBase { auto err = mHal->validateDisplay(mCurrentDisplay, &changedLayers, &compositionTypes, &displayRequestMask, &requestedLayers, &requestMasks); + mResources->setDisplayMustValidateState(mCurrentDisplay, false); if (err == Error::NONE) { mWriter.setPresentOrValidateResult(0); mWriter.setChangedCompositionTypes(changedLayers, compositionTypes); diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h index 7bb369296c..2cbf044604 100644 --- a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h +++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h @@ -216,7 +216,8 @@ class ComposerDisplayResource { : mType(type), mClientTargetCache(importer), mOutputBufferCache(importer, ComposerHandleCache::HandleType::BUFFER, - outputBufferCacheSize) {} + outputBufferCacheSize), + mMustValidate(true) {} bool initClientTargetCache(uint32_t cacheSize) { return mClientTargetCache.initCache(ComposerHandleCache::HandleType::BUFFER, cacheSize); @@ -263,10 +264,15 @@ class ComposerDisplayResource { return layers; } + void setMustValidateState(bool mustValidate) { mMustValidate = mustValidate; } + + bool mustValidate() const { return mMustValidate; } + protected: const DisplayType mType; ComposerHandleCache mClientTargetCache; ComposerHandleCache mOutputBufferCache; + bool mMustValidate; std::unordered_map> mLayerResources; }; @@ -389,6 +395,23 @@ class ComposerResources { outStreamHandle, outReplacedStream); } + void setDisplayMustValidateState(Display display, bool mustValidate) { + std::lock_guard lock(mDisplayResourcesMutex); + auto* displayResource = findDisplayResourceLocked(display); + if (displayResource) { + displayResource->setMustValidateState(mustValidate); + } + } + + bool mustValidateDisplay(Display display) { + std::lock_guard lock(mDisplayResourcesMutex); + auto* displayResource = findDisplayResourceLocked(display); + if (displayResource) { + return displayResource->mustValidate(); + } + return false; + } + protected: virtual std::unique_ptr createDisplayResource( ComposerDisplayResource::DisplayType type, uint32_t outputBufferCacheSize) { diff --git a/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h b/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h index 964e75bdc5..436e4612bb 100644 --- a/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h +++ b/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h @@ -111,7 +111,6 @@ class HwcHalImpl : public Hal { } void registerEventCallback(hal::ComposerHal::EventCallback* callback) override { - mMustValidateDisplay = true; mEventCallback = callback; mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this, @@ -331,7 +330,6 @@ class HwcHalImpl : public Hal { uint32_t typesCount = 0; uint32_t reqsCount = 0; int32_t err = mDispatch.validateDisplay(mDevice, display, &typesCount, &reqsCount); - mMustValidateDisplay = false; if (err != HWC2_ERROR_NONE && err != HWC2_ERROR_HAS_CHANGES) { return static_cast(err); @@ -384,10 +382,6 @@ class HwcHalImpl : public Hal { Error presentDisplay(Display display, int32_t* outPresentFence, std::vector* outLayers, std::vector* outReleaseFences) override { - if (mMustValidateDisplay) { - return Error::NOT_VALIDATED; - } - *outPresentFence = -1; int32_t err = mDispatch.presentDisplay(mDevice, display, outPresentFence); if (err != HWC2_ERROR_NONE) { @@ -593,7 +587,6 @@ class HwcHalImpl : public Hal { static void refreshHook(hwc2_callback_data_t callbackData, hwc2_display_t display) { auto hal = static_cast(callbackData); - hal->mMustValidateDisplay = true; hal->mEventCallback->onRefresh(display); } @@ -654,8 +647,6 @@ class HwcHalImpl : public Hal { } mDispatch = {}; hal::ComposerHal::EventCallback* mEventCallback = nullptr; - - std::atomic mMustValidateDisplay{true}; }; } // namespace detail From 10d77e463ca1e844dbdf1b47add76990a560d2c0 Mon Sep 17 00:00:00 2001 From: Xusong Wang Date: Tue, 28 Aug 2018 16:50:01 -0700 Subject: [PATCH 081/718] Fix logics for floating-point comparision in VTS test. Set the acceptable error range based on both absolute tolerance and relative tolerance. Currently, absolute tolerance is set to 1e-5 for FP32 and 5 epsilon (~5e-3) for FP16 relaxed computation. The relative tolerance is set to 5ULP of the corresponding precision. Add a TODO mark for potential future adjustment on error limit based on testing. Bug: 111768023 Test: none Change-Id: Idedcec3e09fd7de9696811b93c81d0f180e896ef --- .../vts/functional/GeneratedTestHarness.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp index 0682ab95b2..64495cf763 100644 --- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp +++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp @@ -66,8 +66,8 @@ void copy_back(MixedTyped* dst, const std::vector& ra, char* sr // Top level driver for models and examples generated by test_generator.py // Test driver for those generated from ml/nn/runtime/test/spec void EvaluatePreparedModel(sp& preparedModel, std::function is_ignored, - const std::vector& examples, - float fpRange = 1e-5f) { + const std::vector& examples, float fpAtol = 1e-5f, + float fpRtol = 1e-5f) { const uint32_t INPUT = 0; const uint32_t OUTPUT = 1; @@ -175,7 +175,7 @@ void EvaluatePreparedModel(sp& preparedModel, std::function& device, std::function c EXPECT_EQ(ErrorStatus::NONE, prepareReturnStatus); ASSERT_NE(nullptr, preparedModel.get()); - EvaluatePreparedModel(preparedModel, is_ignored, examples); + float fpAtol = 1e-5f, fpRtol = 5.0f * 1.1920928955078125e-7f; + EvaluatePreparedModel(preparedModel, is_ignored, examples, fpAtol, fpRtol); } void Execute(const sp& device, std::function create_model, @@ -265,9 +266,13 @@ void Execute(const sp& device, std::function c EXPECT_EQ(ErrorStatus::NONE, prepareReturnStatus); ASSERT_NE(nullptr, preparedModel.get()); - // If in relaxed mode, set the error range to be 5ULP of FP16. - float fpRange = !model.relaxComputationFloat32toFloat16 ? 1e-5f : 5.0f * 0.0009765625f; - EvaluatePreparedModel(preparedModel, is_ignored, examples, fpRange); + // TODO: Adjust the error limit based on testing. + // If in relaxed mode, set the absolute tolerance to be 5ULP of FP16. + float fpAtol = !model.relaxComputationFloat32toFloat16 ? 1e-5f : 5.0f * 0.0009765625f; + // Set the relative tolerance to be 5ULP of the corresponding FP precision. + float fpRtol = !model.relaxComputationFloat32toFloat16 ? 5.0f * 1.1920928955078125e-7f + : 5.0f * 0.0009765625f; + EvaluatePreparedModel(preparedModel, is_ignored, examples, fpAtol, fpRtol); } } // namespace generated_tests From 6389b829fe2acfee50736c4788871d7cd5d64321 Mon Sep 17 00:00:00 2001 From: Jesse Hall Date: Wed, 29 Aug 2018 13:46:25 -0700 Subject: [PATCH 082/718] CleanSpec: Remove stale configstore@1.1-service.rc Removing this file was inadvertently left out of commit 2b3f826. Bug: 113292034 Test: build+flash from tree before 2b3f826, sync past 2b3f826, apply this change, build+flash again Change-Id: Ic12e57e2426d2e105e6b846fa8ca076c6100c2ba --- CleanSpec.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/CleanSpec.mk b/CleanSpec.mk index fcaced0df0..0900eea0cf 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -68,3 +68,4 @@ $(call add-clean-step, find $(PRODUCT_OUT)/system $(PRODUCT_OUT)/vendor -type f $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/seccomp_policy/configstore@1.0.policy) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/seccomp_policy/configstore@1.1.policy) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/bin/hw/android.hardware.configstore@1.1-service) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/init/android.hardware.configstore@1.1-service.rc) From c40c77ef0d5e7d2075abf12dd47ac6ad4b75e954 Mon Sep 17 00:00:00 2001 From: Sungtak Lee Date: Wed, 8 Aug 2018 17:24:34 -0700 Subject: [PATCH 083/718] Update android.hardware.media.bufferpool@2.0 HAL Add buffer invalidation message for bufferpool@2.0 Bug: 112203066 Change-Id: Ia1fca213c7e663f619e2061dd0055228aecbf15c --- media/bufferpool/2.0/IAccessor.hal | 10 +++++++--- media/bufferpool/2.0/types.hal | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/media/bufferpool/2.0/IAccessor.hal b/media/bufferpool/2.0/IAccessor.hal index 07ea99dead..bd7094594e 100644 --- a/media/bufferpool/2.0/IAccessor.hal +++ b/media/bufferpool/2.0/IAccessor.hal @@ -59,10 +59,14 @@ interface IAccessor { * to get shared buffers from the buffer pool. * @return connectionId Id of IConnection. The Id identifies * sender and receiver in FMQ messages during buffer transfer. - * @return mqDesc FMQ descriptor. The descriptor can be used to - * send/receive FMQ messages. + * @return toFmqDesc FMQ descriptor. The descriptor is used to + * post buffer status messages. + * @return fromFmqDesc FMQ descriptor. The descriptor is used to + * receive buffer invalidation messages from the buffer pool. */ connect() generates (ResultStatus status, IConnection connection, - int64_t connectionId, fmq_sync mqDesc); + int64_t connectionId, + fmq_sync toFmqDesc, + fmq_sync fromFmqDesc); }; diff --git a/media/bufferpool/2.0/types.hal b/media/bufferpool/2.0/types.hal index d5b393778e..7ce53b18bf 100644 --- a/media/bufferpool/2.0/types.hal +++ b/media/bufferpool/2.0/types.hal @@ -91,3 +91,19 @@ struct BufferStatusMessage { */ int64_t timestampUs; }; + +/* + * Buffer pool sends a buffer invalidation message to clients in order to + * ensure fast reclamation of the buffers. Clients must free the invalidated + * buffers as soon as possible upon receiving the message. + */ +struct BufferInvalidationMessage { + /** + * Buffers from fromBufferId to toBufferId must be invalidated. + * Both of fromBufferId and toBufferId are inclusive. + * If fromBufferId > toBufferID, wrap happens. In that case + * the wrap is based on UINT32_MAX. + */ + uint32_t fromBufferId; + uint32_t toBufferId; +}; From e6683e2b06b1de1b48fddebe86271a3cdbd5f051 Mon Sep 17 00:00:00 2001 From: Valerie Hau Date: Thu, 30 Aug 2018 15:47:37 -0700 Subject: [PATCH 084/718] Fixing execute bug in VTS tests for hardware composer Bug: 113532117 Test: ./VtsHalGraphicsComposerV2_1TargetTest && ./VtsHalGraphicsComposerV2_2TargetTest Change-Id: I5c3485d45c798c40377e4567ab14cce667dd17ea --- .../composer/2.1/utils/vts/ComposerVts.cpp | 1 - .../2.1/utils/vts/TestCommandReader.cpp | 4 +++- .../composer-vts/2.1/TestCommandReader.h | 1 + .../VtsHalGraphicsComposerV2_1TargetTest.cpp | 5 ++++- .../composer/2.2/utils/vts/ComposerVts.cpp | 1 - .../VtsHalGraphicsComposerV2_2TargetTest.cpp | 19 ++++++++++++++++++- 6 files changed, 26 insertions(+), 5 deletions(-) diff --git a/graphics/composer/2.1/utils/vts/ComposerVts.cpp b/graphics/composer/2.1/utils/vts/ComposerVts.cpp index 43a5378bfb..1cafafe3ae 100644 --- a/graphics/composer/2.1/utils/vts/ComposerVts.cpp +++ b/graphics/composer/2.1/utils/vts/ComposerVts.cpp @@ -293,7 +293,6 @@ void ComposerClient::execute(TestCommandReader* reader, CommandWriterBase* write if (queueChanged) { auto ret = mClient->setInputCommandQueue(*writer->getMQDescriptor()); ASSERT_EQ(Error::NONE, static_cast(ret)); - return; } mClient->executeCommands(commandLength, commandHandles, diff --git a/graphics/composer/2.1/utils/vts/TestCommandReader.cpp b/graphics/composer/2.1/utils/vts/TestCommandReader.cpp index e1dc5b6ebe..454a89ccdc 100644 --- a/graphics/composer/2.1/utils/vts/TestCommandReader.cpp +++ b/graphics/composer/2.1/utils/vts/TestCommandReader.cpp @@ -26,6 +26,7 @@ namespace V2_1 { namespace vts { void TestCommandReader::parse() { + mErrors.clear(); mCompositionChanges.clear(); while (!isEmpty()) { IComposerClient::Command command; @@ -41,7 +42,8 @@ void TestCommandReader::parse() { ASSERT_EQ(2, length); auto loc = read(); auto err = readSigned(); - GTEST_FAIL() << "unexpected error " << err << " at location " << loc; + std::pair error(loc, err); + mErrors.push_back(error); } break; case IComposerClient::Command::SET_CHANGED_COMPOSITION_TYPES: ASSERT_EQ(0, length % 3); diff --git a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/TestCommandReader.h b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/TestCommandReader.h index b9a4a5c103..c12debe066 100644 --- a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/TestCommandReader.h +++ b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/TestCommandReader.h @@ -33,6 +33,7 @@ class TestCommandReader : public CommandReaderBase { // unexpected errors or commands. void parse(); + std::vector> mErrors; std::vector> mCompositionChanges; }; diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp index 0607d4d81f..8b8c7aeef3 100644 --- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp +++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp @@ -672,7 +672,10 @@ class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest { mReader = std::make_unique(); } - void TearDown() override { ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown()); } + void TearDown() override { + ASSERT_EQ(0, mReader->mErrors.size()); + ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown()); + } const native_handle_t* allocate() { IMapper::BufferDescriptorInfo info{}; diff --git a/graphics/composer/2.2/utils/vts/ComposerVts.cpp b/graphics/composer/2.2/utils/vts/ComposerVts.cpp index 459e0fe2c1..d8fb656b7b 100644 --- a/graphics/composer/2.2/utils/vts/ComposerVts.cpp +++ b/graphics/composer/2.2/utils/vts/ComposerVts.cpp @@ -68,7 +68,6 @@ void ComposerClient::execute(V2_1::vts::TestCommandReader* reader, CommandWriter if (queueChanged) { auto ret = mClient->setInputCommandQueue(*writer->getMQDescriptor()); ASSERT_EQ(Error::NONE, static_cast(ret)); - return; } mClient->executeCommands(commandLength, commandHandles, diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp index e40dc22396..ffd6daf310 100644 --- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp +++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp @@ -127,7 +127,10 @@ class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest { mReader = std::make_unique(); } - void TearDown() override { ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown()); } + void TearDown() override { + ASSERT_EQ(0, mReader->mErrors.size()); + ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown()); + } const native_handle_t* allocate() { IMapper::BufferDescriptorInfo info{}; @@ -189,6 +192,12 @@ TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_PER_FRAME_METADATA) { {IComposerClient::PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL, 62.0}); mWriter->setLayerPerFrameMetadata(hidlMetadata); execute(); + + if (mReader->mErrors.size() == 1 && + static_cast(mReader->mErrors[0].second) == Error::UNSUPPORTED) { + mReader->mErrors.clear(); + GTEST_SUCCEED() << "SetLayerPerFrameMetadata is not supported"; + } } /** @@ -313,6 +322,14 @@ TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_FLOAT_COLOR) { mWriter->selectLayer(layer); mWriter->setLayerFloatColor(IComposerClient::FloatColor{1.0, 1.0, 1.0, 1.0}); mWriter->setLayerFloatColor(IComposerClient::FloatColor{0.0, 0.0, 0.0, 0.0}); + execute(); + + if (mReader->mErrors.size() == 2 && + static_cast(mReader->mErrors[0].second) == Error::UNSUPPORTED && + static_cast(mReader->mErrors[1].second) == Error::UNSUPPORTED) { + mReader->mErrors.clear(); + GTEST_SUCCEED() << "SetLayerFloatColor is not supported"; + } } /** From 019114aa898b4dcb3e7f7d9e30a41b2f893023a4 Mon Sep 17 00:00:00 2001 From: Emilian Peev Date: Tue, 4 Sep 2018 16:37:20 +0100 Subject: [PATCH 085/718] Camera: Add camera.metadata@3.4 The initial entry includes information about static metadata that requires camera permission. Bug: 112160024 Test: hidl-gen, builds Change-Id: I3aa321edbfea4c2adaaeded3fd10c8746ed07aa7 --- camera/metadata/3.4/Android.bp | 21 ++++++++++++++ camera/metadata/3.4/types.hal | 51 ++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 camera/metadata/3.4/Android.bp create mode 100644 camera/metadata/3.4/types.hal diff --git a/camera/metadata/3.4/Android.bp b/camera/metadata/3.4/Android.bp new file mode 100644 index 0000000000..04a00ef8dc --- /dev/null +++ b/camera/metadata/3.4/Android.bp @@ -0,0 +1,21 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +hidl_interface { + name: "android.hardware.camera.metadata@3.4", + root: "android.hardware", + vndk: { + enabled: true, + }, + srcs: [ + "types.hal", + ], + interfaces: [ + "android.hardware.camera.metadata@3.2", + "android.hardware.camera.metadata@3.3", + ], + types: [ + "CameraMetadataTag", + ], + gen_java: true, +} + diff --git a/camera/metadata/3.4/types.hal b/camera/metadata/3.4/types.hal new file mode 100644 index 0000000000..0088087e74 --- /dev/null +++ b/camera/metadata/3.4/types.hal @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Autogenerated from camera metadata definitions in + * /system/media/camera/docs/metadata_definitions.xml + * *** DO NOT EDIT BY HAND *** + */ + +package android.hardware.camera.metadata@3.4; + +/* Include definitions from all prior minor HAL metadata revisions */ +import android.hardware.camera.metadata@3.2; +import android.hardware.camera.metadata@3.3; + +// No new metadata sections added in this revision + +/** + * Main enumeration for defining camera metadata tags added in this revision + * + *

Partial documentation is included for each tag; for complete documentation, reference + * '/system/media/camera/docs/docs.html' in the corresponding Android source tree.

+ */ +enum CameraMetadataTag : @3.3::CameraMetadataTag { + /** android.request.characteristicKeysNeedingPermission [static, int32[], hidden] + * + *

A list of camera characteristics keys that are only available + * in case the camera client has camera permission.

+ */ + ANDROID_REQUEST_CHARACTERISTIC_KEYS_NEEDING_PERMISSION = android.hardware.camera.metadata@3.3::CameraMetadataTag:ANDROID_REQUEST_END_3_3, + + ANDROID_REQUEST_END_3_4, + +}; + +/* + * Enumeration definitions for the various entries that need them + */ From 3a32a2b0661af204199be12d5551cd4225909604 Mon Sep 17 00:00:00 2001 From: Valerie Hau Date: Tue, 28 Aug 2018 17:26:30 -0700 Subject: [PATCH 086/718] Fixing file descriptor close bug and display refresh bug Test: ./VtsHalGraphicsComposerV2_2TargetTest Change-Id: Ib3de65ab33496bb89c708d0b98966b0084f0bd10 --- .../VtsHalGraphicsComposerV2_2ReadbackTest.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp index fc32951c00..229c85667c 100644 --- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp +++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp @@ -289,8 +289,6 @@ TEST_F(GraphicsComposerReadbackTest, SingleSolidColorLayer) { int32_t fenceHandle; mComposerClient->getReadbackBufferFence(mPrimaryDisplay, &fenceHandle); - base::unique_fd fence(fenceHandle); - // lock buffer // Create Rect accessRegion to specify reading the entire buffer IMapper::Rect accessRegion; @@ -299,8 +297,17 @@ TEST_F(GraphicsComposerReadbackTest, SingleSolidColorLayer) { accessRegion.width = info.width; accessRegion.height = info.height; - void* bufData = mGralloc->lock(buffer, info.usage, accessRegion, fence); + void* bufData = mGralloc->lock(buffer, info.usage, accessRegion, fenceHandle); checkReadbackBuffer(info, stride, bufData, expectedColors); + int unlockFence = mGralloc->unlock(buffer); + + if (unlockFence != -1) { + close(unlockFence); + } + + mWriter->validateDisplay(); + mWriter->presentDisplay(); + execute(); } } // anonymous namespace From b1b8ee2c37d4d353db13668d553b279c7641343c Mon Sep 17 00:00:00 2001 From: Jong Wook Kim Date: Tue, 4 Sep 2018 18:52:30 -0700 Subject: [PATCH 087/718] Add VTS for Wifi VendorHAL 1.3 Create 1.3 VTS for Wifi. Bug: 113798959 Bug: 111753174 Test: atest VtsHalWifiV1_3TargetTest Change-Id: Ib26278e8f059110f8e3597038c88c80d87c28747 --- wifi/1.3/vts/OWNERS | 2 + wifi/1.3/vts/functional/Android.bp | 30 ++++++++++++ .../functional/VtsHalWifiV1_3TargetTest.cpp | 48 +++++++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 wifi/1.3/vts/OWNERS create mode 100644 wifi/1.3/vts/functional/Android.bp create mode 100644 wifi/1.3/vts/functional/VtsHalWifiV1_3TargetTest.cpp diff --git a/wifi/1.3/vts/OWNERS b/wifi/1.3/vts/OWNERS new file mode 100644 index 0000000000..8bfb14882c --- /dev/null +++ b/wifi/1.3/vts/OWNERS @@ -0,0 +1,2 @@ +rpius@google.com +etancohen@google.com diff --git a/wifi/1.3/vts/functional/Android.bp b/wifi/1.3/vts/functional/Android.bp new file mode 100644 index 0000000000..dbe77bde95 --- /dev/null +++ b/wifi/1.3/vts/functional/Android.bp @@ -0,0 +1,30 @@ +// +// Copyright (C) 2018 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +cc_test { + name: "VtsHalWifiV1_3TargetTest", + defaults: ["VtsHalTargetTestDefaults"], + srcs: [ + "VtsHalWifiV1_3TargetTest.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", + ], +} diff --git a/wifi/1.3/vts/functional/VtsHalWifiV1_3TargetTest.cpp b/wifi/1.3/vts/functional/VtsHalWifiV1_3TargetTest.cpp new file mode 100644 index 0000000000..b410a4813f --- /dev/null +++ b/wifi/1.3/vts/functional/VtsHalWifiV1_3TargetTest.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "wifi_hidl_test_utils.h" + +// Test environment for Wifi HIDL HAL. +class WifiHidlEnvironment_1_3 : public WifiHidlEnvironment { + public: + // get the test environment singleton + static WifiHidlEnvironment_1_3* Instance() { + static WifiHidlEnvironment_1_3* instance = new WifiHidlEnvironment_1_3; + return instance; + } + + virtual void registerTestServices() override { + registerTestService(); + } + + private: + WifiHidlEnvironment_1_3() {} +}; + +WifiHidlEnvironment_1_3* gEnv = WifiHidlEnvironment_1_3::Instance(); + +int main(int argc, char** argv) { + ::testing::AddGlobalTestEnvironment(gEnv); + ::testing::InitGoogleTest(&argc, argv); + gEnv->init(&argc, argv); + int status = RUN_ALL_TESTS(); + LOG(INFO) << "Test result = " << status; + return status; +} From 57acf9749a2e469e86198a0b4e7b341cddeb70dc Mon Sep 17 00:00:00 2001 From: Kevin Chyn Date: Fri, 31 Aug 2018 15:10:03 -0700 Subject: [PATCH 088/718] Update Face HIDL enroll method Bug: 110597778 Test: builds Change-Id: I61e4f4a61ad0561448bc50a29b84b668e9569551 --- biometrics/face/1.0/IBiometricsFace.hal | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/biometrics/face/1.0/IBiometricsFace.hal b/biometrics/face/1.0/IBiometricsFace.hal index fbdb210694..3c3b0c24cf 100644 --- a/biometrics/face/1.0/IBiometricsFace.hal +++ b/biometrics/face/1.0/IBiometricsFace.hal @@ -109,10 +109,20 @@ interface IBiometricsFace { * @param timeoutSec A timeout in seconds, after which this enrollment * attempt is cancelled. Note that the client still needs to * call postEnroll() to terminate the enrollment session. + * @param requireAttention When set to true, requires user attention (e.g. + * eyes open and looking at the device) for enrollment to complete, as + * well as subsequent authentication. This is expected to be enabled by + * default to improve security and decrease falsing (unintentional face + * detection). This feature can be disabled at the user's request + * during enrollment, e.g. for accessibility reasons. When enabled, + * the FaceAcquiredInfo#POOR_GAZE message must be sent when the user's + * attention has not been established. The UI should inform the user + * to look at the device. * @return status The status of this method call. */ @callflow(next={"cancel", "enroll", "postEnroll", "remove"}) - enroll(vec hat, uint32_t timeoutSec) generates (Status status); + enroll(vec hat, uint32_t timeoutSec, bool requireAttention) + generates (Status status); /** * Finishes the enrollment session and invalidates the challenge generated From af5d0a6d1d143900216f5369cf84b4412f23227a Mon Sep 17 00:00:00 2001 From: Kevin Chyn Date: Fri, 31 Aug 2018 16:06:43 -0700 Subject: [PATCH 089/718] Add setter/getter for requireAttention Also renames pre/postEnroll to get/revokeChallenge Bug: 110597778 Test: builds Change-Id: I5547504b27e0f6d304f016e02be91aa15e548e5f --- biometrics/face/1.0/Android.bp | 1 + biometrics/face/1.0/IBiometricsFace.hal | 71 ++++++++++++++++++------- biometrics/face/1.0/types.hal | 24 ++++++++- 3 files changed, 75 insertions(+), 21 deletions(-) diff --git a/biometrics/face/1.0/Android.bp b/biometrics/face/1.0/Android.bp index 61bf247786..45dbad9d3a 100644 --- a/biometrics/face/1.0/Android.bp +++ b/biometrics/face/1.0/Android.bp @@ -17,6 +17,7 @@ hidl_interface { types: [ "FaceAcquiredInfo", "FaceError", + "OptionalBool", "OptionalUint64", "Status", "UserHandle", diff --git a/biometrics/face/1.0/IBiometricsFace.hal b/biometrics/face/1.0/IBiometricsFace.hal index 3c3b0c24cf..f39eaeb2fd 100644 --- a/biometrics/face/1.0/IBiometricsFace.hal +++ b/biometrics/face/1.0/IBiometricsFace.hal @@ -60,18 +60,18 @@ interface IBiometricsFace { * persistent for a given user. * @param storePath filesystem path to the template storage directory. */ - @callflow(next={"authenticate", "preEnroll", "enumerate", "remove"}) + @callflow(next={"authenticate", "generateChallenge", "enumerate", "remove"}) setActiveUser(int32_t userId, string storePath) generates (Status status); /** - * Begins a pre-enrollment request. + * Begins a secure transaction request, e.g. enrollment. * * Generates a unique and cryptographically secure random token used to - * indicate the start of an enrollment transaction. preEnroll() and - * postEnroll() specify a pin/pattern/password cleared time window where - * enrollment is allowed. + * indicate the start of a secure transaction. generateChallenge() and + * revokeChallenge() specify a pin/pattern/password cleared time window where + * the secure transaction is allowed. * - * preEnroll() generates a challenge which must then be wrapped by the + * generateChallenge() generates a challenge which must then be wrapped by the * gatekeeper after verifying a successful strong authentication attempt, * which generates a Hardware Authentication Token. The challenge prevents * spoofing and replay attacks and ensures that we only update a user’s face @@ -81,8 +81,8 @@ interface IBiometricsFace { * @return result, with its "value" parameter representing a "challenge": a * unique and cryptographically secure random token. */ - @callflow(next={"enroll", "postEnroll"}) - preEnroll() generates (OptionalUint64 result); + @callflow(next={"enroll", "revokeChallenge", "setRequireAttention"}) + generateChallenge() generates (OptionalUint64 result); /** * Enrolls a user's face. @@ -95,20 +95,20 @@ interface IBiometricsFace { * necessity for a shared use case, e.g. TVs or cars. * * Note that the Hardware Authentication Token must still be valid after - * this call, and must be explicitly invalidated by a call to postEnroll(). - * This allows clients to immediately reattempt enrollment (for example, if - * a user wasn’t satisfied with their enrollment) without having to go - * through another strong authentication flow. + * this call, and must be explicitly invalidated by a call to + * revokeChallenge(). This allows clients to immediately reattempt + * enrollment (for example, if a user wasn’t satisfied with their enrollment) + * without having to go through another strong authentication flow. * * This method triggers the IBiometricsFaceClientCallback#onEnrollResult() * method. * * @param hat A valid Hardware Authentication Token, generated as a result - * of a preEnroll() challenge being wrapped by the gatekeeper after a - * sucessful strong authentication request. + * of a generateChallenge() challenge being wrapped by the gatekeeper + * after a sucessful strong authentication request. * @param timeoutSec A timeout in seconds, after which this enrollment * attempt is cancelled. Note that the client still needs to - * call postEnroll() to terminate the enrollment session. + * call revokeChallenge() to terminate the enrollment session. * @param requireAttention When set to true, requires user attention (e.g. * eyes open and looking at the device) for enrollment to complete, as * well as subsequent authentication. This is expected to be enabled by @@ -120,13 +120,13 @@ interface IBiometricsFace { * to look at the device. * @return status The status of this method call. */ - @callflow(next={"cancel", "enroll", "postEnroll", "remove"}) + @callflow(next={"cancel", "enroll", "revokeChallenge", "remove"}) enroll(vec hat, uint32_t timeoutSec, bool requireAttention) generates (Status status); /** - * Finishes the enrollment session and invalidates the challenge generated - * by preEnroll(). + * Finishes the secure transaction by invalidating the challenge generated + * by generateChallenge(). * * Clients must call this method once enrollment is complete, and the user's * face template no longer needs to be updated. @@ -134,7 +134,38 @@ interface IBiometricsFace { * @return status The status of this method call. */ @callflow(next={"authenticate", "setActiveUser", "enumerate", "remove"}) - postEnroll() generates (Status status); + revokeChallenge() generates (Status status); + + /** + * Requires that all subsequent authenticate calls to first have the + * user's attention. This method does not affect enroll, which has its + * own requireAttention parameter. + * + * Changes the state of previous enrollment setting. Because this may + * decrease security, the user must enter their password before this method + * is invoked (see @param HAT). The driver must verify the HAT before + * changing the requireAttention state. + * Note: In some cases it may not be possible to change the state of this + * flag without re-enrolling. For example, if the user didn't provide + * attention during the original enrollment. This flag reflects the same + * persistent state as the one passed to enroll(). + * + * @param requireAttention When set to true, requires user attention for + * authentication to succeed. + * @param hat A valid Hardware Authentication Token, generated as a result + * of getChallenge(). + * @return status The status of this method call. + */ + setRequireAttention(bool requireAttention, vec hat) + generates(Status status); + + /** + * Retrieves the current requireAttention state. + * + * @return result, with its value parameter representing the current + * requireAttention state. + */ + getRequireAttention(vec hat) generates (OptionalBool result); /** * Returns an identifier associated with the current face set. @@ -196,6 +227,6 @@ interface IBiometricsFace { * object instance; or 0 if not being used. * @return status The status of this method call. */ - @callflow(next={"cancel", "preEnroll", "remove"}) + @callflow(next={"cancel", "generateChallenge", "remove"}) authenticate(uint64_t operationId) generates (Status status); }; diff --git a/biometrics/face/1.0/types.hal b/biometrics/face/1.0/types.hal index 08af91907b..92cb70d7b6 100644 --- a/biometrics/face/1.0/types.hal +++ b/biometrics/face/1.0/types.hal @@ -48,7 +48,13 @@ enum Status : uint32_t { /** * The HAL has encountered an internal error and cannot complete the request. */ - INTERNAL_ERROR = 3 + INTERNAL_ERROR = 3, + + /** + * The operation could not be completed because there are no enrolled + * templates. + */ + NOT_ENROLLED = 4 }; /** @@ -253,3 +259,19 @@ struct OptionalUint64 { */ uint64_t value; }; + +/** + * Result structure with an addition bool field. See documentation in + * getRequireAttention() for usage of the value. + */ +struct OptionalBool { + /** + * The return status. + */ + Status status; + + /** + * This value is only meaningful if status is OK. + */ + bool value; +}; \ No newline at end of file From 8d782cbd8f8c3f09709ff6d504c588944f6f489f Mon Sep 17 00:00:00 2001 From: Valerie Hau Date: Tue, 14 Aug 2018 09:53:29 -0700 Subject: [PATCH 090/718] Adding unit tests for IComposerClient V2_2 VTS tests Bug: 111563608 Test: ./VtsHalGraphicsComposerV2_2TargetTest Change-Id: I081cb065e8a574e667e0f49fb7caac24c34c5535 --- ...VtsHalGraphicsComposerV2_2ReadbackTest.cpp | 58 +-- .../VtsHalGraphicsComposerV2_2TargetTest.cpp | 342 +++++++++++++++++- 2 files changed, 353 insertions(+), 47 deletions(-) diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp index 229c85667c..91318bc532 100644 --- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp +++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp @@ -119,10 +119,10 @@ class GraphicsComposerReadbackTest : public ::testing::VtsHalHidlTargetTestBase // assume the first display is primary and is never removed mPrimaryDisplay = waitForFirstDisplay(); Config activeConfig = mComposerClient->getActiveConfig(mPrimaryDisplay); - width = mComposerClient->getDisplayAttribute(mPrimaryDisplay, activeConfig, - IComposerClient::Attribute::WIDTH); - height = mComposerClient->getDisplayAttribute(mPrimaryDisplay, activeConfig, - IComposerClient::Attribute::HEIGHT); + mDisplayWidth = mComposerClient->getDisplayAttribute(mPrimaryDisplay, activeConfig, + IComposerClient::Attribute::WIDTH); + mDisplayHeight = mComposerClient->getDisplayAttribute(mPrimaryDisplay, activeConfig, + IComposerClient::Attribute::HEIGHT); // explicitly disable vsync mComposerClient->setVsyncEnabled(mPrimaryDisplay, false); @@ -132,6 +132,11 @@ class GraphicsComposerReadbackTest : public ::testing::VtsHalHidlTargetTestBase mWriter = std::make_shared(1024); mReader = std::make_unique(); mGralloc = std::make_unique(); + + mComposerClient->getRaw()->getReadbackBufferAttributes( + mPrimaryDisplay, [&](const auto& tmpError, const auto&, const auto&) { + mHasReadbackBuffer = tmpError == Error::NONE; + }); } ~GraphicsComposerReadbackTest() override { @@ -166,7 +171,7 @@ class GraphicsComposerReadbackTest : public ::testing::VtsHalHidlTargetTestBase } bool readbackSupported(const PixelFormat& pixelFormat, const Dataspace& dataspace, - const Error& error) { + const Error error) { if (error == Error::UNSUPPORTED) { return false; } @@ -181,19 +186,12 @@ class GraphicsComposerReadbackTest : public ::testing::VtsHalHidlTargetTestBase } void getReadbackBufferAttributes(Display display, PixelFormat* outPixelFormat, - Dataspace* outDataspace, Error* outError) { + Dataspace* outDataspace) { mComposerClient->getRaw()->getReadbackBufferAttributes( - display, - [&](const auto& tmpError, const auto& tmpOutPixelFormat, const auto& tmpOutDataspace) { - *outError = tmpError; + display, [&](const auto&, const auto& tmpOutPixelFormat, const auto& tmpOutDataspace) { *outPixelFormat = tmpOutPixelFormat; *outDataspace = tmpOutDataspace; }); - - // Not all devices support readback. Pass test if this is the case - if (!readbackSupported(*outPixelFormat, *outDataspace, *outError)) { - GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; - } } void checkReadbackBuffer(IMapper::BufferDescriptorInfo info, uint32_t stride, void* bufferData, @@ -202,9 +200,9 @@ class GraphicsComposerReadbackTest : public ::testing::VtsHalHidlTargetTestBase ASSERT_NE(-1, bytesPerPixel) << "unexpected pixel format " << static_cast(info.format) << "(expected RGBA_8888 or RGB_888)"; - for (int row = 0; row < height; row++) { - for (int col = 0; col < width; col++) { - int pixel = row * width + col; + for (int row = 0; row < mDisplayHeight; row++) { + for (int col = 0; col < mDisplayWidth; col++) { + int pixel = row * mDisplayWidth + col; int offset = (row * stride + col) * bytesPerPixel; uint8_t* pixelColor = (uint8_t*)bufferData + offset; @@ -221,12 +219,14 @@ class GraphicsComposerReadbackTest : public ::testing::VtsHalHidlTargetTestBase sp mComposerCallback; // the first display and is assumed never to be removed Display mPrimaryDisplay; - int32_t width; - int32_t height; + int32_t mDisplayWidth; + int32_t mDisplayHeight; std::shared_ptr mWriter; std::unique_ptr mReader; std::unique_ptr mGralloc; + bool mHasReadbackBuffer; + private: Display waitForFirstDisplay() { while (true) { @@ -241,6 +241,10 @@ class GraphicsComposerReadbackTest : public ::testing::VtsHalHidlTargetTestBase }; TEST_F(GraphicsComposerReadbackTest, SingleSolidColorLayer) { + if (!mHasReadbackBuffer) { + GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; + return; + } mWriter->selectDisplay(mPrimaryDisplay); mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::ON); mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB, RenderIntent::COLORIMETRIC); @@ -255,10 +259,10 @@ TEST_F(GraphicsComposerReadbackTest, SingleSolidColorLayer) { std::vector> layers = {layer}; // expected color for each pixel - std::vector expectedColors(width * height); - for (int row = 0; row < height; row++) { - for (int col = 0; col < width; col++) { - int pixel = row * width + col; + std::vector expectedColors(mDisplayWidth * mDisplayHeight); + for (int row = 0; row < mDisplayHeight; row++) { + for (int col = 0; col < mDisplayWidth; col++) { + int pixel = row * mDisplayWidth + col; if (row >= coloredSquare.top && row < coloredSquare.bottom && col >= coloredSquare.left && col < coloredSquare.right) { expectedColors[pixel] = color; @@ -270,12 +274,12 @@ TEST_F(GraphicsComposerReadbackTest, SingleSolidColorLayer) { PixelFormat pixelFormat; Dataspace dataspace; - Error error; - getReadbackBufferAttributes(mPrimaryDisplay, &pixelFormat, &dataspace, &error); + + getReadbackBufferAttributes(mPrimaryDisplay, &pixelFormat, &dataspace); IMapper::BufferDescriptorInfo info; - info.width = width; - info.height = height; + info.width = mDisplayWidth; + info.height = mDisplayHeight; info.layerCount = 1; info.format = pixelFormat; info.usage = static_cast(BufferUsage::CPU_READ_OFTEN | BufferUsage::GPU_TEXTURE); diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp index ffd6daf310..7834b9460f 100644 --- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp +++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp @@ -73,14 +73,29 @@ class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase { // assume the first display is primary and is never removed mPrimaryDisplay = waitForFirstDisplay(); + Config config = mComposerClient->getActiveConfig(mPrimaryDisplay); + mDisplayWidth = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config, + IComposerClient::Attribute::WIDTH); + mDisplayHeight = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config, + IComposerClient::Attribute::HEIGHT); + // explicitly disable vsync mComposerClient->setVsyncEnabled(mPrimaryDisplay, false); mComposerCallback->setVsyncAllowed(false); mComposerClient->getRaw()->getReadbackBufferAttributes( - mPrimaryDisplay, [&](const auto& tmpError, const auto&, const auto&) { + mPrimaryDisplay, + [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) { mHasReadbackBuffer = tmpError == Error::NONE; + if (mHasReadbackBuffer) { + mReadbackPixelFormat = tmpPixelFormat; + mReadbackDataspace = tmpDataspace; + ASSERT_LT(static_cast(0), mReadbackPixelFormat); + ASSERT_NE(Dataspace::UNKNOWN, mReadbackDataspace); + } }); + + mInvalidDisplayId = GetInvalidDisplayId(); } void TearDown() override { @@ -91,6 +106,22 @@ class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase { } } + // returns an invalid display id (one that has not been registered to a + // display. Currently assuming that a device will never have close to + // std::numeric_limit::max() displays registered while running tests + Display GetInvalidDisplayId() { + std::vector validDisplays = mComposerCallback->getDisplays(); + uint64_t id = std::numeric_limits::max(); + while (id > 0) { + if (std::find(validDisplays.begin(), validDisplays.end(), id) == validDisplays.end()) { + return id; + } + id--; + } + + return 0; + } + // use the slot count usually set by SF static constexpr uint32_t kBufferSlotCount = 64; @@ -99,8 +130,15 @@ class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase { sp mComposerCallback; // the first display and is assumed never to be removed Display mPrimaryDisplay; + int32_t mDisplayWidth; + int32_t mDisplayHeight; + bool mHasReadbackBuffer; + uint64_t mInvalidDisplayId; + PixelFormat mReadbackPixelFormat; + Dataspace mReadbackDataspace; + private: Display waitForFirstDisplay() { while (true) { @@ -197,7 +235,11 @@ TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_PER_FRAME_METADATA) { static_cast(mReader->mErrors[0].second) == Error::UNSUPPORTED) { mReader->mErrors.clear(); GTEST_SUCCEED() << "SetLayerPerFrameMetadata is not supported"; + ASSERT_NO_FATAL_FAILURE(mComposerClient->destroyLayer(mPrimaryDisplay, layer)); + return; } + + ASSERT_NO_FATAL_FAILURE(mComposerClient->destroyLayer(mPrimaryDisplay, layer)); } /** @@ -255,10 +297,36 @@ TEST_F(GraphicsComposerHidlTest, GetClientTargetSupport_2_2) { } } +/** + * Test IComposerClient::getClientTargetSupport_2_2 + * + * Test that IComposerClient::getClientTargetSupport_2_2 returns + * Error::BAD_DISPLAY when passed in an invalid display handle + */ + +TEST_F(GraphicsComposerHidlTest, GetClientTargetSupport_2_2BadDisplay) { + std::vector configs = mComposerClient->getDisplayConfigs(mPrimaryDisplay); + for (auto config : configs) { + int32_t width = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config, + IComposerClient::Attribute::WIDTH); + int32_t height = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config, + IComposerClient::Attribute::HEIGHT); + ASSERT_LT(0, width); + ASSERT_LT(0, height); + + mComposerClient->setActiveConfig(mPrimaryDisplay, config); + + Error error = mComposerClient->getRaw()->getClientTargetSupport_2_2( + mInvalidDisplayId, width, height, PixelFormat::RGBA_8888, Dataspace::UNKNOWN); + + EXPECT_EQ(Error::BAD_DISPLAY, error); + } +} + /** * Test IComposerClient::setPowerMode_2_2. */ -TEST_F(GraphicsComposerHidlTest, setPowerMode_2_2) { +TEST_F(GraphicsComposerHidlTest, SetPowerMode_2_2) { std::vector modes; modes.push_back(IComposerClient::PowerMode::OFF); modes.push_back(IComposerClient::PowerMode::ON_SUSPEND); @@ -269,25 +337,118 @@ TEST_F(GraphicsComposerHidlTest, setPowerMode_2_2) { } } -TEST_F(GraphicsComposerHidlTest, setReadbackBuffer) { +/** + * Test IComposerClient::setPowerMode_2_2 + * + * Test that IComposerClient::setPowerMode_2_2 succeeds for different varations + * of PowerMode + */ +TEST_F(GraphicsComposerHidlTest, SetPowerMode_2_2Variations) { + std::vector modes; + + modes.push_back(IComposerClient::PowerMode::OFF); + modes.push_back(IComposerClient::PowerMode::OFF); + + for (auto mode : modes) { + ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode_2_2(mPrimaryDisplay, mode)); + } + + modes.clear(); + + modes.push_back(IComposerClient::PowerMode::ON); + modes.push_back(IComposerClient::PowerMode::ON); + + for (auto mode : modes) { + ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode_2_2(mPrimaryDisplay, mode)); + } + + modes.clear(); + + modes.push_back(IComposerClient::PowerMode::ON_SUSPEND); + modes.push_back(IComposerClient::PowerMode::ON_SUSPEND); + + for (auto mode : modes) { + ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode_2_2(mPrimaryDisplay, mode)); + } + + if (mComposerClient->getDozeSupport(mPrimaryDisplay)) { + modes.clear(); + + modes.push_back(IComposerClient::PowerMode::DOZE); + modes.push_back(IComposerClient::PowerMode::DOZE); + + for (auto mode : modes) { + ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode_2_2(mPrimaryDisplay, mode)); + } + + modes.clear(); + + modes.push_back(IComposerClient::PowerMode::DOZE_SUSPEND); + modes.push_back(IComposerClient::PowerMode::DOZE_SUSPEND); + + for (auto mode : modes) { + ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode_2_2(mPrimaryDisplay, mode)); + } + } +} + +/** + * Test IComposerClient::setPowerMode_2_2 + * + * Tests that IComposerClient::setPowerMode_2_2 returns BAD_DISPLAY when passed an + * invalid display handle + */ +TEST_F(GraphicsComposerHidlTest, SetPowerMode_2_2BadDisplay) { + Error error = mComposerClient->getRaw()->setPowerMode_2_2(mInvalidDisplayId, + IComposerClient::PowerMode::ON); + ASSERT_EQ(Error::BAD_DISPLAY, error); +} + +/** + * Test IComposerClient::setPowerMode_2_2 + * + * Test that IComposerClient::setPowerMode_2_2 returns BAD_PARAMETER when passed + * an invalid PowerMode + */ +TEST_F(GraphicsComposerHidlTest, SetPowerMode_2_2BadParameter) { + Error error = mComposerClient->getRaw()->setPowerMode_2_2( + mPrimaryDisplay, static_cast(-1)); + ASSERT_EQ(Error::BAD_PARAMETER, error); +} + +/** + * Test IComposerClient::setPowerMode_2_2 + * + * Test that IComposerClient::setPowerMode_2_2 returns UNSUPPORTED when passed + * DOZE or DOZE_SUPPORT on a device that does not support these modes + */ +TEST_F(GraphicsComposerHidlTest, SetPowerMode_2_2Unsupported) { + if (!mComposerClient->getDozeSupport(mPrimaryDisplay)) { + Error error = mComposerClient->getRaw()->setPowerMode_2_2(mPrimaryDisplay, + IComposerClient::PowerMode::DOZE); + EXPECT_EQ(Error::UNSUPPORTED, error); + + error = mComposerClient->getRaw()->setPowerMode_2_2( + mPrimaryDisplay, IComposerClient::PowerMode::DOZE_SUSPEND); + EXPECT_EQ(Error::UNSUPPORTED, error); + } +} + +/** + * Test IComposerClient::setReadbackBuffer + * + * Test IComposerClient::setReadbackBuffer + */ +TEST_F(GraphicsComposerHidlTest, SetReadbackBuffer) { if (!mHasReadbackBuffer) { return; } - PixelFormat pixelFormat; - Dataspace dataspace; - mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay, &pixelFormat, &dataspace); - ASSERT_LT(static_cast(0), pixelFormat); - ASSERT_NE(Dataspace::UNKNOWN, dataspace); - IMapper::BufferDescriptorInfo info{}; - Config config = mComposerClient->getActiveConfig(mPrimaryDisplay); - info.width = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config, - IComposerClient::Attribute::WIDTH); - info.height = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config, - IComposerClient::Attribute::HEIGHT); + info.width = mDisplayWidth; + info.height = mDisplayHeight; info.layerCount = 1; - info.format = static_cast(pixelFormat); + info.format = static_cast(mReadbackPixelFormat); // BufferUsage::COMPOSER_OUTPUT is missing info.usage = static_cast(BufferUsage::COMPOSER_OVERLAY | BufferUsage::CPU_READ_OFTEN); @@ -299,7 +460,49 @@ TEST_F(GraphicsComposerHidlTest, setReadbackBuffer) { mComposerClient->setReadbackBuffer(mPrimaryDisplay, buffer, -1); } -TEST_F(GraphicsComposerHidlTest, getReadbackBufferFenceInactive) { +/** + * Test IComposerClient::setReadbackBuffer + * + * Test that IComposerClient::setReadbackBuffer returns an Error::BAD_DISPLAY + * when passed an invalid display handle + */ +TEST_F(GraphicsComposerHidlTest, SetReadbackBufferBadDisplay) { + if (!mHasReadbackBuffer) { + return; + } + + IMapper::BufferDescriptorInfo info{}; + info.width = mDisplayWidth; + info.height = mDisplayHeight; + info.layerCount = 1; + info.format = static_cast(mReadbackPixelFormat); + info.usage = static_cast(BufferUsage::COMPOSER_OVERLAY | BufferUsage::CPU_READ_OFTEN); + + std::unique_ptr gralloc; + const native_handle_t* buffer; + ASSERT_NO_FATAL_FAILURE(gralloc = std::make_unique()); + ASSERT_NO_FATAL_FAILURE(buffer = gralloc->allocate(info)); + + Error error = mComposerClient->getRaw()->setReadbackBuffer(mInvalidDisplayId, buffer, nullptr); + ASSERT_EQ(Error::BAD_DISPLAY, error); +} + +/** + * Test IComposerClient::setReadbackBuffer + * + * Test that IComposerClient::setReadbackBuffer returns Error::BAD_PARAMETER + * when passed an invalid buffer handle + */ +TEST_F(GraphicsComposerHidlTest, SetReadbackBufferBadParameter) { + if (!mHasReadbackBuffer) { + return; + } + + Error error = mComposerClient->getRaw()->setReadbackBuffer(mPrimaryDisplay, nullptr, nullptr); + ASSERT_EQ(Error::BAD_PARAMETER, error); +} + +TEST_F(GraphicsComposerHidlTest, GetReadbackBufferFenceInactive) { if (!mHasReadbackBuffer) { return; } @@ -320,6 +523,7 @@ TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_FLOAT_COLOR) { mWriter->selectDisplay(mPrimaryDisplay); mWriter->selectLayer(layer); + mWriter->setLayerCompositionType(IComposerClient::Composition::SOLID_COLOR); mWriter->setLayerFloatColor(IComposerClient::FloatColor{1.0, 1.0, 1.0, 1.0}); mWriter->setLayerFloatColor(IComposerClient::FloatColor{0.0, 0.0, 0.0, 0.0}); execute(); @@ -329,13 +533,28 @@ TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_FLOAT_COLOR) { static_cast(mReader->mErrors[1].second) == Error::UNSUPPORTED) { mReader->mErrors.clear(); GTEST_SUCCEED() << "SetLayerFloatColor is not supported"; + return; } + + // ensure setting float color on layer with composition type that is not + // SOLID_COLOR does not fail + V2_1::Layer clientLayer; + ASSERT_NO_FATAL_FAILURE(clientLayer = + mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); + mWriter->selectDisplay(mPrimaryDisplay); + mWriter->selectLayer(clientLayer); + mWriter->setLayerCompositionType(IComposerClient::Composition::CLIENT); + mWriter->setLayerFloatColor(IComposerClient::FloatColor{1.0, 1.0, 1.0, 1.0}); + execute(); + + // At this point we know that this function is supported so there should be + // no errors (checked upon TearDown) } /** * Test IComposerClient::getDataspaceSaturationMatrix. */ -TEST_F(GraphicsComposerHidlTest, getDataspaceSaturationMatrix) { +TEST_F(GraphicsComposerHidlTest, GetDataspaceSaturationMatrix) { auto matrix = mComposerClient->getDataspaceSaturationMatrix(Dataspace::SRGB_LINEAR); // the last row is known ASSERT_EQ(0.0f, matrix[12]); @@ -344,6 +563,19 @@ TEST_F(GraphicsComposerHidlTest, getDataspaceSaturationMatrix) { ASSERT_EQ(1.0f, matrix[15]); } +/* + * Test IComposerClient::getDataspaceSaturationMatrix + * + * Test that IComposerClient::getDataspaceSaturationMatrix returns + * Error::BAD_PARAMETER when passed a dataspace other than + * Dataspace::SRGB_LINEAR + */ +TEST_F(GraphicsComposerHidlTest, GetDataspaceSaturationMatrixBadParameter) { + mComposerClient->getRaw()->getDataspaceSaturationMatrix( + Dataspace::UNKNOWN, + [&](const auto& tmpError, const auto&) { ASSERT_EQ(Error::BAD_PARAMETER, tmpError); }); +} + /** * Test IComposerClient::getColorMode_2_2. */ @@ -354,10 +586,22 @@ TEST_F(GraphicsComposerHidlTest, GetColorMode_2_2) { EXPECT_NE(modes.cend(), nativeMode); } -/** - * Test IComposerClient::getRenderIntent. +/* + * Test IComposerClient::getColorMode_2_2 + * + * Test that IComposerClient::getColorMode returns Error::BAD_DISPLAY when + * passed an invalid display handle */ -TEST_F(GraphicsComposerHidlTest, GetRenderIntent) { +TEST_F(GraphicsComposerHidlTest, GetColorMode_2_2BadDisplay) { + mComposerClient->getRaw()->getColorModes_2_2( + mInvalidDisplayId, + [&](const auto& tmpError, const auto&) { ASSERT_EQ(Error::BAD_DISPLAY, tmpError); }); +} + +/** + * Test IComposerClient::getRenderIntents. + */ +TEST_F(GraphicsComposerHidlTest, GetRenderIntents) { std::vector modes = mComposerClient->getColorModes(mPrimaryDisplay); for (auto mode : modes) { std::vector intents = @@ -381,6 +625,33 @@ TEST_F(GraphicsComposerHidlTest, GetRenderIntent) { } } +/* + * Test IComposerClient::getRenderIntents + * + * Test that IComposerClient::getRenderIntent returns Error::BAD_DISPLAY when + * passed an invalid display handle + */ +TEST_F(GraphicsComposerHidlTest, GetRenderIntentsBadDisplay) { + std::vector modes = mComposerClient->getColorModes(mPrimaryDisplay); + for (auto mode : modes) { + mComposerClient->getRaw()->getRenderIntents( + mInvalidDisplayId, mode, + [&](const auto& tmpError, const auto&) { EXPECT_EQ(Error::BAD_DISPLAY, tmpError); }); + } +} + +/* + * Test IComposerClient::getRenderIntents + * + * Test that IComposerClient::getRenderIntents returns Error::BAD_PARAMETER when + * pased either an invalid Color mode or an invalid Render Intent + */ +TEST_F(GraphicsComposerHidlTest, GetRenderIntentsBadParameter) { + mComposerClient->getRaw()->getRenderIntents( + mPrimaryDisplay, static_cast(-1), + [&](const auto& tmpError, const auto&) { EXPECT_EQ(Error::BAD_PARAMETER, tmpError); }); +} + /** * Test IComposerClient::setColorMode_2_2. */ @@ -393,6 +664,37 @@ TEST_F(GraphicsComposerHidlTest, SetColorMode_2_2) { mComposerClient->setColorMode(mPrimaryDisplay, mode, intent); } } + + mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::NATIVE, RenderIntent::COLORIMETRIC); +} + +/* + * Test IComposerClient::setColorMode_2_2 + * + * Test that IComposerClient::setColorMode_2_2 returns an Error::BAD_DISPLAY + * when passed an invalid display handle + */ +TEST_F(GraphicsComposerHidlTest, SetColorMode_2_2BadDisplay) { + Error error = mComposerClient->getRaw()->setColorMode_2_2(mInvalidDisplayId, ColorMode::NATIVE, + RenderIntent::COLORIMETRIC); + + ASSERT_EQ(Error::BAD_DISPLAY, error); +} + +/* + * Test IComposerClient::setColorMode_2_2 + * + * Test that IComposerClient::setColorMode_2_2 returns Error::BAD_PARAMETER when + * passed an invalid Color mode or an invalid render intent + */ +TEST_F(GraphicsComposerHidlTest, SetColorMode_2_2BadParameter) { + Error colorModeError = mComposerClient->getRaw()->setColorMode_2_2( + mPrimaryDisplay, static_cast(-1), RenderIntent::COLORIMETRIC); + EXPECT_EQ(Error::BAD_PARAMETER, colorModeError); + + Error renderIntentError = mComposerClient->getRaw()->setColorMode_2_2( + mPrimaryDisplay, ColorMode::NATIVE, static_cast(-1)); + EXPECT_EQ(Error::BAD_PARAMETER, renderIntentError); } } // namespace From bfbaf8400e2379b3db71a1cc356d7c5dd7ec3b18 Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Fri, 31 Aug 2018 14:13:36 -0700 Subject: [PATCH 091/718] [ConfigStore] Add getCompositionPreference. In order to tell renderer to render into the best color space with the right pixel format. We need to expose it as a composition preference. This patch adds ConfigStore API to query such preference. Typically, this API will return the default data space of a color space that the panel is calibrated to, with the default pixel format that hardware composer can composite to efficiently. However, devices can make tradeoff between data space and pixel format. BUG: 113530681 Test: Build, flash, boot Change-Id: I0ea09e21e70843b50157ec617c87a42bb4ff7332 --- configstore/1.2/Android.bp | 1 + configstore/1.2/ISurfaceFlingerConfigs.hal | 25 +++++++++++++++++++ .../1.2/default/SurfaceFlingerConfigs.cpp | 23 +++++++++++++++++ .../1.2/default/SurfaceFlingerConfigs.h | 1 + configstore/1.2/default/surfaceflinger.mk | 8 ++++++ 5 files changed, 58 insertions(+) diff --git a/configstore/1.2/Android.bp b/configstore/1.2/Android.bp index a20eb34dd8..cc5644ca80 100644 --- a/configstore/1.2/Android.bp +++ b/configstore/1.2/Android.bp @@ -12,6 +12,7 @@ hidl_interface { interfaces: [ "android.hardware.configstore@1.1", "android.hardware.configstore@1.0", + "android.hardware.graphics.common@1.1", "android.hidl.base@1.0", ], gen_java: true, diff --git a/configstore/1.2/ISurfaceFlingerConfigs.hal b/configstore/1.2/ISurfaceFlingerConfigs.hal index c32cc82910..c8791553a2 100644 --- a/configstore/1.2/ISurfaceFlingerConfigs.hal +++ b/configstore/1.2/ISurfaceFlingerConfigs.hal @@ -15,6 +15,8 @@ */ package android.hardware.configstore@1.2; +import android.hardware.graphics.common@1.1::Dataspace; +import android.hardware.graphics.common@1.1::PixelFormat; import @1.1::ISurfaceFlingerConfigs; import @1.0::OptionalBool; @@ -30,4 +32,27 @@ interface ISurfaceFlingerConfigs extends @1.1::ISurfaceFlingerConfigs { * return true. */ useColorManagement() generates (OptionalBool value); + + /** + * Returns the default data space and default pixel format that + * SurfaceFlinger expects to receive and output. + * To determine the default data space and default pixel format, + * there are a few things we recommend to consider: + * + * 1. Hardware composer's capability to composite contents with the + * data space and pixel format efficiently; + * 2. Hardware composer's ability to composite contents when sRGB contents + * and the chosen data space contents coexist; + * 3. For better blending, consider using pixel format where the alpha + * channel has as many bits as the RGB color channel. + * + * @return dataSpace is the default data space that SurfaceFlinger expects. + * The data space must not be Dataspace::UNKNOWN, if unspecified, + * the default data space is Dataspace::V0_SRGB; + * @return pixelFormat is the default pixel format that SurfaceFlinger + * expects. If unspecified, the default pixel format is + * PixelFormat::RGBA_8888. + */ + getCompositionPreference() + generates (Dataspace dataSpace, PixelFormat pixelFormat); }; diff --git a/configstore/1.2/default/SurfaceFlingerConfigs.cpp b/configstore/1.2/default/SurfaceFlingerConfigs.cpp index c7bd567fef..ae19dc0799 100644 --- a/configstore/1.2/default/SurfaceFlingerConfigs.cpp +++ b/configstore/1.2/default/SurfaceFlingerConfigs.cpp @@ -17,6 +17,7 @@ #include "SurfaceFlingerConfigs.h" #include +#include #include namespace android { @@ -25,6 +26,9 @@ namespace configstore { namespace V1_2 { namespace implementation { +using ::android::hardware::graphics::common::V1_1::Dataspace; +using ::android::hardware::graphics::common::V1_1::PixelFormat; + // ::android::hardware::configstore::V1_0::ISurfaceFlingerConfigs implementation. Return SurfaceFlingerConfigs::vsyncEventPhaseOffsetNs(vsyncEventPhaseOffsetNs_cb _hidl_cb) { #ifdef VSYNC_EVENT_PHASE_OFFSET_NS @@ -199,6 +203,25 @@ Return SurfaceFlingerConfigs::useColorManagement(useColorManagement_cb _hi return Void(); } +#ifdef COMPOSITION_DATA_SPACE +static_assert(COMPOSITION_DATA_SPACE != 0, "Expected composition data space must not be UNKNOWN"); +#endif + +Return SurfaceFlingerConfigs::getCompositionPreference(getCompositionPreference_cb _hidl_cb) { + Dataspace dataSpace = Dataspace::V0_SRGB; + PixelFormat pixelFormat = PixelFormat::RGBA_8888; + +#ifdef COMPOSITION_DATA_SPACE + dataSpace = static_cast(COMPOSITION_DATA_SPACE); +#endif + +#ifdef COMPOSITION_PIXEL_FORMAT + pixelFormat = static_cast(COMPOSITION_PIXEL_FORMAT); +#endif + _hidl_cb(dataSpace, pixelFormat); + return Void(); +} + } // namespace implementation } // namespace V1_2 } // namespace configstore diff --git a/configstore/1.2/default/SurfaceFlingerConfigs.h b/configstore/1.2/default/SurfaceFlingerConfigs.h index fe787890f0..7dd8f6d2c9 100644 --- a/configstore/1.2/default/SurfaceFlingerConfigs.h +++ b/configstore/1.2/default/SurfaceFlingerConfigs.h @@ -52,6 +52,7 @@ struct SurfaceFlingerConfigs : public ISurfaceFlingerConfigs { // ::android::hardware::configstore::V1_2::ISurfaceFlingerConfigs follow implementation. Return useColorManagement(useColorManagement_cb _hidl_cb) override; + Return getCompositionPreference(getCompositionPreference_cb _hidl_cb) override; }; } // namespace implementation diff --git a/configstore/1.2/default/surfaceflinger.mk b/configstore/1.2/default/surfaceflinger.mk index 70be4501e1..f3239996d9 100644 --- a/configstore/1.2/default/surfaceflinger.mk +++ b/configstore/1.2/default/surfaceflinger.mk @@ -58,3 +58,11 @@ endif ifeq ($(TARGET_USE_COLOR_MANAGEMENT),true) LOCAL_CFLAGS += -DUSE_COLOR_MANAGEMENT endif + +ifneq ($(SF_COMPOSITION_DATA_SPACE),) + LOCAL_CFLAGS += -DCOMPOSITION_DATA_SPACE=$(SF_COMPOSITION_DATA_SPACE) +endif + +ifneq ($(SF_COMPOSITION_PIXEL_FORMAT),) + LOCAL_CFLAGS += -DCOMPOSITION_PIXEL_FORMAT=$(SF_COMPOSITION_PIXEL_FORMAT) +endif From 725a9194be79c3ec3bcfbce8bbe84dd6b55ddfbc Mon Sep 17 00:00:00 2001 From: Zachary Iqbal Date: Mon, 10 Sep 2018 14:50:16 -0700 Subject: [PATCH 092/718] Add the biometrics face HAL to the compatibility matrix. Bug: 114777920 Test: Built and booted locally. Change-Id: Ic489b931b750ef1dfcfd5249c4eeb2aef52557b1 --- compatibility_matrices/compatibility_matrix.current.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml index b9cb093213..73afb1bb35 100644 --- a/compatibility_matrices/compatibility_matrix.current.xml +++ b/compatibility_matrices/compatibility_matrix.current.xml @@ -47,6 +47,14 @@ default
+ + android.hardware.biometrics.face + 1.0 + + IBiometricsFace + default + + android.hardware.biometrics.fingerprint 2.1 From c72501342a0615c78d740e1c0e2c7e7d33b2d3ea Mon Sep 17 00:00:00 2001 From: Jordan Jozwiak Date: Thu, 6 Sep 2018 14:03:48 -0700 Subject: [PATCH 093/718] Add the INFO_DRIVER_SEAT property. Bug: b/113356861 Test: Build and install. Change-Id: I07963fd94aca1a2e83d968f85daa78be7ab90fd9 (cherry picked from commit e4d470dc3adc5ba2b35abcdc61e37927953c36d4) --- .../vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h | 10 ++++++++++ 1 file changed, 10 insertions(+) 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 74bbfb44bf..e0b54d069b 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 @@ -225,6 +225,16 @@ const ConfigDeclaration kVehicleProperties[]{ }, .initialValue = {.floatValues = {0.0f}}}, + {.config = + { + .prop = toInt(VehicleProperty::INFO_DRIVER_SEAT), + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::STATIC, + // this was a zoned property on an old vhal, but it is meant to be global + .areaConfigs = {VehicleAreaConfig{.areaId = (0)}}, + }, + .initialValue = {.int32Values = {SEAT_1_LEFT}}}, + {.config = { .prop = toInt(VehicleProperty::PERF_ODOMETER), From 73e63e662c4638091f0cd0efb11dce47341f817d Mon Sep 17 00:00:00 2001 From: mike dooley Date: Wed, 22 Aug 2018 15:00:09 +0200 Subject: [PATCH 094/718] Adding getModelState API to sound trigger Test: built android Bug-Id: 70206501 Change-Id: I8f45fd86bc14544c676c94daeea71a0ecebdbe03 --- .../2.0/default/SoundTriggerHalImpl.cpp | 2 +- .../2.0/default/SoundTriggerHalImpl.h | 5 +- soundtrigger/2.2/Android.bp | 20 ++++ soundtrigger/2.2/ISoundTriggerHw.hal | 40 +++++++ soundtrigger/2.2/default/Android.mk | 50 ++++++++ soundtrigger/2.2/default/SoundTriggerHw.cpp | 110 +++++++++++++++++ soundtrigger/2.2/default/SoundTriggerHw.h | 113 ++++++++++++++++++ soundtrigger/2.2/vts/functional/Android.bp | 29 +++++ .../VtsHalSoundtriggerV2_2TargetTest.cpp | 101 ++++++++++++++++ 9 files changed, 468 insertions(+), 2 deletions(-) create mode 100644 soundtrigger/2.2/Android.bp create mode 100644 soundtrigger/2.2/ISoundTriggerHw.hal create mode 100644 soundtrigger/2.2/default/Android.mk create mode 100644 soundtrigger/2.2/default/SoundTriggerHw.cpp create mode 100644 soundtrigger/2.2/default/SoundTriggerHw.h create mode 100644 soundtrigger/2.2/vts/functional/Android.bp create mode 100644 soundtrigger/2.2/vts/functional/VtsHalSoundtriggerV2_2TargetTest.cpp diff --git a/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp b/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp index 612772cc63..2de35e8a0d 100644 --- a/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp +++ b/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp @@ -247,7 +247,7 @@ exit: } SoundTriggerHalImpl::SoundTriggerHalImpl() - : mModuleName("primary"), mHwDevice(NULL), mNextModelId(1) {} + : mModuleName("primary"), mNextModelId(1), mHwDevice(NULL) {} void SoundTriggerHalImpl::onFirstRef() { const hw_module_t* mod; diff --git a/soundtrigger/2.0/default/SoundTriggerHalImpl.h b/soundtrigger/2.0/default/SoundTriggerHalImpl.h index 5a9f0e19af..fbe24c15d9 100644 --- a/soundtrigger/2.0/default/SoundTriggerHalImpl.h +++ b/soundtrigger/2.0/default/SoundTriggerHalImpl.h @@ -167,8 +167,11 @@ class SoundTriggerHalImpl : public RefBase { static void recognitionCallback(struct sound_trigger_recognition_event* halEvent, void* cookie); const char* mModuleName; - struct sound_trigger_hw_device* mHwDevice; + volatile atomic_uint_fast32_t mNextModelId; + + protected: + struct sound_trigger_hw_device* mHwDevice; DefaultKeyedVector > mClients; Mutex mLock; }; diff --git a/soundtrigger/2.2/Android.bp b/soundtrigger/2.2/Android.bp new file mode 100644 index 0000000000..0a7c2d80ba --- /dev/null +++ b/soundtrigger/2.2/Android.bp @@ -0,0 +1,20 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +hidl_interface { + name: "android.hardware.soundtrigger@2.2", + root: "android.hardware", + vndk: { + enabled: true, + }, + srcs: [ + "ISoundTriggerHw.hal", + ], + interfaces: [ + "android.hardware.audio.common@2.0", + "android.hardware.soundtrigger@2.0", + "android.hardware.soundtrigger@2.1", + "android.hidl.base@1.0", + ], + gen_java: false, +} + diff --git a/soundtrigger/2.2/ISoundTriggerHw.hal b/soundtrigger/2.2/ISoundTriggerHw.hal new file mode 100644 index 0000000000..c5033588de --- /dev/null +++ b/soundtrigger/2.2/ISoundTriggerHw.hal @@ -0,0 +1,40 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.soundtrigger@2.2; + +import @2.1::ISoundTriggerHw; +import @2.0::SoundModelHandle; +import @2.0::ISoundTriggerHwCallback.RecognitionEvent; + +/** + * SoundTrigger HAL interface. Used for hardware recognition of hotwords. + */ +interface ISoundTriggerHw extends @2.1::ISoundTriggerHw { + + /** + * Get the state of a given model. + * The model state is returned as a RecognitionEvent. + * @param modelHandle The handle of the sound model to use for recognition + * @return retval Operation completion status: 0 in case of success, + * -ENOSYS in case of invalid model handle, + * -ENOMEM in case of memory allocation failure, + * -ENODEV in case of initialization error. + * @return state RecognitionEvent in case of success + */ + getModelState(SoundModelHandle modelHandle) + generates (int32_t retval, RecognitionEvent state); +}; diff --git a/soundtrigger/2.2/default/Android.mk b/soundtrigger/2.2/default/Android.mk new file mode 100644 index 0000000000..8c0f653d8d --- /dev/null +++ b/soundtrigger/2.2/default/Android.mk @@ -0,0 +1,50 @@ +# +# Copyright (C) 2018 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE := android.hardware.soundtrigger@2.2-impl +LOCAL_VENDOR_MODULE := true +LOCAL_MODULE_RELATIVE_PATH := hw +LOCAL_SRC_FILES := \ + SoundTriggerHw.cpp + +LOCAL_CFLAGS := -Wall -Werror + +LOCAL_SHARED_LIBRARIES := \ + libhardware \ + libhidlbase \ + libhidlmemory \ + libhidltransport \ + liblog \ + libutils \ + android.hardware.soundtrigger@2.2 \ + android.hardware.soundtrigger@2.1 \ + android.hardware.soundtrigger@2.0 \ + android.hardware.soundtrigger@2.0-core \ + android.hidl.allocator@1.0 \ + android.hidl.memory@1.0 + +LOCAL_C_INCLUDE_DIRS := $(LOCAL_PATH) + +ifeq ($(strip $(AUDIOSERVER_MULTILIB)),) +LOCAL_MULTILIB := 32 +else +LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB) +endif + +include $(BUILD_SHARED_LIBRARY) diff --git a/soundtrigger/2.2/default/SoundTriggerHw.cpp b/soundtrigger/2.2/default/SoundTriggerHw.cpp new file mode 100644 index 0000000000..90faf33598 --- /dev/null +++ b/soundtrigger/2.2/default/SoundTriggerHw.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "SoundTriggerHw" + +#include "SoundTriggerHw.h" + +#include +#include + +namespace android { +namespace hardware { +namespace soundtrigger { +namespace V2_2 { +namespace implementation { + +Return SoundTriggerHw::getModelState_2_2(int32_t modelHandle, getModelState_cb hidl_cb) { + sp client; + if (mHwDevice == NULL) { + hidl_cb(-ENODEV, NULL); + return Void(); + } + + { + AutoMutex lock(mLock); + client = mClients.valueFor(modelHandle); + if (client == 0) { + hidl_cb(-ENOSYS, NULL); + return Void(); + } + } + + if (mHwDevice->get_model_state == NULL) { + ALOGE("Failed to get model state from device, no such method"); + hidl_cb(-ENODEV, NULL); + return Void(); + } + + // Get the state from the device (as a recognition event) + struct sound_trigger_recognition_event* event = + mHwDevice->get_model_state(mHwDevice, client->getHalHandle()); + if (event == NULL) { + ALOGE("Failed to get model state from device"); + hidl_cb(-ENODEV, NULL); + return Void(); + } + + // Allocate shared memory to return to the client + sp alloc = IAllocator::getService("ashmem"); + if (alloc == 0) { + ALOGE("Failed to retrieve ashmem allocator service"); + free(event); + hidl_cb(-ENOMEM, NULL); + return Void(); + } + // Note: Only generic recognition events are currently supported + int n_bytes = sizeof(struct sound_trigger_generic_recognition_event); + bool success = false; + const hidl_memory& mem; + Return r = ashmem->allocate(n_bytes, [&](bool s, const hidl_memory& m) { + success = s; + if (success) mem = m; + }); + if (r.isOk() && success) { + // Copy the event data to the shared memory + sp memory = mapMemory(mem); + if (memory != 0) { + struct sound_trigger_generic_recognition_event* data = + (struct sound_trigger_generic_recognition_event*)memory->getPointer(); + memory->update(); + *data = *event; + memory->commit(); + + // Return the event memory via this callback + hidl_cb(0, memory); + } else { + ALOGE("Failed to map memory for recognition event"); + hidl_cb(-ENOMEM, NULL); + } + } else { + ALOGE("Failed to allocate %d bytes from ashmem allocator service", n_bytes); + hidl_cb(-ENOMEM, NULL); + } + + free(event); + return Void(); +} + +ISoundTriggerHw* HIDL_FETCH_ISoundTriggerHw(const char* /* name */) { + return (new SoundTriggerHw())->getInterface(); +} + +} // namespace implementation +} // namespace V2_2 +} // namespace soundtrigger +} // namespace hardware +} // namespace android diff --git a/soundtrigger/2.2/default/SoundTriggerHw.h b/soundtrigger/2.2/default/SoundTriggerHw.h new file mode 100644 index 0000000000..e7e8be9417 --- /dev/null +++ b/soundtrigger/2.2/default/SoundTriggerHw.h @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_SOUNDTRIGGER_V2_2_SOUNDTRIGGERHW_H +#define ANDROID_HARDWARE_SOUNDTRIGGER_V2_2_SOUNDTRIGGERHW_H + +#include +#include +#include + +namespace android { +namespace hardware { +namespace soundtrigger { +namespace V2_2 { +namespace implementation { + +using ::android::sp; +using ::android::hardware::Return; + +struct SoundTriggerHw : public V2_1::implementation::SoundTriggerHalImpl { + SoundTriggerHw() = default; + ISoundTriggerHw* getInterface() { return new TrampolineSoundTriggerHw_2_2(this); } + + protected: + virtual ~SoundTriggerHw() = default; + + Return> getModelState_2_2( + V2_0::SoundModelHandle modelHandle modelHandle); + + private: + struct TrampolineSoundTriggerHw_2_2 : public ISoundTriggerHw { + explicit TrampolineSoundTriggerHw_2_2(sp impl) : mImpl(impl) {} + + // Methods from ::android::hardware::soundtrigger::V2_0::ISoundTriggerHw follow. + Return getProperties(getProperties_cb _hidl_cb) override { + return mImpl->getProperties(_hidl_cb); + } + Return loadSoundModel(const V2_0::ISoundTriggerHw::SoundModel& soundModel, + const sp& callback, + int32_t cookie, loadSoundModel_cb _hidl_cb) override { + return mImpl->loadSoundModel(soundModel, callback, cookie, _hidl_cb); + } + Return loadPhraseSoundModel(const V2_0::ISoundTriggerHw::PhraseSoundModel& soundModel, + const sp& callback, + int32_t cookie, + loadPhraseSoundModel_cb _hidl_cb) override { + return mImpl->loadPhraseSoundModel(soundModel, callback, cookie, _hidl_cb); + } + Return unloadSoundModel(V2_0::SoundModelHandle modelHandle) override { + return mImpl->unloadSoundModel(modelHandle); + } + Return startRecognition(int32_t modelHandle, + const V2_0::ISoundTriggerHw::RecognitionConfig& config, + const sp& /*callback*/, + int32_t /*cookie*/) override { + return mImpl->startRecognition(modelHandle, config); + } + Return stopRecognition(V2_0::SoundModelHandle modelHandle) override { + return mImpl->stopRecognition(modelHandle); + } + Return stopAllRecognitions() override { return mImpl->stopAllRecognitions(); } + + // Methods from V2_1::ISoundTriggerHw follow. + Return loadSoundModel_2_1(const V2_1::ISoundTriggerHw::SoundModel& soundModel, + const sp& callback, + int32_t cookie, loadSoundModel_2_1_cb _hidl_cb) override { + return mImpl->loadSoundModel_2_1(soundModel, callback, cookie, _hidl_cb); + } + Return loadPhraseSoundModel_2_1( + const V2_1::ISoundTriggerHw::PhraseSoundModel& soundModel, + const sp& callback, int32_t cookie, + loadPhraseSoundModel_2_1_cb _hidl_cb) override { + return mImpl->loadPhraseSoundModel_2_1(soundModel, callback, cookie, _hidl_cb); + } + Return startRecognition_2_1(int32_t modelHandle, + const V2_1::ISoundTriggerHw::RecognitionConfig& config, + const sp& /*callback*/, + int32_t /*cookie*/) override { + return mImpl->startRecognition_2_1(modelHandle, config); + } + + // Methods from V2_2::ISoundTriggerHw follow. + Return getModelState(int32_t modelHandle, getModelState_cb hidl_cb) override { + return mImpl->getModelState_2_2(modelHandle, hidl_cb); + } + + private: + sp mImpl; + }; +}; + +extern "C" ISoundTriggerHw* HIDL_FETCH_ISoundTriggerHw(const char* name); + +} // namespace implementation +} // namespace V2_2 +} // namespace soundtrigger +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_SOUNDTRIGGER_V2_2_SOUNDTRIGGERHW_H diff --git a/soundtrigger/2.2/vts/functional/Android.bp b/soundtrigger/2.2/vts/functional/Android.bp new file mode 100644 index 0000000000..adbd0188b4 --- /dev/null +++ b/soundtrigger/2.2/vts/functional/Android.bp @@ -0,0 +1,29 @@ +// +// Copyright (C) 2018 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +cc_test { + name: "VtsHalSoundtriggerV2_2TargetTest", + defaults: ["VtsHalTargetTestDefaults"], + srcs: ["VtsHalSoundtriggerV2_2TargetTest.cpp"], + static_libs: [ + "android.hidl.allocator@1.0", + "android.hidl.memory@1.0", + "android.hardware.soundtrigger@2.0", + "android.hardware.soundtrigger@2.1", + "android.hardware.soundtrigger@2.2", + "libhidlmemory" + ], +} diff --git a/soundtrigger/2.2/vts/functional/VtsHalSoundtriggerV2_2TargetTest.cpp b/soundtrigger/2.2/vts/functional/VtsHalSoundtriggerV2_2TargetTest.cpp new file mode 100644 index 0000000000..ed5149fe7d --- /dev/null +++ b/soundtrigger/2.2/vts/functional/VtsHalSoundtriggerV2_2TargetTest.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "SoundTriggerHidlHalTest" +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +using ::android::sp; +using ::android::hardware::Return; +using ::android::hardware::soundtrigger::V2_0::ISoundTriggerHwCallback; +using ::android::hardware::soundtrigger::V2_0::SoundModelHandle; +using ::android::hardware::soundtrigger::V2_2::ISoundTriggerHw; + +// Test environment for SoundTrigger HIDL HAL. +class SoundTriggerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { + public: + // get the test environment singleton + static SoundTriggerHidlEnvironment* Instance() { + static SoundTriggerHidlEnvironment* instance = new SoundTriggerHidlEnvironment; + return instance; + } + + void registerTestServices() override { registerTestService(); } + + private: + SoundTriggerHidlEnvironment() {} +}; + +// The main test class for Sound Trigger HIDL HAL. +class SoundTriggerHidlTest : public ::testing::VtsHalHidlTargetTestBase { + public: + void SetUp() override { + mSoundTriggerHal = ::testing::VtsHalHidlTargetTestBase::getService( + SoundTriggerHidlEnvironment::Instance()->getServiceName()); + ASSERT_NE(nullptr, mSoundTriggerHal.get()); + } + + static void SetUpTestCase() { srand(1234); } + + void TearDown() override {} + + protected: + sp mSoundTriggerHal; +}; + +/** + * Test ISoundTriggerHw::getModelState() method + * + * Verifies that: + * - the implementation returns -EINVAL with invalid model handle + * + */ +TEST_F(SoundTriggerHidlTest, GetModelStateInvalidModel) { + int ret = android::OK; + ISoundTriggerHwCallback::RecognitionEvent event; + SoundModelHandle handle = 0; + Return hidlReturn = + mSoundTriggerHal->getModelState(handle, [&](int32_t retval, auto res) { + ret = retval; + event = res; + }); + + EXPECT_TRUE(hidlReturn.isOk()); + EXPECT_EQ(-ENOSYS, ret); +} + +int main(int argc, char** argv) { + ::testing::AddGlobalTestEnvironment(SoundTriggerHidlEnvironment::Instance()); + ::testing::InitGoogleTest(&argc, argv); + SoundTriggerHidlEnvironment::Instance()->init(&argc, argv); + int status = RUN_ALL_TESTS(); + ALOGI("Test result = %d", status); + return status; +} From d3feb3d62c139f08879bbb7f7a0513d593dafcc0 Mon Sep 17 00:00:00 2001 From: Shuzhen Wang Date: Fri, 17 Aug 2018 13:52:40 -0700 Subject: [PATCH 095/718] Camera: Add support for physical camera characteristics query - Add version 3.5 for ICameraDevice for physical camera characteristics query. - Add version 3.5 for ICameraDeviceSession to work around HIDL versioning bug. Test: Camera CTS Bug: 79523700 Change-Id: I8df6cdd4ee6ac5755758510c0dc1ea1cec31aa73 --- camera/common/1.0/default/CameraModule.cpp | 35 ++++++ .../common/1.0/default/include/CameraModule.h | 2 + camera/device/3.2/default/CameraDevice.cpp | 8 +- camera/device/3.2/default/CameraDevice_3_2.h | 54 +++++++-- camera/device/3.5/Android.bp | 23 ++++ camera/device/3.5/ICameraDevice.hal | 62 ++++++++++ camera/device/3.5/ICameraDeviceSession.hal | 29 +++++ camera/device/3.5/default/Android.bp | 53 +++++++++ camera/device/3.5/default/CameraDevice.cpp | 86 ++++++++++++++ .../device_v3_5_impl/CameraDevice_3_5.h | 107 ++++++++++++++++++ camera/provider/2.4/Android.bp | 1 + camera/provider/2.4/default/Android.bp | 5 + .../provider/2.4/default/CameraProvider.cpp | 48 ++++---- 13 files changed, 484 insertions(+), 29 deletions(-) create mode 100644 camera/device/3.5/Android.bp create mode 100644 camera/device/3.5/ICameraDevice.hal create mode 100644 camera/device/3.5/ICameraDeviceSession.hal create mode 100644 camera/device/3.5/default/Android.bp create mode 100644 camera/device/3.5/default/CameraDevice.cpp create mode 100644 camera/device/3.5/default/include/device_v3_5_impl/CameraDevice_3_5.h diff --git a/camera/common/1.0/default/CameraModule.cpp b/camera/common/1.0/default/CameraModule.cpp index dc4e0f01ff..eb840a74f4 100644 --- a/camera/common/1.0/default/CameraModule.cpp +++ b/camera/common/1.0/default/CameraModule.cpp @@ -319,6 +319,41 @@ int CameraModule::getCameraInfo(int cameraId, struct camera_info *info) { return OK; } +int CameraModule::getPhysicalCameraInfo(int physicalCameraId, camera_metadata_t **physicalInfo) { + ATRACE_CALL(); + Mutex::Autolock lock(mCameraInfoLock); + if (physicalCameraId < 0) { + ALOGE("%s: Invalid physical camera ID %d", __FUNCTION__, physicalCameraId); + return -EINVAL; + } + + // Only query physical camera info for 2.5 version for newer + int apiVersion = mModule->common.module_api_version; + if (apiVersion < CAMERA_MODULE_API_VERSION_2_5) { + ALOGE("%s: Module version must be at least 2.5 to handle getPhysicalCameraInfo", + __FUNCTION__); + return -ENODEV; + } + + ssize_t index = mPhysicalCameraInfoMap.indexOfKey(physicalCameraId); + if (index == NAME_NOT_FOUND) { + // Get physical camera characteristics, and cache it + camera_metadata_t *info = nullptr; + ATRACE_BEGIN("camera_module->get_physical_camera_info"); + int ret = mModule->get_physical_camera_info(physicalCameraId, &info); + ATRACE_END(); + if (ret != 0) { + return ret; + } + + index = mPhysicalCameraInfoMap.add(physicalCameraId, info); + } + + assert(index != NAME_NOT_FOUND); + *physicalInfo = mPhysicalCameraInfoMap[index]; + return OK; +} + int CameraModule::getDeviceVersion(int cameraId) { ssize_t index = mDeviceVersionMap.indexOfKey(cameraId); if (index == NAME_NOT_FOUND) { diff --git a/camera/common/1.0/default/include/CameraModule.h b/camera/common/1.0/default/include/CameraModule.h index deebd09480..ed853bf85f 100644 --- a/camera/common/1.0/default/include/CameraModule.h +++ b/camera/common/1.0/default/include/CameraModule.h @@ -65,6 +65,7 @@ public: void *getDso(); // Only used by CameraProvider void removeCamera(int cameraId); + int getPhysicalCameraInfo(int physicalCameraId, camera_metadata_t **physicalInfo); private: // Derive camera characteristics keys defined after HAL device version @@ -76,6 +77,7 @@ private: camera_module_t *mModule; KeyedVector mCameraInfoMap; KeyedVector mDeviceVersionMap; + KeyedVector mPhysicalCameraInfoMap; Mutex mCameraInfoLock; }; diff --git a/camera/device/3.2/default/CameraDevice.cpp b/camera/device/3.2/default/CameraDevice.cpp index dfbb9768a4..2e80ce8631 100644 --- a/camera/device/3.2/default/CameraDevice.cpp +++ b/camera/device/3.2/default/CameraDevice.cpp @@ -101,7 +101,7 @@ Status CameraDevice::getHidlStatus(int status) { } // Methods from ::android::hardware::camera::device::V3_2::ICameraDevice follow. -Return CameraDevice::getResourceCost(getResourceCost_cb _hidl_cb) { +Return CameraDevice::getResourceCost(ICameraDevice::getResourceCost_cb _hidl_cb) { Status status = initStatus(); CameraResourceCost resCost; if (status == Status::OK) { @@ -141,7 +141,8 @@ Return CameraDevice::getResourceCost(getResourceCost_cb _hidl_cb) { return Void(); } -Return CameraDevice::getCameraCharacteristics(getCameraCharacteristics_cb _hidl_cb) { +Return CameraDevice::getCameraCharacteristics( + ICameraDevice::getCameraCharacteristics_cb _hidl_cb) { Status status = initStatus(); CameraMetadata cameraCharacteristics; if (status == Status::OK) { @@ -172,7 +173,8 @@ Return CameraDevice::setTorchMode(TorchMode mode) { return status; } -Return CameraDevice::open(const sp& callback, open_cb _hidl_cb) { +Return CameraDevice::open(const sp& callback, + ICameraDevice::open_cb _hidl_cb) { Status status = initStatus(); sp session = nullptr; diff --git a/camera/device/3.2/default/CameraDevice_3_2.h b/camera/device/3.2/default/CameraDevice_3_2.h index 9534707bd0..f4745337f8 100644 --- a/camera/device/3.2/default/CameraDevice_3_2.h +++ b/camera/device/3.2/default/CameraDevice_3_2.h @@ -51,7 +51,7 @@ using ::android::Mutex; /* * The camera device HAL implementation is opened lazily (via the open call) */ -struct CameraDevice : public ICameraDevice { +struct CameraDevice : public virtual RefBase { // Called by provider HAL. Provider HAL must ensure the uniqueness of // CameraDevice object per cameraId, or there could be multiple CameraDevice // trying to access the same physical camera. @@ -60,7 +60,14 @@ struct CameraDevice : public ICameraDevice { CameraDevice(sp module, const std::string& cameraId, const SortedVector>& cameraDeviceNames); - ~CameraDevice(); + virtual ~CameraDevice(); + + // Retrieve the HIDL interface, split into its own class to avoid inheritance issues when + // dealing with minor version revs and simultaneous implementation and interface inheritance + virtual sp getInterface() { + return new TrampolineDeviceInterface_3_2(this); + } + // Caller must use this method to check if CameraDevice ctor failed bool isInitFailed() { return mInitFail; } // Used by provider HAL to signal external camera disconnected @@ -68,16 +75,16 @@ struct CameraDevice : public ICameraDevice { /* Methods from ::android::hardware::camera::device::V3_2::ICameraDevice follow. */ // The following method can be called without opening the actual camera device - Return getResourceCost(getResourceCost_cb _hidl_cb) override; - Return getCameraCharacteristics(getCameraCharacteristics_cb _hidl_cb) override; - Return setTorchMode(TorchMode mode) override; + Return getResourceCost(ICameraDevice::getResourceCost_cb _hidl_cb); + Return getCameraCharacteristics(ICameraDevice::getCameraCharacteristics_cb _hidl_cb); + Return setTorchMode(TorchMode mode); // Open the device HAL and also return a default capture session - Return open(const sp& callback, open_cb _hidl_cb) override; + Return open(const sp& callback, ICameraDevice::open_cb _hidl_cb); // Forward the dump call to the opened session, or do nothing - Return dumpState(const ::android::hardware::hidl_handle& fd) override; + Return dumpState(const ::android::hardware::hidl_handle& fd); /* End of Methods from ::android::hardware::camera::device::V3_2::ICameraDevice */ protected: @@ -106,6 +113,39 @@ protected: static Status getHidlStatus(int); Status initStatus() const; + +private: + struct TrampolineDeviceInterface_3_2 : public ICameraDevice { + TrampolineDeviceInterface_3_2(sp parent) : + mParent(parent) {} + + virtual Return getResourceCost(V3_2::ICameraDevice::getResourceCost_cb _hidl_cb) + override { + return mParent->getResourceCost(_hidl_cb); + } + + virtual Return getCameraCharacteristics( + V3_2::ICameraDevice::getCameraCharacteristics_cb _hidl_cb) override { + return mParent->getCameraCharacteristics(_hidl_cb); + } + + virtual Return setTorchMode(TorchMode mode) override { + return mParent->setTorchMode(mode); + } + + virtual Return open(const sp& callback, + V3_2::ICameraDevice::open_cb _hidl_cb) override { + return mParent->open(callback, _hidl_cb); + } + + virtual Return dumpState(const hidl_handle& fd) override { + return mParent->dumpState(fd); + } + + private: + sp mParent; + }; + }; } // namespace implementation diff --git a/camera/device/3.5/Android.bp b/camera/device/3.5/Android.bp new file mode 100644 index 0000000000..a4e9ee2243 --- /dev/null +++ b/camera/device/3.5/Android.bp @@ -0,0 +1,23 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +hidl_interface { + name: "android.hardware.camera.device@3.5", + root: "android.hardware", + vndk: { + enabled: true, + }, + srcs: [ + "ICameraDevice.hal", + "ICameraDeviceSession.hal", + ], + interfaces: [ + "android.hardware.camera.common@1.0", + "android.hardware.camera.device@3.2", + "android.hardware.camera.device@3.3", + "android.hardware.camera.device@3.4", + "android.hardware.graphics.common@1.0", + "android.hidl.base@1.0", + ], + gen_java: false, +} + diff --git a/camera/device/3.5/ICameraDevice.hal b/camera/device/3.5/ICameraDevice.hal new file mode 100644 index 0000000000..e7e8dd343f --- /dev/null +++ b/camera/device/3.5/ICameraDevice.hal @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.camera.device@3.5; + +import android.hardware.camera.common@1.0::Status; +import @3.2::CameraMetadata; +import @3.2::ICameraDevice; + +/** + * Camera device interface + * + * Supports the android.hardware.Camera API, and the android.hardware.camera2 + * API at LIMITED or better hardware level. + * + */ +interface ICameraDevice extends @3.2::ICameraDevice { + + /** + * getPhysicalCameraCharacteristics: + * + * Return the static camera information for a physical camera ID backing + * this logical camera device. This information may not change between consecutive calls. + * + * Note that HAL must support this function for physical camera IDs that are + * not exposed via ICameraProvider::getCameraIdList(). + * + * @return status Status code for the operation, one of: + * OK: + * On a successful query of the camera device characteristics + * INTERNAL_ERROR: + * The camera device cannot be opened due to an internal + * error. + * CAMERA_DISCONNECTED: + * An external camera device has been disconnected, and is no longer + * available. This camera device interface is now stale, and a new + * instance must be acquired if the device is reconnected. All + * subsequent calls on this interface must return + * CAMERA_DISCONNECTED. + * + * @return cameraCharacteristics + * The static metadata for this logical camera device's physical device, or an empty + * metadata structure if status is not OK. + * + */ + getPhysicalCameraCharacteristics(string physicalCameraId) + generates (Status status, CameraMetadata cameraCharacteristics); + +}; diff --git a/camera/device/3.5/ICameraDeviceSession.hal b/camera/device/3.5/ICameraDeviceSession.hal new file mode 100644 index 0000000000..84066851e9 --- /dev/null +++ b/camera/device/3.5/ICameraDeviceSession.hal @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.camera.device@3.5; + +import android.hardware.camera.common@1.0::Status; +import @3.4::ICameraDeviceSession; + +/** + * Camera device active session interface. + * + * Obtained via ICameraDevice::open(), this interface contains the methods to + * configure and request captures from an active camera device. + */ +interface ICameraDeviceSession extends @3.4::ICameraDeviceSession { +}; diff --git a/camera/device/3.5/default/Android.bp b/camera/device/3.5/default/Android.bp new file mode 100644 index 0000000000..341f573b7f --- /dev/null +++ b/camera/device/3.5/default/Android.bp @@ -0,0 +1,53 @@ +// +// Copyright (C) 2018 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +cc_library_headers { + name: "camera.device@3.5-impl_headers", + vendor: true, + export_include_dirs: ["include/device_v3_5_impl"] +} + +cc_library_shared { + name: "camera.device@3.5-impl", + defaults: ["hidl_defaults"], + proprietary: true, + vendor: true, + srcs: [ + "CameraDevice.cpp", + ], + shared_libs: [ + "libhidlbase", + "libhidltransport", + "libutils", + "libcutils", + "camera.device@3.2-impl", + "camera.device@3.3-impl", + "camera.device@3.4-impl", + "android.hardware.camera.device@3.2", + "android.hardware.camera.device@3.3", + "android.hardware.camera.device@3.4", + "android.hardware.camera.device@3.5", + "android.hardware.camera.provider@2.4", + "android.hardware.graphics.mapper@2.0", + "liblog", + "libhardware", + "libcamera_metadata", + ], + static_libs: [ + "android.hardware.camera.common@1.0-helper", + ], + local_include_dirs: ["include/device_v3_5_impl"], +} diff --git a/camera/device/3.5/default/CameraDevice.cpp b/camera/device/3.5/default/CameraDevice.cpp new file mode 100644 index 0000000000..fcd1c96565 --- /dev/null +++ b/camera/device/3.5/default/CameraDevice.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "CamDev@3.5-impl" +#include + +#include "CameraModule.h" +#include "CameraDevice_3_5.h" + +namespace android { +namespace hardware { +namespace camera { +namespace device { +namespace V3_5 { +namespace implementation { + +using namespace ::android::hardware::camera::device; +using ::android::hardware::camera::common::V1_0::Status; +using ::android::hardware::camera::device::V3_2::CameraMetadata; + +CameraDevice::CameraDevice(sp module, const std::string& cameraId, + const SortedVector>& cameraDeviceNames) : + V3_4::implementation::CameraDevice(module, cameraId, cameraDeviceNames) { +} + +CameraDevice::~CameraDevice() { +} + +Return CameraDevice::getPhysicalCameraCharacteristics(const hidl_string& physicalCameraId, + V3_5::ICameraDevice::getPhysicalCameraCharacteristics_cb _hidl_cb) { + Status status = initStatus(); + CameraMetadata cameraCharacteristics; + if (status == Status::OK) { + // Require module 2.5+ version. + if (mModule->getModuleApiVersion() < CAMERA_MODULE_API_VERSION_2_5) { + ALOGE("%s: get_physical_camera_info must be called on camera module 2.5 or newer", + __FUNCTION__); + status = Status::INTERNAL_ERROR; + } else { + char *end; + errno = 0; + long id = strtol(physicalCameraId.c_str(), &end, 0); + if (id > INT_MAX || (errno == ERANGE && id == LONG_MAX) || + id < INT_MIN || (errno == ERANGE && id == LONG_MIN) || + *end != '\0') { + ALOGE("%s: Invalid physicalCameraId %s", __FUNCTION__, physicalCameraId.c_str()); + status = Status::ILLEGAL_ARGUMENT; + } else { + camera_metadata_t *physicalInfo = nullptr; + int ret = mModule->getPhysicalCameraInfo((int)id, &physicalInfo); + if (ret == OK) { + V3_2::implementation::convertToHidl(physicalInfo, &cameraCharacteristics); + } else { + ALOGE("%s: Failed to get physical camera %s info: %s (%d)!", __FUNCTION__, + physicalCameraId.c_str(), strerror(-ret), ret); + status = Status::INTERNAL_ERROR; + } + } + } + } + _hidl_cb(status, cameraCharacteristics); + return Void(); +} + +// End of methods from ::android::hardware::camera::device::V3_2::ICameraDevice. + +} // namespace implementation +} // namespace V3_5 +} // namespace device +} // namespace camera +} // namespace hardware +} // namespace android + diff --git a/camera/device/3.5/default/include/device_v3_5_impl/CameraDevice_3_5.h b/camera/device/3.5/default/include/device_v3_5_impl/CameraDevice_3_5.h new file mode 100644 index 0000000000..f250bc9669 --- /dev/null +++ b/camera/device/3.5/default/include/device_v3_5_impl/CameraDevice_3_5.h @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_CAMERA_DEVICE_V3_5_CAMERADEVICE_H +#define ANDROID_HARDWARE_CAMERA_DEVICE_V3_5_CAMERADEVICE_H + +#include "CameraModule.h" +#include <../../../../3.4/default/include/device_v3_4_impl/CameraDevice_3_4.h> + +#include + +namespace android { +namespace hardware { +namespace camera { +namespace device { +namespace V3_5 { +namespace implementation { + +using namespace ::android::hardware::camera::device; + +using ::android::hardware::camera::common::V1_0::helper::CameraModule; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::hidl_string; +using ::android::hardware::camera::common::V1_0::TorchMode; +using ::android::hardware::camera::common::V1_0::helper::CameraModule; +using ::android::hardware::camera::common::V1_0::Status; +using ::android::sp; + +struct CameraDevice : public V3_4::implementation::CameraDevice { + // Called by provider HAL. + // Provider HAL must ensure the uniqueness of CameraDevice object per cameraId, or there could + // be multiple CameraDevice trying to access the same physical camera. Also, provider will have + // to keep track of all CameraDevice objects in order to notify CameraDevice when the underlying + // camera is detached. + // Delegates nearly all work to CameraDevice_3_4 + CameraDevice(sp module, + const std::string& cameraId, + const SortedVector>& cameraDeviceNames); + virtual ~CameraDevice(); + + virtual sp getInterface() override { + return new TrampolineDeviceInterface_3_5(this); + } + +protected: + Return getPhysicalCameraCharacteristics(const hidl_string& physicalCameraId, + V3_5::ICameraDevice::getPhysicalCameraCharacteristics_cb _hidl_cb); + +private: + struct TrampolineDeviceInterface_3_5 : public ICameraDevice { + TrampolineDeviceInterface_3_5(sp parent) : + mParent(parent) {} + + virtual Return getResourceCost(V3_2::ICameraDevice::getResourceCost_cb _hidl_cb) + override { + return mParent->getResourceCost(_hidl_cb); + } + + virtual Return getCameraCharacteristics( + V3_2::ICameraDevice::getCameraCharacteristics_cb _hidl_cb) override { + return mParent->getCameraCharacteristics(_hidl_cb); + } + + virtual Return setTorchMode(TorchMode mode) override { + return mParent->setTorchMode(mode); + } + + virtual Return open(const sp& callback, + V3_2::ICameraDevice::open_cb _hidl_cb) override { + return mParent->open(callback, _hidl_cb); + } + + virtual Return dumpState(const hidl_handle& fd) override { + return mParent->dumpState(fd); + } + + virtual Return getPhysicalCameraCharacteristics(const hidl_string& physicalCameraId, + V3_5::ICameraDevice::getPhysicalCameraCharacteristics_cb _hidl_cb) override { + return mParent->getPhysicalCameraCharacteristics(physicalCameraId, _hidl_cb); + } + private: + sp mParent; + }; +}; + +} // namespace implementation +} // namespace V3_5 +} // namespace device +} // namespace camera +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_CAMERA_DEVICE_V3_5_CAMERADEVICE_H diff --git a/camera/provider/2.4/Android.bp b/camera/provider/2.4/Android.bp index 63d7fd5dca..27329f3b5d 100644 --- a/camera/provider/2.4/Android.bp +++ b/camera/provider/2.4/Android.bp @@ -14,6 +14,7 @@ hidl_interface { "android.hardware.camera.common@1.0", "android.hardware.camera.device@1.0", "android.hardware.camera.device@3.2", + "android.hardware.camera.device@3.5", "android.hidl.base@1.0", ], gen_java: false, diff --git a/camera/provider/2.4/default/Android.bp b/camera/provider/2.4/default/Android.bp index ae24d78143..de02d78a13 100644 --- a/camera/provider/2.4/default/Android.bp +++ b/camera/provider/2.4/default/Android.bp @@ -14,10 +14,12 @@ cc_library_shared { "android.hardware.camera.device@3.2", "android.hardware.camera.device@3.3", "android.hardware.camera.device@3.4", + "android.hardware.camera.device@3.5", "camera.device@1.0-impl", "camera.device@3.2-impl", "camera.device@3.3-impl", "camera.device@3.4-impl", + "camera.device@3.5-impl", "camera.device@3.4-external-impl", "android.hardware.camera.provider@2.4", "android.hardware.camera.common@1.0", @@ -31,6 +33,7 @@ cc_library_shared { ], header_libs: [ "camera.device@3.4-impl_headers", + "camera.device@3.5-impl_headers", "camera.device@3.4-external-impl_headers" ], static_libs: [ @@ -56,6 +59,7 @@ cc_binary { "android.hardware.camera.device@3.2", "android.hardware.camera.device@3.3", "android.hardware.camera.device@3.4", + "android.hardware.camera.device@3.5", "android.hardware.camera.provider@2.4", "android.hardware.camera.common@1.0", ], @@ -80,6 +84,7 @@ cc_binary { "android.hardware.camera.device@3.2", "android.hardware.camera.device@3.3", "android.hardware.camera.device@3.4", + "android.hardware.camera.device@3.5", "android.hardware.camera.provider@2.4", "android.hardware.camera.common@1.0", ], diff --git a/camera/provider/2.4/default/CameraProvider.cpp b/camera/provider/2.4/default/CameraProvider.cpp index 63139390cb..b69fe1a009 100644 --- a/camera/provider/2.4/default/CameraProvider.cpp +++ b/camera/provider/2.4/default/CameraProvider.cpp @@ -23,6 +23,7 @@ #include "CameraDevice_1_0.h" #include "CameraDevice_3_3.h" #include "CameraDevice_3_4.h" +#include "CameraDevice_3_5.h" #include #include #include @@ -43,6 +44,7 @@ const std::regex kDeviceNameRE("device@([0-9]+\\.[0-9]+)/legacy/(.+)"); const char *kHAL3_2 = "3.2"; const char *kHAL3_3 = "3.3"; const char *kHAL3_4 = "3.4"; +const char *kHAL3_5 = "3.5"; const char *kHAL1_0 = "1.0"; const int kMaxCameraDeviceNameLen = 128; const int kMaxCameraIdLen = 16; @@ -250,7 +252,11 @@ std::string CameraProvider::getHidlDeviceName( int versionMajor = isV1 ? 1 : 3; int versionMinor = isV1 ? 0 : mPreferredHal3MinorVersion; if (deviceVersion == CAMERA_DEVICE_API_VERSION_3_5) { - versionMinor = 4; + if (mModule->getModuleApiVersion() == CAMERA_MODULE_API_VERSION_2_5) { + versionMinor = 5; + } else { + versionMinor = 4; + } } char deviceName[kMaxCameraDeviceNameLen]; snprintf(deviceName, sizeof(deviceName), "device@%d.%d/legacy/%s", @@ -546,21 +552,31 @@ Return CameraProvider::getCameraDeviceInterface_V3_x( return Void(); } - sp device; - if (deviceVersion == kHAL3_4) { + sp deviceImpl; + if (deviceVersion >= kHAL3_4) { ALOGV("Constructing v3.4 camera device"); - sp deviceImpl = - new android::hardware::camera::device::V3_4::implementation::CameraDevice( + if (deviceVersion == kHAL3_4) { + deviceImpl = new android::hardware::camera::device::V3_4::implementation::CameraDevice( mModule, cameraId, mCameraDeviceNames); + } else if (deviceVersion == kHAL3_5) { + deviceImpl = new android::hardware::camera::device::V3_5::implementation::CameraDevice( + mModule, cameraId, mCameraDeviceNames); + } if (deviceImpl == nullptr || deviceImpl->isInitFailed()) { ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraId.c_str()); - device = nullptr; _hidl_cb(Status::INTERNAL_ERROR, nullptr); return Void(); } - - device = deviceImpl; - _hidl_cb (Status::OK, device); + IF_ALOGV() { + deviceImpl->getInterface()->interfaceChain([]( + ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) { + ALOGV("Device interface chain:"); + for (auto iface : interfaceChain) { + ALOGV(" %s", iface.c_str()); + } + }); + } + _hidl_cb (Status::OK, deviceImpl->getInterface()); return Void(); } @@ -570,39 +586,33 @@ Return CameraProvider::getCameraDeviceInterface_V3_x( switch (mPreferredHal3MinorVersion) { case 2: { // Map legacy camera device v3 HAL to Treble camera device HAL v3.2 ALOGV("Constructing v3.2 camera device"); - sp deviceImpl = - new android::hardware::camera::device::V3_2::implementation::CameraDevice( + deviceImpl = new android::hardware::camera::device::V3_2::implementation::CameraDevice( mModule, cameraId, mCameraDeviceNames); if (deviceImpl == nullptr || deviceImpl->isInitFailed()) { ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraId.c_str()); - device = nullptr; _hidl_cb(Status::INTERNAL_ERROR, nullptr); return Void(); } - device = deviceImpl; break; } case 3: { // Map legacy camera device v3 HAL to Treble camera device HAL v3.3 ALOGV("Constructing v3.3 camera device"); - sp deviceImpl = - new android::hardware::camera::device::V3_3::implementation::CameraDevice( + deviceImpl = new android::hardware::camera::device::V3_3::implementation::CameraDevice( mModule, cameraId, mCameraDeviceNames); if (deviceImpl == nullptr || deviceImpl->isInitFailed()) { ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraId.c_str()); - device = nullptr; _hidl_cb(Status::INTERNAL_ERROR, nullptr); return Void(); } - device = deviceImpl; break; } default: ALOGE("%s: Unknown HAL minor version %d!", __FUNCTION__, mPreferredHal3MinorVersion); - device = nullptr; _hidl_cb(Status::INTERNAL_ERROR, nullptr); return Void(); } - _hidl_cb (Status::OK, device); + + _hidl_cb (Status::OK, deviceImpl->getInterface()); return Void(); } From ee3f720115a8728414f9dac4b660503cfb2d8a17 Mon Sep 17 00:00:00 2001 From: Brian Stack Date: Wed, 5 Sep 2018 16:46:28 -0700 Subject: [PATCH 096/718] Copy ISensors 1.0 into 2.0 directory Copy the current version of the Sensors HAL into the 2.0 directory to provide a starting point to replace the polling function. Update version and headers. Import types from version 1.0 of Sensors HAL. Bug: 111070257 Test: Build succeeds Change-Id: Ibd00d83016dedc06e583579a0d76c7baa8fbcd05 --- sensors/2.0/Android.bp | 18 ++++ sensors/2.0/ISensors.hal | 203 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 221 insertions(+) create mode 100644 sensors/2.0/Android.bp create mode 100644 sensors/2.0/ISensors.hal diff --git a/sensors/2.0/Android.bp b/sensors/2.0/Android.bp new file mode 100644 index 0000000000..4d22dcb011 --- /dev/null +++ b/sensors/2.0/Android.bp @@ -0,0 +1,18 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +hidl_interface { + name: "android.hardware.sensors@2.0", + root: "android.hardware", + vndk: { + enabled: true, + }, + srcs: [ + "ISensors.hal", + ], + interfaces: [ + "android.hardware.sensors@1.0", + "android.hidl.base@1.0", + ], + gen_java: false, +} + diff --git a/sensors/2.0/ISensors.hal b/sensors/2.0/ISensors.hal new file mode 100644 index 0000000000..6df454d4fd --- /dev/null +++ b/sensors/2.0/ISensors.hal @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.sensors@2.0; + +import @1.0::Event; +import @1.0::OperationMode; +import @1.0::RateLevel; +import @1.0::Result; +import @1.0::SensorInfo; +import @1.0::SharedMemInfo; + +interface ISensors { + /** + * Enumerate all available (static) sensors. + */ + getSensorsList() generates (vec list); + + /** + * Place the module in a specific mode. The following modes are defined + * + * SENSOR_HAL_NORMAL_MODE - Normal operation. Default state of the module. + * + * SENSOR_HAL_DATA_INJECTION_MODE - Loopback mode. + * Data is injected for the supported sensors by the sensor service in + * this mode. + * + * @return OK on success + * BAD_VALUE if requested mode is not supported + * PERMISSION_DENIED if operation is not allowed + */ + setOperationMode(OperationMode mode) generates (Result result); + + /** + * Activate/de-activate one sensor. + * + * After sensor de-activation, existing sensor events that have not + * been picked up by poll() must be abandoned immediately so that + * subsequent activations do not get stale sensor events (events + * that are generated prior to the latter activation). + * + * @param sensorHandle is the handle of the sensor to change. + * @param enabled set to true to enable, or false to disable the sensor. + * @return result OK on success, BAD_VALUE if sensorHandle is invalid. + */ + activate(int32_t sensorHandle, bool enabled) generates (Result result); + + /** + * Generate a vector of sensor events containing at most "maxCount" + * entries. + * + * Additionally a vector of SensorInfos is returned for any dynamic sensors + * connected as notified by returned events of type DYNAMIC_SENSOR_META. + * + * If there is no sensor event when this function is being called, block + * until there are sensor events available. + * + * @param maxCount max number of samples can be returned, must be > 0. + * Actual number of events returned in data must be <= maxCount and > 0 + * @return result OK on success or BAD_VALUE if maxCount <= 0. + * @return data vector of Event contains sensor events. + * @return dynamicSensorsAdded vector of SensorInfo contains dynamic sensor + * added. Each element corresponds to a dynamic sensor meta events in + * data. + */ + poll(int32_t maxCount) + generates ( + Result result, + vec data, + vec dynamicSensorsAdded); + + /** + * Sets a sensor’s parameters, including sampling frequency and maximum + * report latency. This function can be called while the sensor is + * activated, in which case it must not cause any sensor measurements to + * be lost: transitioning from one sampling rate to the other cannot cause + * lost events, nor can transitioning from a high maximum report latency to + * a low maximum report latency. + * + * @param sensorHandle handle of sensor to be changed. + * @param samplingPeriodNs specifies sensor sample period in nanoseconds. + * @param maxReportLatencyNs allowed delay time before an event is sampled + * to time of report. + * @return result OK on success, BAD_VALUE if any parameters are invalid. + */ + batch(int32_t sensorHandle, + int64_t samplingPeriodNs, + int64_t maxReportLatencyNs) + generates ( + Result result); + + /** + * Trigger a flush of internal FIFO. + * + * Flush adds a FLUSH_COMPLETE metadata event to the end of the "batch mode" + * FIFO for the specified sensor and flushes the FIFO. If the FIFO is empty + * or if the sensor doesn't support batching (FIFO size zero), return + * SUCCESS and add a trivial FLUSH_COMPLETE event added to the event stream. + * This applies to all sensors other than one-shot sensors. If the sensor + * is a one-shot sensor, flush must return BAD_VALUE and not generate any + * flush complete metadata. If the sensor is not active at the time flush() + * is called, flush() return BAD_VALUE. + * + * @param sensorHandle handle of sensor to be flushed. + * @return result OK on success and BAD_VALUE if sensorHandle is invalid. + */ + flush(int32_t sensorHandle) generates (Result result); + + /** + * Inject a single sensor event or push operation environment parameters to + * device. + * + * When device is in NORMAL mode, this function is called to push operation + * environment data to device. In this operation, Event is always of + * SensorType::AdditionalInfo type. See operation evironment parameters + * section in AdditionalInfoType. + * + * When device is in DATA_INJECTION mode, this function is also used for + * injecting sensor events. + * + * Regardless of OperationMode, injected SensorType::ADDITIONAL_INFO + * type events should not be routed back to poll() function. + * + * @see AdditionalInfoType + * @see OperationMode + * @param event sensor event to be injected + * @return result OK on success; PERMISSION_DENIED if operation is not + * allowed; INVALID_OPERATION, if this functionality is unsupported; + * BAD_VALUE if sensor event cannot be injected. + */ + injectSensorData(Event event) generates (Result result); + + /** + * Register direct report channel. + * + * Register a direct channel with supplied shared memory information. Upon + * return, the sensor hardware is responsible for resetting the memory + * content to initial value (depending on memory format settings). + * + * @param mem shared memory info data structure. + * @return result OK on success; BAD_VALUE if shared memory information is + * not consistent; NO_MEMORY if shared memory cannot be used by sensor + * system; INVALID_OPERATION if functionality is not supported. + * @return channelHandle a positive integer used for referencing registered + * direct channel (>0) in configureDirectReport and + * unregisterDirectChannel if result is OK, -1 otherwise. + */ + registerDirectChannel(SharedMemInfo mem) + generates (Result result, + int32_t channelHandle); + + /** + * Unregister direct report channel. + * + * Unregister a direct channel previously registered using + * registerDirectChannel, and remove all active sensor report configured in + * still active sensor report configured in the direct channel. + * + * @param channelHandle handle of direct channel to be unregistered. + * @return result OK if direct report is supported; INVALID_OPERATION + * otherwise. + */ + unregisterDirectChannel(int32_t channelHandle) generates (Result result); + + /** + * Configure direct sensor event report in direct channel. + * + * This function start, modify rate or stop direct report of a sensor in a + * certain direct channel. + * + * @param sensorHandle handle of sensor to be configured. When combined + * with STOP rate, sensorHandle can be -1 to denote all active sensors + * in the direct channel specified by channel Handle. + * @param channelHandle handle of direct channel to be configured. + * @param rate rate level, see RateLevel enum. + * @return result OK on success; BAD_VALUE if parameter is invalid (such as + * rate level is not supported by sensor, channelHandle does not exist, + * etc); INVALID_OPERATION if functionality is not supported. + * @return reportToken positive integer to identify multiple sensors of + * the same type in a single direct channel. Ignored if rate is STOP. + * See SharedMemFormat. + */ + configDirectReport( + int32_t sensorHandle, + int32_t channelHandle, + RateLevel rate + ) generates ( + Result result, + int32_t reportToken); +}; From 28c675fd86e7880db0814887db74ec764ddae582 Mon Sep 17 00:00:00 2001 From: Brian Stack Date: Thu, 6 Sep 2018 09:57:29 -0700 Subject: [PATCH 097/718] Replace poll with initializeMessageQueues Replaces poll with the new initializeMessageQueues call in ISensors::2.0. Bug: 111070257 Test: Build succeeds Change-Id: I99f951fe5f1d93d267bee6734534993b1088baeb --- sensors/2.0/Android.bp | 4 +++ sensors/2.0/ISensors.hal | 70 ++++++++++++++++++++++++++++------------ sensors/2.0/types.hal | 25 ++++++++++++++ 3 files changed, 79 insertions(+), 20 deletions(-) create mode 100644 sensors/2.0/types.hal diff --git a/sensors/2.0/Android.bp b/sensors/2.0/Android.bp index 4d22dcb011..20bc4e1d2d 100644 --- a/sensors/2.0/Android.bp +++ b/sensors/2.0/Android.bp @@ -7,12 +7,16 @@ hidl_interface { enabled: true, }, srcs: [ + "types.hal", "ISensors.hal", ], interfaces: [ "android.hardware.sensors@1.0", "android.hidl.base@1.0", ], + types: [ + "SensorTimeout", + ], gen_java: false, } diff --git a/sensors/2.0/ISensors.hal b/sensors/2.0/ISensors.hal index 6df454d4fd..32092ef224 100644 --- a/sensors/2.0/ISensors.hal +++ b/sensors/2.0/ISensors.hal @@ -48,7 +48,7 @@ interface ISensors { * Activate/de-activate one sensor. * * After sensor de-activation, existing sensor events that have not - * been picked up by poll() must be abandoned immediately so that + * been written to the event queue must be abandoned immediately so that * subsequent activations do not get stale sensor events (events * that are generated prior to the latter activation). * @@ -59,28 +59,58 @@ interface ISensors { activate(int32_t sensorHandle, bool enabled) generates (Result result); /** - * Generate a vector of sensor events containing at most "maxCount" - * entries. + * Initialize the Fast Message Queues (FMQ) that are used to send data + * between the framework and the HAL. * - * Additionally a vector of SensorInfos is returned for any dynamic sensors - * connected as notified by returned events of type DYNAMIC_SENSOR_META. + * The Event FMQ is used to transport sensor events from the HAL to the + * framework. The Event FMQ is created using the eventQueueDescriptor. + * Data may only be written to the Event FMQ. Data must not be read from + * the Event FMQ since the framework is the only reader. Upon receiving + * sensor events, the HAL should write the sensor events to the Event FMQ. * - * If there is no sensor event when this function is being called, block - * until there are sensor events available. + * The Wake Lock FMQ is used by the framework to notify the HAL when it is + * safe to release its wake_lock. When the framework receives WAKE_UP events + * from the Event FMQ and the framework has acquired a wake_lock, the + * framework must write a WakeLockEvent to the Wake Lock FMQ with the number + * of WAKE_UP events processed. When the HAL reads the WakeLockEvent from + * the Wake Lock FMQ, the HAL should decrement its current count of + * unprocessed WAKE_UP events and release its wake_lock if the current + * count of unprocessed WAKE_UP events is zero. * - * @param maxCount max number of samples can be returned, must be > 0. - * Actual number of events returned in data must be <= maxCount and > 0 - * @return result OK on success or BAD_VALUE if maxCount <= 0. - * @return data vector of Event contains sensor events. - * @return dynamicSensorsAdded vector of SensorInfo contains dynamic sensor - * added. Each element corresponds to a dynamic sensor meta events in - * data. + * The name of any wake_lock acquired by the Sensors HAL for WAKE_UP events + * must begin with "SensorsHAL_WAKEUP". + * + * If WAKE_LOCK_TIMEOUT_SECONDS has elapsed since the most recent WAKE_UP + * event was written to the Event FMQ without receiving a message on the + * Wake Lock FMQ, then any held wake_lock for WAKE_UP events must be + * released. + * + * If either the Event FMQ or the Wake Lock FMQ is already initialized when + * initializeMessageQueues is invoked, then both existing FMQs must be + * discarded and the new descriptors must be used to create new FMQs within + * the HAL. The number of outstanding WAKE_UP events should also be reset to + * zero, and any outstanding wake_locks held as a result of WAKE_UP events + * should be released. + * + * initializeMessageQueues must be thread safe and prevent concurrent calls + * to initializeMessageQueues from simultaneously modifying state. + * + * @param eventQueueDescriptor Fast Message Queue descriptor that is used to + * create the Event FMQ which is where sensor events are written. The + * descriptor is obtained from the framework's FMQ that is used to read + * sensor events. + * @param wakeLockDescriptor Fast Message Queue descriptor that is used to + * create the Wake Lock FMQ which is where wake_lock events are read + * from. The descriptor is obtained from the framework's FMQ that is + * used to write wake_lock events. + * @return result OK on success; BAD_VALUE if descriptor is invalid (such + * as null) */ - poll(int32_t maxCount) - generates ( - Result result, - vec data, - vec dynamicSensorsAdded); + @entry + @callflow(next = {"getSensorsList"}) + initializeMessageQueues(fmq_sync eventQueueDescriptor, + fmq_sync wakeLockDescriptor) + generates (Result result); /** * Sets a sensor’s parameters, including sampling frequency and maximum @@ -132,7 +162,7 @@ interface ISensors { * injecting sensor events. * * Regardless of OperationMode, injected SensorType::ADDITIONAL_INFO - * type events should not be routed back to poll() function. + * type events should not be routed back to the sensor event queue. * * @see AdditionalInfoType * @see OperationMode diff --git a/sensors/2.0/types.hal b/sensors/2.0/types.hal new file mode 100644 index 0000000000..16e1c03b3b --- /dev/null +++ b/sensors/2.0/types.hal @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.sensors@2.0; + +enum SensorTimeout : int32_t { + /** + * The maximum number of seconds to wait for a message on the Wake Lock FMQ + * before automatically releasing any wake_lock held for a WAKE_UP event. + */ + WAKE_LOCK_SECONDS = 1, +}; From b7326db5c99fbdfab849a63e5e95be3c27e5c83f Mon Sep 17 00:00:00 2001 From: Michael Dooley Date: Fri, 14 Sep 2018 16:10:12 +0000 Subject: [PATCH 098/718] Revert "Adding getModelState API to sound trigger" This reverts commit 73e63e662c4638091f0cd0efb11dce47341f817d. Reason for revert: fix build breakage Change-Id: I37d33bd2536f1917ced8a1ba816f336e7c9bb4e8 --- .../2.0/default/SoundTriggerHalImpl.cpp | 2 +- .../2.0/default/SoundTriggerHalImpl.h | 5 +- soundtrigger/2.2/Android.bp | 20 ---- soundtrigger/2.2/ISoundTriggerHw.hal | 40 ------- soundtrigger/2.2/default/Android.mk | 50 -------- soundtrigger/2.2/default/SoundTriggerHw.cpp | 110 ----------------- soundtrigger/2.2/default/SoundTriggerHw.h | 113 ------------------ soundtrigger/2.2/vts/functional/Android.bp | 29 ----- .../VtsHalSoundtriggerV2_2TargetTest.cpp | 101 ---------------- 9 files changed, 2 insertions(+), 468 deletions(-) delete mode 100644 soundtrigger/2.2/Android.bp delete mode 100644 soundtrigger/2.2/ISoundTriggerHw.hal delete mode 100644 soundtrigger/2.2/default/Android.mk delete mode 100644 soundtrigger/2.2/default/SoundTriggerHw.cpp delete mode 100644 soundtrigger/2.2/default/SoundTriggerHw.h delete mode 100644 soundtrigger/2.2/vts/functional/Android.bp delete mode 100644 soundtrigger/2.2/vts/functional/VtsHalSoundtriggerV2_2TargetTest.cpp diff --git a/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp b/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp index 2de35e8a0d..612772cc63 100644 --- a/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp +++ b/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp @@ -247,7 +247,7 @@ exit: } SoundTriggerHalImpl::SoundTriggerHalImpl() - : mModuleName("primary"), mNextModelId(1), mHwDevice(NULL) {} + : mModuleName("primary"), mHwDevice(NULL), mNextModelId(1) {} void SoundTriggerHalImpl::onFirstRef() { const hw_module_t* mod; diff --git a/soundtrigger/2.0/default/SoundTriggerHalImpl.h b/soundtrigger/2.0/default/SoundTriggerHalImpl.h index fbe24c15d9..5a9f0e19af 100644 --- a/soundtrigger/2.0/default/SoundTriggerHalImpl.h +++ b/soundtrigger/2.0/default/SoundTriggerHalImpl.h @@ -167,11 +167,8 @@ class SoundTriggerHalImpl : public RefBase { static void recognitionCallback(struct sound_trigger_recognition_event* halEvent, void* cookie); const char* mModuleName; - - volatile atomic_uint_fast32_t mNextModelId; - - protected: struct sound_trigger_hw_device* mHwDevice; + volatile atomic_uint_fast32_t mNextModelId; DefaultKeyedVector > mClients; Mutex mLock; }; diff --git a/soundtrigger/2.2/Android.bp b/soundtrigger/2.2/Android.bp deleted file mode 100644 index 0a7c2d80ba..0000000000 --- a/soundtrigger/2.2/Android.bp +++ /dev/null @@ -1,20 +0,0 @@ -// This file is autogenerated by hidl-gen -Landroidbp. - -hidl_interface { - name: "android.hardware.soundtrigger@2.2", - root: "android.hardware", - vndk: { - enabled: true, - }, - srcs: [ - "ISoundTriggerHw.hal", - ], - interfaces: [ - "android.hardware.audio.common@2.0", - "android.hardware.soundtrigger@2.0", - "android.hardware.soundtrigger@2.1", - "android.hidl.base@1.0", - ], - gen_java: false, -} - diff --git a/soundtrigger/2.2/ISoundTriggerHw.hal b/soundtrigger/2.2/ISoundTriggerHw.hal deleted file mode 100644 index c5033588de..0000000000 --- a/soundtrigger/2.2/ISoundTriggerHw.hal +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.hardware.soundtrigger@2.2; - -import @2.1::ISoundTriggerHw; -import @2.0::SoundModelHandle; -import @2.0::ISoundTriggerHwCallback.RecognitionEvent; - -/** - * SoundTrigger HAL interface. Used for hardware recognition of hotwords. - */ -interface ISoundTriggerHw extends @2.1::ISoundTriggerHw { - - /** - * Get the state of a given model. - * The model state is returned as a RecognitionEvent. - * @param modelHandle The handle of the sound model to use for recognition - * @return retval Operation completion status: 0 in case of success, - * -ENOSYS in case of invalid model handle, - * -ENOMEM in case of memory allocation failure, - * -ENODEV in case of initialization error. - * @return state RecognitionEvent in case of success - */ - getModelState(SoundModelHandle modelHandle) - generates (int32_t retval, RecognitionEvent state); -}; diff --git a/soundtrigger/2.2/default/Android.mk b/soundtrigger/2.2/default/Android.mk deleted file mode 100644 index 8c0f653d8d..0000000000 --- a/soundtrigger/2.2/default/Android.mk +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright (C) 2018 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) -LOCAL_MODULE := android.hardware.soundtrigger@2.2-impl -LOCAL_VENDOR_MODULE := true -LOCAL_MODULE_RELATIVE_PATH := hw -LOCAL_SRC_FILES := \ - SoundTriggerHw.cpp - -LOCAL_CFLAGS := -Wall -Werror - -LOCAL_SHARED_LIBRARIES := \ - libhardware \ - libhidlbase \ - libhidlmemory \ - libhidltransport \ - liblog \ - libutils \ - android.hardware.soundtrigger@2.2 \ - android.hardware.soundtrigger@2.1 \ - android.hardware.soundtrigger@2.0 \ - android.hardware.soundtrigger@2.0-core \ - android.hidl.allocator@1.0 \ - android.hidl.memory@1.0 - -LOCAL_C_INCLUDE_DIRS := $(LOCAL_PATH) - -ifeq ($(strip $(AUDIOSERVER_MULTILIB)),) -LOCAL_MULTILIB := 32 -else -LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB) -endif - -include $(BUILD_SHARED_LIBRARY) diff --git a/soundtrigger/2.2/default/SoundTriggerHw.cpp b/soundtrigger/2.2/default/SoundTriggerHw.cpp deleted file mode 100644 index 90faf33598..0000000000 --- a/soundtrigger/2.2/default/SoundTriggerHw.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "SoundTriggerHw" - -#include "SoundTriggerHw.h" - -#include -#include - -namespace android { -namespace hardware { -namespace soundtrigger { -namespace V2_2 { -namespace implementation { - -Return SoundTriggerHw::getModelState_2_2(int32_t modelHandle, getModelState_cb hidl_cb) { - sp client; - if (mHwDevice == NULL) { - hidl_cb(-ENODEV, NULL); - return Void(); - } - - { - AutoMutex lock(mLock); - client = mClients.valueFor(modelHandle); - if (client == 0) { - hidl_cb(-ENOSYS, NULL); - return Void(); - } - } - - if (mHwDevice->get_model_state == NULL) { - ALOGE("Failed to get model state from device, no such method"); - hidl_cb(-ENODEV, NULL); - return Void(); - } - - // Get the state from the device (as a recognition event) - struct sound_trigger_recognition_event* event = - mHwDevice->get_model_state(mHwDevice, client->getHalHandle()); - if (event == NULL) { - ALOGE("Failed to get model state from device"); - hidl_cb(-ENODEV, NULL); - return Void(); - } - - // Allocate shared memory to return to the client - sp alloc = IAllocator::getService("ashmem"); - if (alloc == 0) { - ALOGE("Failed to retrieve ashmem allocator service"); - free(event); - hidl_cb(-ENOMEM, NULL); - return Void(); - } - // Note: Only generic recognition events are currently supported - int n_bytes = sizeof(struct sound_trigger_generic_recognition_event); - bool success = false; - const hidl_memory& mem; - Return r = ashmem->allocate(n_bytes, [&](bool s, const hidl_memory& m) { - success = s; - if (success) mem = m; - }); - if (r.isOk() && success) { - // Copy the event data to the shared memory - sp memory = mapMemory(mem); - if (memory != 0) { - struct sound_trigger_generic_recognition_event* data = - (struct sound_trigger_generic_recognition_event*)memory->getPointer(); - memory->update(); - *data = *event; - memory->commit(); - - // Return the event memory via this callback - hidl_cb(0, memory); - } else { - ALOGE("Failed to map memory for recognition event"); - hidl_cb(-ENOMEM, NULL); - } - } else { - ALOGE("Failed to allocate %d bytes from ashmem allocator service", n_bytes); - hidl_cb(-ENOMEM, NULL); - } - - free(event); - return Void(); -} - -ISoundTriggerHw* HIDL_FETCH_ISoundTriggerHw(const char* /* name */) { - return (new SoundTriggerHw())->getInterface(); -} - -} // namespace implementation -} // namespace V2_2 -} // namespace soundtrigger -} // namespace hardware -} // namespace android diff --git a/soundtrigger/2.2/default/SoundTriggerHw.h b/soundtrigger/2.2/default/SoundTriggerHw.h deleted file mode 100644 index e7e8be9417..0000000000 --- a/soundtrigger/2.2/default/SoundTriggerHw.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_HARDWARE_SOUNDTRIGGER_V2_2_SOUNDTRIGGERHW_H -#define ANDROID_HARDWARE_SOUNDTRIGGER_V2_2_SOUNDTRIGGERHW_H - -#include -#include -#include - -namespace android { -namespace hardware { -namespace soundtrigger { -namespace V2_2 { -namespace implementation { - -using ::android::sp; -using ::android::hardware::Return; - -struct SoundTriggerHw : public V2_1::implementation::SoundTriggerHalImpl { - SoundTriggerHw() = default; - ISoundTriggerHw* getInterface() { return new TrampolineSoundTriggerHw_2_2(this); } - - protected: - virtual ~SoundTriggerHw() = default; - - Return> getModelState_2_2( - V2_0::SoundModelHandle modelHandle modelHandle); - - private: - struct TrampolineSoundTriggerHw_2_2 : public ISoundTriggerHw { - explicit TrampolineSoundTriggerHw_2_2(sp impl) : mImpl(impl) {} - - // Methods from ::android::hardware::soundtrigger::V2_0::ISoundTriggerHw follow. - Return getProperties(getProperties_cb _hidl_cb) override { - return mImpl->getProperties(_hidl_cb); - } - Return loadSoundModel(const V2_0::ISoundTriggerHw::SoundModel& soundModel, - const sp& callback, - int32_t cookie, loadSoundModel_cb _hidl_cb) override { - return mImpl->loadSoundModel(soundModel, callback, cookie, _hidl_cb); - } - Return loadPhraseSoundModel(const V2_0::ISoundTriggerHw::PhraseSoundModel& soundModel, - const sp& callback, - int32_t cookie, - loadPhraseSoundModel_cb _hidl_cb) override { - return mImpl->loadPhraseSoundModel(soundModel, callback, cookie, _hidl_cb); - } - Return unloadSoundModel(V2_0::SoundModelHandle modelHandle) override { - return mImpl->unloadSoundModel(modelHandle); - } - Return startRecognition(int32_t modelHandle, - const V2_0::ISoundTriggerHw::RecognitionConfig& config, - const sp& /*callback*/, - int32_t /*cookie*/) override { - return mImpl->startRecognition(modelHandle, config); - } - Return stopRecognition(V2_0::SoundModelHandle modelHandle) override { - return mImpl->stopRecognition(modelHandle); - } - Return stopAllRecognitions() override { return mImpl->stopAllRecognitions(); } - - // Methods from V2_1::ISoundTriggerHw follow. - Return loadSoundModel_2_1(const V2_1::ISoundTriggerHw::SoundModel& soundModel, - const sp& callback, - int32_t cookie, loadSoundModel_2_1_cb _hidl_cb) override { - return mImpl->loadSoundModel_2_1(soundModel, callback, cookie, _hidl_cb); - } - Return loadPhraseSoundModel_2_1( - const V2_1::ISoundTriggerHw::PhraseSoundModel& soundModel, - const sp& callback, int32_t cookie, - loadPhraseSoundModel_2_1_cb _hidl_cb) override { - return mImpl->loadPhraseSoundModel_2_1(soundModel, callback, cookie, _hidl_cb); - } - Return startRecognition_2_1(int32_t modelHandle, - const V2_1::ISoundTriggerHw::RecognitionConfig& config, - const sp& /*callback*/, - int32_t /*cookie*/) override { - return mImpl->startRecognition_2_1(modelHandle, config); - } - - // Methods from V2_2::ISoundTriggerHw follow. - Return getModelState(int32_t modelHandle, getModelState_cb hidl_cb) override { - return mImpl->getModelState_2_2(modelHandle, hidl_cb); - } - - private: - sp mImpl; - }; -}; - -extern "C" ISoundTriggerHw* HIDL_FETCH_ISoundTriggerHw(const char* name); - -} // namespace implementation -} // namespace V2_2 -} // namespace soundtrigger -} // namespace hardware -} // namespace android - -#endif // ANDROID_HARDWARE_SOUNDTRIGGER_V2_2_SOUNDTRIGGERHW_H diff --git a/soundtrigger/2.2/vts/functional/Android.bp b/soundtrigger/2.2/vts/functional/Android.bp deleted file mode 100644 index adbd0188b4..0000000000 --- a/soundtrigger/2.2/vts/functional/Android.bp +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright (C) 2018 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -cc_test { - name: "VtsHalSoundtriggerV2_2TargetTest", - defaults: ["VtsHalTargetTestDefaults"], - srcs: ["VtsHalSoundtriggerV2_2TargetTest.cpp"], - static_libs: [ - "android.hidl.allocator@1.0", - "android.hidl.memory@1.0", - "android.hardware.soundtrigger@2.0", - "android.hardware.soundtrigger@2.1", - "android.hardware.soundtrigger@2.2", - "libhidlmemory" - ], -} diff --git a/soundtrigger/2.2/vts/functional/VtsHalSoundtriggerV2_2TargetTest.cpp b/soundtrigger/2.2/vts/functional/VtsHalSoundtriggerV2_2TargetTest.cpp deleted file mode 100644 index ed5149fe7d..0000000000 --- a/soundtrigger/2.2/vts/functional/VtsHalSoundtriggerV2_2TargetTest.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "SoundTriggerHidlHalTest" -#include -#include - -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include -#include - -using ::android::sp; -using ::android::hardware::Return; -using ::android::hardware::soundtrigger::V2_0::ISoundTriggerHwCallback; -using ::android::hardware::soundtrigger::V2_0::SoundModelHandle; -using ::android::hardware::soundtrigger::V2_2::ISoundTriggerHw; - -// Test environment for SoundTrigger HIDL HAL. -class SoundTriggerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { - public: - // get the test environment singleton - static SoundTriggerHidlEnvironment* Instance() { - static SoundTriggerHidlEnvironment* instance = new SoundTriggerHidlEnvironment; - return instance; - } - - void registerTestServices() override { registerTestService(); } - - private: - SoundTriggerHidlEnvironment() {} -}; - -// The main test class for Sound Trigger HIDL HAL. -class SoundTriggerHidlTest : public ::testing::VtsHalHidlTargetTestBase { - public: - void SetUp() override { - mSoundTriggerHal = ::testing::VtsHalHidlTargetTestBase::getService( - SoundTriggerHidlEnvironment::Instance()->getServiceName()); - ASSERT_NE(nullptr, mSoundTriggerHal.get()); - } - - static void SetUpTestCase() { srand(1234); } - - void TearDown() override {} - - protected: - sp mSoundTriggerHal; -}; - -/** - * Test ISoundTriggerHw::getModelState() method - * - * Verifies that: - * - the implementation returns -EINVAL with invalid model handle - * - */ -TEST_F(SoundTriggerHidlTest, GetModelStateInvalidModel) { - int ret = android::OK; - ISoundTriggerHwCallback::RecognitionEvent event; - SoundModelHandle handle = 0; - Return hidlReturn = - mSoundTriggerHal->getModelState(handle, [&](int32_t retval, auto res) { - ret = retval; - event = res; - }); - - EXPECT_TRUE(hidlReturn.isOk()); - EXPECT_EQ(-ENOSYS, ret); -} - -int main(int argc, char** argv) { - ::testing::AddGlobalTestEnvironment(SoundTriggerHidlEnvironment::Instance()); - ::testing::InitGoogleTest(&argc, argv); - SoundTriggerHidlEnvironment::Instance()->init(&argc, argv); - int status = RUN_ALL_TESTS(); - ALOGI("Test result = %d", status); - return status; -} From f38f62a1d4520ed075a8e73c78f24f017deb0821 Mon Sep 17 00:00:00 2001 From: Steve Paik Date: Mon, 20 Aug 2018 19:09:15 -0700 Subject: [PATCH 099/718] Add STEERING_ANGLE property Bug: 80551979 Test: Added property to VHAL Change-Id: Ie6310d85af9bf0aebe63f0f2fdbac9a75c32b1ec --- automotive/vehicle/2.0/types.hal | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal index 7fe8377b5a..4d0738650e 100644 --- a/automotive/vehicle/2.0/types.hal +++ b/automotive/vehicle/2.0/types.hal @@ -321,6 +321,21 @@ enum VehicleProperty : int32_t { | VehiclePropertyType:FLOAT | VehicleArea:GLOBAL), + /** + * Steering angle of the vehicle + * + * Angle is in degrees. Left is negative. + * + * @change_mode VehiclePropertyChangeMode:CONTINUOUS + * @access VehiclePropertyAccess:READ + * @unit VehicleUnit:DEGREES + */ + PERF_STEERING_ANGLE = ( + 0x0209 + | VehiclePropertyGroup:SYSTEM + | VehiclePropertyType:FLOAT + | VehicleArea:GLOBAL), + /** * Temperature of engine coolant * @@ -2421,13 +2436,15 @@ enum VehicleUnit : int32_t { NANO_SECS = 0x50, SECS = 0x53, YEAR = 0x59, - KILOPASCAL = 0x70, // Electrical Units WATT_HOUR = 0x60, MILLIAMPERE = 0x61, MILLIVOLT = 0x62, MILLIWATTS = 0x63, + + KILOPASCAL = 0x70, + DEGREES = 0x80, }; /** From e9873256d908d013e902400dc1dfd9537a33fc36 Mon Sep 17 00:00:00 2001 From: xshu Date: Tue, 7 Aug 2018 11:04:34 -0700 Subject: [PATCH 100/718] Add StaLinkLayerStats V1_3 Gets additional scan related information from legacy_hal up to framework. Bug: 77603419 Test: compile, unit tests Change-Id: I9c948166b640af192c8e6f85ed6c76719e0937a4 --- wifi/1.3/Android.bp | 6 + wifi/1.3/IWifiStaIface.hal | 44 +++++++ wifi/1.3/default/hidl_struct_util.cpp | 26 ++-- wifi/1.3/default/hidl_struct_util.h | 3 +- .../tests/hidl_struct_util_unit_tests.cpp | 112 ++++++++++++++++++ wifi/1.3/default/wifi_sta_iface.cpp | 16 ++- wifi/1.3/default/wifi_sta_iface.h | 10 +- wifi/1.3/types.hal | 68 +++++++++++ 8 files changed, 271 insertions(+), 14 deletions(-) create mode 100644 wifi/1.3/IWifiStaIface.hal create mode 100644 wifi/1.3/types.hal diff --git a/wifi/1.3/Android.bp b/wifi/1.3/Android.bp index 95fbf8346d..5e87c1c760 100644 --- a/wifi/1.3/Android.bp +++ b/wifi/1.3/Android.bp @@ -7,7 +7,9 @@ hidl_interface { enabled: true, }, srcs: [ + "types.hal", "IWifi.hal", + "IWifiStaIface.hal", ], interfaces: [ "android.hardware.wifi@1.0", @@ -15,6 +17,10 @@ hidl_interface { "android.hardware.wifi@1.2", "android.hidl.base@1.0", ], + types: [ + "StaLinkLayerRadioStats", + "StaLinkLayerStats", + ], gen_java: true, } diff --git a/wifi/1.3/IWifiStaIface.hal b/wifi/1.3/IWifiStaIface.hal new file mode 100644 index 0000000000..0dc6128564 --- /dev/null +++ b/wifi/1.3/IWifiStaIface.hal @@ -0,0 +1,44 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.wifi@1.3; + +import @1.0::WifiStatus; +import @1.2::IWifiStaIface; + +/** + * Interface used to represent a single STA iface. + * + * IWifiChip.createStaIface() may return a @1.3::IWifiStaIface when supported. + */ +interface IWifiStaIface extends @1.2::IWifiStaIface { + /** + * Retrieve the latest link layer stats. + * Must fail if |StaIfaceCapabilityMask.LINK_LAYER_STATS| is not set or if + * link layer stats collection hasn't been explicitly enabled. + * + * @return status WifiStatus of the operation. + * Possible status codes: + * |WifiStatusCode.SUCCESS|, + * |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|, + * |WifiStatusCode.ERROR_NOT_SUPPORTED|, + * |WifiStatusCode.ERROR_NOT_STARTED|, + * |WifiStatusCode.ERROR_NOT_AVAILABLE|, + * |WifiStatusCode.ERROR_UNKNOWN| + * @return stats Instance of |LinkLayerStats|. + */ + getLinkLayerStats_1_3() generates (WifiStatus status, StaLinkLayerStats stats); +}; diff --git a/wifi/1.3/default/hidl_struct_util.cpp b/wifi/1.3/default/hidl_struct_util.cpp index e793236f5e..c88ddaaae5 100644 --- a/wifi/1.3/default/hidl_struct_util.cpp +++ b/wifi/1.3/default/hidl_struct_util.cpp @@ -785,7 +785,7 @@ bool convertLegacyVectorOfDebugRxPacketFateToHidl( bool convertLegacyLinkLayerStatsToHidl( const legacy_hal::LinkLayerStats& legacy_stats, - StaLinkLayerStats* hidl_stats) { + V1_3::StaLinkLayerStats* hidl_stats) { if (!hidl_stats) { return false; } @@ -826,16 +826,26 @@ bool convertLegacyLinkLayerStatsToHidl( hidl_stats->iface.wmeVoPktStats.retries = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries; // radio legacy_stats conversion. - std::vector hidl_radios_stats; + std::vector hidl_radios_stats; for (const auto& legacy_radio_stats : legacy_stats.radios) { - StaLinkLayerRadioStats hidl_radio_stats; - hidl_radio_stats.onTimeInMs = legacy_radio_stats.stats.on_time; - hidl_radio_stats.txTimeInMs = legacy_radio_stats.stats.tx_time; - hidl_radio_stats.rxTimeInMs = legacy_radio_stats.stats.rx_time; - hidl_radio_stats.onTimeInMsForScan = + V1_3::StaLinkLayerRadioStats hidl_radio_stats; + hidl_radio_stats.V1_0.onTimeInMs = legacy_radio_stats.stats.on_time; + hidl_radio_stats.V1_0.txTimeInMs = legacy_radio_stats.stats.tx_time; + hidl_radio_stats.V1_0.rxTimeInMs = legacy_radio_stats.stats.rx_time; + hidl_radio_stats.V1_0.onTimeInMsForScan = legacy_radio_stats.stats.on_time_scan; - hidl_radio_stats.txTimeInMsPerLevel = + hidl_radio_stats.V1_0.txTimeInMsPerLevel = legacy_radio_stats.tx_time_per_levels; + hidl_radio_stats.onTimeInMsForNanScan = + legacy_radio_stats.stats.on_time_nbd; + hidl_radio_stats.onTimeInMsForBgScan = + legacy_radio_stats.stats.on_time_gscan; + hidl_radio_stats.onTimeInMsForRoamScan = + legacy_radio_stats.stats.on_time_roam_scan; + hidl_radio_stats.onTimeInMsForPnoScan = + legacy_radio_stats.stats.on_time_pno_scan; + hidl_radio_stats.onTimeInMsForHs20Scan = + legacy_radio_stats.stats.on_time_hs20; hidl_radios_stats.push_back(hidl_radio_stats); } hidl_stats->radios = hidl_radios_stats; diff --git a/wifi/1.3/default/hidl_struct_util.h b/wifi/1.3/default/hidl_struct_util.h index e2ba00c1e8..8df484d063 100644 --- a/wifi/1.3/default/hidl_struct_util.h +++ b/wifi/1.3/default/hidl_struct_util.h @@ -24,6 +24,7 @@ #include #include #include +#include #include "wifi_legacy_hal.h" @@ -89,7 +90,7 @@ bool convertLegacyVectorOfCachedGscanResultsToHidl( std::vector* hidl_scan_datas); bool convertLegacyLinkLayerStatsToHidl( const legacy_hal::LinkLayerStats& legacy_stats, - StaLinkLayerStats* hidl_stats); + V1_3::StaLinkLayerStats* hidl_stats); bool convertLegacyRoamingCapabilitiesToHidl( const legacy_hal::wifi_roaming_capabilities& legacy_caps, StaRoamingCapabilities* hidl_caps); diff --git a/wifi/1.3/default/tests/hidl_struct_util_unit_tests.cpp b/wifi/1.3/default/tests/hidl_struct_util_unit_tests.cpp index 4cd3719293..d600a2be4d 100644 --- a/wifi/1.3/default/tests/hidl_struct_util_unit_tests.cpp +++ b/wifi/1.3/default/tests/hidl_struct_util_unit_tests.cpp @@ -126,6 +126,118 @@ TEST_F(HidlStructUtilTest, CanConvertLegacyWifiMacInfosToHidlWithTwoMac) { EXPECT_EQ(static_cast(legacy_iface_info2.channel), hidl_iface_info2.channel); } + +TEST_F(HidlStructUtilTest, canConvertLegacyLinkLayerStatsToHidl) { + legacy_hal::LinkLayerStats legacy_stats{}; + legacy_stats.radios.push_back(legacy_hal::LinkLayerRadioStats{}); + legacy_stats.radios.push_back(legacy_hal::LinkLayerRadioStats{}); + legacy_stats.iface.beacon_rx = rand(); + legacy_stats.iface.rssi_mgmt = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries = rand(); + + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries = rand(); + + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries = rand(); + + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries = rand(); + + for (auto& radio : legacy_stats.radios) { + radio.stats.on_time = rand(); + radio.stats.tx_time = rand(); + radio.stats.rx_time = rand(); + radio.stats.on_time_scan = rand(); + radio.stats.on_time_nbd = rand(); + radio.stats.on_time_gscan = rand(); + radio.stats.on_time_roam_scan = rand(); + radio.stats.on_time_pno_scan = rand(); + radio.stats.on_time_hs20 = rand(); + for (int i = 0; i < 4; i++) { + radio.tx_time_per_levels.push_back(rand()); + } + } + + V1_3::StaLinkLayerStats converted{}; + hidl_struct_util::convertLegacyLinkLayerStatsToHidl(legacy_stats, + &converted); + EXPECT_EQ(legacy_stats.iface.beacon_rx, converted.iface.beaconRx); + EXPECT_EQ(legacy_stats.iface.rssi_mgmt, converted.iface.avgRssiMgmt); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu, + converted.iface.wmeBePktStats.rxMpdu); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu, + converted.iface.wmeBePktStats.txMpdu); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost, + converted.iface.wmeBePktStats.lostMpdu); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries, + converted.iface.wmeBePktStats.retries); + + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu, + converted.iface.wmeBkPktStats.rxMpdu); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu, + converted.iface.wmeBkPktStats.txMpdu); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost, + converted.iface.wmeBkPktStats.lostMpdu); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries, + converted.iface.wmeBkPktStats.retries); + + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu, + converted.iface.wmeViPktStats.rxMpdu); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu, + converted.iface.wmeViPktStats.txMpdu); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost, + converted.iface.wmeViPktStats.lostMpdu); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries, + converted.iface.wmeViPktStats.retries); + + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu, + converted.iface.wmeVoPktStats.rxMpdu); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu, + converted.iface.wmeVoPktStats.txMpdu); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost, + converted.iface.wmeVoPktStats.lostMpdu); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries, + converted.iface.wmeVoPktStats.retries); + + EXPECT_EQ(legacy_stats.radios.size(), converted.radios.size()); + for (int i = 0; i < legacy_stats.radios.size(); i++) { + EXPECT_EQ(legacy_stats.radios[i].stats.on_time, + converted.radios[i].V1_0.onTimeInMs); + EXPECT_EQ(legacy_stats.radios[i].stats.tx_time, + converted.radios[i].V1_0.txTimeInMs); + EXPECT_EQ(legacy_stats.radios[i].stats.rx_time, + converted.radios[i].V1_0.rxTimeInMs); + EXPECT_EQ(legacy_stats.radios[i].stats.on_time_scan, + converted.radios[i].V1_0.onTimeInMsForScan); + EXPECT_EQ(legacy_stats.radios[i].tx_time_per_levels.size(), + converted.radios[i].V1_0.txTimeInMsPerLevel.size()); + for (int j = 0; j < legacy_stats.radios[i].tx_time_per_levels.size(); + j++) { + EXPECT_EQ(legacy_stats.radios[i].tx_time_per_levels[j], + converted.radios[i].V1_0.txTimeInMsPerLevel[j]); + } + EXPECT_EQ(legacy_stats.radios[i].stats.on_time_nbd, + converted.radios[i].onTimeInMsForNanScan); + EXPECT_EQ(legacy_stats.radios[i].stats.on_time_gscan, + converted.radios[i].onTimeInMsForBgScan); + EXPECT_EQ(legacy_stats.radios[i].stats.on_time_roam_scan, + converted.radios[i].onTimeInMsForRoamScan); + EXPECT_EQ(legacy_stats.radios[i].stats.on_time_pno_scan, + converted.radios[i].onTimeInMsForPnoScan); + EXPECT_EQ(legacy_stats.radios[i].stats.on_time_hs20, + converted.radios[i].onTimeInMsForHs20Scan); + } +} } // namespace implementation } // namespace V1_3 } // namespace wifi diff --git a/wifi/1.3/default/wifi_sta_iface.cpp b/wifi/1.3/default/wifi_sta_iface.cpp index 63341dfb4a..b0fa1aef6b 100644 --- a/wifi/1.3/default/wifi_sta_iface.cpp +++ b/wifi/1.3/default/wifi_sta_iface.cpp @@ -152,6 +152,13 @@ Return WifiStaIface::getLinkLayerStats( hidl_status_cb); } +Return WifiStaIface::getLinkLayerStats_1_3( + getLinkLayerStats_1_3_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getLinkLayerStatsInternal_1_3, + hidl_status_cb); +} + Return WifiStaIface::startRssiMonitoring( uint32_t cmd_id, int32_t max_rssi, int32_t min_rssi, startRssiMonitoring_cb hidl_status_cb) { @@ -445,8 +452,13 @@ WifiStatus WifiStaIface::disableLinkLayerStatsCollectionInternal() { return createWifiStatusFromLegacyError(legacy_status); } -std::pair +std::pair WifiStaIface::getLinkLayerStatsInternal() { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}}; +} + +std::pair +WifiStaIface::getLinkLayerStatsInternal_1_3() { legacy_hal::wifi_error legacy_status; legacy_hal::LinkLayerStats legacy_stats; std::tie(legacy_status, legacy_stats) = @@ -454,7 +466,7 @@ WifiStaIface::getLinkLayerStatsInternal() { if (legacy_status != legacy_hal::WIFI_SUCCESS) { return {createWifiStatusFromLegacyError(legacy_status), {}}; } - StaLinkLayerStats hidl_stats; + V1_3::StaLinkLayerStats hidl_stats; if (!hidl_struct_util::convertLegacyLinkLayerStatsToHidl(legacy_stats, &hidl_stats)) { return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; diff --git a/wifi/1.3/default/wifi_sta_iface.h b/wifi/1.3/default/wifi_sta_iface.h index 0fc61e2857..bc3090f241 100644 --- a/wifi/1.3/default/wifi_sta_iface.h +++ b/wifi/1.3/default/wifi_sta_iface.h @@ -19,7 +19,7 @@ #include #include -#include +#include #include @@ -36,7 +36,7 @@ using namespace android::hardware::wifi::V1_0; /** * HIDL interface object used to control a STA Iface instance. */ -class WifiStaIface : public V1_2::IWifiStaIface { +class WifiStaIface : public V1_3::IWifiStaIface { public: WifiStaIface(const std::string& ifname, const std::weak_ptr legacy_hal); @@ -75,6 +75,8 @@ class WifiStaIface : public V1_2::IWifiStaIface { disableLinkLayerStatsCollection_cb hidl_status_cb) override; Return getLinkLayerStats( getLinkLayerStats_cb hidl_status_cb) override; + Return getLinkLayerStats_1_3( + getLinkLayerStats_1_3_cb hidl_status_cb) override; Return startRssiMonitoring( uint32_t cmd_id, int32_t max_rssi, int32_t min_rssi, startRssiMonitoring_cb hidl_status_cb) override; @@ -130,7 +132,9 @@ class WifiStaIface : public V1_2::IWifiStaIface { WifiStatus stopBackgroundScanInternal(uint32_t cmd_id); WifiStatus enableLinkLayerStatsCollectionInternal(bool debug); WifiStatus disableLinkLayerStatsCollectionInternal(); - std::pair getLinkLayerStatsInternal(); + std::pair getLinkLayerStatsInternal(); + std::pair + getLinkLayerStatsInternal_1_3(); WifiStatus startRssiMonitoringInternal(uint32_t cmd_id, int32_t max_rssi, int32_t min_rssi); WifiStatus stopRssiMonitoringInternal(uint32_t cmd_id); diff --git a/wifi/1.3/types.hal b/wifi/1.3/types.hal new file mode 100644 index 0000000000..4585ff31b6 --- /dev/null +++ b/wifi/1.3/types.hal @@ -0,0 +1,68 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.wifi@1.3; + +import @1.0::StaLinkLayerRadioStats; +import @1.0::StaLinkLayerIfaceStats; +import @1.0::TimeStampInMs; + +struct StaLinkLayerRadioStats { + /** + * Baseline information as defined in HAL 1.0. + */ + @1.0::StaLinkLayerRadioStats V1_0; + + /** + * Total time for which the radio is awake due to NAN scan since boot or crash. + */ + uint32_t onTimeInMsForNanScan; + + /** + * Total time for which the radio is awake due to background scan since boot or crash. + */ + uint32_t onTimeInMsForBgScan; + + /** + * Total time for which the radio is awake due to roam scan since boot or crash. + */ + uint32_t onTimeInMsForRoamScan; + + /** + * Total time for which the radio is awake due to PNO scan since boot or crash. + */ + uint32_t onTimeInMsForPnoScan; + + /** + * Total time for which the radio is awake due to Hotspot 2.0 scans and GAS exchange since boot + * or crash. + */ + uint32_t onTimeInMsForHs20Scan; +}; + +/** + * Link layer stats retrieved via |getLinkLayerStats|. + */ +struct StaLinkLayerStats { + StaLinkLayerIfaceStats iface; + vec radios; + /** + * TimeStamp for each stats sample. + * This is the absolute milliseconds from boot when these stats were + * sampled. + */ + TimeStampInMs timeStampInMs; +}; \ No newline at end of file From cbe8e9ab03895d05aac2f17c3cfaa974d988f9ad Mon Sep 17 00:00:00 2001 From: Valerie Hau Date: Mon, 17 Sep 2018 10:58:03 -0700 Subject: [PATCH 101/718] Clearing reader and writer queues in executeCommands for HWC VTS Tests Test: ./VtsHalGraphicsComposerV2_1TargetTest, ./VtsHalGraphicsComposerV2_2TargetTest Change-Id: Ie47e486d191da30be47cde47d768d3cdde8e04e9 --- graphics/composer/2.1/utils/vts/ComposerVts.cpp | 2 ++ graphics/composer/2.2/utils/vts/ComposerVts.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/graphics/composer/2.1/utils/vts/ComposerVts.cpp b/graphics/composer/2.1/utils/vts/ComposerVts.cpp index 1cafafe3ae..250c3928a3 100644 --- a/graphics/composer/2.1/utils/vts/ComposerVts.cpp +++ b/graphics/composer/2.1/utils/vts/ComposerVts.cpp @@ -311,6 +311,8 @@ void ComposerClient::execute(TestCommandReader* reader, CommandWriterBase* write ASSERT_TRUE(reader->readQueue(tmpOutLength, tmpOutHandles)); reader->parse(); }); + reader->reset(); + writer->reset(); } } // namespace vts diff --git a/graphics/composer/2.2/utils/vts/ComposerVts.cpp b/graphics/composer/2.2/utils/vts/ComposerVts.cpp index d8fb656b7b..da994606bb 100644 --- a/graphics/composer/2.2/utils/vts/ComposerVts.cpp +++ b/graphics/composer/2.2/utils/vts/ComposerVts.cpp @@ -86,6 +86,8 @@ void ComposerClient::execute(V2_1::vts::TestCommandReader* reader, CommandWriter ASSERT_TRUE(reader->readQueue(tmpOutLength, tmpOutHandles)); reader->parse(); }); + reader->reset(); + writer->reset(); } Display ComposerClient::createVirtualDisplay_2_2(uint32_t width, uint32_t height, From 9ee5d7103c5c8e501ef7012122faad15a430e5d5 Mon Sep 17 00:00:00 2001 From: Yin-Chia Yeh Date: Mon, 17 Sep 2018 11:50:51 -0700 Subject: [PATCH 102/718] Camera: add buffer management API support key Test: compile Bug: 109829698 Change-Id: I654e07c9c5930bcbf3357d12d97ef32d198fdcc8 --- camera/metadata/3.4/types.hal | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/camera/metadata/3.4/types.hal b/camera/metadata/3.4/types.hal index 0088087e74..b228de8b2b 100644 --- a/camera/metadata/3.4/types.hal +++ b/camera/metadata/3.4/types.hal @@ -44,8 +44,23 @@ enum CameraMetadataTag : @3.3::CameraMetadataTag { ANDROID_REQUEST_END_3_4, + /** android.info.supportedBufferManagementVersion [static, enum, system] + * + *

The version of buffer management API this camera device supports and opts into.

+ */ + ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION = android.hardware.camera.metadata@3.3::CameraMetadataTag:ANDROID_INFO_END_3_3, + + ANDROID_INFO_END_3_4, + }; /* * Enumeration definitions for the various entries that need them */ + +/** android.info.supportedBufferManagementVersion enumeration values + * @see ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION + */ +enum CameraMetadataEnumAndroidInfoSupportedBufferManagementVersion : uint32_t { + ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5, +}; From 830137fc08da2ce0d89cc1316d023f3de015ab6f Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Thu, 13 Sep 2018 17:19:38 -0700 Subject: [PATCH 103/718] [Graphics] Add setLayerColorTransform. This patch adds HAL API to set per-layer color transformation with a 4x4 matrix. Given a 4x4 matrix, the matrix will be applied on the current layer before composition. BUG: 111562338 Test: Build, flash and boot, run VtsHalGraphicsComposerV2_3TargetTest Change-Id: I673cfc2745d35947107dcab19f383ba5a8067605 --- graphics/composer/2.3/Android.bp | 1 + graphics/composer/2.3/IComposerClient.hal | 71 ++++++++++++++++ .../2.3/utils/command-buffer/Android.bp | 15 ++++ .../2.3/ComposerCommandBuffer.h | 76 +++++++++++++++++ graphics/composer/2.3/utils/hal/Android.bp | 2 + .../include/composer-hal/2.3/ComposerClient.h | 20 ++++- .../composer-hal/2.3/ComposerCommandEngine.h | 81 +++++++++++++++++++ .../include/composer-hal/2.3/ComposerHal.h | 2 + .../include/composer-passthrough/2.3/HwcHal.h | 11 +++ graphics/composer/2.3/utils/vts/Android.bp | 1 + .../composer/2.3/vts/functional/Android.bp | 1 + .../VtsHalGraphicsComposerV2_3TargetTest.cpp | 37 +++++++++ 12 files changed, 317 insertions(+), 1 deletion(-) create mode 100644 graphics/composer/2.3/utils/command-buffer/Android.bp create mode 100644 graphics/composer/2.3/utils/command-buffer/include/composer-command-buffer/2.3/ComposerCommandBuffer.h create mode 100644 graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerCommandEngine.h diff --git a/graphics/composer/2.3/Android.bp b/graphics/composer/2.3/Android.bp index 23061dda5b..78da099cfa 100644 --- a/graphics/composer/2.3/Android.bp +++ b/graphics/composer/2.3/Android.bp @@ -12,6 +12,7 @@ hidl_interface { ], interfaces: [ "android.hardware.graphics.common@1.0", + "android.hardware.graphics.common@1.1", "android.hardware.graphics.composer@2.1", "android.hardware.graphics.composer@2.2", "android.hidl.base@1.0", diff --git a/graphics/composer/2.3/IComposerClient.hal b/graphics/composer/2.3/IComposerClient.hal index 77dd3eed72..089438efac 100644 --- a/graphics/composer/2.3/IComposerClient.hal +++ b/graphics/composer/2.3/IComposerClient.hal @@ -16,12 +16,58 @@ package android.hardware.graphics.composer@2.3; +import android.hardware.graphics.composer@2.1::IComposerClient.Command; import @2.2::IComposerClient; import @2.1::Display; import @2.1::Error; interface IComposerClient extends @2.2::IComposerClient { + enum Command : @2.2::IComposerClient.Command { + /** + * SET_LAYER_COLOR_TRANSFORM has this pseudo prototype + * + * setLayerColorTransform(float[16] matrix); + * + * This command has the following binary layout in bytes: + * + * 0 - 16 * 4: matrix + * + * Sets a matrix for color transform which will be applied on this layer + * before composition. + * + * If the device is not capable of apply the matrix on this layer, it must force + * this layer to client composition during VALIDATE_DISPLAY. + * + * The matrix provided is an affine color transformation of the following + * form: + * + * |r.r r.g r.b 0| + * |g.r g.g g.b 0| + * |b.r b.g b.b 0| + * |Tr Tg Tb 1| + * + * This matrix must be provided in row-major form: + * + * {r.r, r.g, r.b, 0, g.r, ...}. + * + * Given a matrix of this form and an input color [R_in, G_in, B_in], + * the input color must first be converted to linear space + * [R_linear, G_linear, B_linear], then the output linear color + * [R_out_linear, G_out_linear, B_out_linear] will be: + * + * R_out_linear = R_linear * r.r + G_linear * g.r + B_linear * b.r + Tr + * G_out_linear = R_linear * r.g + G_linear * g.g + B_linear * b.g + Tg + * B_out_linear = R_linear * r.b + G_linear * g.b + B_linear * b.b + Tb + * + * [R_out_linear, G_out_linear, B_out_linear] must then be converted to + * gamma space: [R_out, G_out, B_out] before blending. + * + * @param matrix is a 4x4 transform matrix (16 floats) as described above. + */ + SET_LAYER_COLOR_TRANSFORM = 0x40d << @2.1::IComposerClient.Command:OPCODE_SHIFT, + }; + /** * Returns the port and data that describe a physical display. The port is * a unique number that identifies a physical connector (e.g. eDP, HDMI) @@ -42,4 +88,29 @@ interface IComposerClient extends @2.2::IComposerClient { uint8_t port, vec data); + /** + * Executes commands from the input command message queue. Return values + * generated by the input commands are written to the output command + * message queue in the form of value commands. + * + * @param inLength is the length of input commands. + * @param inHandles is an array of handles referenced by the input + * commands. + * @return error is NONE upon success. Otherwise, + * BAD_PARAMETER when inLength is not equal to the length of + * commands in the input command message queue. + * NO_RESOURCES when the output command message queue was not + * properly drained. + * @param outQueueChanged indicates whether the output command message + * queue has changed. + * @param outLength is the length of output commands. + * @param outHandles is an array of handles referenced by the output + * commands. + */ + executeCommands_2_3(uint32_t inLength, + vec inHandles) + generates (Error error, + bool outQueueChanged, + uint32_t outLength, + vec outHandles); }; diff --git a/graphics/composer/2.3/utils/command-buffer/Android.bp b/graphics/composer/2.3/utils/command-buffer/Android.bp new file mode 100644 index 0000000000..c48fe7a53c --- /dev/null +++ b/graphics/composer/2.3/utils/command-buffer/Android.bp @@ -0,0 +1,15 @@ +cc_library_headers { + name: "android.hardware.graphics.composer@2.3-command-buffer", + defaults: ["hidl_defaults"], + vendor_available: true, + shared_libs: [ + "android.hardware.graphics.composer@2.1", + "android.hardware.graphics.composer@2.2", + "android.hardware.graphics.composer@2.3", + ], + header_libs: [ + "android.hardware.graphics.composer@2.1-command-buffer", + "android.hardware.graphics.composer@2.2-command-buffer", + ], + export_include_dirs: ["include"], +} diff --git a/graphics/composer/2.3/utils/command-buffer/include/composer-command-buffer/2.3/ComposerCommandBuffer.h b/graphics/composer/2.3/utils/command-buffer/include/composer-command-buffer/2.3/ComposerCommandBuffer.h new file mode 100644 index 0000000000..3f7b2c95f0 --- /dev/null +++ b/graphics/composer/2.3/utils/command-buffer/include/composer-command-buffer/2.3/ComposerCommandBuffer.h @@ -0,0 +1,76 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#ifndef LOG_TAG +#warn "ComposerCommandBuffer.h included without LOG_TAG" +#endif + +#undef LOG_NDEBUG +#define LOG_NDEBUG 0 + +#include +#include +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace composer { +namespace V2_3 { + +using android::hardware::MessageQueue; +using android::hardware::graphics::composer::V2_1::Error; +using android::hardware::graphics::composer::V2_1::IComposerCallback; +using android::hardware::graphics::composer::V2_1::Layer; +using android::hardware::graphics::composer::V2_3::IComposerClient; + +// This class helps build a command queue. Note that all sizes/lengths are in +// units of uint32_t's. +class CommandWriterBase : public V2_2::CommandWriterBase { + public: + CommandWriterBase(uint32_t initialMaxSize) : V2_2::CommandWriterBase(initialMaxSize) {} + + static constexpr uint16_t kSetLayerColorTransformLength = 16; + void setLayerColorTransform(const float* matrix) { + beginCommand_2_3(IComposerClient::Command::SET_LAYER_COLOR_TRANSFORM, + kSetLayerColorTransformLength); + for (int i = 0; i < 16; i++) { + writeFloat(matrix[i]); + } + endCommand(); + } + + protected: + void beginCommand_2_3(IComposerClient::Command command, uint16_t length) { + V2_2::CommandWriterBase::beginCommand_2_2( + static_cast(static_cast(command)), length); + } +}; + +// This class helps parse a command queue. Note that all sizes/lengths are in +// units of uint32_t's. +class CommandReaderBase : public V2_2::CommandReaderBase { + public: + CommandReaderBase() : V2_2::CommandReaderBase(){}; +}; + +} // namespace V2_3 +} // namespace composer +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/graphics/composer/2.3/utils/hal/Android.bp b/graphics/composer/2.3/utils/hal/Android.bp index aa46df1ebb..3ee930050c 100644 --- a/graphics/composer/2.3/utils/hal/Android.bp +++ b/graphics/composer/2.3/utils/hal/Android.bp @@ -26,9 +26,11 @@ cc_library_headers { ], header_libs: [ "android.hardware.graphics.composer@2.2-hal", + "android.hardware.graphics.composer@2.3-command-buffer", ], export_header_lib_headers: [ "android.hardware.graphics.composer@2.2-hal", + "android.hardware.graphics.composer@2.3-command-buffer", ], export_include_dirs: ["include"], } diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h index e717d84ba8..c805472e9e 100644 --- a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h +++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h @@ -22,6 +22,7 @@ #include #include +#include #include namespace android { @@ -55,10 +56,27 @@ class ComposerClientImpl : public V2_2::hal::detail::ComposerClientImpl executeCommands_2_3(uint32_t inLength, const hidl_vec& inHandles, + IComposerClient::executeCommands_2_2_cb hidl_cb) override { + std::lock_guard lock(mCommandEngineMutex); + bool outChanged = false; + uint32_t outLength = 0; + hidl_vec outHandles; + Error error = + mCommandEngine->execute(inLength, inHandles, &outChanged, &outLength, &outHandles); + + hidl_cb(error, outChanged, outLength, outHandles); + + mCommandEngine->reset(); + + return Void(); + } + private: using BaseType2_2 = V2_2::hal::detail::ComposerClientImpl; using BaseType2_1 = V2_1::hal::detail::ComposerClientImpl; - + using BaseType2_1::mCommandEngine; + using BaseType2_1::mCommandEngineMutex; using BaseType2_1::mHal; }; diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerCommandEngine.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerCommandEngine.h new file mode 100644 index 0000000000..c3dcbcd4a6 --- /dev/null +++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerCommandEngine.h @@ -0,0 +1,81 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#ifndef LOG_TAG +#warning "ComposerCommandEngine.h included without LOG_TAG" +#endif + +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace composer { +namespace V2_3 { +namespace hal { + +class ComposerCommandEngine : public V2_2::hal::ComposerCommandEngine { + public: + ComposerCommandEngine(ComposerHal* hal, V2_2::hal::ComposerResources* resources) + : BaseType2_2(hal, resources), mHal(hal) {} + + protected: + bool executeCommand(V2_1::IComposerClient::Command command, uint16_t length) override { + switch (static_cast(command)) { + case IComposerClient::Command::SET_LAYER_COLOR_TRANSFORM: + return executeSetLayerColorTransform(length); + default: + return BaseType2_2::executeCommand(command, length); + } + } + + bool executeSetLayerColorTransform(uint16_t length) { + if (length != CommandWriterBase::kSetLayerColorTransformLength) { + return false; + } + + float matrix[16]; + for (int i = 0; i < 16; i++) { + matrix[i] = readFloat(); + } + auto err = mHal->setLayerColorTransform(mCurrentDisplay, mCurrentLayer, matrix); + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; + } + + private: + using BaseType2_1 = V2_1::hal::ComposerCommandEngine; + using BaseType2_1::mWriter; + using BaseType2_2 = V2_2::hal::ComposerCommandEngine; + + ComposerHal* mHal; +}; + +} // namespace hal +} // namespace V2_3 +} // namespace composer +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h index 37ea0a3c46..0f6205abb7 100644 --- a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h +++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h @@ -27,11 +27,13 @@ namespace hal { using V2_1::Display; using V2_1::Error; +using V2_1::Layer; class ComposerHal : public V2_2::hal::ComposerHal { public: virtual Error getDisplayIdentificationData(Display display, uint8_t* outPort, std::vector* outData) = 0; + virtual Error setLayerColorTransform(Display display, Layer layer, const float* matrix) = 0; }; } // namespace hal diff --git a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h index 53f2d1b254..ed1878b583 100644 --- a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h +++ b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h @@ -66,6 +66,14 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl { return Error::NONE; } + Error setLayerColorTransform(Display display, Layer layer, const float* matrix) override { + if (!mDispatch.setLayerColorTransform) { + return Error::UNSUPPORTED; + } + int32_t err = mDispatch.setLayerColorTransform(mDevice, display, layer, matrix); + return static_cast(err); + } + protected: bool initDispatch() override { if (!BaseType2_2::initDispatch()) { @@ -74,12 +82,15 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl { this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAY_IDENTIFICATION_DATA, &mDispatch.getDisplayIdentificationData); + this->initOptionalDispatch(HWC2_FUNCTION_SET_LAYER_COLOR_TRANSFORM, + &mDispatch.setLayerColorTransform); return true; } private: struct { HWC2_PFN_GET_DISPLAY_IDENTIFICATION_DATA getDisplayIdentificationData; + HWC2_PFN_SET_LAYER_COLOR_TRANSFORM setLayerColorTransform; } mDispatch = {}; using BaseType2_2 = V2_2::passthrough::detail::HwcHalImpl; diff --git a/graphics/composer/2.3/utils/vts/Android.bp b/graphics/composer/2.3/utils/vts/Android.bp index 05532586ef..19438cbe26 100644 --- a/graphics/composer/2.3/utils/vts/Android.bp +++ b/graphics/composer/2.3/utils/vts/Android.bp @@ -31,6 +31,7 @@ cc_library_static { header_libs: [ "android.hardware.graphics.composer@2.1-command-buffer", "android.hardware.graphics.composer@2.2-command-buffer", + "android.hardware.graphics.composer@2.3-command-buffer", ], cflags: [ "-O0", diff --git a/graphics/composer/2.3/vts/functional/Android.bp b/graphics/composer/2.3/vts/functional/Android.bp index df696c9273..7548cb521e 100644 --- a/graphics/composer/2.3/vts/functional/Android.bp +++ b/graphics/composer/2.3/vts/functional/Android.bp @@ -40,5 +40,6 @@ cc_test { header_libs: [ "android.hardware.graphics.composer@2.1-command-buffer", "android.hardware.graphics.composer@2.2-command-buffer", + "android.hardware.graphics.composer@2.3-command-buffer", ], } diff --git a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp index f4e34f08ff..1030ddc9db 100644 --- a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp +++ b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp @@ -20,7 +20,9 @@ #include #include +#include #include +#include #include namespace android { @@ -65,6 +67,9 @@ class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase { // explicitly disable vsync mComposerClient->setVsyncEnabled(mPrimaryDisplay, false); mComposerCallback->setVsyncAllowed(false); + + mWriter = std::make_unique(1024); + mReader = std::make_unique(); } void TearDown() override { @@ -75,11 +80,18 @@ class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase { } } + void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); } + + // use the slot count usually set by SF + static constexpr uint32_t kBufferSlotCount = 64; + std::unique_ptr mComposer; std::unique_ptr mComposerClient; sp mComposerCallback; // the first display and is assumed never to be removed Display mPrimaryDisplay; + std::unique_ptr mWriter; + std::unique_ptr mReader; private: Display waitForFirstDisplay() { @@ -115,6 +127,31 @@ TEST_F(GraphicsComposerHidlTest, GetDisplayIdentificationData) { } } +/** + * Test IComposerClient::Command::SET_LAYER_COLOR_TRANSFORM. + * TODO Add color to the layer, use matrix to keep only red component, + * and check. + */ +TEST_F(GraphicsComposerHidlTest, SetLayerColorTransform) { + Layer layer; + ASSERT_NO_FATAL_FAILURE(layer = + mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); + mWriter->selectDisplay(mPrimaryDisplay); + mWriter->selectLayer(layer); + + // clang-format off + const std::array matrix = {{ + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f, + }}; + // clang-format on + + mWriter->setLayerColorTransform(matrix.data()); + execute(); +} + } // namespace } // namespace vts } // namespace V2_3 From 8edae5199e125925e407d9a26b0310db1cfbc363 Mon Sep 17 00:00:00 2001 From: Emilian Peev Date: Tue, 18 Sep 2018 14:27:13 +0100 Subject: [PATCH 104/718] Camera: Extend camera characteristics test case Verify that device implementations do not set the new privacy characteristics key: ANDROID_REQUEST_CHARACTERISTIC_KEYS_NEEDING_PERMISSION As required by API contract. Bug: 112160024 Bug: 115969437 Test: vts-tradefed run commandAndExit vts --skip-all-system-status-check --skip-preconditions --module VtsHalCameraProviderV2_4Target -l INFO Change-Id: I8d8f0d0e1cdec24117d47e7ae45602f56573376f --- .../vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp index 439333d9ca..f2a7836cd7 100644 --- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp +++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp @@ -2080,6 +2080,14 @@ TEST_F(CameraHidlTest, getCameraCharacteristics) { } else { ADD_FAILURE() << "Get camera hardware level failed!"; } + + entry.count = 0; + retcode = find_camera_metadata_ro_entry(metadata, + ANDROID_REQUEST_CHARACTERISTIC_KEYS_NEEDING_PERMISSION, &entry); + if ((0 == retcode) || (entry.count > 0)) { + ADD_FAILURE() << "ANDROID_REQUEST_CHARACTERISTIC_KEYS_NEEDING_PERMISSION " + << " per API contract should never be set by Hal!"; + } }); ASSERT_TRUE(ret.isOk()); } From b50428170e876ca31334afe4c37da40efeae21e3 Mon Sep 17 00:00:00 2001 From: Valerie Hau Date: Thu, 6 Sep 2018 14:31:07 -0700 Subject: [PATCH 105/718] Adding command tests for VTS V2_1 HWC Bug: 111563608 Test: ./VtsHalGraphicsComposerV2_1TargetTest Change-Id: I0ea1a26aa296a989f8b18fe8a95ec11e29a194c8 --- .../VtsHalGraphicsComposerV2_1TargetTest.cpp | 70 ++++++++++++++++++- 1 file changed, 67 insertions(+), 3 deletions(-) diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp index 8b8c7aeef3..0a3e88b3a2 100644 --- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp +++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp @@ -71,6 +71,7 @@ class GraphicsComposerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEn class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase { protected: void SetUp() override { + VtsHalHidlTargetTestBase::SetUp(); ASSERT_NO_FATAL_FAILURE( mComposer = std::make_unique( GraphicsComposerHidlEnvironment::Instance()->getServiceName())); @@ -100,6 +101,7 @@ class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase { EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount()); EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount()); } + VtsHalHidlTargetTestBase::TearDown(); } // returns an invalid display id (one that has not been registered to a @@ -668,6 +670,11 @@ class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest { ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique()); + Config activeConfig = mComposerClient->getActiveConfig(mPrimaryDisplay); + mDisplayWidth = mComposerClient->getDisplayAttribute(mPrimaryDisplay, activeConfig, + IComposerClient::Attribute::WIDTH); + mDisplayHeight = mComposerClient->getDisplayAttribute(mPrimaryDisplay, activeConfig, + IComposerClient::Attribute::HEIGHT); mWriter = std::make_unique(1024); mReader = std::make_unique(); } @@ -679,12 +686,13 @@ class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest { const native_handle_t* allocate() { IMapper::BufferDescriptorInfo info{}; - info.width = 64; - info.height = 64; + info.width = mDisplayWidth; + info.height = mDisplayHeight; info.layerCount = 1; info.format = PixelFormat::RGBA_8888; info.usage = - static_cast(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN); + static_cast(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN | + BufferUsage::COMPOSER_OVERLAY); return mGralloc->allocate(info); } @@ -693,6 +701,8 @@ class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest { std::unique_ptr mWriter; std::unique_ptr mReader; + int32_t mDisplayWidth; + int32_t mDisplayHeight; private: std::unique_ptr mGralloc; @@ -778,6 +788,60 @@ TEST_F(GraphicsComposerHidlCommandTest, PRESENT_DISPLAY) { execute(); } +/** + * Test IComposerClient::Command::PRESENT_DISPLAY + * + * Test that IComposerClient::Command::PRESENT_DISPLAY works without + * additional call to validateDisplay when only the layer buffer handle and + * surface damage have been set + */ +TEST_F(GraphicsComposerHidlCommandTest, PRESENT_DISPLAY_NO_LAYER_STATE_CHANGES) { + mWriter->selectDisplay(mPrimaryDisplay); + mComposerClient->setPowerMode(mPrimaryDisplay, IComposerClient::PowerMode::ON); + mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB); + + auto handle = allocate(); + ASSERT_NE(nullptr, handle); + + IComposerClient::Rect displayFrame{0, 0, mDisplayWidth, mDisplayHeight}; + + Layer layer; + ASSERT_NO_FATAL_FAILURE(layer = + mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); + mWriter->selectLayer(layer); + mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE); + mWriter->setLayerDisplayFrame(displayFrame); + mWriter->setLayerPlaneAlpha(1); + mWriter->setLayerSourceCrop({0, 0, (float)mDisplayWidth, (float)mDisplayHeight}); + mWriter->setLayerTransform(static_cast(0)); + mWriter->setLayerVisibleRegion(std::vector(1, displayFrame)); + mWriter->setLayerZOrder(10); + mWriter->setLayerBlendMode(IComposerClient::BlendMode::NONE); + mWriter->setLayerSurfaceDamage(std::vector(1, displayFrame)); + mWriter->setLayerBuffer(0, handle, -1); + mWriter->setLayerDataspace(Dataspace::UNKNOWN); + + mWriter->validateDisplay(); + execute(); + if (mReader->mCompositionChanges.size() != 0) { + GTEST_SUCCEED() << "Composition change requested, skipping test"; + return; + } + + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->presentDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + + mWriter->selectLayer(layer); + auto handle2 = allocate(); + ASSERT_NE(nullptr, handle2); + mWriter->setLayerBuffer(0, handle2, -1); + mWriter->setLayerSurfaceDamage(std::vector(1, {0, 0, 10, 10})); + mWriter->presentDisplay(); + execute(); +} + /** * Test IComposerClient::Command::SET_LAYER_CURSOR_POSITION. */ From 5c8e455d732c9952a7e58bff56df35ce7c31c3bc Mon Sep 17 00:00:00 2001 From: Sungtak Lee Date: Fri, 14 Sep 2018 14:57:02 -0700 Subject: [PATCH 106/718] Change buffer invalidataion FMQ to unsync Buffer Invalidation FMQ is designed as a shared FMQ between clients in order to minimize memory consumption. In that case, regarding FMQ is unsync FMQ in order to not to block writer in any situation. Bug: 112203066 Change-Id: I58989ccd332ba790193007f43dd66ecbd617f484 --- media/bufferpool/2.0/IAccessor.hal | 2 +- media/bufferpool/2.0/types.hal | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/media/bufferpool/2.0/IAccessor.hal b/media/bufferpool/2.0/IAccessor.hal index bd7094594e..ab7c02d458 100644 --- a/media/bufferpool/2.0/IAccessor.hal +++ b/media/bufferpool/2.0/IAccessor.hal @@ -68,5 +68,5 @@ interface IAccessor { generates (ResultStatus status, IConnection connection, int64_t connectionId, fmq_sync toFmqDesc, - fmq_sync fromFmqDesc); + fmq_unsync fromFmqDesc); }; diff --git a/media/bufferpool/2.0/types.hal b/media/bufferpool/2.0/types.hal index 7ce53b18bf..456e4aabda 100644 --- a/media/bufferpool/2.0/types.hal +++ b/media/bufferpool/2.0/types.hal @@ -100,7 +100,7 @@ struct BufferStatusMessage { struct BufferInvalidationMessage { /** * Buffers from fromBufferId to toBufferId must be invalidated. - * Both of fromBufferId and toBufferId are inclusive. + * fromBufferId is inclusive, but toBufferId is not inclusive. * If fromBufferId > toBufferID, wrap happens. In that case * the wrap is based on UINT32_MAX. */ From 3db024ec2781d12841790a9e44c76dff2136a5cc Mon Sep 17 00:00:00 2001 From: Yifan Hong Date: Wed, 19 Sep 2018 10:17:40 -0700 Subject: [PATCH 107/718] health.filesystem::IFileSystem -> health.storage::IStorage Rename the HAL because it is regarding 'storage health', not 'filesystem health'. Bug: 111655771 Test: compiles Change-Id: I07072c876fb07c88be8bd74cf6b84aec6020a697 --- health/{filesystem => storage}/1.0/Android.bp | 4 ++-- .../{filesystem => storage}/1.0/IGarbageCollectCallback.hal | 4 ++-- .../1.0/IFileSystem.hal => storage/1.0/IStorage.hal} | 6 +++--- health/{filesystem => storage}/1.0/types.hal | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) rename health/{filesystem => storage}/1.0/Android.bp (81%) rename health/{filesystem => storage}/1.0/IGarbageCollectCallback.hal (90%) rename health/{filesystem/1.0/IFileSystem.hal => storage/1.0/IStorage.hal} (91%) rename health/{filesystem => storage}/1.0/types.hal (95%) diff --git a/health/filesystem/1.0/Android.bp b/health/storage/1.0/Android.bp similarity index 81% rename from health/filesystem/1.0/Android.bp rename to health/storage/1.0/Android.bp index cb7cf0e88e..35ee34f207 100644 --- a/health/filesystem/1.0/Android.bp +++ b/health/storage/1.0/Android.bp @@ -1,15 +1,15 @@ // This file is autogenerated by hidl-gen -Landroidbp. hidl_interface { - name: "android.hardware.health.filesystem@1.0", + name: "android.hardware.health.storage@1.0", root: "android.hardware", vndk: { enabled: true, }, srcs: [ "types.hal", - "IFileSystem.hal", "IGarbageCollectCallback.hal", + "IStorage.hal", ], interfaces: [ "android.hidl.base@1.0", diff --git a/health/filesystem/1.0/IGarbageCollectCallback.hal b/health/storage/1.0/IGarbageCollectCallback.hal similarity index 90% rename from health/filesystem/1.0/IGarbageCollectCallback.hal rename to health/storage/1.0/IGarbageCollectCallback.hal index 901c35c86c..2c24ead14c 100644 --- a/health/filesystem/1.0/IGarbageCollectCallback.hal +++ b/health/storage/1.0/IGarbageCollectCallback.hal @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package android.hardware.health.filesystem@1.0; +package android.hardware.health.storage@1.0; /** - * Callback interface to IFileSystem.garbageCollect. + * Callback interface to IStorage.garbageCollect. */ interface IGarbageCollectCallback { /** diff --git a/health/filesystem/1.0/IFileSystem.hal b/health/storage/1.0/IStorage.hal similarity index 91% rename from health/filesystem/1.0/IFileSystem.hal rename to health/storage/1.0/IStorage.hal index a5e6487a63..980cf45de7 100644 --- a/health/filesystem/1.0/IFileSystem.hal +++ b/health/storage/1.0/IStorage.hal @@ -14,15 +14,15 @@ * limitations under the License. */ -package android.hardware.health.filesystem@1.0; +package android.hardware.health.storage@1.0; import IGarbageCollectCallback; /** - * IFileSystem is an interface that provides operations on underlying storage + * IStorage is an interface that provides operations on underlying storage * devices, including flash memory. */ -interface IFileSystem { +interface IStorage { /** * Start garbage collection on the driver of storage devices. * diff --git a/health/filesystem/1.0/types.hal b/health/storage/1.0/types.hal similarity index 95% rename from health/filesystem/1.0/types.hal rename to health/storage/1.0/types.hal index 0d2db2cdf4..2da0871e34 100644 --- a/health/filesystem/1.0/types.hal +++ b/health/storage/1.0/types.hal @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.hardware.health.filesystem@1.0; +package android.hardware.health.storage@1.0; /** * Status values for HAL methods. From 5a34303ad60fa0100b8f83edeb3b20b6a9c565cb Mon Sep 17 00:00:00 2001 From: Yifan Hong Date: Wed, 19 Sep 2018 14:06:25 -0700 Subject: [PATCH 108/718] matrix: health filesystem->storage Test: compiles Bug: 111655771 Change-Id: I088ec32e4e3d5796b4dbe3f062d8cf32e3644c66 --- compatibility_matrices/compatibility_matrix.current.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml index 73afb1bb35..88d1151840 100644 --- a/compatibility_matrices/compatibility_matrix.current.xml +++ b/compatibility_matrices/compatibility_matrix.current.xml @@ -216,10 +216,10 @@
- android.hardware.health.filesystem + android.hardware.health.storage 1.0 - IFileSystem + IStorage default From 0a9e402efe546540a2f74c24618f3a5938efe07e Mon Sep 17 00:00:00 2001 From: Kevin Chyn Date: Tue, 18 Sep 2018 13:54:40 -0700 Subject: [PATCH 109/718] Update FaceAcquiredInfo comments Fixes: 110887097 Test: builds Change-Id: Ia38043cf292401aea15a34118c2cc59cacd743f0 --- biometrics/face/1.0/types.hal | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/biometrics/face/1.0/types.hal b/biometrics/face/1.0/types.hal index 92cb70d7b6..2628af9ecf 100644 --- a/biometrics/face/1.0/types.hal +++ b/biometrics/face/1.0/types.hal @@ -212,8 +212,10 @@ enum FaceAcquiredInfo : int32_t { FACE_TOO_LEFT = 9, /** - * The user's face was directed away from the sensor. The user should be - * informed to face the sensor when this is returned. + * The user's eyes have strayed away from the sensor. If this message is + * sent, the user should be informed to look at the device. If the user + * can't be found in the frame, one of the other acquisition messages + * must be sent, e.g. NOT_DETECTED. */ POOR_GAZE = 10, @@ -234,7 +236,11 @@ enum FaceAcquiredInfo : int32_t { TOO_MUCH_MOTION = 12, /** - * The sensor needs to be recalibrated. + * The sensor needs to be re-calibrated. This is an unexpected condition, + * and must only be sent if a serious, uncorrectable, and unrecoverable + * calibration issue is detected which requires user intervention, e.g. + * re-enrolling. The expected response to this message is to direct the + * user to re-enroll. */ RECALIBRATE = 13, From 060a9acb3b982a51b4ae79f9456b3589229ba805 Mon Sep 17 00:00:00 2001 From: Slava Shklyaev Date: Fri, 7 Sep 2018 15:27:24 +0100 Subject: [PATCH 110/718] Create NeuralNetworks HAL v1.2 for new OperationTypes Bug: 114365802 Test: mm Change-Id: I86b9261729a64d02ed30dc822a0226de11473ac8 --- neuralnetworks/1.2/Android.bp | 24 +++++++ neuralnetworks/1.2/IDevice.hal | 106 +++++++++++++++++++++++++++++++ neuralnetworks/1.2/types.hal | 112 +++++++++++++++++++++++++++++++++ 3 files changed, 242 insertions(+) create mode 100644 neuralnetworks/1.2/Android.bp create mode 100644 neuralnetworks/1.2/IDevice.hal create mode 100644 neuralnetworks/1.2/types.hal diff --git a/neuralnetworks/1.2/Android.bp b/neuralnetworks/1.2/Android.bp new file mode 100644 index 0000000000..e183a263fa --- /dev/null +++ b/neuralnetworks/1.2/Android.bp @@ -0,0 +1,24 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +hidl_interface { + name: "android.hardware.neuralnetworks@1.2", + root: "android.hardware", + vndk: { + enabled: true, + }, + srcs: [ + "types.hal", + "IDevice.hal", + ], + interfaces: [ + "android.hardware.neuralnetworks@1.0", + "android.hardware.neuralnetworks@1.1", + "android.hidl.base@1.0", + ], + types: [ + "Model", + "Operation", + "OperationType", + ], + gen_java: false, +} diff --git a/neuralnetworks/1.2/IDevice.hal b/neuralnetworks/1.2/IDevice.hal new file mode 100644 index 0000000000..9cc23a26f5 --- /dev/null +++ b/neuralnetworks/1.2/IDevice.hal @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.neuralnetworks@1.2; + +import @1.0::ErrorStatus; +import @1.0::IPreparedModelCallback; +import @1.1::ExecutionPreference; +import @1.1::IDevice; + +/** + * This interface represents a device driver. + */ +interface IDevice extends @1.1::IDevice { + /** + * Gets the supported operations in a model. + * + * getSupportedOperations indicates which operations of a model are fully + * supported by the vendor driver. If an operation may not be supported for + * any reason, getSupportedOperations must return false for that operation. + * + * @param model A model whose operations--and their corresponding operands-- + * are to be verified by the driver. + * @return status Error status of the call, must be: + * - NONE if successful + * - DEVICE_UNAVAILABLE if driver is offline or busy + * - GENERAL_FAILURE if there is an unspecified error + * - INVALID_ARGUMENT if provided model is invalid + * @return supportedOperations A list of supported operations, where true + * indicates the operation is supported and false indicates the + * operation is not supported. The index of "supported" corresponds with + * the index of the operation it is describing. + */ + getSupportedOperations_1_2(Model model) + generates (ErrorStatus status, vec supportedOperations); + + /** + * Creates a prepared model for execution. + * + * prepareModel is used to make any necessary transformations or alternative + * representations to a model for execution, possibly including + * transformations on the constant data, optimization on the model's graph, + * or compilation into the device's native binary format. The model itself + * is not changed. + * + * The model is prepared asynchronously with respect to the caller. The + * prepareModel function must verify the inputs to the prepareModel function + * are correct. If there is an error, prepareModel must immediately invoke + * the callback with the appropriate ErrorStatus value and nullptr for the + * IPreparedModel, then return with the same ErrorStatus. If the inputs to + * the prepareModel function are valid and there is no error, prepareModel + * must launch an asynchronous task to prepare the model in the background, + * and immediately return from prepareModel with ErrorStatus::NONE. If the + * asynchronous task fails to launch, prepareModel must immediately invoke + * the callback with ErrorStatus::GENERAL_FAILURE and nullptr for the + * IPreparedModel, then return with ErrorStatus::GENERAL_FAILURE. + * + * When the asynchronous task has finished preparing the model, it must + * immediately invoke the callback function provided as an input to + * prepareModel. If the model was prepared successfully, the callback object + * must be invoked with an error status of ErrorStatus::NONE and the + * produced IPreparedModel object. If an error occurred preparing the model, + * the callback object must be invoked with the appropriate ErrorStatus + * value and nullptr for the IPreparedModel. + * + * The only information that may be unknown to the model at this stage is + * the shape of the tensors, which may only be known at execution time. As + * such, some driver services may return partially prepared models, where + * the prepared model may only be finished when it is paired with a set of + * inputs to the model. Note that the same prepared model object may be + * used with different shapes of inputs on different (possibly concurrent) + * executions. + * + * Multiple threads may call prepareModel on the same model concurrently. + * + * @param model The model to be prepared for execution. + * @param preference Indicates the intended execution behavior of a prepared + * model. + * @param callback A callback object used to return the error status of + * preparing the model for execution and the prepared model if + * successful, nullptr otherwise. The callback object's notify function + * must be called exactly once, even if the model could not be prepared. + * @return status Error status of launching a task which prepares the model + * in the background; must be: + * - NONE if preparation task is successfully launched + * - DEVICE_UNAVAILABLE if driver is offline or busy + * - GENERAL_FAILURE if there is an unspecified error + * - INVALID_ARGUMENT if one of the input arguments is invalid + */ + prepareModel_1_2(Model model, ExecutionPreference preference, + IPreparedModelCallback callback) + generates (ErrorStatus status); +}; diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal new file mode 100644 index 0000000000..06606cc330 --- /dev/null +++ b/neuralnetworks/1.2/types.hal @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.neuralnetworks@1.2; + +import @1.0::Operand; +import @1.0::PerformanceInfo; +import @1.1::OperationType; + +/** + * Operation types. + * + * The type of an operation in a model. + */ +enum OperationType : @1.1::OperationType { +}; + +/** + * Describes one operation of the model's graph. + */ +struct Operation { + /** + * The operation type. + */ + OperationType type; + + /** + * Describes the table that contains the indexes of the inputs of the + * operation. The offset is the index in the operandIndexes table. + */ + vec inputs; + + /** + * Describes the table that contains the indexes of the outputs of the + * operation. The offset is the index in the operandIndexes table. + */ + vec outputs; +}; + +/** + * A Neural Network Model. + * + * This includes not only the execution graph, but also constant data such as + * weights or scalars added at construction time. The only information that + * may not be known is the shape of the input tensors. + */ +struct Model { + /** + * All operands included in the model. + */ + vec operands; + + /** + * All operations included in the model. + * + * The operations are sorted into execution order. Every operand + * with lifetime MODEL_OUTPUT or TEMPORARY_VARIABLE must be + * written before it is read. + */ + vec operations; + + /** + * Input indexes of the model. There must be at least one. + * + * Each value corresponds to the index of the operand in "operands". + */ + vec inputIndexes; + + /** + * Output indexes of the model. There must be at least one. + * + * Each value corresponds to the index of the operand in "operands". + */ + vec outputIndexes; + + /** + * A byte buffer containing operand data that were copied into the model. + * + * An operand's value must be located here if and only if Operand::lifetime + * equals OperandLifeTime::CONSTANT_COPY. + */ + vec operandValues; + + /** + * A collection of shared memory pools containing operand values. + * + * An operand's value must be located here if and only if Operand::lifetime + * equals OperandLifeTime::CONSTANT_REFERENCE. + */ + vec pools; + + /** + * 'true' indicates TENSOR_FLOAT32 may be calculated with range and/or + * precision as low as that of the IEEE 754 16-bit floating-point format. + * 'false' indicates TENSOR_FLOAT32 must be calculated using at least the + * range and precision of the IEEE 754 32-bit floating-point format. + */ + bool relaxComputationFloat32toFloat16; +}; From 871be9477032e595f685e02f256b2909ea524fc0 Mon Sep 17 00:00:00 2001 From: Slava Shklyaev Date: Wed, 12 Sep 2018 14:52:02 +0100 Subject: [PATCH 111/718] Add VTS tests for NeuralNetworks v1.2 This is a copy the v1.1 tests since we don't have any new ops implemented in v1.2 yet. Bug: 114365802 Test: mm Test: NNAPI VTS Change-Id: Ida7525fcd3ae0fd6f88ff9591e06aba922bdae64 --- neuralnetworks/1.0/vts/functional/Android.bp | 4 +- .../vts/functional/GeneratedTestHarness.cpp | 52 ++ neuralnetworks/1.1/vts/functional/Android.bp | 1 + neuralnetworks/1.2/vts/OWNERS | 14 + neuralnetworks/1.2/vts/functional/Android.bp | 52 ++ .../1.2/vts/functional/BasicTests.cpp | 45 ++ .../1.2/vts/functional/GeneratedTests.cpp | 60 ++ neuralnetworks/1.2/vts/functional/Models.h | 378 ++++++++++++ .../1.2/vts/functional/ValidateModel.cpp | 538 ++++++++++++++++++ .../1.2/vts/functional/ValidateRequest.cpp | 261 +++++++++ .../1.2/vts/functional/ValidationTests.cpp | 50 ++ .../vts/functional/VtsHalNeuralnetworks.cpp | 86 +++ .../1.2/vts/functional/VtsHalNeuralnetworks.h | 92 +++ 13 files changed, 1632 insertions(+), 1 deletion(-) create mode 100644 neuralnetworks/1.2/vts/OWNERS create mode 100644 neuralnetworks/1.2/vts/functional/Android.bp create mode 100644 neuralnetworks/1.2/vts/functional/BasicTests.cpp create mode 100644 neuralnetworks/1.2/vts/functional/GeneratedTests.cpp create mode 100644 neuralnetworks/1.2/vts/functional/Models.h create mode 100644 neuralnetworks/1.2/vts/functional/ValidateModel.cpp create mode 100644 neuralnetworks/1.2/vts/functional/ValidateRequest.cpp create mode 100644 neuralnetworks/1.2/vts/functional/ValidationTests.cpp create mode 100644 neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp create mode 100644 neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h diff --git a/neuralnetworks/1.0/vts/functional/Android.bp b/neuralnetworks/1.0/vts/functional/Android.bp index e28113bcdc..18f35c1a16 100644 --- a/neuralnetworks/1.0/vts/functional/Android.bp +++ b/neuralnetworks/1.0/vts/functional/Android.bp @@ -25,6 +25,7 @@ cc_library_static { static_libs: [ "android.hardware.neuralnetworks@1.0", "android.hardware.neuralnetworks@1.1", + "android.hardware.neuralnetworks@1.2", "android.hidl.allocator@1.0", "android.hidl.memory@1.0", "libhidlmemory", @@ -49,8 +50,9 @@ cc_test { ], defaults: ["VtsHalTargetTestDefaults"], static_libs: [ - "android.hardware.neuralnetworks@1.1", "android.hardware.neuralnetworks@1.0", + "android.hardware.neuralnetworks@1.1", + "android.hardware.neuralnetworks@1.2", "android.hidl.allocator@1.0", "android.hidl.memory@1.0", "libhidlmemory", diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp index 64495cf763..b8046c79b2 100644 --- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp +++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp @@ -275,6 +275,58 @@ void Execute(const sp& device, std::function c EvaluatePreparedModel(preparedModel, is_ignored, examples, fpAtol, fpRtol); } +// TODO: Reduce code duplication. +void Execute(const sp& device, std::function create_model, + std::function is_ignored, + const std::vector& examples) { + V1_2::Model model = create_model(); + + // see if service can handle model + bool fullySupportsModel = false; + Return supportedCall = device->getSupportedOperations_1_2( + model, [&fullySupportsModel](ErrorStatus status, const hidl_vec& supported) { + ASSERT_EQ(ErrorStatus::NONE, status); + ASSERT_NE(0ul, supported.size()); + fullySupportsModel = + std::all_of(supported.begin(), supported.end(), [](bool valid) { return valid; }); + }); + ASSERT_TRUE(supportedCall.isOk()); + + // launch prepare model + sp preparedModelCallback = new PreparedModelCallback(); + ASSERT_NE(nullptr, preparedModelCallback.get()); + Return prepareLaunchStatus = device->prepareModel_1_2( + model, ExecutionPreference::FAST_SINGLE_ANSWER, preparedModelCallback); + ASSERT_TRUE(prepareLaunchStatus.isOk()); + ASSERT_EQ(ErrorStatus::NONE, static_cast(prepareLaunchStatus)); + + // retrieve prepared model + preparedModelCallback->wait(); + ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus(); + sp preparedModel = preparedModelCallback->getPreparedModel(); + + // early termination if vendor service cannot fully prepare model + if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) { + ASSERT_EQ(nullptr, preparedModel.get()); + LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot " + "prepare model that it does not support."; + std::cout << "[ ] Early termination of test because vendor service cannot " + "prepare model that it does not support." + << std::endl; + return; + } + EXPECT_EQ(ErrorStatus::NONE, prepareReturnStatus); + ASSERT_NE(nullptr, preparedModel.get()); + + // TODO: Adjust the error limit based on testing. + // If in relaxed mode, set the absolute tolerance to be 5ULP of FP16. + float fpAtol = !model.relaxComputationFloat32toFloat16 ? 1e-5f : 5.0f * 0.0009765625f; + // Set the relative tolerance to be 5ULP of the corresponding FP precision. + float fpRtol = !model.relaxComputationFloat32toFloat16 ? 5.0f * 1.1920928955078125e-7f + : 5.0f * 0.0009765625f; + EvaluatePreparedModel(preparedModel, is_ignored, examples, fpAtol, fpRtol); +} + } // namespace generated_tests } // namespace neuralnetworks diff --git a/neuralnetworks/1.1/vts/functional/Android.bp b/neuralnetworks/1.1/vts/functional/Android.bp index f755c20be5..52a804a8a3 100644 --- a/neuralnetworks/1.1/vts/functional/Android.bp +++ b/neuralnetworks/1.1/vts/functional/Android.bp @@ -28,6 +28,7 @@ cc_test { static_libs: [ "android.hardware.neuralnetworks@1.0", "android.hardware.neuralnetworks@1.1", + "android.hardware.neuralnetworks@1.2", "android.hidl.allocator@1.0", "android.hidl.memory@1.0", "libhidlmemory", diff --git a/neuralnetworks/1.2/vts/OWNERS b/neuralnetworks/1.2/vts/OWNERS new file mode 100644 index 0000000000..8f254365f6 --- /dev/null +++ b/neuralnetworks/1.2/vts/OWNERS @@ -0,0 +1,14 @@ +# Neuralnetworks team +butlermichael@google.com +dgross@google.com +jeanluc@google.com +levp@google.com +miaowang@google.com +mikie@google.com +mks@google.com +pszczepaniak@google.com +slavash@google.com + +# VTS team +yim@google.com +yuexima@google.com diff --git a/neuralnetworks/1.2/vts/functional/Android.bp b/neuralnetworks/1.2/vts/functional/Android.bp new file mode 100644 index 0000000000..2dc19ccbe4 --- /dev/null +++ b/neuralnetworks/1.2/vts/functional/Android.bp @@ -0,0 +1,52 @@ +// +// Copyright (C) 2018 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +cc_test { + name: "VtsHalNeuralnetworksV1_2TargetTest", + srcs: [ + "BasicTests.cpp", + "GeneratedTests.cpp", + "ValidateModel.cpp", + "ValidateRequest.cpp", + "ValidationTests.cpp", + "VtsHalNeuralnetworks.cpp", + ], + defaults: ["VtsHalTargetTestDefaults"], + static_libs: [ + "android.hardware.neuralnetworks@1.0", + "android.hardware.neuralnetworks@1.1", + "android.hardware.neuralnetworks@1.2", + "android.hidl.allocator@1.0", + "android.hidl.memory@1.0", + "libhidlmemory", + "libneuralnetworks_utils", + "VtsHalNeuralnetworksTest_utils", + ], + header_libs: [ + "libneuralnetworks_headers", + "libneuralnetworks_generated_test_harness_headers", + "libneuralnetworks_generated_tests", + ], + // Bug: http://b/74200014 - Disable arm32 asan since it triggers internal + // error in ld.gold. + arch: { + arm: { + sanitize: { + never: true, + }, + }, + }, +} diff --git a/neuralnetworks/1.2/vts/functional/BasicTests.cpp b/neuralnetworks/1.2/vts/functional/BasicTests.cpp new file mode 100644 index 0000000000..d2dea1dc75 --- /dev/null +++ b/neuralnetworks/1.2/vts/functional/BasicTests.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "neuralnetworks_hidl_hal_test" + +#include "VtsHalNeuralnetworks.h" + +namespace android { +namespace hardware { +namespace neuralnetworks { +namespace V1_2 { +namespace vts { +namespace functional { + +using V1_1::Capabilities; + +// create device test +TEST_F(NeuralnetworksHidlTest, CreateDevice) {} + +// status test +TEST_F(NeuralnetworksHidlTest, StatusTest) { + Return status = device->getStatus(); + ASSERT_TRUE(status.isOk()); + EXPECT_EQ(DeviceStatus::AVAILABLE, static_cast(status)); +} + +} // namespace functional +} // namespace vts +} // namespace V1_2 +} // namespace neuralnetworks +} // namespace hardware +} // namespace android diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp b/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp new file mode 100644 index 0000000000..662c531340 --- /dev/null +++ b/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "neuralnetworks_hidl_hal_test" + +#include "VtsHalNeuralnetworks.h" + +#include "Callbacks.h" +#include "TestHarness.h" +#include "Utils.h" + +#include +#include +#include + +namespace android { +namespace hardware { +namespace neuralnetworks { + +namespace generated_tests { +using ::test_helper::MixedTypedExampleType; +extern void Execute(const sp&, std::function, + std::function, const std::vector&); +} // namespace generated_tests + +namespace V1_2 { +namespace vts { +namespace functional { + +using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback; +using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback; +using ::android::nn::allocateSharedMemory; + +// Mixed-typed examples +typedef generated_tests::MixedTypedExampleType MixedTypedExample; + +// in frameworks/ml/nn/runtime/tests/generated/ +#include "all_generated_V1_0_vts_tests.cpp" +#include "all_generated_V1_1_vts_tests.cpp" +#include "all_generated_V1_2_vts_tests.cpp" + +} // namespace functional +} // namespace vts +} // namespace V1_2 +} // namespace neuralnetworks +} // namespace hardware +} // namespace android diff --git a/neuralnetworks/1.2/vts/functional/Models.h b/neuralnetworks/1.2/vts/functional/Models.h new file mode 100644 index 0000000000..f3769bc677 --- /dev/null +++ b/neuralnetworks/1.2/vts/functional/Models.h @@ -0,0 +1,378 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VTS_HAL_NEURALNETWORKS_V1_2_VTS_FUNCTIONAL_MODELS_H +#define VTS_HAL_NEURALNETWORKS_V1_2_VTS_FUNCTIONAL_MODELS_H + +#define LOG_TAG "neuralnetworks_hidl_hal_test" + +#include "TestHarness.h" + +#include +#include +#include + +namespace android { +namespace hardware { +namespace neuralnetworks { +namespace V1_2 { +namespace vts { +namespace functional { + +using MixedTypedExample = test_helper::MixedTypedExampleType; + +#define FOR_EACH_TEST_MODEL(FN) \ + FN(add) \ + FN(add_broadcast_quant8) \ + FN(add_quant8) \ + FN(add_relaxed) \ + FN(avg_pool_float_1) \ + FN(avg_pool_float_1_relaxed) \ + FN(avg_pool_float_2) \ + FN(avg_pool_float_2_relaxed) \ + FN(avg_pool_float_3) \ + FN(avg_pool_float_3_relaxed) \ + FN(avg_pool_float_4) \ + FN(avg_pool_float_4_relaxed) \ + FN(avg_pool_float_5) \ + FN(avg_pool_float_5_relaxed) \ + FN(avg_pool_quant8_1) \ + FN(avg_pool_quant8_2) \ + FN(avg_pool_quant8_3) \ + FN(avg_pool_quant8_4) \ + FN(avg_pool_quant8_5) \ + FN(batch_to_space) \ + FN(batch_to_space_float_1) \ + FN(batch_to_space_float_1_relaxed) \ + FN(batch_to_space_quant8_1) \ + FN(batch_to_space_relaxed) \ + FN(concat_float_1) \ + FN(concat_float_1_relaxed) \ + FN(concat_float_2) \ + FN(concat_float_2_relaxed) \ + FN(concat_float_3) \ + FN(concat_float_3_relaxed) \ + FN(concat_quant8_1) \ + FN(concat_quant8_2) \ + FN(concat_quant8_3) \ + FN(conv_1_h3_w2_SAME) \ + FN(conv_1_h3_w2_SAME_relaxed) \ + FN(conv_1_h3_w2_VALID) \ + FN(conv_1_h3_w2_VALID_relaxed) \ + FN(conv_3_h3_w2_SAME) \ + FN(conv_3_h3_w2_SAME_relaxed) \ + FN(conv_3_h3_w2_VALID) \ + FN(conv_3_h3_w2_VALID_relaxed) \ + FN(conv_float) \ + FN(conv_float_2) \ + FN(conv_float_2_relaxed) \ + FN(conv_float_channels) \ + FN(conv_float_channels_relaxed) \ + FN(conv_float_channels_weights_as_inputs) \ + FN(conv_float_channels_weights_as_inputs_relaxed) \ + FN(conv_float_large) \ + FN(conv_float_large_relaxed) \ + FN(conv_float_large_weights_as_inputs) \ + FN(conv_float_large_weights_as_inputs_relaxed) \ + FN(conv_float_relaxed) \ + FN(conv_float_weights_as_inputs) \ + FN(conv_float_weights_as_inputs_relaxed) \ + FN(conv_quant8) \ + FN(conv_quant8_2) \ + FN(conv_quant8_channels) \ + FN(conv_quant8_channels_weights_as_inputs) \ + FN(conv_quant8_large) \ + FN(conv_quant8_large_weights_as_inputs) \ + FN(conv_quant8_overflow) \ + FN(conv_quant8_overflow_weights_as_inputs) \ + FN(conv_quant8_weights_as_inputs) \ + FN(depth_to_space_float_1) \ + FN(depth_to_space_float_1_relaxed) \ + FN(depth_to_space_float_2) \ + FN(depth_to_space_float_2_relaxed) \ + FN(depth_to_space_float_3) \ + FN(depth_to_space_float_3_relaxed) \ + FN(depth_to_space_quant8_1) \ + FN(depth_to_space_quant8_2) \ + FN(depthwise_conv) \ + FN(depthwise_conv2d_float) \ + FN(depthwise_conv2d_float_2) \ + FN(depthwise_conv2d_float_2_relaxed) \ + FN(depthwise_conv2d_float_large) \ + FN(depthwise_conv2d_float_large_2) \ + FN(depthwise_conv2d_float_large_2_relaxed) \ + FN(depthwise_conv2d_float_large_2_weights_as_inputs) \ + FN(depthwise_conv2d_float_large_2_weights_as_inputs_relaxed) \ + FN(depthwise_conv2d_float_large_relaxed) \ + FN(depthwise_conv2d_float_large_weights_as_inputs) \ + FN(depthwise_conv2d_float_large_weights_as_inputs_relaxed) \ + FN(depthwise_conv2d_float_relaxed) \ + FN(depthwise_conv2d_float_weights_as_inputs) \ + FN(depthwise_conv2d_float_weights_as_inputs_relaxed) \ + FN(depthwise_conv2d_quant8) \ + FN(depthwise_conv2d_quant8_2) \ + FN(depthwise_conv2d_quant8_large) \ + FN(depthwise_conv2d_quant8_large_weights_as_inputs) \ + FN(depthwise_conv2d_quant8_weights_as_inputs) \ + FN(depthwise_conv_relaxed) \ + FN(dequantize) \ + FN(dequantize_relaxed) \ + FN(div) \ + FN(div_broadcast_float) \ + FN(div_broadcast_float_relaxed) \ + FN(div_relaxed) \ + FN(embedding_lookup) \ + FN(embedding_lookup_relaxed) \ + FN(floor) \ + FN(floor_relaxed) \ + FN(fully_connected_float) \ + FN(fully_connected_float_2) \ + FN(fully_connected_float_2_relaxed) \ + FN(fully_connected_float_4d_simple) \ + FN(fully_connected_float_4d_simple_relaxed) \ + FN(fully_connected_float_large) \ + FN(fully_connected_float_large_relaxed) \ + FN(fully_connected_float_large_weights_as_inputs) \ + FN(fully_connected_float_large_weights_as_inputs_relaxed) \ + FN(fully_connected_float_relaxed) \ + FN(fully_connected_float_weights_as_inputs) \ + FN(fully_connected_float_weights_as_inputs_relaxed) \ + FN(fully_connected_quant8) \ + FN(fully_connected_quant8_2) \ + FN(fully_connected_quant8_large) \ + FN(fully_connected_quant8_large_weights_as_inputs) \ + FN(fully_connected_quant8_weights_as_inputs) \ + FN(hashtable_lookup_float) \ + FN(hashtable_lookup_float_relaxed) \ + FN(hashtable_lookup_quant8) \ + FN(l2_normalization) \ + FN(l2_normalization_2) \ + FN(l2_normalization_2_relaxed) \ + FN(l2_normalization_large) \ + FN(l2_normalization_large_relaxed) \ + FN(l2_normalization_relaxed) \ + FN(l2_pool_float) \ + FN(l2_pool_float_2) \ + FN(l2_pool_float_2_relaxed) \ + FN(l2_pool_float_large) \ + FN(l2_pool_float_large_relaxed) \ + FN(l2_pool_float_relaxed) \ + FN(local_response_norm_float_1) \ + FN(local_response_norm_float_1_relaxed) \ + FN(local_response_norm_float_2) \ + FN(local_response_norm_float_2_relaxed) \ + FN(local_response_norm_float_3) \ + FN(local_response_norm_float_3_relaxed) \ + FN(local_response_norm_float_4) \ + FN(local_response_norm_float_4_relaxed) \ + FN(logistic_float_1) \ + FN(logistic_float_1_relaxed) \ + FN(logistic_float_2) \ + FN(logistic_float_2_relaxed) \ + FN(logistic_quant8_1) \ + FN(logistic_quant8_2) \ + FN(lsh_projection) \ + FN(lsh_projection_2) \ + FN(lsh_projection_2_relaxed) \ + FN(lsh_projection_relaxed) \ + FN(lsh_projection_weights_as_inputs) \ + FN(lsh_projection_weights_as_inputs_relaxed) \ + FN(lstm) \ + FN(lstm2) \ + FN(lstm2_relaxed) \ + FN(lstm2_state) \ + FN(lstm2_state2) \ + FN(lstm2_state2_relaxed) \ + FN(lstm2_state_relaxed) \ + FN(lstm3) \ + FN(lstm3_relaxed) \ + FN(lstm3_state) \ + FN(lstm3_state2) \ + FN(lstm3_state2_relaxed) \ + FN(lstm3_state3) \ + FN(lstm3_state3_relaxed) \ + FN(lstm3_state_relaxed) \ + FN(lstm_relaxed) \ + FN(lstm_state) \ + FN(lstm_state2) \ + FN(lstm_state2_relaxed) \ + FN(lstm_state_relaxed) \ + FN(max_pool_float_1) \ + FN(max_pool_float_1_relaxed) \ + FN(max_pool_float_2) \ + FN(max_pool_float_2_relaxed) \ + FN(max_pool_float_3) \ + FN(max_pool_float_3_relaxed) \ + FN(max_pool_float_4) \ + FN(max_pool_float_4_relaxed) \ + FN(max_pool_quant8_1) \ + FN(max_pool_quant8_2) \ + FN(max_pool_quant8_3) \ + FN(max_pool_quant8_4) \ + FN(mean) \ + FN(mean_float_1) \ + FN(mean_float_1_relaxed) \ + FN(mean_float_2) \ + FN(mean_float_2_relaxed) \ + FN(mean_quant8_1) \ + FN(mean_quant8_2) \ + FN(mean_relaxed) \ + FN(mobilenet_224_gender_basic_fixed) \ + FN(mobilenet_224_gender_basic_fixed_relaxed) \ + FN(mobilenet_quantized) \ + FN(mul) \ + FN(mul_broadcast_quant8) \ + FN(mul_quant8) \ + FN(mul_relaxed) \ + FN(mul_relu) \ + FN(mul_relu_relaxed) \ + FN(pad) \ + FN(pad_float_1) \ + FN(pad_float_1_relaxed) \ + FN(pad_relaxed) \ + FN(relu1_float_1) \ + FN(relu1_float_1_relaxed) \ + FN(relu1_float_2) \ + FN(relu1_float_2_relaxed) \ + FN(relu1_quant8_1) \ + FN(relu1_quant8_2) \ + FN(relu6_float_1) \ + FN(relu6_float_1_relaxed) \ + FN(relu6_float_2) \ + FN(relu6_float_2_relaxed) \ + FN(relu6_quant8_1) \ + FN(relu6_quant8_2) \ + FN(relu_float_1) \ + FN(relu_float_1_relaxed) \ + FN(relu_float_2) \ + FN(relu_float_2_relaxed) \ + FN(relu_quant8_1) \ + FN(relu_quant8_2) \ + FN(reshape) \ + FN(reshape_quant8) \ + FN(reshape_quant8_weights_as_inputs) \ + FN(reshape_relaxed) \ + FN(reshape_weights_as_inputs) \ + FN(reshape_weights_as_inputs_relaxed) \ + FN(resize_bilinear) \ + FN(resize_bilinear_2) \ + FN(resize_bilinear_2_relaxed) \ + FN(resize_bilinear_relaxed) \ + FN(rnn) \ + FN(rnn_relaxed) \ + FN(rnn_state) \ + FN(rnn_state_relaxed) \ + FN(softmax_float_1) \ + FN(softmax_float_1_relaxed) \ + FN(softmax_float_2) \ + FN(softmax_float_2_relaxed) \ + FN(softmax_quant8_1) \ + FN(softmax_quant8_2) \ + FN(space_to_batch) \ + FN(space_to_batch_float_1) \ + FN(space_to_batch_float_1_relaxed) \ + FN(space_to_batch_float_2) \ + FN(space_to_batch_float_2_relaxed) \ + FN(space_to_batch_float_3) \ + FN(space_to_batch_float_3_relaxed) \ + FN(space_to_batch_quant8_1) \ + FN(space_to_batch_quant8_2) \ + FN(space_to_batch_quant8_3) \ + FN(space_to_batch_relaxed) \ + FN(space_to_depth_float_1) \ + FN(space_to_depth_float_1_relaxed) \ + FN(space_to_depth_float_2) \ + FN(space_to_depth_float_2_relaxed) \ + FN(space_to_depth_float_3) \ + FN(space_to_depth_float_3_relaxed) \ + FN(space_to_depth_quant8_1) \ + FN(space_to_depth_quant8_2) \ + FN(squeeze) \ + FN(squeeze_float_1) \ + FN(squeeze_float_1_relaxed) \ + FN(squeeze_quant8_1) \ + FN(squeeze_relaxed) \ + FN(strided_slice) \ + FN(strided_slice_float_1) \ + FN(strided_slice_float_10) \ + FN(strided_slice_float_10_relaxed) \ + FN(strided_slice_float_11) \ + FN(strided_slice_float_11_relaxed) \ + FN(strided_slice_float_1_relaxed) \ + FN(strided_slice_float_2) \ + FN(strided_slice_float_2_relaxed) \ + FN(strided_slice_float_3) \ + FN(strided_slice_float_3_relaxed) \ + FN(strided_slice_float_4) \ + FN(strided_slice_float_4_relaxed) \ + FN(strided_slice_float_5) \ + FN(strided_slice_float_5_relaxed) \ + FN(strided_slice_float_6) \ + FN(strided_slice_float_6_relaxed) \ + FN(strided_slice_float_7) \ + FN(strided_slice_float_7_relaxed) \ + FN(strided_slice_float_8) \ + FN(strided_slice_float_8_relaxed) \ + FN(strided_slice_float_9) \ + FN(strided_slice_float_9_relaxed) \ + FN(strided_slice_qaunt8_10) \ + FN(strided_slice_qaunt8_11) \ + FN(strided_slice_quant8_1) \ + FN(strided_slice_quant8_2) \ + FN(strided_slice_quant8_3) \ + FN(strided_slice_quant8_4) \ + FN(strided_slice_quant8_5) \ + FN(strided_slice_quant8_6) \ + FN(strided_slice_quant8_7) \ + FN(strided_slice_quant8_8) \ + FN(strided_slice_quant8_9) \ + FN(strided_slice_relaxed) \ + FN(sub) \ + FN(sub_broadcast_float) \ + FN(sub_broadcast_float_relaxed) \ + FN(sub_relaxed) \ + FN(svdf) \ + FN(svdf2) \ + FN(svdf2_relaxed) \ + FN(svdf_relaxed) \ + FN(svdf_state) \ + FN(svdf_state_relaxed) \ + FN(tanh) \ + FN(tanh_relaxed) \ + FN(transpose) \ + FN(transpose_float_1) \ + FN(transpose_float_1_relaxed) \ + FN(transpose_quant8_1) \ + FN(transpose_relaxed) + +#define FORWARD_DECLARE_GENERATED_OBJECTS(function) \ + namespace function { \ + extern std::vector examples; \ + Model createTestModel(); \ + } + +FOR_EACH_TEST_MODEL(FORWARD_DECLARE_GENERATED_OBJECTS) + +#undef FORWARD_DECLARE_GENERATED_OBJECTS + +} // namespace functional +} // namespace vts +} // namespace V1_2 +} // namespace neuralnetworks +} // namespace hardware +} // namespace android + +#endif // VTS_HAL_NEURALNETWORKS_V1_2_VTS_FUNCTIONAL_MODELS_H diff --git a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp new file mode 100644 index 0000000000..7ec6ff183e --- /dev/null +++ b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp @@ -0,0 +1,538 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "neuralnetworks_hidl_hal_test" + +#include "VtsHalNeuralnetworks.h" + +#include "Callbacks.h" + +namespace android { +namespace hardware { +namespace neuralnetworks { +namespace V1_2 { + +using V1_0::IPreparedModel; +using V1_0::Operand; +using V1_0::OperandLifeTime; +using V1_0::OperandType; +using V1_1::ExecutionPreference; + +namespace vts { +namespace functional { + +using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback; +using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback; + +///////////////////////// UTILITY FUNCTIONS ///////////////////////// + +static void validateGetSupportedOperations(const sp& device, const std::string& message, + const Model& model) { + SCOPED_TRACE(message + " [getSupportedOperations_1_2]"); + + Return ret = + device->getSupportedOperations_1_2(model, [&](ErrorStatus status, const hidl_vec&) { + EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status); + }); + EXPECT_TRUE(ret.isOk()); +} + +static void validatePrepareModel(const sp& device, const std::string& message, + const Model& model, ExecutionPreference preference) { + SCOPED_TRACE(message + " [prepareModel_1_2]"); + + sp preparedModelCallback = new PreparedModelCallback(); + ASSERT_NE(nullptr, preparedModelCallback.get()); + Return prepareLaunchStatus = + device->prepareModel_1_2(model, preference, preparedModelCallback); + ASSERT_TRUE(prepareLaunchStatus.isOk()); + ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast(prepareLaunchStatus)); + + preparedModelCallback->wait(); + ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus(); + ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, prepareReturnStatus); + sp preparedModel = preparedModelCallback->getPreparedModel(); + ASSERT_EQ(nullptr, preparedModel.get()); +} + +static bool validExecutionPreference(ExecutionPreference preference) { + return preference == ExecutionPreference::LOW_POWER || + preference == ExecutionPreference::FAST_SINGLE_ANSWER || + preference == ExecutionPreference::SUSTAINED_SPEED; +} + +// Primary validation function. This function will take a valid model, apply a +// mutation to it to invalidate the model, then pass it to interface calls that +// use the model. Note that the model here is passed by value, and any mutation +// to the model does not leave this function. +static void validate(const sp& device, const std::string& message, Model model, + const std::function& mutation, + ExecutionPreference preference = ExecutionPreference::FAST_SINGLE_ANSWER) { + mutation(&model); + if (validExecutionPreference(preference)) { + validateGetSupportedOperations(device, message, model); + } + validatePrepareModel(device, message, model, preference); +} + +// Delete element from hidl_vec. hidl_vec doesn't support a "remove" operation, +// so this is efficiently accomplished by moving the element to the end and +// resizing the hidl_vec to one less. +template +static void hidl_vec_removeAt(hidl_vec* vec, uint32_t index) { + if (vec) { + std::rotate(vec->begin() + index, vec->begin() + index + 1, vec->end()); + vec->resize(vec->size() - 1); + } +} + +template +static uint32_t hidl_vec_push_back(hidl_vec* vec, const Type& value) { + // assume vec is valid + const uint32_t index = vec->size(); + vec->resize(index + 1); + (*vec)[index] = value; + return index; +} + +static uint32_t addOperand(Model* model) { + return hidl_vec_push_back(&model->operands, + { + .type = OperandType::INT32, + .dimensions = {}, + .numberOfConsumers = 0, + .scale = 0.0f, + .zeroPoint = 0, + .lifetime = OperandLifeTime::MODEL_INPUT, + .location = {.poolIndex = 0, .offset = 0, .length = 0}, + }); +} + +static uint32_t addOperand(Model* model, OperandLifeTime lifetime) { + uint32_t index = addOperand(model); + model->operands[index].numberOfConsumers = 1; + model->operands[index].lifetime = lifetime; + return index; +} + +///////////////////////// VALIDATE MODEL OPERAND TYPE ///////////////////////// + +static const int32_t invalidOperandTypes[] = { + static_cast(OperandType::FLOAT32) - 1, // lower bound fundamental + static_cast(OperandType::TENSOR_QUANT8_ASYMM) + 1, // upper bound fundamental + static_cast(OperandType::OEM) - 1, // lower bound OEM + static_cast(OperandType::TENSOR_OEM_BYTE) + 1, // upper bound OEM +}; + +static void mutateOperandTypeTest(const sp& device, const Model& model) { + for (size_t operand = 0; operand < model.operands.size(); ++operand) { + for (int32_t invalidOperandType : invalidOperandTypes) { + const std::string message = "mutateOperandTypeTest: operand " + + std::to_string(operand) + " set to value " + + std::to_string(invalidOperandType); + validate(device, message, model, [operand, invalidOperandType](Model* model) { + model->operands[operand].type = static_cast(invalidOperandType); + }); + } + } +} + +///////////////////////// VALIDATE OPERAND RANK ///////////////////////// + +static uint32_t getInvalidRank(OperandType type) { + switch (type) { + case OperandType::FLOAT32: + case OperandType::INT32: + case OperandType::UINT32: + return 1; + case OperandType::TENSOR_FLOAT32: + case OperandType::TENSOR_INT32: + case OperandType::TENSOR_QUANT8_ASYMM: + return 0; + default: + return 0; + } +} + +static void mutateOperandRankTest(const sp& device, const Model& model) { + for (size_t operand = 0; operand < model.operands.size(); ++operand) { + const uint32_t invalidRank = getInvalidRank(model.operands[operand].type); + const std::string message = "mutateOperandRankTest: operand " + std::to_string(operand) + + " has rank of " + std::to_string(invalidRank); + validate(device, message, model, [operand, invalidRank](Model* model) { + model->operands[operand].dimensions = std::vector(invalidRank, 0); + }); + } +} + +///////////////////////// VALIDATE OPERAND SCALE ///////////////////////// + +static float getInvalidScale(OperandType type) { + switch (type) { + case OperandType::FLOAT32: + case OperandType::INT32: + case OperandType::UINT32: + case OperandType::TENSOR_FLOAT32: + return 1.0f; + case OperandType::TENSOR_INT32: + return -1.0f; + case OperandType::TENSOR_QUANT8_ASYMM: + return 0.0f; + default: + return 0.0f; + } +} + +static void mutateOperandScaleTest(const sp& device, const Model& model) { + for (size_t operand = 0; operand < model.operands.size(); ++operand) { + const float invalidScale = getInvalidScale(model.operands[operand].type); + const std::string message = "mutateOperandScaleTest: operand " + std::to_string(operand) + + " has scale of " + std::to_string(invalidScale); + validate(device, message, model, [operand, invalidScale](Model* model) { + model->operands[operand].scale = invalidScale; + }); + } +} + +///////////////////////// VALIDATE OPERAND ZERO POINT ///////////////////////// + +static std::vector getInvalidZeroPoints(OperandType type) { + switch (type) { + case OperandType::FLOAT32: + case OperandType::INT32: + case OperandType::UINT32: + case OperandType::TENSOR_FLOAT32: + case OperandType::TENSOR_INT32: + return {1}; + case OperandType::TENSOR_QUANT8_ASYMM: + return {-1, 256}; + default: + return {}; + } +} + +static void mutateOperandZeroPointTest(const sp& device, const Model& model) { + for (size_t operand = 0; operand < model.operands.size(); ++operand) { + const std::vector invalidZeroPoints = + getInvalidZeroPoints(model.operands[operand].type); + for (int32_t invalidZeroPoint : invalidZeroPoints) { + const std::string message = "mutateOperandZeroPointTest: operand " + + std::to_string(operand) + " has zero point of " + + std::to_string(invalidZeroPoint); + validate(device, message, model, [operand, invalidZeroPoint](Model* model) { + model->operands[operand].zeroPoint = invalidZeroPoint; + }); + } + } +} + +///////////////////////// VALIDATE EXTRA ??? ///////////////////////// + +// TODO: Operand::lifetime +// TODO: Operand::location + +///////////////////////// VALIDATE OPERATION OPERAND TYPE ///////////////////////// + +static void mutateOperand(Operand* operand, OperandType type) { + Operand newOperand = *operand; + newOperand.type = type; + switch (type) { + case OperandType::FLOAT32: + case OperandType::INT32: + case OperandType::UINT32: + newOperand.dimensions = hidl_vec(); + newOperand.scale = 0.0f; + newOperand.zeroPoint = 0; + break; + case OperandType::TENSOR_FLOAT32: + newOperand.dimensions = + operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec({1}); + newOperand.scale = 0.0f; + newOperand.zeroPoint = 0; + break; + case OperandType::TENSOR_INT32: + newOperand.dimensions = + operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec({1}); + newOperand.zeroPoint = 0; + break; + case OperandType::TENSOR_QUANT8_ASYMM: + newOperand.dimensions = + operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec({1}); + newOperand.scale = operand->scale != 0.0f ? operand->scale : 1.0f; + break; + case OperandType::OEM: + case OperandType::TENSOR_OEM_BYTE: + default: + break; + } + *operand = newOperand; +} + +static bool mutateOperationOperandTypeSkip(size_t operand, const Model& model) { + // LSH_PROJECTION's second argument is allowed to have any type. This is the + // only operation that currently has a type that can be anything independent + // from any other type. Changing the operand type to any other type will + // result in a valid model for LSH_PROJECTION. If this is the case, skip the + // test. + for (const Operation& operation : model.operations) { + if (operation.type == OperationType::LSH_PROJECTION && operand == operation.inputs[1]) { + return true; + } + } + return false; +} + +static void mutateOperationOperandTypeTest(const sp& device, const Model& model) { + for (size_t operand = 0; operand < model.operands.size(); ++operand) { + if (mutateOperationOperandTypeSkip(operand, model)) { + continue; + } + for (OperandType invalidOperandType : hidl_enum_range{}) { + // Do not test OEM types + if (invalidOperandType == model.operands[operand].type || + invalidOperandType == OperandType::OEM || + invalidOperandType == OperandType::TENSOR_OEM_BYTE) { + continue; + } + const std::string message = "mutateOperationOperandTypeTest: operand " + + std::to_string(operand) + " set to type " + + toString(invalidOperandType); + validate(device, message, model, [operand, invalidOperandType](Model* model) { + mutateOperand(&model->operands[operand], invalidOperandType); + }); + } + } +} + +///////////////////////// VALIDATE MODEL OPERATION TYPE ///////////////////////// + +static const int32_t invalidOperationTypes[] = { + static_cast(OperationType::ADD) - 1, // lower bound fundamental + static_cast(OperationType::TRANSPOSE) + 1, // upper bound fundamental + static_cast(OperationType::OEM_OPERATION) - 1, // lower bound OEM + static_cast(OperationType::OEM_OPERATION) + 1, // upper bound OEM +}; + +static void mutateOperationTypeTest(const sp& device, const Model& model) { + for (size_t operation = 0; operation < model.operations.size(); ++operation) { + for (int32_t invalidOperationType : invalidOperationTypes) { + const std::string message = "mutateOperationTypeTest: operation " + + std::to_string(operation) + " set to value " + + std::to_string(invalidOperationType); + validate(device, message, model, [operation, invalidOperationType](Model* model) { + model->operations[operation].type = + static_cast(invalidOperationType); + }); + } + } +} + +///////////////////////// VALIDATE MODEL OPERATION INPUT OPERAND INDEX ///////////////////////// + +static void mutateOperationInputOperandIndexTest(const sp& device, const Model& model) { + for (size_t operation = 0; operation < model.operations.size(); ++operation) { + const uint32_t invalidOperand = model.operands.size(); + for (size_t input = 0; input < model.operations[operation].inputs.size(); ++input) { + const std::string message = "mutateOperationInputOperandIndexTest: operation " + + std::to_string(operation) + " input " + + std::to_string(input); + validate(device, message, model, [operation, input, invalidOperand](Model* model) { + model->operations[operation].inputs[input] = invalidOperand; + }); + } + } +} + +///////////////////////// VALIDATE MODEL OPERATION OUTPUT OPERAND INDEX ///////////////////////// + +static void mutateOperationOutputOperandIndexTest(const sp& device, const Model& model) { + for (size_t operation = 0; operation < model.operations.size(); ++operation) { + const uint32_t invalidOperand = model.operands.size(); + for (size_t output = 0; output < model.operations[operation].outputs.size(); ++output) { + const std::string message = "mutateOperationOutputOperandIndexTest: operation " + + std::to_string(operation) + " output " + + std::to_string(output); + validate(device, message, model, [operation, output, invalidOperand](Model* model) { + model->operations[operation].outputs[output] = invalidOperand; + }); + } + } +} + +///////////////////////// REMOVE OPERAND FROM EVERYTHING ///////////////////////// + +static void removeValueAndDecrementGreaterValues(hidl_vec* vec, uint32_t value) { + if (vec) { + // remove elements matching "value" + auto last = std::remove(vec->begin(), vec->end(), value); + vec->resize(std::distance(vec->begin(), last)); + + // decrement elements exceeding "value" + std::transform(vec->begin(), vec->end(), vec->begin(), + [value](uint32_t v) { return v > value ? v-- : v; }); + } +} + +static void removeOperand(Model* model, uint32_t index) { + hidl_vec_removeAt(&model->operands, index); + for (Operation& operation : model->operations) { + removeValueAndDecrementGreaterValues(&operation.inputs, index); + removeValueAndDecrementGreaterValues(&operation.outputs, index); + } + removeValueAndDecrementGreaterValues(&model->inputIndexes, index); + removeValueAndDecrementGreaterValues(&model->outputIndexes, index); +} + +static void removeOperandTest(const sp& device, const Model& model) { + for (size_t operand = 0; operand < model.operands.size(); ++operand) { + const std::string message = "removeOperandTest: operand " + std::to_string(operand); + validate(device, message, model, + [operand](Model* model) { removeOperand(model, operand); }); + } +} + +///////////////////////// REMOVE OPERATION ///////////////////////// + +static void removeOperation(Model* model, uint32_t index) { + for (uint32_t operand : model->operations[index].inputs) { + model->operands[operand].numberOfConsumers--; + } + hidl_vec_removeAt(&model->operations, index); +} + +static void removeOperationTest(const sp& device, const Model& model) { + for (size_t operation = 0; operation < model.operations.size(); ++operation) { + const std::string message = "removeOperationTest: operation " + std::to_string(operation); + validate(device, message, model, + [operation](Model* model) { removeOperation(model, operation); }); + } +} + +///////////////////////// REMOVE OPERATION INPUT ///////////////////////// + +static void removeOperationInputTest(const sp& device, const Model& model) { + for (size_t operation = 0; operation < model.operations.size(); ++operation) { + for (size_t input = 0; input < model.operations[operation].inputs.size(); ++input) { + const Operation& op = model.operations[operation]; + // CONCATENATION has at least 2 inputs, with the last element being + // INT32. Skip this test if removing one of CONCATENATION's + // inputs still produces a valid model. + if (op.type == OperationType::CONCATENATION && op.inputs.size() > 2 && + input != op.inputs.size() - 1) { + continue; + } + const std::string message = "removeOperationInputTest: operation " + + std::to_string(operation) + ", input " + + std::to_string(input); + validate(device, message, model, [operation, input](Model* model) { + uint32_t operand = model->operations[operation].inputs[input]; + model->operands[operand].numberOfConsumers--; + hidl_vec_removeAt(&model->operations[operation].inputs, input); + }); + } + } +} + +///////////////////////// REMOVE OPERATION OUTPUT ///////////////////////// + +static void removeOperationOutputTest(const sp& device, const Model& model) { + for (size_t operation = 0; operation < model.operations.size(); ++operation) { + for (size_t output = 0; output < model.operations[operation].outputs.size(); ++output) { + const std::string message = "removeOperationOutputTest: operation " + + std::to_string(operation) + ", output " + + std::to_string(output); + validate(device, message, model, [operation, output](Model* model) { + hidl_vec_removeAt(&model->operations[operation].outputs, output); + }); + } + } +} + +///////////////////////// MODEL VALIDATION ///////////////////////// + +// TODO: remove model input +// TODO: remove model output +// TODO: add unused operation + +///////////////////////// ADD OPERATION INPUT ///////////////////////// + +static void addOperationInputTest(const sp& device, const Model& model) { + for (size_t operation = 0; operation < model.operations.size(); ++operation) { + const std::string message = "addOperationInputTest: operation " + std::to_string(operation); + validate(device, message, model, [operation](Model* model) { + uint32_t index = addOperand(model, OperandLifeTime::MODEL_INPUT); + hidl_vec_push_back(&model->operations[operation].inputs, index); + hidl_vec_push_back(&model->inputIndexes, index); + }); + } +} + +///////////////////////// ADD OPERATION OUTPUT ///////////////////////// + +static void addOperationOutputTest(const sp& device, const Model& model) { + for (size_t operation = 0; operation < model.operations.size(); ++operation) { + const std::string message = + "addOperationOutputTest: operation " + std::to_string(operation); + validate(device, message, model, [operation](Model* model) { + uint32_t index = addOperand(model, OperandLifeTime::MODEL_OUTPUT); + hidl_vec_push_back(&model->operations[operation].outputs, index); + hidl_vec_push_back(&model->outputIndexes, index); + }); + } +} + +///////////////////////// VALIDATE EXECUTION PREFERENCE ///////////////////////// + +static const int32_t invalidExecutionPreferences[] = { + static_cast(ExecutionPreference::LOW_POWER) - 1, // lower bound + static_cast(ExecutionPreference::SUSTAINED_SPEED) + 1, // upper bound +}; + +static void mutateExecutionPreferenceTest(const sp& device, const Model& model) { + for (int32_t preference : invalidExecutionPreferences) { + const std::string message = + "mutateExecutionPreferenceTest: preference " + std::to_string(preference); + validate(device, message, model, [](Model*) {}, + static_cast(preference)); + } +} + +////////////////////////// ENTRY POINT ////////////////////////////// + +void ValidationTest::validateModel(const Model& model) { + mutateOperandTypeTest(device, model); + mutateOperandRankTest(device, model); + mutateOperandScaleTest(device, model); + mutateOperandZeroPointTest(device, model); + mutateOperationOperandTypeTest(device, model); + mutateOperationTypeTest(device, model); + mutateOperationInputOperandIndexTest(device, model); + mutateOperationOutputOperandIndexTest(device, model); + removeOperandTest(device, model); + removeOperationTest(device, model); + removeOperationInputTest(device, model); + removeOperationOutputTest(device, model); + addOperationInputTest(device, model); + addOperationOutputTest(device, model); + mutateExecutionPreferenceTest(device, model); +} + +} // namespace functional +} // namespace vts +} // namespace V1_2 +} // namespace neuralnetworks +} // namespace hardware +} // namespace android diff --git a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp new file mode 100644 index 0000000000..f4476fa07a --- /dev/null +++ b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "neuralnetworks_hidl_hal_test" + +#include "VtsHalNeuralnetworks.h" + +#include "Callbacks.h" +#include "TestHarness.h" +#include "Utils.h" + +#include +#include +#include + +namespace android { +namespace hardware { +namespace neuralnetworks { +namespace V1_2 { +namespace vts { +namespace functional { + +using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback; +using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback; +using ::android::hidl::memory::V1_0::IMemory; +using test_helper::for_all; +using test_helper::MixedTyped; +using test_helper::MixedTypedExampleType; + +///////////////////////// UTILITY FUNCTIONS ///////////////////////// + +static void createPreparedModel(const sp& device, const Model& model, + sp* preparedModel) { + ASSERT_NE(nullptr, preparedModel); + + // see if service can handle model + bool fullySupportsModel = false; + Return supportedOpsLaunchStatus = device->getSupportedOperations_1_2( + model, [&fullySupportsModel](ErrorStatus status, const hidl_vec& supported) { + ASSERT_EQ(ErrorStatus::NONE, status); + ASSERT_NE(0ul, supported.size()); + fullySupportsModel = + std::all_of(supported.begin(), supported.end(), [](bool valid) { return valid; }); + }); + ASSERT_TRUE(supportedOpsLaunchStatus.isOk()); + + // launch prepare model + sp preparedModelCallback = new PreparedModelCallback(); + ASSERT_NE(nullptr, preparedModelCallback.get()); + Return prepareLaunchStatus = device->prepareModel_1_2( + model, ExecutionPreference::FAST_SINGLE_ANSWER, preparedModelCallback); + ASSERT_TRUE(prepareLaunchStatus.isOk()); + ASSERT_EQ(ErrorStatus::NONE, static_cast(prepareLaunchStatus)); + + // retrieve prepared model + preparedModelCallback->wait(); + ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus(); + *preparedModel = preparedModelCallback->getPreparedModel(); + + // The getSupportedOperations_1_2 call returns a list of operations that are + // guaranteed not to fail if prepareModel_1_2 is called, and + // 'fullySupportsModel' is true i.f.f. the entire model is guaranteed. + // If a driver has any doubt that it can prepare an operation, it must + // return false. So here, if a driver isn't sure if it can support an + // operation, but reports that it successfully prepared the model, the test + // can continue. + if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) { + ASSERT_EQ(nullptr, preparedModel->get()); + LOG(INFO) << "NN VTS: Unable to test Request validation because vendor service cannot " + "prepare model that it does not support."; + std::cout << "[ ] Unable to test Request validation because vendor service " + "cannot prepare model that it does not support." + << std::endl; + return; + } + ASSERT_EQ(ErrorStatus::NONE, prepareReturnStatus); + ASSERT_NE(nullptr, preparedModel->get()); +} + +// Primary validation function. This function will take a valid request, apply a +// mutation to it to invalidate the request, then pass it to interface calls +// that use the request. Note that the request here is passed by value, and any +// mutation to the request does not leave this function. +static void validate(const sp& preparedModel, const std::string& message, + Request request, const std::function& mutation) { + mutation(&request); + SCOPED_TRACE(message + " [execute]"); + + sp executionCallback = new ExecutionCallback(); + ASSERT_NE(nullptr, executionCallback.get()); + Return executeLaunchStatus = preparedModel->execute(request, executionCallback); + ASSERT_TRUE(executeLaunchStatus.isOk()); + ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast(executeLaunchStatus)); + + executionCallback->wait(); + ErrorStatus executionReturnStatus = executionCallback->getStatus(); + ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, executionReturnStatus); +} + +// Delete element from hidl_vec. hidl_vec doesn't support a "remove" operation, +// so this is efficiently accomplished by moving the element to the end and +// resizing the hidl_vec to one less. +template +static void hidl_vec_removeAt(hidl_vec* vec, uint32_t index) { + if (vec) { + std::rotate(vec->begin() + index, vec->begin() + index + 1, vec->end()); + vec->resize(vec->size() - 1); + } +} + +template +static uint32_t hidl_vec_push_back(hidl_vec* vec, const Type& value) { + // assume vec is valid + const uint32_t index = vec->size(); + vec->resize(index + 1); + (*vec)[index] = value; + return index; +} + +///////////////////////// REMOVE INPUT //////////////////////////////////// + +static void removeInputTest(const sp& preparedModel, const Request& request) { + for (size_t input = 0; input < request.inputs.size(); ++input) { + const std::string message = "removeInput: removed input " + std::to_string(input); + validate(preparedModel, message, request, + [input](Request* request) { hidl_vec_removeAt(&request->inputs, input); }); + } +} + +///////////////////////// REMOVE OUTPUT //////////////////////////////////// + +static void removeOutputTest(const sp& preparedModel, const Request& request) { + for (size_t output = 0; output < request.outputs.size(); ++output) { + const std::string message = "removeOutput: removed Output " + std::to_string(output); + validate(preparedModel, message, request, + [output](Request* request) { hidl_vec_removeAt(&request->outputs, output); }); + } +} + +///////////////////////////// ENTRY POINT ////////////////////////////////// + +std::vector createRequests(const std::vector& examples) { + const uint32_t INPUT = 0; + const uint32_t OUTPUT = 1; + + std::vector requests; + + for (auto& example : examples) { + const MixedTyped& inputs = example.first; + const MixedTyped& outputs = example.second; + + std::vector inputs_info, outputs_info; + uint32_t inputSize = 0, outputSize = 0; + + // This function only partially specifies the metadata (vector of RequestArguments). + // The contents are copied over below. + for_all(inputs, [&inputs_info, &inputSize](int index, auto, auto s) { + if (inputs_info.size() <= static_cast(index)) inputs_info.resize(index + 1); + RequestArgument arg = { + .location = {.poolIndex = INPUT, .offset = 0, .length = static_cast(s)}, + .dimensions = {}, + }; + RequestArgument arg_empty = { + .hasNoValue = true, + }; + inputs_info[index] = s ? arg : arg_empty; + inputSize += s; + }); + // Compute offset for inputs 1 and so on + { + size_t offset = 0; + for (auto& i : inputs_info) { + if (!i.hasNoValue) i.location.offset = offset; + offset += i.location.length; + } + } + + // Go through all outputs, initialize RequestArgument descriptors + for_all(outputs, [&outputs_info, &outputSize](int index, auto, auto s) { + if (outputs_info.size() <= static_cast(index)) outputs_info.resize(index + 1); + RequestArgument arg = { + .location = {.poolIndex = OUTPUT, .offset = 0, .length = static_cast(s)}, + .dimensions = {}, + }; + outputs_info[index] = arg; + outputSize += s; + }); + // Compute offset for outputs 1 and so on + { + size_t offset = 0; + for (auto& i : outputs_info) { + i.location.offset = offset; + offset += i.location.length; + } + } + std::vector pools = {nn::allocateSharedMemory(inputSize), + nn::allocateSharedMemory(outputSize)}; + if (pools[INPUT].size() == 0 || pools[OUTPUT].size() == 0) { + return {}; + } + + // map pool + sp inputMemory = mapMemory(pools[INPUT]); + if (inputMemory == nullptr) { + return {}; + } + char* inputPtr = reinterpret_cast(static_cast(inputMemory->getPointer())); + if (inputPtr == nullptr) { + return {}; + } + + // initialize pool + inputMemory->update(); + for_all(inputs, [&inputs_info, inputPtr](int index, auto p, auto s) { + char* begin = (char*)p; + char* end = begin + s; + // TODO: handle more than one input + std::copy(begin, end, inputPtr + inputs_info[index].location.offset); + }); + inputMemory->commit(); + + requests.push_back({.inputs = inputs_info, .outputs = outputs_info, .pools = pools}); + } + + return requests; +} + +void ValidationTest::validateRequests(const Model& model, const std::vector& requests) { + // create IPreparedModel + sp preparedModel; + ASSERT_NO_FATAL_FAILURE(createPreparedModel(device, model, &preparedModel)); + if (preparedModel == nullptr) { + return; + } + + // validate each request + for (const Request& request : requests) { + removeInputTest(preparedModel, request); + removeOutputTest(preparedModel, request); + } +} + +} // namespace functional +} // namespace vts +} // namespace V1_2 +} // namespace neuralnetworks +} // namespace hardware +} // namespace android diff --git a/neuralnetworks/1.2/vts/functional/ValidationTests.cpp b/neuralnetworks/1.2/vts/functional/ValidationTests.cpp new file mode 100644 index 0000000000..3bdc5cdea7 --- /dev/null +++ b/neuralnetworks/1.2/vts/functional/ValidationTests.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "neuralnetworks_hidl_hal_test" + +#include "Models.h" +#include "VtsHalNeuralnetworks.h" + +namespace android { +namespace hardware { +namespace neuralnetworks { +namespace V1_2 { +namespace vts { +namespace functional { + +// forward declarations +std::vector createRequests(const std::vector& examples); + +// generate validation tests +#define VTS_CURRENT_TEST_CASE(TestName) \ + TEST_F(ValidationTest, TestName) { \ + const Model model = TestName::createTestModel(); \ + const std::vector requests = createRequests(TestName::examples); \ + validateModel(model); \ + validateRequests(model, requests); \ + } + +FOR_EACH_TEST_MODEL(VTS_CURRENT_TEST_CASE) + +#undef VTS_CURRENT_TEST_CASE + +} // namespace functional +} // namespace vts +} // namespace V1_2 +} // namespace neuralnetworks +} // namespace hardware +} // namespace android diff --git a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp new file mode 100644 index 0000000000..90a910c6f0 --- /dev/null +++ b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "neuralnetworks_hidl_hal_test" + +#include "VtsHalNeuralnetworks.h" + +namespace android { +namespace hardware { +namespace neuralnetworks { +namespace V1_2 { +namespace vts { +namespace functional { + +// A class for test environment setup +NeuralnetworksHidlEnvironment::NeuralnetworksHidlEnvironment() {} + +NeuralnetworksHidlEnvironment::~NeuralnetworksHidlEnvironment() {} + +NeuralnetworksHidlEnvironment* NeuralnetworksHidlEnvironment::getInstance() { + // This has to return a "new" object because it is freed inside + // ::testing::AddGlobalTestEnvironment when the gtest is being torn down + static NeuralnetworksHidlEnvironment* instance = new NeuralnetworksHidlEnvironment(); + return instance; +} + +void NeuralnetworksHidlEnvironment::registerTestServices() { + registerTestService(); +} + +// The main test class for NEURALNETWORK HIDL HAL. +NeuralnetworksHidlTest::NeuralnetworksHidlTest() {} + +NeuralnetworksHidlTest::~NeuralnetworksHidlTest() {} + +void NeuralnetworksHidlTest::SetUp() { + ::testing::VtsHalHidlTargetTestBase::SetUp(); + device = ::testing::VtsHalHidlTargetTestBase::getService( + NeuralnetworksHidlEnvironment::getInstance()); + ASSERT_NE(nullptr, device.get()); +} + +void NeuralnetworksHidlTest::TearDown() { + device = nullptr; + ::testing::VtsHalHidlTargetTestBase::TearDown(); +} + +} // namespace functional +} // namespace vts + +::std::ostream& operator<<(::std::ostream& os, ErrorStatus errorStatus) { + return os << toString(errorStatus); +} + +::std::ostream& operator<<(::std::ostream& os, DeviceStatus deviceStatus) { + return os << toString(deviceStatus); +} + +} // namespace V1_2 +} // namespace neuralnetworks +} // namespace hardware +} // namespace android + +using android::hardware::neuralnetworks::V1_2::vts::functional::NeuralnetworksHidlEnvironment; + +int main(int argc, char** argv) { + ::testing::AddGlobalTestEnvironment(NeuralnetworksHidlEnvironment::getInstance()); + ::testing::InitGoogleTest(&argc, argv); + NeuralnetworksHidlEnvironment::getInstance()->init(&argc, argv); + + int status = RUN_ALL_TESTS(); + return status; +} diff --git a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h new file mode 100644 index 0000000000..a87d788c47 --- /dev/null +++ b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VTS_HAL_NEURALNETWORKS_V1_2_H +#define VTS_HAL_NEURALNETWORKS_V1_2_H + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace neuralnetworks { +namespace V1_2 { + +using V1_0::DeviceStatus; +using V1_0::ErrorStatus; +using V1_0::Request; + +namespace vts { +namespace functional { + +// A class for test environment setup +class NeuralnetworksHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { + DISALLOW_COPY_AND_ASSIGN(NeuralnetworksHidlEnvironment); + NeuralnetworksHidlEnvironment(); + ~NeuralnetworksHidlEnvironment() override; + + public: + static NeuralnetworksHidlEnvironment* getInstance(); + void registerTestServices() override; +}; + +// The main test class for NEURALNETWORKS HIDL HAL. +class NeuralnetworksHidlTest : public ::testing::VtsHalHidlTargetTestBase { + DISALLOW_COPY_AND_ASSIGN(NeuralnetworksHidlTest); + + public: + NeuralnetworksHidlTest(); + ~NeuralnetworksHidlTest() override; + void SetUp() override; + void TearDown() override; + + protected: + sp device; +}; + +// Tag for the validation tests +class ValidationTest : public NeuralnetworksHidlTest { + protected: + void validateModel(const Model& model); + void validateRequests(const Model& model, const std::vector& request); +}; + +// Tag for the generated tests +class GeneratedTest : public NeuralnetworksHidlTest {}; + +} // namespace functional +} // namespace vts + +// pretty-print values for error messages +::std::ostream& operator<<(::std::ostream& os, ErrorStatus errorStatus); +::std::ostream& operator<<(::std::ostream& os, DeviceStatus deviceStatus); + +} // namespace V1_2 +} // namespace neuralnetworks +} // namespace hardware +} // namespace android + +#endif // VTS_HAL_NEURALNETWORKS_V1_2_H From 1f0c5ea652d6b4b8f68e88600ca2adb7942f06c5 Mon Sep 17 00:00:00 2001 From: Brian Stack Date: Tue, 18 Sep 2018 16:04:09 -0700 Subject: [PATCH 112/718] Define EventQueueFlagBits The EventQueueFlagBits is used to notify the other end of an FMQ when an action should be taken. For instance, the read end of the queue is able to wait on a particular mask bit to be set by the write end of the queue before reading events. This is necessary because the number of events to read must be specified when calling the FMQ's read() or readBlocking() functions. read() will fail if the specified number of events is not available. readBlocking() will not perform a partial read, so if the number of events to read is not known ahead of time, the function may block for an extended period of time until enough events are queued up. By utilizing the EventFlag, the reading of events is able to wait until events are ready to be read, and then the availableToRead() function provides the number of events to read when calling read() or readBlocking(). Bug: 111070257 Test: Compiles Change-Id: I20e9e566efc58196e27e50dae3fc13518ce605fc --- sensors/2.0/Android.bp | 1 + sensors/2.0/ISensors.hal | 4 ++++ sensors/2.0/types.hal | 7 +++++++ 3 files changed, 12 insertions(+) diff --git a/sensors/2.0/Android.bp b/sensors/2.0/Android.bp index 20bc4e1d2d..f61483482a 100644 --- a/sensors/2.0/Android.bp +++ b/sensors/2.0/Android.bp @@ -15,6 +15,7 @@ hidl_interface { "android.hidl.base@1.0", ], types: [ + "EventQueueFlagBits", "SensorTimeout", ], gen_java: false, diff --git a/sensors/2.0/ISensors.hal b/sensors/2.0/ISensors.hal index 32092ef224..24454b47c7 100644 --- a/sensors/2.0/ISensors.hal +++ b/sensors/2.0/ISensors.hal @@ -67,6 +67,10 @@ interface ISensors { * Data may only be written to the Event FMQ. Data must not be read from * the Event FMQ since the framework is the only reader. Upon receiving * sensor events, the HAL should write the sensor events to the Event FMQ. + * Once the HAL is finished writing sensor events to the Event FMQ, the HAL + * must call the Event FMQ's EventFlag wake() function with the + * EventQueueFlagBits::READ_AND_PROCESS mask which notifies the framework + * that sensor events are available to be read and processed. * * The Wake Lock FMQ is used by the framework to notify the HAL when it is * safe to release its wake_lock. When the framework receives WAKE_UP events diff --git a/sensors/2.0/types.hal b/sensors/2.0/types.hal index 16e1c03b3b..e1a029a082 100644 --- a/sensors/2.0/types.hal +++ b/sensors/2.0/types.hal @@ -23,3 +23,10 @@ enum SensorTimeout : int32_t { */ WAKE_LOCK_SECONDS = 1, }; + +enum EventQueueFlagBits : uint32_t { + /** + * Used to notify the Event FMQ that events should be read and processed. + */ + READ_AND_PROCESS = 1 << 0, +}; From 2e880493d6a227b050dabc6caa294eea408338ca Mon Sep 17 00:00:00 2001 From: Hridya Valsaraju Date: Fri, 21 Sep 2018 15:47:05 -0700 Subject: [PATCH 113/718] Revert "Add command to pass oem commands to HAL" This reverts commit ddaa8ecb379479a3450c954161df33fda1348685. Test: make Change-Id: I14c745ade7c19d961bdc588d6e09930bc1360b36 --- fastboot/1.0/IFastboot.hal | 10 ---------- fastboot/1.0/types.hal | 4 ++-- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/fastboot/1.0/IFastboot.hal b/fastboot/1.0/IFastboot.hal index 5e42c17042..653fd79ef5 100644 --- a/fastboot/1.0/IFastboot.hal +++ b/fastboot/1.0/IFastboot.hal @@ -29,14 +29,4 @@ interface IFastboot { * reformatting. */ getPartitionType(string partitionName) generates (FileSystemType type, Result result); - - /** - * Executes a fastboot OEM command. - * - * @param oemCmdArgs The oem command that is passed to the fastboot HAL. - * @response result Returns the status SUCCESS if the operation is successful, - * INVALID_ARGUMENT for bad arguments, - * FAILURE_UNKNOWN for an invalid/unsupported command. - */ - doOemCommand(string oemCmd) generates (Result result); }; diff --git a/fastboot/1.0/types.hal b/fastboot/1.0/types.hal index 3fbe63959c..8453deb2a4 100644 --- a/fastboot/1.0/types.hal +++ b/fastboot/1.0/types.hal @@ -53,9 +53,9 @@ enum FileSystemType : uint8_t { struct Result { Status status; /** - * Message pertaining to the status. It must be a failure message for + * Error message pertaining to the status. It must be a failure message for * Status FAILURE_UNKNOWN/NOT_SUPPORTED or an informative message for * Status SUCCESS. */ - string message; + string error; }; From 3c2443ec29984c7c003e8b21a26fc25ad519475d Mon Sep 17 00:00:00 2001 From: Hridya Valsaraju Date: Fri, 21 Sep 2018 16:06:30 -0700 Subject: [PATCH 114/718] Revert "Revert "Add command to pass oem commands to HAL"" Test: make This reverts commit 2e880493d6a227b050dabc6caa294eea408338ca. --- fastboot/1.0/IFastboot.hal | 10 ++++++++++ fastboot/1.0/types.hal | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/fastboot/1.0/IFastboot.hal b/fastboot/1.0/IFastboot.hal index 653fd79ef5..5e42c17042 100644 --- a/fastboot/1.0/IFastboot.hal +++ b/fastboot/1.0/IFastboot.hal @@ -29,4 +29,14 @@ interface IFastboot { * reformatting. */ getPartitionType(string partitionName) generates (FileSystemType type, Result result); + + /** + * Executes a fastboot OEM command. + * + * @param oemCmdArgs The oem command that is passed to the fastboot HAL. + * @response result Returns the status SUCCESS if the operation is successful, + * INVALID_ARGUMENT for bad arguments, + * FAILURE_UNKNOWN for an invalid/unsupported command. + */ + doOemCommand(string oemCmd) generates (Result result); }; diff --git a/fastboot/1.0/types.hal b/fastboot/1.0/types.hal index 8453deb2a4..3fbe63959c 100644 --- a/fastboot/1.0/types.hal +++ b/fastboot/1.0/types.hal @@ -53,9 +53,9 @@ enum FileSystemType : uint8_t { struct Result { Status status; /** - * Error message pertaining to the status. It must be a failure message for + * Message pertaining to the status. It must be a failure message for * Status FAILURE_UNKNOWN/NOT_SUPPORTED or an informative message for * Status SUCCESS. */ - string error; + string message; }; From 78aa4fc9dd57983fc21ed7588019caa94624f6bf Mon Sep 17 00:00:00 2001 From: Brian Stack Date: Tue, 18 Sep 2018 13:45:36 -0700 Subject: [PATCH 115/718] Define the ISensorsCallback The ISensorsCallback will be used to push notifications into the sensors framework, such as when dynamic sensors are connected. Bug: 111070257 Test: Compiles Change-Id: I681e6de341a80016983a3ab7fa45284ee9104918 --- sensors/2.0/Android.bp | 1 + sensors/2.0/ISensors.hal | 35 +++++++++++++++-------- sensors/2.0/ISensorsCallback.hal | 48 ++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 12 deletions(-) create mode 100644 sensors/2.0/ISensorsCallback.hal diff --git a/sensors/2.0/Android.bp b/sensors/2.0/Android.bp index f61483482a..3b948a9cee 100644 --- a/sensors/2.0/Android.bp +++ b/sensors/2.0/Android.bp @@ -9,6 +9,7 @@ hidl_interface { srcs: [ "types.hal", "ISensors.hal", + "ISensorsCallback.hal", ], interfaces: [ "android.hardware.sensors@1.0", diff --git a/sensors/2.0/ISensors.hal b/sensors/2.0/ISensors.hal index 24454b47c7..2a57251103 100644 --- a/sensors/2.0/ISensors.hal +++ b/sensors/2.0/ISensors.hal @@ -22,6 +22,7 @@ import @1.0::RateLevel; import @1.0::Result; import @1.0::SensorInfo; import @1.0::SharedMemInfo; +import @2.0::ISensorsCallback; interface ISensors { /** @@ -59,8 +60,11 @@ interface ISensors { activate(int32_t sensorHandle, bool enabled) generates (Result result); /** - * Initialize the Fast Message Queues (FMQ) that are used to send data - * between the framework and the HAL. + * Initialize the Sensors HAL's Fast Message Queues (FMQ) and callback. + * + * The Fast Message Queues (FMQ) that are used to send data between the + * framework and the HAL. The callback is used by the HAL to notify the + * framework of asynchronous events, such as a dynamic sensor connection. * * The Event FMQ is used to transport sensor events from the HAL to the * framework. The Event FMQ is created using the eventQueueDescriptor. @@ -81,6 +85,9 @@ interface ISensors { * unprocessed WAKE_UP events and release its wake_lock if the current * count of unprocessed WAKE_UP events is zero. * + * The ISensorsCallback is used by the HAL to notify the framework of + * asynchronous events, such as a dynamic sensor connection. + * * The name of any wake_lock acquired by the Sensors HAL for WAKE_UP events * must begin with "SensorsHAL_WAKEUP". * @@ -90,14 +97,14 @@ interface ISensors { * released. * * If either the Event FMQ or the Wake Lock FMQ is already initialized when - * initializeMessageQueues is invoked, then both existing FMQs must be - * discarded and the new descriptors must be used to create new FMQs within - * the HAL. The number of outstanding WAKE_UP events should also be reset to - * zero, and any outstanding wake_locks held as a result of WAKE_UP events - * should be released. + * initialize is invoked, then both existing FMQs must be discarded and the + * new descriptors must be used to create new FMQs within the HAL. The + * number of outstanding WAKE_UP events should also be reset to zero, and + * any outstanding wake_locks held as a result of WAKE_UP events should be + * released. * - * initializeMessageQueues must be thread safe and prevent concurrent calls - * to initializeMessageQueues from simultaneously modifying state. + * initialize must be thread safe and prevent concurrent calls + * to initialize from simultaneously modifying state. * * @param eventQueueDescriptor Fast Message Queue descriptor that is used to * create the Event FMQ which is where sensor events are written. The @@ -107,14 +114,18 @@ interface ISensors { * create the Wake Lock FMQ which is where wake_lock events are read * from. The descriptor is obtained from the framework's FMQ that is * used to write wake_lock events. + * @param sensorsCallback sensors callback that receives asynchronous data + * from the Sensors HAL. * @return result OK on success; BAD_VALUE if descriptor is invalid (such * as null) */ @entry @callflow(next = {"getSensorsList"}) - initializeMessageQueues(fmq_sync eventQueueDescriptor, - fmq_sync wakeLockDescriptor) - generates (Result result); + initialize(fmq_sync eventQueueDescriptor, + fmq_sync wakeLockDescriptor, + ISensorsCallback sensorsCallback) + generates + (Result result); /** * Sets a sensor’s parameters, including sampling frequency and maximum diff --git a/sensors/2.0/ISensorsCallback.hal b/sensors/2.0/ISensorsCallback.hal new file mode 100644 index 0000000000..e0bd98f506 --- /dev/null +++ b/sensors/2.0/ISensorsCallback.hal @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.sensors@2.0; + +import @1.0::SensorInfo; + +interface ISensorsCallback { + /** + * Notify the framework that new dynamic sensors have been connected. + * + * If a dynamic sensor was previously connected and has not been + * disconnected, then that sensor must not be included in sensorInfos. + * + * @param sensorInfos vector of SensorInfo for each dynamic sensor that + * was connected. + */ + oneway onDynamicSensorsConnected(vec sensorInfos); + + /** + * Notify the framework that previously connected dynamic sensors have been + * disconnected. + * + * If a dynamic sensor was previously disconnected and has not been + * reconnected, then that sensor must not be included in sensorHandles. + * + * The HAL must ensure that all sensor events from departing dynamic + * sensors have been written to the Event FMQ before calling + * onDynamicSensorsDisconnected. + * + * @param sensorHandles vector of sensor handles for each dynamic sensors + * that was disconnected. + */ + oneway onDynamicSensorsDisconnected(vec sensorHandles); +}; From 2acfd2aab67f3b5e6aae69510f4c830d296eb002 Mon Sep 17 00:00:00 2001 From: Kevin Chyn Date: Thu, 20 Sep 2018 18:42:09 -0700 Subject: [PATCH 116/718] Add timeout parameter to generateChallenge Fixes: 115925222 Test: builds Change-Id: Idac1730b36eadb5acdb6420cc330585ebb2f3197 --- biometrics/face/1.0/IBiometricsFace.hal | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/biometrics/face/1.0/IBiometricsFace.hal b/biometrics/face/1.0/IBiometricsFace.hal index f39eaeb2fd..1c7bfb9be5 100644 --- a/biometrics/face/1.0/IBiometricsFace.hal +++ b/biometrics/face/1.0/IBiometricsFace.hal @@ -78,11 +78,15 @@ interface IBiometricsFace { * template if the operation was preceded by some kind of strong credential * confirmation (e.g. device password). * + * @param challengeTimeoutSec A timeout in seconds, after which the driver + * must invalidate the challenge. This is to prevent bugs or crashes in + * the system from leaving a challenge enabled indefinitely. * @return result, with its "value" parameter representing a "challenge": a * unique and cryptographically secure random token. */ @callflow(next={"enroll", "revokeChallenge", "setRequireAttention"}) - generateChallenge() generates (OptionalUint64 result); + generateChallenge(uint32_t challengeTimeoutSec) + generates (OptionalUint64 result); /** * Enrolls a user's face. From cc31bd6622f5e01ab640916fbb26433dd4ff9db2 Mon Sep 17 00:00:00 2001 From: Slava Shklyaev Date: Wed, 19 Sep 2018 16:55:31 +0100 Subject: [PATCH 117/718] Add new ops ARGMAX and ARGMIN Bug: 113558658 Test: NeuralNetworksTest_static Change-Id: I8862d4062181689ce69ab65aa07c1b6af07ba567 --- neuralnetworks/1.2/types.hal | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal index 61970f00fd..fc2b540297 100644 --- a/neuralnetworks/1.2/types.hal +++ b/neuralnetworks/1.2/types.hal @@ -26,7 +26,9 @@ import @1.1::OperationType; * The type of an operation in a model. */ enum OperationType : @1.1::OperationType { - + // TODO: Sync docs. + ARGMAX = 38, + ARGMIN = 39, }; /** From ffe467e6d863b2b555171df7b2f46676ad46200e Mon Sep 17 00:00:00 2001 From: Slava Shklyaev Date: Thu, 20 Sep 2018 13:43:37 +0100 Subject: [PATCH 118/718] Add new op PAD_V2 Bug: 113561890 Test: NeuralNetworksTest_static Change-Id: I34351d6ff5fae0a13e3e883ca42210c534418ff3 --- neuralnetworks/1.2/types.hal | 1 + 1 file changed, 1 insertion(+) diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal index fc2b540297..ecd99cc8e2 100644 --- a/neuralnetworks/1.2/types.hal +++ b/neuralnetworks/1.2/types.hal @@ -29,6 +29,7 @@ enum OperationType : @1.1::OperationType { // TODO: Sync docs. ARGMAX = 38, ARGMIN = 39, + PAD_V2 = 40, }; /** From 5a9362eb2d1378636fd8bf604f6536eb2a268d2c Mon Sep 17 00:00:00 2001 From: Przemyslaw Szczepaniak Date: Mon, 24 Sep 2018 14:12:28 +0100 Subject: [PATCH 119/718] Reserve enums for new NNAPI ops. Test: NeuralNetworksTest_static Bug: 114365802 Change-Id: I3b379fe3f0336b92ef602bbb12a4bd4a150c573c --- neuralnetworks/1.2/types.hal | 46 ++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal index ecd99cc8e2..129172d25c 100644 --- a/neuralnetworks/1.2/types.hal +++ b/neuralnetworks/1.2/types.hal @@ -30,6 +30,52 @@ enum OperationType : @1.1::OperationType { ARGMAX = 38, ARGMIN = 39, PAD_V2 = 40, + BBOX_TRANSFORM = 41, + BIDIRECTIONAL_SEQUENCE_LSTM = 42, + BIDIRECTIONAL_SEQUENCE_RNN = 43, + BOX_WITH_NMS_LIMIT = 44, + CAST = 45, + CHANNEL_SHUFFLE = 46, + DETECTION_OUTPUT = 47, + EMBEDDING_LOOKUP_SPARSE = 48, + EXP = 49, + EXPAND_DIMS = 50, + GATHER = 51, + GENERATE_PROPOSALS = 52, + GREATER = 53, + GREATER_EQUAL = 54, + GROUPED_CONV_2D = 55, + HEATMAP_MAX_KEYPOINT = 56, + LESS = 57, + LESS_EQUAL = 58, + LOG = 59, + LOGICAL_AND = 60, + LOGICAL_NOT = 61, + LOGICAL_OR = 62, + LOG_SOFTMAX = 63, + MAXIMUM = 64, + MINIMUM = 65, + NEG = 66, + POW = 67, + PRELU = 68, + PRIOR_BOX = 69, + QUANTIZE = 70, + QUANTIZED_16BIT_LSTM = 71, + RANDOM_MULTINOMIAL = 72, + REDUCE = 73, + ROI_ALIGN = 74, + RSQRT = 75, + SELECT = 76, + SIN = 77, + SLICE = 78, + SPARSE_TO_DENSE = 78, + SPLIT = 79, + SQRT = 80, + TILE = 81, + TOPK_V2 = 82, + TRANSPOSE_CONV_2D = 83, + UNIDIRECTIONAL_SEQUENCE_LSTM = 84, + UNIDIRECTIONAL_SEQUENCE_RNN = 85, }; /** From 7f9f46159183b02d53ca8d6bbe728e5610c2ea5a Mon Sep 17 00:00:00 2001 From: Slava Shklyaev Date: Tue, 25 Sep 2018 16:10:38 +0100 Subject: [PATCH 120/718] Attach a bug to syncing docs Bug: 116445845 Test: none Change-Id: I841b1dc503d70efddb8175b75d9d3efe8078eeb1 --- neuralnetworks/1.2/types.hal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal index 129172d25c..0e076f5c5b 100644 --- a/neuralnetworks/1.2/types.hal +++ b/neuralnetworks/1.2/types.hal @@ -26,7 +26,7 @@ import @1.1::OperationType; * The type of an operation in a model. */ enum OperationType : @1.1::OperationType { - // TODO: Sync docs. + // TODO(b/116445845): Sync docs when all ops are implemented. ARGMAX = 38, ARGMIN = 39, PAD_V2 = 40, From 1a6fd42e034daf71390ad1f3c014ccd40cee1ab7 Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Tue, 25 Sep 2018 14:44:15 -0700 Subject: [PATCH 121/718] configstore: make consistent with AOSP 'rd' -> 'RD' to avoid having a different hash/merge conflicts. Bug: N/A Test: hidl-gen -Lcheck android.hardware.configstore@1.0 Test: manually check the hash is the same on AOSP Change-Id: Id57f21d25bc905859c43f229b9d5b66c0c9d2cfc --- configstore/1.0/ISurfaceFlingerConfigs.hal | 2 +- current.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configstore/1.0/ISurfaceFlingerConfigs.hal b/configstore/1.0/ISurfaceFlingerConfigs.hal index 0790905e63..1de7570bd2 100644 --- a/configstore/1.0/ISurfaceFlingerConfigs.hal +++ b/configstore/1.0/ISurfaceFlingerConfigs.hal @@ -61,7 +61,7 @@ interface ISurfaceFlingerConfigs { hasWideColorDisplay() generates (OptionalBool value); /** - * hwHdrDisplay indicates that the device has an High Dynamic Range display. + * hwHDRDisplay indicates that the device has an High Dynamic Range display. * A display is considered High Dynamic Range if it * * 1. is a wide color gamut display, typically DCI-P3 or lager diff --git a/current.txt b/current.txt index e09eaa305a..ebb8cf690a 100644 --- a/current.txt +++ b/current.txt @@ -386,7 +386,7 @@ cd4330c3196bda1d642a32abfe23a7d64ebfbda721940643af6867af3b3f0aa9 android.hardwar # ABI preserving changes to HALs during Android Q a95745bbf76aea16a76518bd7efe70cabc5886d09eaeffc993c2e1787a22ed23 android.hardware.camera.metadata@3.3::types -5f936a5befde7af8d2a683670f80a836b4741e94d84b7b39026da3ed78be9906 android.hardware.configstore@1.0::ISurfaceFlingerConfigs +da33234403ff5d60f3473711917b9948e6484a4260b5247acdafb111193a9de2 android.hardware.configstore@1.0::ISurfaceFlingerConfigs 574e8f1499436fb4075894dcae0b36682427956ecb114f17f1fe22d116a83c6b android.hardware.neuralnetworks@1.0::IPreparedModel 1fb32361286b938d48a55c2539c846732afce0b99fe08590f556643125bc13d3 android.hardware.neuralnetworks@1.0::types e22e8135d061d0e9c4c1a70c25c19fdba10f4d3cda9795ef25b6392fc520317c android.hardware.neuralnetworks@1.1::types From db895ad8da1008082521146eac3647907a56a2b1 Mon Sep 17 00:00:00 2001 From: Wei Wang Date: Fri, 21 Sep 2018 15:44:31 -0700 Subject: [PATCH 122/718] Add atrace HAL 1.0 Bug: 111098596 Test: vts, atrace and systrace Change-Id: If59efe6fe74e9ca832f38fe0cfe0186db5ca7fe3 --- atrace/1.0/Android.bp | 22 ++++ atrace/1.0/IAtraceDevice.hal | 51 ++++++++ atrace/1.0/default/Android.bp | 35 ++++++ atrace/1.0/default/AtraceDevice.cpp | 110 ++++++++++++++++ atrace/1.0/default/AtraceDevice.h | 54 ++++++++ .../android.hardware.atrace@1.0-service.rc | 13 ++ .../android.hardware.atrace@1.0-service.xml | 11 ++ atrace/1.0/default/service.cpp | 44 +++++++ atrace/1.0/types.hal | 43 +++++++ atrace/1.0/vts/functional/Android.bp | 22 ++++ .../functional/VtsHalAtraceV1_0TargetTest.cpp | 118 ++++++++++++++++++ .../compatibility_matrix.current.xml | 8 ++ 12 files changed, 531 insertions(+) create mode 100644 atrace/1.0/Android.bp create mode 100644 atrace/1.0/IAtraceDevice.hal create mode 100644 atrace/1.0/default/Android.bp create mode 100644 atrace/1.0/default/AtraceDevice.cpp create mode 100644 atrace/1.0/default/AtraceDevice.h create mode 100644 atrace/1.0/default/android.hardware.atrace@1.0-service.rc create mode 100644 atrace/1.0/default/android.hardware.atrace@1.0-service.xml create mode 100644 atrace/1.0/default/service.cpp create mode 100644 atrace/1.0/types.hal create mode 100644 atrace/1.0/vts/functional/Android.bp create mode 100644 atrace/1.0/vts/functional/VtsHalAtraceV1_0TargetTest.cpp diff --git a/atrace/1.0/Android.bp b/atrace/1.0/Android.bp new file mode 100644 index 0000000000..f7c9078333 --- /dev/null +++ b/atrace/1.0/Android.bp @@ -0,0 +1,22 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +hidl_interface { + name: "android.hardware.atrace@1.0", + root: "android.hardware", + vndk: { + enabled: true, + }, + srcs: [ + "types.hal", + "IAtraceDevice.hal", + ], + interfaces: [ + "android.hidl.base@1.0", + ], + types: [ + "Status", + "TracingCategory", + ], + gen_java: true, +} + diff --git a/atrace/1.0/IAtraceDevice.hal b/atrace/1.0/IAtraceDevice.hal new file mode 100644 index 0000000000..b6e78b41dc --- /dev/null +++ b/atrace/1.0/IAtraceDevice.hal @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.atrace@1.0; + +interface IAtraceDevice { + /** + * Get vendor extended atrace points. + * + * + * @return categories of tracing points the device extended. + */ + listCategories() generates (vec categories); + + /** + * A hook when atrace set to enable specific categories, so HAL + * can enable kernel tracing points and/or notify other things + * for userspace tracing turning on. + * + * @param categories A vector of strings of categories (corresponding to + * TracingCategory.name) atrace needs to be enabled. + * + * @return status SUCCESS on success, + * ERROR_TRACING_POINT on error with enabling categories, + * ERROR_INVALID_ARGUMENT on invalid argument passed. + */ + enableCategories(vec categories) generates (Status status); + + /** + * A hook when atrace set to clean up tracing categories, so HAL + * can disable all kernel tracing points and/or notify other things + * for userspace tracing turning off. + * + * @return status SUCCESS on success, + * ERROR_TRACING_POINT on error with disabling categories. + */ + disableAllCategories() generates (Status status); +}; diff --git a/atrace/1.0/default/Android.bp b/atrace/1.0/default/Android.bp new file mode 100644 index 0000000000..bcaf064245 --- /dev/null +++ b/atrace/1.0/default/Android.bp @@ -0,0 +1,35 @@ +// +// Copyright (C) 2018 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +cc_binary { + name: "android.hardware.atrace@1.0-service", + defaults: ["hidl_defaults"], + relative_install_path: "hw", + vendor: true, + init_rc: ["android.hardware.atrace@1.0-service.rc"], + vintf_fragments: ["android.hardware.atrace@1.0-service.xml"], + srcs: [ + "AtraceDevice.cpp", + "service.cpp", + ], + shared_libs: [ + "liblog", + "libbase", + "libutils", + "libhidlbase", + "libhidltransport", + "android.hardware.atrace@1.0", + ], +} diff --git a/atrace/1.0/default/AtraceDevice.cpp b/atrace/1.0/default/AtraceDevice.cpp new file mode 100644 index 0000000000..43bcd9a29c --- /dev/null +++ b/atrace/1.0/default/AtraceDevice.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "AtraceDevice.h" + +namespace android { +namespace hardware { +namespace atrace { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::atrace::V1_0::Status; +using ::android::hardware::atrace::V1_0::TracingCategory; + +struct TracingConfig { + std::string description; + std::vector> paths; +}; + +// This is a map stores categories and their sysfs paths with required flags +const std::map kTracingMap = { + // gfx + { + "gfx", + {"Graphics", + {{"/sys/kernel/debug/tracing/events/mdss/enable", false}, + {"/sys/kernel/debug/tracing/events/sde/enable", false}, + {"/sys/kernel/debug/tracing/events/mali_systrace/enable", false}}}, + }, + { + "ion", + {"ION allocation", + {{"/sys/kernel/debug/tracing/events/kmem/ion_alloc_buffer_start/enable", true}}}, + }, +}; + +// Methods from ::android::hardware::atrace::V1_0::IAtraceDevice follow. +Return AtraceDevice::listCategories(listCategories_cb _hidl_cb) { + hidl_vec categories; + categories.resize(kTracingMap.size()); + std::size_t i = 0; + for (auto& c : kTracingMap) { + categories[i].name = c.first; + categories[i].description = c.second.description; + i++; + } + _hidl_cb(categories); + return Void(); +} + +Return<::android::hardware::atrace::V1_0::Status> AtraceDevice::enableCategories( + const hidl_vec& categories) { + if (!categories.size()) { + return Status::ERROR_INVALID_ARGUMENT; + } + for (auto& c : categories) { + if (kTracingMap.count(c)) { + for (auto& p : kTracingMap.at(c).paths) { + if (!android::base::WriteStringToFile("1", p.first)) { + LOG(ERROR) << "Failed to enable tracing on: " << p.first; + if (p.second) { + // disable before return + disableAllCategories(); + return Status::ERROR_TRACING_POINT; + } + } + } + } else { + return Status::ERROR_INVALID_ARGUMENT; + } + } + return Status::SUCCESS; +} + +Return<::android::hardware::atrace::V1_0::Status> AtraceDevice::disableAllCategories() { + auto ret = Status::SUCCESS; + for (auto& c : kTracingMap) { + for (auto& p : c.second.paths) { + if (!android::base::WriteStringToFile("0", p.first)) { + LOG(ERROR) << "Failed to enable tracing on: " << p.first; + if (p.second) { + ret = Status::ERROR_TRACING_POINT; + } + } + } + } + return ret; +} + +} // namespace implementation +} // namespace V1_0 +} // namespace atrace +} // namespace hardware +} // namespace android diff --git a/atrace/1.0/default/AtraceDevice.h b/atrace/1.0/default/AtraceDevice.h new file mode 100644 index 0000000000..e700f89129 --- /dev/null +++ b/atrace/1.0/default/AtraceDevice.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_ATRACE_V1_0_ATRACEDEVICE_H +#define ANDROID_HARDWARE_ATRACE_V1_0_ATRACEDEVICE_H + +#include +#include +#include + +namespace android { +namespace hardware { +namespace atrace { +namespace V1_0 { +namespace implementation { + +using ::android::sp; +using ::android::hardware::hidl_array; +using ::android::hardware::hidl_memory; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; + +struct AtraceDevice : public IAtraceDevice { + // Methods from ::android::hardware::atrace::V1_0::IAtraceDevice follow. + Return listCategories(listCategories_cb _hidl_cb) override; + Return<::android::hardware::atrace::V1_0::Status> enableCategories( + const hidl_vec& categories) override; + Return<::android::hardware::atrace::V1_0::Status> disableAllCategories() override; + + // Methods from ::android::hidl::base::V1_0::IBase follow. +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace atrace +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_ATRACE_V1_0_ATRACEDEVICE_H 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 new file mode 100644 index 0000000000..eb54c39a61 --- /dev/null +++ b/atrace/1.0/default/android.hardware.atrace@1.0-service.rc @@ -0,0 +1,13 @@ +on late-init + # vendor graphics trace points + chmod 0666 /sys/kernel/debug/tracing/events/sde/enable + chmod 0666 /sys/kernel/debug/tracing/events/mdss/enable + chmod 0666 /sys/kernel/debug/tracing/events/mali_systrace/enable + # ion allocation trace point + chmod 0666 /sys/kernel/debug/tracing/events/kmem/ion_alloc_buffer_start/enable + +service vendor.atrace-hal-1-0 /vendor/bin/hw/android.hardware.atrace@1.0-service + interface android.hardware.atrace@1.0::IAtraceDevice default + class early_hal + user system + group system diff --git a/atrace/1.0/default/android.hardware.atrace@1.0-service.xml b/atrace/1.0/default/android.hardware.atrace@1.0-service.xml new file mode 100644 index 0000000000..fd3631caf5 --- /dev/null +++ b/atrace/1.0/default/android.hardware.atrace@1.0-service.xml @@ -0,0 +1,11 @@ + + + android.hardware.atrace + hwbinder + 1.0 + + IAtraceDevice + default + + + diff --git a/atrace/1.0/default/service.cpp b/atrace/1.0/default/service.cpp new file mode 100644 index 0000000000..662fd73657 --- /dev/null +++ b/atrace/1.0/default/service.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "android.hardware.atrace@1.0-service" + +#include +#include + +#include "AtraceDevice.h" + +using ::android::OK; +using ::android::sp; +using ::android::hardware::configureRpcThreadpool; +using ::android::hardware::joinRpcThreadpool; +using ::android::hardware::atrace::V1_0::IAtraceDevice; +using ::android::hardware::atrace::V1_0::Status; +using ::android::hardware::atrace::V1_0::TracingCategory; +using ::android::hardware::atrace::V1_0::implementation::AtraceDevice; + +int main(int /* argc */, char* /* argv */ []) { + sp atrace = new AtraceDevice; + configureRpcThreadpool(1, true /* will join */); + if (atrace->registerAsService() != OK) { + ALOGE("Could not register service."); + return 1; + } + joinRpcThreadpool(); + + ALOGE("Service exited!"); + return 1; +} diff --git a/atrace/1.0/types.hal b/atrace/1.0/types.hal new file mode 100644 index 0000000000..f137ef6253 --- /dev/null +++ b/atrace/1.0/types.hal @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.atrace@1.0; + +enum Status : uint32_t { + /** + * Operation completed without errors. + */ + SUCCESS = 0, + /** + * Operation failed with errors on enabling tracing point. + */ + ERROR_TRACING_POINT = 1, + /** + * Operation failed because of invalid argument. + */ + ERROR_INVALID_ARGUMENT = 2 +}; + +struct TracingCategory { + /** + * Tracing category name, unique to frameworks's category. + */ + string name; + /** + * Tracing category description. + */ + string description; +}; diff --git a/atrace/1.0/vts/functional/Android.bp b/atrace/1.0/vts/functional/Android.bp new file mode 100644 index 0000000000..6b50fb5bf7 --- /dev/null +++ b/atrace/1.0/vts/functional/Android.bp @@ -0,0 +1,22 @@ +// +// Copyright (C) 2018 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +cc_test { + name: "VtsHalAtraceV1_0TargetTest", + defaults: ["VtsHalTargetTestDefaults"], + srcs: ["VtsHalAtraceV1_0TargetTest.cpp"], + static_libs: ["android.hardware.atrace@1.0"], +} diff --git a/atrace/1.0/vts/functional/VtsHalAtraceV1_0TargetTest.cpp b/atrace/1.0/vts/functional/VtsHalAtraceV1_0TargetTest.cpp new file mode 100644 index 0000000000..c62c2f08e3 --- /dev/null +++ b/atrace/1.0/vts/functional/VtsHalAtraceV1_0TargetTest.cpp @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +#include +#include + +using ::android::sp; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::atrace::V1_0::IAtraceDevice; +using ::android::hardware::atrace::V1_0::Status; + +// Test environment for Boot HIDL HAL. +class AtraceHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { + public: + // get the test environment singleton + static AtraceHidlEnvironment* Instance() { + static AtraceHidlEnvironment* instance = new AtraceHidlEnvironment; + return instance; + } + + virtual void registerTestServices() override { registerTestService(); } + + private: + AtraceHidlEnvironment() {} +}; + +/** + * There is no expected behaviour that can be tested so these tests check the + * HAL doesn't crash with different execution orders. + */ +struct AtraceHidlTest : public ::testing::VtsHalHidlTargetTestBase { + virtual void SetUp() override { + atrace = ::testing::VtsHalHidlTargetTestBase::getService( + AtraceHidlEnvironment::Instance()->getServiceName()); + ASSERT_NE(atrace, nullptr); + } + + sp atrace; +}; + +hidl_vec getVendorCategoryName(sp atrace) { + std::unordered_set categories_set; + Return ret = atrace->listCategories([&](const auto& list) { + for (const auto& category : list) { + std::string name = category.name; + if (categories_set.count(name)) { + ADD_FAILURE() << "Duplicate category: " << name; + } else { + categories_set.emplace(name); + } + } + }); + if (!ret.isOk()) { + ADD_FAILURE(); + } + hidl_vec categories; + categories.resize(categories_set.size()); + std::size_t i = 0; + for (auto& c : categories_set) { + categories[i++] = c; + } + return categories; +} + +/* list categories from vendors. */ +TEST_F(AtraceHidlTest, listCategories) { + hidl_vec vnd_categories = getVendorCategoryName(atrace); + EXPECT_NE(0, vnd_categories.size()); +} + +/* enable categories. */ +TEST_F(AtraceHidlTest, enableCategories) { + hidl_vec vnd_categories = getVendorCategoryName(atrace); + // empty Category with ERROR_INVALID_ARGUMENT + hidl_vec empty_categories; + auto ret = atrace->enableCategories(empty_categories); + ASSERT_TRUE(ret.isOk()); + EXPECT_EQ(Status::ERROR_INVALID_ARGUMENT, ret); + // non-empty categories SUCCESS + ret = atrace->enableCategories(vnd_categories); + ASSERT_TRUE(ret.isOk()); + EXPECT_EQ(Status::SUCCESS, ret); +} + +/* enable categories. */ +TEST_F(AtraceHidlTest, disableAllCategories) { + auto ret = atrace->disableAllCategories(); + ASSERT_TRUE(ret.isOk()); + EXPECT_EQ(Status::SUCCESS, ret); +} + +int main(int argc, char** argv) { + ::testing::AddGlobalTestEnvironment(AtraceHidlEnvironment::Instance()); + ::testing::InitGoogleTest(&argc, argv); + AtraceHidlEnvironment::Instance()->init(&argc, argv); + int status = RUN_ALL_TESTS(); + ALOGI("Test result = %d", status); + return status; +} diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml index 88d1151840..ff5b3e8d70 100644 --- a/compatibility_matrices/compatibility_matrix.current.xml +++ b/compatibility_matrices/compatibility_matrix.current.xml @@ -1,4 +1,12 @@ + + android.hardware.atrace + 1.0 + + IAtraceDevice + default + + android.hardware.audio 4.0 From 317a9ed5bac3869b8c241a15887df9769b41aef5 Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Thu, 20 Sep 2018 14:25:01 -0700 Subject: [PATCH 123/718] audio: Allow vendors to configure hwbinder RPC buffer size If persist.vendor.audio.hw.binder.size_kbyte property is set, its value is used to configure the size of hwbinder's MMap buffer. Bug: 114776290 Test: set the property, check logcat Change-Id: Icb6a4d0ebe98eb702201f8a9f0fed3a91a24f7ba --- .../common/all-versions/default/service/Android.mk | 2 ++ .../all-versions/default/service/service.cpp | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/audio/common/all-versions/default/service/Android.mk b/audio/common/all-versions/default/service/Android.mk index 43d7fe19c5..e6ae03ee0c 100644 --- a/audio/common/all-versions/default/service/Android.mk +++ b/audio/common/all-versions/default/service/Android.mk @@ -31,12 +31,14 @@ LOCAL_SRC_FILES := \ LOCAL_CFLAGS := -Wall -Werror LOCAL_SHARED_LIBRARIES := \ + libcutils \ libbinder \ libhidlbase \ libhidltransport \ liblog \ libutils \ libhardware \ + libhwbinder \ android.hardware.audio@2.0 \ android.hardware.audio@4.0 \ android.hardware.audio.common@2.0 \ diff --git a/audio/common/all-versions/default/service/service.cpp b/audio/common/all-versions/default/service/service.cpp index c7ce638e7f..ff1394ebeb 100644 --- a/audio/common/all-versions/default/service/service.cpp +++ b/audio/common/all-versions/default/service/service.cpp @@ -24,16 +24,26 @@ #include #include #include +#include #include #include +#include using namespace android::hardware; using android::OK; int main(int /* argc */, char* /* argv */ []) { - android::ProcessState::initWithDriver("/dev/vndbinder"); + ::android::ProcessState::initWithDriver("/dev/vndbinder"); // start a threadpool for vndbinder interactions - android::ProcessState::self()->startThreadPool(); + ::android::ProcessState::self()->startThreadPool(); + + const int32_t defaultValue = -1; + int32_t value = + property_get_int32("persist.vendor.audio.service.hwbinder.size_kbyte", defaultValue); + if (value != defaultValue) { + ALOGD("Configuring hwbinder with mmap size %d KBytes", value); + ProcessState::initWithMmapSize(static_cast(value) * 1024); + } configureRpcThreadpool(16, true /*callerWillJoin*/); bool fail = registerPassthroughServiceImplementation() != OK && From 3f27a7b373305f98117607f159eeb3c4e1fe4f6f Mon Sep 17 00:00:00 2001 From: Hridya Valsaraju Date: Wed, 26 Sep 2018 13:06:21 -0700 Subject: [PATCH 124/718] Add command to read fastboot variable 'variant' Bug: 79480454 Test: fastboot getvar variant Change-Id: I04f588f09d03e121c066449b0a7223f51d2e59af --- fastboot/1.0/IFastboot.hal | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/fastboot/1.0/IFastboot.hal b/fastboot/1.0/IFastboot.hal index 5e42c17042..c5979d9c78 100644 --- a/fastboot/1.0/IFastboot.hal +++ b/fastboot/1.0/IFastboot.hal @@ -39,4 +39,15 @@ interface IFastboot { * FAILURE_UNKNOWN for an invalid/unsupported command. */ doOemCommand(string oemCmd) generates (Result result); + + /** + * Returns an OEM-defined string indicating the variant of the device, for + * example, US and ROW. + * + * @response variant Indicates the device variant. + * @response result Returns the status SUCCESS if the operation is successful, + * FAILURE_UNKNOWN otherwise. + */ + getVariant() generates (string variant, Result result); + }; From 0320d560eaaaaf88ca84dfd6b22b1792904d986c Mon Sep 17 00:00:00 2001 From: mike dooley Date: Fri, 21 Sep 2018 09:07:37 +0200 Subject: [PATCH 125/718] Adding getModelState to soundtrigger with build fix. original cl was ag/4879522 Bug: 70206501 Test: Built android Change-Id: I11f164d8ade66cd7e56f1fa4e46dafa1d56db8cd --- .../2.0/default/SoundTriggerHalImpl.cpp | 2 +- .../2.0/default/SoundTriggerHalImpl.h | 5 +- soundtrigger/2.2/Android.bp | 20 +++ soundtrigger/2.2/ISoundTriggerHw.hal | 40 ++++++ soundtrigger/2.2/default/Android.mk | 50 ++++++++ soundtrigger/2.2/default/SoundTriggerHw.cpp | 110 +++++++++++++++++ soundtrigger/2.2/default/SoundTriggerHw.h | 114 ++++++++++++++++++ soundtrigger/2.2/vts/functional/Android.bp | 29 +++++ .../VtsHalSoundtriggerV2_2TargetTest.cpp | 101 ++++++++++++++++ 9 files changed, 469 insertions(+), 2 deletions(-) create mode 100644 soundtrigger/2.2/Android.bp create mode 100644 soundtrigger/2.2/ISoundTriggerHw.hal create mode 100644 soundtrigger/2.2/default/Android.mk create mode 100644 soundtrigger/2.2/default/SoundTriggerHw.cpp create mode 100644 soundtrigger/2.2/default/SoundTriggerHw.h create mode 100644 soundtrigger/2.2/vts/functional/Android.bp create mode 100644 soundtrigger/2.2/vts/functional/VtsHalSoundtriggerV2_2TargetTest.cpp diff --git a/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp b/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp index 612772cc63..2de35e8a0d 100644 --- a/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp +++ b/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp @@ -247,7 +247,7 @@ exit: } SoundTriggerHalImpl::SoundTriggerHalImpl() - : mModuleName("primary"), mHwDevice(NULL), mNextModelId(1) {} + : mModuleName("primary"), mNextModelId(1), mHwDevice(NULL) {} void SoundTriggerHalImpl::onFirstRef() { const hw_module_t* mod; diff --git a/soundtrigger/2.0/default/SoundTriggerHalImpl.h b/soundtrigger/2.0/default/SoundTriggerHalImpl.h index 5a9f0e19af..fbe24c15d9 100644 --- a/soundtrigger/2.0/default/SoundTriggerHalImpl.h +++ b/soundtrigger/2.0/default/SoundTriggerHalImpl.h @@ -167,8 +167,11 @@ class SoundTriggerHalImpl : public RefBase { static void recognitionCallback(struct sound_trigger_recognition_event* halEvent, void* cookie); const char* mModuleName; - struct sound_trigger_hw_device* mHwDevice; + volatile atomic_uint_fast32_t mNextModelId; + + protected: + struct sound_trigger_hw_device* mHwDevice; DefaultKeyedVector > mClients; Mutex mLock; }; diff --git a/soundtrigger/2.2/Android.bp b/soundtrigger/2.2/Android.bp new file mode 100644 index 0000000000..0a7c2d80ba --- /dev/null +++ b/soundtrigger/2.2/Android.bp @@ -0,0 +1,20 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +hidl_interface { + name: "android.hardware.soundtrigger@2.2", + root: "android.hardware", + vndk: { + enabled: true, + }, + srcs: [ + "ISoundTriggerHw.hal", + ], + interfaces: [ + "android.hardware.audio.common@2.0", + "android.hardware.soundtrigger@2.0", + "android.hardware.soundtrigger@2.1", + "android.hidl.base@1.0", + ], + gen_java: false, +} + diff --git a/soundtrigger/2.2/ISoundTriggerHw.hal b/soundtrigger/2.2/ISoundTriggerHw.hal new file mode 100644 index 0000000000..c5033588de --- /dev/null +++ b/soundtrigger/2.2/ISoundTriggerHw.hal @@ -0,0 +1,40 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.soundtrigger@2.2; + +import @2.1::ISoundTriggerHw; +import @2.0::SoundModelHandle; +import @2.0::ISoundTriggerHwCallback.RecognitionEvent; + +/** + * SoundTrigger HAL interface. Used for hardware recognition of hotwords. + */ +interface ISoundTriggerHw extends @2.1::ISoundTriggerHw { + + /** + * Get the state of a given model. + * The model state is returned as a RecognitionEvent. + * @param modelHandle The handle of the sound model to use for recognition + * @return retval Operation completion status: 0 in case of success, + * -ENOSYS in case of invalid model handle, + * -ENOMEM in case of memory allocation failure, + * -ENODEV in case of initialization error. + * @return state RecognitionEvent in case of success + */ + getModelState(SoundModelHandle modelHandle) + generates (int32_t retval, RecognitionEvent state); +}; diff --git a/soundtrigger/2.2/default/Android.mk b/soundtrigger/2.2/default/Android.mk new file mode 100644 index 0000000000..8c0f653d8d --- /dev/null +++ b/soundtrigger/2.2/default/Android.mk @@ -0,0 +1,50 @@ +# +# Copyright (C) 2018 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE := android.hardware.soundtrigger@2.2-impl +LOCAL_VENDOR_MODULE := true +LOCAL_MODULE_RELATIVE_PATH := hw +LOCAL_SRC_FILES := \ + SoundTriggerHw.cpp + +LOCAL_CFLAGS := -Wall -Werror + +LOCAL_SHARED_LIBRARIES := \ + libhardware \ + libhidlbase \ + libhidlmemory \ + libhidltransport \ + liblog \ + libutils \ + android.hardware.soundtrigger@2.2 \ + android.hardware.soundtrigger@2.1 \ + android.hardware.soundtrigger@2.0 \ + android.hardware.soundtrigger@2.0-core \ + android.hidl.allocator@1.0 \ + android.hidl.memory@1.0 + +LOCAL_C_INCLUDE_DIRS := $(LOCAL_PATH) + +ifeq ($(strip $(AUDIOSERVER_MULTILIB)),) +LOCAL_MULTILIB := 32 +else +LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB) +endif + +include $(BUILD_SHARED_LIBRARY) diff --git a/soundtrigger/2.2/default/SoundTriggerHw.cpp b/soundtrigger/2.2/default/SoundTriggerHw.cpp new file mode 100644 index 0000000000..90faf33598 --- /dev/null +++ b/soundtrigger/2.2/default/SoundTriggerHw.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "SoundTriggerHw" + +#include "SoundTriggerHw.h" + +#include +#include + +namespace android { +namespace hardware { +namespace soundtrigger { +namespace V2_2 { +namespace implementation { + +Return SoundTriggerHw::getModelState_2_2(int32_t modelHandle, getModelState_cb hidl_cb) { + sp client; + if (mHwDevice == NULL) { + hidl_cb(-ENODEV, NULL); + return Void(); + } + + { + AutoMutex lock(mLock); + client = mClients.valueFor(modelHandle); + if (client == 0) { + hidl_cb(-ENOSYS, NULL); + return Void(); + } + } + + if (mHwDevice->get_model_state == NULL) { + ALOGE("Failed to get model state from device, no such method"); + hidl_cb(-ENODEV, NULL); + return Void(); + } + + // Get the state from the device (as a recognition event) + struct sound_trigger_recognition_event* event = + mHwDevice->get_model_state(mHwDevice, client->getHalHandle()); + if (event == NULL) { + ALOGE("Failed to get model state from device"); + hidl_cb(-ENODEV, NULL); + return Void(); + } + + // Allocate shared memory to return to the client + sp alloc = IAllocator::getService("ashmem"); + if (alloc == 0) { + ALOGE("Failed to retrieve ashmem allocator service"); + free(event); + hidl_cb(-ENOMEM, NULL); + return Void(); + } + // Note: Only generic recognition events are currently supported + int n_bytes = sizeof(struct sound_trigger_generic_recognition_event); + bool success = false; + const hidl_memory& mem; + Return r = ashmem->allocate(n_bytes, [&](bool s, const hidl_memory& m) { + success = s; + if (success) mem = m; + }); + if (r.isOk() && success) { + // Copy the event data to the shared memory + sp memory = mapMemory(mem); + if (memory != 0) { + struct sound_trigger_generic_recognition_event* data = + (struct sound_trigger_generic_recognition_event*)memory->getPointer(); + memory->update(); + *data = *event; + memory->commit(); + + // Return the event memory via this callback + hidl_cb(0, memory); + } else { + ALOGE("Failed to map memory for recognition event"); + hidl_cb(-ENOMEM, NULL); + } + } else { + ALOGE("Failed to allocate %d bytes from ashmem allocator service", n_bytes); + hidl_cb(-ENOMEM, NULL); + } + + free(event); + return Void(); +} + +ISoundTriggerHw* HIDL_FETCH_ISoundTriggerHw(const char* /* name */) { + return (new SoundTriggerHw())->getInterface(); +} + +} // namespace implementation +} // namespace V2_2 +} // namespace soundtrigger +} // namespace hardware +} // namespace android diff --git a/soundtrigger/2.2/default/SoundTriggerHw.h b/soundtrigger/2.2/default/SoundTriggerHw.h new file mode 100644 index 0000000000..7db54db941 --- /dev/null +++ b/soundtrigger/2.2/default/SoundTriggerHw.h @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_SOUNDTRIGGER_V2_2_SOUNDTRIGGERHW_H +#define ANDROID_HARDWARE_SOUNDTRIGGER_V2_2_SOUNDTRIGGERHW_H + +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace soundtrigger { +namespace V2_2 { +namespace implementation { + +using ::android::sp; +using ::android::hardware::Return; + +struct SoundTriggerHw : public V2_1::implementation::SoundTriggerHw { + SoundTriggerHw() = default; + ISoundTriggerHw* getInterface() { return new TrampolineSoundTriggerHw_2_2(this); } + + protected: + virtual ~SoundTriggerHw() = default; + + Return> getModelState_2_2( + V2_0::SoundModelHandle modelHandle modelHandle); + + private: + struct TrampolineSoundTriggerHw_2_2 : public ISoundTriggerHw { + explicit TrampolineSoundTriggerHw_2_2(sp impl) : mImpl(impl) {} + + // Methods from ::android::hardware::soundtrigger::V2_0::ISoundTriggerHw follow. + Return getProperties(getProperties_cb _hidl_cb) override { + return mImpl->getProperties(_hidl_cb); + } + Return loadSoundModel(const V2_0::ISoundTriggerHw::SoundModel& soundModel, + const sp& callback, + int32_t cookie, loadSoundModel_cb _hidl_cb) override { + return mImpl->loadSoundModel(soundModel, callback, cookie, _hidl_cb); + } + Return loadPhraseSoundModel(const V2_0::ISoundTriggerHw::PhraseSoundModel& soundModel, + const sp& callback, + int32_t cookie, + loadPhraseSoundModel_cb _hidl_cb) override { + return mImpl->loadPhraseSoundModel(soundModel, callback, cookie, _hidl_cb); + } + Return unloadSoundModel(V2_0::SoundModelHandle modelHandle) override { + return mImpl->unloadSoundModel(modelHandle); + } + Return startRecognition(int32_t modelHandle, + const V2_0::ISoundTriggerHw::RecognitionConfig& config, + const sp& /*callback*/, + int32_t /*cookie*/) override { + return mImpl->startRecognition(modelHandle, config); + } + Return stopRecognition(V2_0::SoundModelHandle modelHandle) override { + return mImpl->stopRecognition(modelHandle); + } + Return stopAllRecognitions() override { return mImpl->stopAllRecognitions(); } + + // Methods from V2_1::ISoundTriggerHw follow. + Return loadSoundModel_2_1(const V2_1::ISoundTriggerHw::SoundModel& soundModel, + const sp& callback, + int32_t cookie, loadSoundModel_2_1_cb _hidl_cb) override { + return mImpl->loadSoundModel_2_1(soundModel, callback, cookie, _hidl_cb); + } + Return loadPhraseSoundModel_2_1( + const V2_1::ISoundTriggerHw::PhraseSoundModel& soundModel, + const sp& callback, int32_t cookie, + loadPhraseSoundModel_2_1_cb _hidl_cb) override { + return mImpl->loadPhraseSoundModel_2_1(soundModel, callback, cookie, _hidl_cb); + } + Return startRecognition_2_1(int32_t modelHandle, + const V2_1::ISoundTriggerHw::RecognitionConfig& config, + const sp& /*callback*/, + int32_t /*cookie*/) override { + return mImpl->startRecognition_2_1(modelHandle, config); + } + + // Methods from V2_2::ISoundTriggerHw follow. + Return getModelState(int32_t modelHandle, getModelState_cb hidl_cb) override { + return mImpl->getModelState_2_2(modelHandle, hidl_cb); + } + + private: + sp mImpl; + }; +}; + +extern "C" ISoundTriggerHw* HIDL_FETCH_ISoundTriggerHw(const char* name); + +} // namespace implementation +} // namespace V2_2 +} // namespace soundtrigger +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_SOUNDTRIGGER_V2_2_SOUNDTRIGGERHW_H diff --git a/soundtrigger/2.2/vts/functional/Android.bp b/soundtrigger/2.2/vts/functional/Android.bp new file mode 100644 index 0000000000..adbd0188b4 --- /dev/null +++ b/soundtrigger/2.2/vts/functional/Android.bp @@ -0,0 +1,29 @@ +// +// Copyright (C) 2018 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +cc_test { + name: "VtsHalSoundtriggerV2_2TargetTest", + defaults: ["VtsHalTargetTestDefaults"], + srcs: ["VtsHalSoundtriggerV2_2TargetTest.cpp"], + static_libs: [ + "android.hidl.allocator@1.0", + "android.hidl.memory@1.0", + "android.hardware.soundtrigger@2.0", + "android.hardware.soundtrigger@2.1", + "android.hardware.soundtrigger@2.2", + "libhidlmemory" + ], +} diff --git a/soundtrigger/2.2/vts/functional/VtsHalSoundtriggerV2_2TargetTest.cpp b/soundtrigger/2.2/vts/functional/VtsHalSoundtriggerV2_2TargetTest.cpp new file mode 100644 index 0000000000..ed5149fe7d --- /dev/null +++ b/soundtrigger/2.2/vts/functional/VtsHalSoundtriggerV2_2TargetTest.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "SoundTriggerHidlHalTest" +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +using ::android::sp; +using ::android::hardware::Return; +using ::android::hardware::soundtrigger::V2_0::ISoundTriggerHwCallback; +using ::android::hardware::soundtrigger::V2_0::SoundModelHandle; +using ::android::hardware::soundtrigger::V2_2::ISoundTriggerHw; + +// Test environment for SoundTrigger HIDL HAL. +class SoundTriggerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { + public: + // get the test environment singleton + static SoundTriggerHidlEnvironment* Instance() { + static SoundTriggerHidlEnvironment* instance = new SoundTriggerHidlEnvironment; + return instance; + } + + void registerTestServices() override { registerTestService(); } + + private: + SoundTriggerHidlEnvironment() {} +}; + +// The main test class for Sound Trigger HIDL HAL. +class SoundTriggerHidlTest : public ::testing::VtsHalHidlTargetTestBase { + public: + void SetUp() override { + mSoundTriggerHal = ::testing::VtsHalHidlTargetTestBase::getService( + SoundTriggerHidlEnvironment::Instance()->getServiceName()); + ASSERT_NE(nullptr, mSoundTriggerHal.get()); + } + + static void SetUpTestCase() { srand(1234); } + + void TearDown() override {} + + protected: + sp mSoundTriggerHal; +}; + +/** + * Test ISoundTriggerHw::getModelState() method + * + * Verifies that: + * - the implementation returns -EINVAL with invalid model handle + * + */ +TEST_F(SoundTriggerHidlTest, GetModelStateInvalidModel) { + int ret = android::OK; + ISoundTriggerHwCallback::RecognitionEvent event; + SoundModelHandle handle = 0; + Return hidlReturn = + mSoundTriggerHal->getModelState(handle, [&](int32_t retval, auto res) { + ret = retval; + event = res; + }); + + EXPECT_TRUE(hidlReturn.isOk()); + EXPECT_EQ(-ENOSYS, ret); +} + +int main(int argc, char** argv) { + ::testing::AddGlobalTestEnvironment(SoundTriggerHidlEnvironment::Instance()); + ::testing::InitGoogleTest(&argc, argv); + SoundTriggerHidlEnvironment::Instance()->init(&argc, argv); + int status = RUN_ALL_TESTS(); + ALOGI("Test result = %d", status); + return status; +} From 4a211d836457e22788010ddd58c8c2f6dd3cfbe7 Mon Sep 17 00:00:00 2001 From: Slava Shklyaev Date: Thu, 27 Sep 2018 16:18:54 +0100 Subject: [PATCH 126/718] Fix indexing bug in NNAPI Bug: 114365802 Test: n/a Change-Id: I87173528b58f66175c99e7c7e2e66daa307b04da --- neuralnetworks/1.2/types.hal | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal index 0e076f5c5b..43771316d8 100644 --- a/neuralnetworks/1.2/types.hal +++ b/neuralnetworks/1.2/types.hal @@ -68,14 +68,14 @@ enum OperationType : @1.1::OperationType { SELECT = 76, SIN = 77, SLICE = 78, - SPARSE_TO_DENSE = 78, - SPLIT = 79, - SQRT = 80, - TILE = 81, - TOPK_V2 = 82, - TRANSPOSE_CONV_2D = 83, - UNIDIRECTIONAL_SEQUENCE_LSTM = 84, - UNIDIRECTIONAL_SEQUENCE_RNN = 85, + SPARSE_TO_DENSE = 79, + SPLIT = 80, + SQRT = 81, + TILE = 82, + TOPK_V2 = 83, + TRANSPOSE_CONV_2D = 84, + UNIDIRECTIONAL_SEQUENCE_LSTM = 85, + UNIDIRECTIONAL_SEQUENCE_RNN = 86, }; /** From 6a6fe0f47bb02e0d29c8dc4a9f909612a1c616ba Mon Sep 17 00:00:00 2001 From: Yin-Chia Yeh Date: Thu, 6 Sep 2018 15:38:34 -0700 Subject: [PATCH 127/718] Camera: new buffer management HIDL APIs No actual implementations yet. Test: compile, new VTS to be written Bug: 109829698 Change-Id: Ibe509dd743a84b147fdfed6599d8f066adb8793b --- camera/device/3.2/ICameraDevice.hal | 4 +- camera/device/3.2/ICameraDeviceSession.hal | 5 +- camera/device/3.4/ICameraDeviceSession.hal | 2 +- camera/device/3.5/Android.bp | 10 ++ camera/device/3.5/ICameraDeviceCallback.hal | 70 ++++++++ camera/device/3.5/ICameraDeviceSession.hal | 73 ++++++++ camera/device/3.5/default/Android.bp | 1 + camera/device/3.5/default/CameraDevice.cpp | 16 ++ .../3.5/default/CameraDeviceSession.cpp | 68 ++++++++ .../device_v3_5_impl/CameraDeviceSession.h | 157 ++++++++++++++++++ .../device_v3_5_impl/CameraDevice_3_5.h | 6 +- camera/device/3.5/types.hal | 131 +++++++++++++++ camera/metadata/3.4/Android.bp | 1 + camera/provider/2.4/Android.bp | 1 - .../provider/2.4/default/CameraProvider.cpp | 2 + current.txt | 3 + 16 files changed, 543 insertions(+), 7 deletions(-) create mode 100644 camera/device/3.5/ICameraDeviceCallback.hal create mode 100644 camera/device/3.5/default/CameraDeviceSession.cpp create mode 100644 camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h create mode 100644 camera/device/3.5/types.hal diff --git a/camera/device/3.2/ICameraDevice.hal b/camera/device/3.2/ICameraDevice.hal index 1f523e420d..5236bb1cd8 100644 --- a/camera/device/3.2/ICameraDevice.hal +++ b/camera/device/3.2/ICameraDevice.hal @@ -148,7 +148,9 @@ interface ICameraDevice { * session handle for active operations. * * @param callback Interface to invoke by the HAL for device asynchronous - * events. + * events. For HALs newer than version 3.2, HAL must use castFrom + * method to check the exact version of callback sent by camera service. + * * @return status Status code for the operation, one of: * OK: * On a successful open of the camera device. diff --git a/camera/device/3.2/ICameraDeviceSession.hal b/camera/device/3.2/ICameraDeviceSession.hal index 477a3cc5d0..225e52b01e 100644 --- a/camera/device/3.2/ICameraDeviceSession.hal +++ b/camera/device/3.2/ICameraDeviceSession.hal @@ -149,9 +149,8 @@ interface ICameraDeviceSession { * - Including too many output streams of a certain format. * - Unsupported rotation configuration * - Stream sizes/formats don't satisfy the - * camera3_stream_configuration_t->operation_mode requirements - * for non-NORMAL mode, or the requested operation_mode is not - * supported by the HAL. + * StreamConfigurationMode requirements for non-NORMAL mode, or + * the requested operation_mode is not supported by the HAL. * - Unsupported usage flag * The camera service cannot filter out all possible illegal stream * configurations, since some devices may support more simultaneous diff --git a/camera/device/3.4/ICameraDeviceSession.hal b/camera/device/3.4/ICameraDeviceSession.hal index c41d90e27a..e1663e6669 100644 --- a/camera/device/3.4/ICameraDeviceSession.hal +++ b/camera/device/3.4/ICameraDeviceSession.hal @@ -54,7 +54,7 @@ interface ICameraDeviceSession extends @3.3::ICameraDeviceSession { * - Including too many output streams of a certain format. * - Unsupported rotation configuration * - Stream sizes/formats don't satisfy the - * camera3_stream_configuration_t->operation_mode requirements + * StreamConfigurationMode requirements * for non-NORMAL mode, or the requested operation_mode is not * supported by the HAL. * - Unsupported usage flag diff --git a/camera/device/3.5/Android.bp b/camera/device/3.5/Android.bp index a4e9ee2243..2a9ba05571 100644 --- a/camera/device/3.5/Android.bp +++ b/camera/device/3.5/Android.bp @@ -7,7 +7,9 @@ hidl_interface { enabled: true, }, srcs: [ + "types.hal", "ICameraDevice.hal", + "ICameraDeviceCallback.hal", "ICameraDeviceSession.hal", ], interfaces: [ @@ -18,6 +20,14 @@ hidl_interface { "android.hardware.graphics.common@1.0", "android.hidl.base@1.0", ], + types: [ + "BufferRequest", + "BufferRequestStatus", + "StreamBufferRequestError", + "StreamBufferRet", + "StreamBuffersVal", + "StreamConfiguration", + ], gen_java: false, } diff --git a/camera/device/3.5/ICameraDeviceCallback.hal b/camera/device/3.5/ICameraDeviceCallback.hal new file mode 100644 index 0000000000..aa4ad22ac5 --- /dev/null +++ b/camera/device/3.5/ICameraDeviceCallback.hal @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.camera.device@3.5; + +import @3.2::StreamBuffer; +import @3.4::ICameraDeviceCallback; + +/** + * Callback methods for the HAL to call into the framework. + */ +interface ICameraDeviceCallback extends @3.4::ICameraDeviceCallback { + + /** + * requestStreamBuffers: + * + * Synchronous callback for HAL to ask for output buffers from camera service. + * + * This call may be serialized in camera service so it is strongly + * recommended to only call this method from one thread. + * + * When camera device advertises + * (CameraMetadataEnumAndroidInfoSupportedBufferManagementVersion == + * ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5), HAL + * can use this method to request buffers from camera service. + * + * @return status Status code for the operation, one of: + * OK: all requested buffers are returned + * FAILED_PARTIAL: some streams failed while some succeeds. Check + * individual StreamBufferRet for details. + * FAILED_CONFIGURING: the request failed because camera servicve is + * performing configureStreams and no buffers are returned. + * FAILED_UNKNOWN: the request failed for unknown reason and no buffers + * are returned. + * + * Performance requirements: + * This is a blocking call that takes more time with more buffers requested. + * HAL must not request large amount of buffers on a latency critical code + * path. It is highly recommended to use a dedicated thread to perform + * all requestStreamBuffers calls, and adjust the thread priority and/or + * timing of making the call in order for buffers to arrive before HAL is + * ready to fill the buffer. + */ + requestStreamBuffers(vec bufReqs) + generates (BufferRequestStatus st, vec buffers); + + /** + * returnStreamBuffers: + * + * Synchronous callback for HAL to return output buffers to camera service. + * + * If this method is called during a configureStreams call, it must be blocked + * until camera service finishes the ongoing configureStreams call. + */ + returnStreamBuffers(vec buffers); + +}; diff --git a/camera/device/3.5/ICameraDeviceSession.hal b/camera/device/3.5/ICameraDeviceSession.hal index 84066851e9..b2b71cdd35 100644 --- a/camera/device/3.5/ICameraDeviceSession.hal +++ b/camera/device/3.5/ICameraDeviceSession.hal @@ -18,6 +18,7 @@ package android.hardware.camera.device@3.5; import android.hardware.camera.common@1.0::Status; import @3.4::ICameraDeviceSession; +import @3.4::HalStreamConfiguration; /** * Camera device active session interface. @@ -26,4 +27,76 @@ import @3.4::ICameraDeviceSession; * configure and request captures from an active camera device. */ interface ICameraDeviceSession extends @3.4::ICameraDeviceSession { + + /** + * configureStreams_3_5: + * + * Identical to @3.4::ICameraDeviceSession.configureStreams, except that: + * + * - a streamConfigCounter counter is provided to check for race condition + * between configureStreams_3_5 and signalStreamFlush call. + * + * @return status Status code for the operation, one of: + * OK: + * On successful stream configuration. + * INTERNAL_ERROR: + * If there has been a fatal error and the device is no longer + * operational. Only close() can be called successfully by the + * framework after this error is returned. + * ILLEGAL_ARGUMENT: + * If the requested stream configuration is invalid. Some examples + * of invalid stream configurations include: + * - Including more than 1 INPUT stream + * - Not including any OUTPUT streams + * - Including streams with unsupported formats, or an unsupported + * size for that format. + * - Including too many output streams of a certain format. + * - Unsupported rotation configuration + * - Stream sizes/formats don't satisfy the + * StreamConfigurationMode requirements + * for non-NORMAL mode, or the requested operation_mode is not + * supported by the HAL. + * - Unsupported usage flag + * The camera service cannot filter out all possible illegal stream + * configurations, since some devices may support more simultaneous + * streams or larger stream resolutions than the minimum required + * for a given camera device hardware level. The HAL must return an + * ILLEGAL_ARGUMENT for any unsupported stream set, and then be + * ready to accept a future valid stream configuration in a later + * configureStreams call. + * @return halConfiguration The stream parameters desired by the HAL for + * each stream, including maximum buffers, the usage flags, and the + * override format. + */ + configureStreams_3_5(@3.5::StreamConfiguration requestedConfiguration) + generates (Status status, + @3.4::HalStreamConfiguration halConfiguration); + + + /** + * signalStreamFlush: + * + * Signaling HAL camera service is about to perform configureStreams_3_5 and + * HAL must return all buffers of designated streams. HAL must finish + * inflight requests normally and return all buffers that belongs to the + * designated streams through processCaptureResult or returnStreamBuffer + * API in a timely manner, or camera service will run into a fatal error. + * + * Note that this call serves as an optional hint and camera service may + * skip sending this call if all buffers are already returned. + * + * @param streamIds The ID of streams camera service need all of its + * buffers returned. + * + * @param streamConfigCounter Note that due to concurrency nature, it is + * possible the signalStreamFlush call arrives later than the + * corresponding configureStreams_3_5 call, HAL must check + * streamConfigCounter for such race condition. If the counter is less + * than the counter in the last configureStreams_3_5 call HAL last + * received, the call is stale and HAL should just return this call. + */ + oneway signalStreamFlush( + vec streamIds, + uint32_t streamConfigCounter + ); }; diff --git a/camera/device/3.5/default/Android.bp b/camera/device/3.5/default/Android.bp index 341f573b7f..09cf3a421c 100644 --- a/camera/device/3.5/default/Android.bp +++ b/camera/device/3.5/default/Android.bp @@ -27,6 +27,7 @@ cc_library_shared { vendor: true, srcs: [ "CameraDevice.cpp", + "CameraDeviceSession.cpp", ], shared_libs: [ "libhidlbase", diff --git a/camera/device/3.5/default/CameraDevice.cpp b/camera/device/3.5/default/CameraDevice.cpp index fcd1c96565..c5d6c576d8 100644 --- a/camera/device/3.5/default/CameraDevice.cpp +++ b/camera/device/3.5/default/CameraDevice.cpp @@ -39,6 +39,22 @@ CameraDevice::CameraDevice(sp module, const std::string& cameraId, CameraDevice::~CameraDevice() { } +sp CameraDevice::createSession(camera3_device_t* device, + const camera_metadata_t* deviceInfo, + const sp& callback) { + sp session = new CameraDeviceSession(device, deviceInfo, callback); + IF_ALOGV() { + session->getInterface()->interfaceChain([]( + ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) { + ALOGV("Session interface chain:"); + for (auto iface : interfaceChain) { + ALOGV(" %s", iface.c_str()); + } + }); + } + return session; +} + Return CameraDevice::getPhysicalCameraCharacteristics(const hidl_string& physicalCameraId, V3_5::ICameraDevice::getPhysicalCameraCharacteristics_cb _hidl_cb) { Status status = initStatus(); diff --git a/camera/device/3.5/default/CameraDeviceSession.cpp b/camera/device/3.5/default/CameraDeviceSession.cpp new file mode 100644 index 0000000000..5336ca9ef0 --- /dev/null +++ b/camera/device/3.5/default/CameraDeviceSession.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "CamDevSession@3.5-impl" +#include + +#include +#include "CameraDeviceSession.h" + +namespace android { +namespace hardware { +namespace camera { +namespace device { +namespace V3_5 { +namespace implementation { + +CameraDeviceSession::CameraDeviceSession( + camera3_device_t* device, + const camera_metadata_t* deviceInfo, + const sp& callback) : + V3_4::implementation::CameraDeviceSession(device, deviceInfo, callback) { + + mHasCallback_3_5 = false; + + auto castResult = ICameraDeviceCallback::castFrom(callback); + if (castResult.isOk()) { + sp callback3_5 = castResult; + if (callback3_5 != nullptr) { + mHasCallback_3_5 = true; + } + } +} + +CameraDeviceSession::~CameraDeviceSession() { +} + +Return CameraDeviceSession::configureStreams_3_5( + const StreamConfiguration& /*requestedConfiguration*/, + ICameraDeviceSession::configureStreams_3_5_cb _hidl_cb) { + HalStreamConfiguration outStreams; + _hidl_cb(Status::OPERATION_NOT_SUPPORTED, outStreams); + return Void(); +} + +Return CameraDeviceSession::signalStreamFlush( + const hidl_vec& /*requests*/, uint32_t /*streamConfigCounter*/) { + return Void(); +} + +} // namespace implementation +} // namespace V3_5 +} // namespace device +} // namespace camera +} // namespace hardware +} // namespace android diff --git a/camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h b/camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h new file mode 100644 index 0000000000..ec34769973 --- /dev/null +++ b/camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_CAMERA_DEVICE_V3_5_CAMERADEVICE3SESSION_H +#define ANDROID_HARDWARE_CAMERA_DEVICE_V3_5_CAMERADEVICE3SESSION_H + +#include +#include +#include +#include <../../3.4/default/include/device_v3_4_impl/CameraDeviceSession.h> + +namespace android { +namespace hardware { +namespace camera { +namespace device { +namespace V3_5 { +namespace implementation { + +using namespace ::android::hardware::camera::device; +using ::android::hardware::camera::device::V3_2::CaptureRequest; +using ::android::hardware::camera::device::V3_5::StreamConfiguration; +using ::android::hardware::camera::device::V3_4::HalStreamConfiguration; +using ::android::hardware::camera::device::V3_5::ICameraDeviceSession; +using ::android::hardware::camera::device::V3_5::ICameraDeviceCallback; +using ::android::hardware::camera::common::V1_0::Status; +using ::android::hardware::camera::common::V1_0::helper::HandleImporter; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::hidl_vec; +using ::android::hardware::hidl_string; +using ::android::sp; +using ::android::Mutex; + +struct CameraDeviceSession : public V3_4::implementation::CameraDeviceSession { + + CameraDeviceSession(camera3_device_t*, + const camera_metadata_t* deviceInfo, + const sp&); + virtual ~CameraDeviceSession(); + + virtual sp getInterface() override { + return new TrampolineSessionInterface_3_5(this); + } + +protected: + // Methods from v3.4 and earlier will trampoline to inherited implementation + Return configureStreams_3_5( + const StreamConfiguration& requestedConfiguration, + ICameraDeviceSession::configureStreams_3_5_cb _hidl_cb); + + Return signalStreamFlush( + const hidl_vec& requests, + uint32_t streamConfigCounter); + + + // Whether this camera device session is created with version 3.5 callback. + bool mHasCallback_3_5; + +private: + + struct TrampolineSessionInterface_3_5 : public ICameraDeviceSession { + TrampolineSessionInterface_3_5(sp parent) : + mParent(parent) {} + + virtual Return constructDefaultRequestSettings( + V3_2::RequestTemplate type, + V3_3::ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb) override { + return mParent->constructDefaultRequestSettings(type, _hidl_cb); + } + + virtual Return configureStreams( + const V3_2::StreamConfiguration& requestedConfiguration, + V3_3::ICameraDeviceSession::configureStreams_cb _hidl_cb) override { + return mParent->configureStreams(requestedConfiguration, _hidl_cb); + } + + virtual Return processCaptureRequest_3_4( + const hidl_vec& requests, + const hidl_vec& cachesToRemove, + ICameraDeviceSession::processCaptureRequest_3_4_cb _hidl_cb) override { + return mParent->processCaptureRequest_3_4(requests, cachesToRemove, _hidl_cb); + } + + virtual Return processCaptureRequest(const hidl_vec& requests, + const hidl_vec& cachesToRemove, + V3_3::ICameraDeviceSession::processCaptureRequest_cb _hidl_cb) override { + return mParent->processCaptureRequest(requests, cachesToRemove, _hidl_cb); + } + + virtual Return getCaptureRequestMetadataQueue( + V3_3::ICameraDeviceSession::getCaptureRequestMetadataQueue_cb _hidl_cb) override { + return mParent->getCaptureRequestMetadataQueue(_hidl_cb); + } + + virtual Return getCaptureResultMetadataQueue( + V3_3::ICameraDeviceSession::getCaptureResultMetadataQueue_cb _hidl_cb) override { + return mParent->getCaptureResultMetadataQueue(_hidl_cb); + } + + virtual Return flush() override { + return mParent->flush(); + } + + virtual Return close() override { + return mParent->close(); + } + + virtual Return configureStreams_3_3( + const V3_2::StreamConfiguration& requestedConfiguration, + configureStreams_3_3_cb _hidl_cb) override { + return mParent->configureStreams_3_3(requestedConfiguration, _hidl_cb); + } + + virtual Return configureStreams_3_4( + const V3_4::StreamConfiguration& requestedConfiguration, + configureStreams_3_4_cb _hidl_cb) override { + return mParent->configureStreams_3_4(requestedConfiguration, _hidl_cb); + } + + virtual Return configureStreams_3_5( + const StreamConfiguration& requestedConfiguration, + configureStreams_3_5_cb _hidl_cb) override { + return mParent->configureStreams_3_5(requestedConfiguration, _hidl_cb); + } + + virtual Return signalStreamFlush( + const hidl_vec& requests, + uint32_t streamConfigCounter) override { + return mParent->signalStreamFlush(requests, streamConfigCounter); + } + + private: + sp mParent; + }; +}; + +} // namespace implementation +} // namespace V3_5 +} // namespace device +} // namespace camera +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_CAMERA_DEVICE_V3_5_CAMERADEVICE3SESSION_H diff --git a/camera/device/3.5/default/include/device_v3_5_impl/CameraDevice_3_5.h b/camera/device/3.5/default/include/device_v3_5_impl/CameraDevice_3_5.h index f250bc9669..6bdc60f2d9 100644 --- a/camera/device/3.5/default/include/device_v3_5_impl/CameraDevice_3_5.h +++ b/camera/device/3.5/default/include/device_v3_5_impl/CameraDevice_3_5.h @@ -17,7 +17,7 @@ #ifndef ANDROID_HARDWARE_CAMERA_DEVICE_V3_5_CAMERADEVICE_H #define ANDROID_HARDWARE_CAMERA_DEVICE_V3_5_CAMERADEVICE_H -#include "CameraModule.h" +#include "CameraDeviceSession.h" #include <../../../../3.4/default/include/device_v3_4_impl/CameraDevice_3_4.h> #include @@ -57,6 +57,10 @@ struct CameraDevice : public V3_4::implementation::CameraDevice { } protected: + virtual sp createSession(camera3_device_t*, + const camera_metadata_t* deviceInfo, + const sp&) override; + Return getPhysicalCameraCharacteristics(const hidl_string& physicalCameraId, V3_5::ICameraDevice::getPhysicalCameraCharacteristics_cb _hidl_cb); diff --git a/camera/device/3.5/types.hal b/camera/device/3.5/types.hal new file mode 100644 index 0000000000..613187d96e --- /dev/null +++ b/camera/device/3.5/types.hal @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.camera.device@3.5; + +import @3.2::StreamBuffer; +import @3.4::StreamConfiguration; + +/** + * StreamConfiguration: + * + * Identical to @3.4::StreamConfiguration, except that it contains streamConfigCounter + */ +struct StreamConfiguration { + @3.4::StreamConfiguration v3_4; + + /** + * An incrementing counter used for HAL to keep track of the stream + * configuration and the paired oneway signalStreamFlush call. When the + * counter in signalStreamFlush call is less than the counter here, that + * signalStreamFlush call is stale. + */ + uint32_t streamConfigCounter; +}; + +enum StreamBufferRequestError : uint32_t { + /** + * Get buffer failed due to timeout waiting for an available buffer. This is + * likely due to the client application holding too many buffers, or the + * system is under memory pressure. + * This is not a fatal error. HAL may try to request buffer for this stream + * later. If HAL cannot get a buffer for certain capture request in time + * due to this error, HAL can send an ERROR_REQUEST to camera service and + * drop processing that request. + */ + NO_BUFFER_AVAILABLE = 1, + + /** + * Get buffer failed due to HAL has reached its maxBuffer count. This is not + * a fatal error. HAL may try to request buffer for this stream again after + * it returns at least one buffer of that stream to camera service. + */ + MAX_BUFFER_EXCEEDED = 2, + + /** + * Get buffer failed due to the stream is disconnected by client + * application, has been removed, or not recognized by camera service. + * This means application is no longer interested in this stream. + * Requesting buffer for this stream must never succeed after this error is + * returned. HAL must safely return all buffers of this stream after + * getting this error. If HAL gets another capture request later targeting + * a disconnected stream, HAL must send an ERROR_REQUEST to camera service + * and drop processing that request. + */ + STREAM_DISCONNECTED = 3, + + /** + * Get buffer failed for unknown reasons. This is a fatal error and HAL must + * send ERROR_DEVICE to camera service and be ready to be closed. + */ + UNKNOWN_ERROR = 4 +}; + +/** + * Per-stream return value for requestStreamBuffers. + * For each stream, either an StreamBufferRequestError error code, or all + * requested buffers for this stream is returned, so buffers.size() must be + * equal to BufferRequest::numBuffersRequested of corresponding stream. + */ +safe_union StreamBuffersVal { + StreamBufferRequestError error; + vec<@3.2::StreamBuffer> buffers; +}; + +struct StreamBufferRet { + int32_t streamId; + StreamBuffersVal val; +}; + +enum BufferRequestStatus : uint32_t { + /** + * Method call succeeded and all requested buffers are returned. + */ + OK = 0, + + /** + * Method call failed for some streams. Check per stream status for each + * returned StreamBufferRet. + */ + FAILED_PARTIAL = 1, + + /** + * Method call failed for all streams and no buffers are returned at all. + * Camera service is about to or is performing configureStreams. HAL must + * wait until next configureStreams call is finished before requesting + * buffers again. + */ + FAILED_CONFIGURING = 2, + + /** + * Method call failed for all streams and no buffers are returned at all. + * Failure due to bad BufferRequest input, eg: unknown streamId or repeated + * streamId. + */ + FAILED_ILLEGAL_ARGUMENTS = 3, + + /** + * Method call failed for all streams and no buffers are returned at all. + * Failure due to unknown reason. + */ + FAILED_UNKNOWN = 4, +}; + +struct BufferRequest { + int32_t streamId; + uint32_t numBuffersRequested; +}; + diff --git a/camera/metadata/3.4/Android.bp b/camera/metadata/3.4/Android.bp index 04a00ef8dc..388df6848c 100644 --- a/camera/metadata/3.4/Android.bp +++ b/camera/metadata/3.4/Android.bp @@ -14,6 +14,7 @@ hidl_interface { "android.hardware.camera.metadata@3.3", ], types: [ + "CameraMetadataEnumAndroidInfoSupportedBufferManagementVersion", "CameraMetadataTag", ], gen_java: true, diff --git a/camera/provider/2.4/Android.bp b/camera/provider/2.4/Android.bp index 27329f3b5d..63d7fd5dca 100644 --- a/camera/provider/2.4/Android.bp +++ b/camera/provider/2.4/Android.bp @@ -14,7 +14,6 @@ hidl_interface { "android.hardware.camera.common@1.0", "android.hardware.camera.device@1.0", "android.hardware.camera.device@3.2", - "android.hardware.camera.device@3.5", "android.hidl.base@1.0", ], gen_java: false, diff --git a/camera/provider/2.4/default/CameraProvider.cpp b/camera/provider/2.4/default/CameraProvider.cpp index b69fe1a009..488b9afe58 100644 --- a/camera/provider/2.4/default/CameraProvider.cpp +++ b/camera/provider/2.4/default/CameraProvider.cpp @@ -552,6 +552,7 @@ Return CameraProvider::getCameraDeviceInterface_V3_x( return Void(); } + // ICameraDevice 3.4 or upper sp deviceImpl; if (deviceVersion >= kHAL3_4) { ALOGV("Constructing v3.4 camera device"); @@ -580,6 +581,7 @@ Return CameraProvider::getCameraDeviceInterface_V3_x( return Void(); } + // ICameraDevice 3.2 and 3.3 // Since some Treble HAL revisions can map to the same legacy HAL version(s), we default // to the newest possible Treble HAL revision, but allow for override if needed via // system property. diff --git a/current.txt b/current.txt index 4e5ec41383..7c77b36ac2 100644 --- a/current.txt +++ b/current.txt @@ -385,6 +385,9 @@ cd4330c3196bda1d642a32abfe23a7d64ebfbda721940643af6867af3b3f0aa9 android.hardwar 10ff2fae516346b86121368ce5790d5accdfcb73983246b813f3d488b66db45a android.hardware.wifi.supplicant@1.1::ISupplicantStaNetwork # ABI preserving changes to HALs during Android Q +2a55e224aa9bc62c0387cd85ad3c97e33f0c33a4e1489cbae86b2523e6f9df35 android.hardware.camera.device@3.2::ICameraDevice +f61b616732d8f374e030f90575d7eba3ecc99d209a05b945949ba892bcb81e1d android.hardware.camera.device@3.2::ICameraDeviceSession +684702a60deef03a1e8093961dc0a18c555c857ad5a77ba7340b0635ae01eb70 android.hardware.camera.device@3.4::ICameraDeviceSession a95745bbf76aea16a76518bd7efe70cabc5886d09eaeffc993c2e1787a22ed23 android.hardware.camera.metadata@3.3::types 5f936a5befde7af8d2a683670f80a836b4741e94d84b7b39026da3ed78be9906 android.hardware.configstore@1.0::ISurfaceFlingerConfigs 574e8f1499436fb4075894dcae0b36682427956ecb114f17f1fe22d116a83c6b android.hardware.neuralnetworks@1.0::IPreparedModel From ecac1123237c610a1166b1e07b678d259e4d4e71 Mon Sep 17 00:00:00 2001 From: Michael Dooley Date: Fri, 28 Sep 2018 07:25:12 +0000 Subject: [PATCH 128/718] Revert "Adding getModelState to soundtrigger with build fix." This reverts commit 0320d560eaaaaf88ca84dfd6b22b1792904d986c. Reason for revert: broke build Change-Id: I69cda44f90985b57e69455a8d04cec71f2675831 --- .../2.0/default/SoundTriggerHalImpl.cpp | 2 +- .../2.0/default/SoundTriggerHalImpl.h | 5 +- soundtrigger/2.2/Android.bp | 20 --- soundtrigger/2.2/ISoundTriggerHw.hal | 40 ------ soundtrigger/2.2/default/Android.mk | 50 -------- soundtrigger/2.2/default/SoundTriggerHw.cpp | 110 ----------------- soundtrigger/2.2/default/SoundTriggerHw.h | 114 ------------------ soundtrigger/2.2/vts/functional/Android.bp | 29 ----- .../VtsHalSoundtriggerV2_2TargetTest.cpp | 101 ---------------- 9 files changed, 2 insertions(+), 469 deletions(-) delete mode 100644 soundtrigger/2.2/Android.bp delete mode 100644 soundtrigger/2.2/ISoundTriggerHw.hal delete mode 100644 soundtrigger/2.2/default/Android.mk delete mode 100644 soundtrigger/2.2/default/SoundTriggerHw.cpp delete mode 100644 soundtrigger/2.2/default/SoundTriggerHw.h delete mode 100644 soundtrigger/2.2/vts/functional/Android.bp delete mode 100644 soundtrigger/2.2/vts/functional/VtsHalSoundtriggerV2_2TargetTest.cpp diff --git a/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp b/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp index 2de35e8a0d..612772cc63 100644 --- a/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp +++ b/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp @@ -247,7 +247,7 @@ exit: } SoundTriggerHalImpl::SoundTriggerHalImpl() - : mModuleName("primary"), mNextModelId(1), mHwDevice(NULL) {} + : mModuleName("primary"), mHwDevice(NULL), mNextModelId(1) {} void SoundTriggerHalImpl::onFirstRef() { const hw_module_t* mod; diff --git a/soundtrigger/2.0/default/SoundTriggerHalImpl.h b/soundtrigger/2.0/default/SoundTriggerHalImpl.h index fbe24c15d9..5a9f0e19af 100644 --- a/soundtrigger/2.0/default/SoundTriggerHalImpl.h +++ b/soundtrigger/2.0/default/SoundTriggerHalImpl.h @@ -167,11 +167,8 @@ class SoundTriggerHalImpl : public RefBase { static void recognitionCallback(struct sound_trigger_recognition_event* halEvent, void* cookie); const char* mModuleName; - - volatile atomic_uint_fast32_t mNextModelId; - - protected: struct sound_trigger_hw_device* mHwDevice; + volatile atomic_uint_fast32_t mNextModelId; DefaultKeyedVector > mClients; Mutex mLock; }; diff --git a/soundtrigger/2.2/Android.bp b/soundtrigger/2.2/Android.bp deleted file mode 100644 index 0a7c2d80ba..0000000000 --- a/soundtrigger/2.2/Android.bp +++ /dev/null @@ -1,20 +0,0 @@ -// This file is autogenerated by hidl-gen -Landroidbp. - -hidl_interface { - name: "android.hardware.soundtrigger@2.2", - root: "android.hardware", - vndk: { - enabled: true, - }, - srcs: [ - "ISoundTriggerHw.hal", - ], - interfaces: [ - "android.hardware.audio.common@2.0", - "android.hardware.soundtrigger@2.0", - "android.hardware.soundtrigger@2.1", - "android.hidl.base@1.0", - ], - gen_java: false, -} - diff --git a/soundtrigger/2.2/ISoundTriggerHw.hal b/soundtrigger/2.2/ISoundTriggerHw.hal deleted file mode 100644 index c5033588de..0000000000 --- a/soundtrigger/2.2/ISoundTriggerHw.hal +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.hardware.soundtrigger@2.2; - -import @2.1::ISoundTriggerHw; -import @2.0::SoundModelHandle; -import @2.0::ISoundTriggerHwCallback.RecognitionEvent; - -/** - * SoundTrigger HAL interface. Used for hardware recognition of hotwords. - */ -interface ISoundTriggerHw extends @2.1::ISoundTriggerHw { - - /** - * Get the state of a given model. - * The model state is returned as a RecognitionEvent. - * @param modelHandle The handle of the sound model to use for recognition - * @return retval Operation completion status: 0 in case of success, - * -ENOSYS in case of invalid model handle, - * -ENOMEM in case of memory allocation failure, - * -ENODEV in case of initialization error. - * @return state RecognitionEvent in case of success - */ - getModelState(SoundModelHandle modelHandle) - generates (int32_t retval, RecognitionEvent state); -}; diff --git a/soundtrigger/2.2/default/Android.mk b/soundtrigger/2.2/default/Android.mk deleted file mode 100644 index 8c0f653d8d..0000000000 --- a/soundtrigger/2.2/default/Android.mk +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright (C) 2018 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) -LOCAL_MODULE := android.hardware.soundtrigger@2.2-impl -LOCAL_VENDOR_MODULE := true -LOCAL_MODULE_RELATIVE_PATH := hw -LOCAL_SRC_FILES := \ - SoundTriggerHw.cpp - -LOCAL_CFLAGS := -Wall -Werror - -LOCAL_SHARED_LIBRARIES := \ - libhardware \ - libhidlbase \ - libhidlmemory \ - libhidltransport \ - liblog \ - libutils \ - android.hardware.soundtrigger@2.2 \ - android.hardware.soundtrigger@2.1 \ - android.hardware.soundtrigger@2.0 \ - android.hardware.soundtrigger@2.0-core \ - android.hidl.allocator@1.0 \ - android.hidl.memory@1.0 - -LOCAL_C_INCLUDE_DIRS := $(LOCAL_PATH) - -ifeq ($(strip $(AUDIOSERVER_MULTILIB)),) -LOCAL_MULTILIB := 32 -else -LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB) -endif - -include $(BUILD_SHARED_LIBRARY) diff --git a/soundtrigger/2.2/default/SoundTriggerHw.cpp b/soundtrigger/2.2/default/SoundTriggerHw.cpp deleted file mode 100644 index 90faf33598..0000000000 --- a/soundtrigger/2.2/default/SoundTriggerHw.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "SoundTriggerHw" - -#include "SoundTriggerHw.h" - -#include -#include - -namespace android { -namespace hardware { -namespace soundtrigger { -namespace V2_2 { -namespace implementation { - -Return SoundTriggerHw::getModelState_2_2(int32_t modelHandle, getModelState_cb hidl_cb) { - sp client; - if (mHwDevice == NULL) { - hidl_cb(-ENODEV, NULL); - return Void(); - } - - { - AutoMutex lock(mLock); - client = mClients.valueFor(modelHandle); - if (client == 0) { - hidl_cb(-ENOSYS, NULL); - return Void(); - } - } - - if (mHwDevice->get_model_state == NULL) { - ALOGE("Failed to get model state from device, no such method"); - hidl_cb(-ENODEV, NULL); - return Void(); - } - - // Get the state from the device (as a recognition event) - struct sound_trigger_recognition_event* event = - mHwDevice->get_model_state(mHwDevice, client->getHalHandle()); - if (event == NULL) { - ALOGE("Failed to get model state from device"); - hidl_cb(-ENODEV, NULL); - return Void(); - } - - // Allocate shared memory to return to the client - sp alloc = IAllocator::getService("ashmem"); - if (alloc == 0) { - ALOGE("Failed to retrieve ashmem allocator service"); - free(event); - hidl_cb(-ENOMEM, NULL); - return Void(); - } - // Note: Only generic recognition events are currently supported - int n_bytes = sizeof(struct sound_trigger_generic_recognition_event); - bool success = false; - const hidl_memory& mem; - Return r = ashmem->allocate(n_bytes, [&](bool s, const hidl_memory& m) { - success = s; - if (success) mem = m; - }); - if (r.isOk() && success) { - // Copy the event data to the shared memory - sp memory = mapMemory(mem); - if (memory != 0) { - struct sound_trigger_generic_recognition_event* data = - (struct sound_trigger_generic_recognition_event*)memory->getPointer(); - memory->update(); - *data = *event; - memory->commit(); - - // Return the event memory via this callback - hidl_cb(0, memory); - } else { - ALOGE("Failed to map memory for recognition event"); - hidl_cb(-ENOMEM, NULL); - } - } else { - ALOGE("Failed to allocate %d bytes from ashmem allocator service", n_bytes); - hidl_cb(-ENOMEM, NULL); - } - - free(event); - return Void(); -} - -ISoundTriggerHw* HIDL_FETCH_ISoundTriggerHw(const char* /* name */) { - return (new SoundTriggerHw())->getInterface(); -} - -} // namespace implementation -} // namespace V2_2 -} // namespace soundtrigger -} // namespace hardware -} // namespace android diff --git a/soundtrigger/2.2/default/SoundTriggerHw.h b/soundtrigger/2.2/default/SoundTriggerHw.h deleted file mode 100644 index 7db54db941..0000000000 --- a/soundtrigger/2.2/default/SoundTriggerHw.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_HARDWARE_SOUNDTRIGGER_V2_2_SOUNDTRIGGERHW_H -#define ANDROID_HARDWARE_SOUNDTRIGGER_V2_2_SOUNDTRIGGERHW_H - -#include -#include -#include -#include - -namespace android { -namespace hardware { -namespace soundtrigger { -namespace V2_2 { -namespace implementation { - -using ::android::sp; -using ::android::hardware::Return; - -struct SoundTriggerHw : public V2_1::implementation::SoundTriggerHw { - SoundTriggerHw() = default; - ISoundTriggerHw* getInterface() { return new TrampolineSoundTriggerHw_2_2(this); } - - protected: - virtual ~SoundTriggerHw() = default; - - Return> getModelState_2_2( - V2_0::SoundModelHandle modelHandle modelHandle); - - private: - struct TrampolineSoundTriggerHw_2_2 : public ISoundTriggerHw { - explicit TrampolineSoundTriggerHw_2_2(sp impl) : mImpl(impl) {} - - // Methods from ::android::hardware::soundtrigger::V2_0::ISoundTriggerHw follow. - Return getProperties(getProperties_cb _hidl_cb) override { - return mImpl->getProperties(_hidl_cb); - } - Return loadSoundModel(const V2_0::ISoundTriggerHw::SoundModel& soundModel, - const sp& callback, - int32_t cookie, loadSoundModel_cb _hidl_cb) override { - return mImpl->loadSoundModel(soundModel, callback, cookie, _hidl_cb); - } - Return loadPhraseSoundModel(const V2_0::ISoundTriggerHw::PhraseSoundModel& soundModel, - const sp& callback, - int32_t cookie, - loadPhraseSoundModel_cb _hidl_cb) override { - return mImpl->loadPhraseSoundModel(soundModel, callback, cookie, _hidl_cb); - } - Return unloadSoundModel(V2_0::SoundModelHandle modelHandle) override { - return mImpl->unloadSoundModel(modelHandle); - } - Return startRecognition(int32_t modelHandle, - const V2_0::ISoundTriggerHw::RecognitionConfig& config, - const sp& /*callback*/, - int32_t /*cookie*/) override { - return mImpl->startRecognition(modelHandle, config); - } - Return stopRecognition(V2_0::SoundModelHandle modelHandle) override { - return mImpl->stopRecognition(modelHandle); - } - Return stopAllRecognitions() override { return mImpl->stopAllRecognitions(); } - - // Methods from V2_1::ISoundTriggerHw follow. - Return loadSoundModel_2_1(const V2_1::ISoundTriggerHw::SoundModel& soundModel, - const sp& callback, - int32_t cookie, loadSoundModel_2_1_cb _hidl_cb) override { - return mImpl->loadSoundModel_2_1(soundModel, callback, cookie, _hidl_cb); - } - Return loadPhraseSoundModel_2_1( - const V2_1::ISoundTriggerHw::PhraseSoundModel& soundModel, - const sp& callback, int32_t cookie, - loadPhraseSoundModel_2_1_cb _hidl_cb) override { - return mImpl->loadPhraseSoundModel_2_1(soundModel, callback, cookie, _hidl_cb); - } - Return startRecognition_2_1(int32_t modelHandle, - const V2_1::ISoundTriggerHw::RecognitionConfig& config, - const sp& /*callback*/, - int32_t /*cookie*/) override { - return mImpl->startRecognition_2_1(modelHandle, config); - } - - // Methods from V2_2::ISoundTriggerHw follow. - Return getModelState(int32_t modelHandle, getModelState_cb hidl_cb) override { - return mImpl->getModelState_2_2(modelHandle, hidl_cb); - } - - private: - sp mImpl; - }; -}; - -extern "C" ISoundTriggerHw* HIDL_FETCH_ISoundTriggerHw(const char* name); - -} // namespace implementation -} // namespace V2_2 -} // namespace soundtrigger -} // namespace hardware -} // namespace android - -#endif // ANDROID_HARDWARE_SOUNDTRIGGER_V2_2_SOUNDTRIGGERHW_H diff --git a/soundtrigger/2.2/vts/functional/Android.bp b/soundtrigger/2.2/vts/functional/Android.bp deleted file mode 100644 index adbd0188b4..0000000000 --- a/soundtrigger/2.2/vts/functional/Android.bp +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright (C) 2018 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -cc_test { - name: "VtsHalSoundtriggerV2_2TargetTest", - defaults: ["VtsHalTargetTestDefaults"], - srcs: ["VtsHalSoundtriggerV2_2TargetTest.cpp"], - static_libs: [ - "android.hidl.allocator@1.0", - "android.hidl.memory@1.0", - "android.hardware.soundtrigger@2.0", - "android.hardware.soundtrigger@2.1", - "android.hardware.soundtrigger@2.2", - "libhidlmemory" - ], -} diff --git a/soundtrigger/2.2/vts/functional/VtsHalSoundtriggerV2_2TargetTest.cpp b/soundtrigger/2.2/vts/functional/VtsHalSoundtriggerV2_2TargetTest.cpp deleted file mode 100644 index ed5149fe7d..0000000000 --- a/soundtrigger/2.2/vts/functional/VtsHalSoundtriggerV2_2TargetTest.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "SoundTriggerHidlHalTest" -#include -#include - -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include -#include - -using ::android::sp; -using ::android::hardware::Return; -using ::android::hardware::soundtrigger::V2_0::ISoundTriggerHwCallback; -using ::android::hardware::soundtrigger::V2_0::SoundModelHandle; -using ::android::hardware::soundtrigger::V2_2::ISoundTriggerHw; - -// Test environment for SoundTrigger HIDL HAL. -class SoundTriggerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { - public: - // get the test environment singleton - static SoundTriggerHidlEnvironment* Instance() { - static SoundTriggerHidlEnvironment* instance = new SoundTriggerHidlEnvironment; - return instance; - } - - void registerTestServices() override { registerTestService(); } - - private: - SoundTriggerHidlEnvironment() {} -}; - -// The main test class for Sound Trigger HIDL HAL. -class SoundTriggerHidlTest : public ::testing::VtsHalHidlTargetTestBase { - public: - void SetUp() override { - mSoundTriggerHal = ::testing::VtsHalHidlTargetTestBase::getService( - SoundTriggerHidlEnvironment::Instance()->getServiceName()); - ASSERT_NE(nullptr, mSoundTriggerHal.get()); - } - - static void SetUpTestCase() { srand(1234); } - - void TearDown() override {} - - protected: - sp mSoundTriggerHal; -}; - -/** - * Test ISoundTriggerHw::getModelState() method - * - * Verifies that: - * - the implementation returns -EINVAL with invalid model handle - * - */ -TEST_F(SoundTriggerHidlTest, GetModelStateInvalidModel) { - int ret = android::OK; - ISoundTriggerHwCallback::RecognitionEvent event; - SoundModelHandle handle = 0; - Return hidlReturn = - mSoundTriggerHal->getModelState(handle, [&](int32_t retval, auto res) { - ret = retval; - event = res; - }); - - EXPECT_TRUE(hidlReturn.isOk()); - EXPECT_EQ(-ENOSYS, ret); -} - -int main(int argc, char** argv) { - ::testing::AddGlobalTestEnvironment(SoundTriggerHidlEnvironment::Instance()); - ::testing::InitGoogleTest(&argc, argv); - SoundTriggerHidlEnvironment::Instance()->init(&argc, argv); - int status = RUN_ALL_TESTS(); - ALOGI("Test result = %d", status); - return status; -} From 44b029b181b554931367c670f8bd026ceacc0536 Mon Sep 17 00:00:00 2001 From: Miao Wang Date: Thu, 20 Sep 2018 11:35:42 -0700 Subject: [PATCH 129/718] Add HAL entry to allow querying device impl version. Bug: 111425781 Bug: 112661050 Test: mm Test: NeuralNetworksTest_static Change-Id: I32527fa09e45459bc9759f5b679646073cf96785 --- neuralnetworks/1.2/IDevice.hal | 30 +++++++++++++++++++ .../1.2/vts/functional/BasicTests.cpp | 8 +++++ 2 files changed, 38 insertions(+) diff --git a/neuralnetworks/1.2/IDevice.hal b/neuralnetworks/1.2/IDevice.hal index 9cc23a26f5..aff4cf30f4 100644 --- a/neuralnetworks/1.2/IDevice.hal +++ b/neuralnetworks/1.2/IDevice.hal @@ -25,6 +25,36 @@ import @1.1::IDevice; * This interface represents a device driver. */ interface IDevice extends @1.1::IDevice { + /** + * Get the version string of the driver implementation. + * + * The version string must be a unique token among the set of version strings of + * drivers of a specific device. The token identifies the device driver's + * implementation. The token must not be confused with the feature level which is solely + * defined by the interface version. This API is opaque to the Android framework, but the + * Android framework may use the information for debugging or to pass on to NNAPI applications. + * + * Application developers sometimes have specific requirements to ensure good user experiences, + * and they need more information to make intelligent decisions when the Android framework cannot. + * For example, combined with the device name and other information, the token can help + * NNAPI applications filter devices based on their needs: + * - An application demands a certain level of performance, but a specific version of + * the driver cannot meet that requirement because of a performance regression. + * The application can blacklist the driver based on the version provided. + * - An application has a minimum precision requirement, but certain versions of + * the driver cannot meet that requirement because of bugs or certain optimizations. + * The application can filter out versions of these drivers. + * + * @return status Error status returned from querying the version string. Must be: + * - NONE if the query was successful + * - DEVICE_UNAVAILABLE if driver is offline or busy + * - GENERAL_FAILURE if the query resulted in an + * unspecified error + * @return version The version string of the device implementation. + * Must have nonzero length + */ + getVersionString() generates (ErrorStatus status, string version); + /** * Gets the supported operations in a model. * diff --git a/neuralnetworks/1.2/vts/functional/BasicTests.cpp b/neuralnetworks/1.2/vts/functional/BasicTests.cpp index d2dea1dc75..eb3ebd326b 100644 --- a/neuralnetworks/1.2/vts/functional/BasicTests.cpp +++ b/neuralnetworks/1.2/vts/functional/BasicTests.cpp @@ -37,6 +37,14 @@ TEST_F(NeuralnetworksHidlTest, StatusTest) { EXPECT_EQ(DeviceStatus::AVAILABLE, static_cast(status)); } +// device version test +TEST_F(NeuralnetworksHidlTest, GetDeviceVersionStringTest) { + Return ret = device->getVersionString([](ErrorStatus status, const hidl_string& version) { + EXPECT_EQ(ErrorStatus::NONE, status); + EXPECT_LT(0, version.size()); + }); + EXPECT_TRUE(ret.isOk()); +} } // namespace functional } // namespace vts } // namespace V1_2 From 3d76cf0d8e6abe52e459bb7bc741e58b34b9790d Mon Sep 17 00:00:00 2001 From: Hridya Valsaraju Date: Thu, 27 Sep 2018 10:21:07 -0700 Subject: [PATCH 130/718] Add command to check whether off-mode-charging is enabled. Bug: 78793464 Bug: 79480454 Test: fastboot getvar off-mode-charge Change-Id: I1bd4148ff3476acf110e4aa95a40084300608875 --- fastboot/1.0/IFastboot.hal | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/fastboot/1.0/IFastboot.hal b/fastboot/1.0/IFastboot.hal index c5979d9c78..a96755e499 100644 --- a/fastboot/1.0/IFastboot.hal +++ b/fastboot/1.0/IFastboot.hal @@ -50,4 +50,13 @@ interface IFastboot { */ getVariant() generates (string variant, Result result); + /** + * Returns whether off-mode-charging is enabled. If enabled, the device + * autoboots into a special mode when power is applied. + * + * @response state Returns whether off mode charging is enabled. + * @response result Returns the status SUCCESS if the operation is successful, + * FAILURE_UNKNOWN otherwise. + */ + getOffModeChargeState() generates (bool state, Result result); }; From 7ff9564b20b4a94f91e971694f27d3368d7bb6c5 Mon Sep 17 00:00:00 2001 From: Brian Stack Date: Mon, 1 Oct 2018 16:06:39 -0700 Subject: [PATCH 131/718] Require consistent getSensorsList Require that the values returned from getSensorsList do not change before the entire system reboots. The values must be stable even across Sensors HAL restarts. This allows for the framework to automatically re-establish connections if the Sensors HAL crashes. Bug: 111070257 Test: Compiles Change-Id: I0e4b7d6ef8f89f6780c6a14d67465fd3692cd482 --- sensors/2.0/ISensors.hal | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sensors/2.0/ISensors.hal b/sensors/2.0/ISensors.hal index 2a57251103..939bf73715 100644 --- a/sensors/2.0/ISensors.hal +++ b/sensors/2.0/ISensors.hal @@ -27,6 +27,13 @@ import @2.0::ISensorsCallback; interface ISensors { /** * Enumerate all available (static) sensors. + * + * The SensorInfo for each sensor returned by getSensorsList must be stable + * from the initial call to getSensorsList after a device boot until the + * entire system restarts. The SensorInfo for each sensor must not change + * between subsequent calls to getSensorsList, even across restarts of the + * HAL and its dependencies (for example, the sensor handle for a given + * sensor must not change across HAL restarts). */ getSensorsList() generates (vec list); From cfb29a4e7b4905522f7e5dc9a546c7449de2f91c Mon Sep 17 00:00:00 2001 From: Valerie Hau Date: Wed, 8 Aug 2018 09:39:53 -0700 Subject: [PATCH 132/718] Adding more Readback tests and refactoring Bug: 111563608 Test: ./VtsHalGraphicsComposerV2_2TargetTest --gtest_filter=GraphicsComposerReadbackTest.* Change-Id: I0e4a8212bf08c2890747f99d5754f92821c2e2f4 --- ...VtsHalGraphicsComposerV2_2ReadbackTest.cpp | 1305 +++++++++++++++-- 1 file changed, 1147 insertions(+), 158 deletions(-) diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp index 91318bc532..db4c914bbe 100644 --- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp +++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp @@ -44,6 +44,12 @@ using V2_1::Display; using V2_1::Layer; using V2_1::vts::TestCommandReader; +static const IComposerClient::Color BLACK = {0, 0, 0, 0xff}; +static const IComposerClient::Color RED = {0xff, 0, 0, 0xff}; +static const IComposerClient::Color TRANSLUCENT_RED = {0xff, 0, 0, 0x33}; +static const IComposerClient::Color GREEN = {0, 0xff, 0, 0xff}; +static const IComposerClient::Color BLUE = {0, 0, 0xff, 0xff}; + // Test environment for graphics.composer class GraphicsComposerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { public: @@ -61,106 +67,57 @@ class GraphicsComposerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEn class TestLayer { public: - TestLayer(std::shared_ptr const client, Display display) - : mLayer(client->createLayer(display, kBufferSlotCount)), - mComposerClient(client), - mDisplay(display) {} + TestLayer(const std::shared_ptr& client, Display display) + : mLayer(client->createLayer(display, kBufferSlotCount)), mComposerClient(client) {} - virtual ~TestLayer() { mComposerClient->destroyLayer(mDisplay, mLayer); } + // ComposerClient will take care of destroying layers, no need to explicitly + // call destroyLayers here + virtual ~TestLayer(){}; - virtual void write(std::shared_ptr writer) { + virtual void write(const std::shared_ptr& writer) { writer->selectLayer(mLayer); writer->setLayerDisplayFrame(mDisplayFrame); + writer->setLayerSourceCrop(mSourceCrop); writer->setLayerZOrder(mZOrder); + writer->setLayerSurfaceDamage(mSurfaceDamage); + writer->setLayerTransform(mTransform); + writer->setLayerPlaneAlpha(mAlpha); + writer->setLayerBlendMode(mBlendMode); } void setDisplayFrame(IComposerClient::Rect frame) { mDisplayFrame = frame; } + void setSourceCrop(IComposerClient::FRect crop) { mSourceCrop = crop; } void setZOrder(uint32_t z) { mZOrder = z; } + void setSurfaceDamage(std::vector surfaceDamage) { + mSurfaceDamage = surfaceDamage; + } + + void setTransform(Transform transform) { mTransform = transform; } + void setAlpha(float alpha) { mAlpha = alpha; } + void setBlendMode(IComposerClient::BlendMode blendMode) { mBlendMode = blendMode; } + + static constexpr uint32_t kBufferSlotCount = 64; + + IComposerClient::Rect mDisplayFrame = {0, 0, 0, 0}; + uint32_t mZOrder = 0; + std::vector mSurfaceDamage; + Transform mTransform = static_cast(0); + IComposerClient::FRect mSourceCrop = {0, 0, 0, 0}; + float mAlpha = 1.0; + IComposerClient::BlendMode mBlendMode = IComposerClient::BlendMode::NONE; + protected: Layer mLayer; - IComposerClient::Rect mDisplayFrame = {0, 0, 0, 0}; - uint32_t mZOrder = 0; private: std::shared_ptr const mComposerClient; - const Display mDisplay; - static constexpr uint32_t kBufferSlotCount = 64; -}; - -class TestColorLayer : public TestLayer { - public: - TestColorLayer(std::shared_ptr const client, Display display) - : TestLayer{client, display} {} - - void write(std::shared_ptr writer) override { - TestLayer::write(writer); - writer->setLayerCompositionType(IComposerClient::Composition::SOLID_COLOR); - writer->setLayerColor(mColor); - } - - void setColor(IComposerClient::Color color) { mColor = color; } - - private: - IComposerClient::Color mColor = {0xff, 0xff, 0xff, 0xff}; }; class GraphicsComposerReadbackTest : public ::testing::VtsHalHidlTargetTestBase { - protected: - using PowerMode = V2_1::IComposerClient::PowerMode; - void SetUp() override { - ASSERT_NO_FATAL_FAILURE( - mComposer = std::make_unique( - GraphicsComposerHidlEnvironment::Instance()->getServiceName())); - ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient()); - mComposerCallback = new V2_1::vts::GraphicsComposerCallback; - mComposerClient->registerCallback(mComposerCallback); - - // assume the first display is primary and is never removed - mPrimaryDisplay = waitForFirstDisplay(); - Config activeConfig = mComposerClient->getActiveConfig(mPrimaryDisplay); - mDisplayWidth = mComposerClient->getDisplayAttribute(mPrimaryDisplay, activeConfig, - IComposerClient::Attribute::WIDTH); - mDisplayHeight = mComposerClient->getDisplayAttribute(mPrimaryDisplay, activeConfig, - IComposerClient::Attribute::HEIGHT); - - // explicitly disable vsync - mComposerClient->setVsyncEnabled(mPrimaryDisplay, false); - mComposerCallback->setVsyncAllowed(false); - - // set up command writer/reader and gralloc - mWriter = std::make_shared(1024); - mReader = std::make_unique(); - mGralloc = std::make_unique(); - - mComposerClient->getRaw()->getReadbackBufferAttributes( - mPrimaryDisplay, [&](const auto& tmpError, const auto&, const auto&) { - mHasReadbackBuffer = tmpError == Error::NONE; - }); - } - - ~GraphicsComposerReadbackTest() override { - if (mComposerCallback != nullptr) { - EXPECT_EQ(0, mComposerCallback->getInvalidHotplugCount()); - EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount()); - EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount()); - } - } - - void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); } - - void render(const std::vector>& layers) { - for (auto layer : layers) { - layer->write(mWriter); - } - execute(); - mWriter->validateDisplay(); - mWriter->presentDisplay(); - execute(); - } - - int32_t GetBytesPerPixel(PixelFormat format) { - switch (format) { + public: + static int32_t GetBytesPerPixel(PixelFormat pixelFormat) { + switch (pixelFormat) { case PixelFormat::RGBA_8888: return 4; case PixelFormat::RGB_888: @@ -170,9 +127,120 @@ class GraphicsComposerReadbackTest : public ::testing::VtsHalHidlTargetTestBase } } + static void fillBuffer(int32_t width, int32_t height, uint32_t stride, void* bufferData, + PixelFormat pixelFormat, + std::vector desiredPixelColors) { + ASSERT_TRUE(pixelFormat == PixelFormat::RGB_888 || pixelFormat == PixelFormat::RGBA_8888); + int32_t bytesPerPixel = GetBytesPerPixel(pixelFormat); + ASSERT_NE(-1, bytesPerPixel); + for (int row = 0; row < height; row++) { + for (int col = 0; col < width; col++) { + int pixel = row * width + col; + IComposerClient::Color srcColor = desiredPixelColors[pixel]; + + int offset = (row * stride + col) * bytesPerPixel; + uint8_t* pixelColor = (uint8_t*)bufferData + offset; + pixelColor[0] = srcColor.r; + pixelColor[1] = srcColor.g; + pixelColor[2] = srcColor.b; + + if (bytesPerPixel == 4) { + pixelColor[3] = srcColor.a; + } + } + } + } + + protected: + using PowerMode = V2_1::IComposerClient::PowerMode; + void SetUp() override { + VtsHalHidlTargetTestBase::SetUp(); + ASSERT_NO_FATAL_FAILURE( + mComposer = std::make_unique( + GraphicsComposerHidlEnvironment::Instance()->getServiceName())); + ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient()); + mComposerCallback = new V2_1::vts::GraphicsComposerCallback; + mComposerClient->registerCallback(mComposerCallback); + + // assume the first display is primary and is never removed + mPrimaryDisplay = waitForFirstDisplay(); + Config activeConfig; + ASSERT_NO_FATAL_FAILURE(activeConfig = mComposerClient->getActiveConfig(mPrimaryDisplay)); + ASSERT_NO_FATAL_FAILURE( + mDisplayWidth = mComposerClient->getDisplayAttribute( + mPrimaryDisplay, activeConfig, IComposerClient::Attribute::WIDTH)); + ASSERT_NO_FATAL_FAILURE( + mDisplayHeight = mComposerClient->getDisplayAttribute( + mPrimaryDisplay, activeConfig, IComposerClient::Attribute::HEIGHT)); + + // explicitly disable vsync + ASSERT_NO_FATAL_FAILURE(mComposerClient->setVsyncEnabled(mPrimaryDisplay, false)); + mComposerCallback->setVsyncAllowed(false); + + // set up command writer/reader and gralloc + mWriter = std::make_shared(1024); + mReader = std::make_unique(); + mGralloc = std::make_shared(); + + mComposerClient->getRaw()->getReadbackBufferAttributes( + mPrimaryDisplay, + [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) { + mHasReadbackBuffer = readbackSupported(tmpPixelFormat, tmpDataspace, tmpError); + mPixelFormat = tmpPixelFormat; + mDataspace = tmpDataspace; + }); + ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::ON)); + } + + void TearDown() override { + mWriter->validateDisplay(); + mWriter->presentDisplay(); + execute(); + ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::OFF)); + EXPECT_EQ(0, mReader->mErrors.size()); + EXPECT_EQ(0, mReader->mCompositionChanges.size()); + if (mComposerCallback != nullptr) { + EXPECT_EQ(0, mComposerCallback->getInvalidHotplugCount()); + EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount()); + EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount()); + } + VtsHalHidlTargetTestBase::TearDown(); + } + + void execute() { + ASSERT_NO_FATAL_FAILURE(mComposerClient->execute(mReader.get(), mWriter.get())); + } + + void writeLayers(const std::vector>& layers) { + for (auto layer : layers) { + layer->write(mWriter); + } + execute(); + } + + void clearColors(std::vector& expectedColors, int32_t width, + int32_t height) { + for (int row = 0; row < height; row++) { + for (int col = 0; col < width; col++) { + int pixel = row * mDisplayWidth + col; + expectedColors[pixel] = BLACK; + } + } + } + + void fillColorsArea(std::vector& expectedColors, int32_t stride, + IComposerClient::Rect area, IComposerClient::Color color) { + for (int row = area.top; row < area.bottom; row++) { + for (int col = area.left; col < area.right; col++) { + int pixel = row * stride + col; + expectedColors[pixel] = color; + } + } + } + bool readbackSupported(const PixelFormat& pixelFormat, const Dataspace& dataspace, const Error error) { - if (error == Error::UNSUPPORTED) { + if (error != Error::NONE) { return false; } // TODO: add support for RGBA_1010102 @@ -185,33 +253,6 @@ class GraphicsComposerReadbackTest : public ::testing::VtsHalHidlTargetTestBase return true; } - void getReadbackBufferAttributes(Display display, PixelFormat* outPixelFormat, - Dataspace* outDataspace) { - mComposerClient->getRaw()->getReadbackBufferAttributes( - display, [&](const auto&, const auto& tmpOutPixelFormat, const auto& tmpOutDataspace) { - *outPixelFormat = tmpOutPixelFormat; - *outDataspace = tmpOutDataspace; - }); - } - - void checkReadbackBuffer(IMapper::BufferDescriptorInfo info, uint32_t stride, void* bufferData, - std::vector expectedColors) { - int32_t bytesPerPixel = GetBytesPerPixel(info.format); - ASSERT_NE(-1, bytesPerPixel) - << "unexpected pixel format " << static_cast(info.format) - << "(expected RGBA_8888 or RGB_888)"; - for (int row = 0; row < mDisplayHeight; row++) { - for (int col = 0; col < mDisplayWidth; col++) { - int pixel = row * mDisplayWidth + col; - int offset = (row * stride + col) * bytesPerPixel; - uint8_t* pixelColor = (uint8_t*)bufferData + offset; - - EXPECT_EQ(expectedColors[pixel].r, pixelColor[0]); - EXPECT_EQ(expectedColors[pixel].g, pixelColor[1]); - EXPECT_EQ(expectedColors[pixel].b, pixelColor[2]); - } - } - } std::unique_ptr mComposer; std::shared_ptr mComposerClient; @@ -223,9 +264,13 @@ class GraphicsComposerReadbackTest : public ::testing::VtsHalHidlTargetTestBase int32_t mDisplayHeight; std::shared_ptr mWriter; std::unique_ptr mReader; - std::unique_ptr mGralloc; + std::shared_ptr mGralloc; bool mHasReadbackBuffer; + PixelFormat mPixelFormat; + Dataspace mDataspace; + + static constexpr uint32_t kClientTargetSlotCount = 64; private: Display waitForFirstDisplay() { @@ -239,6 +284,178 @@ class GraphicsComposerReadbackTest : public ::testing::VtsHalHidlTargetTestBase } } }; +class ReadbackBuffer { + public: + ReadbackBuffer(Display display, const std::shared_ptr& client, + const std::shared_ptr& gralloc, uint32_t width, uint32_t height, + PixelFormat pixelFormat, Dataspace dataspace) { + mDisplay = display; + + mComposerClient = client; + mGralloc = gralloc; + + mPixelFormat = pixelFormat; + mDataspace = dataspace; + + mInfo.width = width; + mInfo.height = height; + mInfo.layerCount = 1; + mInfo.format = mPixelFormat; + mInfo.usage = static_cast(BufferUsage::CPU_READ_OFTEN | BufferUsage::GPU_TEXTURE); + + mAccessRegion.top = 0; + mAccessRegion.left = 0; + mAccessRegion.width = width; + mAccessRegion.height = height; + }; + + ~ReadbackBuffer() { + if (mBufferHandle != nullptr) { + mGralloc->freeBuffer(mBufferHandle); + } + } + + void setReadbackBuffer() { + if (mBufferHandle != nullptr) { + mGralloc->freeBuffer(mBufferHandle); + mBufferHandle = nullptr; + } + mBufferHandle = mGralloc->allocate(mInfo, /*import*/ true, &mStride); + ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle, mInfo, mStride)); + ASSERT_NO_FATAL_FAILURE(mComposerClient->setReadbackBuffer(mDisplay, mBufferHandle, -1)); + } + + void checkReadbackBuffer(std::vector expectedColors) { + // lock buffer for reading + int32_t fenceHandle; + ASSERT_NO_FATAL_FAILURE(mComposerClient->getReadbackBufferFence(mDisplay, &fenceHandle)); + + void* bufData = mGralloc->lock(mBufferHandle, mInfo.usage, mAccessRegion, fenceHandle); + ASSERT_TRUE(mPixelFormat == PixelFormat::RGB_888 || mPixelFormat == PixelFormat::RGBA_8888); + int32_t bytesPerPixel = GraphicsComposerReadbackTest::GetBytesPerPixel(mPixelFormat); + ASSERT_NE(-1, bytesPerPixel); + for (int row = 0; row < mInfo.height; row++) { + for (int col = 0; col < mInfo.width; col++) { + int pixel = row * mInfo.width + col; + int offset = (row * mStride + col) * bytesPerPixel; + uint8_t* pixelColor = (uint8_t*)bufData + offset; + + ASSERT_EQ(expectedColors[pixel].r, pixelColor[0]); + ASSERT_EQ(expectedColors[pixel].g, pixelColor[1]); + ASSERT_EQ(expectedColors[pixel].b, pixelColor[2]); + } + } + int32_t unlockFence = mGralloc->unlock(mBufferHandle); + if (unlockFence != -1) { + sync_wait(unlockFence, -1); + close(unlockFence); + } + } + + protected: + IMapper::BufferDescriptorInfo mInfo; + IMapper::Rect mAccessRegion; + uint32_t mStride; + const native_handle_t* mBufferHandle = nullptr; + PixelFormat mPixelFormat; + Dataspace mDataspace; + Display mDisplay; + std::shared_ptr mGralloc; + std::shared_ptr mComposerClient; +}; + +class TestColorLayer : public TestLayer { + public: + TestColorLayer(const std::shared_ptr& client, Display display) + : TestLayer{client, display} {} + + void write(const std::shared_ptr& writer) override { + TestLayer::write(writer); + writer->setLayerCompositionType(IComposerClient::Composition::SOLID_COLOR); + writer->setLayerColor(mColor); + } + + void setColor(IComposerClient::Color color) { mColor = color; } + + private: + IComposerClient::Color mColor = {0xff, 0xff, 0xff, 0xff}; +}; + +class TestBufferLayer : public TestLayer { + public: + TestBufferLayer(const std::shared_ptr& client, + const std::shared_ptr& gralloc, Display display, int32_t width, + int32_t height, PixelFormat format, + IComposerClient::Composition composition = IComposerClient::Composition::DEVICE) + : TestLayer{client, display} { + mGralloc = gralloc; + mComposition = composition; + mInfo.width = width; + mInfo.height = height; + mInfo.layerCount = 1; + mInfo.format = format; + mInfo.usage = + static_cast(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY); + + mAccessRegion.top = 0; + mAccessRegion.left = 0; + mAccessRegion.width = width; + mAccessRegion.height = height; + + setSourceCrop({0, 0, (float)width, (float)height}); + } + + ~TestBufferLayer() { + if (mBufferHandle != nullptr) { + mGralloc->freeBuffer(mBufferHandle); + } + } + + void write(const std::shared_ptr& writer) override { + TestLayer::write(writer); + writer->setLayerCompositionType(mComposition); + writer->setLayerDataspace(Dataspace::UNKNOWN); + writer->setLayerVisibleRegion(std::vector(1, mDisplayFrame)); + if (mBufferHandle != nullptr) writer->setLayerBuffer(0, mBufferHandle, mFillFence); + } + + void fillBuffer(std::vector expectedColors) { + void* bufData = mGralloc->lock(mBufferHandle, mInfo.usage, mAccessRegion, -1); + ASSERT_NO_FATAL_FAILURE(GraphicsComposerReadbackTest::fillBuffer( + mInfo.width, mInfo.height, mStride, bufData, mInfo.format, expectedColors)); + mFillFence = mGralloc->unlock(mBufferHandle); + if (mFillFence != -1) { + sync_wait(mFillFence, -1); + close(mFillFence); + } + } + void setBuffer(std::vector colors) { + if (mBufferHandle != nullptr) { + mGralloc->freeBuffer(mBufferHandle); + mBufferHandle = nullptr; + } + mBufferHandle = mGralloc->allocate(mInfo, /*import*/ true, &mStride); + ASSERT_NE(nullptr, mBufferHandle); + ASSERT_NO_FATAL_FAILURE(fillBuffer(colors)); + ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle, mInfo, mStride)); + } + + void setToClientComposition(const std::shared_ptr& writer) { + writer->selectLayer(mLayer); + writer->setLayerCompositionType(IComposerClient::Composition::CLIENT); + } + + IMapper::BufferDescriptorInfo mInfo; + IMapper::Rect mAccessRegion; + uint32_t mStride; + + protected: + IComposerClient::Composition mComposition; + std::shared_ptr mGralloc; + int32_t mFillFence; + const native_handle_t* mBufferHandle = nullptr; +}; TEST_F(GraphicsComposerReadbackTest, SingleSolidColorLayer) { if (!mHasReadbackBuffer) { @@ -246,13 +463,12 @@ TEST_F(GraphicsComposerReadbackTest, SingleSolidColorLayer) { return; } mWriter->selectDisplay(mPrimaryDisplay); - mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::ON); - mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB, RenderIntent::COLORIMETRIC); + ASSERT_NO_FATAL_FAILURE(mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB, + RenderIntent::COLORIMETRIC)); auto layer = std::make_shared(mComposerClient, mPrimaryDisplay); - IComposerClient::Color color({0, 0, 0xff, 0xff}); - IComposerClient::Rect coloredSquare({100, 100, 500, 500}); - layer->setColor(color); + IComposerClient::Rect coloredSquare({0, 0, mDisplayWidth, mDisplayHeight}); + layer->setColor(BLUE); layer->setDisplayFrame(coloredSquare); layer->setZOrder(10); @@ -260,58 +476,831 @@ TEST_F(GraphicsComposerReadbackTest, SingleSolidColorLayer) { // expected color for each pixel std::vector expectedColors(mDisplayWidth * mDisplayHeight); - for (int row = 0; row < mDisplayHeight; row++) { - for (int col = 0; col < mDisplayWidth; col++) { - int pixel = row * mDisplayWidth + col; - if (row >= coloredSquare.top && row < coloredSquare.bottom && - col >= coloredSquare.left && col < coloredSquare.right) { - expectedColors[pixel] = color; - } else { - expectedColors[pixel] = {0, 0, 0, 0xff}; + fillColorsArea(expectedColors, mDisplayWidth, coloredSquare, BLUE); + + ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth, + mDisplayHeight, mPixelFormat, mDataspace); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + + writeLayers(layers); + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->validateDisplay(); + execute(); + // if hwc cannot handle and asks for composition change, + // just succeed the test + if (mReader->mCompositionChanges.size() != 0) { + GTEST_SUCCEED(); + return; + } + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->presentDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); +} + +TEST_F(GraphicsComposerReadbackTest, SetLayerBuffer) { + if (!mHasReadbackBuffer) { + GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; + return; + } + + mWriter->selectDisplay(mPrimaryDisplay); + + ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth, + mDisplayHeight, mPixelFormat, mDataspace); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + std::vector expectedColors(mDisplayWidth * mDisplayHeight); + fillColorsArea(expectedColors, mDisplayWidth, {0, 0, mDisplayWidth, mDisplayHeight / 4}, RED); + fillColorsArea(expectedColors, mDisplayWidth, + {0, mDisplayHeight / 4, mDisplayWidth, mDisplayHeight / 2}, GREEN); + fillColorsArea(expectedColors, mDisplayWidth, + {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight}, BLUE); + + auto layer = + std::make_shared(mComposerClient, mGralloc, mPrimaryDisplay, mDisplayWidth, + mDisplayHeight, PixelFormat::RGBA_8888); + layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight}); + layer->setZOrder(10); + ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors)); + + std::vector> layers = {layer}; + + writeLayers(layers); + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->validateDisplay(); + execute(); + + if (mReader->mCompositionChanges.size() != 0) { + GTEST_SUCCEED(); + return; + } + ASSERT_EQ(0, mReader->mErrors.size()); + + mWriter->presentDisplay(); + execute(); + + ASSERT_EQ(0, mReader->mErrors.size()); + + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); +} + +TEST_F(GraphicsComposerReadbackTest, SetLayerBufferNoEffect) { + if (!mHasReadbackBuffer) { + GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; + return; + } + + mWriter->selectDisplay(mPrimaryDisplay); + ASSERT_NO_FATAL_FAILURE(mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB, + RenderIntent::COLORIMETRIC)); + + auto layer = std::make_shared(mComposerClient, mPrimaryDisplay); + IComposerClient::Rect coloredSquare({0, 0, mDisplayWidth, mDisplayHeight}); + layer->setColor(BLUE); + layer->setDisplayFrame(coloredSquare); + layer->setZOrder(10); + layer->write(mWriter); + + // This following buffer call should have no effect + IMapper::BufferDescriptorInfo bufferInfo{}; + bufferInfo.width = mDisplayWidth; + bufferInfo.height = mDisplayHeight; + bufferInfo.layerCount = 1; + bufferInfo.format = PixelFormat::RGBA_8888; + bufferInfo.usage = + static_cast(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN); + const native_handle_t* bufferHandle = mGralloc->allocate(bufferInfo); + mWriter->setLayerBuffer(0, bufferHandle, -1); + + // expected color for each pixel + std::vector expectedColors(mDisplayWidth * mDisplayHeight); + fillColorsArea(expectedColors, mDisplayWidth, coloredSquare, BLUE); + + ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth, + mDisplayHeight, mPixelFormat, mDataspace); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + + mWriter->validateDisplay(); + execute(); + + if (mReader->mCompositionChanges.size() != 0) { + GTEST_SUCCEED(); + return; + } + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->presentDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); +} + +TEST_F(GraphicsComposerReadbackTest, ClientComposition) { + if (!mHasReadbackBuffer) { + GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; + return; + } + + mWriter->selectDisplay(mPrimaryDisplay); + + std::vector expectedColors(mDisplayWidth * mDisplayHeight); + fillColorsArea(expectedColors, mDisplayWidth, {0, 0, mDisplayWidth, mDisplayHeight / 4}, RED); + fillColorsArea(expectedColors, mDisplayWidth, + {0, mDisplayHeight / 4, mDisplayWidth, mDisplayHeight / 2}, GREEN); + fillColorsArea(expectedColors, mDisplayWidth, + {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight}, BLUE); + + auto layer = + std::make_shared(mComposerClient, mGralloc, mPrimaryDisplay, mDisplayWidth, + mDisplayHeight, PixelFormat::RGBA_FP16); + layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight}); + layer->setZOrder(10); + + std::vector> layers = {layer}; + + ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth, + mDisplayHeight, mPixelFormat, mDataspace); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + writeLayers(layers); + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->validateDisplay(); + execute(); + + if (mReader->mCompositionChanges.size() != 0) { + ASSERT_EQ(1, mReader->mCompositionChanges.size()); + ASSERT_EQ(1, mReader->mCompositionChanges[0].second); + + ASSERT_NO_FATAL_FAILURE( + mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kClientTargetSlotCount)); + + // create client target buffer + uint32_t clientStride; + IMapper::BufferDescriptorInfo clientInfo; + clientInfo.width = layer->mInfo.width; + clientInfo.height = layer->mInfo.height; + clientInfo.layerCount = layer->mInfo.layerCount; + clientInfo.format = PixelFormat::RGBA_8888; + clientInfo.usage = + static_cast(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_CLIENT_TARGET); + const native_handle_t* clientBufferHandle = + mGralloc->allocate(clientInfo, /*import*/ true, &clientStride); + ASSERT_NE(nullptr, clientBufferHandle); + + void* clientBufData = + mGralloc->lock(clientBufferHandle, clientInfo.usage, layer->mAccessRegion, -1); + + ASSERT_NO_FATAL_FAILURE(fillBuffer(clientInfo.width, clientInfo.height, clientStride, + clientBufData, clientInfo.format, expectedColors)); + int clientFence = mGralloc->unlock(clientBufferHandle); + if (clientFence != -1) { + sync_wait(clientFence, -1); + close(clientFence); + } + + IComposerClient::Rect damage{0, 0, mDisplayWidth, mDisplayHeight}; + mWriter->setClientTarget(0, clientBufferHandle, clientFence, Dataspace::UNKNOWN, + std::vector(1, damage)); + + layer->setToClientComposition(mWriter); + mWriter->validateDisplay(); + execute(); + ASSERT_EQ(0, mReader->mCompositionChanges.size()); + } + ASSERT_EQ(0, mReader->mErrors.size()); + + mWriter->presentDisplay(); + execute(); + + ASSERT_EQ(0, mReader->mErrors.size()); + + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); +} + +TEST_F(GraphicsComposerReadbackTest, DeviceAndClientComposition) { + if (!mHasReadbackBuffer) { + GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; + return; + } + + mWriter->selectDisplay(mPrimaryDisplay); + ASSERT_NO_FATAL_FAILURE( + mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kClientTargetSlotCount)); + + std::vector expectedColors(mDisplayWidth * mDisplayHeight); + fillColorsArea(expectedColors, mDisplayWidth, {0, 0, mDisplayWidth, mDisplayHeight / 2}, GREEN); + fillColorsArea(expectedColors, mDisplayWidth, + {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight}, RED); + + ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth, + mDisplayHeight, mPixelFormat, mDataspace); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + + auto deviceLayer = + std::make_shared(mComposerClient, mGralloc, mPrimaryDisplay, mDisplayWidth, + mDisplayHeight / 2, PixelFormat::RGBA_8888); + std::vector deviceColors(deviceLayer->mInfo.width * + deviceLayer->mInfo.height); + fillColorsArea(deviceColors, deviceLayer->mInfo.width, + {0, 0, static_cast(deviceLayer->mInfo.width), + static_cast(deviceLayer->mInfo.height)}, + GREEN); + deviceLayer->setDisplayFrame({0, 0, static_cast(deviceLayer->mInfo.width), + static_cast(deviceLayer->mInfo.height)}); + deviceLayer->setZOrder(10); + ASSERT_NO_FATAL_FAILURE(deviceLayer->setBuffer(deviceColors)); + deviceLayer->write(mWriter); + + auto clientLayer = std::make_shared( + mComposerClient, mGralloc, mPrimaryDisplay, mDisplayWidth, mDisplayHeight / 2, + PixelFormat::RGBA_8888, IComposerClient::Composition::CLIENT); + IComposerClient::Rect clientFrame = {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight}; + clientLayer->setDisplayFrame(clientFrame); + clientLayer->setZOrder(0); + clientLayer->write(mWriter); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + + IMapper::BufferDescriptorInfo clientInfo; + clientInfo.width = mDisplayWidth; + clientInfo.height = mDisplayHeight; + clientInfo.layerCount = 1; + clientInfo.format = PixelFormat::RGBA_8888; + clientInfo.usage = + static_cast(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_CLIENT_TARGET); + + uint32_t clientStride; + const native_handle_t* clientBufferHandle = + mGralloc->allocate(clientInfo, /*import*/ true, &clientStride); + ASSERT_NE(nullptr, clientBufferHandle); + + IMapper::Rect clientAccessRegion; + clientAccessRegion.left = 0; + clientAccessRegion.top = 0; + clientAccessRegion.width = mDisplayWidth; + clientAccessRegion.height = mDisplayHeight; + void* clientData = mGralloc->lock(clientBufferHandle, clientInfo.usage, clientAccessRegion, -1); + std::vector clientColors(clientInfo.width * clientInfo.height); + fillColorsArea(clientColors, clientInfo.width, clientFrame, RED); + ASSERT_NO_FATAL_FAILURE(fillBuffer(clientInfo.width, clientInfo.height, clientStride, + clientData, clientInfo.format, clientColors)); + int clientFence = mGralloc->unlock(clientBufferHandle); + if (clientFence != -1) { + sync_wait(clientFence, -1); + close(clientFence); + } + + mWriter->setClientTarget(0, clientBufferHandle, clientFence, Dataspace::UNKNOWN, + std::vector(1, clientFrame)); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->validateDisplay(); + execute(); + if (mReader->mCompositionChanges.size() != 0) { + GTEST_SUCCEED(); + return; + } + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->presentDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); +} + +TEST_F(GraphicsComposerReadbackTest, SetLayerDamage) { + if (!mHasReadbackBuffer) { + GTEST_SUCCEED() << "Readback not supported or unsupported pixelformat/dataspace"; + return; + } + + mWriter->selectDisplay(mPrimaryDisplay); + + IComposerClient::Rect redRect = {0, 0, mDisplayWidth / 4, mDisplayHeight / 4}; + + std::vector expectedColors(mDisplayWidth * mDisplayHeight); + fillColorsArea(expectedColors, mDisplayWidth, redRect, RED); + + auto layer = + std::make_shared(mComposerClient, mGralloc, mPrimaryDisplay, mDisplayWidth, + mDisplayHeight, PixelFormat::RGBA_8888); + layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight}); + layer->setZOrder(10); + ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors)); + + std::vector> layers = {layer}; + + ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth, + mDisplayHeight, mPixelFormat, mDataspace); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + + writeLayers(layers); + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->validateDisplay(); + execute(); + if (mReader->mCompositionChanges.size() != 0) { + GTEST_SUCCEED(); + return; + } + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->presentDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); + + // update surface damage and recheck + redRect = {mDisplayWidth / 4, mDisplayHeight / 4, mDisplayWidth / 2, mDisplayHeight / 2}; + clearColors(expectedColors, mDisplayWidth, mDisplayHeight); + fillColorsArea(expectedColors, mDisplayWidth, redRect, RED); + + ASSERT_NO_FATAL_FAILURE(layer->fillBuffer(expectedColors)); + layer->setSurfaceDamage( + std::vector(1, {0, 0, mDisplayWidth / 2, mDisplayWidth / 2})); + + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + + writeLayers(layers); + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->validateDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + ASSERT_EQ(0, mReader->mCompositionChanges.size()); + mWriter->presentDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); +} + +TEST_F(GraphicsComposerReadbackTest, SetLayerPlaneAlpha) { + if (!mHasReadbackBuffer) { + GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; + return; + } + + mWriter->selectDisplay(mPrimaryDisplay); + ASSERT_NO_FATAL_FAILURE(mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB, + RenderIntent::COLORIMETRIC)); + + auto layer = std::make_shared(mComposerClient, mPrimaryDisplay); + layer->setColor(RED); + layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight}); + layer->setZOrder(10); + layer->setAlpha(0); + layer->setBlendMode(IComposerClient::BlendMode::PREMULTIPLIED); + + std::vector> layers = {layer}; + + ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth, + mDisplayHeight, mPixelFormat, mDataspace); + + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + + writeLayers(layers); + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->validateDisplay(); + execute(); + if (mReader->mCompositionChanges.size() != 0) { + GTEST_SUCCEED(); + return; + } + ASSERT_EQ(0, mReader->mErrors.size()); + + mWriter->presentDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + + std::vector expectedColors(mDisplayWidth * mDisplayHeight); + + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); +} + +TEST_F(GraphicsComposerReadbackTest, SetLayerSourceCrop) { + if (!mHasReadbackBuffer) { + GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; + return; + } + + mWriter->selectDisplay(mPrimaryDisplay); + + std::vector expectedColors(mDisplayWidth * mDisplayHeight); + fillColorsArea(expectedColors, mDisplayWidth, {0, 0, mDisplayWidth, mDisplayHeight / 4}, RED); + fillColorsArea(expectedColors, mDisplayWidth, + {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight}, BLUE); + + auto layer = + std::make_shared(mComposerClient, mGralloc, mPrimaryDisplay, mDisplayWidth, + mDisplayHeight, PixelFormat::RGBA_8888); + layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight}); + layer->setZOrder(10); + layer->setSourceCrop({0, static_cast(mDisplayHeight / 2), + static_cast(mDisplayWidth), static_cast(mDisplayHeight)}); + ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors)); + + std::vector> layers = {layer}; + + // update expected colors to match crop + fillColorsArea(expectedColors, mDisplayWidth, {0, 0, mDisplayWidth, mDisplayHeight}, BLUE); + ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth, + mDisplayHeight, mPixelFormat, mDataspace); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + writeLayers(layers); + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->validateDisplay(); + execute(); + if (mReader->mCompositionChanges.size() != 0) { + GTEST_SUCCEED(); + return; + } + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->presentDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); +} + +TEST_F(GraphicsComposerReadbackTest, SetLayerZOrder) { + if (!mHasReadbackBuffer) { + GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; + return; + } + + mWriter->selectDisplay(mPrimaryDisplay); + ASSERT_NO_FATAL_FAILURE(mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB, + RenderIntent::COLORIMETRIC)); + + IComposerClient::Rect redRect = {0, 0, mDisplayWidth, mDisplayHeight / 2}; + IComposerClient::Rect blueRect = {0, mDisplayHeight / 4, mDisplayWidth, mDisplayHeight}; + auto redLayer = std::make_shared(mComposerClient, mPrimaryDisplay); + redLayer->setColor(RED); + redLayer->setDisplayFrame(redRect); + + auto blueLayer = std::make_shared(mComposerClient, mPrimaryDisplay); + blueLayer->setColor(BLUE); + blueLayer->setDisplayFrame(blueRect); + blueLayer->setZOrder(5); + + std::vector> layers = {redLayer, blueLayer}; + std::vector expectedColors(mDisplayWidth * mDisplayHeight); + + // red in front of blue + redLayer->setZOrder(10); + + // fill blue first so that red will overwrite on overlap + fillColorsArea(expectedColors, mDisplayWidth, blueRect, BLUE); + fillColorsArea(expectedColors, mDisplayWidth, redRect, RED); + + ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth, + mDisplayHeight, mPixelFormat, mDataspace); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + + writeLayers(layers); + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->validateDisplay(); + execute(); + if (mReader->mCompositionChanges.size() != 0) { + GTEST_SUCCEED(); + return; + } + mWriter->presentDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); + + redLayer->setZOrder(1); + clearColors(expectedColors, mDisplayWidth, mDisplayHeight); + fillColorsArea(expectedColors, mDisplayWidth, redRect, RED); + fillColorsArea(expectedColors, mDisplayWidth, blueRect, BLUE); + + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + + writeLayers(layers); + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->validateDisplay(); + execute(); + ASSERT_EQ(0, mReader->mCompositionChanges.size()); + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->presentDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); +} + +class GraphicsComposerBlendModeReadbackTest : public GraphicsComposerReadbackTest, + public ::testing::WithParamInterface { + public: + void SetUp() override { + GraphicsComposerReadbackTest::SetUp(); + mBackgroundColor = BLACK; + mTopLayerColor = RED; + } + + void TearDown() override { GraphicsComposerReadbackTest::TearDown(); } + + void setBackgroundColor(IComposerClient::Color color) { mBackgroundColor = color; } + + void setTopLayerColor(IComposerClient::Color color) { mTopLayerColor = color; } + + void setUpLayers(IComposerClient::BlendMode blendMode) { + mLayers.clear(); + std::vector topLayerPixelColors(mDisplayWidth * mDisplayHeight); + fillColorsArea(topLayerPixelColors, mDisplayWidth, {0, 0, mDisplayWidth, mDisplayHeight}, + mTopLayerColor); + + auto backgroundLayer = std::make_shared(mComposerClient, mPrimaryDisplay); + backgroundLayer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight}); + backgroundLayer->setZOrder(0); + backgroundLayer->setColor(mBackgroundColor); + + auto layer = std::make_shared(mComposerClient, mGralloc, mPrimaryDisplay, + mDisplayWidth, mDisplayHeight, + PixelFormat::RGBA_8888); + layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight}); + layer->setZOrder(10); + ASSERT_NO_FATAL_FAILURE(layer->setBuffer(topLayerPixelColors)); + + layer->setBlendMode(blendMode); + layer->setAlpha(GetParam()); + + mLayers.push_back(backgroundLayer); + mLayers.push_back(layer); + } + + void setExpectedColors(std::vector& expectedColors) { + ASSERT_EQ(2, mLayers.size()); + clearColors(expectedColors, mDisplayWidth, mDisplayHeight); + + auto layer = mLayers[1]; + IComposerClient::BlendMode blendMode = layer->mBlendMode; + float alpha = mTopLayerColor.a / 255.0 * layer->mAlpha; + if (blendMode == IComposerClient::BlendMode::NONE) { + for (int i = 0; i < expectedColors.size(); i++) { + expectedColors[i].r = mTopLayerColor.r * layer->mAlpha; + expectedColors[i].g = mTopLayerColor.g * layer->mAlpha; + expectedColors[i].b = mTopLayerColor.b * layer->mAlpha; + expectedColors[i].a = alpha * 255.0; + } + } else if (blendMode == IComposerClient::BlendMode::PREMULTIPLIED) { + for (int i = 0; i < expectedColors.size(); i++) { + expectedColors[i].r = + mTopLayerColor.r * layer->mAlpha + mBackgroundColor.r * (1.0 - alpha); + expectedColors[i].g = + mTopLayerColor.g * layer->mAlpha + mBackgroundColor.g * (1.0 - alpha); + expectedColors[i].b = + mTopLayerColor.b * layer->mAlpha + mBackgroundColor.b * (1.0 - alpha); + expectedColors[i].a = alpha + mBackgroundColor.a * (1.0 - alpha); + } + } else if (blendMode == IComposerClient::BlendMode::COVERAGE) { + for (int i = 0; i < expectedColors.size(); i++) { + expectedColors[i].r = mTopLayerColor.r * alpha + mBackgroundColor.r * (1.0 - alpha); + expectedColors[i].g = mTopLayerColor.g * alpha + mBackgroundColor.g * (1.0 - alpha); + expectedColors[i].b = mTopLayerColor.b * alpha + mBackgroundColor.b * (1.0 - alpha); + expectedColors[i].a = mTopLayerColor.a * alpha + mBackgroundColor.a * (1.0 - alpha); } } } - PixelFormat pixelFormat; - Dataspace dataspace; + protected: + std::vector> mLayers; + IComposerClient::Color mBackgroundColor; + IComposerClient::Color mTopLayerColor; +}; - getReadbackBufferAttributes(mPrimaryDisplay, &pixelFormat, &dataspace); - - IMapper::BufferDescriptorInfo info; - info.width = mDisplayWidth; - info.height = mDisplayHeight; - info.layerCount = 1; - info.format = pixelFormat; - info.usage = static_cast(BufferUsage::CPU_READ_OFTEN | BufferUsage::GPU_TEXTURE); - - uint32_t stride; - const native_handle_t* buffer = mGralloc->allocate(info, /*import*/ true, &stride); - mComposerClient->setReadbackBuffer(mPrimaryDisplay, buffer, -1); - - render(layers); - - int32_t fenceHandle; - mComposerClient->getReadbackBufferFence(mPrimaryDisplay, &fenceHandle); - - // lock buffer - // Create Rect accessRegion to specify reading the entire buffer - IMapper::Rect accessRegion; - accessRegion.left = 0; - accessRegion.top = 0; - accessRegion.width = info.width; - accessRegion.height = info.height; - - void* bufData = mGralloc->lock(buffer, info.usage, accessRegion, fenceHandle); - checkReadbackBuffer(info, stride, bufData, expectedColors); - int unlockFence = mGralloc->unlock(buffer); - - if (unlockFence != -1) { - close(unlockFence); +TEST_P(GraphicsComposerBlendModeReadbackTest, None) { + if (!mHasReadbackBuffer) { + GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; + return; } + mWriter->selectDisplay(mPrimaryDisplay); + + std::vector expectedColors(mDisplayWidth * mDisplayHeight); + + setBackgroundColor(BLACK); + setTopLayerColor(TRANSLUCENT_RED); + setUpLayers(IComposerClient::BlendMode::NONE); + setExpectedColors(expectedColors); + + ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth, + mDisplayHeight, mPixelFormat, mDataspace); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + writeLayers(mLayers); + ASSERT_EQ(0, mReader->mErrors.size()); mWriter->validateDisplay(); + execute(); + if (mReader->mCompositionChanges.size() != 0) { + GTEST_SUCCEED(); + return; + } + ASSERT_EQ(0, mReader->mErrors.size()); mWriter->presentDisplay(); execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); +} + +// TODO: bug 116865056: Readback returns (245, 0, 0) for layer plane +// alpha of .2, expected 10.2 +TEST_P(GraphicsComposerBlendModeReadbackTest, DISABLED_Coverage) { + if (!mHasReadbackBuffer) { + GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; + return; + } + + mWriter->selectDisplay(mPrimaryDisplay); + + std::vector expectedColors(mDisplayWidth * mDisplayHeight); + + setBackgroundColor(BLACK); + setTopLayerColor(TRANSLUCENT_RED); + + setUpLayers(IComposerClient::BlendMode::COVERAGE); + setExpectedColors(expectedColors); + + ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth, + mDisplayHeight, mPixelFormat, mDataspace); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + writeLayers(mLayers); + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->validateDisplay(); + execute(); + if (mReader->mCompositionChanges.size() != 0) { + GTEST_SUCCEED(); + return; + } + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->presentDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); +} + +TEST_P(GraphicsComposerBlendModeReadbackTest, Premultiplied) { + if (!mHasReadbackBuffer) { + GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; + return; + } + + mWriter->selectDisplay(mPrimaryDisplay); + + std::vector expectedColors(mDisplayWidth * mDisplayHeight); + + setBackgroundColor(BLACK); + setTopLayerColor(TRANSLUCENT_RED); + setUpLayers(IComposerClient::BlendMode::PREMULTIPLIED); + setExpectedColors(expectedColors); + + ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth, + mDisplayHeight, mPixelFormat, mDataspace); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + writeLayers(mLayers); + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->validateDisplay(); + execute(); + if (mReader->mCompositionChanges.size() != 0) { + GTEST_SUCCEED(); + return; + } + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->presentDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); +} + +INSTANTIATE_TEST_CASE_P(BlendModeTest, GraphicsComposerBlendModeReadbackTest, + ::testing::Values(.2, 1.0)); + +class GraphicsComposerTransformReadbackTest : public GraphicsComposerReadbackTest { + protected: + void SetUp() override { + GraphicsComposerReadbackTest::SetUp(); + if (!mHasReadbackBuffer) { + GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; + return; + } + + mWriter->selectDisplay(mPrimaryDisplay); + ASSERT_NO_FATAL_FAILURE(mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB, + RenderIntent::COLORIMETRIC)); + + auto backgroundLayer = std::make_shared(mComposerClient, mPrimaryDisplay); + backgroundLayer->setColor({0, 0, 0, 0}); + backgroundLayer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight}); + backgroundLayer->setZOrder(0); + + mSideLength = mDisplayWidth < mDisplayHeight ? mDisplayWidth : mDisplayHeight; + IComposerClient::Rect redRect = {0, 0, mSideLength / 2, mSideLength / 2}; + IComposerClient::Rect blueRect = {mSideLength / 2, mSideLength / 2, mSideLength, + mSideLength}; + + mLayer = + std::make_shared(mComposerClient, mGralloc, mPrimaryDisplay, + mSideLength, mSideLength, PixelFormat::RGBA_8888); + mLayer->setDisplayFrame({0, 0, mSideLength, mSideLength}); + mLayer->setZOrder(10); + + std::vector baseColors(mSideLength * mSideLength); + fillColorsArea(baseColors, mSideLength, redRect, RED); + fillColorsArea(baseColors, mSideLength, blueRect, BLUE); + ASSERT_NO_FATAL_FAILURE(mLayer->setBuffer(baseColors)); + + mLayers = {backgroundLayer, mLayer}; + } + + protected: + std::shared_ptr mLayer; + std::vector baseColors; + std::vector> mLayers; + int mSideLength; +}; + +TEST_F(GraphicsComposerTransformReadbackTest, FLIP_H) { + ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth, + mDisplayHeight, mPixelFormat, mDataspace); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + mLayer->setTransform(Transform::FLIP_H); + std::vector expectedColors(mDisplayWidth * mDisplayHeight); + fillColorsArea(expectedColors, mDisplayWidth, + {mSideLength / 2, 0, mSideLength, mSideLength / 2}, RED); + fillColorsArea(expectedColors, mDisplayWidth, + {0, mSideLength / 2, mSideLength / 2, mSideLength}, BLUE); + + writeLayers(mLayers); + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->validateDisplay(); + execute(); + if (mReader->mCompositionChanges.size() != 0) { + GTEST_SUCCEED(); + return; + } + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->presentDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); +} + +TEST_F(GraphicsComposerTransformReadbackTest, FLIP_V) { + ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth, + mDisplayHeight, mPixelFormat, mDataspace); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + + mLayer->setTransform(Transform::FLIP_V); + + std::vector expectedColors(mDisplayWidth * mDisplayHeight); + fillColorsArea(expectedColors, mDisplayWidth, + {0, mSideLength / 2, mSideLength / 2, mSideLength}, RED); + fillColorsArea(expectedColors, mDisplayWidth, + {mSideLength / 2, 0, mSideLength, mSideLength / 2}, BLUE); + + writeLayers(mLayers); + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->validateDisplay(); + execute(); + if (mReader->mCompositionChanges.size() != 0) { + GTEST_SUCCEED(); + return; + } + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->presentDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); +} + +TEST_F(GraphicsComposerTransformReadbackTest, ROT_180) { + ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth, + mDisplayHeight, mPixelFormat, mDataspace); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + + mLayer->setTransform(Transform::ROT_180); + + std::vector expectedColors(mDisplayWidth * mDisplayHeight); + fillColorsArea(expectedColors, mDisplayWidth, + {mSideLength / 2, mSideLength / 2, mSideLength, mSideLength}, RED); + fillColorsArea(expectedColors, mDisplayWidth, {0, 0, mSideLength / 2, mSideLength / 2}, BLUE); + + writeLayers(mLayers); + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->validateDisplay(); + execute(); + if (mReader->mCompositionChanges.size() != 0) { + GTEST_SUCCEED(); + return; + } + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->presentDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); } } // anonymous namespace From 83f5631deb5169d7b6f897679956bc11d13e6e0b Mon Sep 17 00:00:00 2001 From: Hridya Valsaraju Date: Mon, 1 Oct 2018 15:47:24 -0700 Subject: [PATCH 133/718] Add a command to get the minimum battery voltage required for flashing Bug: 79480454 Test: fastboot getvar battery-soc-ok Change-Id: I6141993972a3084fe3620d81f707999e1264b997 --- fastboot/1.0/IFastboot.hal | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/fastboot/1.0/IFastboot.hal b/fastboot/1.0/IFastboot.hal index a96755e499..dce3ad796e 100644 --- a/fastboot/1.0/IFastboot.hal +++ b/fastboot/1.0/IFastboot.hal @@ -34,7 +34,7 @@ interface IFastboot { * Executes a fastboot OEM command. * * @param oemCmdArgs The oem command that is passed to the fastboot HAL. - * @response result Returns the status SUCCESS if the operation is successful, + * @return result Returns the status SUCCESS if the operation is successful, * INVALID_ARGUMENT for bad arguments, * FAILURE_UNKNOWN for an invalid/unsupported command. */ @@ -44,8 +44,8 @@ interface IFastboot { * Returns an OEM-defined string indicating the variant of the device, for * example, US and ROW. * - * @response variant Indicates the device variant. - * @response result Returns the status SUCCESS if the operation is successful, + * @return variant Indicates the device variant. + * @return result Returns the status SUCCESS if the operation is successful, * FAILURE_UNKNOWN otherwise. */ getVariant() generates (string variant, Result result); @@ -54,9 +54,19 @@ interface IFastboot { * Returns whether off-mode-charging is enabled. If enabled, the device * autoboots into a special mode when power is applied. * - * @response state Returns whether off mode charging is enabled. - * @response result Returns the status SUCCESS if the operation is successful, + * @return state Returns whether off mode charging is enabled. + * @return result Returns the status SUCCESS if the operation is successful, * FAILURE_UNKNOWN otherwise. */ getOffModeChargeState() generates (bool state, Result result); + + /** + * Returns the minimum battery voltage required for flashing in mV. + * + * @return batteryVoltage Minimum batterery voltage (in mV) required for + * flashing to be successful. + * @return result Returns the status SUCCESS if the operation is successful, + * FAILURE_UNKNOWN otherwise. + */ + getBatteryVoltageFlashingThreshold() generates (int32_t batteryVoltage, Result result); }; From ba9ec8795aec556343232a0b5113f15d4b02949b Mon Sep 17 00:00:00 2001 From: Kevin Chyn Date: Fri, 28 Sep 2018 16:37:45 -0700 Subject: [PATCH 134/718] Add IBiometricsFace#userActivity Fixes: 116821097 Test: builds Change-Id: I88363e186a41ce65665122606b357c7d31d8c18d --- biometrics/face/1.0/IBiometricsFace.hal | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/biometrics/face/1.0/IBiometricsFace.hal b/biometrics/face/1.0/IBiometricsFace.hal index 1c7bfb9be5..0ac788ed86 100644 --- a/biometrics/face/1.0/IBiometricsFace.hal +++ b/biometrics/face/1.0/IBiometricsFace.hal @@ -225,7 +225,10 @@ interface IBiometricsFace { * Authenticates the active user. * * An optional operationId can be specified as a token from the transaction - * being authorized. + * being authorized. The hardware may enter a standby state during + * authentication, where the device is idle to conserve power while + * authenticating, e.g. after 3 seconds without finding a face. See + * IBiometricsFace#userActivity() for more info. * * @param operationId A non-zero operation id associated with a crypto * object instance; or 0 if not being used. @@ -233,4 +236,17 @@ interface IBiometricsFace { */ @callflow(next={"cancel", "generateChallenge", "remove"}) authenticate(uint64_t operationId) generates (Status status); + + /** + * A hint to the HAL to continue looking for faces. + * + * This method should only be used when the HAL is in the authenticating + * or standby state. Using this method when the HAL is not in one of the + * mentioned states must return OPERATION_NOT_SUPPORTED. Calling this + * method while the HAL is already authenticating may extend the duration + * where it's looking for a face. + * + * @return status The status of this method call. + */ + userActivity() generates (Status status); }; From 6bdeaf55bf5cb7d313628d0ff092413c42b5782c Mon Sep 17 00:00:00 2001 From: Shuzhen Wang Date: Wed, 5 Sep 2018 09:40:00 -0700 Subject: [PATCH 135/718] VTS: Add test for device version 3.5 Also includes: - Add test for getPhysicalCameraCharacteristics. - Doc update for the new HIDL API. - Tighten boundary check for camera ID in CameraModule. Test: vts-tradefed run commandAndExit vts --skip-all-system-status-check --skip-preconditions --module VtsHalCameraProviderV2_4Target -l INFO Bug: 79523700 Bug: 115969176 Bug: 116512585 Change-Id: I051d1b0c91834781a1f8d893ed5ebfa579b03774 --- camera/common/1.0/default/CameraModule.cpp | 11 +- .../common/1.0/default/include/CameraModule.h | 1 + camera/device/3.5/ICameraDevice.hal | 20 +- camera/device/3.5/default/CameraDevice.cpp | 4 + camera/provider/2.4/vts/functional/Android.bp | 1 + .../VtsHalCameraProviderV2_4TargetTest.cpp | 182 ++++++++++++++---- 6 files changed, 176 insertions(+), 43 deletions(-) diff --git a/camera/common/1.0/default/CameraModule.cpp b/camera/common/1.0/default/CameraModule.cpp index eb840a74f4..392ebbc237 100644 --- a/camera/common/1.0/default/CameraModule.cpp +++ b/camera/common/1.0/default/CameraModule.cpp @@ -235,7 +235,7 @@ void CameraModule::appendAvailableKeys(CameraMetadata &chars, chars.update(keyTag, availableKeys); } -CameraModule::CameraModule(camera_module_t *module) { +CameraModule::CameraModule(camera_module_t *module) : mNumberOfCameras(0) { if (module == NULL) { ALOGE("%s: camera hardware module must not be null", __FUNCTION__); assert(0); @@ -264,7 +264,8 @@ int CameraModule::init() { res = mModule->init(); ATRACE_END(); } - mCameraInfoMap.setCapacity(getNumberOfCameras()); + mNumberOfCameras = getNumberOfCameras(); + mCameraInfoMap.setCapacity(mNumberOfCameras); return res; } @@ -322,7 +323,7 @@ int CameraModule::getCameraInfo(int cameraId, struct camera_info *info) { int CameraModule::getPhysicalCameraInfo(int physicalCameraId, camera_metadata_t **physicalInfo) { ATRACE_CALL(); Mutex::Autolock lock(mCameraInfoLock); - if (physicalCameraId < 0) { + if (physicalCameraId < mNumberOfCameras) { ALOGE("%s: Invalid physical camera ID %d", __FUNCTION__, physicalCameraId); return -EINVAL; } @@ -334,6 +335,10 @@ int CameraModule::getPhysicalCameraInfo(int physicalCameraId, camera_metadata_t __FUNCTION__); return -ENODEV; } + if (mModule->get_physical_camera_info == nullptr) { + ALOGE("%s: get_physical_camera is NULL for module version 2.5", __FUNCTION__); + return -EINVAL; + } ssize_t index = mPhysicalCameraInfoMap.indexOfKey(physicalCameraId); if (index == NAME_NOT_FOUND) { diff --git a/camera/common/1.0/default/include/CameraModule.h b/camera/common/1.0/default/include/CameraModule.h index ed853bf85f..aee9654dc7 100644 --- a/camera/common/1.0/default/include/CameraModule.h +++ b/camera/common/1.0/default/include/CameraModule.h @@ -75,6 +75,7 @@ private: int32_t keyTag, const Vector& appendKeys); status_t filterOpenErrorCode(status_t err); camera_module_t *mModule; + int mNumberOfCameras; KeyedVector mCameraInfoMap; KeyedVector mDeviceVersionMap; KeyedVector mPhysicalCameraInfoMap; diff --git a/camera/device/3.5/ICameraDevice.hal b/camera/device/3.5/ICameraDevice.hal index e7e8dd343f..a77380f75c 100644 --- a/camera/device/3.5/ICameraDevice.hal +++ b/camera/device/3.5/ICameraDevice.hal @@ -36,11 +36,24 @@ interface ICameraDevice extends @3.2::ICameraDevice { * this logical camera device. This information may not change between consecutive calls. * * Note that HAL must support this function for physical camera IDs that are - * not exposed via ICameraProvider::getCameraIdList(). + * not exposed via ICameraProvider::getCameraIdList(). Calling + * getCameraDeviceInterface_V3_x() on these camera IDs must return ILLEGAL_ARGUMENT. + * + * The characteristics of all cameras returned by + * ICameraProvider::getCameraIdList() must be queried via + * getCameraCharacteristics(). Calling getPhysicalCameraCharacteristics() on + * those cameras must return ILLEGAL_ARGUMENT. + * + * @param physicalCameraId The physical camera id parsed from the logical + * camera's ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS static metadata + * key. The framework assumes that this ID is just the part of fully + * qualified camera device name "device@.//". And + * the physical camera must be of the same version and type as the parent + * logical camera device. * * @return status Status code for the operation, one of: * OK: - * On a successful query of the camera device characteristics + * On a successful query of the physical camera device characteristics * INTERNAL_ERROR: * The camera device cannot be opened due to an internal * error. @@ -50,6 +63,9 @@ interface ICameraDevice extends @3.2::ICameraDevice { * instance must be acquired if the device is reconnected. All * subsequent calls on this interface must return * CAMERA_DISCONNECTED. + * ILLEGAL_ARGUMENT: + * If the physicalCameraId is not a valid physical camera Id outside + * of ICameraProvider::getCameraIdList(). * * @return cameraCharacteristics * The static metadata for this logical camera device's physical device, or an empty diff --git a/camera/device/3.5/default/CameraDevice.cpp b/camera/device/3.5/default/CameraDevice.cpp index c5d6c576d8..a6969af54a 100644 --- a/camera/device/3.5/default/CameraDevice.cpp +++ b/camera/device/3.5/default/CameraDevice.cpp @@ -79,6 +79,10 @@ Return CameraDevice::getPhysicalCameraCharacteristics(const hidl_string& p int ret = mModule->getPhysicalCameraInfo((int)id, &physicalInfo); if (ret == OK) { V3_2::implementation::convertToHidl(physicalInfo, &cameraCharacteristics); + } else if (ret == -EINVAL) { + ALOGE("%s: %s is not a valid physical camera Id outside of getCameraIdList()", + __FUNCTION__, physicalCameraId.c_str()); + status = Status::ILLEGAL_ARGUMENT; } else { ALOGE("%s: Failed to get physical camera %s info: %s (%d)!", __FUNCTION__, physicalCameraId.c_str(), strerror(-ret), ret); diff --git a/camera/provider/2.4/vts/functional/Android.bp b/camera/provider/2.4/vts/functional/Android.bp index ead4083ea1..eb8d43e5be 100644 --- a/camera/provider/2.4/vts/functional/Android.bp +++ b/camera/provider/2.4/vts/functional/Android.bp @@ -37,6 +37,7 @@ cc_test { "android.hardware.camera.device@3.2", "android.hardware.camera.device@3.3", "android.hardware.camera.device@3.4", + "android.hardware.camera.device@3.5", "android.hardware.camera.provider@2.4", "android.hardware.graphics.allocator@2.0", "android.hardware.graphics.common@1.0", diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp index fd9396c840..94d06e8611 100644 --- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp +++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -144,10 +145,12 @@ struct AvailableZSLInputOutput { namespace { // "device@/legacy/" const char *kDeviceNameRE = "device@([0-9]+\\.[0-9]+)/%s/(.+)"; + const int CAMERA_DEVICE_API_VERSION_3_5 = 0x305; const int CAMERA_DEVICE_API_VERSION_3_4 = 0x304; const int CAMERA_DEVICE_API_VERSION_3_3 = 0x303; const int CAMERA_DEVICE_API_VERSION_3_2 = 0x302; const int CAMERA_DEVICE_API_VERSION_1_0 = 0x100; + const char *kHAL3_5 = "3.5"; const char *kHAL3_4 = "3.4"; const char *kHAL3_3 = "3.3"; const char *kHAL3_2 = "3.2"; @@ -182,7 +185,9 @@ namespace { return -1; } - if (version.compare(kHAL3_4) == 0) { + if (version.compare(kHAL3_5) == 0) { + return CAMERA_DEVICE_API_VERSION_3_5; + } else if (version.compare(kHAL3_4) == 0) { return CAMERA_DEVICE_API_VERSION_3_4; } else if (version.compare(kHAL3_3) == 0) { return CAMERA_DEVICE_API_VERSION_3_3; @@ -670,12 +675,19 @@ public: HalStreamConfiguration *halStreamConfig /*out*/, bool *supportsPartialResults /*out*/, uint32_t *partialResultCount /*out*/); + + void verifyLogicalCameraMetadata(const std::string& cameraName, + const ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice>& device, + const CameraMetadata& chars, int deviceVersion, + const hidl_vec& deviceNames); + void verifyCameraCharacteristics(Status status, const CameraMetadata& chars); + static Status getAvailableOutputStreams(camera_metadata_t *staticMeta, std::vector &outputStreams, const AvailableStream *threshold = nullptr); static Status isConstrainedModeAvailable(camera_metadata_t *staticMeta); - static Status isLogicalMultiCamera(camera_metadata_t *staticMeta); - static Status getPhysicalCameraIds(camera_metadata_t *staticMeta, + static Status isLogicalMultiCamera(const camera_metadata_t *staticMeta); + static Status getPhysicalCameraIds(const camera_metadata_t *staticMeta, std::unordered_set *physicalIds/*out*/); static Status getSupportedKeys(camera_metadata_t *staticMeta, uint32_t tagId, std::unordered_set *requestIDs/*out*/); @@ -1266,6 +1278,7 @@ TEST_F(CameraHidlTest, getCameraDeviceInterface) { for (const auto& name : cameraDeviceNames) { int deviceVersion = getCameraDeviceVersion(name, mProviderType); switch (deviceVersion) { + 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: { @@ -1307,6 +1320,7 @@ TEST_F(CameraHidlTest, getResourceCost) { for (const auto& name : cameraDeviceNames) { int deviceVersion = getCameraDeviceVersion(name, mProviderType); switch (deviceVersion) { + 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: { @@ -2047,6 +2061,7 @@ TEST_F(CameraHidlTest, getCameraCharacteristics) { for (const auto& name : cameraDeviceNames) { int deviceVersion = getCameraDeviceVersion(name, mProviderType); switch (deviceVersion) { + 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: { @@ -2063,41 +2078,31 @@ TEST_F(CameraHidlTest, getCameraCharacteristics) { ASSERT_TRUE(ret.isOk()); ret = device3_x->getCameraCharacteristics([&](auto status, const auto& chars) { - ALOGI("getCameraCharacteristics returns status:%d", (int)status); - ASSERT_EQ(Status::OK, status); - const camera_metadata_t* metadata = (camera_metadata_t*)chars.data(); - size_t expectedSize = chars.size(); - int result = validate_camera_metadata_structure(metadata, &expectedSize); - ASSERT_TRUE((result == 0) || (result == CAMERA_METADATA_VALIDATION_SHIFTED)); - size_t entryCount = get_camera_metadata_entry_count(metadata); - // TODO: we can do better than 0 here. Need to check how many required - // characteristics keys we've defined. - ASSERT_GT(entryCount, 0u); - ALOGI("getCameraCharacteristics metadata entry count is %zu", entryCount); + verifyCameraCharacteristics(status, chars); - camera_metadata_ro_entry entry; - int retcode = find_camera_metadata_ro_entry(metadata, - ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL, &entry); - if ((0 == retcode) && (entry.count > 0)) { - uint8_t hardwareLevel = entry.data.u8[0]; - ASSERT_TRUE( - hardwareLevel == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED || - hardwareLevel == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL || - hardwareLevel == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_3 || - hardwareLevel == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL); - } else { - ADD_FAILURE() << "Get camera hardware level failed!"; - } - - entry.count = 0; - retcode = find_camera_metadata_ro_entry(metadata, - ANDROID_REQUEST_CHARACTERISTIC_KEYS_NEEDING_PERMISSION, &entry); - if ((0 == retcode) || (entry.count > 0)) { - ADD_FAILURE() << "ANDROID_REQUEST_CHARACTERISTIC_KEYS_NEEDING_PERMISSION " - << " per API contract should never be set by Hal!"; - } + verifyLogicalCameraMetadata(name, device3_x, chars, deviceVersion, + cameraDeviceNames); }); ASSERT_TRUE(ret.isOk()); + + //getPhysicalCameraCharacteristics will fail for publicly + //advertised camera IDs. + if (deviceVersion >= CAMERA_DEVICE_API_VERSION_3_5) { + 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); + + std::string version, cameraId; + ASSERT_TRUE(::matchDeviceName(name, mProviderType, &version, &cameraId)); + Return ret = device3_5->getPhysicalCameraCharacteristics(cameraId, + [&](auto status, const auto& chars) { + ASSERT_TRUE(Status::ILLEGAL_ARGUMENT == status); + ASSERT_EQ(0, chars.size()); + }); + ASSERT_TRUE(ret.isOk()); + } } break; case CAMERA_DEVICE_API_VERSION_1_0: { @@ -2134,6 +2139,7 @@ TEST_F(CameraHidlTest, setTorchMode) { for (const auto& name : cameraDeviceNames) { int deviceVersion = getCameraDeviceVersion(name, mProviderType); switch (deviceVersion) { + 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: { @@ -2259,6 +2265,7 @@ TEST_F(CameraHidlTest, dumpState) { for (const auto& name : cameraDeviceNames) { int deviceVersion = getCameraDeviceVersion(name, mProviderType); switch (deviceVersion) { + 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: { @@ -2323,6 +2330,7 @@ TEST_F(CameraHidlTest, openClose) { for (const auto& name : cameraDeviceNames) { int deviceVersion = getCameraDeviceVersion(name, mProviderType); switch (deviceVersion) { + 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: { @@ -2351,7 +2359,8 @@ TEST_F(CameraHidlTest, openClose) { sp sessionV3_3; sp sessionV3_4; castSession(session, deviceVersion, &sessionV3_3, &sessionV3_4); - if (deviceVersion == CAMERA_DEVICE_API_VERSION_3_4) { + if (deviceVersion == CAMERA_DEVICE_API_VERSION_3_4 || + deviceVersion == CAMERA_DEVICE_API_VERSION_3_5) { ASSERT_TRUE(sessionV3_4.get() != nullptr); } else if (deviceVersion == CAMERA_DEVICE_API_VERSION_3_3) { ASSERT_TRUE(sessionV3_3.get() != nullptr); @@ -2409,6 +2418,7 @@ TEST_F(CameraHidlTest, constructDefaultRequestSettings) { for (const auto& name : cameraDeviceNames) { int deviceVersion = getCameraDeviceVersion(name, mProviderType); switch (deviceVersion) { + 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: { @@ -4152,7 +4162,7 @@ Status CameraHidlTest::getAvailableOutputStreams(camera_metadata_t *staticMeta, } // Check if the camera device has logical multi-camera capability. -Status CameraHidlTest::isLogicalMultiCamera(camera_metadata_t *staticMeta) { +Status CameraHidlTest::isLogicalMultiCamera(const camera_metadata_t *staticMeta) { Status ret = Status::METHOD_NOT_SUPPORTED; if (nullptr == staticMeta) { return Status::ILLEGAL_ARGUMENT; @@ -4176,7 +4186,7 @@ Status CameraHidlTest::isLogicalMultiCamera(camera_metadata_t *staticMeta) { } // Generate a list of physical camera ids backing a logical multi-camera. -Status CameraHidlTest::getPhysicalCameraIds(camera_metadata_t *staticMeta, +Status CameraHidlTest::getPhysicalCameraIds(const camera_metadata_t *staticMeta, std::unordered_set *physicalIds) { if ((nullptr == staticMeta) || (nullptr == physicalIds)) { return Status::ILLEGAL_ARGUMENT; @@ -4649,6 +4659,7 @@ void CameraHidlTest::castSession(const sp &session, int32_ ASSERT_NE(nullptr, session3_4); switch (deviceVersion) { + case CAMERA_DEVICE_API_VERSION_3_5: case CAMERA_DEVICE_API_VERSION_3_4: { auto castResult = device::V3_4::ICameraDeviceSession::castFrom(session); ASSERT_TRUE(castResult.isOk()); @@ -4667,6 +4678,101 @@ void CameraHidlTest::castSession(const sp &session, int32_ } } +// Verify logical camera static metadata +void CameraHidlTest::verifyLogicalCameraMetadata(const std::string& cameraName, + const ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice>& device, + const CameraMetadata &chars, int deviceVersion, + const hidl_vec& deviceNames) { + const camera_metadata_t* metadata = (camera_metadata_t*)chars.data(); + ASSERT_NE(nullptr, metadata); + + Status rc = isLogicalMultiCamera(metadata); + ASSERT_TRUE(Status::OK == rc || Status::METHOD_NOT_SUPPORTED == rc); + if (Status::METHOD_NOT_SUPPORTED == rc) { + return; + } + + std::string version, cameraId; + ASSERT_TRUE(::matchDeviceName(cameraName, mProviderType, &version, &cameraId)); + std::unordered_set physicalIds; + ASSERT_TRUE(Status::OK == getPhysicalCameraIds(metadata, &physicalIds)); + for (auto physicalId : physicalIds) { + ASSERT_NE(physicalId, cameraId); + bool isPublicId = false; + for (auto& deviceName : deviceNames) { + std::string publicVersion, publicId; + ASSERT_TRUE(::matchDeviceName(deviceName, mProviderType, &publicVersion, &publicId)); + if (physicalId == publicId) { + isPublicId = true; + break; + } + } + if (isPublicId) { + continue; + } + + ASSERT_TRUE(deviceVersion >= CAMERA_DEVICE_API_VERSION_3_5); + auto castResult = device::V3_5::ICameraDevice::castFrom(device); + 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 ret = device3_5->getPhysicalCameraCharacteristics(physicalId, + [&](auto status, const auto& chars) { + verifyCameraCharacteristics(status, chars); + }); + ASSERT_TRUE(ret.isOk()); + + // Check calling getCameraDeviceInterface_V3_x() on hidden camera id returns + // ILLEGAL_ARGUMENT. + std::stringstream s; + s << "device@" << version << "/" << mProviderType << "/" << physicalId; + hidl_string fullPhysicalId(s.str()); + ret = mProvider->getCameraDeviceInterface_V3_x(fullPhysicalId, + [&](auto status, const auto& device3_x) { + ASSERT_EQ(Status::ILLEGAL_ARGUMENT, status); + ASSERT_EQ(device3_x, nullptr); + }); + ASSERT_TRUE(ret.isOk()); + } +} + +void CameraHidlTest::verifyCameraCharacteristics(Status status, const CameraMetadata& chars) { + ASSERT_EQ(Status::OK, status); + const camera_metadata_t* metadata = (camera_metadata_t*)chars.data(); + size_t expectedSize = chars.size(); + int result = validate_camera_metadata_structure(metadata, &expectedSize); + ASSERT_TRUE((result == 0) || (result == CAMERA_METADATA_VALIDATION_SHIFTED)); + size_t entryCount = get_camera_metadata_entry_count(metadata); + // TODO: we can do better than 0 here. Need to check how many required + // characteristics keys we've defined. + ASSERT_GT(entryCount, 0u); + + camera_metadata_ro_entry entry; + int retcode = find_camera_metadata_ro_entry(metadata, + ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL, &entry); + if ((0 == retcode) && (entry.count > 0)) { + uint8_t hardwareLevel = entry.data.u8[0]; + ASSERT_TRUE( + hardwareLevel == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED || + hardwareLevel == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL || + hardwareLevel == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_3 || + hardwareLevel == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL); + } else { + ADD_FAILURE() << "Get camera hardware level failed!"; + } + + entry.count = 0; + retcode = find_camera_metadata_ro_entry(metadata, + ANDROID_REQUEST_CHARACTERISTIC_KEYS_NEEDING_PERMISSION, &entry); + if ((0 == retcode) || (entry.count > 0)) { + ADD_FAILURE() << "ANDROID_REQUEST_CHARACTERISTIC_KEYS_NEEDING_PERMISSION " + << " per API contract should never be set by Hal!"; + } +} + // Open a device session with empty callbacks and return static metadata. void CameraHidlTest::openEmptyDeviceSession(const std::string &name, sp provider, From 16e37eb7caaf10a09ed9ee1ee5ab065e5e5e6b0f Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Thu, 4 Oct 2018 15:56:22 -0700 Subject: [PATCH 136/718] audio: Copy audio_policy_configuration.xsd for HAL V4.1 This only copies the file to simplify reviewing additons Bug: 116356348 Test: N/A Change-Id: Idbc1489163f0ea8938ff5c32499d22ddbf8fc12d --- .../4.1/config/audio_policy_configuration.xsd | 564 ++++++++++++++++++ 1 file changed, 564 insertions(+) create mode 100644 audio/4.1/config/audio_policy_configuration.xsd diff --git a/audio/4.1/config/audio_policy_configuration.xsd b/audio/4.1/config/audio_policy_configuration.xsd new file mode 100644 index 0000000000..ee17fc983b --- /dev/null +++ b/audio/4.1/config/audio_policy_configuration.xsd @@ -0,0 +1,564 @@ + + + + + + + + + + + + + + Version of the interface the hal implements. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + There should be one section per audio HW module present on the platform. + Each contains two mandatory tags: “halVersion” and “name”. + The module "name" is the same as in previous .conf file. + Each module must contain the following sections: + - : a list of device descriptors for all + input and output devices accessible via this module. + This contains both permanently attached devices and removable devices. + - : listing all output and input streams exposed by the audio HAL + - : list of possible connections between input + and output devices or between stream and devices. + A is defined by a set of 3 attributes: + -"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 this route + - : permanently attached devices. + The attachedDevices section is a list of devices names. + Their names correspond to device names defined in "devicePorts" section. + - is the device to be used when no policy rule applies + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + "|" separated list of audio_output_flags_t or audio_input_flags_t. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + When choosing the mixPort of an audio track, the audioPolicy + first considers the mixPorts with a preferredUsage including + the track AudioUsage preferred . + If non support the track format, the other mixPorts are considered. + Eg: a will receive + the audio of all apps playing with a MEDIA usage. + It may receive audio from ALARM if there are no audio compatible + . + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comma (",") separated list of channel flags + from audio_channel_mask_t. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The default device will be used if multiple have the same type + and no explicit route request exists for a specific device of + that type. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + List all available sources for a given sink. + + + + + + + + + + + + + + + + + + + + + + Comma separated pair of number. + The fist one is the framework level (between 0 and 100). + The second one is the volume to send to the HAL. + The framework will interpolate volumes not specified. + Their MUST be at least 2 points specified. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Volume section defines a volume curve for a given use case and device category. + It contains a list of points of this curve expressing the attenuation in Millibels + for a given volume index from 0 to 100. + + 0,-9600 + 100,0 + + + It may also reference a reference/@name to avoid duplicating curves. + + + 0,-9600 + 100,0 + + + + + + + + + + + + + + + + + From cc3677997cd1a3f5ff375e765ef4b7555fabffb6 Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Thu, 4 Oct 2018 15:59:37 -0700 Subject: [PATCH 137/718] audio: Add configuration for surround sound Bug: 116356348 Test: xmllint --noout --xinclude --schema \ hardware/interfaces/audio/4.1/config/audio_policy_configuration.xsd \ frameworks/av/services/audiopolicy/config/audio_policy_configuration.xml Change-Id: Ib8d84b950f439c2ebed181385b41a83556976e60 --- .../4.1/config/audio_policy_configuration.xsd | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/audio/4.1/config/audio_policy_configuration.xsd b/audio/4.1/config/audio_policy_configuration.xsd index ee17fc983b..311b9c1a83 100644 --- a/audio/4.1/config/audio_policy_configuration.xsd +++ b/audio/4.1/config/audio_policy_configuration.xsd @@ -42,6 +42,7 @@ + @@ -344,6 +345,12 @@ + + + + + + + 1.3-4 IRadio slot1 From 08ff314594235ad32967cacf7336d2da90f29df5 Mon Sep 17 00:00:00 2001 From: Jeff Tinker Date: Thu, 17 Jan 2019 17:24:50 -0800 Subject: [PATCH 397/718] Add securityLevel to MediaDrm isCryptoSchemeSupported API bug:110701831 test: cts media test cases, widevine integration tests Change-Id: I9e4679ee63b3997f7141c9b81fd6f375e862862d --- drm/1.2/IDrmFactory.hal | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drm/1.2/IDrmFactory.hal b/drm/1.2/IDrmFactory.hal index c94e4bbcd3..682889c22a 100644 --- a/drm/1.2/IDrmFactory.hal +++ b/drm/1.2/IDrmFactory.hal @@ -17,6 +17,7 @@ package android.hardware.drm@1.2; import @1.1::IDrmFactory; import @1.1::IDrmPlugin; +import @1.1::SecurityLevel; /** * IDrmFactory is the main entry point for interacting with a vendor's @@ -35,4 +36,16 @@ import @1.1::IDrmPlugin; */ interface IDrmFactory extends @1.1::IDrmFactory { + /** + * Determine if a specific security level is supported by the device. + * This method only differs from @1.0 isCryptoSchemeSupported + * by the addition of a security level. + * + * @param uuid identifies the crypto scheme in question + * @param mimeType identifies the mime type in question + * @param securityLevel specifies the security level required + * @return isSupported must be true only if the scheme is supported + */ + isCryptoSchemeSupported_1_2(uint8_t[16] uuid, string mimeType, + @1.1::SecurityLevel securityLevel) generates(bool isSupported); }; From 1f702cac1fea2088b1cd34c9dcaa7cdbddaefb1c Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Tue, 22 Jan 2019 12:41:41 -0800 Subject: [PATCH 398/718] audio: add new audio formats Add AAC_LATM*, CELT and APTX_ADAPTIVE to the list of audio formats. Bug: 123082414 Test: make Change-Id: Id75e1f5016929d5a67e777774aaa892df6f91e78 --- audio/5.0/config/api/current.txt | 6 ++++++ audio/5.0/config/audio_policy_configuration.xsd | 6 ++++++ audio/common/5.0/types.hal | 7 +++++++ 3 files changed, 19 insertions(+) diff --git a/audio/5.0/config/api/current.txt b/audio/5.0/config/api/current.txt index 822237e014..d4469f8b28 100644 --- a/audio/5.0/config/api/current.txt +++ b/audio/5.0/config/api/current.txt @@ -91,6 +91,10 @@ package audio.policy.configuration.V5_0 { enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_AAC_ERLC; enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_AAC_HE_V1; enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_AAC_HE_V2; + enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_AAC_LATM; + enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_AAC_LATM_HE_V1; + enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_AAC_LATM_HE_V2; + enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_AAC_LATM_LC; enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_AAC_LC; enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_AAC_LD; enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_AAC_LTP; @@ -106,7 +110,9 @@ package audio.policy.configuration.V5_0 { enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_AMR_WB_PLUS; enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_APE; enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_APTX; + enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_APTX_ADAPTIVE; enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_APTX_HD; + enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_CELT; enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_DOLBY_TRUEHD; enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_DSD; enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_DTS; diff --git a/audio/5.0/config/audio_policy_configuration.xsd b/audio/5.0/config/audio_policy_configuration.xsd index efe93b3ee9..d85f9c2a96 100644 --- a/audio/5.0/config/audio_policy_configuration.xsd +++ b/audio/5.0/config/audio_policy_configuration.xsd @@ -364,6 +364,12 @@ + + + + + + diff --git a/audio/common/5.0/types.hal b/audio/common/5.0/types.hal index b4e947096f..3f81836f0b 100644 --- a/audio/common/5.0/types.hal +++ b/audio/common/5.0/types.hal @@ -235,6 +235,10 @@ enum AudioFormat : uint32_t { LDAC = 0x23000000UL, /** Dolby Metadata-enhanced Audio Transmission */ MAT = 0x24000000UL, + AAC_LATM = 0x25000000UL, + CELT = 0x26000000UL, + APTX_ADAPTIVE = 0x27000000UL, + /** Deprecated */ MAIN_MASK = 0xFF000000UL, SUB_MASK = 0x00FFFFFFUL, @@ -306,6 +310,9 @@ enum AudioFormat : uint32_t { MAT_1_0 = (MAT | MAT_SUB_1_0), MAT_2_0 = (MAT | MAT_SUB_2_0), MAT_2_1 = (MAT | MAT_SUB_2_1), + AAC_LATM_LC = (AAC_LATM | AAC_SUB_LC), + AAC_LATM_HE_V1 = (AAC_LATM | AAC_SUB_HE_V1), + AAC_LATM_HE_V2 = (AAC_LATM | AAC_SUB_HE_V2), }; /** From f2b77b0705b0b823e24adeb06d35b526ef640781 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Tue, 22 Jan 2019 12:56:56 -0800 Subject: [PATCH 399/718] audio: add new audio formats Add audio format for LHDC Bluetooth codec. Also add missing audio sources and devices in xsd. Bug: 120395342 Test: make Change-Id: Ib55c7d351074d8ef75747bcb1195e1ce15ed8b20 --- audio/5.0/config/api/current.txt | 4 ++++ audio/5.0/config/audio_policy_configuration.xsd | 4 ++++ audio/common/5.0/types.hal | 2 ++ audio/effect/2.0/xml/audio_effects_conf.xsd | 1 + audio/effect/5.0/xml/api/current.txt | 1 + 5 files changed, 12 insertions(+) diff --git a/audio/5.0/config/api/current.txt b/audio/5.0/config/api/current.txt index d4469f8b28..17f38c1647 100644 --- a/audio/5.0/config/api/current.txt +++ b/audio/5.0/config/api/current.txt @@ -20,8 +20,10 @@ package audio.policy.configuration.V5_0 { enum_constant public static final audio.policy.configuration.V5_0.AudioDevice AUDIO_DEVICE_IN_COMMUNICATION; enum_constant public static final audio.policy.configuration.V5_0.AudioDevice AUDIO_DEVICE_IN_DEFAULT; enum_constant public static final audio.policy.configuration.V5_0.AudioDevice AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET; + enum_constant public static final audio.policy.configuration.V5_0.AudioDevice AUDIO_DEVICE_IN_ECHO_REFERENCE; enum_constant public static final audio.policy.configuration.V5_0.AudioDevice AUDIO_DEVICE_IN_FM_TUNER; enum_constant public static final audio.policy.configuration.V5_0.AudioDevice AUDIO_DEVICE_IN_HDMI; + enum_constant public static final audio.policy.configuration.V5_0.AudioDevice AUDIO_DEVICE_IN_HDMI_ARC; enum_constant public static final audio.policy.configuration.V5_0.AudioDevice AUDIO_DEVICE_IN_IP; enum_constant public static final audio.policy.configuration.V5_0.AudioDevice AUDIO_DEVICE_IN_LINE; enum_constant public static final audio.policy.configuration.V5_0.AudioDevice AUDIO_DEVICE_IN_LOOPBACK; @@ -128,6 +130,8 @@ package audio.policy.configuration.V5_0 { enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_HE_AAC_V2; enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_IEC61937; enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_LDAC; + enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_LHDC; + enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_LHDC_LL; enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_MAT_1_0; enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_MAT_2_0; enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_MAT_2_1; diff --git a/audio/5.0/config/audio_policy_configuration.xsd b/audio/5.0/config/audio_policy_configuration.xsd index d85f9c2a96..ee3a437d1d 100644 --- a/audio/5.0/config/audio_policy_configuration.xsd +++ b/audio/5.0/config/audio_policy_configuration.xsd @@ -277,6 +277,8 @@ + + @@ -370,6 +372,8 @@ + + diff --git a/audio/common/5.0/types.hal b/audio/common/5.0/types.hal index 3f81836f0b..ffe45069a8 100644 --- a/audio/common/5.0/types.hal +++ b/audio/common/5.0/types.hal @@ -238,6 +238,8 @@ enum AudioFormat : uint32_t { AAC_LATM = 0x25000000UL, CELT = 0x26000000UL, APTX_ADAPTIVE = 0x27000000UL, + LHDC = 0x28000000UL, + LHDC_LL = 0x29000000UL, /** Deprecated */ MAIN_MASK = 0xFF000000UL, diff --git a/audio/effect/2.0/xml/audio_effects_conf.xsd b/audio/effect/2.0/xml/audio_effects_conf.xsd index df281b32d1..b97b847a39 100644 --- a/audio/effect/2.0/xml/audio_effects_conf.xsd +++ b/audio/effect/2.0/xml/audio_effects_conf.xsd @@ -39,6 +39,7 @@ + diff --git a/audio/effect/5.0/xml/api/current.txt b/audio/effect/5.0/xml/api/current.txt index 4a7f88b558..473bb10358 100644 --- a/audio/effect/5.0/xml/api/current.txt +++ b/audio/effect/5.0/xml/api/current.txt @@ -74,6 +74,7 @@ package audio.effects.V5_0 { enum_constant public static final audio.effects.V5_0.StreamInputType voice_call; enum_constant public static final audio.effects.V5_0.StreamInputType voice_communication; enum_constant public static final audio.effects.V5_0.StreamInputType voice_downlink; + enum_constant public static final audio.effects.V5_0.StreamInputType voice_performance; enum_constant public static final audio.effects.V5_0.StreamInputType voice_recognition; enum_constant public static final audio.effects.V5_0.StreamInputType voice_uplink; } From 143d32860fbe08eef95f582b3e9b5b65762f2706 Mon Sep 17 00:00:00 2001 From: Amit Mahajan Date: Tue, 22 Jan 2019 16:01:19 -0800 Subject: [PATCH 400/718] Add a new parameter to emergencyDial(). The new parameter is to indicate if the request is initiated by the user through an emergency dialer or shortcut, meaning that the request is explicitly an emergency dial request. This is to indicate to the modem that no disambiguation (regarding whether this is really an emergency request) should be done for this request. Test: builds fine Bug: 123101600 Change-Id: Ic830762d8a8319f494f22d875ca6adad91ffce3b --- radio/1.4/IRadio.hal | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/radio/1.4/IRadio.hal b/radio/1.4/IRadio.hal index dd69607e5e..21c509766a 100644 --- a/radio/1.4/IRadio.hal +++ b/radio/1.4/IRadio.hal @@ -128,6 +128,10 @@ interface IRadio extends @1.3::IRadio { * does not support the emergency service category or emergency uniform resource names, the * field 'categories' or 'urns' may be ignored. * + * 'fromEmergencyDialer' indicates if this request originated from emergency dialer/shortcut, + * which means an explicit intent from the user to dial an emergency number. The modem must + * treat this as an actual emergency dial and not try to disambiguate. + * * If 'isTesting' is true, this request is for testing purpose, and must not be sent to a real * emergency service; otherwise it's for a real emergency call request. * @@ -142,12 +146,14 @@ interface IRadio extends @1.3::IRadio { * of the call. * @param urns the emergency Uniform Resource Names (URN) * @param routing @1.4::EmergencyCallRouting the emergency call routing information. + * @param fromEmergencyDialer Flag indicating if this request originated from emergency dialer. + * @param isTesting Flag indicating if this request is for testing purpose. * * Response function is IRadioResponse.emergencyDialResponse() */ oneway emergencyDial(int32_t serial, Dial dialInfo, bitfield categories, vec urns, - EmergencyCallRouting routing, bool isTesting); + EmergencyCallRouting routing, bool fromEmergencyDialer, bool isTesting); /** * Starts a network scan From 2bb37160b2707fd446ec540d4bbaa54775ed2c6f Mon Sep 17 00:00:00 2001 From: Henry Fang Date: Mon, 14 Jan 2019 16:18:33 -0800 Subject: [PATCH 401/718] Update CEC hal to 2.0 cec@2.0 spec was published with HDMI 2.0b in March 2016. it added a few important message types, and also require new mechanism to build and maintain device information. Test: manual Bug: 122853595 Change-Id: I00819829573dc260b043f5b14a15c29bc2a119b0 --- tv/cec/2.0/Android.bp | 46 ++ tv/cec/2.0/IHdmiCec.hal | 209 +++++++ tv/cec/2.0/IHdmiCecCallback.hal | 41 ++ tv/cec/2.0/default/Android.bp | 42 ++ tv/cec/2.0/default/HdmiCec.cpp | 421 ++++++++++++++ tv/cec/2.0/default/HdmiCec.h | 115 ++++ tv/cec/2.0/default/OWNERS | 4 + .../android.hardware.tv.cec@2.0-service.rc | 4 + .../android.hardware.tv.cec@2.0-service.xml | 11 + tv/cec/2.0/default/service.cpp | 27 + tv/cec/2.0/types.hal | 548 ++++++++++++++++++ 11 files changed, 1468 insertions(+) create mode 100644 tv/cec/2.0/Android.bp create mode 100644 tv/cec/2.0/IHdmiCec.hal create mode 100644 tv/cec/2.0/IHdmiCecCallback.hal create mode 100644 tv/cec/2.0/default/Android.bp create mode 100644 tv/cec/2.0/default/HdmiCec.cpp create mode 100644 tv/cec/2.0/default/HdmiCec.h create mode 100644 tv/cec/2.0/default/OWNERS create mode 100644 tv/cec/2.0/default/android.hardware.tv.cec@2.0-service.rc create mode 100644 tv/cec/2.0/default/android.hardware.tv.cec@2.0-service.xml create mode 100644 tv/cec/2.0/default/service.cpp create mode 100644 tv/cec/2.0/types.hal diff --git a/tv/cec/2.0/Android.bp b/tv/cec/2.0/Android.bp new file mode 100644 index 0000000000..998cb23ecb --- /dev/null +++ b/tv/cec/2.0/Android.bp @@ -0,0 +1,46 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +hidl_interface { + name: "android.hardware.tv.cec@2.0", + root: "android.hardware", + vndk: { + enabled: true, + }, + srcs: [ + "types.hal", + "IHdmiCec.hal", + "IHdmiCecCallback.hal", + ], + interfaces: [ + "android.hidl.base@1.0", + "android.hidl.safe_union@1.0", + ], + types: [ + "AbortReason", + "CecAllDeviceTypeValue", + "CecDeviceFeature", + "CecDeviceInfo", + "CecDeviceType", + "CecLogicalAddress", + "CecMessage", + "CecMessageType", + "CecPowerState", + "CecRcProfile", + "CecRcProfile1", + "CecRcProfileId", + "CecRcProfileSource", + "CecTopologyEvent", + "CecTopologyEventType", + "CecUICommandCodes", + "CecVersion", + "HdmiPortInfo", + "HdmiPortType", + "HotplugEvent", + "MaxLength", + "OptionKey", + "Result", + "SendMessageResult", + ], + gen_java: true, +} + diff --git a/tv/cec/2.0/IHdmiCec.hal b/tv/cec/2.0/IHdmiCec.hal new file mode 100644 index 0000000000..0723bad8c6 --- /dev/null +++ b/tv/cec/2.0/IHdmiCec.hal @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.tv.cec@2.0; + +import IHdmiCecCallback; + +/** + * HDMI-CEC HAL interface definition. + */ +interface IHdmiCec { + /** + * Passes Primary Device Type that must be used in this system. + * + * HAL must use it to allocate logical address as specified in CEC section + * 11.3.2 of the CEC spec 2.0b. Then CEC commands addressed the given + * logical address can be filtered in. + * This method shall be able to be called up to twice to support two Primary + * Device Type as specified in CEC Table 11-8 of the CEC spec 2.0b. + * + * @param deviceType that must be used in this system. It must be a valid + * value in CecDeviceType for the call to succeed. + * @return result Result status of the operation. SUCCESS if successful, + * FAILURE_INVALID_ARGS if the given device type is invalid, + * FAILURE_BUSY if device or resource is busy + */ + @callflow(next={"*"}) + addDeviceType(CecDeviceType deviceType) generates (Result result); + + /** + * Clears all Primary Device Types. + * + * It is used when the system plan to reconfigure Primary Device Type, + * hence to tell HAL to release all logical address associated to them, + * and change the state back to the beginning. + */ + @callflow(next="addDeviceType") + @exit + clearDeviceTypes(); + + /** + * Set All Device Types for a Primary Device Type. + * + * This value must be used in REPORT_FEATURES message to response + * GIVE_FEATURES message in HAL. + * + * @param allDeviceTypes device all device types for a Primary Device Type. + */ + @callflow(next="addDeviceType") + setAllDeviceTypes(CecAllDeviceTypes allDeviceTypes); + + /** + * Set Device Features for a Primary Device Type. + * + * This value must be used in REPORT_FEATURES message to response + * GIVE_FEATURES message in HAL. + * + * @param deviceType The device Primary Device Type. + * @param deviceFeatures device features for a Primary Device Type. + */ + @callflow(next="addDeviceType") + setDeviceFeatures(CecDeviceType deviceType, + CecDeviceFeatures deviceFeatures); + + /** + * Set Remote Control Profile for a Primary Device Type. + * + * This value must be used in REPORT_FEATURES message to response + * GIVE_FEATURES message in HAL. + * + * @param deviceType The device Primary Device Type. + * @param rcProliles remote control profiles for a Primary Device Type. + */ + @callflow(next="addDeviceType") + setRcProfile(CecDeviceType deviceType, CecRcProfile rcProfile); + + /** + * Retrieve CEC device information. + * + * CEC section 11.3 of the CEC spec 2.0b specify that a device should not + * ask for static information that another device has already supplied. + * Therefore, CEC 2.0 software stack need a map to store all cec + * devices’ information of current CEC network. + * The device information is broadcasted by a device after it allocates a + * logical address. Messages used to send out these information are + * REPORT_FEATURES, REPORT_PHYSICAL_ADDRESS, DEVICE_VENDOR_ID. + * The spec also requires less than 1 second between REPORT_FEATURES and + * REPORT_PHYSICAL_ADDRESS message, and less than 2 second between + * REPORT_PHYSICAL_ADDRESS and DEVICE_VENDOR_ID. An Implementation of + * device information map in hal can help to meet the timing constraints. + * Logical addressing is part of the process to build this map, so the + * implementation shall include allocating logical address too. + * Whenever a device plug/unplug, the topology of CEC network changes. + * The hal implementation shall update devices’ information map, and + * send out onTopologyEvent to Android system. Then Android system + * will use readDeviceInfo to retreive latest devices’ information of CEC + * network. + * If SYSTEM_CEC_CONTROL is false, the hal implementation need continue to + * maintain and update device information map, and send out pending + * onTopologyEvent to Android system when SYSTEM_CEC_CONTROL is + * changed to true. + * + * @param logicalAddress logical address of CEC device. + * @param physicalAddress physical address of CEC device. + * @return CecDeviceInfo from device information map. + * @return result Result status of the operation. SUCCESS if successful, + * FAILURE_INVALID_ARGS if logical or physical address is invalid. + * FAILURE_INVALID_STATE if device information isn't available yet. + */ + @callflow(next="onTopologyChangeEvent") + readDeviceInfo(CecLogicalAddress logicalAddress, + CecPhysicalAddress physicalAddress) + generates (Result result, CecDeviceInfo deviceInfo); + + /** + * Transmits HDMI-CEC message to other HDMI device. + * + * The method must be designed to return in a certain amount of time and not + * hanging forever. This method MUST complete with in 1 second. + * + * It must try retransmission at least once as specified in the section '7.1 + * Frame Re-transmissions' of the CEC Spec 1.4b. + * + * @param message CEC message to be sent to other HDMI device. + * @return result Result status of the operation. SUCCESS if successful, + * NACK if the sent message is not acknowledged, + * BUSY if the CEC bus is busy. + */ + @callflow(next="*") + sendMessage(CecMessage message) generates (SendMessageResult result); + + /** + * Set the callback + * + * It is used by the framework to receive CecMessages, HDMI hotplug event + * and topology update event. Only one callback client is supported. + * + * @param callback Callback object to pass hdmi events to the system. The + * previously registered callback must be replaced with this one. + */ + @callflow(next={"*"}) + @entry + setCallback(IHdmiCecCallback callback); + + /** + * Gets the hdmi port information of underlying hardware. + * + * @return infos The list of HDMI port information + */ + @callflow(next={"*"}) + getPortInfo() generates (vec infos); + + /** + * Sets flags controlling the way HDMI-CEC service works down to HAL + * implementation. Those flags must be used in case the feature needs update + * in HAL itself, firmware or microcontroller. + * + * @param key The key of the option to be updated with a new value. + * @param value Value to be set. + */ + @callflow(next="*") + setOption(OptionKey key, bool value); + + /** + * Passes the updated language information of Android system. Contains + * three-letter code as defined in ISO/FDIS 639-2. Must be used for HAL to + * respond to while in standby mode. + * + * @param language Three-letter code defined in ISO/FDIS 639-2. Must be + * lowercase letters. (e.g., eng for English) + */ + @callflow(next="*") + setLanguage(string language); + + /** + * Configures ARC circuit in the hardware logic to start or stop the + * feature. + * + * @param portId Port id to be configured. + * @param enable Flag must be either true to start the feature or false to + * stop it. + */ + @callflow(next="*") + enableAudioReturnChannel(HdmiPortId portId, bool enable); + + /** + * Gets the connection status of the specified port. + * + * It's specified in CEC section 10.8 of the CEC spec 2.0b + * + * @param portId Port id to be inspected for the connection status. + * @return status True if a device is connected, otherwise false. + */ + @callflow(next="*") + isConnected(HdmiPortId portId) generates (bool connected); +}; diff --git a/tv/cec/2.0/IHdmiCecCallback.hal b/tv/cec/2.0/IHdmiCecCallback.hal new file mode 100644 index 0000000000..1a8a4895cd --- /dev/null +++ b/tv/cec/2.0/IHdmiCecCallback.hal @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.tv.cec@2.0; + +interface IHdmiCecCallback { + /** + * The callback function that must be called by HAL implementation to notify + * the system of new CEC message arrival. + */ + oneway onCecMessage(CecMessage message); + + /** + * The callback function that must be called by HAL implementation to notify + * the system of new hotplug event. + */ + oneway onHotplugEvent(HotplugEvent event); + + /** + * The callback function must be called by HAL implementation to notify the + * system whenever CEC device information of CEC network change. + * HAL shall be ready for readDeviceInfo call before invoke this callback. + * This event is triggered by topology change of whole CEC network. It's + * different from HotplugEvent which is triggered between devices which are + * connected directly through HDMI cable. + */ + oneway onTopologyEvent(CecTopologyEvent event); +}; diff --git a/tv/cec/2.0/default/Android.bp b/tv/cec/2.0/default/Android.bp new file mode 100644 index 0000000000..6e624e3e7d --- /dev/null +++ b/tv/cec/2.0/default/Android.bp @@ -0,0 +1,42 @@ +cc_library_shared { + name: "android.hardware.tv.cec@2.0-impl", + defaults: ["hidl_defaults"], + vendor: true, + relative_install_path: "hw", + srcs: ["HdmiCec.cpp"], + + shared_libs: [ + "libhidlbase", + "libhidltransport", + "liblog", + "libbase", + "libutils", + "libhardware", + "android.hardware.tv.cec@2.0", + ], + +} + +cc_binary { + name: "android.hardware.tv.cec@2.0-service", + vintf_fragments: ["android.hardware.tv.cec@2.0-service.xml"], + defaults: ["hidl_defaults"], + relative_install_path: "hw", + vendor: true, + init_rc: ["android.hardware.tv.cec@2.0-service.rc"], + srcs: ["service.cpp"], + + shared_libs: [ + "liblog", + "libcutils", + "libdl", + "libbase", + "libutils", + "libhardware_legacy", + "libhardware", + "libhidlbase", + "libhidltransport", + "android.hardware.tv.cec@2.0", + ], + +} diff --git a/tv/cec/2.0/default/HdmiCec.cpp b/tv/cec/2.0/default/HdmiCec.cpp new file mode 100644 index 0000000000..f45171955b --- /dev/null +++ b/tv/cec/2.0/default/HdmiCec.cpp @@ -0,0 +1,421 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "android.hardware.tv.cec@2.0-impl" +#include + +#include +#include +#include "HdmiCec.h" + +namespace android { +namespace hardware { +namespace tv { +namespace cec { +namespace V2_0 { +namespace implementation { + +static_assert(CEC_DEVICE_INACTIVE == static_cast(CecDeviceType::INACTIVE), + "CecDeviceType::INACTIVE must match legacy value."); +static_assert(CEC_DEVICE_TV == static_cast(CecDeviceType::TV), + "CecDeviceType::TV must match legacy value."); +static_assert(CEC_DEVICE_RECORDER == static_cast(CecDeviceType::RECORDER), + "CecDeviceType::RECORDER must match legacy value."); +static_assert(CEC_DEVICE_TUNER == static_cast(CecDeviceType::TUNER), + "CecDeviceType::TUNER must match legacy value."); +static_assert(CEC_DEVICE_PLAYBACK == static_cast(CecDeviceType::PLAYBACK), + "CecDeviceType::PLAYBACK must match legacy value."); +static_assert(CEC_DEVICE_AUDIO_SYSTEM == static_cast(CecDeviceType::AUDIO_SYSTEM), + "CecDeviceType::AUDIO_SYSTEM must match legacy value."); +/* TODO: Adjust for cec@2.0 +static_assert(CEC_DEVICE_MAX == static_cast(CecDeviceType::MAX), + "CecDeviceType::MAX must match legacy value."); +*/ +static_assert(CEC_ADDR_TV == static_cast(CecLogicalAddress::TV), + "CecLogicalAddress::TV must match legacy value."); +static_assert(CEC_ADDR_RECORDER_1 == static_cast(CecLogicalAddress::RECORDER_1), + "CecLogicalAddress::RECORDER_1 must match legacy value."); +static_assert(CEC_ADDR_RECORDER_2 == static_cast(CecLogicalAddress::RECORDER_2), + "CecLogicalAddress::RECORDER_2 must match legacy value."); +static_assert(CEC_ADDR_TUNER_1 == static_cast(CecLogicalAddress::TUNER_1), + "CecLogicalAddress::TUNER_1 must match legacy value."); +static_assert(CEC_ADDR_PLAYBACK_1 == static_cast(CecLogicalAddress::PLAYBACK_1), + "CecLogicalAddress::PLAYBACK_1 must match legacy value."); +static_assert(CEC_ADDR_AUDIO_SYSTEM == static_cast(CecLogicalAddress::AUDIO_SYSTEM), + "CecLogicalAddress::AUDIO_SYSTEM must match legacy value."); +static_assert(CEC_ADDR_TUNER_2 == static_cast(CecLogicalAddress::TUNER_2), + "CecLogicalAddress::TUNER_2 must match legacy value."); +static_assert(CEC_ADDR_TUNER_3 == static_cast(CecLogicalAddress::TUNER_3), + "CecLogicalAddress::TUNER_3 must match legacy value."); +static_assert(CEC_ADDR_PLAYBACK_2 == static_cast(CecLogicalAddress::PLAYBACK_2), + "CecLogicalAddress::PLAYBACK_2 must match legacy value."); +static_assert(CEC_ADDR_RECORDER_3 == static_cast(CecLogicalAddress::RECORDER_3), + "CecLogicalAddress::RECORDER_3 must match legacy value."); +static_assert(CEC_ADDR_TUNER_4 == static_cast(CecLogicalAddress::TUNER_4), + "CecLogicalAddress::TUNER_4 must match legacy value."); +static_assert(CEC_ADDR_PLAYBACK_3 == static_cast(CecLogicalAddress::PLAYBACK_3), + "CecLogicalAddress::PLAYBACK_3 must match legacy value."); +/* TODO: Adjust for cec@2.0 +static_assert(CEC_ADDR_FREE_USE == static_cast(CecLogicalAddress::FREE_USE), + "CecLogicalAddress::FREE_USE must match legacy value."); +*/ +static_assert(CEC_ADDR_UNREGISTERED == static_cast(CecLogicalAddress::UNREGISTERED), + "CecLogicalAddress::UNREGISTERED must match legacy value."); +static_assert(CEC_ADDR_BROADCAST == static_cast(CecLogicalAddress::BROADCAST), + "CecLogicalAddress::BROADCAST must match legacy value."); + +static_assert(CEC_MESSAGE_FEATURE_ABORT == static_cast(CecMessageType::FEATURE_ABORT), + "CecMessageType::FEATURE_ABORT must match legacy value."); +static_assert(CEC_MESSAGE_IMAGE_VIEW_ON == static_cast(CecMessageType::IMAGE_VIEW_ON), + "CecMessageType::IMAGE_VIEW_ON must match legacy value."); +static_assert(CEC_MESSAGE_TUNER_STEP_INCREMENT == + static_cast(CecMessageType::TUNER_STEP_INCREMENT), + "CecMessageType::TUNER_STEP_INCREMENT must match legacy value."); +static_assert(CEC_MESSAGE_TUNER_STEP_DECREMENT == + static_cast(CecMessageType::TUNER_STEP_DECREMENT), + "CecMessageType::TUNER_STEP_DECREMENT must match legacy value."); +static_assert(CEC_MESSAGE_TUNER_DEVICE_STATUS == + static_cast(CecMessageType::TUNER_DEVICE_STATUS), + "CecMessageType::TUNER_DEVICE_STATUS must match legacy value."); +static_assert(CEC_MESSAGE_GIVE_TUNER_DEVICE_STATUS == + static_cast(CecMessageType::GIVE_TUNER_DEVICE_STATUS), + "CecMessageType::GIVE_TUNER_DEVICE_STATUS must match legacy value."); +static_assert(CEC_MESSAGE_RECORD_ON == static_cast(CecMessageType::RECORD_ON), + "CecMessageType::RECORD_ON must match legacy value."); +static_assert(CEC_MESSAGE_RECORD_STATUS == static_cast(CecMessageType::RECORD_STATUS), + "CecMessageType::RECORD_STATUS must match legacy value."); +static_assert(CEC_MESSAGE_RECORD_OFF == static_cast(CecMessageType::RECORD_OFF), + "CecMessageType::RECORD_OFF must match legacy value."); +static_assert(CEC_MESSAGE_TEXT_VIEW_ON == static_cast(CecMessageType::TEXT_VIEW_ON), + "CecMessageType::TEXT_VIEW_ON must match legacy value."); +static_assert(CEC_MESSAGE_RECORD_TV_SCREEN == static_cast(CecMessageType::RECORD_TV_SCREEN), + "CecMessageType::RECORD_TV_SCREEN must match legacy value."); +static_assert(CEC_MESSAGE_GIVE_DECK_STATUS == static_cast(CecMessageType::GIVE_DECK_STATUS), + "CecMessageType::GIVE_DECK_STATUS must match legacy value."); +static_assert(CEC_MESSAGE_STANDBY == static_cast(CecMessageType::STANDBY), + "CecMessageType::STANDBY must match legacy value."); +static_assert(CEC_MESSAGE_PLAY == static_cast(CecMessageType::PLAY), + "CecMessageType::PLAY must match legacy value."); +static_assert(CEC_MESSAGE_DECK_CONTROL == static_cast(CecMessageType::DECK_CONTROL), + "CecMessageType::DECK_CONTROL must match legacy value."); +static_assert(CEC_MESSAGE_TIMER_CLEARED_STATUS == + static_cast(CecMessageType::TIMER_CLEARED_STATUS), + "CecMessageType::TIMER_CLEARED_STATUS must match legacy value."); +static_assert(CEC_MESSAGE_USER_CONTROL_PRESSED == + static_cast(CecMessageType::USER_CONTROL_PRESSED), + "CecMessageType::USER_CONTROL_PRESSED must match legacy value."); +static_assert(CEC_MESSAGE_USER_CONTROL_RELEASED == + static_cast(CecMessageType::USER_CONTROL_RELEASED), + "CecMessageType::USER_CONTROL_RELEASED must match legacy value."); +static_assert(CEC_MESSAGE_GIVE_OSD_NAME == static_cast(CecMessageType::GIVE_OSD_NAME), + "CecMessageType::GIVE_OSD_NAME must match legacy value."); +static_assert(CEC_MESSAGE_SET_OSD_NAME == static_cast(CecMessageType::SET_OSD_NAME), + "CecMessageType::SET_OSD_NAME must match legacy value."); +static_assert(CEC_MESSAGE_SYSTEM_AUDIO_MODE_REQUEST == + static_cast(CecMessageType::SYSTEM_AUDIO_MODE_REQUEST), + "CecMessageType::SYSTEM_AUDIO_MODE_REQUEST must match legacy value."); +static_assert(CEC_MESSAGE_GIVE_AUDIO_STATUS == static_cast(CecMessageType::GIVE_AUDIO_STATUS), + "CecMessageType::GIVE_AUDIO_STATUS must match legacy value."); +static_assert(CEC_MESSAGE_SET_SYSTEM_AUDIO_MODE == + static_cast(CecMessageType::SET_SYSTEM_AUDIO_MODE), + "CecMessageType::SET_SYSTEM_AUDIO_MODE must match legacy value."); +static_assert(CEC_MESSAGE_REPORT_AUDIO_STATUS == + static_cast(CecMessageType::REPORT_AUDIO_STATUS), + "CecMessageType::REPORT_AUDIO_STATUS must match legacy value."); +static_assert(CEC_MESSAGE_GIVE_SYSTEM_AUDIO_MODE_STATUS == + static_cast(CecMessageType::GIVE_SYSTEM_AUDIO_MODE_STATUS), + "CecMessageType::GIVE_SYSTEM_AUDIO_MODE_STATUS must match legacy value."); +static_assert(CEC_MESSAGE_SYSTEM_AUDIO_MODE_STATUS == + static_cast(CecMessageType::SYSTEM_AUDIO_MODE_STATUS), + "CecMessageType::SYSTEM_AUDIO_MODE_STATUS must match legacy value."); +static_assert(CEC_MESSAGE_ROUTING_CHANGE == static_cast(CecMessageType::ROUTING_CHANGE), + "CecMessageType::ROUTING_CHANGE must match legacy value."); +static_assert(CEC_MESSAGE_ROUTING_INFORMATION == + static_cast(CecMessageType::ROUTING_INFORMATION), + "CecMessageType::ROUTING_INFORMATION must match legacy value."); +static_assert(CEC_MESSAGE_ACTIVE_SOURCE == static_cast(CecMessageType::ACTIVE_SOURCE), + "CecMessageType::ACTIVE_SOURCE must match legacy value."); +static_assert(CEC_MESSAGE_GIVE_PHYSICAL_ADDRESS == + static_cast(CecMessageType::GIVE_PHYSICAL_ADDRESS), + "CecMessageType::GIVE_PHYSICAL_ADDRESS must match legacy value."); +static_assert(CEC_MESSAGE_REPORT_PHYSICAL_ADDRESS == + static_cast(CecMessageType::REPORT_PHYSICAL_ADDRESS), + "CecMessageType::REPORT_PHYSICAL_ADDRESS must match legacy value."); +static_assert(CEC_MESSAGE_REQUEST_ACTIVE_SOURCE == + static_cast(CecMessageType::REQUEST_ACTIVE_SOURCE), + "CecMessageType::REQUEST_ACTIVE_SOURCE must match legacy value."); +static_assert(CEC_MESSAGE_SET_STREAM_PATH == static_cast(CecMessageType::SET_STREAM_PATH), + "CecMessageType::SET_STREAM_PATH must match legacy value."); +static_assert(CEC_MESSAGE_DEVICE_VENDOR_ID == static_cast(CecMessageType::DEVICE_VENDOR_ID), + "CecMessageType::DEVICE_VENDOR_ID must match legacy value."); +static_assert(CEC_MESSAGE_VENDOR_COMMAND == static_cast(CecMessageType::VENDOR_COMMAND), + "CecMessageType::VENDOR_COMMAND must match legacy value."); +static_assert(CEC_MESSAGE_VENDOR_REMOTE_BUTTON_DOWN == + static_cast(CecMessageType::VENDOR_REMOTE_BUTTON_DOWN), + "CecMessageType::VENDOR_REMOTE_BUTTON_DOWN must match legacy value."); +static_assert(CEC_MESSAGE_VENDOR_REMOTE_BUTTON_UP == + static_cast(CecMessageType::VENDOR_REMOTE_BUTTON_UP), + "CecMessageType::VENDOR_REMOTE_BUTTON_UP must match legacy value."); +static_assert(CEC_MESSAGE_GIVE_DEVICE_VENDOR_ID == + static_cast(CecMessageType::GIVE_DEVICE_VENDOR_ID), + "CecMessageType::GIVE_DEVICE_VENDOR_ID must match legacy value."); +static_assert(CEC_MESSAGE_MENU_REQUEST == static_cast(CecMessageType::MENU_REQUEST), + "CecMessageType::MENU_REQUEST must match legacy value."); +static_assert(CEC_MESSAGE_MENU_STATUS == static_cast(CecMessageType::MENU_STATUS), + "CecMessageType::MENU_STATUS must match legacy value."); +static_assert(CEC_MESSAGE_GIVE_DEVICE_POWER_STATUS == + static_cast(CecMessageType::GIVE_DEVICE_POWER_STATUS), + "CecMessageType::GIVE_DEVICE_POWER_STATUS must match legacy value."); +static_assert(CEC_MESSAGE_REPORT_POWER_STATUS == + static_cast(CecMessageType::REPORT_POWER_STATUS), + "CecMessageType::REPORT_POWER_STATUS must match legacy value."); +static_assert(CEC_MESSAGE_GET_MENU_LANGUAGE == static_cast(CecMessageType::GET_MENU_LANGUAGE), + "CecMessageType::GET_MENU_LANGUAGE must match legacy value."); +static_assert(CEC_MESSAGE_SELECT_ANALOG_SERVICE == + static_cast(CecMessageType::SELECT_ANALOG_SERVICE), + "CecMessageType::SELECT_ANALOG_SERVICE must match legacy value."); +static_assert(CEC_MESSAGE_SELECT_DIGITAL_SERVICE == + static_cast(CecMessageType::SELECT_DIGITAL_SERVICE), + "CecMessageType::SELECT_DIGITAL_SERVICE must match legacy value."); +static_assert(CEC_MESSAGE_SET_DIGITAL_TIMER == static_cast(CecMessageType::SET_DIGITAL_TIMER), + "CecMessageType::SET_DIGITAL_TIMER must match legacy value."); +static_assert(CEC_MESSAGE_CLEAR_DIGITAL_TIMER == + static_cast(CecMessageType::CLEAR_DIGITAL_TIMER), + "CecMessageType::CLEAR_DIGITAL_TIMER must match legacy value."); +static_assert(CEC_MESSAGE_SET_AUDIO_RATE == static_cast(CecMessageType::SET_AUDIO_RATE), + "CecMessageType::SET_AUDIO_RATE must match legacy value."); +static_assert(CEC_MESSAGE_INACTIVE_SOURCE == static_cast(CecMessageType::INACTIVE_SOURCE), + "CecMessageType::INACTIVE_SOURCE must match legacy value."); +static_assert(CEC_MESSAGE_CEC_VERSION == static_cast(CecMessageType::CEC_VERSION), + "CecMessageType::CEC_VERSION must match legacy value."); +static_assert(CEC_MESSAGE_GET_CEC_VERSION == static_cast(CecMessageType::GET_CEC_VERSION), + "CecMessageType::GET_CEC_VERSION must match legacy value."); +static_assert(CEC_MESSAGE_VENDOR_COMMAND_WITH_ID == + static_cast(CecMessageType::VENDOR_COMMAND_WITH_ID), + "CecMessageType::VENDOR_COMMAND_WITH_ID must match legacy value."); +static_assert(CEC_MESSAGE_CLEAR_EXTERNAL_TIMER == + static_cast(CecMessageType::CLEAR_EXTERNAL_TIMER), + "CecMessageType::CLEAR_EXTERNAL_TIMER must match legacy value."); +static_assert(CEC_MESSAGE_SET_EXTERNAL_TIMER == + static_cast(CecMessageType::SET_EXTERNAL_TIMER), + "CecMessageType::SET_EXTERNAL_TIMER must match legacy value."); +static_assert(CEC_MESSAGE_INITIATE_ARC == static_cast(CecMessageType::INITIATE_ARC), + "CecMessageType::INITIATE_ARC must match legacy value."); +static_assert(CEC_MESSAGE_REPORT_ARC_INITIATED == + static_cast(CecMessageType::REPORT_ARC_INITIATED), + "CecMessageType::REPORT_ARC_INITIATED must match legacy value."); +static_assert(CEC_MESSAGE_REPORT_ARC_TERMINATED == + static_cast(CecMessageType::REPORT_ARC_TERMINATED), + "CecMessageType::REPORT_ARC_TERMINATED must match legacy value."); +static_assert(CEC_MESSAGE_REQUEST_ARC_INITIATION == + static_cast(CecMessageType::REQUEST_ARC_INITIATION), + "CecMessageType::REQUEST_ARC_INITIATION must match legacy value."); +static_assert(CEC_MESSAGE_REQUEST_ARC_TERMINATION == + static_cast(CecMessageType::REQUEST_ARC_TERMINATION), + "CecMessageType::REQUEST_ARC_TERMINATION must match legacy value."); +static_assert(CEC_MESSAGE_TERMINATE_ARC == static_cast(CecMessageType::TERMINATE_ARC), + "CecMessageType::TERMINATE_ARC must match legacy value."); +static_assert(CEC_MESSAGE_ABORT == static_cast(CecMessageType::ABORT), + "CecMessageType::ABORT must match legacy value."); + +static_assert(ABORT_UNRECOGNIZED_MODE == static_cast(AbortReason::UNRECOGNIZED_MODE), + "AbortReason::UNRECOGNIZED_MODE must match legacy value."); +static_assert(ABORT_NOT_IN_CORRECT_MODE == static_cast(AbortReason::NOT_IN_CORRECT_MODE), + "AbortReason::NOT_IN_CORRECT_MODE must match legacy value."); +static_assert(ABORT_CANNOT_PROVIDE_SOURCE == static_cast(AbortReason::CANNOT_PROVIDE_SOURCE), + "AbortReason::CANNOT_PROVIDE_SOURCE must match legacy value."); +static_assert(ABORT_INVALID_OPERAND == static_cast(AbortReason::INVALID_OPERAND), + "AbortReason::INVALID_OPERAND must match legacy value."); +static_assert(ABORT_REFUSED == static_cast(AbortReason::REFUSED), + "AbortReason::REFUSED must match legacy value."); +static_assert(ABORT_UNABLE_TO_DETERMINE == static_cast(AbortReason::UNABLE_TO_DETERMINE), + "AbortReason::UNABLE_TO_DETERMINE must match legacy value."); + +static_assert(HDMI_RESULT_SUCCESS == static_cast(SendMessageResult::SUCCESS), + "SendMessageResult::SUCCESS must match legacy value."); +static_assert(HDMI_RESULT_NACK == static_cast(SendMessageResult::NACK), + "SendMessageResult::NACK must match legacy value."); +static_assert(HDMI_RESULT_BUSY == static_cast(SendMessageResult::BUSY), + "SendMessageResult::BUSY must match legacy value."); +static_assert(HDMI_RESULT_FAIL == static_cast(SendMessageResult::FAIL), + "SendMessageResult::FAIL must match legacy value."); + +static_assert(HDMI_INPUT == static_cast(HdmiPortType::INPUT), + "HdmiPortType::INPUT must match legacy value."); +static_assert(HDMI_OUTPUT == static_cast(HdmiPortType::OUTPUT), + "HdmiPortType::OUTPUT must match legacy value."); + +static_assert(HDMI_OPTION_WAKEUP == static_cast(OptionKey::WAKEUP), + "OptionKey::WAKEUP must match legacy value."); +static_assert(HDMI_OPTION_ENABLE_CEC == static_cast(OptionKey::ENABLE_CEC), + "OptionKey::ENABLE_CEC must match legacy value."); +static_assert(HDMI_OPTION_SYSTEM_CEC_CONTROL == static_cast(OptionKey::SYSTEM_CEC_CONTROL), + "OptionKey::SYSTEM_CEC_CONTROL must match legacy value."); + +sp HdmiCec::mCallback = nullptr; + +HdmiCec::HdmiCec(hdmi_cec_device_t* device) : mDevice(device) {} + +// Methods from ::android::hardware::tv::cec::V2_0::IHdmiCec follow. +Return HdmiCec::addDeviceType(CecDeviceType deviceType) { + // TODO implement + if (deviceType <= CecDeviceType::MAX) { + return Result::SUCCESS; + } else { + return Result::FAILURE_INVALID_ARGS; + } +} + +Return HdmiCec::clearDeviceTypes() { + // TODO implement + return Void(); +} + +Return HdmiCec::setAllDeviceTypes(CecAllDeviceTypes allDeviceTypes) { + // TODO implement + if (allDeviceTypes == 1) { + } + return Void(); +} + +Return HdmiCec::setDeviceFeatures(CecDeviceType deviceType, + CecDeviceFeatures /* deviceFeatures */) { + // TODO implement + if (deviceType != CecDeviceType::MAX) { + } + return Void(); +} + +Return HdmiCec::setRcProfile(CecDeviceType deviceType, const CecRcProfile& /* rcProfile */) { + // TODO implement + if (deviceType != CecDeviceType::MAX) { + } + return Void(); +} + +Return HdmiCec::readDeviceInfo(CecLogicalAddress logicalAddress, + CecPhysicalAddress physicalAddress, + const readDeviceInfo_cb _hidl_cb) { + // TODO implement + CecDeviceInfo deviceInfo; + + if (logicalAddress == CecLogicalAddress::TV) { + _hidl_cb(Result::SUCCESS, deviceInfo); + if (physicalAddress) { + } + } + return Void(); +} + +Return HdmiCec::sendMessage(const CecMessage& message) { + cec_message_t legacyMessage{ + .initiator = static_cast(message.initiator), + .destination = static_cast(message.destination), + .length = message.body.size(), + }; + for (size_t i = 0; i < message.body.size(); ++i) { + legacyMessage.body[i] = static_cast(message.body[i]); + } + return static_cast(mDevice->send_message(mDevice, &legacyMessage)); +} + +Return HdmiCec::setCallback(const sp& callback) { + if (mCallback != nullptr) { + mCallback->unlinkToDeath(this); + mCallback = nullptr; + } + + if (callback != nullptr) { + mCallback = callback; + mCallback->linkToDeath(this, 0 /*cookie*/); + mDevice->register_event_callback(mDevice, eventCallback, nullptr); + } + return Void(); +} + +Return HdmiCec::getPortInfo(getPortInfo_cb _hidl_cb) { + struct hdmi_port_info* legacyPorts; + int numPorts; + hidl_vec portInfos; + mDevice->get_port_info(mDevice, &legacyPorts, &numPorts); + portInfos.resize(numPorts); + for (int i = 0; i < numPorts; ++i) { + portInfos[i] = {.type = static_cast(legacyPorts[i].type), + .portId = static_cast(legacyPorts[i].port_id), + .cecSupported = legacyPorts[i].cec_supported != 0, + .arcSupported = legacyPorts[i].arc_supported != 0, + .physicalAddress = legacyPorts[i].physical_address}; + } + _hidl_cb(portInfos); + return Void(); +} + +Return HdmiCec::setOption(OptionKey key, bool value) { + mDevice->set_option(mDevice, static_cast(key), value ? 1 : 0); + return Void(); +} + +Return HdmiCec::setLanguage(const hidl_string& language) { + if (language.size() != 3) { + LOG(ERROR) << "Wrong language code: expected 3 letters, but it was " << language.size() + << "."; + return Void(); + } + const char* languageStr = language.c_str(); + int convertedLanguage = ((languageStr[0] & 0xFF) << 16) | ((languageStr[1] & 0xFF) << 8) | + (languageStr[2] & 0xFF); + mDevice->set_option(mDevice, HDMI_OPTION_SET_LANG, convertedLanguage); + return Void(); +} + +Return HdmiCec::enableAudioReturnChannel(HdmiPortId portId, bool enable) { + mDevice->set_audio_return_channel(mDevice, portId, enable ? 1 : 0); + return Void(); +} + +Return HdmiCec::isConnected(HdmiPortId portId) { + return mDevice->is_connected(mDevice, portId) > 0; +} + +IHdmiCec* HIDL_FETCH_IHdmiCec(const char* hal) { + hdmi_cec_device_t* hdmi_cec_device; + int ret = 0; + const hw_module_t* hw_module = nullptr; + + ret = hw_get_module(HDMI_CEC_HARDWARE_MODULE_ID, &hw_module); + if (ret == 0) { + ret = hdmi_cec_open(hw_module, &hdmi_cec_device); + if (ret != 0) { + LOG(ERROR) << "hdmi_cec_open " << hal << " failed: " << ret; + } + } else { + LOG(ERROR) << "hw_get_module " << hal << " failed: " << ret; + } + + if (ret == 0) { + return new HdmiCec(hdmi_cec_device); + } else { + LOG(ERROR) << "Passthrough failed to load legacy HAL."; + return nullptr; + } +} + +} // namespace implementation +} // namespace V2_0 +} // namespace cec +} // namespace tv +} // namespace hardware +} // namespace android diff --git a/tv/cec/2.0/default/HdmiCec.h b/tv/cec/2.0/default/HdmiCec.h new file mode 100644 index 0000000000..ab5477089f --- /dev/null +++ b/tv/cec/2.0/default/HdmiCec.h @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2019 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_TV_CEC_V2_0_HDMICEC_H +#define ANDROID_HARDWARE_TV_CEC_V2_0_HDMICEC_H + +#include + +#include +#include +#include +#include + +#include +namespace android { +namespace hardware { +namespace tv { +namespace cec { +namespace V2_0 { +namespace implementation { + +using ::android::sp; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::tv::cec::V2_0::CecLogicalAddress; +using ::android::hardware::tv::cec::V2_0::CecMessage; +using ::android::hardware::tv::cec::V2_0::CecPhysicalAddress; +using ::android::hardware::tv::cec::V2_0::HdmiPortId; +using ::android::hardware::tv::cec::V2_0::HdmiPortInfo; +using ::android::hardware::tv::cec::V2_0::IHdmiCec; +using ::android::hardware::tv::cec::V2_0::IHdmiCecCallback; +using ::android::hardware::tv::cec::V2_0::MaxLength; +using ::android::hardware::tv::cec::V2_0::OptionKey; +using ::android::hardware::tv::cec::V2_0::Result; +using ::android::hardware::tv::cec::V2_0::SendMessageResult; + +struct HdmiCec : public IHdmiCec, public hidl_death_recipient { + HdmiCec(hdmi_cec_device_t* device); + // Methods from ::android::hardware::tv::cec::V2_0::IHdmiCec follow. + Return addDeviceType(CecDeviceType deviceType) override; + Return clearDeviceTypes() override; + Return setAllDeviceTypes(CecAllDeviceTypes allDeviceTypes) override; + Return setDeviceFeatures(CecDeviceType deviceType, + CecDeviceFeatures /* deviceFeatures */) override; + Return setRcProfile(CecDeviceType deviceType, + const CecRcProfile& /* rcProfile */) override; + Return readDeviceInfo(CecLogicalAddress logicalAddress, + CecPhysicalAddress physicalAddress, + const readDeviceInfo_cb _hidl_cb) override; + Return sendMessage(const CecMessage& message) override; + Return setCallback(const sp& callback) override; + Return getPortInfo(getPortInfo_cb _hidl_cb) override; + Return setOption(OptionKey key, bool value) override; + Return setLanguage(const hidl_string& language) override; + Return enableAudioReturnChannel(HdmiPortId portId, bool enable) override; + Return isConnected(HdmiPortId portId) override; + + static void eventCallback(const hdmi_event_t* event, void* /* arg */) { + if (mCallback != nullptr && event != nullptr) { + if (event->type == HDMI_EVENT_CEC_MESSAGE) { + size_t length = + std::min(event->cec.length, static_cast(MaxLength::MESSAGE_BODY)); + CecMessage cecMessage{ + .initiator = static_cast(event->cec.initiator), + .destination = static_cast(event->cec.destination), + }; + cecMessage.body.resize(length); + for (size_t i = 0; i < length; ++i) { + cecMessage.body[i] = static_cast(event->cec.body[i]); + } + mCallback->onCecMessage(cecMessage); + } else if (event->type == HDMI_EVENT_HOT_PLUG) { + HotplugEvent hotplugEvent{ + .connected = event->hotplug.connected > 0, + .portId = static_cast(event->hotplug.port_id)}; + mCallback->onHotplugEvent(hotplugEvent); + } + } + } + + virtual void serviceDied(uint64_t /*cookie*/, + const wp<::android::hidl::base::V1_0::IBase>& /*who*/) { + setCallback(nullptr); + } + + private: + static sp mCallback; + const hdmi_cec_device_t* mDevice; +}; + +extern "C" IHdmiCec* HIDL_FETCH_IHdmiCec(const char* name); + +} // namespace implementation +} // namespace V2_0 +} // namespace cec +} // namespace tv +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_TV_CEC_V2_0_HDMICEC_H diff --git a/tv/cec/2.0/default/OWNERS b/tv/cec/2.0/default/OWNERS new file mode 100644 index 0000000000..1b3d095f9c --- /dev/null +++ b/tv/cec/2.0/default/OWNERS @@ -0,0 +1,4 @@ +nchalko@google.com +amyjojo@google.com +shubang@google.com +quxiangfang@google.com diff --git a/tv/cec/2.0/default/android.hardware.tv.cec@2.0-service.rc b/tv/cec/2.0/default/android.hardware.tv.cec@2.0-service.rc new file mode 100644 index 0000000000..1e8cd8052c --- /dev/null +++ b/tv/cec/2.0/default/android.hardware.tv.cec@2.0-service.rc @@ -0,0 +1,4 @@ +service vendor.cec-hal-2-0 /vendor/bin/hw/android.hardware.tv.cec@2.0-service + class hal + user system + group system diff --git a/tv/cec/2.0/default/android.hardware.tv.cec@2.0-service.xml b/tv/cec/2.0/default/android.hardware.tv.cec@2.0-service.xml new file mode 100644 index 0000000000..61fb1bbf9b --- /dev/null +++ b/tv/cec/2.0/default/android.hardware.tv.cec@2.0-service.xml @@ -0,0 +1,11 @@ + + + android.hardware.tv.cec + hwbinder + 2.0 + + IHdmiCec + default + + + diff --git a/tv/cec/2.0/default/service.cpp b/tv/cec/2.0/default/service.cpp new file mode 100644 index 0000000000..dacc38cc9d --- /dev/null +++ b/tv/cec/2.0/default/service.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "android.hardware.tv.cec@2.0-service" + +#include +#include + +using android::hardware::defaultPassthroughServiceImplementation; +using android::hardware::tv::cec::V2_0::IHdmiCec; + +int main() { + return defaultPassthroughServiceImplementation(); +} diff --git a/tv/cec/2.0/types.hal b/tv/cec/2.0/types.hal new file mode 100644 index 0000000000..cad6c396e9 --- /dev/null +++ b/tv/cec/2.0/types.hal @@ -0,0 +1,548 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.tv.cec@2.0; + +import android.hidl.safe_union@1.0; + +/** + * CEC device type as specified in CEC Table 11-7 of the CEC spec 2.0b. + */ +enum CecDeviceType : int32_t { + INACTIVE = -1, + TV = 0, + RECORDER = 1, + TUNER = 3, + PLAYBACK = 4, + AUDIO_SYSTEM = 5, + PURE_CEC_SWITCH = 6, + PROCESSOR = 7, + MAX = PROCESSOR, +}; + +/** + * CEC logical address as specified in CEC Table 11-9 of the CEC spec 2.0b. + */ +enum CecLogicalAddress : int32_t { + TV = 0, + RECORDER_1 = 1, + RECORDER_2 = 2, + TUNER_1 = 3, + PLAYBACK_1 = 4, + AUDIO_SYSTEM = 5, + TUNER_2 = 6, + TUNER_3 = 7, + PLAYBACK_2 = 8, + RECORDER_3 = 9, + TUNER_4 = 10, + PLAYBACK_3 = 11, + BACKUP_1 = 12, // backup1 for Playback/Recording/Tuner/Processor device + BACKUP_2 = 13, // backup2 for Playback/Recording/Tuner/Processor device + SPECIFIC_USE = 14, + UNREGISTERED = 15, // as Initiator address + BROADCAST = 15, // as Destination address +}; + +/** + * HDMI CEC message types. + * + * The assigned values represent opcode used in CEC frame as specified in + * Section 11.10 of the CEC spec 2.0b on top of Section CEC 15 of the CEC + * Spec 1.4b. + */ +enum CecMessageType : int32_t { + FEATURE_ABORT = 0x00, + IMAGE_VIEW_ON = 0x04, + TUNER_STEP_INCREMENT = 0x05, + TUNER_STEP_DECREMENT = 0x06, + TUNER_DEVICE_STATUS = 0x07, + GIVE_TUNER_DEVICE_STATUS = 0x08, + RECORD_ON = 0x09, + RECORD_STATUS = 0x0A, + RECORD_OFF = 0x0B, + TEXT_VIEW_ON = 0x0D, + RECORD_TV_SCREEN = 0x0F, + GIVE_DECK_STATUS = 0x1A, + DECK_STATUS = 0x1B, + SET_MENU_LANGUAGE = 0x32, + CLEAR_ANALOG_TIMER = 0x33, + SET_ANALOG_TIMER = 0x34, + TIMER_STATUS = 0x35, + STANDBY = 0x36, + PLAY = 0x41, + DECK_CONTROL = 0x42, + TIMER_CLEARED_STATUS = 0x43, + USER_CONTROL_PRESSED = 0x44, + USER_CONTROL_RELEASED = 0x45, + GIVE_OSD_NAME = 0x46, + SET_OSD_NAME = 0x47, + SET_OSD_STRING = 0x64, + SET_TIMER_PROGRAM_TITLE = 0x67, + SYSTEM_AUDIO_MODE_REQUEST = 0x70, + GIVE_AUDIO_STATUS = 0x71, + SET_SYSTEM_AUDIO_MODE = 0x72, + REPORT_AUDIO_STATUS = 0x7A, + GIVE_SYSTEM_AUDIO_MODE_STATUS = 0x7D, + SYSTEM_AUDIO_MODE_STATUS = 0x7E, + ROUTING_CHANGE = 0x80, + ROUTING_INFORMATION = 0x81, + ACTIVE_SOURCE = 0x82, + GIVE_PHYSICAL_ADDRESS = 0x83, + REPORT_PHYSICAL_ADDRESS = 0x84, + REQUEST_ACTIVE_SOURCE = 0x85, + SET_STREAM_PATH = 0x86, + DEVICE_VENDOR_ID = 0x87, + VENDOR_COMMAND = 0x89, + VENDOR_REMOTE_BUTTON_DOWN = 0x8A, + VENDOR_REMOTE_BUTTON_UP = 0x8B, + GIVE_DEVICE_VENDOR_ID = 0x8C, + MENU_REQUEST = 0x8D, + MENU_STATUS = 0x8E, + GIVE_DEVICE_POWER_STATUS = 0x8F, + REPORT_POWER_STATUS = 0x90, + GET_MENU_LANGUAGE = 0x91, + SELECT_ANALOG_SERVICE = 0x92, + SELECT_DIGITAL_SERVICE = 0x93, + SET_DIGITAL_TIMER = 0x97, + CLEAR_DIGITAL_TIMER = 0x99, + SET_AUDIO_RATE = 0x9A, + INACTIVE_SOURCE = 0x9D, + CEC_VERSION = 0x9E, + GET_CEC_VERSION = 0x9F, + VENDOR_COMMAND_WITH_ID = 0xA0, + CLEAR_EXTERNAL_TIMER = 0xA1, + SET_EXTERNAL_TIMER = 0xA2, + REPORT_SHORT_AUDIO_DESCRIPTOR = 0xA3, + REQUEST_SHORT_AUDIO_DESCRIPTOR = 0xA4, + GIVE_FEATURES = 0XA5, + REPORT_FEATURES = 0xA6, + REQUEST_CURRENT_LATENCY = 0xA7, + REPORT_CURRENT_LATENCY = 0xA8, + INITIATE_ARC = 0xC0, + REPORT_ARC_INITIATED = 0xC1, + REPORT_ARC_TERMINATED = 0xC2, + REQUEST_ARC_INITIATION = 0xC3, + REQUEST_ARC_TERMINATION = 0xC4, + TERMINATE_ARC = 0xC5, + ABORT = 0xFF, + POLLING_MESSAGE = 0xFFFFFF00, // used for cec polling message +}; + +/** + * Abort Reason as specified in CEC Table 29 of the CEC spec 1.4b. + */ +enum AbortReason : int32_t { + UNRECOGNIZED_MODE = 0, + NOT_IN_CORRECT_MODE = 1, + CANNOT_PROVIDE_SOURCE = 2, + INVALID_OPERAND = 3, + REFUSED = 4, + UNABLE_TO_DETERMINE = 5, +}; + +enum MaxLength : int32_t { + MESSAGE_BODY = 14, +}; + +struct CecMessage { + /** logical address of sender */ + CecLogicalAddress initiator; + + /** logical address of receiver */ + CecLogicalAddress destination; + + /** cec message type */ + CecMessageType cecMessageType; + + /** + * The maximum size of body is 14 (MaxLength::MESSAGE_BODY) as specified in + * the section 6 of the CEC Spec 1.4b. Overflowed data must be ignored. + */ + vec body; +}; + +/** + * error code used for send_message. + */ +enum SendMessageResult : int32_t { + SUCCESS = 0, + NACK = 1, // not acknowledged + BUSY = 2, // bus is busy + FAIL = 3, +}; + +/** + * CEC All Device Type Value as specified in Table 11-30 of the CEC spec 2.0b. + */ +enum CecAllDeviceTypeValue : uint8_t { + RESERVED_DEVICE_2 = 1 << 0, + RESERVED_DEVICE_1 = 1 << 1, + CEC_SWITCH_DEVICE = 1 << 2, + AUDIO_DEVICE = 1 << 3, + PLAYBACK_DEVICE = 1 << 4, + TUNER_DEVICE = 1 << 5, + RECORDING_DEVICE = 1 << 6, + TV_DEVICE = 1 << 7, +}; + +/** + * CEC All Device Types + * + * It is a combination of all supported type from CecAllDeviceTypeValue. + * For example a record with tuner functionalitye, + * cecAllDeviceTypes = ((CecAllDeviceTypeValue::RECORDING_DEVICE) + * |(CecAllDeviceTypeValue::TUNER_DEVICE)) + */ +typedef bitfield CecAllDeviceTypes; + +/** + * CEC Versions as specified in CEC Table 11-30 of the CEC spec 2.0b. + */ +enum CecVersion : int32_t { + V_1_3_A = 0x04, + V_1_4 = 0x05, // indicate CEC 1.4, 1.4a or 1.4b + V_2_0 = 0x06, +}; + +/** + * Device Feature + * + * It is specified in CEC Table 11-30 of the CEC spec 2.0b. As a uint32 there + * is room for future extensions aka DeviceFeature2 through DeviceFeature4. + */ +enum CecDeviceFeature : uint32_t { + RESERVED = 1 << 0, + SOURCE_SUPPORT_ARC_RX = 1 << 1, + SINK_SUPPORT_ARC_TX = 1 << 2, + SOURCE_SUPPORT_SET_AUDIO_RATE = 1 << 3, + SUPPORT_CONTROLLED_BY_DECK = 1 << 4, + TV_SUPPORT_SET_OSD_STRINGS = 1 << 5, + TV_SUPPORT_RECORD_TV_SCREEN = 1 << 6, +}; + +/** + * CEC Device Features + * + * It is a combination of all supported features from CecDeviceFeature. + * For example a TV with OSD and ARC capabilities, + * CecDeviceFeatures = ((CecDeviceFeature::TV_SUPPORT_SET_OSD_STRINGS) + * |(CecDeviceFeature::SINK_SUPPORT_ARC_TX)) + */ +typedef bitfield CecDeviceFeatures; + +/** + * Remote Control Profile + * + * It is specified in CEC Table 11-30 of the CEC spec 2.0b. + */ +enum CecRcProfileId : uint8_t { + NONE = 0, // TV doesn’t support any of these profiles + RC_PROFILE_1 = 0x02, // minimalistic zapper (low button count) + RC_PROFILE_2 = 0x06, // intermediate between profile 1 and profile 3 + RC_PROFILE_3 = 0x0A, // typical TV remote + RC_PROFILE_4 = 0x0E, // extended form of profile 3 +}; + +/** + * Remote Control Profile Source + * + * It is specified in CEC Table 11-30 of the CEC spec 2.0b. + */ +enum CecRcProfileSource : uint8_t { + MEDIA_CONTEXT_SENSITIVE = 1 << 0, // source can handle UI command 0x11 + MEDIA_TO = 1 << 1, // source can handle UI command 0x10 + CONTENTS = 1 << 2, // source can handle UI command 0x0B + DEVICE_SETUP = 1 << 3, // source can handle UI command 0x0A + DEVICE_ROOT = 1 << 4, // source can handle UI command 0x09 + SOURCE_FLAG = 1 << 6, // Indicate the profile is for source +}; + +/** + * Remote Control Profile for either TV or Source. + */ +safe_union CecRcProfile1 { + /** CEC remote control profile for TV. */ + CecRcProfileId profileId; + + /* CEC remote control profile for source + * + * It is a combination of all supported profiles from CecRcProfileSource. + * For example a playback device support root menu and setup menu, + * profileSource = ((CecRcProfileSource::DEVICE_ROOT) + * |(CecRcProfileSource::DEVICE_SETUP) + * |(CecRcProfileSource::SOURCE_FLAG)) + */ + bitfield profileSource; +}; + +/** + * CEC Remote Control Profiles + * + * CEC 2.0 only use one byte to represent Remote Control Profile. + */ +struct CecRcProfile { + CecRcProfile1 rcProfile1; +}; + +/** + * CEC device power states as specified in CEC Table 11-10 of the CEC spec 2.0b + */ +enum CecPowerState : int8_t { + ON = 0, + STANDBY = 1, + ON_TO_STANDBY = 2, + STANDBY_TO_ON = 4, + UNKNOWN = 0xFF, // some devices may not report power status +}; + +/** CEC physical address of device */ +typedef uint16_t CecPhysicalAddress; + +/** + * CEC device information + * + * It is initially built during addressing specified in CEC section 11.3 of + * the CEC spec 2.0b. It may be updated with cec devices's status changed. + */ +struct CecDeviceInfo { + /** CEC version which device supports */ + CecVersion version; + + /** CEC device primary type */ + CecDeviceType devceType; + + /** CEC all device types */ + CecAllDeviceTypes allDeviceTypes; + + /** CEC device features */ + CecDeviceFeatures deviceFeatures; + + /** CEC Device Remote Control Profile */ + CecRcProfile rcProfile; + + /** CEC Device Vendor ID */ + uint32_t vendorId; + + /** logical address of device */ + CecLogicalAddress logicalAddress; + + /** physical of device */ + CecPhysicalAddress physicalAddress; + + /** power status of device */ + CecPowerState powerState; +}; + +/** + * Topology Event Type. + */ +enum CecTopologyEventType : int32_t { + DEVICE_ADDED, + DEVICE_REMOVED, + DEVICE_UPDATED, +}; + +/** + * Topology Event. + */ +struct CecTopologyEvent { + CecTopologyEventType eventType; + CecLogicalAddress logicalAddress; + CecPhysicalAddress physicalAddress; + + /** true if the event is about the device which the system run on */ + bool isHostDevice; +}; + + +/** + * CEC UI Command Codes as specified in CEC Table 11-31 of the CEC spec 2.0b + */ +enum CecUICommandCodes : int32_t { + SELECT_OK = 0x00, + UP = 0x01, + DOWN = 0x02, + LEFT = 0x03, + RIGHT = 0x04, + RIGHT_UP = 0x05, + RIGHT_DOWN = 0x06, + LEFT_UP = 0x07, + LEFT_DOWN = 0x08, + DEVICE_ROOT_MENU = 0x09, + DEVICE_SETUP_MENU = 0x0A, + CONTENTS_MENU = 0x0B, + FAVORITE_MENU = 0x0C, + BACK = 0x0D, + MEDIA_TOP_MENU = 0x10, + MEDIA_CONTEXT_SENSITIVE_MENU = 0x11, + NUMBER_ENTRY_MODE = 0x1D, + NUMBER_11 = 0x1E, + NUMBER_12 = 0x1F, + NUMBER_0 = 0x20, // or NUMBER 10 + NUMBER_1 = 0x21, + NUMBER_2 = 0x22, + NUMBER_3 = 0x23, + NUMBER_4 = 0x24, + NUMBER_5 = 0x25, + NUMBER_6 = 0x26, + NUMBER_7 = 0x27, + NUMBER_8 = 0x28, + NUMBER_9 = 0x29, + DOT = 0x2A, + ENTER = 0x2B, + CLEAR = 0x2C, + NEXT_FAVORITE = 0x2F, + CHANNEL_UP = 0x30, + CHANNEL_DOWN = 0x31, + PREVIOUS_CHANNEL = 0x32, + SOUND_SELECT = 0x33, + INPUT_SELECT = 0x34, + DISPLAY_INFORMATION = 0x35, + HELP = 0x36, + PAGE_UP = 0x37, + PAGE_DOWN = 0x38, + POWER = 0x40, + VOLUME_UP = 0x41, + VOLUME_DOWN = 0x42, + MUTE = 0x43, + PLAY = 0x44, + STOP = 0x45, + PAUSE = 0x46, + RECORD = 0x47, + REWIND = 0x48, + FAST_FORWARD = 0x49, + EJECT = 0x4A, + SKIP_FORWARD = 0x4B, + SKIP_BACKWARD = 0x4C, + STOP_RECORD = 0x4D, + PAUSE_RECORD = 0x4E, + ANGLE = 0x50, + SUB_PICTURE = 0x51, + VIDEO_ON_DEMAND = 0x52, + ELECTRONIC_PROGRAM_GUIDE = 0x53, + TIMER_PROGRAMMING = 0x54, + INITIAL_CONFIGURATION = 0x55, + SELECT_BROADCAST_TYPE = 0x56, + SELECT_SOUND_PRESENTATION = 0x57, + AUDIO_DESCRIPTION = 0x58, + INTERNET = 0x59, + THREE_DIMENSIONAL_MODE = 0x5A, + PLAY_FUNCTION = 0x60, + PAUSE_PLAY_FUNCTION = 0x61, + RECORD_FUNCTION = 0x62, + PAUSE_RECORD_FUNCTION = 0x63, + STOP_FUNCTION = 0x64, + MUTE_FUNCTION = 0x65, + RESTORE_VOLUME_FUNCTION = 0x66, + TUNE_FUNCTION = 0x67, + SELECT_MEDIA_FUNCTION = 0x68, + SELECT_AV_INPUT_FUNCTION = 0x69, + SELECT_AUDIO_INPUT_FUNCTION = 0x6A, + POWER_TOGGLE_FUNCTION = 0x6B, + POWER_OFF_FUNCTION = 0x6C, + POWER_ON_FUNCTION = 0x6D, + F1 = 0x71, // BLUE + F2 = 0x72, // RED + F3 = 0x73, // GREEN + F4 = 0x74, // YELLOW + F5 = 0x75, + DATA = 0x76, +}; + +/** + * HDMI port type. + */ +enum HdmiPortType : int32_t { + INPUT = 0, + OUTPUT = 1, +}; + +/** + * Options used for IHdmiCec.setOption() + */ +enum OptionKey : int32_t { + /** + * When set to false, HAL does not wake up the system upon receiving or . Used when user changes the TV settings to + * disable the auto TV on functionality. + * Deprecated since and become mandatory + * featrues for CEC device. Use ENABLE_CEC OptionKey to disable CEC + * functionality instead. + * True by Default + */ + WAKEUP = 1, + + /** + * When set to false, all the CEC commands are discarded. if logical address + * is ever used, it shall be released. Used when user changes the TV + * settings to disable CEC functionality. + * True by default. + * + */ + ENABLE_CEC = 2, + + /** + * Setting this flag to false means Android system must stop handling CEC + * service and yield the control over to the microprocessor that is powered + * on through the standby mode.The microprocessor shall keep current logical + * and physical address. It shall response POLLING_MESSAGE, GIVE_FEATURES, + * GIVE_DEVICE_POWER_STATUS,GIVE_DEVICE_VENDOR_ID and GIVE_PHYSICAL_ADDRESS + * to allow other CEC devices to build CEC devices map specified in CEC + * section 11.3 of the CEC spec 2.0b. + * When set to true, the system must gain the control over, hence telling + * the microprocessor to start forwarding CEC messages to Android system. + * For example, this may be called when system goes in and out of + * standby mode to notify the microprocessor that it should start/stop + * handling CEC commands on behalf of the system. + * True by default. + */ + SYSTEM_CEC_CONTROL = 3, + + /* Option 4 not used */ +}; + +/** + * Hdmi port ID. + * + * It shall start from 1 which corresponds to HDMI "port 1". + */ +typedef uint32_t HdmiPortId; + +/** Hdmi hotplug event */ +struct HotplugEvent { + bool connected; + HdmiPortId portId; +}; + +/** + * HDMI port descriptor + */ +struct HdmiPortInfo { + HdmiPortType type; + HdmiPortId portId; + bool cecSupported; + bool arcSupported; + CecPhysicalAddress physicalAddress; +}; + +enum Result : int32_t { + SUCCESS = 0, + FAILURE_UNKNOWN = 1, + FAILURE_INVALID_ARGS = 2, + FAILURE_INVALID_STATE = 3, + FAILURE_NOT_SUPPORTED = 4, + FAILURE_BUSY = 5, +}; From 7e91e24fe155de15c677c48ca5a2c141ba2246dc Mon Sep 17 00:00:00 2001 From: Michael Butler Date: Tue, 15 Jan 2019 10:52:41 -0800 Subject: [PATCH 402/718] NNAPI Burst -- HAL interface FastMessageQueue is a Treble-compliant data structure that enables fast communication between two processes. The FMQ object itself is an atomic circular buffer that is optionally synchronized with a futex. However, FMQ has no notion of ownership or lifetime across processes, so it must be paired with higher-level constructs to manage the lifetime and ownership. The NNAPI is introducing the notion of an "Execution Burst" object (or more simply a "Burst" object), which is similar to an ANeuralNetworksExecution, but is intended to be reused across multiple executions and has lower IPC overheads. It achieves this low IPC overhead by replacing HIDL HwBinder calls with FMQ messages. Specifically, it replaces IPreparedModel::executeSynchronously's call from the client into the service with fmq_sync (an FMQ channel used to pass a serialized Request object) and it replaces the return from the service into the client with fmq_sync (an FMQ channel used to return serialized result status and OutputShapes information). Each channel is a unidirectional flow of information with exactly one producer and exactly one consumer. The channels are created by the NN runtime and passed to the service via IPreparedModel::configureExecutionBurst. This CL defines the FmqRequestDatum and FmqResultDatum types in types.hal. IBurstContext.hal defines IBurstContext, a HIDL object used by the service to manage the resources of a Burst. IBurstCallback.hal defines IBurstCallback, a HIDL callback object that can be used to retrieve the handle to a resource the service has either not yet seen or has evicted from its cache. Finally, IPreparedModel.hal is extended with IPreparedModel::configureExecutionBurst to create the burst object. Bug: 119570067 Test: mma Change-Id: I333da70201531b1396efc714d096c277e8e1d47b --- neuralnetworks/1.2/Android.bp | 6 + neuralnetworks/1.2/IBurstCallback.hal | 41 ++++++ neuralnetworks/1.2/IBurstContext.hal | 32 +++++ neuralnetworks/1.2/IPreparedModel.hal | 32 +++++ neuralnetworks/1.2/types.hal | 193 ++++++++++++++++++++++++++ 5 files changed, 304 insertions(+) create mode 100644 neuralnetworks/1.2/IBurstCallback.hal create mode 100644 neuralnetworks/1.2/IBurstContext.hal diff --git a/neuralnetworks/1.2/Android.bp b/neuralnetworks/1.2/Android.bp index d8762b093c..9057b9423b 100644 --- a/neuralnetworks/1.2/Android.bp +++ b/neuralnetworks/1.2/Android.bp @@ -8,6 +8,8 @@ hidl_interface { }, srcs: [ "types.hal", + "IBurstCallback.hal", + "IBurstContext.hal", "IDevice.hal", "IExecutionCallback.hal", "IPreparedModel.hal", @@ -20,6 +22,9 @@ hidl_interface { "android.hidl.safe_union@1.0", ], types: [ + "DeviceType", + "FmqRequestDatum", + "FmqResultDatum", "Model", "Operand", "OperandType", @@ -28,6 +33,7 @@ hidl_interface { "OperationType", "OperationTypeRange", "OutputShape", + "SymmPerChannelQuantParams", ], gen_java: false, } diff --git a/neuralnetworks/1.2/IBurstCallback.hal b/neuralnetworks/1.2/IBurstCallback.hal new file mode 100644 index 0000000000..3f82e3152b --- /dev/null +++ b/neuralnetworks/1.2/IBurstCallback.hal @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.neuralnetworks@1.2; + +import @1.0::ErrorStatus; + +/** + * Callback object used by a service to retreive memory objects based on unique + * identifiers ("slots"). + */ +interface IBurstCallback { + /** + * Get the memory regions that correspond to slot ids. The slot ids are are + * unique to the burst object. + * + * @param slots Values uniquely identifying memory regions within a Burst. + * @return status Indicates whether the memories were successfully returned; + * must be: + * - NONE if the memory region was successfully retrieved + * - GENERAL_FAILURE if there is an unspecified error + * - INVALID_ARGUMENT if a slot number is invalid + * @return buffers Memory buffers corresponding to the slot numbers. If an + * error occurs, an empty vector must be returned for + * buffers, otherwise slots.size() == buffers.size(). + */ + getMemories(vec slots) generates (ErrorStatus status, vec buffers); +}; diff --git a/neuralnetworks/1.2/IBurstContext.hal b/neuralnetworks/1.2/IBurstContext.hal new file mode 100644 index 0000000000..60bf53b1de --- /dev/null +++ b/neuralnetworks/1.2/IBurstContext.hal @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.neuralnetworks@1.2; + +/** + * Context object to manage the resources of a burst. + */ +interface IBurstContext { + /** + * freeMemory is used by the client to signal to the service that a memory + * buffer corresponding to a slot number is no longer needed by the client. + * + * The slot ids are unique to the burst object. + * + * @param slot Value uniquely identifying a memory region. + */ + freeMemory(int32_t slot); +}; diff --git a/neuralnetworks/1.2/IPreparedModel.hal b/neuralnetworks/1.2/IPreparedModel.hal index 044ca289b9..2d4e572333 100644 --- a/neuralnetworks/1.2/IPreparedModel.hal +++ b/neuralnetworks/1.2/IPreparedModel.hal @@ -19,6 +19,8 @@ package android.hardware.neuralnetworks@1.2; import @1.0::ErrorStatus; import @1.0::IPreparedModel; import @1.0::Request; +import IBurstCallback; +import IBurstContext; import IExecutionCallback; /** @@ -113,4 +115,34 @@ interface IPreparedModel extends @1.0::IPreparedModel { */ executeSynchronously(Request request) generates (ErrorStatus status, vec outputShapes); + + /** + * Configure a Burst object used to execute multiple inferences on a + * prepared model in rapid succession. + * + * @param callback A callback object used to retrieve memory resources + * corresponding to a unique identifiers ("slots"). + * @param requestChannel Used by the client to send a serialized Request to + * the Burst for execution. requestChannel must not be + * used to pass a second Request object until a result + * has been received from resultChannel. + * @param resultChannel Used by the service to return the results of an + * execution to the client: the status of the execution + * and OutputShape of all output tensors. resultChannel + * must be used to return the results if a Request was + * sent through the requestChannel. + * @return status Error status of configuring the execution burst, must be: + * - NONE if the burst is successfully configured + * - DEVICE_UNAVAILABLE if driver is offline or busy + * - GENERAL_FAILURE if there is an unspecified error + * - INVALID_ARGUMENT if one of the input arguments is + * invalid + * @return context Object containing all resources (such as cached + * hidl_memory) related to a Burst if successful, otherwise + * nullptr. + */ + configureExecutionBurst(IBurstCallback callback, + fmq_sync requestChannel, + fmq_sync resultChannel) + generates (ErrorStatus status, IBurstContext context); }; diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal index ac944c8e56..ce993d71a9 100644 --- a/neuralnetworks/1.2/types.hal +++ b/neuralnetworks/1.2/types.hal @@ -17,6 +17,7 @@ package android.hardware.neuralnetworks@1.2; import @1.0::DataLocation; +import @1.0::ErrorStatus; import @1.0::OperandLifeTime; import @1.0::OperandType; import @1.0::PerformanceInfo; @@ -444,3 +445,195 @@ struct OutputShape { */ bool isSufficient; }; + +/** + * FmqRequestDatum is a single element of a serialized representation of a + * {@link @1.0::Request} object which is sent across FastMessageQueue. + * + * The serialized representation for a particular execution is referred to later + * in these descriptions as a 'packet'. + * + * FastMessageQueue can only pass HIDL-defined types that do not involve nested + * buffers, handles, or interfaces. + * + * The {@link @1.0::Request} is serialized as follows: + * 1) 'packetInformation' + * 2) For each input operand: + * 2.1) 'inputOperandInformation' + * 2.2) For each dimension element of the operand: + * 2.2.1) 'inputOperandDimensionValue' + * 3) For each output operand: + * 3.1) 'outputOperandInformation' + * 3.2) For each dimension element of the operand: + * 3.2.1) 'outputOperandDimensionValue' + * 4) For each pool: + * 4.1) 'poolIdentifier' + */ +safe_union FmqRequestDatum { + /** + * Type to describe the high-level layout of the packet. + */ + struct PacketInformation { + /** + * How many elements the packet contains, including the + * "packetInformation" datum. + */ + uint32_t packetSize; + + /** + * Number of input operands. + */ + uint32_t numberOfInputOperands; + + /** + * Number of output operands. + */ + uint32_t numberOfOutputOperands; + + /** + * Number of pool identifiers. + */ + uint32_t numberOfPools; + }; + + /** + * Type representing the information for each operand. + */ + struct OperandInformation { + /** + * If true, the argument does not have a value. This can be used for + * operations that take optional arguments. If true, the fields of + * 'location' are set to 0, 'numberOfDimensions' is set to 0, and the + * dimensions information is omitted from the serialization. + */ + bool hasNoValue; + + /** + * The location within one of the memory pools passed in the Request. + */ + DataLocation location; + + /** + * Number of subsequent elements that belong to the dimensions vector. + */ + uint32_t numberOfDimensions; + }; + + /** + * packetInformation is the first element of the packet and describes the + * remainder of the packet. + */ + PacketInformation packetInformation; + + /** + * Information for each input operand. + */ + OperandInformation inputOperandInformation; + + /** + * Element of the dimensions vector. + */ + uint32_t inputOperandDimensionValue; + + /** + * Information for each output operand. + */ + OperandInformation outputOperandInformation; + + /** + * Element of the dimensions vector. + */ + uint32_t outputOperandDimensionValue; + + /** + * Unique identifier for a pool. + * + * A {@link @1.0::Request} passes across one or more pools of shared memory + * for the inputs and outputs of an execution. However, these memory pools + * are not able to be sent across FastMessageQueue directly. Instead, the + * producing side of the FMQ represents each different pool with a unique + * identifier, and sends this identifier across the FMQ. Whenever the + * consuming side of the FMQ needs the memory corresponding to this unique + * identifier, it can pass the identifier to + * {@link IBurstCallback::getMemories} to retreive the memory. Although this + * HIDL Binder call is expensive compared to communication across FMQ, it is + * only needed in the cases when the consumer does not recognize the unique + * identifier. + */ + int32_t poolIdentifier; +}; + +/** + * FmqResultDatum is a single element of a serialized representation of the + * values returned from an execution ({@link @1.0::ErrorStatus} and + * vec<{@link OutputShape}>) which is returned via FastMessageQueue. + * + * The serialized representation for a particular execution is referred to later + * in these descriptions as a 'packet'. + * + * FastMessageQueue can only pass HIDL-defined types that do not involve nested + * buffers, handles, or interfaces. + * + * The execution return values ({@link @1.0::ErrorStatus} and + * vec<{@link OutputShape}>) are serialized as follows: + * 1) 'packetInformation' + * 2) For each returned operand: + * 2.1) 'operandInformation' + * 2.2) For each dimension element of the operand: + * 2.2.1) 'operandDimensionValue' + */ +safe_union FmqResultDatum { + /** + * Type to describe the high-level layout of the packet. + */ + struct PacketInformation { + /** + * How many elements the packet contains, including the + * "packetInformation" datum. + */ + uint32_t packetSize; + + /** + * Status of the execution. + */ + ErrorStatus errorStatus; + + /** + * Number of returned operands. + */ + uint32_t numberOfOperands; + }; + + /** + * Type representing the information for each operand. + */ + struct OperandInformation { + /** + * Indicates whether the operand's output buffer is large enough to + * store the operand's result data. + */ + bool isSufficient; + + /** + * Number of subsequent elements that belong to the dimensions vector. + */ + uint32_t numberOfDimensions; + }; + + /** + * packetInformation is the first element of the packet and describes the + * remainder of the packet. It additionally includes the status of the + * execution. + */ + PacketInformation packetInformation; + + /** + * Information for each returned operand. + */ + OperandInformation operandInformation; + + /** + * Element of the dimensions vector. + */ + uint32_t operandDimensionValue; +}; From 02b66cd6fca2ee680a9a287cc84f22c294514b79 Mon Sep 17 00:00:00 2001 From: Les Lee Date: Thu, 17 Jan 2019 16:12:14 +0800 Subject: [PATCH 403/718] hostapd: add vts testcase for hostapd 1.1 Bug: 113799562 Test: build - make vts Test: atest VtsHalWifiHostapdV1_1Target / atest VtsHalWifiHostapdV1_0Target Test: vts-tradefed run commandAndExit vts-hal --skip-all-system-status-check \ --primary-abi-only --skip-preconditions --module \ VtsHalWifiHostapdV1_0Target -l INFO vts-tradefed run commandAndExit vts-hal --skip-all-system-status-check \ --primary-abi-only --skip-preconditions --module \ VtsHalWifiHostapdV1_1Target -l INFO Change-Id: I4b7badc8c123f18c34d47fdc2b4db4e05b7387a8 --- wifi/hostapd/1.0/vts/OWNERS | 2 + wifi/hostapd/1.1/vts/OWNERS | 2 + wifi/hostapd/1.1/vts/functional/Android.bp | 58 ++++++++++++++++ .../VtsHalWifiHostapdV1_1TargetTest.cpp | 51 ++++++++++++++ .../1.1/vts/functional/hostapd_hidl_test.cpp | 67 +++++++++++++++++++ .../hostapd_hidl_test_utils_1_1.cpp | 26 +++++++ .../functional/hostapd_hidl_test_utils_1_1.h | 30 +++++++++ 7 files changed, 236 insertions(+) create mode 100644 wifi/hostapd/1.0/vts/OWNERS create mode 100644 wifi/hostapd/1.1/vts/OWNERS create mode 100644 wifi/hostapd/1.1/vts/functional/Android.bp create mode 100644 wifi/hostapd/1.1/vts/functional/VtsHalWifiHostapdV1_1TargetTest.cpp create mode 100644 wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp create mode 100644 wifi/hostapd/1.1/vts/functional/hostapd_hidl_test_utils_1_1.cpp create mode 100644 wifi/hostapd/1.1/vts/functional/hostapd_hidl_test_utils_1_1.h diff --git a/wifi/hostapd/1.0/vts/OWNERS b/wifi/hostapd/1.0/vts/OWNERS new file mode 100644 index 0000000000..8bfb14882c --- /dev/null +++ b/wifi/hostapd/1.0/vts/OWNERS @@ -0,0 +1,2 @@ +rpius@google.com +etancohen@google.com diff --git a/wifi/hostapd/1.1/vts/OWNERS b/wifi/hostapd/1.1/vts/OWNERS new file mode 100644 index 0000000000..8bfb14882c --- /dev/null +++ b/wifi/hostapd/1.1/vts/OWNERS @@ -0,0 +1,2 @@ +rpius@google.com +etancohen@google.com diff --git a/wifi/hostapd/1.1/vts/functional/Android.bp b/wifi/hostapd/1.1/vts/functional/Android.bp new file mode 100644 index 0000000000..bbf5246cee --- /dev/null +++ b/wifi/hostapd/1.1/vts/functional/Android.bp @@ -0,0 +1,58 @@ +// +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +cc_library_static { + name: "VtsHalWifiHostapdV1_1TargetTestUtil", + defaults: ["VtsHalTargetTestDefaults"], + srcs: ["hostapd_hidl_test_utils_1_1.cpp"], + export_include_dirs: [ + "." + ], + static_libs: [ + "VtsHalWifiV1_0TargetTestUtil", + "VtsHalWifiHostapdV1_0TargetTestUtil", + "android.hardware.wifi.hostapd@1.0", + "android.hardware.wifi.hostapd@1.1", + "android.hardware.wifi@1.0", + "libcrypto", + "libgmock", + "libwifi-system", + "libwifi-system-iface", + ], +} + +cc_test { + name: "VtsHalWifiHostapdV1_1TargetTest", + defaults: ["VtsHalTargetTestDefaults"], + srcs: [ + "VtsHalWifiHostapdV1_1TargetTest.cpp", + "hostapd_hidl_test.cpp", + ], + static_libs: [ + "VtsHalWifiV1_0TargetTestUtil", + "VtsHalWifiHostapdV1_0TargetTestUtil", + "VtsHalWifiHostapdV1_1TargetTestUtil", + "android.hardware.wifi.hostapd@1.0", + "android.hardware.wifi.hostapd@1.1", + "android.hardware.wifi@1.0", + "libcrypto", + "libgmock", + "libwifi-system", + "libwifi-system-iface", + ], + test_suites: ["general-tests"], +} + diff --git a/wifi/hostapd/1.1/vts/functional/VtsHalWifiHostapdV1_1TargetTest.cpp b/wifi/hostapd/1.1/vts/functional/VtsHalWifiHostapdV1_1TargetTest.cpp new file mode 100644 index 0000000000..6916db2ca7 --- /dev/null +++ b/wifi/hostapd/1.1/vts/functional/VtsHalWifiHostapdV1_1TargetTest.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2019 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 +#include + +#include "hostapd_hidl_test_utils.h" +#include "hostapd_hidl_test_utils_1_1.h" + +class WifiHostapdHidlEnvironment_1_1 : public WifiHostapdHidlEnvironment { + public: + // get the test environment singleton + static WifiHostapdHidlEnvironment_1_1* Instance() { + static WifiHostapdHidlEnvironment_1_1* instance = + new WifiHostapdHidlEnvironment_1_1; + return instance; + } + + virtual void registerTestServices() override { + registerTestService<::android::hardware::wifi::V1_0::IWifi>(); + registerTestService(); + registerTestService(); + } + + private: + WifiHostapdHidlEnvironment_1_1() {} +}; + +WifiHostapdHidlEnvironment* gEnv = WifiHostapdHidlEnvironment_1_1::Instance(); + +int main(int argc, char** argv) { + ::testing::AddGlobalTestEnvironment(gEnv); + ::testing::InitGoogleTest(&argc, argv); + gEnv->init(&argc, argv); + int status = RUN_ALL_TESTS(); + LOG(INFO) << "Test result = " << status; + return status; +} diff --git a/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp b/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp new file mode 100644 index 0000000000..d1af655f91 --- /dev/null +++ b/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2019 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 +#include + +#include + +#include + +#include "hostapd_hidl_call_util.h" +#include "hostapd_hidl_test_utils.h" +#include "hostapd_hidl_test_utils_1_1.h" + +using ::android::sp; +using ::android::hardware::hidl_string; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::wifi::hostapd::V1_0::HostapdStatus; +using ::android::hardware::wifi::hostapd::V1_0::HostapdStatusCode; +using ::android::hardware::wifi::hostapd::V1_1::IHostapd; +using ::android::hardware::wifi::hostapd::V1_1::IHostapdCallback; + +class HostapdHidlTest : public ::testing::VtsHalHidlTargetTestBase { + public: + virtual void SetUp() override { + startHostapdAndWaitForHidlService(); + hostapd_ = getHostapd_1_1(); + ASSERT_NE(hostapd_.get(), nullptr); + } + + virtual void TearDown() override { stopHostapd(); } + + protected: + // IHostapd object used for all tests in this fixture. + sp hostapd_; +}; + +class IfaceCallback : public IHostapdCallback { + Return onFailure( + const hidl_string& /* Name of the interface */) override { + return Void(); + } +}; + +/* + * RegisterCallback + */ +TEST_F(HostapdHidlTest, registerCallback) { + hostapd_->registerCallback( + new IfaceCallback(), [](const HostapdStatus& status) { + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); + }); +} diff --git a/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test_utils_1_1.cpp b/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test_utils_1_1.cpp new file mode 100644 index 0000000000..8bb72a19f1 --- /dev/null +++ b/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test_utils_1_1.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2019 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 +#include + +#include "hostapd_hidl_test_utils.h" +#include "hostapd_hidl_test_utils_1_1.h" + +using ::android::sp; +using ::android::hardware::wifi::hostapd::V1_1::IHostapd; + +sp getHostapd_1_1() { return IHostapd::castFrom(getHostapd()); } diff --git a/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test_utils_1_1.h b/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test_utils_1_1.h new file mode 100644 index 0000000000..c43ddfa207 --- /dev/null +++ b/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test_utils_1_1.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2019 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 HOSTAPD_HIDL_TEST_UTILS_1_1_H +#define HOSTAPD_HIDL_TEST_UTILS_1_1_H + +#include + +#include + +// Helper functions to obtain references to the various HIDL interface objects. +// Note: We only have a single instance of each of these objects currently. +// These helper functions should be modified to return vectors if we support +// multiple instances. +android::sp getHostapd_1_1(); + +#endif /* HOSTAPD_HIDL_TEST_UTILS_1_1_H */ From b577571fd907de3bacfe4be14c47ce50d608b39e Mon Sep 17 00:00:00 2001 From: Badhri Jagan Sridharan Date: Fri, 18 Jan 2019 00:39:47 -0800 Subject: [PATCH 404/718] USB V1.2 interface Supports reporting and userspace control of USB contamination presence. Bug: 117330206 Bug: 77606903 Bug: 119642987 Test: USB HAL V1.2 HIDL tests. Change-Id: I70219641cdd48d59d217334dbd6d4ed8a8ce4927 --- .../compatibility_matrix.current.xml | 2 +- usb/1.2/Android.bp | 29 +++++ usb/1.2/IUsb.hal | 65 ++++++++++ usb/1.2/IUsbCallback.hal | 42 ++++++ usb/1.2/types.hal | 120 ++++++++++++++++++ 5 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 usb/1.2/Android.bp create mode 100644 usb/1.2/IUsb.hal create mode 100644 usb/1.2/IUsbCallback.hal create mode 100644 usb/1.2/types.hal diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml index 0dd174aa99..94ffe80aab 100644 --- a/compatibility_matrices/compatibility_matrix.current.xml +++ b/compatibility_matrices/compatibility_matrix.current.xml @@ -443,7 +443,7 @@ android.hardware.usb - 1.0-1 + 1.0-2 IUsb default diff --git a/usb/1.2/Android.bp b/usb/1.2/Android.bp new file mode 100644 index 0000000000..55ffad06b1 --- /dev/null +++ b/usb/1.2/Android.bp @@ -0,0 +1,29 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +hidl_interface { + name: "android.hardware.usb@1.2", + root: "android.hardware", + vndk: { + enabled: true, + }, + srcs: [ + "types.hal", + "IUsb.hal", + "IUsbCallback.hal", + ], + interfaces: [ + "android.hardware.usb@1.0", + "android.hardware.usb@1.1", + "android.hidl.base@1.0", + ], + types: [ + "ContaminantDetectionStatus", + "ContaminantProtectionMode", + "ContaminantProtectionStatus", + "PortStatus", + "Status", + ], + gen_java: true, + gen_java_constants: true, +} + diff --git a/usb/1.2/IUsb.hal b/usb/1.2/IUsb.hal new file mode 100644 index 0000000000..ecc911ebf2 --- /dev/null +++ b/usb/1.2/IUsb.hal @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.usb@1.2; + +import android.hardware.usb@1.1::IUsb; + +/** + * The setCallback function in V1_0 is used to register the V1_2 + * IUsbCallback object as well. The implementation can use the + * castFrom method to cast the IUsbCallback object. + */ +interface IUsb extends @1.1::IUsb { + /** + * When supportsEnableContaminantPresenceDetection is true, + * enableContaminantPresenceDetection enables/disables contaminant + * presence detection algorithm. Calling enableContaminantPresenceDetection + * when supportsEnableContaminantPresenceDetection is false does + * not have any effect. + * Change in contantaminant presence status should notify should + * be notified to the client via notifyPortStatusChange_1_2 through + * PortStatus. + * + * @param portName name of the port. + * @param enable true Enable contaminant presence detection algorithm. + * false Disable contaminant presence detection algorithm. + */ + oneway enableContaminantPresenceDetection(string portName, bool enable); + + /** + * When supportsEnableContaminantPresenceProtection is true, + * enableContaminantPresenceProtection enables/disables contaminant + * presence protection algorithm. Calling + * enableContaminantPresenceProtection + * when supportsEnableContaminantPresenceProtection is false does + * not have any effect. + * Used to enable/disable contaminant presence protection algorithm. + * Enabling port protection algoritm must make the lower layers to autonomously + * act on taking the corresponding preventive measure mentioned at + * ContaminantProtectionModes when contaminant is detected on the USB Port. + * Calling this method with enable set to true must set to contaminantProtectionEnabled + * to true upon success and vice versa. + * currentContaminantProtectionMode should be updated whenever there is a + * change in the status of contaminant presence protection algorithm. + * + * @param portName name of the port. + * @param enable true Reduce capabilities of the port to protect port + * from damage due to contaminant presence. + * false No action is taken upon contaminant presence. + */ + oneway enableContaminantPresenceProtection(string portName, bool enable); +}; diff --git a/usb/1.2/IUsbCallback.hal b/usb/1.2/IUsbCallback.hal new file mode 100644 index 0000000000..8cc16df10c --- /dev/null +++ b/usb/1.2/IUsbCallback.hal @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.usb@1.2; + +import android.hardware.usb@1.1::IUsbCallback; +import android.hardware.usb@1.0::Status; + +/** + * Callback object used for all the IUsb async methods which expects a result. + * Caller is expected to register the callback object using setCallback method + * to receive updates on the PortStatus. + */ +interface IUsbCallback extends @1.1::IUsbCallback { + /** + * Used to convey the current port status to the caller. + * Must be called either when PortState changes due to the port partner or + * when caller requested for the PortStatus update through queryPortStatus. + * + * @param currentPortStatus vector object of current status(PortStatus + * of all the typeC ports in the device. + * @param retval SUCCESS when the required information was enquired form + * kernel and the PortStatus_1_2 object was built. + * ERROR otherwise. + */ + oneway notifyPortStatusChange_1_2(vec currentPortStatus, + @1.0::Status retval); +}; + diff --git a/usb/1.2/types.hal b/usb/1.2/types.hal new file mode 100644 index 0000000000..081a64391b --- /dev/null +++ b/usb/1.2/types.hal @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.usb@1.2; + +import android.hardware.usb@1.1::PortStatus_1_1; +import android.hardware.usb@1.0::Status; + +enum Status : @1.0::Status { + /** + * Error value returned when the operation is not supported. + */ + NOT_SUPPORTED = 4, +}; + +@export +enum ContaminantDetectionStatus : uint32_t { + /** + * Contaminant presence detection is not supported. + */ + NOT_SUPPORTED = 0, + + /** + * Contaminant presence detection is supported but disabled. + */ + DISABLED = 1, + + /** + * Contaminant presence detection is enabled and contaminant not detected. + */ + NOT_DETECTED = 2, + + /** + * Contaminant presence detection is enabled and contaminant detected. + */ + DETECTED = 3, +}; + +@export +enum ContaminantProtectionMode : uint32_t { + /** + * No action performed upon detection of contaminant presence. + */ + NONE = 0, + + /** + * Upon detection of contaminant presence, Port is forced to sink only + * mode where a port shall only detect chargers until contaminant presence + * is no longer detected. + */ + FORCE_SINK = 1 << 0, + + /** + * Upon detection of contaminant presence, Port is forced to source only + * mode where a port shall only detect usb accessories such as headsets + * until contaminant presence is no longer detected. + */ + FORCE_SOURCE = 1 << 1, + + /** + * Upon detection of contaminant presence, port is disabled until contaminant + * presence is no longer detected. In the disabled state port will + * not respond to connection of chargers or usb accessories. + */ + FORCE_DISABLE = 1 << 2, +}; + +@export +enum ContaminantProtectionStatus : ContaminantProtectionMode { + /** + * Client disabled cotaminant protection by calling + * enableContaminantPresencePortProtection set to false. Low level drivers should + * not autmomously take any corrective action when contaminant presence is detected. + */ + DISABLED = 1 << 3, +}; + +struct PortStatus { + PortStatus_1_1 status_1_1; + + /** + * Contaminant presence protection modes supported by the port. + */ + bitfield supportedContaminantProtectionModes; + + /** + * Client can enable/disable contaminant presence protection through + * enableContaminantPresenceProtection when true. + */ + bool supportsEnableContaminantPresenceProtection; + + /** + * Contaminant presence protection modes currently active for the port. + */ + ContaminantProtectionStatus contaminantProtectionStatus; + + /** + * Client can enable/disable contaminant presence detection through + * enableContaminantPresenceDetection when true. + */ + bool supportsEnableContaminantPresenceDetection; + + /** + * Current status of contaminant detection algorithm. + */ + ContaminantDetectionStatus contaminantDetectionStatus; +}; From 28a33a9cb1e567dcc5c74a3c1b46483b16f417ba Mon Sep 17 00:00:00 2001 From: Xusong Wang Date: Wed, 23 Jan 2019 11:47:54 -0800 Subject: [PATCH 405/718] Clean and reorder operation enums. Four operation enums are removed: - DETECTION_OUTPUT - PRIOR_BOX - SPARSE_TO_DENSE - EMBEDDING_LOOKUP_SPARSE Operation enums are reorder into alphabetic order. Bug: 123253865 Bug: 122744669 Test: NeuralNetworksTest_static Change-Id: Ie5d2bff6fac061bdca0a99e5b8c8ac05733fac4b --- neuralnetworks/1.2/types.hal | 90 +++++++++++++++++------------------- 1 file changed, 43 insertions(+), 47 deletions(-) diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal index ac944c8e56..c2d10b9094 100644 --- a/neuralnetworks/1.2/types.hal +++ b/neuralnetworks/1.2/types.hal @@ -113,17 +113,17 @@ enum OperandTypeRange : uint32_t { */ enum OperationType : @1.1::OperationType { // TODO(b/116445845): Sync docs when all ops are implemented. - ARGMAX = 38, - ARGMIN = 39, - PAD_V2 = 40, + ABS = 38, + ARGMAX = 39, + ARGMIN = 40, AXIS_ALIGNED_BBOX_TRANSFORM = 41, BIDIRECTIONAL_SEQUENCE_LSTM = 42, BIDIRECTIONAL_SEQUENCE_RNN = 43, BOX_WITH_NMS_LIMIT = 44, CAST = 45, CHANNEL_SHUFFLE = 46, - DETECTION_OUTPUT = 47, - EMBEDDING_LOOKUP_SPARSE = 48, + DETECTION_POSTPROCESSING = 47, + EQUAL = 48, EXP = 49, EXPAND_DIMS = 50, GATHER = 51, @@ -132,47 +132,43 @@ enum OperationType : @1.1::OperationType { GREATER_EQUAL = 54, GROUPED_CONV_2D = 55, HEATMAP_MAX_KEYPOINT = 56, - LESS = 57, - LESS_EQUAL = 58, - LOG = 59, - LOGICAL_AND = 60, - LOGICAL_NOT = 61, - LOGICAL_OR = 62, - LOG_SOFTMAX = 63, - MAXIMUM = 64, - MINIMUM = 65, - NEG = 66, - POW = 67, - PRELU = 68, - PRIOR_BOX = 69, - QUANTIZE = 70, - QUANTIZED_16BIT_LSTM = 71, - RANDOM_MULTINOMIAL = 72, - REDUCE_PROD = 73, - ROI_ALIGN = 74, - RSQRT = 75, - SELECT = 76, - SIN = 77, - SLICE = 78, - SPARSE_TO_DENSE = 79, - SPLIT = 80, - SQRT = 81, - TILE = 82, - TOPK_V2 = 83, - TRANSPOSE_CONV_2D = 84, - UNIDIRECTIONAL_SEQUENCE_LSTM = 85, - UNIDIRECTIONAL_SEQUENCE_RNN = 86, - DETECTION_POSTPROCESSING = 87, - ABS = 88, - ROI_POOLING = 89, - EQUAL = 90, - NOT_EQUAL = 91, - REDUCE_SUM = 92, - REDUCE_MAX = 93, - REDUCE_MIN = 94, - REDUCE_ANY = 95, - REDUCE_ALL = 96, - INSTANCE_NORMALIZATION = 97, + INSTANCE_NORMALIZATION = 57, + LESS = 58, + LESS_EQUAL = 59, + LOG = 60, + LOGICAL_AND = 61, + LOGICAL_NOT = 62, + LOGICAL_OR = 63, + LOG_SOFTMAX = 64, + MAXIMUM = 65, + MINIMUM = 66, + NEG = 67, + NOT_EQUAL = 68, + PAD_V2 = 69, + POW = 70, + PRELU = 71, + QUANTIZE = 72, + QUANTIZED_16BIT_LSTM = 73, + RANDOM_MULTINOMIAL = 74, + REDUCE_ALL = 75, + REDUCE_ANY = 76, + REDUCE_MAX = 77, + REDUCE_MIN = 78, + REDUCE_PROD = 79, + REDUCE_SUM = 80, + ROI_ALIGN = 81, + ROI_POOLING = 82, + RSQRT = 83, + SELECT = 84, + SIN = 85, + SLICE = 86, + SPLIT = 87, + SQRT = 88, + TILE = 89, + TOPK_V2 = 90, + TRANSPOSE_CONV_2D = 91, + UNIDIRECTIONAL_SEQUENCE_LSTM = 92, + UNIDIRECTIONAL_SEQUENCE_RNN = 93, /* ADDING A NEW FUNDAMENTAL OPERATION REQUIRES UPDATING THE VALUE OF * OperationTypeRange::OPERATION_FUNDAMENTAL_MAX. */ @@ -186,7 +182,7 @@ enum OperationType : @1.1::OperationType { */ enum OperationTypeRange : uint32_t { OPERATION_FUNDAMENTAL_MIN = 0, - OPERATION_FUNDAMENTAL_MAX = 97, + OPERATION_FUNDAMENTAL_MAX = 93, OPERATION_OEM_MIN = 10000, OPERATION_OEM_MAX = 10000, }; From e301349b0597f2cc136703f2aaa182e6a546b50c Mon Sep 17 00:00:00 2001 From: David Gross Date: Wed, 23 Jan 2019 14:01:52 -0800 Subject: [PATCH 406/718] Update neuralnetworks HAL to allow collecting execution duration. Test: VtsHalNeuralnetworksV1_0TargetTest --hal_service_instance=android.hardware.neuralnetworks@1.0::IDevice/sample-all Test: VtsHalNeuralnetworksV1_1TargetTest --hal_service_instance=android.hardware.neuralnetworks@1.1::IDevice/sample-all Test: VtsHalNeuralnetworksV1_2TargetTest --hal_service_instance=android.hardware.neuralnetworks@1.2::IDevice/sample-all Bug: 115390094 Change-Id: If67a5ffe39cfdd78498e01f26251734fdc8e66c7 --- .../1.0/vts/functional/Callbacks.cpp | 11 +++- neuralnetworks/1.0/vts/functional/Callbacks.h | 33 +++++++++- .../vts/functional/GeneratedTestHarness.cpp | 65 ++++++++++++------- neuralnetworks/1.2/IExecutionCallback.hal | 8 ++- neuralnetworks/1.2/IPreparedModel.hal | 18 ++++- neuralnetworks/1.2/types.hal | 55 ++++++++++++++-- .../1.2/vts/functional/ValidateRequest.cpp | 29 +++++++-- 7 files changed, 177 insertions(+), 42 deletions(-) diff --git a/neuralnetworks/1.0/vts/functional/Callbacks.cpp b/neuralnetworks/1.0/vts/functional/Callbacks.cpp index 03afcd0751..c30702cd99 100644 --- a/neuralnetworks/1.0/vts/functional/Callbacks.cpp +++ b/neuralnetworks/1.0/vts/functional/Callbacks.cpp @@ -135,14 +135,18 @@ ExecutionCallback::~ExecutionCallback() {} Return ExecutionCallback::notify(ErrorStatus errorStatus) { mErrorStatus = errorStatus; + mOutputShapes = {}; + mTiming = {.timeOnDevice = UINT64_MAX, .timeInDriver = UINT64_MAX}; CallbackBase::notify(); return Void(); } Return ExecutionCallback::notify_1_2(ErrorStatus errorStatus, - const hidl_vec& outputShapes) { + const hidl_vec& outputShapes, + const Timing& timing) { mErrorStatus = errorStatus; mOutputShapes = outputShapes; + mTiming = timing; CallbackBase::notify(); return Void(); } @@ -157,6 +161,11 @@ const std::vector& ExecutionCallback::getOutputShapes() { return mOutputShapes; } +Timing ExecutionCallback::getTiming() { + wait(); + return mTiming; +} + } // namespace implementation } // namespace V1_2 } // namespace neuralnetworks diff --git a/neuralnetworks/1.0/vts/functional/Callbacks.h b/neuralnetworks/1.0/vts/functional/Callbacks.h index 46f29a60e7..4707d0a251 100644 --- a/neuralnetworks/1.0/vts/functional/Callbacks.h +++ b/neuralnetworks/1.0/vts/functional/Callbacks.h @@ -308,8 +308,20 @@ class ExecutionCallback : public CallbackBase, public IExecutionCallback { * of the output operand in the Request outputs vector. * outputShapes must be empty unless the status is either * NONE or OUTPUT_INSUFFICIENT_SIZE. + * @return Timing Duration of execution. Unless MeasureTiming::YES was passed when + * launching the execution and status is NONE, all times must + * be reported as UINT64_MAX. A driver may choose to report + * any time as UINT64_MAX, indicating that particular measurement is + * not available. */ - Return notify_1_2(ErrorStatus status, const hidl_vec& outputShapes) override; + Return notify_1_2(ErrorStatus status, const hidl_vec& outputShapes, + const Timing& timing) override; + + // An overload of the latest notify interface to hide the version from ExecutionBuilder. + Return notify(ErrorStatus status, const hidl_vec& outputShapes, + const Timing& timing) { + return notify_1_2(status, outputShapes, timing); + } /** * Retrieves the error status returned from the asynchronous task launched @@ -350,9 +362,24 @@ class ExecutionCallback : public CallbackBase, public IExecutionCallback { */ const std::vector& getOutputShapes(); + /** + * Retrieves the duration of execution ofthe asynchronous task launched + * by IPreparedModel::execute_1_2. If IPreparedModel::execute_1_2 has not finished + * asynchronously executing, this call will block until the asynchronous task + * notifies the object. + * + * If the asynchronous task was launched by IPreparedModel::execute, every time + * must be UINT64_MAX. + * + * @return timing Duration of the execution. Every time must be UINT64_MAX unless + * the status is NONE. + */ + Timing getTiming(); + private: - ErrorStatus mErrorStatus; - std::vector mOutputShapes; + ErrorStatus mErrorStatus = ErrorStatus::GENERAL_FAILURE; + std::vector mOutputShapes = {}; + Timing mTiming = {}; }; diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp index d45922e1c4..65c425ee1e 100644 --- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp +++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp @@ -77,29 +77,33 @@ void copy_back(MixedTyped* dst, const std::vector& ra, char* sr // Top level driver for models and examples generated by test_generator.py // Test driver for those generated from ml/nn/runtime/test/spec static Return ExecutePreparedModel(sp& preparedModel, - const Request& request, + const Request& request, MeasureTiming, sp& callback) { return preparedModel->execute(request, callback); } static Return ExecutePreparedModel(sp& preparedModel, - const Request& request, + const Request& request, MeasureTiming measure, sp& callback) { - return preparedModel->execute_1_2(request, callback); + return preparedModel->execute_1_2(request, measure, callback); } static Return ExecutePreparedModel(sp&, const Request&, - hidl_vec*) { + MeasureTiming, hidl_vec*, Timing*) { ADD_FAILURE() << "asking for synchronous execution at V1_0"; return ErrorStatus::GENERAL_FAILURE; } static Return ExecutePreparedModel(sp& preparedModel, - const Request& request, - hidl_vec* outputShapes) { + const Request& request, MeasureTiming measure, + hidl_vec* outputShapes, + Timing* timing) { ErrorStatus result; Return ret = preparedModel->executeSynchronously( - request, [&result, &outputShapes](ErrorStatus error, const hidl_vec& shapes) { - result = error; - *outputShapes = shapes; - }); + request, measure, + [&result, outputShapes, timing](ErrorStatus error, const hidl_vec& shapes, + const Timing& time) { + result = error; + *outputShapes = shapes; + *timing = time; + }); if (!ret.isOk()) { return ErrorStatus::GENERAL_FAILURE; } @@ -111,9 +115,8 @@ const float kDefaultRtol = 1e-5f; template void EvaluatePreparedModel(sp& preparedModel, std::function is_ignored, const std::vector& examples, - bool hasRelaxedFloat32Model = false, float fpAtol = kDefaultAtol, - float fpRtol = kDefaultRtol, Synchronously sync = Synchronously::NO, - bool testDynamicOutputShape = false) { + bool hasRelaxedFloat32Model, float fpAtol, float fpRtol, + Synchronously sync, MeasureTiming measure, bool testDynamicOutputShape) { const uint32_t INPUT = 0; const uint32_t OUTPUT = 1; @@ -208,6 +211,7 @@ void EvaluatePreparedModel(sp& preparedModel, std::function outputShapes; + Timing timing; if (sync == Synchronously::NO) { SCOPED_TRACE("asynchronous"); @@ -215,8 +219,8 @@ void EvaluatePreparedModel(sp& preparedModel, std::function executionCallback = new ExecutionCallback(); ASSERT_NE(nullptr, executionCallback.get()); Return executionLaunchStatus = ExecutePreparedModel( - preparedModel, {.inputs = inputs_info, .outputs = outputs_info, .pools = pools}, - executionCallback); + preparedModel, {.inputs = inputs_info, .outputs = outputs_info, .pools = pools}, + measure, executionCallback); ASSERT_TRUE(executionLaunchStatus.isOk()); EXPECT_EQ(ErrorStatus::NONE, static_cast(executionLaunchStatus)); @@ -224,13 +228,14 @@ void EvaluatePreparedModel(sp& preparedModel, std::functionwait(); executionStatus = executionCallback->getStatus(); outputShapes = executionCallback->getOutputShapes(); + timing = executionCallback->getTiming(); } else { SCOPED_TRACE("synchronous"); // execute Return executionReturnStatus = ExecutePreparedModel( - preparedModel, {.inputs = inputs_info, .outputs = outputs_info, .pools = pools}, - &outputShapes); + preparedModel, {.inputs = inputs_info, .outputs = outputs_info, .pools = pools}, + measure, &outputShapes, &timing); ASSERT_TRUE(executionReturnStatus.isOk()); executionStatus = static_cast(executionReturnStatus); } @@ -244,6 +249,14 @@ void EvaluatePreparedModel(sp& preparedModel, std::function& preparedModel, std::function void EvaluatePreparedModel(sp& preparedModel, std::function is_ignored, const std::vector& examples, - bool hasRelaxedFloat32Model, Synchronously sync, + bool hasRelaxedFloat32Model, Synchronously sync, MeasureTiming measure, bool testDynamicOutputShape) { EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model, kDefaultAtol, - kDefaultRtol, sync, testDynamicOutputShape); + kDefaultRtol, sync, measure, testDynamicOutputShape); } static void getPreparedModel(sp callback, @@ -333,7 +346,7 @@ void Execute(const sp& device, std::function c float fpAtol = 1e-5f, fpRtol = 5.0f * 1.1920928955078125e-7f; EvaluatePreparedModel(preparedModel, is_ignored, examples, /*hasRelaxedFloat32Model=*/false, fpAtol, fpRtol, Synchronously::NO, - /*testDynamicOutputShape=*/false); + MeasureTiming::NO, /*testDynamicOutputShape=*/false); } void Execute(const sp& device, std::function create_model, @@ -380,7 +393,7 @@ void Execute(const sp& device, std::function c EvaluatePreparedModel(preparedModel, is_ignored, examples, model.relaxComputationFloat32toFloat16, 1e-5f, 1e-5f, Synchronously::NO, - /*testDynamicOutputShape=*/false); + MeasureTiming::NO, /*testDynamicOutputShape=*/false); } // TODO: Reduce code duplication. @@ -429,10 +442,16 @@ void Execute(const sp& device, std::function c EvaluatePreparedModel(preparedModel, is_ignored, examples, model.relaxComputationFloat32toFloat16, Synchronously::NO, - testDynamicOutputShape); + MeasureTiming::NO, testDynamicOutputShape); EvaluatePreparedModel(preparedModel, is_ignored, examples, model.relaxComputationFloat32toFloat16, Synchronously::YES, - testDynamicOutputShape); + MeasureTiming::NO, testDynamicOutputShape); + EvaluatePreparedModel(preparedModel, is_ignored, examples, + model.relaxComputationFloat32toFloat16, Synchronously::NO, + MeasureTiming::YES, testDynamicOutputShape); + EvaluatePreparedModel(preparedModel, is_ignored, examples, + model.relaxComputationFloat32toFloat16, Synchronously::YES, + MeasureTiming::YES, testDynamicOutputShape); } } // namespace generated_tests diff --git a/neuralnetworks/1.2/IExecutionCallback.hal b/neuralnetworks/1.2/IExecutionCallback.hal index 47de1b60ec..7f6c9eeffe 100644 --- a/neuralnetworks/1.2/IExecutionCallback.hal +++ b/neuralnetworks/1.2/IExecutionCallback.hal @@ -18,7 +18,6 @@ package android.hardware.neuralnetworks@1.2; import @1.0::ErrorStatus; import @1.0::IExecutionCallback; -import OutputShape; /** * IExecutionCallback must be used to return the error status result from an @@ -50,6 +49,11 @@ interface IExecutionCallback extends @1.0::IExecutionCallback { * of the output operand in the Request outputs vector. * outputShapes must be empty unless the status is either * NONE or OUTPUT_INSUFFICIENT_SIZE. + * @return Timing Duration of execution. Unless MeasureTiming::YES was passed when + * launching the execution and status is NONE, all times must + * be reported as UINT64_MAX. A driver may choose to report + * any time as UINT64_MAX, indicating that particular measurement is + * not available. */ - oneway notify_1_2(ErrorStatus status, vec outputShapes); + oneway notify_1_2(ErrorStatus status, vec outputShapes, Timing timing); }; diff --git a/neuralnetworks/1.2/IPreparedModel.hal b/neuralnetworks/1.2/IPreparedModel.hal index 2d4e572333..5d2d80ff71 100644 --- a/neuralnetworks/1.2/IPreparedModel.hal +++ b/neuralnetworks/1.2/IPreparedModel.hal @@ -59,6 +59,10 @@ interface IPreparedModel extends @1.0::IPreparedModel { * * @param request The input and output information on which the prepared * model is to be executed. + * @param measure Specifies whether or not to measure duration of the execution. + * The duration runs from the time the driver sees the call + * to the execute_1_2 function to the time the driver invokes + * the callback. * @param callback A callback object used to return the error status of * the execution. The callback object's notify function must * be called exactly once, even if the execution was @@ -72,7 +76,7 @@ interface IPreparedModel extends @1.0::IPreparedModel { * - INVALID_ARGUMENT if one of the input arguments is * invalid */ - execute_1_2(Request request, IExecutionCallback callback) + execute_1_2(Request request, MeasureTiming measure, IExecutionCallback callback) generates (ErrorStatus status); /** @@ -98,6 +102,10 @@ interface IPreparedModel extends @1.0::IPreparedModel { * * @param request The input and output information on which the prepared * model is to be executed. + * @param measure Specifies whether or not to measure duration of the execution. + * The duration runs from the time the driver sees the call + * to the executeSynchronously function to the time the driver + * returns from the function. * @return status Error status of the execution, must be: * - NONE if execution is performed successfully * - DEVICE_UNAVAILABLE if driver is offline or busy @@ -112,9 +120,13 @@ interface IPreparedModel extends @1.0::IPreparedModel { * of the output operand in the Request outputs vector. * outputShapes must be empty unless the status is either * NONE or OUTPUT_INSUFFICIENT_SIZE. + * @return Timing Duration of execution. Unless measure is YES and status is + * NONE, all times must be reported as UINT64_MAX. A driver may + * choose to report any time as UINT64_MAX, indicating that + * measurement is not available. */ - executeSynchronously(Request request) - generates (ErrorStatus status, vec outputShapes); + executeSynchronously(Request request, MeasureTiming measure) + generates (ErrorStatus status, vec outputShapes, Timing timing); /** * Configure a Burst object used to execute multiple inferences on a diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal index ce993d71a9..8bc28b4885 100644 --- a/neuralnetworks/1.2/types.hal +++ b/neuralnetworks/1.2/types.hal @@ -447,8 +447,34 @@ struct OutputShape { }; /** - * FmqRequestDatum is a single element of a serialized representation of a - * {@link @1.0::Request} object which is sent across FastMessageQueue. + * Specifies whether or not to measure timing information during execution. + */ +enum MeasureTiming : int32_t { + NO = 0, + YES = 1, +}; + +/** + + * Timing information measured during execution. Each time is a duration from + * the beginning of some task to the end of that task, including time when that + * task is not active (for example, preempted by some other task, or + * waiting for some resource to become available). + * + * Times are measured in microseconds. + * When a time is not available, it must be reported as UINT64_MAX. + */ +struct Timing { + /** Execution time on device (not driver, which runs on host processor). */ + uint64_t timeOnDevice; + /** Execution time in driver (including time on device). */ + uint64_t timeInDriver; +}; + +/** + * FmqRequestDatum is a single element of a serialized representation of an + * execution request (a {@link @1.0::Request} object and a {@link MeasureTiming} + * value) which is sent across FastMessageQueue. * * The serialized representation for a particular execution is referred to later * in these descriptions as a 'packet'. @@ -456,7 +482,7 @@ struct OutputShape { * FastMessageQueue can only pass HIDL-defined types that do not involve nested * buffers, handles, or interfaces. * - * The {@link @1.0::Request} is serialized as follows: + * The request is serialized as follows: * 1) 'packetInformation' * 2) For each input operand: * 2.1) 'inputOperandInformation' @@ -468,6 +494,7 @@ struct OutputShape { * 3.2.1) 'outputOperandDimensionValue' * 4) For each pool: * 4.1) 'poolIdentifier' + * 5) 'measureTiming' */ safe_union FmqRequestDatum { /** @@ -561,12 +588,21 @@ safe_union FmqRequestDatum { * identifier. */ int32_t poolIdentifier; + + /** + * Specifies whether or not to measure duration of the execution. The + * duration runs from the time the driver dequeues the request from a + * FastMessageQueue to the time the driver enqueues results to a + * FastMessageQueue. + */ + MeasureTiming measureTiming; }; /** * FmqResultDatum is a single element of a serialized representation of the - * values returned from an execution ({@link @1.0::ErrorStatus} and - * vec<{@link OutputShape}>) which is returned via FastMessageQueue. + * values returned from an execution ({@link @1.0::ErrorStatus}, + * vec<{@link OutputShape}>, and {@link Timing}) which is returned via + * FastMessageQueue. * * The serialized representation for a particular execution is referred to later * in these descriptions as a 'packet'. @@ -581,6 +617,7 @@ safe_union FmqRequestDatum { * 2.1) 'operandInformation' * 2.2) For each dimension element of the operand: * 2.2.1) 'operandDimensionValue' + * 3) 'executionTiming' */ safe_union FmqResultDatum { /** @@ -636,4 +673,12 @@ safe_union FmqResultDatum { * Element of the dimensions vector. */ uint32_t operandDimensionValue; + + /** + * Duration of execution. Unless measurement was requested and execution + * succeeds, all times must be reported as UINT64_MAX. A driver may choose + * to report any time as UINT64_MAX, indicating that measurement is not + * available. + */ + Timing executionTiming; }; diff --git a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp index 1eaea4b9a6..00a7c3ec4f 100644 --- a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp +++ b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp @@ -42,6 +42,10 @@ using test_helper::MixedTypedExample; ///////////////////////// UTILITY FUNCTIONS ///////////////////////// +static bool badTiming(Timing timing) { + return timing.timeOnDevice == UINT64_MAX && timing.timeInDriver == UINT64_MAX; +} + static void createPreparedModel(const sp& device, const Model& model, sp* preparedModel) { ASSERT_NE(nullptr, preparedModel); @@ -98,31 +102,46 @@ static void validate(const sp& preparedModel, const std::string& Request request, const std::function& mutation) { mutation(&request); + // We'd like to test both with timing requested and without timing + // requested. Rather than running each test both ways, we'll decide whether + // to request timing by hashing the message. We do not use std::hash because + // it is not guaranteed stable across executions. + char hash = 0; + for (auto c : message) { + hash ^= c; + }; + MeasureTiming measure = (hash & 1) ? MeasureTiming::YES : MeasureTiming::NO; + { SCOPED_TRACE(message + " [execute_1_2]"); sp executionCallback = new ExecutionCallback(); ASSERT_NE(nullptr, executionCallback.get()); Return executeLaunchStatus = - preparedModel->execute_1_2(request, executionCallback); + preparedModel->execute_1_2(request, measure, executionCallback); ASSERT_TRUE(executeLaunchStatus.isOk()); ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast(executeLaunchStatus)); executionCallback->wait(); ErrorStatus executionReturnStatus = executionCallback->getStatus(); const auto& outputShapes = executionCallback->getOutputShapes(); + Timing timing = executionCallback->getTiming(); ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, executionReturnStatus); ASSERT_EQ(outputShapes.size(), 0); + ASSERT_TRUE(badTiming(timing)); } { SCOPED_TRACE(message + " [executeSynchronously]"); Return executeStatus = preparedModel->executeSynchronously( - request, [](ErrorStatus error, const hidl_vec& outputShapes) { - ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, error); - EXPECT_EQ(outputShapes.size(), 0); - }); + request, measure, + [](ErrorStatus error, const hidl_vec& outputShapes, + const Timing& timing) { + ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, error); + EXPECT_EQ(outputShapes.size(), 0); + EXPECT_TRUE(badTiming(timing)); + }); ASSERT_TRUE(executeStatus.isOk()); } } From c846dc8feebc22c1327ad3649103d885136ae88d Mon Sep 17 00:00:00 2001 From: Badhri Jagan Sridharan Date: Fri, 18 Jan 2019 00:40:25 -0800 Subject: [PATCH 407/718] USB HAL V1.2 tests Bug: 117330206 Bug: 77606903 Bug: 119642987 Test: Executed tests on pixel device. Change-Id: Ibd3cfdfc59b15d54565597434c795eadb19f0f1a --- usb/1.2/vts/OWNERS | 2 + usb/1.2/vts/functional/Android.bp | 28 ++ .../functional/VtsHalUsbV1_2TargetTest.cpp | 380 ++++++++++++++++++ 3 files changed, 410 insertions(+) create mode 100644 usb/1.2/vts/OWNERS create mode 100644 usb/1.2/vts/functional/Android.bp create mode 100644 usb/1.2/vts/functional/VtsHalUsbV1_2TargetTest.cpp diff --git a/usb/1.2/vts/OWNERS b/usb/1.2/vts/OWNERS new file mode 100644 index 0000000000..f60d39a3b4 --- /dev/null +++ b/usb/1.2/vts/OWNERS @@ -0,0 +1,2 @@ +badhri@google.com +yim@google.com diff --git a/usb/1.2/vts/functional/Android.bp b/usb/1.2/vts/functional/Android.bp new file mode 100644 index 0000000000..761d37f184 --- /dev/null +++ b/usb/1.2/vts/functional/Android.bp @@ -0,0 +1,28 @@ +// +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +cc_test { + name: "VtsHalUsbV1_2TargetTest", + defaults: ["VtsHalTargetTestDefaults"], + srcs: ["VtsHalUsbV1_2TargetTest.cpp"], + static_libs: [ + "android.hardware.usb@1.0", + "android.hardware.usb@1.1", + "android.hardware.usb@1.2", + ], + test_suites: ["general-tests"], +} + diff --git a/usb/1.2/vts/functional/VtsHalUsbV1_2TargetTest.cpp b/usb/1.2/vts/functional/VtsHalUsbV1_2TargetTest.cpp new file mode 100644 index 0000000000..7b3dea938e --- /dev/null +++ b/usb/1.2/vts/functional/VtsHalUsbV1_2TargetTest.cpp @@ -0,0 +1,380 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "VtsHalUsbV1_2TargetTest" +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using ::android::sp; +using ::android::hardware::hidl_array; +using ::android::hardware::hidl_memory; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::usb::V1_0::PortDataRole; +using ::android::hardware::usb::V1_0::PortMode; +using ::android::hardware::usb::V1_0::PortPowerRole; +using ::android::hardware::usb::V1_0::PortRole; +using ::android::hardware::usb::V1_0::PortRoleType; +using ::android::hardware::usb::V1_0::Status; +using ::android::hardware::usb::V1_1::PortMode_1_1; +using ::android::hardware::usb::V1_1::PortStatus_1_1; +using ::android::hardware::usb::V1_2::ContaminantDetectionStatus; +using ::android::hardware::usb::V1_2::ContaminantProtectionMode; +using ::android::hardware::usb::V1_2::ContaminantProtectionStatus; +using ::android::hardware::usb::V1_2::IUsb; +using ::android::hardware::usb::V1_2::IUsbCallback; +using ::android::hardware::usb::V1_2::PortStatus; +using ::android::hidl::base::V1_0::IBase; + +constexpr char kCallbackNameNotifyPortStatusChange_1_2[] = "notifyPortStatusChange_1_2"; +const int kCallbackIdentifier = 2; + +// Worst case wait time 20secs +#define WAIT_FOR_TIMEOUT std::chrono::milliseconds(20000) + +class UsbClientCallbackArgs { + public: + // The last conveyed status of the USB ports. + // Stores information of currentt_data_role, power_role for all the USB ports + PortStatus usb_last_port_status; + + // Status of the last role switch operation. + Status usb_last_status; + + // Identifier for the usb callback object. + // Stores the cookie of the last invoked usb callback object. + int last_usb_cookie; +}; + +// Callback class for the USB HIDL hal. +// Usb Hal will call this object upon role switch or port query. +class UsbCallback : public ::testing::VtsHalHidlTargetCallbackBase, + public IUsbCallback { + int cookie; + + public: + UsbCallback(int cookie) : cookie(cookie){}; + + virtual ~UsbCallback() = default; + + // V1_0 Callback method for the port status. + // This should not be called so not signalling the Test here assuming that + // the test thread will timeout + Return notifyPortStatusChange(const hidl_vec& + /* currentPortStatus */, + Status /* retval */) override { + return Void(); + }; + + // V1_1 Callback method for the port status. + // This should not be called so not signalling the Test here assuming that + // the test thread will timeout + Return notifyPortStatusChange_1_1(const hidl_vec& /* currentPortStatus */, + Status /* retval */) override { + return Void(); + } + + // This callback method should be used. + Return notifyPortStatusChange_1_2(const hidl_vec& currentPortStatus, + Status retval) override { + UsbClientCallbackArgs arg; + if (retval == Status::SUCCESS) { + arg.usb_last_port_status.status_1_1.status.supportedModes = + currentPortStatus[0].status_1_1.status.supportedModes; + arg.usb_last_port_status.status_1_1.status.currentMode = + currentPortStatus[0].status_1_1.status.currentMode; + arg.usb_last_port_status.status_1_1.status.portName = + currentPortStatus[0].status_1_1.status.portName; + arg.usb_last_port_status.contaminantDetectionStatus = + currentPortStatus[0].contaminantDetectionStatus; + arg.usb_last_port_status.contaminantProtectionStatus = + currentPortStatus[0].contaminantProtectionStatus; + arg.usb_last_port_status.supportsEnableContaminantPresenceProtection = + currentPortStatus[0].supportsEnableContaminantPresenceProtection; + arg.usb_last_port_status.supportsEnableContaminantPresenceDetection = + currentPortStatus[0].supportsEnableContaminantPresenceDetection; + arg.usb_last_port_status.supportedContaminantProtectionModes = + currentPortStatus[0].supportedContaminantProtectionModes; + } + arg.usb_last_status = retval; + arg.last_usb_cookie = cookie; + + NotifyFromCallback(kCallbackNameNotifyPortStatusChange_1_2, arg); + return Void(); + } + + // Callback method for the status of role switch operation. + // RoleSwitch operation has not changed since V1_0 so leaving + // the callback blank here. + Return notifyRoleSwitchStatus(const hidl_string& /*portName*/, + const PortRole& /*newRole*/, Status /*retval*/) override { + return Void(); + }; +}; + +// Test environment for Usb HIDL HAL. +class UsbHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { + public: + // get the test environment singleton + static UsbHidlEnvironment* Instance() { + static UsbHidlEnvironment* instance = new UsbHidlEnvironment; + return instance; + } + + virtual void registerTestServices() override { registerTestService(); } +}; + +// The main test class for the USB hidl HAL +class UsbHidlTest : public ::testing::VtsHalHidlTargetTestBase { + public: + virtual void SetUp() override { + ALOGI(__FUNCTION__); + usb = ::testing::VtsHalHidlTargetTestBase::getService(); + ASSERT_NE(usb, nullptr); + + usb_cb_2 = new UsbCallback(kCallbackIdentifier); + ASSERT_NE(usb_cb_2, nullptr); + usb_cb_2->SetWaitTimeout(kCallbackNameNotifyPortStatusChange_1_2, WAIT_FOR_TIMEOUT); + Return ret = usb->setCallback(usb_cb_2); + ASSERT_TRUE(ret.isOk()); + } + + virtual void TearDown() override { ALOGI("Teardown"); } + + // USB hidl hal Proxy + sp usb; + + // Callback objects for usb hidl + // Methods of these objects are called to notify port status updates. + sp usb_cb_1; + sp usb_cb_2; +}; + +/* + * Test to see if setCallback on V1_1 callback object succeeds. + * Callback oject is created and registered. + * Check to see if the hidl transaction succeeded. + */ +TEST_F(UsbHidlTest, setCallback) { + usb_cb_1 = new UsbCallback(1); + ASSERT_NE(usb_cb_1, nullptr); + Return ret = usb->setCallback(usb_cb_1); + ASSERT_TRUE(ret.isOk()); +} + +/* + * Check to see if querying type-c + * port status succeeds. + * HAL service should call notifyPortStatusChange_1_2 + * instead of notifyPortStatusChange of V1_0/V1_1 interface + */ +TEST_F(UsbHidlTest, queryPortStatus) { + Return ret = usb->queryPortStatus(); + ASSERT_TRUE(ret.isOk()); + auto res = usb_cb_2->WaitForCallback(kCallbackNameNotifyPortStatusChange_1_2); + EXPECT_TRUE(res.no_timeout); + EXPECT_EQ(kCallbackIdentifier, res.args->last_usb_cookie); + EXPECT_EQ(PortMode::NONE, res.args->usb_last_port_status.status_1_1.status.currentMode); + EXPECT_EQ(PortMode::NONE, res.args->usb_last_port_status.status_1_1.status.supportedModes); + EXPECT_EQ(Status::SUCCESS, res.args->usb_last_status); +} + +/* + * supportedContaminantProtectionModes is immutable. + * Check if supportedContaminantProtectionModes changes across queryPortStatus + * call. + */ +TEST_F(UsbHidlTest, checkSupportedContaminantProtectionModes) { + Return ret = usb->queryPortStatus(); + ASSERT_TRUE(ret.isOk()); + auto res = usb_cb_2->WaitForCallback(kCallbackNameNotifyPortStatusChange_1_2); + EXPECT_TRUE(res.no_timeout); + EXPECT_EQ(kCallbackIdentifier, res.args->last_usb_cookie); + EXPECT_EQ(PortMode::NONE, res.args->usb_last_port_status.status_1_1.status.currentMode); + EXPECT_EQ(PortMode::NONE, res.args->usb_last_port_status.status_1_1.status.supportedModes); + EXPECT_EQ(Status::SUCCESS, res.args->usb_last_status); + + uint32_t supportedContaminantProtectionModes = static_cast( + res.args->usb_last_port_status.supportedContaminantProtectionModes); + for (int runs = 1; runs <= 10; runs++) { + ret = usb->queryPortStatus(); + ASSERT_TRUE(ret.isOk()); + res = usb_cb_2->WaitForCallback(kCallbackNameNotifyPortStatusChange_1_2); + EXPECT_TRUE(res.no_timeout); + EXPECT_EQ(kCallbackIdentifier, res.args->last_usb_cookie); + EXPECT_EQ(PortMode::NONE, res.args->usb_last_port_status.status_1_1.status.currentMode); + EXPECT_EQ(PortMode::NONE, res.args->usb_last_port_status.status_1_1.status.supportedModes); + EXPECT_EQ(Status::SUCCESS, res.args->usb_last_status); + EXPECT_EQ(supportedContaminantProtectionModes, + static_cast( + res.args->usb_last_port_status.supportedContaminantProtectionModes)); + } +} + +/* + * When supportsEnableContaminantPresenceDetection is set false, + * enableContaminantPresenceDetection should not enable/disable + * contaminantPresenceProtection. + */ +TEST_F(UsbHidlTest, presenceDetectionSupportedCheck) { + Return ret = usb->queryPortStatus(); + ASSERT_TRUE(ret.isOk()); + auto res = usb_cb_2->WaitForCallback(kCallbackNameNotifyPortStatusChange_1_2); + EXPECT_TRUE(res.no_timeout); + EXPECT_EQ(kCallbackIdentifier, res.args->last_usb_cookie); + EXPECT_EQ(Status::SUCCESS, res.args->usb_last_status); + + if (!res.args->usb_last_port_status.supportsEnableContaminantPresenceDetection) { + for (int runs = 1; runs <= 10; runs++) { + bool currentStatus = !(res.args->usb_last_port_status.contaminantDetectionStatus == + ContaminantDetectionStatus::DISABLED); + + ret = usb->enableContaminantPresenceDetection( + res.args->usb_last_port_status.status_1_1.status.portName, !currentStatus); + ASSERT_TRUE(ret.isOk()); + + res = usb_cb_2->WaitForCallback(kCallbackNameNotifyPortStatusChange_1_2); + EXPECT_TRUE(res.no_timeout); + EXPECT_EQ(kCallbackIdentifier, res.args->last_usb_cookie); + EXPECT_EQ(currentStatus, !(res.args->usb_last_port_status.contaminantDetectionStatus == + ContaminantDetectionStatus::DISABLED)); + } + } +} + +/* + * enableContaminantPresenceDetection should succeed atleast 90% when supported. + */ +TEST_F(UsbHidlTest, contaminantPresenceDetectionStability) { + int successCount = 0; + bool currentStatus; + bool supported = true; + + Return ret = usb->queryPortStatus(); + ASSERT_TRUE(ret.isOk()); + auto res = usb_cb_2->WaitForCallback(kCallbackNameNotifyPortStatusChange_1_2); + EXPECT_TRUE(res.no_timeout); + EXPECT_EQ(kCallbackIdentifier, res.args->last_usb_cookie); + EXPECT_EQ(Status::SUCCESS, res.args->usb_last_status); + + if (!res.args->usb_last_port_status.supportsEnableContaminantPresenceDetection) return; + + for (int count = 1; count <= 10; count++) { + currentStatus = !(res.args->usb_last_port_status.contaminantDetectionStatus == + ContaminantDetectionStatus::DISABLED); + + ret = usb->enableContaminantPresenceDetection( + res.args->usb_last_port_status.status_1_1.status.portName, !currentStatus); + ASSERT_TRUE(ret.isOk()); + res = usb_cb_2->WaitForCallback(kCallbackNameNotifyPortStatusChange_1_2); + EXPECT_TRUE(res.no_timeout); + EXPECT_EQ(kCallbackIdentifier, res.args->last_usb_cookie); + if (!currentStatus == !(res.args->usb_last_port_status.contaminantDetectionStatus == + ContaminantDetectionStatus::DISABLED)) + successCount++; + } + + if (!supported) EXPECT_GE(successCount, 9); +} + +/* + * When supportsEnableContaminantPresenceProtection is set false, + * enableContaminantPresenceProtection should not enable/disable + * contaminantPresenceProtection. + */ +TEST_F(UsbHidlTest, presenceProtectionSupportedCheck) { + Return ret = usb->queryPortStatus(); + ASSERT_TRUE(ret.isOk()); + auto res = usb_cb_2->WaitForCallback(kCallbackNameNotifyPortStatusChange_1_2); + EXPECT_TRUE(res.no_timeout); + EXPECT_EQ(kCallbackIdentifier, res.args->last_usb_cookie); + EXPECT_EQ(Status::SUCCESS, res.args->usb_last_status); + + if (!res.args->usb_last_port_status.supportsEnableContaminantPresenceProtection) { + for (int runs = 1; runs <= 10; runs++) { + bool currentStatus = !(res.args->usb_last_port_status.contaminantProtectionStatus == + ContaminantProtectionStatus::DISABLED); + + ret = usb->enableContaminantPresenceProtection( + res.args->usb_last_port_status.status_1_1.status.portName, !currentStatus); + ASSERT_TRUE(ret.isOk()); + + res = usb_cb_2->WaitForCallback(kCallbackNameNotifyPortStatusChange_1_2); + EXPECT_TRUE(res.no_timeout); + EXPECT_EQ(kCallbackIdentifier, res.args->last_usb_cookie); + EXPECT_EQ(currentStatus, !(res.args->usb_last_port_status.contaminantProtectionStatus == + ContaminantProtectionStatus::DISABLED)); + } + } +} + +/* + * enableContaminantPresenceProtection should succeed atleast 90% when supported. + */ +TEST_F(UsbHidlTest, contaminantPresenceProtectionStability) { + int successCount = 0; + bool currentStatus; + bool supported = true; + + Return ret = usb->queryPortStatus(); + ASSERT_TRUE(ret.isOk()); + auto res = usb_cb_2->WaitForCallback(kCallbackNameNotifyPortStatusChange_1_2); + EXPECT_TRUE(res.no_timeout); + EXPECT_EQ(kCallbackIdentifier, res.args->last_usb_cookie); + EXPECT_EQ(Status::SUCCESS, res.args->usb_last_status); + + if (!res.args->usb_last_port_status.supportsEnableContaminantPresenceProtection) return; + + for (int count = 1; count <= 10; count++) { + currentStatus = !(res.args->usb_last_port_status.contaminantProtectionStatus == + ContaminantProtectionStatus::DISABLED); + + ret = usb->enableContaminantPresenceProtection( + res.args->usb_last_port_status.status_1_1.status.portName, !currentStatus); + ASSERT_TRUE(ret.isOk()); + res = usb_cb_2->WaitForCallback(kCallbackNameNotifyPortStatusChange_1_2); + EXPECT_TRUE(res.no_timeout); + EXPECT_EQ(kCallbackIdentifier, res.args->last_usb_cookie); + if (!currentStatus == !(res.args->usb_last_port_status.contaminantProtectionStatus == + ContaminantProtectionStatus::DISABLED)) + successCount++; + } + + if (!supported) EXPECT_GE(successCount, 9); +} + +int main(int argc, char** argv) { + ::testing::AddGlobalTestEnvironment(UsbHidlEnvironment::Instance()); + ::testing::InitGoogleTest(&argc, argv); + UsbHidlEnvironment::Instance()->init(&argc, argv); + int status = RUN_ALL_TESTS(); + ALOGI("Test result = %d", status); + return status; +} From 8972040239b21a92b13eb62dc2b79b56ef744fb2 Mon Sep 17 00:00:00 2001 From: Brian Stack Date: Mon, 7 Jan 2019 16:28:30 -0800 Subject: [PATCH 408/718] Add VINTF Fragment to Sensors HAL 2.0 Bug: 122267378 Test: Built Cuttlefish, Sensors HAL 2.0 requested on boot Change-Id: Ibe1eaa277852db1b8346caee172632f0951daefc --- sensors/2.0/default/Android.bp | 1 + sensors/2.0/default/android.hardware.sensors@2.0.xml | 11 +++++++++++ 2 files changed, 12 insertions(+) create mode 100644 sensors/2.0/default/android.hardware.sensors@2.0.xml diff --git a/sensors/2.0/default/Android.bp b/sensors/2.0/default/Android.bp index db0b14881e..d83a9c36fe 100644 --- a/sensors/2.0/default/Android.bp +++ b/sensors/2.0/default/Android.bp @@ -35,4 +35,5 @@ cc_binary { "libpower", "libutils", ], + vintf_fragments: ["android.hardware.sensors@2.0.xml"], } diff --git a/sensors/2.0/default/android.hardware.sensors@2.0.xml b/sensors/2.0/default/android.hardware.sensors@2.0.xml new file mode 100644 index 0000000000..1acc8e6113 --- /dev/null +++ b/sensors/2.0/default/android.hardware.sensors@2.0.xml @@ -0,0 +1,11 @@ + + + android.hardware.sensors + hwbinder + 2.0 + + ISensors + default + + + From 6c9e78482249f6e833de5274bd1c4e06873c4c8a Mon Sep 17 00:00:00 2001 From: Pawin Vongmasa Date: Wed, 14 Nov 2018 17:16:10 -0800 Subject: [PATCH 409/718] Revert to new Codec2 HAL This includes the following changes: 1. Revert commit 7570e3cd4b0608d05212c6323e614295ad1164bb. 2. Revert commit 2a40d309b7eefe36d2f78bbff42aafad24eb65b0. 3. Use the new bufferpool (@2.0). 4. Use the old bufferqueue (@1.0). 5. Add IInputSink to eliminate downcasting from IBase. Test: Builds Bug: 112362730 Change-Id: I2b5f2e2821c62cbb7166320e1e128d883e278480 --- media/c2/1.0/Android.bp | 1 + media/c2/1.0/IComponent.hal | 336 +++++++------ media/c2/1.0/IComponentInterface.hal | 23 +- media/c2/1.0/IComponentListener.hal | 82 ++- media/c2/1.0/IComponentStore.hal | 177 +++---- media/c2/1.0/IConfigurable.hal | 218 +++++--- media/c2/1.0/IInputSink.hal | 55 +++ media/c2/1.0/IInputSurface.hal | 66 ++- media/c2/1.0/IInputSurfaceConnection.hal | 29 +- media/c2/1.0/types.hal | 604 ++++++++++++++++------- 10 files changed, 1039 insertions(+), 552 deletions(-) create mode 100644 media/c2/1.0/IInputSink.hal diff --git a/media/c2/1.0/Android.bp b/media/c2/1.0/Android.bp index c37c22b4e2..56c78b2e6e 100644 --- a/media/c2/1.0/Android.bp +++ b/media/c2/1.0/Android.bp @@ -13,6 +13,7 @@ hidl_interface { "IComponentListener.hal", "IComponentStore.hal", "IConfigurable.hal", + "IInputSink.hal", "IInputSurface.hal", "IInputSurfaceConnection.hal", ], diff --git a/media/c2/1.0/IComponent.hal b/media/c2/1.0/IComponent.hal index deb9255ecd..7fd551fc2b 100644 --- a/media/c2/1.0/IComponent.hal +++ b/media/c2/1.0/IComponent.hal @@ -22,13 +22,19 @@ import android.hardware.media.omx@1.0::IGraphicBufferSource; import IConfigurable; import IComponentInterface; import IComponentListener; +import IInputSurface; +import IInputSurfaceConnection; /** - * Interface for a Codec 2.0 component corresponding to API level 1.0 or - * below. Components have two states: stopped and running. The running - * state has three sub-states: executing, tripped and error. + * Interface for a Codec2 component corresponding to API level 1.0 or below. + * Components have two states: stopped and running. The running state has three + * sub-states: executing, tripped and error. + * + * All methods in `IComponent` must not block. If a method call cannot be + * completed in a timely manner, it must return `TIMED_OUT` in the return + * status. */ -interface IComponent extends IComponentInterface { +interface IComponent { // METHODS AVAILABLE WHEN RUNNING // ========================================================================= @@ -38,44 +44,42 @@ interface IComponent extends IComponentInterface { * * This method must be supported in running (including tripped) states. * - * This method must return within 1ms + * It is acceptable for this method to return `OK` and return an error value + * using the IComponentListener::onWorkDone() callback. * - * It is acceptable for this method to return OK and return an error value - * using the onWorkDone() callback. - * - * @param workBundle WorkBundle object containing Works to queue to the - * component. + * @param workBundle `WorkBundle` object containing a list of `Work` objects + * to queue to the component. * @return status Status of the call, which may be - * - OK - Works in \p workBundle were successfully queued. - * - BAD_INDEX - Some component(s) in some Work do(es) not exist. - * - CANNOT_DO - The components are not tunneled. - * - NO_MEMORY - Not enough memory to queue \p workBundle. - * - CORRUPTED - Some unknown error prevented queuing the Works. - * (unexpected). + * - `OK` - Works in @p workBundle were successfully queued. + * - `BAD_INDEX` - Some component id in some `Worklet` is not valid. + * - `CANNOT_DO` - The components are not tunneled but some `Work` object + * contains tunneling information. + * - `NO_MEMORY` - Not enough memory to queue @p workBundle. + * - `TIMED_OUT` - The operation cannot be finished in a timely manner. + * - `CORRUPTED` - Some unknown error occurred. */ queue(WorkBundle workBundle) generates (Status status); /** - * Discards and abandons any pending work for the component. + * Discards and abandons any pending `Work` items for the component. * * This method must be supported in running (including tripped) states. * - * This method must return within 5ms. + * `Work` that could be immediately abandoned/discarded must be returned in + * @p flushedWorkBundle. The order in which queued `Work` items are + * discarded can be arbitrary. * - * Work that could be immediately abandoned/discarded must be returned in - * \p flushedWorks; this can be done in an arbitrary order. - * - * Work that could not be abandoned or discarded immediately must be marked - * to be discarded at the earliest opportunity, and must be returned via - * the onWorkDone() callback. This must be completed within 500ms. + * `Work` that could not be abandoned or discarded immediately must be + * marked to be discarded at the earliest opportunity, and must be returned + * via IComponentListener::onWorkDone(). This must be completed within + * 500ms. * * @return status Status of the call, which may be - * - OK - The component has been successfully flushed. - * - TIMED_OUT - The flush could not be completed within the time limit. - * (unexpected) - * - CORRUPTED - Some unknown error prevented flushing from - * completion. (unexpected) - * @return flushedWorkBundle WorkBundle object containing flushed Works. + * - `OK` - The component has been successfully flushed. + * - `TIMED_OUT` - The operation cannot be finished in a timely manner. + * - `CORRUPTED` - Some unknown error occurred. + * @return flushedWorkBundle `WorkBundle` object containing flushed `Work` + * items. */ flush( ) generates ( @@ -87,42 +91,39 @@ interface IComponent extends IComponentInterface { * Drains the component, and optionally downstream components. This is a * signalling method; as such it does not wait for any work completion. * - * Marks last work item as "drain-till-here", so component is notified not - * to wait for further work before it processes work already queued. This - * method can also be used to set the end-of-stream flag after work has been - * queued. Client can continue to queue further work immediately after this - * method returns. + * The last `Work` item is marked as "drain-till-here", so the component is + * notified not to wait for further `Work` before it processes what is + * already queued. This method can also be used to set the end-of-stream + * flag after `Work` has been queued. Client can continue to queue further + * `Work` immediately after this method returns. * * This method must be supported in running (including tripped) states. * - * This method must return within 1ms. - * - * Work that is completed must be returned via the onWorkDone() callback. + * `Work` that is completed must be returned via + * IComponentListener::onWorkDone(). * * @param withEos Whether to drain the component with marking end-of-stream. * @return status Status of the call, which may be - * - OK - The drain request has been successfully recorded. - * - TIMED_OUT - The flush could not be completed within the time limit. - * (unexpected) - * - CORRUPTED - Some unknown error prevented flushing from completion. - * (unexpected) + * - `OK` - The drain request has been successfully recorded. + * - `TIMED_OUT` - The operation cannot be finished in a timely manner. + * - `CORRUPTED` - Some unknown error occurred. */ drain(bool withEos) generates (Status status); /** * Starts using a surface for output. * - * @param blockPoolId The id of the BlockPool to be associated with the - * output surface. - * @param surface A surface to use for codec output. + * This method must not block. + * + * @param blockPoolId Id of the `C2BlockPool` to be associated with the + * output surface. + * @param surface Output surface. * @return status Status of the call, which may be - * - OK - The operation completed successfully. - * - CANNOT_DO - The component does not support an output surface. - * - REFUSED - The output surface cannot be accessed. - * - TIMED_OUT - The component could not be connected within the time - * limit. (unexpected) - * - CORRUPTED - Some unknown error prevented connecting the component. - * (unexpected) + * - `OK` - The operation completed successfully. + * - `CANNOT_DO` - The component does not support an output surface. + * - `REFUSED` - The output surface cannot be accessed. + * - `TIMED_OUT` - The operation cannot be finished in a timely manner. + * - `CORRUPTED` - Some unknown error occurred. */ setOutputSurface( uint64_t blockPoolId, @@ -132,65 +133,101 @@ interface IComponent extends IComponentInterface { ); /** - * Starts using a persistent OMX input surface for a component. + * Starts using an input surface. * * The component must be in running state. * - * @param producer Producer component of an OMX persistent input surface. - * @param source Source component of an OMX persistent input surface. + * @param inputSurface Input surface to connect to. * @return status Status of the call, which may be - * - OK - The operation completed successfully. - * - CANNOT_DO - The component does not support an input surface. - * - BAD_STATE - Component is not in running state. - * - DUPLICATE - The component is already connected to an input surface. - * - REFUSED - The input surface is already in use. - * - NO_MEMORY - Not enough memory to start the component. - * - TIMED_OUT - The component could not be connected within the time - * limit. (unexpected) - * - CORRUPTED - Some unknown error prevented connecting the component. - * (unexpected) + * - `OK` - The operation completed successfully. + * - `CANNOT_DO` - The component does not support an input surface. + * - `BAD_STATE` - The component is not in running state. + * - `DUPLICATE` - The component is already connected to an input surface. + * - `REFUSED` - The input surface is already in use. + * - `NO_MEMORY` - Not enough memory to start the component. + * - `TIMED_OUT` - The operation cannot be finished in a timely manner. + * - `CORRUPTED` - Some unknown error occurred. + * @return connection `IInputSurfaceConnection` object, which can be used to + * query and configure properties of the connection. This cannot be + * null. + */ + connectToInputSurface( + IInputSurface inputSurface + ) generates ( + Status status, + IInputSurfaceConnection connection + ); + + /** + * Starts using an OMX input surface. + * + * The component must be in running state. + * + * This method is similar to connectToInputSurface(), but it takes an OMX + * input surface (as a pair of `IGraphicBufferProducer` and + * `IGraphicBufferSource`) instead of Codec2's own `IInputSurface`. + * + * @param producer Producer component of an OMX input surface. + * @param source Source component of an OMX input surface. + * @return status Status of the call, which may be + * - `OK` - The operation completed successfully. + * - `CANNOT_DO` - The component does not support an OMX input surface. + * - `BAD_STATE` - The component is not in running state. + * - `DUPLICATE` - The component is already connected to an input surface. + * - `REFUSED` - The input surface is already in use. + * - `NO_MEMORY` - Not enough memory to start the component. + * - `TIMED_OUT` - The operation cannot be finished in a timely manner. + * - `CORRUPTED` - Some unknown error occurred. + * @return connection `IInputSurfaceConnection` object, which can be used to + * query and configure properties of the connection. This cannot be + * null. */ connectToOmxInputSurface( IGraphicBufferProducer producer, IGraphicBufferSource source - ) generates (Status status); + ) generates ( + Status status, + IInputSurfaceConnection connection + ); /** * Stops using an input surface. * - * This call is used for both Codec 2.0 and OMX input surfaces. - * * The component must be in running state. * * @return status Status of the call, which may be - * - OK - The operation completed successfully. - * - CANNOT_DO - The component does not support an input surface. - * - BAD_STATE - Component is not in running state. - * - NOT_FOUND - The component is not connected to an input surface. - * - TIMED_OUT - The component could not be connected within the time - * limit. (unexpected) - * - CORRUPTED - Some unknown error prevented connecting the component. - * (unexpected) + * - `OK` - The operation completed successfully. + * - `CANNOT_DO` - The component does not support an input surface. + * - `BAD_STATE` - The component is not in running state. + * - `NOT_FOUND` - The component is not connected to an input surface. + * - `TIMED_OUT` - The operation cannot be finished in a timely manner. + * - `CORRUPTED` - Some unknown error occurred. */ disconnectFromInputSurface() generates (Status Status); /** - * Creates a local block pool backed by the given allocator and returns its - * identifier. + * Creates a local `C2BlockPool` backed by the given allocator and returns + * its id. * - * This call must return within 100 msec. + * The returned @p blockPoolId is the only way the client can refer to a + * `C2BlockPool` object in the component. The id can be passed to + * setOutputSurface() or used in some C2Param objects later. * - * @param allocatorId The Codec 2.0 allocator ID + * The created `C2BlockPool` object can be destroyed by calling + * destroyBlockPool(), reset() or release(). reset() and release() must + * destroy all `C2BlockPool` objects that have been created. + * + * @param allocatorId Id of a `C2Allocator`. * @return status Status of the call, which may be - * - OK - The operation completed successfully. - * - NO_MEMORY - Not enough memory to create the pool. - * - BAD_VALUE - Invalid allocator. - * - TIMED_OUT - The pool could not be created within the time - * limit. (unexpected) - * - CORRUPTED - Some unknown error prevented creating the pool. - * (unexpected) - * @return blockPoolId The Codec 2.0 blockpool ID for the created pool. - * @return configurable Configuration interface for the created pool. + * - `OK` - The operation completed successfully. + * - `NO_MEMORY` - Not enough memory to create the pool. + * - `BAD_VALUE` - @p allocatorId is not recognized. + * - `TIMED_OUT` - The operation cannot be finished in a timely manner. + * - `CORRUPTED` - Some unknown error occurred. + * @return blockPoolId Id of the created C2BlockPool object. This may be + * used in setOutputSurface() if the allocator + * @return configurable Configuration interface for the created pool. This + * must not be null. */ createBlockPool(uint32_t allocatorId) generates ( Status status, @@ -201,17 +238,13 @@ interface IComponent extends IComponentInterface { /** * Destroys a local block pool previously created by createBlockPool(). * - * This call must return within 100 msec. - * - * @param blockPoolId The block pool id previously returned by + * @param blockPoolId Id of a `C2BlockPool` that was previously returned by * createBlockPool(). * @return status Status of the call, which may be - * - OK - The operation completed successfully. - * - NOT_FOUND - The supplied blockPoolId is not valid. - * - TIMED_OUT - The pool could not be destroyedwithin the time limit. - * (unexpected) - * - CORRUPTED - Some unknown error prevented destruction of the pool. - * (unexpected) + * - `OK` - The operation completed successfully. + * - `NOT_FOUND` - The supplied blockPoolId is not valid. + * - `TIMED_OUT` - The operation cannot be finished in a timely manner. + * - `CORRUPTED` - Some unknown error occurred. */ destroyBlockPool(uint64_t blockPoolId) generates (Status status); @@ -223,28 +256,24 @@ interface IComponent extends IComponentInterface { * * This method must be supported in stopped state as well as tripped state. * - * If the return value is OK, the component must be in the running state. - * If the return value is BAD_STATE or DUPLICATE, no state change is - * expected as a response to this call. - * Otherwise, the component must be in the stopped state. + * If the return value is `OK`, the component must be in the running state. + * If the return value is `BAD_STATE` or `DUPLICATE`, no state change is + * expected as a response to this call. Otherwise, the component must be in + * the stopped state. * * If a component is in the tripped state and start() is called while the - * component configuration still results in a trip, start must succeed and - * a new onTripped callback must be used to communicate the configuration + * component configuration still results in a trip, start() must succeed and + * a new onTripped() callback must be used to communicate the configuration * conflict that results in the new trip. * - * This method must return within 500ms. - * * @return status Status of the call, which may be - * - OK - The component has started successfully. - * - BAD_STATE - Component is not in stopped or tripped state. - * - DUPLICATE - When called during another start call from another - * thread. - * - NO_MEMORY - Not enough memory to start the component. - * - TIMED_OUT - The component could not be started within the time limit. - * (unexpected) - * - CORRUPTED - Some unknown error prevented starting the component. - * (unexpected) + * - `OK` - The component has started successfully. + * - `BAD_STATE` - Component is not in stopped or tripped state. + * - `DUPLICATE` - When called during another start call from another + * thread. + * - `NO_MEMORY` - Not enough memory to start the component. + * - `TIMED_OUT` - The operation cannot be finished in a timely manner. + * - `CORRUPTED` - Some unknown error occurred. */ start() generates (Status status); @@ -255,22 +284,22 @@ interface IComponent extends IComponentInterface { * * This method must return withing 500ms. * - * Upon this call, all pending work must be abandoned. - * If the return value is BAD_STATE or DUPLICATE, no state change is - * expected as a response to this call. - * For all other return values, the component must be in the stopped state. + * Upon this call, all pending `Work` must be abandoned. + * + * If the return value is `BAD_STATE` or `DUPLICATE`, no state change is + * expected as a response to this call. For all other return values, the + * component must be in the stopped state. * * This does not alter any settings and tunings that may have resulted in a * tripped state. * * @return status Status of the call, which may be - * - OK - The component has stopped successfully. - * - BAD_STATE - Component is not in running state. - * - DUPLICATE - When called during another stop call from another thread. - * - TIMED_OUT - The component could not be stopped within the time limit. - * (unexpected) - * - CORRUPTED - Some unknown error prevented starting the component. - * (unexpected) + * - `OK` - The component has stopped successfully. + * - `BAD_STATE` - Component is not in running state. + * - `DUPLICATE` - When called during another stop call from another + * thread. + * - `TIMED_OUT` - The operation cannot be finished in a timely manner. + * - `CORRUPTED` - Some unknown error occurred. */ stop() generates (Status status); @@ -284,25 +313,24 @@ interface IComponent extends IComponentInterface { * * This method must return withing 500ms. * - * After this call returns all work must have been abandoned, all references - * must have been released. + * When this call returns, if @p status is `OK`, all `Work` items must + * have been abandoned, and all resources (including `C2BlockPool` objects + * previously created by createBlockPool()) must have been released. * - * If the return value is BAD_STATE or DUPLICATE, no state change is - * expected as a response to this call. - * For all other return values, the component shall be in the stopped state. + * If the return value is `BAD_STATE` or `DUPLICATE`, no state change is + * expected as a response to this call. For all other return values, the + * component must be in the stopped state. * - * This brings settings back to their default - "guaranteeing" no tripped + * This brings settings back to their default, "guaranteeing" no tripped * state. * * @return status Status of the call, which may be - * - OK - The component has been reset. - * - BAD_STATE - Component is in released state. - * - DUPLICATE - When called during another reset call from another - * thread. - * - TIMED_OUT - The component could not be reset within the time limit. - * (unexpected) - * - CORRUPTED - Some unknown error prevented resetting the component. - * (unexpected) + * - `OK` - The component has been reset. + * - `BAD_STATE` - Component is in released state. + * - `DUPLICATE` - When called during another reset call from another + * thread. + * - `TIMED_OUT` - The operation cannot be finished in a timely manner. + * - `CORRUPTED` - Some unknown error occurred. */ reset() generates (Status status); @@ -311,19 +339,27 @@ interface IComponent extends IComponentInterface { * * This method must be supported in stopped state. * - * This method must return withing 500ms. Upon return all references must - * be abandoned. + * This method destroys the component. Upon return, if @p status is `OK` or + * `DUPLICATE`, all resources must have been released. * * @return status Status of the call, which may be - * - OK - The component has been released. - * - BAD_STATE - The component is running. - * - DUPLICATE - The component is already released. - * - TIMED_OUT - The component could not be released within the time - * limit. (unexpected) - * - CORRUPTED - Some unknown error prevented releasing the component. - * (unexpected) + * - `OK` - The component has been released. + * - `BAD_STATE` - The component is running. + * - `DUPLICATE` - The component is already released. + * - `TIMED_OUT` - The operation cannot be finished in a timely manner. + * - `CORRUPTED` - Some unknown error occurred. */ release() generates (Status status); + /** + * Returns the @ref IComponentInterface instance associated to this + * component. + * + * An @p IConfigurable instance for the component can be obtained by calling + * IComponentInterface::getConfigurable() on the returned @p intf. + * + * @return intf `IComponentInterface` instance. This must not be null. + */ + getInterface() generates (IComponentInterface intf); }; diff --git a/media/c2/1.0/IComponentInterface.hal b/media/c2/1.0/IComponentInterface.hal index d4b30b1b7b..a007d02fe3 100644 --- a/media/c2/1.0/IComponentInterface.hal +++ b/media/c2/1.0/IComponentInterface.hal @@ -19,21 +19,20 @@ package android.hardware.media.c2@1.0; import IConfigurable; /** - * Component interface object. This object contains all of the configuration of + * Component interface object. This object contains all of the configurations of * a potential or actual component. It can be created and used independently of - * an actual Codec 2.0 component instance to query support and parameters for - * various component settings and configurations for a potential component. - * Actual components also expose this interface. + * an actual Codec2 component to query supported parameters for various + * component settings, and configurations for a potential component. + * + * An actual component exposes this interface via IComponent::getInterface(). */ -interface IComponentInterface extends IConfigurable { - /* - * There are no additional methods to IConfigurable interface. +interface IComponentInterface { + /** + * Returns the @ref IConfigurable instance associated to this component + * interface. * - * Component interfaces have no states. - * - * The name of the component or component interface object is a unique name - * for that component or component interface 'class'; however, multiple - * instances of that component must have the same name. + * @return configurable `IConfigurable` instance. This must not be null. */ + getConfigurable() generates (IConfigurable configurable); }; diff --git a/media/c2/1.0/IComponentListener.hal b/media/c2/1.0/IComponentListener.hal index eb71ecbdd5..70d5fb289e 100644 --- a/media/c2/1.0/IComponentListener.hal +++ b/media/c2/1.0/IComponentListener.hal @@ -17,54 +17,112 @@ package android.hardware.media.c2@1.0; /** - * This callback interface is used for handling notifications from IComponent. + * Callback interface for handling notifications from @ref IComponent. */ interface IComponentListener { /** - * Notify the listener that some works have been completed. + * Notify the listener that some `Work` items have been completed. + * + * All the input buffers in the returned `Work` objects must not be used by + * the component after onWorkDone() is called. + * + * @param workBundle List of completed `Work` objects. */ oneway onWorkDone(WorkBundle workBundle); /** * Notify the listener that the component is tripped. + * + * @param settingResults List of failures. */ oneway onTripped(vec settingResults); /** * Notify the listener of an error. * - * @param status Error type. \p status may be `OK`, which means that an - * error has occurred, but the error type is unknown. - * @param errorCode Additional error code. The framework may not recognize - * this. + * @param status Error type. @p status may be `OK`, which means that an + * error has occurred, but the error type does not fit into the type + * `Status`. In this case, additional information is provided by + * @p errorCode. + * @param errorCode Additional error information. The framework may not + * recognize the meaning of this value. */ oneway onError(Status status, uint32_t errorCode); /** - * Information about rendering of a frame. + * Information about rendering of a frame to a `Surface`. */ struct RenderedFrame { /** - * Id of the buffer queue containing the rendered buffer. + * Id of the `BufferQueue` containing the rendered buffer. + * + * This value must have been obtained by an earlier call to + * IGraphicBufferProducer::getUniqueId(). */ uint64_t bufferQueueId; /** * Id of the slot of the rendered buffer. + * + * This value must have been obtained by an earlier call to + * IGraphicBufferProducer::dequeueBuffer() or + * IGraphicBufferProducer::attachBuffer(). */ int32_t slotId; /** - * Timestamp of the rendering (consistent with timestamps in - * the associated BufferQueue). + * Timestamp the rendering happened. + * + * The reference point for the timestamp is determined by the + * `BufferQueue` that performed the rendering. */ int64_t timestampNs; }; /** - * Notify the listener that frames are rendered. + * Notify the listener that frames have been rendered. * - * @param renderedFrames List of information about renderings of frames. + * @param renderedFrames List of @ref RenderedFrame objects. */ oneway onFramesRendered(vec renderedFrames); + + /** + * Identifying information for an input buffer previously queued to the + * component via IComponent::queue(). + */ + struct InputBuffer { + /** + * This value comes from `Work::input.ordinal.frameIndex` in a `Work` + * object that was previously queued. + */ + uint64_t frameIndex; + /** + * This value is an index into `Work::input.buffers` (which is an array) + * in a `Work` object that was previously queued. + */ + uint32_t arrayIndex; + }; + + /** + * Notify the listener that some input buffers are no longer needed by the + * component, and hence can be released or reused by the client. + * + * Input buffers that are contained in a `Work` object returned by an + * earlier onWorkDone() call are assumed released, so they must not appear + * in any onInputBuffersReleased() calls. That means + * onInputBuffersReleased() must only report input buffers that are released + * before the output in the same `Work` item is produced. However, it is + * possible for an input buffer to be returned by onWorkDone() after it has + * been reported by onInputBuffersReleased(). + * + * @note onWorkDone() and onInputBuffersReleased() both notify the client + * that input buffers are no longer needed. However, in order to minimize + * IPC calls, onInputBuffersReleased() should be called only when + * onWorkDone() cannot be called, e.g., the component needs more input + * before an output can be produced. + * + * @param inputBuffers List of `InputBuffer` objects, identifying input + * buffers that are no longer needed by the component. + */ + oneway onInputBuffersReleased(vec inputBuffers); }; diff --git a/media/c2/1.0/IComponentStore.hal b/media/c2/1.0/IComponentStore.hal index 4bfa170283..2aa6a70b5d 100644 --- a/media/c2/1.0/IComponentStore.hal +++ b/media/c2/1.0/IComponentStore.hal @@ -23,27 +23,33 @@ import IComponent; import IConfigurable; import IInputSurface; -interface IComponentStore extends IConfigurable { +/** + * Entry point for Codec2 HAL. + * + * All methods in `IComponentStore` must not block. If a method call cannot be + * completed in a timely manner, it must return `TIMED_OUT` in the return + * status. The only exceptions are getPoolClientManager() and getConfigurable(), + * which must always return immediately. + */ +interface IComponentStore { /** * Creates a component by name. * - * This method must return within 100ms. - * - * @param name Name of the component to create. This should match one of the + * @param name Name of the component to create. This must match one of the * names returned by listComponents(). - * @param listener The component listener to use for the component. - * @param pool The buffer pool client manager of the component listener. - * This must be null if the listener process does not own a buffer pool. + * @param listener Callback receiver. + * @param pool `IClientManager` object of the BufferPool in the client + * process. This may be null if the client does not own a BufferPool. * @return status Status of the call, which may be - * - OK - The component was created successfully. - * - NOT_FOUND - There is no component with the given name. - * - NO_MEMORY - Not enough memory to create the component. - * - TIMED_OUT - The component could not be created within the time limit. - * (unexpected) - * - CORRUPTED - Some unknown error prevented the creation of the - * component. (unexpected) - * @return comp The created component if `Status = OK`. + * - `OK` - The component was created successfully. + * - `NOT_FOUND` - There is no component with the given name. + * - `NO_MEMORY` - Not enough memory to create the component. + * - `TIMED_OUT` - The operation cannot be finished in a timely manner. + * - `CORRUPTED` - Some unknown error occurred. + * @return comp The created component if @p status is `OK`. + * + * @sa IComponentListener. */ createComponent( string name, @@ -57,19 +63,15 @@ interface IComponentStore extends IConfigurable { /** * Creates a component interface by name. * - * This method must return within 100ms. - * * @param name Name of the component interface to create. This should match * one of the names returned by listComponents(). * @return status Status of the call, which may be - * - OK - The component interface was created successfully. - * - NOT_FOUND - There is no component interface with the given name. - * - NO_MEMORY - Not enough memory to create the component interface. - * - TIMED_OUT - The component interface could not be created within the - * time limit. (unexpected) - * - CORRUPTED - Some unknown error prevented the creation of the - * component interface. (unexpected) - * @return compIntf The created component interface if `Status = OK`. + * - `OK` - The component interface was created successfully. + * - `NOT_FOUND` - There is no component interface with the given name. + * - `NO_MEMORY` - Not enough memory to create the component interface. + * - `TIMED_OUT` - The operation cannot be finished in a timely manner. + * - `CORRUPTED` - Some unknown error occurred. + * @return compIntf The created component interface if @p status is `OK`. */ createInterface( string name @@ -83,57 +85,49 @@ interface IComponentStore extends IConfigurable { */ struct ComponentTraits { /** - * Name of the component. + * Name of the component. This must be unique for each component. + * + * This name is use to identify the component to create in + * createComponent() and createComponentInterface(). */ string name; enum Domain : uint32_t { - AUDIO, + OTHER = 0, VIDEO, - OTHER = 0xffffffff, + AUDIO, + IMAGE, }; /** - * Component domain. The framework may not recognize `OTHER`. + * Component domain. */ Domain domain; - /** - * If #domain is `OTHER`, #domainOther can be used to provide additional - * information. Otherwise, #domainOther is ignored. The framework may - * not inspect this value. - */ - uint32_t domainOther; enum Kind : uint32_t { + OTHER = 0, DECODER, ENCODER, - OTHER = 0xffffffff, }; /** - * Component kind. The framework may not recognize `OTHER`. + * Component kind. */ Kind kind; - /** - * If #kind is `OTHER`, #kindOther can be used to provide additional - * information. Otherwise, #kindOther is ignored. The framework may not - * inspect this value. - */ - uint32_t kindOther; /** - * Rank used by MediaCodecList to determine component ordering. Lower + * Rank used by `MediaCodecList` to determine component ordering. Lower * value means higher priority. */ uint32_t rank; /** - * Media type. + * MIME type. */ string mediaType; /** * Aliases for component name for backward compatibility. * - * \note Multiple components can have the same alias (but not the same + * Multiple components can have the same alias (but not the same * component name) as long as their media types differ. */ vec aliases; @@ -142,36 +136,51 @@ interface IComponentStore extends IConfigurable { /** * Returns the list of components supported by this component store. * - * This method must return within 500ms. - * - * @return traits List of component traits for all components supported by this store in no - * particular order. + * @return status Status of the call, which may be + * - `OK` - The operation was successful. + * - `NO_MEMORY` - Not enough memory to complete this method. + * - `TIMED_OUT` - The operation cannot be finished in a timely manner. + * - `CORRUPTED` - Some unknown error occurred. + * @return traits List of component traits for all components supported by + * this store (in no particular order). */ - listComponents() generates (vec traits); + listComponents() generates ( + Status status, + vec traits + ); /** * Creates a persistent input surface that can be used as an input surface * for any IComponent instance * - * This method must return within 100ms. - * - * @return surface A persistent input surface + * @return status Status of the call, which may be + * - `OK` - The operation was successful. + * - `NO_MEMORY` - Not enough memory to complete this method. + * - `TIMED_OUT` - The operation cannot be finished in a timely manner. + * - `CORRUPTED` - Some unknown error occurred. + * @return surface A persistent input surface. This may be null to indicate + * an error. */ - createInputSurface() generates (IInputSurface surface); + createInputSurface() generates ( + Status status, + IInputSurface surface + ); /** - * Returns a list of StructDescriptor object for a set of requested - * structures that this store is aware of. + * Returns a list of `StructDescriptor` objects for a set of requested + * C2Param structure indices that this store is aware of. * * This operation must be performed at best effort, e.g. the component * store must simply ignore all struct indices that it is not aware of. * - * @param indices struct indices to return des + * @param indices Indices of C2Param structures to describe. * @return status Status of the call, which may be - * - OK - The operation completed successfully. - * - NOT_FOUND - Some indices were not known. - * - NO_MEMORY - Not enough memory to complete this method. - * @return structs List of StructDescriptor objects. + * - `OK` - The operation completed successfully. + * - `NOT_FOUND` - Some indices were not known. + * - `NO_MEMORY` - Not enough memory to complete this method. + * - `TIMED_OUT` - The operation cannot be finished in a timely manner. + * - `CORRUPTED` - Some unknown error occurred. + * @return structs List of `StructDescriptor` objects. */ getStructDescriptors( vec indices @@ -181,33 +190,35 @@ interface IComponentStore extends IConfigurable { ); /** - * Returns information required for using BufferPool API in buffer passing. - * If the returned pool is not null, the client can call registerSender() to - * register its IAccessor instance, hence allowing the client to send - * buffers to components hosted by this process. - * - * @return pool If the component store supports receiving buffers via - * BufferPool API, \p pool must be a valid `IClientManager` instance. - * Otherwise, \p pool must be null. - */ - getPoolClientManager( - ) generates ( - IClientManager pool - ); - - /** - * The store must copy the contents of \p src into \p dst without changing - * the format of \p dst. + * Copies the contents of @p src into @p dst without changing the format of + * @p dst. * * @param src Source buffer. * @param dst Destination buffer. * @return status Status of the call, which may be - * - OK - The copy is successful. - * - CANNOT_DO - \p src and \p dst are not compatible. - * - REFUSED - No permission to copy. - * - CORRUPTED - The copy cannot be done. (unexpected) + * - `OK` - The copy is successful. + * - `CANNOT_DO` - @p src and @p dst are not compatible. + * - `REFUSED` - No permission to copy. + * - `TIMED_OUT` - The operation cannot be finished in a timely manner. + * - `CORRUPTED` - Some unknown error occurred. */ copyBuffer(Buffer src, Buffer dst) generates (Status status); + /** + * Returns the `IClientManager` object for the component's BufferPool. + * + * @return pool If the component store supports receiving buffers via + * BufferPool API, @p pool must be a valid `IClientManager` instance. + * Otherwise, @p pool must be null. + */ + getPoolClientManager() generates (IClientManager pool); + + /** + * Returns the @ref IConfigurable instance associated to this component + * store. + * + * @return configurable `IConfigurable` instance. This must not be null. + */ + getConfigurable() generates (IConfigurable configurable); }; diff --git a/media/c2/1.0/IConfigurable.hal b/media/c2/1.0/IConfigurable.hal index cd4dd10151..31dc4d3cba 100644 --- a/media/c2/1.0/IConfigurable.hal +++ b/media/c2/1.0/IConfigurable.hal @@ -17,43 +17,78 @@ package android.hardware.media.c2@1.0; /** - * Generic configuration interface used by all configurable Codec 2.0 - * components. + * Generic configuration interface presented by all configurable Codec2 objects. * - * This interface must be supported in all states of the inheriting - * object, and must not change the state of the inheriting object. + * This interface must be supported in all states of the owning object, and must + * not change the state of the owning object. */ interface IConfigurable { /** - * Returns the name of this object. This must match the name that was - * supplied during the creation of the object. + * Returns the id of the object. This must be unique among all objects of + * the same type hosted by the same store. * - * @return name Name of this object. + * @return id Id of the object. + */ + getId() generates (uint32_t id); + + /** + * Returns the name of the object. + * + * This must match the name that was supplied during the creation of the + * object. + * + * @return name Name of the object. */ getName() generates (string name); /** - * Queries a set of parameters from the object. Querying is performed at - * best effort: the object must query all supported parameters and skip - * unsupported ones, or parameters that could not be allocated. Any errors - * are communicated in the return value. + * Queries a set of parameters from the object. * - * \note Parameter values do not depend on the order of query. + * Querying is performed at best effort: the object must query all supported + * parameters and skip unsupported ones (which may include parameters that + * could not be allocated). Any errors are communicated in the return value. * - * This method must return within 1ms if \p mayBlock is DONT_BLOCK, and - * within 5ms otherwise. + * If @p mayBlock is false, this method must not block. All parameter + * queries that require blocking must be skipped. * - * @param indices List of param indices for params to be queried. + * If @p mayBlock is true, a query may block, but the whole method call + * has to complete in a timely manner, or `status = TIMED_OUT` is returned. + * + * If @p mayBlock is false, this method must not block. Otherwise, this + * method is allowed to block for a certain period of time before completing + * the operation. If the operation is not completed in a timely manner, + * `status = TIMED_OUT` is returned. + * + * @note The order of C2Param objects in @p param does not depend on the + * order of C2Param structure indices in @p indices. + * + * \par For IComponent + * + * When the object type is @ref IComponent, this method must be supported in + * any state except released. This call must not change the state nor the + * internal configuration of the component. + * + * The blocking behavior of this method differs among states: + * - In the stopped state, this must be non-blocking. @p mayBlock is + * ignored. (The method operates as if @p mayBlock was false.) + * - In any of the running states, this method may block momentarily if + * @p mayBlock is true. However, if the call cannot be completed in a + * timely manner, `status = TIMED_OUT` is returned. + * + * @param indices List of C2Param structure indices to query. * @param mayBlock Whether this call may block or not. * @return status Status of the call, which may be - * - OK - All parameters could be queried. - * - BAD_INDEX - All supported parameters could be queried, but some - * parameters were not supported. - * - NO_MEMORY - Could not allocate memory for a supported parameter. - * - BLOCKING - Querying some parameters requires blocking. - * - CORRUPTED - Some unknown error prevented the querying of the - * parameters. (unexpected) - * @return params List of params queried corresponding to \p indices. + * - `OK` - All parameters could be queried. + * - `BAD_INDEX` - All supported parameters could be queried, but some + * parameters were not supported. + * - `NO_MEMORY` - Could not allocate memory for a supported parameter. + * - `BLOCKING` - Querying some parameters requires blocking, but + * @p mayBlock is false. + * - `TIMED_OUT` - The operation cannot be finished in a timely manner. + * - `CORRUPTED` - Some unknown error occurred. + * @return params Flattened representation of C2Param objects. + * + * @sa Params. */ query( vec indices, @@ -64,31 +99,60 @@ interface IConfigurable { ); /** - * Sets a set of parameters for the object. Tuning is performed at best - * effort: the object must update all supported configuration at best - * effort and skip unsupported parameters. Any errors are communicated in - * the return value and in \p failures. + * Sets a set of parameters for the object. * - * \note Parameter tuning DOES depend on the order of the tuning parameters. - * E.g. some parameter update may allow some subsequent parameter update. + * Tuning is performed at best effort: the object must update all supported + * configurations at best effort and skip unsupported parameters. Any errors + * are communicated in the return value and in @p failures. * - * This method must return within 1ms if \p mayBlock is false, and within - * 5ms otherwise. + * A non-strict parameter update with an unsupported value shall cause an + * update to the closest supported value. A strict parameter update with an + * unsupported value shall be skipped and a failure shall be returned. + * + * If @p mayBlock is false, this method must not block. An update that + * requires blocking shall be skipped and a failure shall be returned. + * + * If @p mayBlock is true, an update may block, but the whole method call + * has to complete in a timely manner, or `status = TIMED_OUT` is returned. + * + * The final values for all parameters set are propagated back to the caller + * in @p params. + * + * \par For IComponent + * + * When the object type is @ref IComponent, this method must be supported in + * any state except released. + * + * The blocking behavior of this method differs among states: + * - In the stopped state, this must be non-blocking. @p mayBlock is + * ignored. (The method operates as if @p mayBlock was false.) + * - In any of the running states, this method may block momentarily if + * @p mayBlock is true. However, if the call cannot be completed in a + * timely manner, `status = TIMED_OUT` is returned. + * + * @note Parameter tuning @e does depend on the order of the tuning + * parameters, e.g., some parameter update may enable some subsequent + * parameter update. * * @param inParams Requested parameter updates. * @param mayBlock Whether this call may block or not. * @return status Status of the call, which may be - * - OK - All parameters could be updated successfully. - * - BAD_INDEX - All supported parameters could be updated successfully, - * but some parameters were not supported. - * - NO_MEMORY - Some supported parameters could not be updated - * successfully because they contained unsupported values. - * These are returned in \p failures. - * - BLOCKING - Setting some parameters requires blocking. - * - CORRUPTED - Some unknown error prevented the update of the - * parameters. (unexpected) - * @return failures List of parameter failures. - * @return outParams Resulting values for the configured parameters. + * - `OK` - All parameters could be updated successfully. + * - `BAD_INDEX` - All supported parameters could be updated successfully, + * but some parameters were not supported. + * - `NO_MEMORY` - Some supported parameters could not be updated + * successfully because they contained unsupported values. + * These are returned in @p failures. + * - `BLOCKING` - Setting some parameters requires blocking, but + * @p mayBlock is false. + * - `TIMED_OUT` - The operation cannot be finished in a timely manner. + * - `CORRUPTED` - Some unknown error occurred. + * @return failures List of update failures. + * @return outParams Flattened representation of configured parameters. The + * order of parameters in @p outParams is based on the order of + * requested updates in @p inParams. + * + * @sa SettingResult. */ config( Params inParams, @@ -103,22 +167,19 @@ interface IConfigurable { // ========================================================================= /** - * Returns a selected range of the set of supported parameters. + * Returns a list of supported parameters within a selected range of C2Param + * structure indices. * - * The set of supported parameters are represented in a vector with a - * start index of 0, and the selected range are indices into this vector. - * Fewer than \p count parameters are returned if the selected range is - * not fully/not at all part of the available vector indices. - * - * This method must return within 1ms. - * - * @param start start index of selected range - * @param count size of the selected + * @param start The first index of the selected range. + * @param count The length of the selected range. * @return status Status of the call, which may be - * - OK - The operation completed successfully. - * - NO_MEMORY - Not enough memory to complete this method. - * @return params Vector containing the selected range of supported - * parameters. + * - `OK` - The operation completed successfully. + * - `NO_MEMORY` - Not enough memory to complete this method. + * @return params List of supported parameters in the selected range. This + * list may have fewer than @p count elements if some indices in the + * range are not supported. + * + * @sa ParamDescriptor. */ querySupportedParams( uint32_t start, @@ -131,23 +192,42 @@ interface IConfigurable { /** * Retrieves the supported values for the queried fields. * - * Upon return the object must fill in the supported - * values for the fields listed as well as a status for each field. - * Object shall process all fields queried even if some queries fail. + * The object must process all fields queried even if some queries fail. * - * This method must return within 1ms if \p mayBlock is false, and within - * 5ms otherwise. + * If @p mayBlock is false, this method must not block. Otherwise, this + * method is allowed to block for a certain period of time before completing + * the operation. If the operation cannot be completed in a timely manner, + * `status = TIMED_OUT` is returned. * - * @param inFields Vector of field queries. + * \par For IComponent + * + * When the object type is @ref IComponent, this method must be supported in + * any state except released. + * + * The blocking behavior of this method differs among states: + * - In the stopped state, this must be non-blocking. @p mayBlock is + * ignored. (The method operates as if @p mayBlock was false.) + * - In any of the running states, this method may block momentarily if + * @p mayBlock is true. However, if the call cannot be completed in a + * timely manner, `status = TIMED_OUT` is returned. + * + * @param inFields List of field queries. * @param mayBlock Whether this call may block or not. * @return status Status of the call, which may be - * - OK - The operation completed successfully. - * - BLOCKING - Querying some parameters requires blocking. - * - NO_MEMORY - Not enough memory to complete this method. - * - BAD_INDEX - At least one field was not recognized as a component - * field. - * @return outFields Vector containing supported values and query result - * for the selected fields. + * - `OK` - The operation completed successfully. + * - `BLOCKING` - Querying some parameters requires blocking, but + * @p mayBlock is false. + * - `NO_MEMORY` - Not enough memory to complete this method. + * - `BAD_INDEX` - At least one field was not recognized as a component + * field. + * - `BLOCKING` - Querying some fields requires blocking, but @p mayblock + * is false. + * - `TIMED_OUT` - The operation cannot be finished in a timely manner. + * - `CORRUPTED` - Some unknown error occurred. + * @return outFields List of supported values and results for the + * supplied queries. + * + * @sa FieldSupportedValuesQuery, FieldSupportedValuesQueryResult. */ querySupportedValues( vec inFields, diff --git a/media/c2/1.0/IInputSink.hal b/media/c2/1.0/IInputSink.hal new file mode 100644 index 0000000000..809c27a7aa --- /dev/null +++ b/media/c2/1.0/IInputSink.hal @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.media.c2@1.0; + +import android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer; + +import IConfigurable; + +/** + * An `IInputSink` is a receiver of work items. + * + * An @ref IComponent instance can present itself as an `IInputSink` via a thin + * wrapper. + * + * @sa IInputSurface, IComponent. + */ +interface IInputSink { + /** + * Feeds work to the sink. + * + * @param workBundle `WorkBundle` object containing a list of `Work` objects + * to queue to the component. + * @return status Status of the call, which may be + * - `OK` - Works in @p workBundle were successfully queued. + * - `BAD_INDEX` - Some component id in some `Worklet` is not valid. + * - `CANNOT_DO` - Tunneling has not been set up for this sink, but some + * `Work` object contains tunneling information. + * - `NO_MEMORY` - Not enough memory to queue @p workBundle. + * - `TIMED_OUT` - The operation cannot be finished in a timely manner. + * - `CORRUPTED` - Some unknown error occurred. + */ + queue(WorkBundle workBundle) generates (Status status); + + /** + * Returns the @ref IConfigurable instance associated to this sink. + * + * @return configurable `IConfigurable` instance. This must not be null. + */ + getConfigurable() generates (IConfigurable configurable); +}; + diff --git a/media/c2/1.0/IInputSurface.hal b/media/c2/1.0/IInputSurface.hal index c083a21879..d11ce15e0e 100644 --- a/media/c2/1.0/IInputSurface.hal +++ b/media/c2/1.0/IInputSurface.hal @@ -19,43 +19,57 @@ package android.hardware.media.c2@1.0; import android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer; import IConfigurable; -import IComponent; +import IInputSink; import IInputSurfaceConnection; /** - * Input surface that can be configured for the IComponent. + * Input surface for a Codec2 component. + * + * An input surface is an instance of `IInputSurface`, which may be + * created by calling IComponentStore::createInputSurface(). Once created, the + * client may + * 1. write data to it via the `IGraphicBufferProducer` interface; and + * 2. use it as input to a Codec2 encoder. + * + * @sa IInputSurfaceConnection, IComponentStore::createInputSurface(), + * IComponent::connectToInputSurface(). */ -interface IInputSurface extends IGraphicBufferProducer { +interface IInputSurface { + /** + * Returns the producer interface into the internal buffer queue. + * + * @return producer `IGraphicBufferProducer` instance. This must not be + * null. + */ + getGraphicBufferProducer() generates (IGraphicBufferProducer producer); /** - * Connects this input surface to a component. + * Returns the @ref IConfigurable instance associated to this input surface. * - * This call must return within 100 ms. - * - * @param component The component to connect to. This must have type - * IComponent. - * @return status Status of the call, which may be - * - OK - The operation succeeded. - * - BAD_STATE - The component is in running state. - * - DUPLICATE - The surface is already connected to a component. - * - NO_MEMORY - Could not allocate memory to connect to the component. - * - CORRUPTED - Some unknown error prevented the connection. (unexpected) - * @return connection Connection object that is used to disconnect - * from the component. + * @return configurable `IConfigurable` instance. This must not be null. */ - connectToComponent( - IComponent component + getConfigurable() generates (IConfigurable configurable); + + /** + * Connects the input surface to an input sink. + * + * This function is generally called from inside the implementation of + * IComponent::connectToInputSurface(), where @p sink is a thin wrapper of + * the component that consumes buffers from this surface. + * + * @param sink Input sink. See `IInputSink` for more information. + * @return status Status of the call, which may be + * - `OK` - Configuration successful. + * - `BAD_VALUE` - @p sink is invalid. + * - `CORRUPTED` - Some unknown error occurred. + * @return connection `IInputSurfaceConnection` object. This must not be + * null if @p status is `OK`. + */ + connect( + IInputSink sink ) generates ( Status status, IInputSurfaceConnection connection ); - - /** - * Returns the Codec 2.0 configuration object for this surface. - * - * @return configurable The configuration object for this surface. - */ - getConfigurable() generates (IConfigurable configurable); - }; diff --git a/media/c2/1.0/IInputSurfaceConnection.hal b/media/c2/1.0/IInputSurfaceConnection.hal index 500091dbbc..035b1159b4 100644 --- a/media/c2/1.0/IInputSurfaceConnection.hal +++ b/media/c2/1.0/IInputSurfaceConnection.hal @@ -16,20 +16,33 @@ package android.hardware.media.c2@1.0; -interface IInputSurfaceConnection { +import IConfigurable; +/** + * Connection between a component and an input surface. + * + * An instance of `IInputSurfaceConnection` contains an `IConfigurable` + * interface for querying and configuring properties of the connection. + */ +interface IInputSurfaceConnection { /** - * Disconnects this input surface from the component. - * - * This call must return within 100 ms. + * Destroys the connection between an input surface and a component. * * @return status Status of the call, which may be - * - OK - The operation succeeded. - * - BAD_STATE - The component is not in running state. - * - NOT_FOUND - The surface is not connected to a component. - * - CORRUPTED - Some unknown error prevented the connection. (unexpected) + * - `OK` - The disconnection succeeded. + * - `BAD_STATE` - The component is not in running state. + * - `NOT_FOUND` - The surface is not connected to a component. + * - `CORRUPTED` - Some unknown error occurred. */ disconnect() generates (Status status); + /** + * Returns the @ref IConfigurable instance associated to this connection. + * + * This can be used to customize the connection. + * + * @return configurable `IConfigurable` instance. This must not be null. + */ + getConfigurable() generates (IConfigurable configurable); }; diff --git a/media/c2/1.0/types.hal b/media/c2/1.0/types.hal index 252d781e7f..ec422b1f40 100644 --- a/media/c2/1.0/types.hal +++ b/media/c2/1.0/types.hal @@ -18,220 +18,278 @@ package android.hardware.media.c2@1.0; import android.hardware.media.bufferpool@2.0::BufferStatusMessage; +/** + * Common return values for Codec2 operations. + */ enum Status : int32_t { - /** operation completed successfully */ + /** Operation completed successfully. */ OK = 0, // bad input - /** argument has invalid value (user error) */ + /** Argument has invalid value (user error). */ BAD_VALUE = -22, - /** argument uses invalid index (user error) */ + /** Argument uses invalid index (user error). */ BAD_INDEX = -75, - /** argument/index is valid but not possible */ + /** Argument/Index is valid but not possible. */ CANNOT_DO = -2147483646, // bad sequencing of events - /** object already exists */ + /** Object already exists. */ DUPLICATE = -17, - /** object not found */ + /** Object not found. */ NOT_FOUND = -2, - /** operation is not permitted in the current state */ + /** Operation is not permitted in the current state. */ BAD_STATE = -38, - /** operation would block but blocking is not permitted */ + /** Operation would block but blocking is not permitted. */ BLOCKING = -9930, // bad environment - /** not enough memory to complete operation */ + /** Not enough memory to complete operation. */ NO_MEMORY = -12, - /** missing permission to complete operation */ + /** Missing permission to complete operation. */ REFUSED = -1, - /** operation did not complete within timeout */ + /** Operation did not complete within timeout. */ TIMED_OUT = -110, // missing functionality - /** operation is not implemented/supported (optional only) */ + /** Operation is not implemented/supported (optional only). */ OMITTED = -74, // unknown fatal - /** some unexpected error prevented the operation */ + /** Some unexpected error prevented the operation. */ CORRUPTED = -2147483648, // uninitialized - /** status has not been initialized */ + /** Status has not been initialized. */ NO_INIT = -19, }; /** - * Codec 2.0 parameter index + * C2Param structure index. + * + * This is a number that is unique for each C2Param structure type. + * + * @sa Codec 2.0 standard. */ typedef uint32_t ParamIndex; /** - * Codec 2.0 parameter structure + * Flattened representation of C2Param objects. * - * The description of a Params is provided by supplying a ParamIndex to - * IComponentStore::getStructDescriptors(). + * The `Params` type is an array of bytes made up by concatenating a list of + * C2Param objects. The start index (offset into @ref Params) of each C2Param + * object in the list is divisible by 8. Up to 7 padding bytes may be added + * after each C2Param object to achieve this 64-bit alignment. + * + * Each C2Param object has the following layout: + * - 4 bytes: C2Param structure index (of type @ref ParamIndex) identifying the + * type of the C2Param object. + * - 4 bytes: size of the C2Param object (unsigned 4-byte integer). + * - (size - 8) bytes: data of the C2Param object. + * + * In order to interpret each C2Param object correctly, its structure must be + * described by IComponentStore::getStructDescriptors(). + * + * @note Please refer to the Codec 2.0 standard for the list of standard + * parameter structures. + * + * @sa Codec 2.0 standard. */ typedef vec Params; /** - * Struct uniquely specifying a field in an arbitrary parameter structure. + * Identifying information of a field relative to a known C2Param structure. + * + * Within a given C2Param structure, each field is uniquely identified by @ref + * FieldId. */ struct FieldId { - /** Offset of the field in bytes */ + /** Offset of the field in bytes. */ uint32_t offset; - /** Size of the field in bytes */ + /** Size of the field in bytes. */ uint32_t size; }; /** - * Struct representing a location of a field in a parameter with a given index. + * Reference to a field in a C2Param structure. */ struct ParamField { - /** Index of the parameter */ + /** Index of the C2Param structure. */ ParamIndex index; - /** Field identifier */ + /** Identifier of the field inside the C2Param structure. */ FieldId fieldId; }; /** - * Struct describing basic properties of a parameter with a given index. + * Usage description of a C2Param structure. + * + * @ref ParamDescriptor is returned by IConfigurable::querySupportedParams(). */ struct ParamDescriptor { - /** Parameter index */ + /** + * Index of the C2Param structure being described. + */ ParamIndex index; enum Attrib : uint32_t { /** - * Parameter is required to be specified. + * The parameter is required to be specified. */ REQUIRED = 1u << 0, /** - * Parameter retains its value. + * The parameter retains its value. */ PERSISTENT = 1u << 1, /** - * Parameter is strict. + * The parameter is strict. */ STRICT = 1u << 2, /** - * Parameter is publicly read-only. + * The parameter is publicly read-only. */ READ_ONLY = 1u << 3, /** - * Parameter must not be visible to clients. + * The parameter must not be visible to clients. */ HIDDEN = 1u << 4, /** - * Parameter must not be used by framework (other than testing). + * The parameter must not be used by framework (other than testing). */ INTERNAL = 1u << 5, /** - * Parameter is publicly constant (hence read-only). + * The parameter is publicly constant (hence read-only). */ CONST = 1u << 6, }; - /** Parameter attributes */ bitfield attrib; - /** Parameter name */ + /** + * Name of the structure. This must be unique for each structure. + */ string name; - /** index of other parameters that this parameter depends on */ + /** + * Indices of other C2Param structures that this C2Param structure depends + * on. + */ vec dependencies; }; -// Generic way to describe supported numeric values for Codec 2.0 interfaces. +// Generic way to describe supported numeric values for Codec2 interfaces. /** - * An untyped value that can fit on 64 bits - the type of which is communicated - * via a separate channel (FieldType). + * An untyped value that can fit in 64 bits, the type of which is communicated + * via a separate channel (@ref FieldSupportedValues.type). */ typedef uint64_t PrimitiveValue; /* - * Generic supported values for a field. + * Description of supported values for a field. * - * This can be either a range or a set of values. The range can be linear or - * geometric with clear minimum and maximum values, and can have an optional - * step size or geometric ratio. Values can optionally represent flags. + * This can be a continuous range or a discrete set of values. */ struct FieldSupportedValues { + /** + * Used if #type is `RANGE`. + * + * If the `step` member is 0, and `num` and `denom` are both 1, the `Range` + * structure represents a closed interval bounded by `min` and `max`. + * + * Otherwise, the #Range structure represents a finite sequence of numbers + * produced from the following recurrence relation: + * + * @code + * v[0] = min + * v[i] = v[i - 1] * num / denom + step ; i >= 1 + * @endcode + * + * Both the ratio `num / denom` and the value `step` must be positive. The + * last number in the sequence described by this #Range structure is the + * largest number in the sequence that is smaller than or equal to `max`. + * + * @note + * The division in the formula may truncate the result if the data type of + * these values is an integral type. + */ struct Range { + /** + * Lower end of the range (inclusive). + */ PrimitiveValue min; + /** + * Upper end of the range (inclusive). + */ PrimitiveValue max; + /** + * The non-homogeneous term in the recurrence relation. + */ PrimitiveValue step; + /** + * The numerator of the scale coefficient in the recurrence relation. + */ PrimitiveValue num; + /** + * The denominator of the scale coefficient in the recurrence relation. + */ PrimitiveValue denom; }; enum Type : int32_t { /** No supported values */ - EMPTY, - /** Numeric range that can be continuous or discrete */ + EMPTY = 0, + /** Numeric range, described in a #Range structure */ RANGE, /** List of values */ VALUES, /** List of flags that can be OR-ed */ FLAGS, - /** Other representations */ - OTHER = 0xffffffff, }; /** - * Type of the supported values. The framework may not recognize `OTHER`. + * Type of the supported values. */ Type type; - /** - * Codec2.0 type code of the supported values. - * * If #type is `OTHER`, #typeOther can be used to give more information. - * In this case, the interpretation of this structure is - * implementation-defined. - * * For all other values of #type, #typeOther is not used. - * The framework may not inspect this value. - */ - int32_t typeOther; - - /* - * If #type = EMPTY, #range and #value are unused. - */ /** - * If #type = RANGE, #range will specify the range of possible values. + * When #type is #Type.RANGE, #range shall specify the range of possible + * values. * - * The intended type of members of #range will be clear in the context where - * FieldSupportedValues is used. + * The intended type of members of #range shall be clear in the context + * where `FieldSupportedValues` is used. */ Range range; /** - * If #type is `VALUES` or `FLAGS`, #value will list supported values. + * When #type is #Type.VALUES or #Type.FLAGS, #value shall list supported + * values/flags. * - * The intended type of components of #value will be clear in the context - * where FieldSupportedValues is used. + * The intended type of components of #value shall be clear in the context + * where `FieldSupportedValues` is used. */ vec values; }; /** - * Supported values for a specific field. + * Supported values for a field. * * This is a pair of the field specifier together with an optional supported * values object. This structure is used when reporting parameter configuration * failures and conflicts. */ struct ParamFieldValues { - /** the field or parameter */ + /** + * Reference to a field or a C2Param structure. + */ ParamField paramOrField; /** - * optional supported values for the field if paramOrField specifies an + * Optional supported values for the field if #paramOrField specifies an * actual field that is numeric (non struct, blob or string). Supported * values for arrays (including string and blobs) describe the supported * values for each element (character for string, and bytes for blobs). It @@ -241,18 +299,18 @@ struct ParamFieldValues { }; /** - * Field descriptor. + * Description of a field inside a C2Param structure. */ struct FieldDescriptor { - /** Field id */ + /** Location of the field in the C2Param structure */ FieldId fieldId; /** - * Possible types of a field. + * Possible types of the field. */ enum Type : uint32_t { - NO_INIT, + NO_INIT = 0, INT32, UINT32, CNTR32, @@ -261,186 +319,227 @@ struct FieldDescriptor { CNTR64, FLOAT, /** - * Fixed-size string (POD) + * Fixed-size string (POD). */ STRING = 0x100, /** - * blobs have no sub-elements and can be thought of as byte arrays. - * However, bytes cannot be individually addressed by clients. + * A blob has no sub-elements and can be thought of as an array of + * bytes. However, bytes cannot be individually addressed by clients. */ BLOB, /** - * Structs. Marked with this flag in addition to their coreIndex. + * The field is a structure that may contain other fields. */ - STRUCT_FLAG = 0x20000, + STRUCT = 0x20000, }; /** * Type of the field. */ bitfield type; - /** Extent of the field */ - uint32_t length; - /* - * Note: the last member of a param struct can be of arbitrary length (e.g. - * if it is T[] array, which extends to the last byte of the parameter.) - * This is marked with extent 0. + /** + * If #type is #Type.STRUCT, #structIndex is the C2Param structure index; + * otherwise, #structIndex is not used. */ + ParamIndex structIndex; - /** Name of the field */ + /** + * Extent of the field. + * - For a non-array field, #extent is 1. + * - For a fixed-length array field, #extent is the length. An array field + * of length 1 is indistinguishable from a non-array field. + * - For a variable-length array field, #extent is 0. This can only occur as + * the last member of a C2Param structure. + */ + uint32_t extent; + + /** + * Name of the field. This must be unique for each field in the same + * structure. + */ string name; - /** Named value type */ + + /** + * Named value type. This is used for defining an enum value for a numeric + * type. + */ struct NamedValue { + /** + * Name of the enum value. This must be unique for each enum value in + * the same field. + */ string name; + /** + * Underlying value of the enum value. Multiple enum names may have the + * same underlying value. + */ PrimitiveValue value; }; - /** Named values for the field */ + /** + * List of enum values. This is not used when #type is not one of the + * numeric types. + */ vec namedValues; }; /** - * Struct descriptor. + * Description of a C2Param structure. It consists of an index and a list of + * `FieldDescriptor`s. */ struct StructDescriptor { - /** Struct type */ + /** + * Index of the structure. + */ ParamIndex type; - /** Field descriptors for each field */ + /** + * List of fields in the structure. + * + * Fields are ordered by their offsets. A field that is a structure is + * ordered before its members. + */ vec fields; }; /** - * Information describing the reason a parameter settings may fail, or - * may be overriden. + * Information describing the reason the parameter settings may fail, or may be + * overridden. */ struct SettingResult { - /** Failure code (of Codec 2.0 SettingResult failure type) */ + /** Failure code */ enum Failure : uint32_t { - /** Parameter is read-only and cannot be set. */ - READ_ONLY, - /** Parameter mismatches input data. */ - MISMATCH, - /** Parameter does not accept value. */ - BAD_VALUE, /** Parameter is not supported. */ BAD_TYPE, /** Parameter is not supported on the specific port. */ BAD_PORT, /** Parameter is not supported on the specific stream. */ BAD_INDEX, - /** Parameter is in conflict with an/other setting(s). */ + /** Parameter is read-only and cannot be set. */ + READ_ONLY, + /** Parameter mismatches input data. */ + MISMATCH, + /** Strict parameter does not accept value for the field at all. */ + BAD_VALUE, + /** + * Strict parameter field value is in conflict with an/other + * setting(s). + */ CONFLICT, /** - * Parameter is out of range due to other settings. (This failure mode - * can only be used for strict parameters.) + * Parameter field is out of range due to other settings. (This failure + * mode can only be used for strict calculated parameters.) */ UNSUPPORTED, + /** + * Field does not access the requested parameter value at all. It has + * been corrected to the closest supported value. This failure mode is + * provided to give guidance as to what are the currently supported + * values for this field (which may be a subset of the at-all-potential + * values). + */ + INFO_BAD_VALUE, /** * Requested parameter value is in conflict with an/other setting(s) * and has been corrected to the closest supported value. This failure - * mode is given to provide suggestion to the client as to how to enable - * the requested parameter value. */ - INFO_CONFLICT, - /** - * This failure mode is reported when all the above failure modes do not - * apply. + * mode is given to provide guidance as to what are the currently + * supported values as well as to optionally provide suggestion to the + * client as to how to enable the requested parameter value. */ - OTHER = 0xffffffff, + INFO_CONFLICT, }; - /** - * The failure type. The framework might not recognize `OTHER`. - */ Failure failure; - /** - * The failure code. - * * If #failure is `OTHER`, #failureOther can be used to give more - * information. - * * For all other values of #failure, #failureOther is not used. - * The framework may not inspect this value. - */ - uint32_t failureOther; /** - * Failing (or corrected) field. Currently supported values for the field. - * This is set if different from the globally supported values (e.g. due to - * restrictions by another param or input data) + * Failing (or corrected) field or parameter and optionally, currently + * supported values for the field. Values must only be set for field + * failures other than `BAD_VALUE`, and only if they are different from the + * globally supported values (e.g. due to restrictions by another parameter + * or input data). */ ParamFieldValues field; /** - * Conflicting parameters or fields with - * (optional) suggested values for any conflicting fields to avoid the conflict. + * Conflicting parameters or fields with (optional) suggested values for any + * conflicting fields to avoid the conflict. Values must only be set for + * `CONFLICT`, `UNSUPPORTED` or `INFO_CONFLICT` failure code. */ vec conflicts; }; /** - * Data structure for ordering Work objects. Each member is used for comparing - * urgency in the same fashion: a smaller value indicates that the associated - * Work object is more urgent. + * Ordering information of @ref FrameData objects. Each member is used for + * comparing urgency: a smaller difference from a reference value indicates that + * the associated Work object is more urgent. The reference value for each + * member is initialized the first time it is communicated between the client + * and the codec, and it may be updated to later values that are communicated. + * + * Each member of `WorkOrdinal` is stored as an unsigned integer, but the actual + * order it represents is derived by subtracting the reference value, then + * interpreting the result as a signed number with the same storage size (using + * two's complement). + * + * @note `WorkOrdinal` is the HIDL counterpart of `C2WorkOrdinalStruct` in the + * Codec 2.0 standard. */ struct WorkOrdinal { /** - * Timestamp in microseconds - can wrap around. + * Timestamp in microseconds. */ uint64_t timestampUs; /** - * Frame index - can wrap around. + * Frame index. */ uint64_t frameIndex; /** - * Component specific frame ordinal - can wrap around. + * Component specific frame ordinal. */ uint64_t customOrdinal; }; /** - * A structure that holds information of a Block. There are two types of Blocks: - * NATIVE and POOLED. Each type has its own way of identifying blocks. + * Storage type for `BaseBlock`. + * + * A `BaseBlock` is a representation of a codec memory block. Coded data, + * decoded data, codec-specific data, and other codec-related data are all sent + * in the form of BaseBlocks. */ -struct BaseBlock { - enum Type : int32_t { - NATIVE, - POOLED, - }; +safe_union BaseBlock { /** - * There are two types of blocks: NATIVE and POOLED. - */ - Type type; - - /** - * A "NATIVE" block is represented by a native handle. + * #nativeBlock is the opaque representation of a buffer. */ handle nativeBlock; - - /* - * A "POOLED" block is represented by `BufferStatusMessage`. + /** + * #pooledBlock is a reference to a buffer handled by a BufferPool. */ BufferStatusMessage pooledBlock; }; /** - * A Block in transfer consists of an index into an array of BaseBlock plus some - * extra information. One BaseBlock may occur in multiple blocks in one - * `WorkBundle`. + * Reference to a @ref BaseBlock within a @ref WorkBundle. + * + * `Block` contains additional attributes that `BaseBlock` does not. These + * attributes may differ among `Block` objects that refer to the same + * `BaseBlock` in the same `WorkBundle`. */ struct Block { /** - * Identity of the BaseBlock within a WorkBundle. This is an index into the - * `baseBlocks` array of a `WorkBundle` object. + * Identity of a `BaseBlock` within a `WorkBundle`. This is an index into + * #WorkBundle.baseBlocks. */ uint32_t index; /** - * Metadata associated with the block. + * Metadata associated with this `Block`. */ Params meta; /** - * Fence for synchronizing block access. + * Fence for synchronizing `Block` access. */ handle fence; }; /** - * Type of buffers processed by a component. + * A codec buffer, which is a collection of @ref Block objects and metadata. + * + * This is a part of @ref FrameData. */ struct Buffer { /** @@ -454,23 +553,37 @@ struct Buffer { }; /** - * An extension of Buffer that also contains an index. + * An extension of @ref Buffer that also contains a C2Param structure index. + * + * This is a part of @ref FrameData. */ struct InfoBuffer { + /** + * A C2Param structure index. + */ ParamIndex index; + /** + * Associated @ref Buffer object. + */ Buffer buffer; }; /** - * This structure represents a frame with its metadata. A frame consists of an - * ordered set of buffers, configuration changes, and info buffers along with - * some non-configuration metadata. + * Data for an input frame or an output frame. + * + * This structure represents a @e frame with its metadata. A @e frame consists + * of an ordered set of buffers, configuration changes, and info buffers along + * with some non-configuration metadata. + * + * @note `FrameData` is the HIDL counterpart of `C2FrameData` in the Codec 2.0 + * standard. */ struct FrameData { enum Flags : uint32_t { /** - * For input frames: no output frame will be generated when processing + * For input frames: no output frame shall be generated when processing * this frame, but metadata must still be processed. + * * For output frames: this frame must be discarded but metadata is still * valid. */ @@ -482,92 +595,178 @@ struct FrameData { END_OF_STREAM = (1 << 1), /** * This frame must be discarded with its metadata. - * This flag is only set by components - e.g. as a response to the flush + * + * This flag is only set by components, e.g. as a response to the flush * command. */ DISCARD_FRAME = (1 << 2), + /** + * This frame is not the last frame produced for the input. + * + * This flag is normally set by the component - e.g. when an input frame + * results in multiple output frames, this flag is set on all but the + * last output frame. + * + * Also, when components are chained, this flag should be propagated + * down the work chain. That is, if set on an earlier frame of a + * work-chain, it should be propagated to all later frames in that + * chain. Additionally, components down the chain could set this flag + * even if not set earlier, e.g. if multiple output frames are generated + * at that component for the input frame. + */ + FLAG_INCOMPLETE = (1 << 3), /** * This frame contains only codec-specific configuration data, and no * actual access unit. * - * \deprecated Pass codec configuration with the codec-specific + * @deprecated Pass codec configuration with the codec-specific * configuration info together with the access unit. */ CODEC_CONFIG = (1u << 31), }; /** - * Frame flags. + * Frame flags, as described in #Flags. */ bitfield flags; /** - * Ordinal of the frame. + * @ref WorkOrdinal of the frame. */ WorkOrdinal ordinal; /** - * Frame buffers. + * List of frame buffers. */ vec buffers; /** - * Params determining a configuration update. + * List of configuration updates. */ Params configUpdate; /** - * Info buffers. + * List of info buffers. */ vec infoBuffers; }; /** - * Struct for + * In/out structure containing some instructions for and results from output + * processing. + * + * This is a part of @ref Work. One `Worklet` corresponds to one output + * @ref FrameData. The client must construct an original `Worklet` object inside + * a @ref Work object for each expected output before calling + * IComponent::queue(). */ struct Worklet { /** - * List of Params describing tunings. + * Component id. (Input) + * + * This is used only when tunneling is enabled. + * + * When used, this must match the return value from IConfigurable::getId(). */ - vec tunings; + uint32_t componentId; /** - * List of failures. + * List of C2Param objects describing tunings to be applied before + * processing this `Worklet`. (Input) + */ + Params tunings; + + /** + * List of failures. (Output) */ vec failures; /** - * Output frame data. + * Output frame data. (Output) */ FrameData output; - - /* Note: Component id is not necessary as tunneling is not supported. */ }; /** - * This structure holds information about a single work item. It must be passed - * by the client to the component. + * A collection of input data to and output data from the component. + * + * A `Work` object holds information about a single work item. It is created by + * the client and passed to the component via IComponent::queue(). The component + * has two ways of returning a `Work` object to the client: + * 1. If the queued `Work` object has been successfully processed, + * IComponentListener::onWorkDone() shall be called to notify the listener, + * and the output shall be included in the returned `Work` object. + * 2. If the client calls IComponent::flush(), a `Work` object that has not + * been processed shall be returned. + * + * `Work` is a part of @ref WorkBundle. */ struct Work { /** - * FrameData for the input. Indices of Blocks inside #input refer to - * BaseBlocks in the member `blocks` of the containing `WorkBundle`. + * Additional work chain info not part of this work. + */ + Params chainInfo; + + /** + * @ref FrameData for the input. */ FrameData input; + /** - * Worklet. Indices of Blocks inside `worklet.output` refer to - * BaseBlocks in the member `blocks` of the containing `WorkBundle`. + * The chain of `Worklet`s. + * + * The length of #worklets is 1 when tunneling is not enabled. + * + * If #worklets has more than a single element, the tunnels between + * successive components of the work chain must have been successfully + * pre-registered at the time that the `Work` is submitted. Allocating the + * output buffers in the `Worklet`s is the responsibility of each component + * in the chain. + * + * Upon `Work` submission, #worklets must be an appropriately sized vector + * containing `Worklet`s with @ref Worklet.hasOutput set to `false`. After a + * successful processing, all but the final `Worklet` in the returned + * #worklets must have @ref Worklet.hasOutput set to `false`. */ - Worklet worklet; + vec worklets; + /** - * Whether the worklet was processed or not. + * The number of `Worklet`s successfully processed in this chain. + * + * This must be initialized to 0 by the client when the `Work` is submitted, + * and it must contain the number of `Worklet`s that were successfully + * processed when the `Work` is returned to the client. + * + * #workletsProcessed cannot exceed the length of #worklets. If + * #workletsProcessed is smaller than the length of #worklets, #result + * cannot be `OK`. + */ + uint32_t workletsProcessed; + + /** + * The final outcome of the `Work` (corresponding to #workletsProcessed). + * + * The value of @ref Status.OK implies that all `Worklet`s have been + * successfully processed. */ - bool workletProcessed; Status result; }; /** - * This structure holds a list of Work objects and a list of BaseBlocks. + * List of `Work` objects. + * + * `WorkBundle` is used in IComponent::queue(), IComponent::flush() and + * IComponentListener::onWorkDone(). A `WorkBundle` object consists of a list of + * `Work` objects and a list of `BaseBlock` objects. Bundling multiple `Work` + * objects together provides two benefits: + * 1. Batching of `Work` objects can reduce the number of IPC calls. + * 2. If multiple `Work` objects contain `Block`s that refer to the same + * `BaseBlock`, the number of `BaseBlock`s that is sent between processes + * is also reduced. + * + * @note `WorkBundle` is the HIDL counterpart of the vector of `C2Work` in the + * Codec 2.0 standard. The presence of #baseBlocks helps with minimizing the + * data transferred over an IPC. */ struct WorkBundle { /** @@ -581,27 +780,48 @@ struct WorkBundle { }; /** - * This structure describes a query for supported values of a field. This is - * used as input to IConfigurable::queryFieldSupportedValues(). + * Query information for supported values of a field. This is used as input to + * IConfigurable::querySupportedValues(). */ struct FieldSupportedValuesQuery { + /** + * Identity of the field to query. + */ + ParamField field; + enum Type : uint32_t { - /** Query all possible values regardless of other settings */ + /** Query all possible values regardless of other settings. */ POSSIBLE, - /** Query currently possible values given dependent settings */ + /** Query currently possible values given dependent settings. */ CURRENT, }; - - ParamField field; + /** + * Type of the query. See #Type for more information. + */ Type type; }; /** * This structure is used to hold the result from - * IConfigurable::queryFieldSupportedValues(). + * IConfigurable::querySupportedValues(). */ struct FieldSupportedValuesQueryResult { + /** + * Result of the query. Possible values are + * - `OK`: The query was successful. + * - `BAD_STATE`: The query was requested when the `IConfigurable` instance + * was in a bad state. + * - `BAD_INDEX`: The requested field was not recognized. + * - `TIMED_OUT`: The query could not be completed in a timely manner. + * - `BLOCKING`: The query must block, but the parameter `mayBlock` in the + * call to `querySupportedValues()` was `false`. + * - `CORRUPTED`: Some unknown error occurred. + */ Status status; + + /** + * Supported values. This is meaningful only when #status is `OK`. + */ FieldSupportedValues values; }; From 496a29e182a81974bad0d4fcd80be47f276971cc Mon Sep 17 00:00:00 2001 From: lesl Date: Thu, 24 Jan 2019 16:47:25 +0800 Subject: [PATCH 410/718] vts: bypass test for deprecated API addAccessPoint BUG:123325192 Test: build - make vts Test: atest VtsHalWifiHostapdV1_0Target Test: vts-tradefed run commandAndExit vts-hal --skip-all-system-status-check \ --primary-abi-only --skip-preconditions --module \ VtsHalWifiHostapdV1_0Target -l INFO Change-Id: Ia91d650ed8603fc62114eb00cae482de2a5f93fa --- wifi/hostapd/1.0/vts/functional/Android.bp | 2 + .../1.0/vts/functional/hostapd_hidl_test.cpp | 81 +++++++++++-------- .../functional/hostapd_hidl_test_utils.cpp | 6 ++ .../vts/functional/hostapd_hidl_test_utils.h | 3 + 4 files changed, 60 insertions(+), 32 deletions(-) diff --git a/wifi/hostapd/1.0/vts/functional/Android.bp b/wifi/hostapd/1.0/vts/functional/Android.bp index 79c5183886..93867d28ad 100644 --- a/wifi/hostapd/1.0/vts/functional/Android.bp +++ b/wifi/hostapd/1.0/vts/functional/Android.bp @@ -24,6 +24,7 @@ cc_library_static { static_libs: [ "VtsHalWifiV1_0TargetTestUtil", "android.hardware.wifi.hostapd@1.0", + "android.hardware.wifi.hostapd@1.1", "android.hardware.wifi@1.0", "libcrypto", "libgmock", @@ -43,6 +44,7 @@ cc_test { "VtsHalWifiV1_0TargetTestUtil", "VtsHalWifiHostapdV1_0TargetTestUtil", "android.hardware.wifi.hostapd@1.0", + "android.hardware.wifi.hostapd@1.1", "android.hardware.wifi@1.0", "libcrypto", "libgmock", diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test.cpp b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test.cpp index 504f4c8d2b..fa780f9a5c 100644 --- a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test.cpp +++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test.cpp @@ -138,9 +138,11 @@ TEST(HostapdHidlTestNoFixture, Create) { * Access point creation should pass. */ TEST_F(HostapdHidlTest, AddPskAccessPointWithAcs) { - auto status = HIDL_INVOKE(hostapd_, addAccessPoint, getIfaceParamsWithAcs(), - getPskNwParams()); - EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); + if (!is_1_1(hostapd_)) { + auto status = HIDL_INVOKE(hostapd_, addAccessPoint, + getIfaceParamsWithAcs(), getPskNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); + } } /** @@ -148,9 +150,11 @@ TEST_F(HostapdHidlTest, AddPskAccessPointWithAcs) { * Access point creation should pass. */ TEST_F(HostapdHidlTest, AddOpenAccessPointWithAcs) { - auto status = HIDL_INVOKE(hostapd_, addAccessPoint, getIfaceParamsWithAcs(), - getOpenNwParams()); - EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); + if (!is_1_1(hostapd_)) { + auto status = HIDL_INVOKE(hostapd_, addAccessPoint, + getIfaceParamsWithAcs(), getOpenNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); + } } /** @@ -158,9 +162,11 @@ TEST_F(HostapdHidlTest, AddOpenAccessPointWithAcs) { * Access point creation should pass. */ TEST_F(HostapdHidlTest, AddPskAccessPointWithoutAcs) { - auto status = HIDL_INVOKE(hostapd_, addAccessPoint, - getIfaceParamsWithoutAcs(), getPskNwParams()); - EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); + if (!is_1_1(hostapd_)) { + auto status = HIDL_INVOKE(hostapd_, addAccessPoint, + getIfaceParamsWithoutAcs(), getPskNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); + } } /** @@ -168,9 +174,12 @@ TEST_F(HostapdHidlTest, AddPskAccessPointWithoutAcs) { * Access point creation should pass. */ TEST_F(HostapdHidlTest, AddOpenAccessPointWithoutAcs) { - auto status = HIDL_INVOKE(hostapd_, addAccessPoint, - getIfaceParamsWithoutAcs(), getOpenNwParams()); - EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); + if (!is_1_1(hostapd_)) { + auto status = + HIDL_INVOKE(hostapd_, addAccessPoint, getIfaceParamsWithoutAcs(), + getOpenNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); + } } /** @@ -178,12 +187,14 @@ TEST_F(HostapdHidlTest, AddOpenAccessPointWithoutAcs) { * Access point creation & removal should pass. */ TEST_F(HostapdHidlTest, RemoveAccessPointWithAcs) { - auto status = HIDL_INVOKE(hostapd_, addAccessPoint, getIfaceParamsWithAcs(), - getPskNwParams()); - EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); - status = - HIDL_INVOKE(hostapd_, removeAccessPoint, getPrimaryWlanIfaceName()); - EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); + if (!is_1_1(hostapd_)) { + auto status = HIDL_INVOKE(hostapd_, addAccessPoint, + getIfaceParamsWithAcs(), getPskNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); + status = + HIDL_INVOKE(hostapd_, removeAccessPoint, getPrimaryWlanIfaceName()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); + } } /** @@ -191,12 +202,14 @@ TEST_F(HostapdHidlTest, RemoveAccessPointWithAcs) { * Access point creation & removal should pass. */ TEST_F(HostapdHidlTest, RemoveAccessPointWithoutAcs) { - auto status = HIDL_INVOKE(hostapd_, addAccessPoint, - getIfaceParamsWithoutAcs(), getPskNwParams()); - EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); - status = - HIDL_INVOKE(hostapd_, removeAccessPoint, getPrimaryWlanIfaceName()); - EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); + if (!is_1_1(hostapd_)) { + auto status = HIDL_INVOKE(hostapd_, addAccessPoint, + getIfaceParamsWithoutAcs(), getPskNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); + status = + HIDL_INVOKE(hostapd_, removeAccessPoint, getPrimaryWlanIfaceName()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); + } } /** @@ -204,10 +217,12 @@ TEST_F(HostapdHidlTest, RemoveAccessPointWithoutAcs) { * Access point creation should fail. */ TEST_F(HostapdHidlTest, AddPskAccessPointWithInvalidChannel) { - auto status = - HIDL_INVOKE(hostapd_, addAccessPoint, - getIfaceParamsWithInvalidChannel(), getPskNwParams()); - EXPECT_NE(HostapdStatusCode::SUCCESS, status.code); + if (!is_1_1(hostapd_)) { + auto status = + HIDL_INVOKE(hostapd_, addAccessPoint, + getIfaceParamsWithInvalidChannel(), getPskNwParams()); + EXPECT_NE(HostapdStatusCode::SUCCESS, status.code); + } } /** @@ -215,10 +230,12 @@ TEST_F(HostapdHidlTest, AddPskAccessPointWithInvalidChannel) { * Access point creation should fail. */ TEST_F(HostapdHidlTest, AddInvalidPskAccessPointWithoutAcs) { - auto status = - HIDL_INVOKE(hostapd_, addAccessPoint, getIfaceParamsWithoutAcs(), - getInvalidPskNwParams()); - EXPECT_NE(HostapdStatusCode::SUCCESS, status.code); + if (!is_1_1(hostapd_)) { + auto status = + HIDL_INVOKE(hostapd_, addAccessPoint, getIfaceParamsWithoutAcs(), + getInvalidPskNwParams()); + EXPECT_NE(HostapdStatusCode::SUCCESS, status.code); + } } /* diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp index e5ba8efa90..22dbb528c3 100644 --- a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp +++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp @@ -130,6 +130,12 @@ void startHostapdAndWaitForHidlService() { ASSERT_TRUE(notification_listener->waitForHidlService(200, service_name)); } +bool is_1_1(const sp& hostapd) { + sp<::android::hardware::wifi::hostapd::V1_1::IHostapd> hostapd_1_1 = + ::android::hardware::wifi::hostapd::V1_1::IHostapd::castFrom(hostapd); + return hostapd_1_1.get() != nullptr; +} + sp getHostapd() { return ::testing::VtsHalHidlTargetTestBase::getService( gEnv->getServiceName()); diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h index 1b92477329..8e2f1a34d1 100644 --- a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h +++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h @@ -18,6 +18,7 @@ #define HOSTAPD_HIDL_TEST_UTILS_H #include +#include #include @@ -34,6 +35,8 @@ void startHostapdAndWaitForHidlService(); // These helper functions should be modified to return vectors if we support // multiple instances. android::sp getHostapd(); +bool is_1_1(const android::sp& + hostapd); class WifiHostapdHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { From 97e1a932ec52ce49e4c51527a6fce78bfa810294 Mon Sep 17 00:00:00 2001 From: Kevin DuBois Date: Tue, 22 Jan 2019 10:22:37 -0800 Subject: [PATCH 411/718] graphics.common: add HSV format definition to 1.2 Adds HSV format used in some color sampling engines to the list of pixel formats. Rev the sampling engine in composer to reference the new format revision. Test: built image, with new format reported in vendor code. Test: VtsHalGraphicsComposerV2_3TargetTest Fixes: 122943743 Change-Id: I1b454a86f464f38e3c2cbeef5379a187ff38ab06 --- configstore/1.2/ISurfaceFlingerConfigs.hal | 2 +- .../1.2/default/SurfaceFlingerConfigs.cpp | 2 +- .../VtsHalConfigstoreV1_2TargetTest.cpp | 4 ++-- graphics/common/1.2/types.hal | 18 +++++++++++++++++- graphics/composer/2.3/IComposerClient.hal | 2 +- .../include/composer-hal/2.3/ComposerClient.h | 2 +- .../hal/include/composer-hal/2.3/ComposerHal.h | 2 +- .../include/composer-passthrough/2.3/HwcHal.h | 8 +++++--- .../vts/include/composer-vts/2.3/ComposerVts.h | 2 +- .../VtsHalGraphicsComposerV2_3TargetTest.cpp | 5 +---- 10 files changed, 31 insertions(+), 16 deletions(-) diff --git a/configstore/1.2/ISurfaceFlingerConfigs.hal b/configstore/1.2/ISurfaceFlingerConfigs.hal index 7e5f706c02..431b3fc479 100644 --- a/configstore/1.2/ISurfaceFlingerConfigs.hal +++ b/configstore/1.2/ISurfaceFlingerConfigs.hal @@ -15,7 +15,7 @@ */ package android.hardware.configstore@1.2; -import android.hardware.graphics.common@1.1::PixelFormat; +import android.hardware.graphics.common@1.2::PixelFormat; import android.hardware.graphics.common@1.2::Dataspace; import @1.1::ISurfaceFlingerConfigs; import @1.0::OptionalBool; diff --git a/configstore/1.2/default/SurfaceFlingerConfigs.cpp b/configstore/1.2/default/SurfaceFlingerConfigs.cpp index d38b402889..714442bd22 100644 --- a/configstore/1.2/default/SurfaceFlingerConfigs.cpp +++ b/configstore/1.2/default/SurfaceFlingerConfigs.cpp @@ -27,8 +27,8 @@ namespace configstore { namespace V1_2 { namespace implementation { -using ::android::hardware::graphics::common::V1_1::PixelFormat; using ::android::hardware::graphics::common::V1_2::Dataspace; +using ::android::hardware::graphics::common::V1_2::PixelFormat; // ::android::hardware::configstore::V1_0::ISurfaceFlingerConfigs implementation. Return SurfaceFlingerConfigs::vsyncEventPhaseOffsetNs(vsyncEventPhaseOffsetNs_cb _hidl_cb) { diff --git a/configstore/1.2/vts/functional/VtsHalConfigstoreV1_2TargetTest.cpp b/configstore/1.2/vts/functional/VtsHalConfigstoreV1_2TargetTest.cpp index 881b591284..d7f4dcf75f 100644 --- a/configstore/1.2/vts/functional/VtsHalConfigstoreV1_2TargetTest.cpp +++ b/configstore/1.2/vts/functional/VtsHalConfigstoreV1_2TargetTest.cpp @@ -31,10 +31,10 @@ using ::android::hardware::Void; using ::android::hardware::configstore::V1_0::OptionalBool; using ::android::hardware::configstore::V1_0::OptionalInt64; using ::android::hardware::configstore::V1_0::OptionalUInt64; -using ::android::hardware::configstore::V1_2::ISurfaceFlingerConfigs; using ::android::hardware::configstore::V1_2::DisplayPrimaries; -using ::android::hardware::graphics::common::V1_1::PixelFormat; +using ::android::hardware::configstore::V1_2::ISurfaceFlingerConfigs; using ::android::hardware::graphics::common::V1_2::Dataspace; +using ::android::hardware::graphics::common::V1_2::PixelFormat; #define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk()) #define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk()) diff --git a/graphics/common/1.2/types.hal b/graphics/common/1.2/types.hal index 392a12e2e4..c9c3aeb972 100644 --- a/graphics/common/1.2/types.hal +++ b/graphics/common/1.2/types.hal @@ -25,7 +25,8 @@ import @1.1::PixelFormat; /** * Hdr */ -@export(name="android_hdr_v1_2_t", value_prefix="HAL_HDR_") +@export(name="android_hdr_v1_2_t", value_prefix="HAL_HDR_", + export_parent="false") enum Hdr : @1.0::Hdr { HDR10_PLUS = 4, }; @@ -96,3 +97,18 @@ struct HardwareBuffer { */ typedef int32_t[4] Rect; +/** + * Pixel formats for graphics buffers. + */ +@export(name="android_pixel_format_v1_2_t", value_prefix="HAL_PIXEL_FORMAT_", + export_parent="false") +enum PixelFormat : @1.1::PixelFormat { + /** + * 24-bit format that has 8-bit H, S, and V components, in that order, + * from the lowest memory address to the highest memory address. + * + * The component values are unsigned normalized to the range [0, 1], whose + * interpretation is defined by the dataspace. + */ + HSV_888 = 0x37, +}; diff --git a/graphics/composer/2.3/IComposerClient.hal b/graphics/composer/2.3/IComposerClient.hal index cf78dea532..a3b7792c05 100644 --- a/graphics/composer/2.3/IComposerClient.hal +++ b/graphics/composer/2.3/IComposerClient.hal @@ -17,7 +17,7 @@ package android.hardware.graphics.composer@2.3; import android.hardware.graphics.common@1.1::RenderIntent; -import android.hardware.graphics.common@1.1::PixelFormat; +import android.hardware.graphics.common@1.2::PixelFormat; import android.hardware.graphics.common@1.2::ColorMode; import android.hardware.graphics.common@1.2::Dataspace; import android.hardware.graphics.common@1.2::Hdr; diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h index edc203eb1d..a272e72d74 100644 --- a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h +++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h @@ -123,7 +123,7 @@ class ComposerClientImpl : public V2_2::hal::detail::ComposerClientImpl getDisplayedContentSamplingAttributes( uint64_t display, IComposerClient::getDisplayedContentSamplingAttributes_cb hidl_cb) override { - common::V1_1::PixelFormat format; + PixelFormat format; common::V1_2::Dataspace dataspace; hidl_bitfield componentMask; Error error = diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h index 882621f086..a0812ad9a7 100644 --- a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h +++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h @@ -25,11 +25,11 @@ namespace composer { namespace V2_3 { namespace hal { -using common::V1_1::PixelFormat; using common::V1_1::RenderIntent; using common::V1_2::ColorMode; using common::V1_2::Dataspace; using common::V1_2::Hdr; +using common::V1_2::PixelFormat; using V2_1::Display; using V2_1::Error; using V2_1::Layer; diff --git a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h index 9fb6d4bf7d..41e333ac5e 100644 --- a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h +++ b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h @@ -34,11 +34,11 @@ namespace passthrough { namespace detail { -using common::V1_1::PixelFormat; using common::V1_1::RenderIntent; using common::V1_2::ColorMode; using common::V1_2::Dataspace; using common::V1_2::Hdr; +using common::V1_2::PixelFormat; using V2_1::Display; using V2_1::Error; @@ -91,14 +91,16 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl { Error getClientTargetSupport_2_3(Display display, uint32_t width, uint32_t height, PixelFormat format, Dataspace dataspace) override { - return getClientTargetSupport_2_2(display, width, height, format, + return getClientTargetSupport_2_2(display, width, height, + static_cast(format), static_cast(dataspace)); } Error getReadbackBufferAttributes_2_3(Display display, PixelFormat* outFormat, Dataspace* outDataspace) override { return getReadbackBufferAttributes( - display, outFormat, reinterpret_cast(outDataspace)); + display, reinterpret_cast(outFormat), + reinterpret_cast(outDataspace)); } Error getDisplayIdentificationData(Display display, uint8_t* outPort, diff --git a/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h b/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h index 7add322282..ad4ef0b51e 100644 --- a/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h +++ b/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h @@ -32,11 +32,11 @@ namespace composer { namespace V2_3 { namespace vts { -using common::V1_1::PixelFormat; using common::V1_1::RenderIntent; using common::V1_2::ColorMode; using common::V1_2::Dataspace; using common::V1_2::Hdr; +using common::V1_2::PixelFormat; using V2_1::Display; using V2_1::Error; using V2_3::IComposer; diff --git a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp index dca7406c10..de74e28cc7 100644 --- a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp +++ b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp @@ -36,10 +36,10 @@ namespace vts { namespace { using common::V1_0::BufferUsage; -using common::V1_1::PixelFormat; using common::V1_1::RenderIntent; using common::V1_2::ColorMode; using common::V1_2::Dataspace; +using common::V1_2::PixelFormat; using mapper::V2_0::IMapper; using mapper::V2_0::vts::Gralloc; @@ -492,9 +492,6 @@ TEST_F(GraphicsComposerHidlTest, SetLayerColorTransform) { } TEST_F(GraphicsComposerHidlTest, GetDisplayedContentSamplingAttributes) { - using common::V1_1::PixelFormat; - using common::V1_2::Dataspace; - int constexpr invalid = -1; auto format = static_cast(invalid); auto dataspace = static_cast(invalid); From 54c13ddf60973df7ea0e2819624009ae5805c6e7 Mon Sep 17 00:00:00 2001 From: Kevin Chyn Date: Thu, 24 Jan 2019 11:20:00 -0800 Subject: [PATCH 412/718] Add additional acquired constants Fixes: 123101870 Test: Builds Change-Id: I67365b4a821c43ac01810119e9f1fa24f27d3c7f --- biometrics/face/1.0/types.hal | 45 ++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/biometrics/face/1.0/types.hal b/biometrics/face/1.0/types.hal index a488d671d0..2bcd3d5e3e 100644 --- a/biometrics/face/1.0/types.hal +++ b/biometrics/face/1.0/types.hal @@ -280,10 +280,53 @@ enum FaceAcquiredInfo : int32_t { */ TOO_SIMILAR = 15, + /** + * The magnitude of the pan angle of the user’s face with respect to the sensor’s + * capture plane is too high. + * + * The pan angle is defined as the angle swept out by the user’s face turning + * their neck left and right. The pan angle would be zero if the user faced the + * camera directly. + * + * The user should be informed to look more directly at the camera. + */ + PAN_TOO_EXTREME = 16, + + /** + * The magnitude of the tilt angle of the user’s face with respect to the sensor’s + * capture plane is too high. + * + * The tilt angle is defined as the angle swept out by the user’s face looking up + * and down. The pan angle would be zero if the user faced the camera directly. + * + * The user should be informed to look more directly at the camera. + */ + TILT_TOO_EXTREME = 17, + + /** + * The magnitude of the roll angle of the user’s face with respect to the sensor’s + * capture plane is too high. + * + * The roll angle is defined as the angle swept out by the user’s face tilting their head + * towards their shoulders to the left and right. The pan angle would be zero if the user + * faced the camera directly. + * + * The user should be informed to look more directly at the camera. + */ + ROLL_TOO_EXTREME = 18, + + /** + * The user’s face has been obscured by some object. + * + * The user should be informed to remove any objects from the line of sight from + * the sensor to the user’s face. + */ + FACE_OBSCURED = 19, + /** * Used to enable a vendor-specific acquisition message. */ - VENDOR = 16 + VENDOR = 20 }; /** From e2f69f22289ffadc8dcfdbb476422e194442253a Mon Sep 17 00:00:00 2001 From: Kevin DuBois Date: Fri, 25 Jan 2019 17:06:01 +0000 Subject: [PATCH 413/718] Revert "graphics.common: add HSV format definition to 1.2" This reverts commit 97e1a932ec52ce49e4c51527a6fce78bfa810294. Reason for revert: broke build Change-Id: Ib264957e9a1de83c37e4129471b3c75522e21d08 --- configstore/1.2/ISurfaceFlingerConfigs.hal | 2 +- .../1.2/default/SurfaceFlingerConfigs.cpp | 2 +- .../VtsHalConfigstoreV1_2TargetTest.cpp | 4 ++-- graphics/common/1.2/types.hal | 18 +----------------- graphics/composer/2.3/IComposerClient.hal | 2 +- .../include/composer-hal/2.3/ComposerClient.h | 2 +- .../hal/include/composer-hal/2.3/ComposerHal.h | 2 +- .../include/composer-passthrough/2.3/HwcHal.h | 8 +++----- .../vts/include/composer-vts/2.3/ComposerVts.h | 2 +- .../VtsHalGraphicsComposerV2_3TargetTest.cpp | 5 ++++- 10 files changed, 16 insertions(+), 31 deletions(-) diff --git a/configstore/1.2/ISurfaceFlingerConfigs.hal b/configstore/1.2/ISurfaceFlingerConfigs.hal index 431b3fc479..7e5f706c02 100644 --- a/configstore/1.2/ISurfaceFlingerConfigs.hal +++ b/configstore/1.2/ISurfaceFlingerConfigs.hal @@ -15,7 +15,7 @@ */ package android.hardware.configstore@1.2; -import android.hardware.graphics.common@1.2::PixelFormat; +import android.hardware.graphics.common@1.1::PixelFormat; import android.hardware.graphics.common@1.2::Dataspace; import @1.1::ISurfaceFlingerConfigs; import @1.0::OptionalBool; diff --git a/configstore/1.2/default/SurfaceFlingerConfigs.cpp b/configstore/1.2/default/SurfaceFlingerConfigs.cpp index 714442bd22..d38b402889 100644 --- a/configstore/1.2/default/SurfaceFlingerConfigs.cpp +++ b/configstore/1.2/default/SurfaceFlingerConfigs.cpp @@ -27,8 +27,8 @@ namespace configstore { namespace V1_2 { namespace implementation { +using ::android::hardware::graphics::common::V1_1::PixelFormat; using ::android::hardware::graphics::common::V1_2::Dataspace; -using ::android::hardware::graphics::common::V1_2::PixelFormat; // ::android::hardware::configstore::V1_0::ISurfaceFlingerConfigs implementation. Return SurfaceFlingerConfigs::vsyncEventPhaseOffsetNs(vsyncEventPhaseOffsetNs_cb _hidl_cb) { diff --git a/configstore/1.2/vts/functional/VtsHalConfigstoreV1_2TargetTest.cpp b/configstore/1.2/vts/functional/VtsHalConfigstoreV1_2TargetTest.cpp index d7f4dcf75f..881b591284 100644 --- a/configstore/1.2/vts/functional/VtsHalConfigstoreV1_2TargetTest.cpp +++ b/configstore/1.2/vts/functional/VtsHalConfigstoreV1_2TargetTest.cpp @@ -31,10 +31,10 @@ using ::android::hardware::Void; using ::android::hardware::configstore::V1_0::OptionalBool; using ::android::hardware::configstore::V1_0::OptionalInt64; using ::android::hardware::configstore::V1_0::OptionalUInt64; -using ::android::hardware::configstore::V1_2::DisplayPrimaries; using ::android::hardware::configstore::V1_2::ISurfaceFlingerConfigs; +using ::android::hardware::configstore::V1_2::DisplayPrimaries; +using ::android::hardware::graphics::common::V1_1::PixelFormat; using ::android::hardware::graphics::common::V1_2::Dataspace; -using ::android::hardware::graphics::common::V1_2::PixelFormat; #define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk()) #define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk()) diff --git a/graphics/common/1.2/types.hal b/graphics/common/1.2/types.hal index c9c3aeb972..392a12e2e4 100644 --- a/graphics/common/1.2/types.hal +++ b/graphics/common/1.2/types.hal @@ -25,8 +25,7 @@ import @1.1::PixelFormat; /** * Hdr */ -@export(name="android_hdr_v1_2_t", value_prefix="HAL_HDR_", - export_parent="false") +@export(name="android_hdr_v1_2_t", value_prefix="HAL_HDR_") enum Hdr : @1.0::Hdr { HDR10_PLUS = 4, }; @@ -97,18 +96,3 @@ struct HardwareBuffer { */ typedef int32_t[4] Rect; -/** - * Pixel formats for graphics buffers. - */ -@export(name="android_pixel_format_v1_2_t", value_prefix="HAL_PIXEL_FORMAT_", - export_parent="false") -enum PixelFormat : @1.1::PixelFormat { - /** - * 24-bit format that has 8-bit H, S, and V components, in that order, - * from the lowest memory address to the highest memory address. - * - * The component values are unsigned normalized to the range [0, 1], whose - * interpretation is defined by the dataspace. - */ - HSV_888 = 0x37, -}; diff --git a/graphics/composer/2.3/IComposerClient.hal b/graphics/composer/2.3/IComposerClient.hal index a3b7792c05..cf78dea532 100644 --- a/graphics/composer/2.3/IComposerClient.hal +++ b/graphics/composer/2.3/IComposerClient.hal @@ -17,7 +17,7 @@ package android.hardware.graphics.composer@2.3; import android.hardware.graphics.common@1.1::RenderIntent; -import android.hardware.graphics.common@1.2::PixelFormat; +import android.hardware.graphics.common@1.1::PixelFormat; import android.hardware.graphics.common@1.2::ColorMode; import android.hardware.graphics.common@1.2::Dataspace; import android.hardware.graphics.common@1.2::Hdr; diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h index a272e72d74..edc203eb1d 100644 --- a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h +++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h @@ -123,7 +123,7 @@ class ComposerClientImpl : public V2_2::hal::detail::ComposerClientImpl getDisplayedContentSamplingAttributes( uint64_t display, IComposerClient::getDisplayedContentSamplingAttributes_cb hidl_cb) override { - PixelFormat format; + common::V1_1::PixelFormat format; common::V1_2::Dataspace dataspace; hidl_bitfield componentMask; Error error = diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h index a0812ad9a7..882621f086 100644 --- a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h +++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h @@ -25,11 +25,11 @@ namespace composer { namespace V2_3 { namespace hal { +using common::V1_1::PixelFormat; using common::V1_1::RenderIntent; using common::V1_2::ColorMode; using common::V1_2::Dataspace; using common::V1_2::Hdr; -using common::V1_2::PixelFormat; using V2_1::Display; using V2_1::Error; using V2_1::Layer; diff --git a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h index 41e333ac5e..9fb6d4bf7d 100644 --- a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h +++ b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h @@ -34,11 +34,11 @@ namespace passthrough { namespace detail { +using common::V1_1::PixelFormat; using common::V1_1::RenderIntent; using common::V1_2::ColorMode; using common::V1_2::Dataspace; using common::V1_2::Hdr; -using common::V1_2::PixelFormat; using V2_1::Display; using V2_1::Error; @@ -91,16 +91,14 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl { Error getClientTargetSupport_2_3(Display display, uint32_t width, uint32_t height, PixelFormat format, Dataspace dataspace) override { - return getClientTargetSupport_2_2(display, width, height, - static_cast(format), + return getClientTargetSupport_2_2(display, width, height, format, static_cast(dataspace)); } Error getReadbackBufferAttributes_2_3(Display display, PixelFormat* outFormat, Dataspace* outDataspace) override { return getReadbackBufferAttributes( - display, reinterpret_cast(outFormat), - reinterpret_cast(outDataspace)); + display, outFormat, reinterpret_cast(outDataspace)); } Error getDisplayIdentificationData(Display display, uint8_t* outPort, diff --git a/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h b/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h index ad4ef0b51e..7add322282 100644 --- a/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h +++ b/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h @@ -32,11 +32,11 @@ namespace composer { namespace V2_3 { namespace vts { +using common::V1_1::PixelFormat; using common::V1_1::RenderIntent; using common::V1_2::ColorMode; using common::V1_2::Dataspace; using common::V1_2::Hdr; -using common::V1_2::PixelFormat; using V2_1::Display; using V2_1::Error; using V2_3::IComposer; diff --git a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp index de74e28cc7..dca7406c10 100644 --- a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp +++ b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp @@ -36,10 +36,10 @@ namespace vts { namespace { using common::V1_0::BufferUsage; +using common::V1_1::PixelFormat; using common::V1_1::RenderIntent; using common::V1_2::ColorMode; using common::V1_2::Dataspace; -using common::V1_2::PixelFormat; using mapper::V2_0::IMapper; using mapper::V2_0::vts::Gralloc; @@ -492,6 +492,9 @@ TEST_F(GraphicsComposerHidlTest, SetLayerColorTransform) { } TEST_F(GraphicsComposerHidlTest, GetDisplayedContentSamplingAttributes) { + using common::V1_1::PixelFormat; + using common::V1_2::Dataspace; + int constexpr invalid = -1; auto format = static_cast(invalid); auto dataspace = static_cast(invalid); From 89dfafb42f0a29a6f8c51c3aba7d0a301031124c Mon Sep 17 00:00:00 2001 From: Xusong Wang Date: Fri, 11 Jan 2019 17:41:11 -0800 Subject: [PATCH 414/718] Implement NN HAL for compilation caching. Add three methods - IDevice::isCachingSupported - IDevice::prepareModelFromCache - IPreparedModel::saveToCache Bug: 119616526 Test: NeuralNetworksTest_static Test: VtsHalNeuralnetworksV1_xTargetTest with 1.2 sample driver Change-Id: If28ffe0be48bcb9f4715293fc1201c8d2dbeb946 --- neuralnetworks/1.2/IDevice.hal | 99 +++++++++++++++++++++++++++ neuralnetworks/1.2/IPreparedModel.hal | 58 ++++++++++++++++ neuralnetworks/1.2/types.hal | 7 ++ 3 files changed, 164 insertions(+) diff --git a/neuralnetworks/1.2/IDevice.hal b/neuralnetworks/1.2/IDevice.hal index 6c3b4839e1..de249b0e08 100644 --- a/neuralnetworks/1.2/IDevice.hal +++ b/neuralnetworks/1.2/IDevice.hal @@ -97,6 +97,25 @@ interface IDevice extends @1.1::IDevice { getSupportedOperations_1_2(Model model) generates (ErrorStatus status, vec supportedOperations); + /** + * Gets whether the driver supports compilation caching. + * + * isCachingSupported indicates whether the driver supports compilation caching. + * Even if so, the driver may still choose not to cache certain compiled models. + * + * If the device reports the caching is not supported, the user may avoid calling + * IDevice::prepareModelFromCache and IPreparedModel::saveToCache. + * + * @return status Error status of the call, must be: + * - NONE if successful + * - DEVICE_UNAVAILABLE if driver is offline or busy + * - GENERAL_FAILURE if there is an unspecified error + * @return supported A boolean indicating whether the driver supports compilation + * caching. Even on returning true, the driver may still choose + * not to cache certain compiled models. + */ + isCachingSupported() generates (ErrorStatus status, bool supported); + /** * Creates a prepared model for execution. * @@ -153,4 +172,84 @@ interface IDevice extends @1.1::IDevice { prepareModel_1_2(Model model, ExecutionPreference preference, IPreparedModelCallback callback) generates (ErrorStatus status); + + /** + * Creates a prepared model from cache files for execution. + * + * prepareModelFromCache is used to retrieve a prepared model directly from + * cache files to avoid slow model compilation time. There are exactly two + * cache file descriptors provided to the driver: modelCache and dataCache. + * + * The dataCache is for caching constant data, possibly including preprocessed + * and transformed tensor buffers. Any modification to the dataCache should + * have no worse effect than generating bad output values at execution time. + * + * The modelCache is for caching security-sensitive data such as compiled + * executable machine code in the device's native binary format. A modification + * to the modelCache may affect the driver's execution behavior, and a malicious + * client could make use of this to execute beyond the granted permission. Thus, + * the driver must always check whether the modelCache is corrupted before preparing + * the model from cache. + * + * The two file descriptors may be closed by the client once the asynchronous + * preparation has finished. The driver has to copy all the data it needs. + * + * The model is prepared asynchronously with respect to the caller. The + * prepareModelFromCache function must verify the inputs to the + * prepareModelFromCache function are correct, and that the security-sensitive + * cache has not been modified since it was last written by the driver. + * If there is an error, or if compilation caching is not supported, or if the + * security-sensitive cache has been modified, prepareModelFromCache must + * immediately invoke the callback with the appropriate ErrorStatus value and + * nullptr for the IPreparedModel, then return with the same ErrorStatus. If + * the inputs to the prepareModelFromCache function are valid, the security-sensitive + * cache is not modified, and there is no error, prepareModelFromCache must launch an + * asynchronous task to prepare the model in the background, and immediately return + * from prepareModelFromCache with ErrorStatus::NONE. If the asynchronous task + * fails to launch, prepareModelFromCache must immediately invoke the callback + * with ErrorStatus::GENERAL_FAILURE and nullptr for the IPreparedModel, then + * return with ErrorStatus::GENERAL_FAILURE. + * + * When the asynchronous task has finished preparing the model, it must + * immediately invoke the callback function provided as an input to + * prepareModelFromCache. If the model was prepared successfully, the + * callback object must be invoked with an error status of ErrorStatus::NONE + * and the produced IPreparedModel object. If an error occurred preparing + * the model, the callback object must be invoked with the appropriate + * ErrorStatus value and nullptr for the IPreparedModel. + * + * The only information that may be unknown to the model at this stage is + * the shape of the tensors, which may only be known at execution time. As + * such, some driver services may return partially prepared models, where + * the prepared model may only be finished when it is paired with a set of + * inputs to the model. Note that the same prepared model object may be + * used with different shapes of inputs on different (possibly concurrent) + * executions. + * + * @param modelCache A handle holding exactly one cache file descriptor for the + * security-sensitive cache. + * @param dataCache A handle holding exactly one cache file descriptor for the + * constants' cache. + * @param token A caching token of length Constant::BYTE_SIZE_OF_CACHE_TOKEN + * identifying the prepared model. It is the same token provided when saving + * the cache files with IPreparedModel::saveToCache. Tokens should be chosen + * to have a low rate of collision for a particular application. The driver + * cannot detect a collision; a collision will result in a failed execution + * or in a successful execution that produces incorrect output values. + * @param callback A callback object used to return the error status of + * preparing the model for execution and the prepared model if + * successful, nullptr otherwise. The callback object's notify function + * must be called exactly once, even if the model could not be prepared. + * @return status Error status of launching a task which prepares the model + * in the background; must be: + * - NONE if preparation task is successfully launched + * - DEVICE_UNAVAILABLE if driver is offline or busy + * - GENERAL_FAILURE if caching is not supported or if there is an + * unspecified error + * - INVALID_ARGUMENT if one of the input arguments is invalid + */ + prepareModelFromCache(handle modelCache, handle dataCache, + uint8_t[Constant:BYTE_SIZE_OF_CACHE_TOKEN] token, + IPreparedModelCallback callback) + generates (ErrorStatus status); }; diff --git a/neuralnetworks/1.2/IPreparedModel.hal b/neuralnetworks/1.2/IPreparedModel.hal index 5d2d80ff71..757d5f1467 100644 --- a/neuralnetworks/1.2/IPreparedModel.hal +++ b/neuralnetworks/1.2/IPreparedModel.hal @@ -157,4 +157,62 @@ interface IPreparedModel extends @1.0::IPreparedModel { fmq_sync requestChannel, fmq_sync resultChannel) generates (ErrorStatus status, IBurstContext context); + + /* + * Saves the prepared model to cache files. + * + * saveToCache is used to save a prepared model to cache files for faster + * model compilation time when the same model preparation is requested in + * the future. There are exactly two cache file descriptors provided to the + * driver: modelCache and dataCache. + * + * The dataCache is for caching constant data, possibly including preprocessed + * and transformed tensor buffers. Any modification to the dataCache should + * have no worse effect than generating bad output values at execution time. + * + * The modelCache is for caching security-sensitive data such as compiled + * executable machine code in the device's native binary format. A modification + * to the modelCache may affect the driver's execution behavior, and a malicious + * client could make use of this to execute beyond the granted permission. Thus, + * the driver must always check whether the modelCache is corrupted before preparing + * the model from cache. + * + * The two file descriptors must point to two zero-length files with offset + * positioned at the beginning of the file. The file descriptors may be closed + * by the client once the method has returned. + * + * If the driver decides not to save the prepared model without looking at the + * input arguments to the saveToCache function, saveToCache must return with + * ErrorStatus::GENERAL_FAILURE. Otherwise, the saveToCache function must verify + * the input arguments to the saveToCache function are valid, and return with + * ErrorStatus::INVALID_ARGUMENT if not. If the inputs are valid but the driver + * could not save the prepared model, saveToCache must return with the appropriate + * ErrorStatus. Otherwise, it must write the cache files and return + * ErrorStatus::NONE. Unless saveToCache returns ErrorStatus::NONE, the contents + * of the cache files are undefined. + * + * @param modelCache A handle holding exactly one cache file descriptor for the + * security-sensitive cache. + * @param dataCache A handle holding exactly one cache file descriptor for the + * constants' cache. + * @param token A caching token of length Constant::BYTE_SIZE_OF_CACHE_TOKEN + * identifying the prepared model. The same token will be provided + * when retrieving the prepared model from cache files with + * IDevice::prepareModelFromCache. Tokens should be chosen to have + * a low rate of collision for a particular application. The driver + * cannot detect a collision; a collision will result in a failed + * execution or in a successful execution that produces incorrect + * output values. + * @return status Error status of saveToCache, must be: + * - NONE if saveToCache is performed successfully + * - DEVICE_UNAVAILABLE if driver is offline or busy + * - GENERAL_FAILURE if the driver could not save the + * prepared model or if there is an unspecified error + * - INVALID_ARGUMENT if one of the input arguments is invalid, + * unless the driver decides not to save the prepared model + * without looking at the input arguments + */ + saveToCache(handle modelCache, handle dataCache, + uint8_t[Constant:BYTE_SIZE_OF_CACHE_TOKEN] token) + generates (ErrorStatus status); }; diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal index bd8354fecf..0abe56dea6 100644 --- a/neuralnetworks/1.2/types.hal +++ b/neuralnetworks/1.2/types.hal @@ -25,6 +25,13 @@ import @1.1::OperationType; import android.hidl.safe_union@1.0::Monostate; +enum Constant : uint32_t { + /** + * The byte size of the cache token. + */ + BYTE_SIZE_OF_CACHE_TOKEN = 32, +}; + enum OperandType : @1.0::OperandType { /** * An 8 bit boolean scalar value. From 1ec0b52d176ddf41ab3e052917df3d3b7d7e0fa0 Mon Sep 17 00:00:00 2001 From: Kevin DuBois Date: Fri, 25 Jan 2019 11:06:13 -0800 Subject: [PATCH 415/718] graphics.common: add HSV format definition to 1.2 Adds HSV format used in some color sampling engines to the list of pixel formats. Rev the sampling engine in composer to reference the new format revision. Test: built image, with new format reported in vendor code. Test: VtsHalGraphicsComposerV2_3TargetTest Fixes: 122943743 Roll-forward of build-breaking topic commit. No changes were needed in this patch. see bug 123404649 for breakage details. This reverts commit e2f69f22289ffadc8dcfdbb476422e194442253a. Change-Id: I38ac5cafeb6a07e683352c8d297892a681e24702 --- configstore/1.2/ISurfaceFlingerConfigs.hal | 2 +- .../1.2/default/SurfaceFlingerConfigs.cpp | 2 +- .../VtsHalConfigstoreV1_2TargetTest.cpp | 4 ++-- graphics/common/1.2/types.hal | 18 +++++++++++++++++- graphics/composer/2.3/IComposerClient.hal | 2 +- .../include/composer-hal/2.3/ComposerClient.h | 2 +- .../hal/include/composer-hal/2.3/ComposerHal.h | 2 +- .../include/composer-passthrough/2.3/HwcHal.h | 8 +++++--- .../vts/include/composer-vts/2.3/ComposerVts.h | 2 +- .../VtsHalGraphicsComposerV2_3TargetTest.cpp | 5 +---- 10 files changed, 31 insertions(+), 16 deletions(-) diff --git a/configstore/1.2/ISurfaceFlingerConfigs.hal b/configstore/1.2/ISurfaceFlingerConfigs.hal index 7e5f706c02..431b3fc479 100644 --- a/configstore/1.2/ISurfaceFlingerConfigs.hal +++ b/configstore/1.2/ISurfaceFlingerConfigs.hal @@ -15,7 +15,7 @@ */ package android.hardware.configstore@1.2; -import android.hardware.graphics.common@1.1::PixelFormat; +import android.hardware.graphics.common@1.2::PixelFormat; import android.hardware.graphics.common@1.2::Dataspace; import @1.1::ISurfaceFlingerConfigs; import @1.0::OptionalBool; diff --git a/configstore/1.2/default/SurfaceFlingerConfigs.cpp b/configstore/1.2/default/SurfaceFlingerConfigs.cpp index d38b402889..714442bd22 100644 --- a/configstore/1.2/default/SurfaceFlingerConfigs.cpp +++ b/configstore/1.2/default/SurfaceFlingerConfigs.cpp @@ -27,8 +27,8 @@ namespace configstore { namespace V1_2 { namespace implementation { -using ::android::hardware::graphics::common::V1_1::PixelFormat; using ::android::hardware::graphics::common::V1_2::Dataspace; +using ::android::hardware::graphics::common::V1_2::PixelFormat; // ::android::hardware::configstore::V1_0::ISurfaceFlingerConfigs implementation. Return SurfaceFlingerConfigs::vsyncEventPhaseOffsetNs(vsyncEventPhaseOffsetNs_cb _hidl_cb) { diff --git a/configstore/1.2/vts/functional/VtsHalConfigstoreV1_2TargetTest.cpp b/configstore/1.2/vts/functional/VtsHalConfigstoreV1_2TargetTest.cpp index 881b591284..d7f4dcf75f 100644 --- a/configstore/1.2/vts/functional/VtsHalConfigstoreV1_2TargetTest.cpp +++ b/configstore/1.2/vts/functional/VtsHalConfigstoreV1_2TargetTest.cpp @@ -31,10 +31,10 @@ using ::android::hardware::Void; using ::android::hardware::configstore::V1_0::OptionalBool; using ::android::hardware::configstore::V1_0::OptionalInt64; using ::android::hardware::configstore::V1_0::OptionalUInt64; -using ::android::hardware::configstore::V1_2::ISurfaceFlingerConfigs; using ::android::hardware::configstore::V1_2::DisplayPrimaries; -using ::android::hardware::graphics::common::V1_1::PixelFormat; +using ::android::hardware::configstore::V1_2::ISurfaceFlingerConfigs; using ::android::hardware::graphics::common::V1_2::Dataspace; +using ::android::hardware::graphics::common::V1_2::PixelFormat; #define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk()) #define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk()) diff --git a/graphics/common/1.2/types.hal b/graphics/common/1.2/types.hal index 392a12e2e4..c9c3aeb972 100644 --- a/graphics/common/1.2/types.hal +++ b/graphics/common/1.2/types.hal @@ -25,7 +25,8 @@ import @1.1::PixelFormat; /** * Hdr */ -@export(name="android_hdr_v1_2_t", value_prefix="HAL_HDR_") +@export(name="android_hdr_v1_2_t", value_prefix="HAL_HDR_", + export_parent="false") enum Hdr : @1.0::Hdr { HDR10_PLUS = 4, }; @@ -96,3 +97,18 @@ struct HardwareBuffer { */ typedef int32_t[4] Rect; +/** + * Pixel formats for graphics buffers. + */ +@export(name="android_pixel_format_v1_2_t", value_prefix="HAL_PIXEL_FORMAT_", + export_parent="false") +enum PixelFormat : @1.1::PixelFormat { + /** + * 24-bit format that has 8-bit H, S, and V components, in that order, + * from the lowest memory address to the highest memory address. + * + * The component values are unsigned normalized to the range [0, 1], whose + * interpretation is defined by the dataspace. + */ + HSV_888 = 0x37, +}; diff --git a/graphics/composer/2.3/IComposerClient.hal b/graphics/composer/2.3/IComposerClient.hal index cf78dea532..a3b7792c05 100644 --- a/graphics/composer/2.3/IComposerClient.hal +++ b/graphics/composer/2.3/IComposerClient.hal @@ -17,7 +17,7 @@ package android.hardware.graphics.composer@2.3; import android.hardware.graphics.common@1.1::RenderIntent; -import android.hardware.graphics.common@1.1::PixelFormat; +import android.hardware.graphics.common@1.2::PixelFormat; import android.hardware.graphics.common@1.2::ColorMode; import android.hardware.graphics.common@1.2::Dataspace; import android.hardware.graphics.common@1.2::Hdr; diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h index edc203eb1d..a272e72d74 100644 --- a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h +++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h @@ -123,7 +123,7 @@ class ComposerClientImpl : public V2_2::hal::detail::ComposerClientImpl getDisplayedContentSamplingAttributes( uint64_t display, IComposerClient::getDisplayedContentSamplingAttributes_cb hidl_cb) override { - common::V1_1::PixelFormat format; + PixelFormat format; common::V1_2::Dataspace dataspace; hidl_bitfield componentMask; Error error = diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h index 882621f086..a0812ad9a7 100644 --- a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h +++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h @@ -25,11 +25,11 @@ namespace composer { namespace V2_3 { namespace hal { -using common::V1_1::PixelFormat; using common::V1_1::RenderIntent; using common::V1_2::ColorMode; using common::V1_2::Dataspace; using common::V1_2::Hdr; +using common::V1_2::PixelFormat; using V2_1::Display; using V2_1::Error; using V2_1::Layer; diff --git a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h index 9fb6d4bf7d..41e333ac5e 100644 --- a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h +++ b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h @@ -34,11 +34,11 @@ namespace passthrough { namespace detail { -using common::V1_1::PixelFormat; using common::V1_1::RenderIntent; using common::V1_2::ColorMode; using common::V1_2::Dataspace; using common::V1_2::Hdr; +using common::V1_2::PixelFormat; using V2_1::Display; using V2_1::Error; @@ -91,14 +91,16 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl { Error getClientTargetSupport_2_3(Display display, uint32_t width, uint32_t height, PixelFormat format, Dataspace dataspace) override { - return getClientTargetSupport_2_2(display, width, height, format, + return getClientTargetSupport_2_2(display, width, height, + static_cast(format), static_cast(dataspace)); } Error getReadbackBufferAttributes_2_3(Display display, PixelFormat* outFormat, Dataspace* outDataspace) override { return getReadbackBufferAttributes( - display, outFormat, reinterpret_cast(outDataspace)); + display, reinterpret_cast(outFormat), + reinterpret_cast(outDataspace)); } Error getDisplayIdentificationData(Display display, uint8_t* outPort, diff --git a/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h b/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h index 7add322282..ad4ef0b51e 100644 --- a/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h +++ b/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h @@ -32,11 +32,11 @@ namespace composer { namespace V2_3 { namespace vts { -using common::V1_1::PixelFormat; using common::V1_1::RenderIntent; using common::V1_2::ColorMode; using common::V1_2::Dataspace; using common::V1_2::Hdr; +using common::V1_2::PixelFormat; using V2_1::Display; using V2_1::Error; using V2_3::IComposer; diff --git a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp index dca7406c10..de74e28cc7 100644 --- a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp +++ b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp @@ -36,10 +36,10 @@ namespace vts { namespace { using common::V1_0::BufferUsage; -using common::V1_1::PixelFormat; using common::V1_1::RenderIntent; using common::V1_2::ColorMode; using common::V1_2::Dataspace; +using common::V1_2::PixelFormat; using mapper::V2_0::IMapper; using mapper::V2_0::vts::Gralloc; @@ -492,9 +492,6 @@ TEST_F(GraphicsComposerHidlTest, SetLayerColorTransform) { } TEST_F(GraphicsComposerHidlTest, GetDisplayedContentSamplingAttributes) { - using common::V1_1::PixelFormat; - using common::V1_2::Dataspace; - int constexpr invalid = -1; auto format = static_cast(invalid); auto dataspace = static_cast(invalid); From 758f4bb127f26a276376e3f01bb0473287c6217a Mon Sep 17 00:00:00 2001 From: Shik Chen Date: Wed, 16 Jan 2019 19:11:16 +0800 Subject: [PATCH 416/718] Camera: Enable external camera handling in default provider. * The sCameraDeviceStatusChange() callback might be fired between initialize() and setCallback(), which can be easily triggered if there is an external camera connected at the boot time. * The external cameras need to be excluded in the getCameraIdList(). Bug: 77833131 Bug: 122800852 Test: Reboot with an external camera is connected, and see the camera list is corrected probed in $ android-sh -c 'dumpsys media.camera' The testing device is Nautilus (Samsung Chromebook Plus). Change-Id: I5cec6732ce4e26632f1bb5186331b7ce7a94a0b3 --- .../provider/2.4/default/CameraProvider.cpp | 47 ++++++++++++++----- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/camera/provider/2.4/default/CameraProvider.cpp b/camera/provider/2.4/default/CameraProvider.cpp index 488b9afe58..f143dd7859 100644 --- a/camera/provider/2.4/default/CameraProvider.cpp +++ b/camera/provider/2.4/default/CameraProvider.cpp @@ -143,7 +143,6 @@ void CameraProvider::sCameraDeviceStatusChange( int new_status) { CameraProvider* cp = const_cast( static_cast(callbacks)); - bool found = false; if (cp == nullptr) { ALOGE("%s: callback ops is null", __FUNCTION__); @@ -155,17 +154,23 @@ void CameraProvider::sCameraDeviceStatusChange( snprintf(cameraId, sizeof(cameraId), "%d", camera_id); std::string cameraIdStr(cameraId); cp->mCameraStatusMap[cameraIdStr] = (camera_device_status_t) new_status; - if (cp->mCallbacks != nullptr) { - CameraDeviceStatus status = (CameraDeviceStatus) new_status; - for (auto const& deviceNamePair : cp->mCameraDeviceNames) { - if (cameraIdStr.compare(deviceNamePair.first) == 0) { - cp->mCallbacks->cameraDeviceStatusChange( - deviceNamePair.second, status); - found = true; - } - } - switch (status) { + if (cp->mCallbacks == nullptr) { + // For camera connected before mCallbacks is set, the corresponding + // addDeviceNames() would be called later in setCallbacks(). + return; + } + + bool found = false; + CameraDeviceStatus status = (CameraDeviceStatus)new_status; + for (auto const& deviceNamePair : cp->mCameraDeviceNames) { + if (cameraIdStr.compare(deviceNamePair.first) == 0) { + cp->mCallbacks->cameraDeviceStatusChange(deviceNamePair.second, status); + found = true; + } + } + + switch (status) { case CameraDeviceStatus::PRESENT: case CameraDeviceStatus::ENUMERATING: if (!found) { @@ -176,7 +181,6 @@ void CameraProvider::sCameraDeviceStatusChange( if (found) { cp->removeDeviceNames(camera_id); } - } } } @@ -439,8 +443,22 @@ bool CameraProvider::setUpVendorTags() { // Methods from ::android::hardware::camera::provider::V2_4::ICameraProvider follow. Return CameraProvider::setCallback(const sp& callback) { + if (callback == nullptr) { + return Status::ILLEGAL_ARGUMENT; + } + Mutex::Autolock _l(mCbLock); mCallbacks = callback; + + // Add and report all presenting external cameras. + for (auto const& statusPair : mCameraStatusMap) { + int id = std::stoi(statusPair.first); + auto status = static_cast(statusPair.second); + if (id >= mNumberOfLegacyCameras && status != CameraDeviceStatus::NOT_PRESENT) { + addDeviceNames(id, status, true); + } + } + return Status::OK; } @@ -452,6 +470,11 @@ Return CameraProvider::getVendorTags(getVendorTags_cb _hidl_cb) { Return CameraProvider::getCameraIdList(getCameraIdList_cb _hidl_cb) { std::vector deviceNameList; for (auto const& deviceNamePair : mCameraDeviceNames) { + if (std::stoi(deviceNamePair.first) >= mNumberOfLegacyCameras) { + // External camera devices must be reported through the device status change callback, + // not in this list. + continue; + } if (mCameraStatusMap[deviceNamePair.first] == CAMERA_DEVICE_STATUS_PRESENT) { deviceNameList.push_back(deviceNamePair.second); } From 814d8372f36fa0b7e6a8ac37784b4ec6ffa890fd Mon Sep 17 00:00:00 2001 From: Michael Butler Date: Tue, 15 Jan 2019 11:02:55 -0800 Subject: [PATCH 417/718] NNAPI Burst -- HAL VTS tests FastMessageQueue is a Treble-compliant data structure that enables fast communication between two processes. The FMQ object itself is an atomic circular buffer that is optionally synchronized with a futex. However, FMQ has no notion of ownership or lifetime across processes, so it must be paired with higher-level constructs to manage the lifetime and ownership. The NNAPI is introducing the notion of an "Execution Burst" object (or more simply a "Burst" object), which is similar to an ANeuralNetworksExecution, but is intended to be reused across multiple executions and has lower IPC overheads. It achieves this low IPC overhead by replacing HIDL HwBinder calls with FMQ messages. Specifically, it replaces IPreparedModel::executeSynchronously's call from the client into the service with fmq_sync (an FMQ channel used to pass a serialized Request object) and it replaces the return from the service into the client with fmq_sync (an FMQ channel used to return serialized result status and OutputShapes information). Each channel is a unidirectional flow of information with exactly one producer and exactly one consumer. The channels are created by the NN runtime and passed to the service via IPreparedModel::configureExecutionBurst. This CL tests the Burst in both the execution path and validation path in the Vendor Test Suite (VTS) in neuralnetworks/1.*/vts/functional/. The VTS binary--VtsHalNeuralnetworksV1_2TargetTest--can be built and run as any previous version could. Bug: 119570067 Test: mma Test: VtsHalNeuralnetworksV1_2TargetTest Change-Id: I3a36484eff9565c2d028c07c099804a0289f294a --- neuralnetworks/1.0/vts/functional/Android.bp | 2 + .../vts/functional/GeneratedTestHarness.cpp | 109 ++++++++++++------ .../1.2/vts/functional/ValidateRequest.cpp | 40 +++++++ 3 files changed, 118 insertions(+), 33 deletions(-) diff --git a/neuralnetworks/1.0/vts/functional/Android.bp b/neuralnetworks/1.0/vts/functional/Android.bp index 2920cec7cd..52d63286b7 100644 --- a/neuralnetworks/1.0/vts/functional/Android.bp +++ b/neuralnetworks/1.0/vts/functional/Android.bp @@ -23,6 +23,7 @@ cc_library_static { defaults: ["VtsHalTargetTestDefaults"], export_include_dirs: ["."], shared_libs: [ + "libfmq", "libnativewindow", ], static_libs: [ @@ -51,6 +52,7 @@ cc_defaults { "VtsHalNeuralnetworks.cpp", ], shared_libs: [ + "libfmq", "libnativewindow", ], static_libs: [ diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp index 65c425ee1e..8d427b1227 100644 --- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp +++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp @@ -15,6 +15,7 @@ */ #include "Callbacks.h" +#include "ExecutionBurstController.h" #include "TestHarness.h" #include "Utils.h" @@ -109,14 +110,23 @@ static Return ExecutePreparedModel(sp& prepar } return result; } -enum class Synchronously { NO, YES }; +static std::unique_ptr<::android::nn::ExecutionBurstController> CreateBurst( + const sp&) { + ADD_FAILURE() << "asking for burst execution at V1_0"; + return nullptr; +} +static std::unique_ptr<::android::nn::ExecutionBurstController> CreateBurst( + const sp& preparedModel) { + return ::android::nn::createExecutionBurstController(preparedModel, /*blocking=*/true); +} +enum class Executor { ASYNC, SYNC, BURST }; const float kDefaultAtol = 1e-5f; const float kDefaultRtol = 1e-5f; template void EvaluatePreparedModel(sp& preparedModel, std::function is_ignored, const std::vector& examples, bool hasRelaxedFloat32Model, float fpAtol, float fpRtol, - Synchronously sync, MeasureTiming measure, bool testDynamicOutputShape) { + Executor executor, MeasureTiming measure, bool testDynamicOutputShape) { const uint32_t INPUT = 0; const uint32_t OUTPUT = 1; @@ -209,35 +219,62 @@ void EvaluatePreparedModel(sp& preparedModel, std::functioncommit(); outputMemory->commit(); + const Request request = {.inputs = inputs_info, .outputs = outputs_info, .pools = pools}; + ErrorStatus executionStatus; hidl_vec outputShapes; Timing timing; - if (sync == Synchronously::NO) { - SCOPED_TRACE("asynchronous"); + switch (executor) { + case Executor::ASYNC: { + SCOPED_TRACE("asynchronous"); - // launch execution - sp executionCallback = new ExecutionCallback(); - ASSERT_NE(nullptr, executionCallback.get()); - Return executionLaunchStatus = ExecutePreparedModel( - preparedModel, {.inputs = inputs_info, .outputs = outputs_info, .pools = pools}, - measure, executionCallback); - ASSERT_TRUE(executionLaunchStatus.isOk()); - EXPECT_EQ(ErrorStatus::NONE, static_cast(executionLaunchStatus)); + // launch execution + sp executionCallback = new ExecutionCallback(); + ASSERT_NE(nullptr, executionCallback.get()); + Return executionLaunchStatus = + ExecutePreparedModel(preparedModel, request, measure, executionCallback); + ASSERT_TRUE(executionLaunchStatus.isOk()); + EXPECT_EQ(ErrorStatus::NONE, static_cast(executionLaunchStatus)); - // retrieve execution status - executionCallback->wait(); - executionStatus = executionCallback->getStatus(); - outputShapes = executionCallback->getOutputShapes(); - timing = executionCallback->getTiming(); - } else { - SCOPED_TRACE("synchronous"); + // retrieve execution status + executionCallback->wait(); + executionStatus = executionCallback->getStatus(); + outputShapes = executionCallback->getOutputShapes(); + timing = executionCallback->getTiming(); - // execute - Return executionReturnStatus = ExecutePreparedModel( - preparedModel, {.inputs = inputs_info, .outputs = outputs_info, .pools = pools}, - measure, &outputShapes, &timing); - ASSERT_TRUE(executionReturnStatus.isOk()); - executionStatus = static_cast(executionReturnStatus); + break; + } + case Executor::SYNC: { + SCOPED_TRACE("synchronous"); + + // execute + Return executionReturnStatus = ExecutePreparedModel( + preparedModel, request, measure, &outputShapes, &timing); + ASSERT_TRUE(executionReturnStatus.isOk()); + executionStatus = static_cast(executionReturnStatus); + + break; + } + case Executor::BURST: { + SCOPED_TRACE("burst"); + + // create burst + const std::unique_ptr<::android::nn::ExecutionBurstController> controller = + CreateBurst(preparedModel); + ASSERT_NE(nullptr, controller.get()); + + // create memory keys + std::vector keys(request.pools.size()); + for (size_t i = 0; i < keys.size(); ++i) { + keys[i] = reinterpret_cast(&request.pools[i]); + } + + // execute burst + std::tie(executionStatus, outputShapes, timing) = + controller->compute(request, measure, keys); + + break; + } } if (testDynamicOutputShape && executionStatus != ErrorStatus::NONE) { @@ -286,10 +323,10 @@ void EvaluatePreparedModel(sp& preparedModel, std::function void EvaluatePreparedModel(sp& preparedModel, std::function is_ignored, const std::vector& examples, - bool hasRelaxedFloat32Model, Synchronously sync, MeasureTiming measure, + bool hasRelaxedFloat32Model, Executor executor, MeasureTiming measure, bool testDynamicOutputShape) { EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model, kDefaultAtol, - kDefaultRtol, sync, measure, testDynamicOutputShape); + kDefaultRtol, executor, measure, testDynamicOutputShape); } static void getPreparedModel(sp callback, @@ -345,7 +382,7 @@ void Execute(const sp& device, std::function c float fpAtol = 1e-5f, fpRtol = 5.0f * 1.1920928955078125e-7f; EvaluatePreparedModel(preparedModel, is_ignored, examples, - /*hasRelaxedFloat32Model=*/false, fpAtol, fpRtol, Synchronously::NO, + /*hasRelaxedFloat32Model=*/false, fpAtol, fpRtol, Executor::ASYNC, MeasureTiming::NO, /*testDynamicOutputShape=*/false); } @@ -392,7 +429,7 @@ void Execute(const sp& device, std::function c ASSERT_NE(nullptr, preparedModel.get()); EvaluatePreparedModel(preparedModel, is_ignored, examples, - model.relaxComputationFloat32toFloat16, 1e-5f, 1e-5f, Synchronously::NO, + model.relaxComputationFloat32toFloat16, 1e-5f, 1e-5f, Executor::ASYNC, MeasureTiming::NO, /*testDynamicOutputShape=*/false); } @@ -441,16 +478,22 @@ void Execute(const sp& device, std::function c ASSERT_NE(nullptr, preparedModel.get()); EvaluatePreparedModel(preparedModel, is_ignored, examples, - model.relaxComputationFloat32toFloat16, Synchronously::NO, + model.relaxComputationFloat32toFloat16, Executor::ASYNC, MeasureTiming::NO, testDynamicOutputShape); EvaluatePreparedModel(preparedModel, is_ignored, examples, - model.relaxComputationFloat32toFloat16, Synchronously::YES, + model.relaxComputationFloat32toFloat16, Executor::SYNC, MeasureTiming::NO, + testDynamicOutputShape); + EvaluatePreparedModel(preparedModel, is_ignored, examples, + model.relaxComputationFloat32toFloat16, Executor::BURST, MeasureTiming::NO, testDynamicOutputShape); EvaluatePreparedModel(preparedModel, is_ignored, examples, - model.relaxComputationFloat32toFloat16, Synchronously::NO, + model.relaxComputationFloat32toFloat16, Executor::ASYNC, MeasureTiming::YES, testDynamicOutputShape); EvaluatePreparedModel(preparedModel, is_ignored, examples, - model.relaxComputationFloat32toFloat16, Synchronously::YES, + model.relaxComputationFloat32toFloat16, Executor::SYNC, + MeasureTiming::YES, testDynamicOutputShape); + EvaluatePreparedModel(preparedModel, is_ignored, examples, + model.relaxComputationFloat32toFloat16, Executor::BURST, MeasureTiming::YES, testDynamicOutputShape); } diff --git a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp index 00a7c3ec4f..d411da4819 100644 --- a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp +++ b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp @@ -19,6 +19,7 @@ #include "VtsHalNeuralnetworks.h" #include "Callbacks.h" +#include "ExecutionBurstController.h" #include "TestHarness.h" #include "Utils.h" @@ -112,6 +113,7 @@ static void validate(const sp& preparedModel, const std::string& }; MeasureTiming measure = (hash & 1) ? MeasureTiming::YES : MeasureTiming::NO; + // asynchronous { SCOPED_TRACE(message + " [execute_1_2]"); @@ -131,6 +133,7 @@ static void validate(const sp& preparedModel, const std::string& ASSERT_TRUE(badTiming(timing)); } + // synchronous { SCOPED_TRACE(message + " [executeSynchronously]"); @@ -144,6 +147,43 @@ static void validate(const sp& preparedModel, const std::string& }); ASSERT_TRUE(executeStatus.isOk()); } + + // burst + { + SCOPED_TRACE(message + " [burst]"); + + // create burst + std::unique_ptr<::android::nn::ExecutionBurstController> burst = + ::android::nn::createExecutionBurstController(preparedModel, /*blocking=*/true); + ASSERT_NE(nullptr, burst.get()); + + // create memory keys + std::vector keys(request.pools.size()); + for (size_t i = 0; i < keys.size(); ++i) { + keys[i] = reinterpret_cast(&request.pools[i]); + } + + // execute and verify + ErrorStatus error; + std::vector outputShapes; + Timing timing; + std::tie(error, outputShapes, timing) = burst->compute(request, measure, keys); + EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, error); + EXPECT_EQ(outputShapes.size(), 0); + EXPECT_TRUE(badTiming(timing)); + + // additional burst testing + if (request.pools.size() > 0) { + // valid free + burst->freeMemory(keys.front()); + + // negative test: invalid free of unknown (blank) memory + burst->freeMemory(intptr_t{}); + + // negative test: double free of memory + burst->freeMemory(keys.front()); + } + } } // Delete element from hidl_vec. hidl_vec doesn't support a "remove" operation, From 45c1d0c19285f3abcbf394357541027841995c8e Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Thu, 24 Jan 2019 10:38:02 -0800 Subject: [PATCH 418/718] Move input definitions into separate HAL The types added for input in InputClassifier HAL are not specific to that HAL. These are common input definitions. To allow for future reuse in this and other HALs, move these definitions into a separate, type-only HAL android::hardware::input::common. This will be similar to such existing HALs as: hardware/interfaces/graphics/common hardware/interfaces/camera/common hardware/interfaces/audio/common Test: make only Bug: 111480215 Change-Id: I16d76d6bdb48b24487b232fda45c6146e1003fe9 --- input/classifier/1.0/Android.bp | 19 +---------- input/classifier/1.0/IInputClassifier.hal | 3 ++ .../1.0/default/InputClassifier.cpp | 2 +- .../classifier/1.0/default/InputClassifier.h | 5 +-- input/common/1.0/Android.bp | 34 +++++++++++++++++++ input/{classifier => common}/1.0/types.hal | 14 ++++---- 6 files changed, 49 insertions(+), 28 deletions(-) create mode 100644 input/common/1.0/Android.bp rename input/{classifier => common}/1.0/types.hal (99%) diff --git a/input/classifier/1.0/Android.bp b/input/classifier/1.0/Android.bp index c3c6fc6123..6815a513c1 100644 --- a/input/classifier/1.0/Android.bp +++ b/input/classifier/1.0/Android.bp @@ -7,29 +7,12 @@ hidl_interface { enabled: true, }, srcs: [ - "types.hal", "IInputClassifier.hal", ], interfaces: [ + "android.hardware.input.common@1.0", "android.hidl.base@1.0", ], - types: [ - "Action", - "Axis", - "Button", - "Classification", - "EdgeFlag", - "Flag", - "Meta", - "MotionEvent", - "PointerCoords", - "PointerProperties", - "PolicyFlag", - "Source", - "SourceClass", - "ToolType", - "VideoFrame", - ], gen_java: true, } diff --git a/input/classifier/1.0/IInputClassifier.hal b/input/classifier/1.0/IInputClassifier.hal index edc113807a..5f8c2a564d 100644 --- a/input/classifier/1.0/IInputClassifier.hal +++ b/input/classifier/1.0/IInputClassifier.hal @@ -16,6 +16,9 @@ package android.hardware.input.classifier@1.0; +import android.hardware.input.common@1.0::Classification; +import android.hardware.input.common@1.0::MotionEvent; + interface IInputClassifier { /** diff --git a/input/classifier/1.0/default/InputClassifier.cpp b/input/classifier/1.0/default/InputClassifier.cpp index c463361dcb..7005e9d8b6 100644 --- a/input/classifier/1.0/default/InputClassifier.cpp +++ b/input/classifier/1.0/default/InputClassifier.cpp @@ -21,7 +21,7 @@ #include #include -using namespace android::hardware::input::classifier::V1_0; +using namespace android::hardware::input::common::V1_0; namespace android { namespace hardware { diff --git a/input/classifier/1.0/default/InputClassifier.h b/input/classifier/1.0/default/InputClassifier.h index 0858ecbae0..39c4b17b38 100644 --- a/input/classifier/1.0/default/InputClassifier.h +++ b/input/classifier/1.0/default/InputClassifier.h @@ -31,8 +31,9 @@ using ::android::hardware::Return; struct InputClassifier : public IInputClassifier { // Methods from ::android::hardware::input::classifier::V1_0::IInputClassifier follow. - Return classify( - const ::android::hardware::input::classifier::V1_0::MotionEvent& event) override; + + Return classify( + const android::hardware::input::common::V1_0::MotionEvent& event) override; }; } // namespace implementation diff --git a/input/common/1.0/Android.bp b/input/common/1.0/Android.bp new file mode 100644 index 0000000000..68a77f13d9 --- /dev/null +++ b/input/common/1.0/Android.bp @@ -0,0 +1,34 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +hidl_interface { + name: "android.hardware.input.common@1.0", + root: "android.hardware", + vndk: { + enabled: true, + }, + srcs: [ + "types.hal", + ], + interfaces: [ + "android.hidl.base@1.0", + ], + types: [ + "Action", + "Axis", + "Button", + "Classification", + "EdgeFlag", + "Flag", + "Meta", + "MotionEvent", + "PointerCoords", + "PointerProperties", + "PolicyFlag", + "Source", + "SourceClass", + "ToolType", + "VideoFrame", + ], + gen_java: true, +} + diff --git a/input/classifier/1.0/types.hal b/input/common/1.0/types.hal similarity index 99% rename from input/classifier/1.0/types.hal rename to input/common/1.0/types.hal index 244ecd93b8..1a07f3b76d 100644 --- a/input/classifier/1.0/types.hal +++ b/input/common/1.0/types.hal @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.hardware.input.classifier@1.0; +package android.hardware.input.common@1.0; /** @@ -435,12 +435,12 @@ struct PointerCoords { }; enum SourceClass: uint8_t { - NONE = 1 << 0, - BUTTON = 1 << 1, - POINTER = 1 << 2, - NAVIGATION = 1 << 3, - POSITION = 1 << 4, - JOYSTICK = 1 << 5, + NONE = 0 << 0, + BUTTON = 1 << 0, + POINTER = 1 << 1, + NAVIGATION = 1 << 2, + POSITION = 1 << 3, + JOYSTICK = 1 << 4, }; /** From 5f103998ffd9e6af55c19c00af424b0b87338c36 Mon Sep 17 00:00:00 2001 From: Emilian Peev Date: Fri, 4 Jan 2019 13:01:05 +0000 Subject: [PATCH 419/718] Camera: Add dynamic depth tags and dataspace Add necessary metadata tags for supporting dynamic depth streams. Includes minor gfx fix which should help eliminate build errors after HIDL header autogen. Bug: 109735087 Test: vts-tradefed run commandAndExit vts --skip-all-system-status-check --skip-preconditions --module VtsHalCameraProviderV2_4Target -l INFO Change-Id: Ia476b195095ae7a29bc740174331dfbfdaa6d320 --- camera/metadata/3.4/types.hal | 30 +++++++++++++++++++ .../VtsHalCameraProviderV2_4TargetTest.cpp | 18 +++++++++++ graphics/common/1.2/types.hal | 7 +++++ 3 files changed, 55 insertions(+) diff --git a/camera/metadata/3.4/types.hal b/camera/metadata/3.4/types.hal index 28c56c8081..9bbc90dc28 100644 --- a/camera/metadata/3.4/types.hal +++ b/camera/metadata/3.4/types.hal @@ -73,6 +73,28 @@ enum CameraMetadataTag : @3.3::CameraMetadataTag { */ ANDROID_DEPTH_AVAILABLE_RECOMMENDED_DEPTH_STREAM_CONFIGURATIONS = android.hardware.camera.metadata@3.2::CameraMetadataTag:ANDROID_DEPTH_END, + /** android.depth.availableDynamicDepthStreamConfigurations [static, enum[], ndk_public] + * + *

The available dynamic depth dataspace stream + * configurations that this camera device supports + * (i.e. format, width, height, output/input stream).

+ */ + ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS, + + /** android.depth.availableDynamicDepthMinFrameDurations [static, int64[], ndk_public] + * + *

This lists the minimum frame duration for each + * format/size combination for dynamic depth output streams.

+ */ + ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS, + + /** android.depth.availableDynamicDepthStallDurations [static, int64[], ndk_public] + * + *

This lists the maximum stall duration for each + * output format/size combination for dynamic depth streams.

+ */ + ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS, + ANDROID_DEPTH_END_3_4, /** android.logicalMultiCamera.activePhysicalId [dynamic, byte, public] @@ -136,3 +158,11 @@ enum CameraMetadataEnumAndroidSensorInfoColorFilterArrangement : enum CameraMetadataEnumAndroidInfoSupportedBufferManagementVersion : uint32_t { ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5, }; + +/** android.depth.availableDynamicDepthStreamConfigurations enumeration values + * @see ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS + */ +enum CameraMetadataEnumAndroidDepthAvailableDynamicDepthStreamConfigurations : uint32_t { + ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS_OUTPUT, + ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS_INPUT, +}; diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp index 1556c08c9f..211240a06b 100644 --- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp +++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp @@ -5521,6 +5521,24 @@ void CameraHidlTest::verifyCameraCharacteristics(Status status, const CameraMeta ADD_FAILURE() << "ANDROID_REQUEST_CHARACTERISTIC_KEYS_NEEDING_PERMISSION " << " per API contract should never be set by Hal!"; } + retcode = find_camera_metadata_ro_entry(metadata, + ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS, &entry); + if ((0 == retcode) || (entry.count > 0)) { + ADD_FAILURE() << "ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS" + << " per API contract should never be set by Hal!"; + } + retcode = find_camera_metadata_ro_entry(metadata, + ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS, &entry); + if ((0 == retcode) || (entry.count > 0)) { + ADD_FAILURE() << "ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS" + << " per API contract should never be set by Hal!"; + } + retcode = find_camera_metadata_ro_entry(metadata, + ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS, &entry); + if ((0 == retcode) || (entry.count > 0)) { + ADD_FAILURE() << "ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS" + << " per API contract should never be set by Hal!"; + } } void CameraHidlTest::verifyMonochromeCharacteristics(const CameraMetadata& chars, diff --git a/graphics/common/1.2/types.hal b/graphics/common/1.2/types.hal index c9c3aeb972..3da6176342 100644 --- a/graphics/common/1.2/types.hal +++ b/graphics/common/1.2/types.hal @@ -42,6 +42,13 @@ enum Dataspace : @1.1::Dataspace { * Use full range, sRGB transfer and BT2020 standard */ DISPLAY_BT2020 = STANDARD_BT2020 | TRANSFER_SRGB | RANGE_FULL, + + /** + * ISO 16684-1:2011(E) + * + * Embedded depth metadata following the dynamic depth specification. + */ + DYNAMIC_DEPTH = 0x1002, }; enum ColorMode : @1.1::ColorMode { From 7bdd7298ee86b48ad8c1dee0da52fb1f43e28874 Mon Sep 17 00:00:00 2001 From: lesl Date: Thu, 24 Jan 2019 16:16:18 +0800 Subject: [PATCH 420/718] vts: add vts for hostapd1.1 new function addAccessPoint_1_1 BUG: 123209079 Test: build - make vts Test: atest VtsHalWifiHostapdV1_1Target Test: vts-tradefed run commandAndExit vts-hal --skip-all-system-status-check \ --primary-abi-only --skip-preconditions --module \ VtsHalWifiHostapdV1_1Target -l INFO Change-Id: I2798c363f51d64c8dcfdfdb8488374cd217f3e47 --- .../1.1/vts/functional/hostapd_hidl_test.cpp | 211 ++++++++++++++++++ 1 file changed, 211 insertions(+) diff --git a/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp b/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp index d1af655f91..439a62403d 100644 --- a/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp +++ b/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp @@ -34,6 +34,14 @@ using ::android::hardware::wifi::hostapd::V1_0::HostapdStatusCode; using ::android::hardware::wifi::hostapd::V1_1::IHostapd; using ::android::hardware::wifi::hostapd::V1_1::IHostapdCallback; +namespace { +constexpr unsigned char kNwSsid[] = {'t', 'e', 's', 't', '1', + '2', '3', '4', '5'}; +constexpr char kNwPassphrase[] = "test12345"; +constexpr int kIfaceChannel = 6; +constexpr int kIfaceInvalidChannel = 567; +} // namespace + class HostapdHidlTest : public ::testing::VtsHalHidlTargetTestBase { public: virtual void SetUp() override { @@ -45,6 +53,99 @@ class HostapdHidlTest : public ::testing::VtsHalHidlTargetTestBase { virtual void TearDown() override { stopHostapd(); } protected: + std::string getPrimaryWlanIfaceName() { + std::array buffer; + property_get("wifi.interface", buffer.data(), "wlan0"); + return buffer.data(); + } + + IHostapd::IfaceParams getIfaceParamsWithAcs() { + ::android::hardware::wifi::hostapd::V1_0::IHostapd::IfaceParams + iface_params; + IHostapd::IfaceParams iface_params_1_1; + + iface_params.ifaceName = getPrimaryWlanIfaceName(); + iface_params.hwModeParams.enable80211N = true; + iface_params.hwModeParams.enable80211AC = false; + iface_params.channelParams.enableAcs = true; + iface_params.channelParams.acsShouldExcludeDfs = true; + iface_params.channelParams.channel = 0; + iface_params.channelParams.band = IHostapd::Band::BAND_ANY; + iface_params_1_1.V1_0 = iface_params; + return iface_params_1_1; + } + + IHostapd::IfaceParams getIfaceParamsWithAcsAndChannelRange() { + IHostapd::IfaceParams iface_params_1_1 = getIfaceParamsWithAcs(); + IHostapd::ChannelParams channelParams; + IHostapd::AcsChannelRange acsChannelRange; + acsChannelRange.start = 1; + acsChannelRange.end = 11; + std::vector vec_acsChannelRange; + vec_acsChannelRange.push_back(acsChannelRange); + channelParams.acsChannelRanges = vec_acsChannelRange; + iface_params_1_1.channelParams = channelParams; + return iface_params_1_1; + } + + IHostapd::IfaceParams getIfaceParamsWithAcsAndInvalidChannelRange() { + IHostapd::IfaceParams iface_params_1_1 = + getIfaceParamsWithAcsAndChannelRange(); + iface_params_1_1.channelParams.acsChannelRanges[0].start = 222; + iface_params_1_1.channelParams.acsChannelRanges[0].end = 999; + return iface_params_1_1; + } + + IHostapd::IfaceParams getIfaceParamsWithoutAcs() { + ::android::hardware::wifi::hostapd::V1_0::IHostapd::IfaceParams + iface_params; + IHostapd::IfaceParams iface_params_1_1; + + iface_params.ifaceName = getPrimaryWlanIfaceName(); + iface_params.hwModeParams.enable80211N = true; + iface_params.hwModeParams.enable80211AC = false; + iface_params.channelParams.enableAcs = false; + iface_params.channelParams.acsShouldExcludeDfs = false; + iface_params.channelParams.channel = kIfaceChannel; + iface_params.channelParams.band = IHostapd::Band::BAND_2_4_GHZ; + iface_params_1_1.V1_0 = iface_params; + return iface_params_1_1; + } + + IHostapd::IfaceParams getIfaceParamsWithInvalidChannel() { + IHostapd::IfaceParams iface_params_1_1 = getIfaceParamsWithoutAcs(); + iface_params_1_1.V1_0.channelParams.channel = kIfaceInvalidChannel; + return iface_params_1_1; + } + + IHostapd::NetworkParams getPskNwParams() { + IHostapd::NetworkParams nw_params; + nw_params.ssid = + std::vector(kNwSsid, kNwSsid + sizeof(kNwSsid)); + nw_params.isHidden = false; + nw_params.encryptionType = IHostapd::EncryptionType::WPA2; + nw_params.pskPassphrase = kNwPassphrase; + return nw_params; + } + + IHostapd::NetworkParams getInvalidPskNwParams() { + IHostapd::NetworkParams nw_params; + nw_params.ssid = + std::vector(kNwSsid, kNwSsid + sizeof(kNwSsid)); + nw_params.isHidden = false; + nw_params.encryptionType = IHostapd::EncryptionType::WPA2; + return nw_params; + } + + IHostapd::NetworkParams getOpenNwParams() { + IHostapd::NetworkParams nw_params; + nw_params.ssid = + std::vector(kNwSsid, kNwSsid + sizeof(kNwSsid)); + nw_params.isHidden = false; + nw_params.encryptionType = IHostapd::EncryptionType::NONE; + return nw_params; + } + // IHostapd object used for all tests in this fixture. sp hostapd_; }; @@ -65,3 +166,113 @@ TEST_F(HostapdHidlTest, registerCallback) { EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); }); } + +/** + * Adds an access point with PSK network config & ACS enabled. + * Access point creation should pass. + */ +TEST_F(HostapdHidlTest, AddPskAccessPointWithAcs) { + auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_1, + getIfaceParamsWithAcs(), getPskNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with PSK network config, ACS enabled & channel Range. + * Access point creation should pass. + */ +TEST_F(HostapdHidlTest, AddPskAccessPointWithAcsAndChannelRange) { + auto status = + HIDL_INVOKE(hostapd_, addAccessPoint_1_1, + getIfaceParamsWithAcsAndChannelRange(), getPskNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with invalid channel range. + * Access point creation should fail. + */ +TEST_F(HostapdHidlTest, AddPskAccessPointWithAcsAndInvalidChannelRange) { + auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_1, + getIfaceParamsWithAcsAndInvalidChannelRange(), + getPskNwParams()); + EXPECT_NE(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with Open network config & ACS enabled. + * Access point creation should pass. + */ +TEST_F(HostapdHidlTest, AddOpenAccessPointWithAcs) { + auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_1, + getIfaceParamsWithAcs(), getOpenNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with PSK network config & ACS disabled. + * Access point creation should pass. + */ +TEST_F(HostapdHidlTest, AddPskAccessPointWithoutAcs) { + auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_1, + getIfaceParamsWithoutAcs(), getPskNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with Open network config & ACS disabled. + * Access point creation should pass. + */ +TEST_F(HostapdHidlTest, AddOpenAccessPointWithoutAcs) { + auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_1, + getIfaceParamsWithoutAcs(), getOpenNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds & then removes an access point with PSK network config & ACS enabled. + * Access point creation & removal should pass. + */ +TEST_F(HostapdHidlTest, RemoveAccessPointWithAcs) { + auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_1, + getIfaceParamsWithAcs(), getPskNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); + status = + HIDL_INVOKE(hostapd_, removeAccessPoint, getPrimaryWlanIfaceName()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds & then removes an access point with PSK network config & ACS disabled. + * Access point creation & removal should pass. + */ +TEST_F(HostapdHidlTest, RemoveAccessPointWithoutAcs) { + auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_1, + getIfaceParamsWithoutAcs(), getPskNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); + status = + HIDL_INVOKE(hostapd_, removeAccessPoint, getPrimaryWlanIfaceName()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with invalid channel. + * Access point creation should fail. + */ +TEST_F(HostapdHidlTest, AddPskAccessPointWithInvalidChannel) { + auto status = + HIDL_INVOKE(hostapd_, addAccessPoint_1_1, + getIfaceParamsWithInvalidChannel(), getPskNwParams()); + EXPECT_NE(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with invalid PSK network config. + * Access point creation should fail. + */ +TEST_F(HostapdHidlTest, AddInvalidPskAccessPointWithoutAcs) { + auto status = + HIDL_INVOKE(hostapd_, addAccessPoint_1_1, getIfaceParamsWithoutAcs(), + getInvalidPskNwParams()); + EXPECT_NE(HostapdStatusCode::SUCCESS, status.code); +} From 4aa0f074203c689830f3e6f1f675a8d05b5e3a12 Mon Sep 17 00:00:00 2001 From: Jasmine Cha Date: Fri, 25 Jan 2019 15:00:46 +0800 Subject: [PATCH 421/718] Effects: add new effect volume flag Add new effect flag to monitor requested volume from audio framework. Bug: 123251705 Test: on/off equalizer on spotify/google music switch songs with equalizer Change-Id: Id89f6921923e7d55fa06c52579357fcd2f1c1fd0 Signed-off-by: Jasmine Cha --- audio/effect/5.0/types.hal | 2 ++ 1 file changed, 2 insertions(+) diff --git a/audio/effect/5.0/types.hal b/audio/effect/5.0/types.hal index 84e11086b4..4b6c196b81 100644 --- a/audio/effect/5.0/types.hal +++ b/audio/effect/5.0/types.hal @@ -53,6 +53,7 @@ enum Result : int32_t { * | Volume | 6..8 | 0 none * | management | | 1 implements volume control * | | | 2 requires volume indication + * | | | 3 monitors requested volume * | | | 4 reserved * +----------------+--------+-------------------------------------------------- * | Device | 9..11 | 0 none @@ -136,6 +137,7 @@ enum EffectFlags : int32_t { VOLUME_MASK = ((1 << VOLUME_SIZE) -1) << VOLUME_SHIFT, VOLUME_CTRL = 1 << VOLUME_SHIFT, VOLUME_IND = 2 << VOLUME_SHIFT, + VOLUME_MONITOR = 3 << VOLUME_SHIFT, VOLUME_NONE = 0 << VOLUME_SHIFT, // Device indication From 3944daace2677fbeac84be54661c9ad3c570bb5a Mon Sep 17 00:00:00 2001 From: kumachang Date: Mon, 28 Jan 2019 17:28:28 +0800 Subject: [PATCH 422/718] vts(wifi): Separate SoftAP specific tests Separate out SoftAP specific tests in WIFI HAL VTS test suite. Use the |gEnv->isSoftApOn| flag to skip softAP tests if not support SoftAP. Bug: 73543546 Test: vts-tradefed run commandAndExit vts-hal --skip-all-system-status-check --primary-abi-only --skip-preconditions --module VtsHalWifiV1_0Host -l INFO Change-Id: I72217268783bb0bcff10b44114c03394ee1e1d88 --- wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp | 12 +++++++++++- wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp | 4 ++++ wifi/1.0/vts/functional/wifi_hidl_test_utils.h | 11 +++++++++-- 3 files changed, 24 insertions(+), 3 deletions(-) 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 c0af30bf5a..e5762f28f0 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 @@ -29,17 +29,23 @@ using ::android::hardware::wifi::V1_0::WifiBand; using ::android::hardware::wifi::V1_0::WifiStatusCode; using ::android::sp; +extern WifiHidlEnvironment* gEnv; + /** * Fixture to use for all AP Iface HIDL interface tests. */ class WifiApIfaceHidlTest : public ::testing::VtsHalHidlTargetTestBase { public: virtual void SetUp() override { + if (!gEnv->isSoftApOn) return; wifi_ap_iface_ = getWifiApIface(); ASSERT_NE(nullptr, wifi_ap_iface_.get()); } - virtual void TearDown() override { stopWifi(); } + virtual void TearDown() override { + if (!gEnv->isSoftApOn) return; + stopWifi(); + } protected: sp wifi_ap_iface_; @@ -51,6 +57,7 @@ class WifiApIfaceHidlTest : public ::testing::VtsHalHidlTargetTestBase { * successfully created. */ TEST(WifiApIfaceHidlTestNoFixture, Create) { + if (!gEnv->isSoftApOn) return; EXPECT_NE(nullptr, getWifiApIface().get()); stopWifi(); } @@ -60,6 +67,7 @@ TEST(WifiApIfaceHidlTestNoFixture, Create) { * Ensures that the correct interface type is returned for AP interface. */ TEST_F(WifiApIfaceHidlTest, GetType) { + if (!gEnv->isSoftApOn) return; const auto& status_and_type = HIDL_INVOKE(wifi_ap_iface_, getType); EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_type.first.code); EXPECT_EQ(IfaceType::AP, status_and_type.second); @@ -71,6 +79,7 @@ TEST_F(WifiApIfaceHidlTest, GetType) { * status code. */ TEST_F(WifiApIfaceHidlTest, SetCountryCode) { + if (!gEnv->isSoftApOn) return; const android::hardware::hidl_array kCountryCode{ std::array{{0x55, 0x53}}}; EXPECT_EQ(WifiStatusCode::SUCCESS, @@ -82,6 +91,7 @@ TEST_F(WifiApIfaceHidlTest, SetCountryCode) { * Ensures that we can retrieve valid frequencies for 2.4 GHz band. */ TEST_F(WifiApIfaceHidlTest, GetValidFrequenciesForBand) { + if (!gEnv->isSoftApOn) return; const auto& status_and_freqs = HIDL_INVOKE( wifi_ap_iface_, getValidFrequenciesForBand, WifiBand::BAND_24GHZ); EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_freqs.first.code); diff --git a/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp index 3555c2ed03..72cafd1e9f 100644 --- a/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp +++ b/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp @@ -365,6 +365,7 @@ TEST_F(WifiChipHidlTest, GetDebugHostWakeReasonStats) { * succeeds. The 2nd iface creation should be rejected. */ TEST_F(WifiChipHidlTest, CreateApIface) { + if (!gEnv->isSoftApOn) return; configureChipForIfaceType(IfaceType::AP, true); sp iface; @@ -381,6 +382,7 @@ TEST_F(WifiChipHidlTest, CreateApIface) { * iface name is returned via the list. */ TEST_F(WifiChipHidlTest, GetApIfaceNames) { + if (!gEnv->isSoftApOn) return; configureChipForIfaceType(IfaceType::AP, true); const auto& status_and_iface_names1 = @@ -413,6 +415,7 @@ TEST_F(WifiChipHidlTest, GetApIfaceNames) { * doesn't retrieve an iface object. */ TEST_F(WifiChipHidlTest, GetApIface) { + if (!gEnv->isSoftApOn) return; configureChipForIfaceType(IfaceType::AP, true); sp ap_iface; @@ -439,6 +442,7 @@ TEST_F(WifiChipHidlTest, GetApIface) { * doesn't remove the iface. */ TEST_F(WifiChipHidlTest, RemoveApIface) { + if (!gEnv->isSoftApOn) return; configureChipForIfaceType(IfaceType::AP, true); sp ap_iface; diff --git a/wifi/1.0/vts/functional/wifi_hidl_test_utils.h b/wifi/1.0/vts/functional/wifi_hidl_test_utils.h index 2b1c8ec82e..d430ce0bea 100644 --- a/wifi/1.0/vts/functional/wifi_hidl_test_utils.h +++ b/wifi/1.0/vts/functional/wifi_hidl_test_utils.h @@ -58,26 +58,33 @@ class WifiHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { public: // Whether NaN feature is supported on the device. bool isNanOn = false; + // Whether SoftAp feature is supported on the device. + bool isSoftApOn = false; void usage(char* me, char* arg) { fprintf(stderr, "unrecognized option: %s\n\n" "usage: %s \n\n" "test options are:\n\n" - "-N, --nan_on: Whether NAN feature is supported\n", + "-N, --nan_on: Whether NAN feature is supported\n" + "-S, --softap_on: Whether SOFTAP feature is supported\n", arg, me); } int initFromOptions(int argc, char** argv) { static struct option options[] = {{"nan_on", no_argument, 0, 'N'}, + {"softap_on", no_argument, 0, 'S'}, {0, 0, 0, 0}}; int c; - while ((c = getopt_long(argc, argv, "N", options, NULL)) >= 0) { + while ((c = getopt_long(argc, argv, "NS", options, NULL)) >= 0) { switch (c) { case 'N': isNanOn = true; break; + case 'S': + isSoftApOn = true; + break; default: usage(argv[0], argv[optind]); return 2; From 1ca066eb55f9dae3cb907c80e3e6aec43b9a05f3 Mon Sep 17 00:00:00 2001 From: Huihong Luo Date: Fri, 21 Sep 2018 15:19:07 -0700 Subject: [PATCH 423/718] Add interface tag so other components can start the hal interface when needed. Test: manual Change-Id: I61a4d396e86ec8dbda2cbabcc7afca7be7628f26 (cherry picked from commit c4f493977b6315d3dfe8e05f0c2516e2b00feca4) --- .../default/android.hardware.graphics.allocator@2.0-service.rc | 1 + 1 file changed, 1 insertion(+) diff --git a/graphics/allocator/2.0/default/android.hardware.graphics.allocator@2.0-service.rc b/graphics/allocator/2.0/default/android.hardware.graphics.allocator@2.0-service.rc index 6eee71f6e7..a2a881a8f4 100644 --- a/graphics/allocator/2.0/default/android.hardware.graphics.allocator@2.0-service.rc +++ b/graphics/allocator/2.0/default/android.hardware.graphics.allocator@2.0-service.rc @@ -1,5 +1,6 @@ service vendor.gralloc-2-0 /vendor/bin/hw/android.hardware.graphics.allocator@2.0-service class hal animation + interface android.hardware.graphics.allocator@2.0::IAllocator default user system group graphics drmrpc capabilities SYS_NICE From a2d16bbc44adca41e4db2047b77e11b3e619cc87 Mon Sep 17 00:00:00 2001 From: Brian Stack Date: Fri, 25 Jan 2019 11:22:04 -0800 Subject: [PATCH 424/718] Add missing sensors to Sensors 2.0 Bug: 123380869 Test: atest com.android.devicehealthchecks.SensorsBootCheck#checkSensors passes on Cuttlefish Change-Id: I08a8406b3932469878da981add61f60b7774a377 --- sensors/2.0/default/Sensor.cpp | 187 +++++++++++++++++++++++++++++++- sensors/2.0/default/Sensor.h | 56 +++++++++- sensors/2.0/default/Sensors.cpp | 13 ++- sensors/2.0/default/Sensors.h | 15 +++ 4 files changed, 262 insertions(+), 9 deletions(-) diff --git a/sensors/2.0/default/Sensor.cpp b/sensors/2.0/default/Sensor.cpp index 168b40219c..373ab1280d 100644 --- a/sensors/2.0/default/Sensor.cpp +++ b/sensors/2.0/default/Sensor.cpp @@ -131,9 +131,9 @@ std::vector Sensor::readEvents() { event.sensorHandle = mSensorInfo.sensorHandle; event.sensorType = mSensorInfo.type; event.timestamp = ::android::elapsedRealtimeNano(); - event.u.vec3.x = 1; - event.u.vec3.y = 2; - event.u.vec3.z = 3; + event.u.vec3.x = 0; + event.u.vec3.y = 0; + event.u.vec3.z = 0; event.u.vec3.status = SensorStatus::ACCURACY_HIGH; events.push_back(event); return events; @@ -166,6 +166,31 @@ Result Sensor::injectEvent(const Event& event) { return result; } +OnChangeSensor::OnChangeSensor(ISensorsEventCallback* callback) + : Sensor(callback), mPreviousEventSet(false) {} + +void OnChangeSensor::activate(bool enable) { + Sensor::activate(enable); + if (!enable) { + mPreviousEventSet = false; + } +} + +std::vector OnChangeSensor::readEvents() { + std::vector events = Sensor::readEvents(); + std::vector outputEvents; + + for (auto iter = events.begin(); iter != events.end(); ++iter) { + Event ev = *iter; + if (ev.u.vec3 != mPreviousEvent.u.vec3 || !mPreviousEventSet) { + outputEvents.push_back(ev); + mPreviousEvent = ev; + mPreviousEventSet = true; + } + } + return outputEvents; +} + AccelSensor::AccelSensor(int32_t sensorHandle, ISensorsEventCallback* callback) : Sensor(callback) { mSensorInfo.sensorHandle = sensorHandle; mSensorInfo.name = "Accel Sensor"; @@ -181,10 +206,162 @@ AccelSensor::AccelSensor(int32_t sensorHandle, ISensorsEventCallback* callback) mSensorInfo.fifoReservedEventCount = 0; mSensorInfo.fifoMaxEventCount = 0; mSensorInfo.requiredPermission = ""; - mSensorInfo.flags = - static_cast(SensorFlagBits::WAKE_UP | SensorFlagBits::DATA_INJECTION); + mSensorInfo.flags = static_cast(SensorFlagBits::DATA_INJECTION); }; +PressureSensor::PressureSensor(int32_t sensorHandle, ISensorsEventCallback* callback) + : Sensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Pressure Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::PRESSURE; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 1100.0f; // hPa + mSensorInfo.resolution = 1.0f; // hPa + mSensorInfo.power = 0.001f; // mA + mSensorInfo.minDelay = 28571.0f; // microseconds + mSensorInfo.maxDelay = 0.0f; // microseconds + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = 0; +}; + +MagnetometerSensor::MagnetometerSensor(int32_t sensorHandle, ISensorsEventCallback* callback) + : Sensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Magnetic Field Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::MAGNETIC_FIELD; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 4911.0f; + mSensorInfo.resolution = 1.00f; + mSensorInfo.power = 0.001f; // mA + mSensorInfo.minDelay = 14284.0f; // microseconds + mSensorInfo.maxDelay = 0.0f; // microseconds + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = 0; +}; + +LightSensor::LightSensor(int32_t sensorHandle, ISensorsEventCallback* callback) + : OnChangeSensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Light Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::LIGHT; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 10000.0f; + mSensorInfo.resolution = 10.0f; + mSensorInfo.power = 0.001f; // mA + mSensorInfo.minDelay = 20.0f * 1000; // microseconds + mSensorInfo.maxDelay = 0; // microseconds + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = static_cast(SensorFlagBits::ON_CHANGE_MODE); +}; + +ProximitySensor::ProximitySensor(int32_t sensorHandle, ISensorsEventCallback* callback) + : OnChangeSensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Proximity Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::PROXIMITY; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 5.0f; + mSensorInfo.resolution = 1.0f; + mSensorInfo.power = 0.012f; // mA + mSensorInfo.minDelay = 500; // microseconds + mSensorInfo.maxDelay = 2 * mSensorInfo.minDelay; + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = + static_cast(SensorFlagBits::ON_CHANGE_MODE | SensorFlagBits::WAKE_UP); +}; + +GyroSensor::GyroSensor(int32_t sensorHandle, ISensorsEventCallback* callback) : Sensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Gyro Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::GYROSCOPE; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 8.726639f; + mSensorInfo.resolution = 1.0f; + mSensorInfo.power = 0.001f; + mSensorInfo.minDelay = 4444; // microseonds + mSensorInfo.maxDelay = 0; // microseconds + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = 0; +}; + +AmbientTempSensor::AmbientTempSensor(int32_t sensorHandle, ISensorsEventCallback* callback) + : OnChangeSensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Ambient Temp Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::AMBIENT_TEMPERATURE; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 80.0f; + mSensorInfo.resolution = 1.0f; + mSensorInfo.power = 0.001f; + mSensorInfo.minDelay = 4444; // microseonds + mSensorInfo.maxDelay = 0; // microseconds + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = static_cast(SensorFlagBits::ON_CHANGE_MODE); +}; + +DeviceTempSensor::DeviceTempSensor(int32_t sensorHandle, ISensorsEventCallback* callback) + : OnChangeSensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Device Temp Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::TEMPERATURE; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 80.0f; + mSensorInfo.resolution = 1.0f; + mSensorInfo.power = 0.001f; + mSensorInfo.minDelay = 4444; // microseonds + mSensorInfo.maxDelay = 0; // microseconds + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = static_cast(SensorFlagBits::ON_CHANGE_MODE); +} + +RelativeHumiditySensor::RelativeHumiditySensor(int32_t sensorHandle, + ISensorsEventCallback* callback) + : OnChangeSensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Relative Humidity Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::RELATIVE_HUMIDITY; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 100.0f; + mSensorInfo.resolution = 1.0f; + mSensorInfo.power = 0.001f; + mSensorInfo.minDelay = 4444; // microseonds + mSensorInfo.maxDelay = 0; // microseconds + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = static_cast(SensorFlagBits::ON_CHANGE_MODE); +} + } // namespace implementation } // namespace V2_0 } // namespace sensors diff --git a/sensors/2.0/default/Sensor.h b/sensors/2.0/default/Sensor.h index 3ab2299a23..61900fa436 100644 --- a/sensors/2.0/default/Sensor.h +++ b/sensors/2.0/default/Sensor.h @@ -50,7 +50,7 @@ class Sensor { const SensorInfo& getSensorInfo() const; void batch(int32_t samplingPeriodNs); - void activate(bool enable); + virtual void activate(bool enable); Result flush(); void setOperationMode(OperationMode mode); @@ -79,11 +79,65 @@ class Sensor { OperationMode mMode; }; +class OnChangeSensor : public Sensor { + public: + OnChangeSensor(ISensorsEventCallback* callback); + + virtual void activate(bool enable) override; + + protected: + virtual std::vector readEvents() override; + + protected: + Event mPreviousEvent; + bool mPreviousEventSet; +}; + class AccelSensor : public Sensor { public: AccelSensor(int32_t sensorHandle, ISensorsEventCallback* callback); }; +class GyroSensor : public Sensor { + public: + GyroSensor(int32_t sensorHandle, ISensorsEventCallback* callback); +}; + +class AmbientTempSensor : public OnChangeSensor { + public: + AmbientTempSensor(int32_t sensorHandle, ISensorsEventCallback* callback); +}; + +class DeviceTempSensor : public OnChangeSensor { + public: + DeviceTempSensor(int32_t sensorHandle, ISensorsEventCallback* callback); +}; + +class PressureSensor : public Sensor { + public: + PressureSensor(int32_t sensorHandle, ISensorsEventCallback* callback); +}; + +class MagnetometerSensor : public Sensor { + public: + MagnetometerSensor(int32_t sensorHandle, ISensorsEventCallback* callback); +}; + +class LightSensor : public OnChangeSensor { + public: + LightSensor(int32_t sensorHandle, ISensorsEventCallback* callback); +}; + +class ProximitySensor : public OnChangeSensor { + public: + ProximitySensor(int32_t sensorHandle, ISensorsEventCallback* callback); +}; + +class RelativeHumiditySensor : public OnChangeSensor { + public: + RelativeHumiditySensor(int32_t sensorHandle, ISensorsEventCallback* callback); +}; + } // namespace implementation } // namespace V2_0 } // namespace sensors diff --git a/sensors/2.0/default/Sensors.cpp b/sensors/2.0/default/Sensors.cpp index 15fe86f788..23dd26bccb 100644 --- a/sensors/2.0/default/Sensors.cpp +++ b/sensors/2.0/default/Sensors.cpp @@ -37,13 +37,20 @@ constexpr const char* kWakeLockName = "SensorsHAL_WAKEUP"; Sensors::Sensors() : mEventQueueFlag(nullptr), + mNextHandle(1), mOutstandingWakeUpEvents(0), mReadWakeLockQueueRun(false), mAutoReleaseWakeLockTime(0), mHasWakeLock(false) { - std::shared_ptr accel = - std::make_shared(1 /* sensorHandle */, this /* callback */); - mSensors[accel->getSensorInfo().sensorHandle] = accel; + AddSensor(); + AddSensor(); + AddSensor(); + AddSensor(); + AddSensor(); + AddSensor(); + AddSensor(); + AddSensor(); + AddSensor(); } Sensors::~Sensors() { diff --git a/sensors/2.0/default/Sensors.h b/sensors/2.0/default/Sensors.h index eba3f97a08..d06dd78dad 100644 --- a/sensors/2.0/default/Sensors.h +++ b/sensors/2.0/default/Sensors.h @@ -86,6 +86,16 @@ struct Sensors : public ISensors, public ISensorsEventCallback { void postEvents(const std::vector& events, bool wakeup) override; private: + /** + * Add a new sensor + */ + template + void AddSensor() { + std::shared_ptr sensor = + std::make_shared(mNextHandle++ /* sensorHandle */, this /* callback */); + mSensors[sensor->getSensorInfo().sensorHandle] = sensor; + } + /** * Utility function to delete the Event Flag */ @@ -131,6 +141,11 @@ struct Sensors : public ISensors, public ISensorsEventCallback { */ std::map> mSensors; + /** + * The next available sensor handle + */ + int32_t mNextHandle; + /** * Lock to protect writes to the FMQs */ From c2d3d1ddb5c161dc1e1640d9c7c9e9bf0412ab84 Mon Sep 17 00:00:00 2001 From: Yin-Chia Yeh Date: Thu, 20 Sep 2018 15:06:13 -0700 Subject: [PATCH 425/718] Camera: support libhardware camera device 3.6 Add buffer management API support. Test: VTS to be written. Need Pixel device impl to verify. Bug: 120986771 Change-Id: Icdbc621f8cd17aa0868d3ac361867c44793a268c --- .../3.2/default/CameraDeviceSession.cpp | 86 +++-- .../device/3.2/default/CameraDeviceSession.h | 21 +- .../3.4/default/CameraDeviceSession.cpp | 23 +- .../device_v3_4_impl/CameraDeviceSession.h | 6 + .../3.5/default/CameraDeviceSession.cpp | 306 +++++++++++++++++- .../device_v3_5_impl/CameraDeviceSession.h | 102 +++++- .../provider/2.4/default/CameraProvider.cpp | 52 +-- camera/provider/2.4/default/CameraProvider.h | 1 - 8 files changed, 539 insertions(+), 58 deletions(-) diff --git a/camera/device/3.2/default/CameraDeviceSession.cpp b/camera/device/3.2/default/CameraDeviceSession.cpp index fd785df1a9..f2d7a47e83 100644 --- a/camera/device/3.2/default/CameraDeviceSession.cpp +++ b/camera/device/3.2/default/CameraDeviceSession.cpp @@ -44,13 +44,15 @@ static constexpr int METADATA_SHRINK_ABS_THRESHOLD = 4096; static constexpr int METADATA_SHRINK_REL_THRESHOLD = 2; HandleImporter CameraDeviceSession::sHandleImporter; +buffer_handle_t CameraDeviceSession::sEmptyBuffer = nullptr; + const int CameraDeviceSession::ResultBatcher::NOT_BATCHED; CameraDeviceSession::CameraDeviceSession( camera3_device_t* device, const camera_metadata_t* deviceInfo, const sp& callback) : - camera3_callback_ops({&sProcessCaptureResult, &sNotify}), + camera3_callback_ops({&sProcessCaptureResult, &sNotify, nullptr, nullptr}), mDevice(device), mDeviceVersion(device->common.version), mFreeBufEarly(shouldFreeBufEarly()), @@ -246,10 +248,50 @@ void CameraDeviceSession::overrideResultForPrecaptureCancelLocked( } } +Status CameraDeviceSession::importBuffer(int32_t streamId, + uint64_t bufId, buffer_handle_t buf, + /*out*/buffer_handle_t** outBufPtr, + bool allowEmptyBuf) { + + if (buf == nullptr && bufId == BUFFER_ID_NO_BUFFER) { + if (allowEmptyBuf) { + *outBufPtr = &sEmptyBuffer; + return Status::OK; + } else { + ALOGE("%s: bufferId %" PRIu64 " has null buffer handle!", __FUNCTION__, bufId); + return Status::ILLEGAL_ARGUMENT; + } + } + + Mutex::Autolock _l(mInflightLock); + CirculatingBuffers& cbs = mCirculatingBuffers[streamId]; + if (cbs.count(bufId) == 0) { + // Register a newly seen buffer + buffer_handle_t importedBuf = buf; + sHandleImporter.importBuffer(importedBuf); + if (importedBuf == nullptr) { + ALOGE("%s: output buffer for stream %d is invalid!", __FUNCTION__, streamId); + return Status::INTERNAL_ERROR; + } else { + cbs[bufId] = importedBuf; + } + } + *outBufPtr = &cbs[bufId]; + return Status::OK; +} + Status CameraDeviceSession::importRequest( const CaptureRequest& request, hidl_vec& allBufPtrs, hidl_vec& allFences) { + return importRequestImpl(request, allBufPtrs, allFences); +} + +Status CameraDeviceSession::importRequestImpl( + const CaptureRequest& request, + hidl_vec& allBufPtrs, + hidl_vec& allFences, + bool allowEmptyBuf) { bool hasInputBuf = (request.inputBuffer.streamId != -1 && request.inputBuffer.bufferId != 0); size_t numOutputBufs = request.outputBuffers.size(); @@ -277,25 +319,15 @@ Status CameraDeviceSession::importRequest( } for (size_t i = 0; i < numBufs; i++) { - buffer_handle_t buf = allBufs[i]; - uint64_t bufId = allBufIds[i]; - CirculatingBuffers& cbs = mCirculatingBuffers[streamIds[i]]; - if (cbs.count(bufId) == 0) { - if (buf == nullptr) { - ALOGE("%s: bufferId %" PRIu64 " has null buffer handle!", __FUNCTION__, bufId); - return Status::ILLEGAL_ARGUMENT; - } - // Register a newly seen buffer - buffer_handle_t importedBuf = buf; - sHandleImporter.importBuffer(importedBuf); - if (importedBuf == nullptr) { - ALOGE("%s: output buffer %zu is invalid!", __FUNCTION__, i); - return Status::INTERNAL_ERROR; - } else { - cbs[bufId] = importedBuf; - } + Status st = importBuffer( + streamIds[i], allBufIds[i], allBufs[i], &allBufPtrs[i], + // Disallow empty buf for input stream, otherwise follow + // the allowEmptyBuf argument. + (hasInputBuf && i == numOutputBufs) ? false : allowEmptyBuf); + if (st != Status::OK) { + // Detailed error logs printed in importBuffer + return st; } - allBufPtrs[i] = &cbs[bufId]; } // All buffers are imported. Now validate output buffer acquire fences @@ -1271,18 +1303,26 @@ Return CameraDeviceSession::close() { ATRACE_END(); // free all imported buffers + Mutex::Autolock _l(mInflightLock); for(auto& pair : mCirculatingBuffers) { CirculatingBuffers& buffers = pair.second; for (auto& p2 : buffers) { sHandleImporter.freeBuffer(p2.second); } + buffers.clear(); } + mCirculatingBuffers.clear(); mClosed = true; } return Void(); } +uint64_t CameraDeviceSession::getCapResultBufferId(const buffer_handle_t&, int) { + // No need to fill in bufferId by default + return BUFFER_ID_NO_BUFFER; +} + status_t CameraDeviceSession::constructCaptureResult(CaptureResult& result, const camera3_capture_result *hal_result) { uint32_t frameNumber = hal_result->frame_number; @@ -1396,6 +1436,14 @@ status_t CameraDeviceSession::constructCaptureResult(CaptureResult& result, result.outputBuffers[i].streamId = static_cast(hal_result->output_buffers[i].stream)->mId; result.outputBuffers[i].buffer = nullptr; + if (hal_result->output_buffers[i].buffer != nullptr) { + result.outputBuffers[i].bufferId = getCapResultBufferId( + *(hal_result->output_buffers[i].buffer), + result.outputBuffers[i].streamId); + } else { + result.outputBuffers[i].bufferId = 0; + } + result.outputBuffers[i].status = (BufferStatus) hal_result->output_buffers[i].status; // skip acquire fence since it's of no use to camera service if (hal_result->output_buffers[i].release_fence != -1) { diff --git a/camera/device/3.2/default/CameraDeviceSession.h b/camera/device/3.2/default/CameraDeviceSession.h index bcee259fbd..a96c245067 100644 --- a/camera/device/3.2/default/CameraDeviceSession.h +++ b/camera/device/3.2/default/CameraDeviceSession.h @@ -161,6 +161,7 @@ protected: std::map mInflightRawBoostPresent; ::android::hardware::camera::common::V1_0::helper::CameraMetadata mOverridenRequest; + static const uint64_t BUFFER_ID_NO_BUFFER = 0; // buffers currently ciculating between HAL and camera service // key: bufferId sent via HIDL interface // value: imported buffer_handle_t @@ -171,6 +172,7 @@ protected: std::map mCirculatingBuffers; static HandleImporter sHandleImporter; + static buffer_handle_t sEmptyBuffer; bool mInitFail; bool mFirstRequest = false; @@ -301,11 +303,23 @@ protected: Status initStatus() const; // Validate and import request's input buffer and acquire fence - Status importRequest( + virtual Status importRequest( const CaptureRequest& request, hidl_vec& allBufPtrs, hidl_vec& allFences); + Status importRequestImpl( + const CaptureRequest& request, + hidl_vec& allBufPtrs, + hidl_vec& allFences, + // Optional argument for ICameraDeviceSession@3.5 impl + bool allowEmptyBuf = false); + + Status importBuffer(int32_t streamId, + uint64_t bufId, buffer_handle_t buf, + /*out*/buffer_handle_t** outBufPtr, + bool allowEmptyBuf); + static void cleanupInflightFences( hidl_vec& allFences, size_t numFences); @@ -332,6 +346,11 @@ protected: static callbacks_process_capture_result_t sProcessCaptureResult; static callbacks_notify_t sNotify; + // By default camera service uses frameNumber/streamId pair to retrieve the buffer that + // was sent to HAL. Override this implementation if HAL is using buffers from buffer management + // APIs to send output buffer. + virtual uint64_t getCapResultBufferId(const buffer_handle_t& buf, int streamId); + status_t constructCaptureResult(CaptureResult& result, const camera3_capture_result *hal_result); diff --git a/camera/device/3.4/default/CameraDeviceSession.cpp b/camera/device/3.4/default/CameraDeviceSession.cpp index f2e031c674..e52577cfb9 100644 --- a/camera/device/3.4/default/CameraDeviceSession.cpp +++ b/camera/device/3.4/default/CameraDeviceSession.cpp @@ -87,6 +87,14 @@ CameraDeviceSession::~CameraDeviceSession() { Return CameraDeviceSession::configureStreams_3_4( const StreamConfiguration& requestedConfiguration, ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb) { + configureStreams_3_4_Impl(requestedConfiguration, _hidl_cb); + return Void(); +} + +void CameraDeviceSession::configureStreams_3_4_Impl( + const StreamConfiguration& requestedConfiguration, + ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb, + uint32_t streamConfigCounter) { Status status = initStatus(); HalStreamConfiguration outStreams; @@ -97,7 +105,7 @@ Return CameraDeviceSession::configureStreams_3_4( ALOGE("%s: trying to configureStreams with physical camera id with V3.2 callback", __FUNCTION__); _hidl_cb(Status::INTERNAL_ERROR, outStreams); - return Void(); + return; } } } @@ -109,7 +117,7 @@ Return CameraDeviceSession::configureStreams_3_4( ALOGE("%s: trying to configureStreams while there are still %zu inflight buffers!", __FUNCTION__, mInflightBuffers.size()); _hidl_cb(Status::INTERNAL_ERROR, outStreams); - return Void(); + return; } if (!mInflightAETriggerOverrides.empty()) { @@ -117,7 +125,7 @@ Return CameraDeviceSession::configureStreams_3_4( " trigger overrides!", __FUNCTION__, mInflightAETriggerOverrides.size()); _hidl_cb(Status::INTERNAL_ERROR, outStreams); - return Void(); + return; } if (!mInflightRawBoostPresent.empty()) { @@ -125,12 +133,12 @@ Return CameraDeviceSession::configureStreams_3_4( " boost overrides!", __FUNCTION__, mInflightRawBoostPresent.size()); _hidl_cb(Status::INTERNAL_ERROR, outStreams); - return Void(); + return; } if (status != Status::OK) { _hidl_cb(status, outStreams); - return Void(); + return; } const camera_metadata_t *paramBuffer = nullptr; @@ -139,11 +147,12 @@ Return CameraDeviceSession::configureStreams_3_4( } camera3_stream_configuration_t stream_list{}; + stream_list.stream_configuration_counter = streamConfigCounter; hidl_vec streams; stream_list.session_parameters = paramBuffer; if (!preProcessConfigurationLocked_3_4(requestedConfiguration, &stream_list, &streams)) { _hidl_cb(Status::INTERNAL_ERROR, outStreams); - return Void(); + return; } ATRACE_BEGIN("camera3->configure_streams"); @@ -168,7 +177,7 @@ Return CameraDeviceSession::configureStreams_3_4( } _hidl_cb(status, outStreams); - return Void(); + return; } bool CameraDeviceSession::preProcessConfigurationLocked_3_4( diff --git a/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h b/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h index fdc8a5afd2..00500b15f8 100644 --- a/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h +++ b/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h @@ -87,6 +87,12 @@ protected: void postProcessConfigurationFailureLocked_3_4( const StreamConfiguration& requestedConfiguration); + void configureStreams_3_4_Impl( + const StreamConfiguration& requestedConfiguration, + ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb, + // Optional argument for ICameraDeviceSession@3.5 impl + uint32_t streamConfigCounter = 0); + Return processCaptureRequest_3_4( const hidl_vec& requests, const hidl_vec& cachesToRemove, diff --git a/camera/device/3.5/default/CameraDeviceSession.cpp b/camera/device/3.5/default/CameraDeviceSession.cpp index 963893afbd..0770f0418c 100644 --- a/camera/device/3.5/default/CameraDeviceSession.cpp +++ b/camera/device/3.5/default/CameraDeviceSession.cpp @@ -15,8 +15,10 @@ */ #define LOG_TAG "CamDevSession@3.5-impl" +#define ATRACE_TAG ATRACE_TAG_CAMERA #include +#include #include #include "CameraDeviceSession.h" @@ -33,13 +35,26 @@ CameraDeviceSession::CameraDeviceSession( const sp& callback) : V3_4::implementation::CameraDeviceSession(device, deviceInfo, callback) { - mHasCallback_3_5 = false; + mCallback_3_5 = nullptr; auto castResult = ICameraDeviceCallback::castFrom(callback); if (castResult.isOk()) { sp callback3_5 = castResult; if (callback3_5 != nullptr) { - mHasCallback_3_5 = true; + mCallback_3_5 = callback3_5; + } + } + + if (mCallback_3_5 != nullptr) { + camera_metadata_entry bufMgrVersion = mDeviceInfo.find( + ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION); + if (bufMgrVersion.count > 0) { + mSupportBufMgr = (bufMgrVersion.data.u8[0] == + ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5); + if (mSupportBufMgr) { + request_stream_buffers = sRequestStreamBuffers; + return_stream_buffers = sReturnStreamBuffers; + } } } } @@ -50,14 +65,297 @@ CameraDeviceSession::~CameraDeviceSession() { Return CameraDeviceSession::configureStreams_3_5( const StreamConfiguration& requestedConfiguration, ICameraDeviceSession::configureStreams_3_5_cb _hidl_cb) { - return configureStreams_3_4(requestedConfiguration.v3_4, _hidl_cb); + configureStreams_3_4_Impl(requestedConfiguration.v3_4, _hidl_cb, + requestedConfiguration.streamConfigCounter); + return Void(); } Return CameraDeviceSession::signalStreamFlush( - const hidl_vec& /*requests*/, uint32_t /*streamConfigCounter*/) { + const hidl_vec& streamIds, uint32_t streamConfigCounter) { + std::vector streams(streamIds.size()); + { + Mutex::Autolock _l(mInflightLock); + for (size_t i = 0; i < streamIds.size(); i++) { + int32_t id = streamIds[i]; + if (mStreamMap.count(id) == 0) { + ALOGE("%s: unknown streamId %d", __FUNCTION__, id); + return Void(); + } + streams[i] = &mStreamMap[id]; + } + } + if (mDevice->ops->signal_stream_flush != nullptr) { + mDevice->ops->signal_stream_flush(mDevice, + streamConfigCounter, streams.size(), streams.data()); + } return Void(); } +Status CameraDeviceSession::importRequest( + const CaptureRequest& request, + hidl_vec& allBufPtrs, + hidl_vec& allFences) { + if (mSupportBufMgr) { + return importRequestImpl(request, allBufPtrs, allFences, /*allowEmptyBuf*/ true); + } + return importRequestImpl(request, allBufPtrs, allFences, /*allowEmptyBuf*/ false); +} + +void CameraDeviceSession::pushBufferId( + const buffer_handle_t& buf, uint64_t bufferId, int streamId) { + std::lock_guard lock(mBufferIdMapLock); + + // emplace will return existing entry if there is one. + auto pair = mBufferIdMaps.emplace(streamId, BufferIdMap{}); + BufferIdMap& bIdMap = pair.first->second; + bIdMap[buf] = bufferId; +} + +uint64_t CameraDeviceSession::popBufferId( + const buffer_handle_t& buf, int streamId) { + std::lock_guard lock(mBufferIdMapLock); + + auto streamIt = mBufferIdMaps.find(streamId); + if (streamIt == mBufferIdMaps.end()) { + return BUFFER_ID_NO_BUFFER; + } + BufferIdMap& bIdMap = streamIt->second; + auto it = bIdMap.find(buf); + if (it == bIdMap.end()) { + return BUFFER_ID_NO_BUFFER; + } + uint64_t bufId = it->second; + bIdMap.erase(it); + if (bIdMap.empty()) { + mBufferIdMaps.erase(streamIt); + } + return bufId; +} + +uint64_t CameraDeviceSession::getCapResultBufferId(const buffer_handle_t& buf, int streamId) { + if (mSupportBufMgr) { + return popBufferId(buf, streamId); + } + return BUFFER_ID_NO_BUFFER; +} + +Camera3Stream* CameraDeviceSession::getStreamPointer(int32_t streamId) { + Mutex::Autolock _l(mInflightLock); + if (mStreamMap.count(streamId) == 0) { + ALOGE("%s: unknown streamId %d", __FUNCTION__, streamId); + return nullptr; + } + return &mStreamMap[streamId]; +} + +void CameraDeviceSession::cleanupInflightBufferFences( + std::vector& fences, std::vector>& bufs) { + hidl_vec hFences = fences; + cleanupInflightFences(hFences, fences.size()); + for (auto& p : bufs) { + popBufferId(p.first, p.second); + } +} + +camera3_buffer_request_status_t CameraDeviceSession::requestStreamBuffers( + uint32_t num_buffer_reqs, + const camera3_buffer_request_t *buffer_reqs, + /*out*/uint32_t *num_returned_buf_reqs, + /*out*/camera3_stream_buffer_ret_t *returned_buf_reqs) { + ATRACE_CALL(); + *num_returned_buf_reqs = 0; + hidl_vec hBufReqs(num_buffer_reqs); + for (size_t i = 0; i < num_buffer_reqs; i++) { + hBufReqs[i].streamId = + static_cast(buffer_reqs[i].stream)->mId; + hBufReqs[i].numBuffersRequested = buffer_reqs[i].num_buffers_requested; + } + + ATRACE_BEGIN("HIDL requestStreamBuffers"); + BufferRequestStatus status; + hidl_vec bufRets; + auto err = mCallback_3_5->requestStreamBuffers(hBufReqs, + [&status, &bufRets] + (BufferRequestStatus s, const hidl_vec& rets) { + status = s; + bufRets = std::move(rets); + }); + if (!err.isOk()) { + ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str()); + return CAMERA3_BUF_REQ_FAILED_UNKNOWN; + } + ATRACE_END(); + + if (status == BufferRequestStatus::OK || status == BufferRequestStatus::FAILED_PARTIAL) { + if (bufRets.size() != num_buffer_reqs) { + ALOGE("%s: expect %d buffer requests returned, only got %zu", + __FUNCTION__, num_buffer_reqs, bufRets.size()); + return CAMERA3_BUF_REQ_FAILED_UNKNOWN; + } + + for (size_t i = 0; i < num_buffer_reqs; i++) { + // maybe we can query all streams in one call to avoid frequent locking device here? + Camera3Stream* stream = getStreamPointer(bufRets[i].streamId); + if (stream == nullptr) { + ALOGE("%s: unknown streamId %d", __FUNCTION__, bufRets[i].streamId); + return CAMERA3_BUF_REQ_FAILED_UNKNOWN; + } + returned_buf_reqs[i].stream = stream; + } + + std::vector importedFences; + std::vector> importedBuffers; + for (size_t i = 0; i < num_buffer_reqs; i++) { + int streamId = bufRets[i].streamId; + switch (bufRets[i].val.getDiscriminator()) { + case StreamBuffersVal::hidl_discriminator::error: + returned_buf_reqs[i].num_output_buffers = 0; + switch (bufRets[i].val.error()) { + case StreamBufferRequestError::NO_BUFFER_AVAILABLE: + returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_NO_BUFFER_AVAILABLE; + break; + case StreamBufferRequestError::MAX_BUFFER_EXCEEDED: + returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_MAX_BUFFER_EXCEEDED; + break; + case StreamBufferRequestError::STREAM_DISCONNECTED: + returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_STREAM_DISCONNECTED; + break; + case StreamBufferRequestError::UNKNOWN_ERROR: + returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_UNKNOWN_ERROR; + break; + default: + ALOGE("%s: Unknown StreamBufferRequestError %d", + __FUNCTION__, bufRets[i].val.error()); + cleanupInflightBufferFences(importedFences, importedBuffers); + return CAMERA3_BUF_REQ_FAILED_UNKNOWN; + } + break; + case StreamBuffersVal::hidl_discriminator::buffers: { + const hidl_vec& hBufs = bufRets[i].val.buffers(); + camera3_stream_buffer_t* outBufs = returned_buf_reqs[i].output_buffers; + for (size_t b = 0; b < hBufs.size(); b++) { + const StreamBuffer& hBuf = hBufs[b]; + camera3_stream_buffer_t& outBuf = outBufs[b]; + // maybe add importBuffers API to avoid frequent locking device? + Status s = importBuffer(streamId, + hBuf.bufferId, hBuf.buffer.getNativeHandle(), + /*out*/&(outBuf.buffer), + /*allowEmptyBuf*/false); + if (s != Status::OK) { + ALOGE("%s: import stream %d bufferId %" PRIu64 " failed!", + __FUNCTION__, streamId, hBuf.bufferId); + cleanupInflightBufferFences(importedFences, importedBuffers); + // Buffer import should never fail - restart HAL since something is very + // wrong. + assert(false); + return CAMERA3_BUF_REQ_FAILED_UNKNOWN; + } + + pushBufferId(*(outBuf.buffer), hBuf.bufferId, streamId); + importedBuffers.push_back(std::make_pair(*(outBuf.buffer), streamId)); + + if (!sHandleImporter.importFence( + hBuf.acquireFence, + outBuf.acquire_fence)) { + ALOGE("%s: stream %d bufferId %" PRIu64 "acquire fence is invalid", + __FUNCTION__, streamId, hBuf.bufferId); + cleanupInflightBufferFences(importedFences, importedBuffers); + return CAMERA3_BUF_REQ_FAILED_UNKNOWN; + } + importedFences.push_back(outBuf.acquire_fence); + outBuf.stream = returned_buf_reqs[i].stream; + outBuf.status = CAMERA3_BUFFER_STATUS_OK; + outBuf.release_fence = -1; + } + returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_OK; + } break; + default: + ALOGE("%s: unknown StreamBuffersVal discrimator!", __FUNCTION__); + cleanupInflightBufferFences(importedFences, importedBuffers); + return CAMERA3_BUF_REQ_FAILED_UNKNOWN; + } + } + + *num_returned_buf_reqs = num_buffer_reqs; + + return (status == BufferRequestStatus::OK) ? + CAMERA3_BUF_REQ_OK : CAMERA3_BUF_REQ_FAILED_PARTIAL; + } + + switch (status) { + case BufferRequestStatus::FAILED_CONFIGURING: + return CAMERA3_BUF_REQ_FAILED_CONFIGURING; + case BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS: + return CAMERA3_BUF_REQ_FAILED_ILLEGAL_ARGUMENTS; + case BufferRequestStatus::FAILED_UNKNOWN: + default: + return CAMERA3_BUF_REQ_FAILED_UNKNOWN; + } +} + +void CameraDeviceSession::returnStreamBuffers( + uint32_t num_buffers, + const camera3_stream_buffer_t* const* buffers) { + ATRACE_CALL(); + hidl_vec hBufs(num_buffers); + + for (size_t i = 0; i < num_buffers; i++) { + hBufs[i].streamId = + static_cast(buffers[i]->stream)->mId; + hBufs[i].buffer = nullptr; // use bufferId + hBufs[i].bufferId = popBufferId(*(buffers[i]->buffer), hBufs[i].streamId); + if (hBufs[i].bufferId == BUFFER_ID_NO_BUFFER) { + ALOGE("%s: unknown buffer is returned to stream %d", + __FUNCTION__, hBufs[i].streamId); + } + // ERROR since the buffer is not for application to consume + hBufs[i].status = BufferStatus::ERROR; + // skip acquire fence since it's of no use to camera service + if (buffers[i]->release_fence != -1) { + native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0); + handle->data[0] = buffers[i]->release_fence; + hBufs[i].releaseFence.setTo(handle, /*shouldOwn*/true); + } + } + + mCallback_3_5->returnStreamBuffers(hBufs); + return; +} + +/** + * Static callback forwarding methods from HAL to instance + */ +camera3_buffer_request_status_t CameraDeviceSession::sRequestStreamBuffers( + const struct camera3_callback_ops *cb, + uint32_t num_buffer_reqs, + const camera3_buffer_request_t *buffer_reqs, + /*out*/uint32_t *num_returned_buf_reqs, + /*out*/camera3_stream_buffer_ret_t *returned_buf_reqs) { + CameraDeviceSession *d = + const_cast(static_cast(cb)); + + if (num_buffer_reqs == 0 || buffer_reqs == nullptr || num_returned_buf_reqs == nullptr || + returned_buf_reqs == nullptr) { + ALOGE("%s: bad argument: numBufReq %d, bufReqs %p, numRetBufReq %p, retBufReqs %p", + __FUNCTION__, num_buffer_reqs, buffer_reqs, + num_returned_buf_reqs, returned_buf_reqs); + return CAMERA3_BUF_REQ_FAILED_ILLEGAL_ARGUMENTS; + } + + return d->requestStreamBuffers(num_buffer_reqs, buffer_reqs, + num_returned_buf_reqs, returned_buf_reqs); +} + +void CameraDeviceSession::sReturnStreamBuffers( + const struct camera3_callback_ops *cb, + uint32_t num_buffers, + const camera3_stream_buffer_t* const* buffers) { + CameraDeviceSession *d = + const_cast(static_cast(cb)); + + d->returnStreamBuffers(num_buffers, buffers); +} + } // namespace implementation } // namespace V3_5 } // namespace device diff --git a/camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h b/camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h index ec34769973..4f7284c5fe 100644 --- a/camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h +++ b/camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h @@ -21,6 +21,7 @@ #include #include #include <../../3.4/default/include/device_v3_4_impl/CameraDeviceSession.h> +#include namespace android { namespace hardware { @@ -30,11 +31,14 @@ namespace V3_5 { namespace implementation { using namespace ::android::hardware::camera::device; +using ::android::hardware::camera::device::V3_2::BufferStatus; using ::android::hardware::camera::device::V3_2::CaptureRequest; +using ::android::hardware::camera::device::V3_2::StreamBuffer; using ::android::hardware::camera::device::V3_5::StreamConfiguration; using ::android::hardware::camera::device::V3_4::HalStreamConfiguration; using ::android::hardware::camera::device::V3_5::ICameraDeviceSession; using ::android::hardware::camera::device::V3_5::ICameraDeviceCallback; +using ::android::hardware::camera::device::V3_2::implementation::Camera3Stream; using ::android::hardware::camera::common::V1_0::Status; using ::android::hardware::camera::common::V1_0::helper::HandleImporter; using ::android::hardware::Return; @@ -44,6 +48,25 @@ using ::android::hardware::hidl_string; using ::android::sp; using ::android::Mutex; + +/** + * Function pointer types with C calling convention to + * use for HAL callback functions. + */ +extern "C" { + typedef camera3_buffer_request_status_t (callbacks_request_stream_buffer_t)( + const struct camera3_callback_ops *, + uint32_t num_buffer_reqs, + const camera3_buffer_request_t *buffer_reqs, + /*out*/uint32_t *num_returned_buf_reqs, + /*out*/camera3_stream_buffer_ret_t *returned_buf_reqs); + + typedef void (callbacks_return_stream_buffer_t)( + const struct camera3_callback_ops *, + uint32_t num_buffers, + const camera3_stream_buffer_t* const* buffers); +} + struct CameraDeviceSession : public V3_4::implementation::CameraDeviceSession { CameraDeviceSession(camera3_device_t*, @@ -62,12 +85,85 @@ protected: ICameraDeviceSession::configureStreams_3_5_cb _hidl_cb); Return signalStreamFlush( - const hidl_vec& requests, + const hidl_vec& streamIds, uint32_t streamConfigCounter); + virtual Status importRequest( + const CaptureRequest& request, + hidl_vec& allBufPtrs, + hidl_vec& allFences) override; - // Whether this camera device session is created with version 3.5 callback. - bool mHasCallback_3_5; + /** + * Static callback forwarding methods from HAL to instance + */ + static callbacks_request_stream_buffer_t sRequestStreamBuffers; + static callbacks_return_stream_buffer_t sReturnStreamBuffers; + + camera3_buffer_request_status_t requestStreamBuffers( + uint32_t num_buffer_reqs, + const camera3_buffer_request_t *buffer_reqs, + /*out*/uint32_t *num_returned_buf_reqs, + /*out*/camera3_stream_buffer_ret_t *returned_buf_reqs); + + void returnStreamBuffers( + uint32_t num_buffers, + const camera3_stream_buffer_t* const* buffers); + + struct BufferHasher { + size_t operator()(const buffer_handle_t& buf) const { + if (buf == nullptr) + return 0; + + size_t result = 1; + result = 31 * result + buf->numFds; + for (int i = 0; i < buf->numFds; i++) { + result = 31 * result + buf->data[i]; + } + return result; + } + }; + + struct BufferComparator { + bool operator()(const buffer_handle_t& buf1, const buffer_handle_t& buf2) const { + if (buf1->numFds == buf2->numFds) { + for (int i = 0; i < buf1->numFds; i++) { + if (buf1->data[i] != buf2->data[i]) { + return false; + } + } + return true; + } + return false; + } + }; + + Camera3Stream* getStreamPointer(int32_t streamId); + + // Register buffer to mBufferIdMaps so we can find corresponding bufferId + // when the buffer is returned to camera service + void pushBufferId(const buffer_handle_t& buf, uint64_t bufferId, int streamId); + + // Method to pop buffer's bufferId from mBufferIdMaps + // BUFFER_ID_NO_BUFFER is returned if no matching buffer is found + uint64_t popBufferId(const buffer_handle_t& buf, int streamId); + + // Method to cleanup imported buffer/fences if requestStreamBuffers fails half way + void cleanupInflightBufferFences( + std::vector& fences, std::vector>& bufs); + + // Overrides the default constructCaptureResult behavior for buffer management APIs + virtual uint64_t getCapResultBufferId(const buffer_handle_t& buf, int streamId) override; + + std::mutex mBufferIdMapLock; // protecting mBufferIdMaps and mNextBufferId + typedef std::unordered_map BufferIdMap; + // stream ID -> per stream buffer ID map for buffers coming from requestStreamBuffers API + // Entries are created during requestStreamBuffers when a stream first request a buffer, and + // deleted in returnStreamBuffers/processCaptureResult* when all buffers are returned + std::unordered_map mBufferIdMaps; + + sp mCallback_3_5; + bool mSupportBufMgr; private: diff --git a/camera/provider/2.4/default/CameraProvider.cpp b/camera/provider/2.4/default/CameraProvider.cpp index 488b9afe58..30f2bfbc15 100644 --- a/camera/provider/2.4/default/CameraProvider.cpp +++ b/camera/provider/2.4/default/CameraProvider.cpp @@ -41,11 +41,8 @@ const char *kLegacyProviderName = "legacy/0"; const char *kExternalProviderName = "external/0"; // "device@/legacy/" const std::regex kDeviceNameRE("device@([0-9]+\\.[0-9]+)/legacy/(.+)"); -const char *kHAL3_2 = "3.2"; -const char *kHAL3_3 = "3.3"; const char *kHAL3_4 = "3.4"; const char *kHAL3_5 = "3.5"; -const char *kHAL1_0 = "1.0"; const int kMaxCameraDeviceNameLen = 128; const int kMaxCameraIdLen = 16; @@ -222,22 +219,6 @@ std::string CameraProvider::getLegacyCameraId(const hidl_string& deviceName) { return cameraId; } -int CameraProvider::getCameraDeviceVersion(const hidl_string& deviceName) { - std::string deviceVersion; - bool match = matchDeviceName(deviceName, &deviceVersion, nullptr); - if (!match) { - return -1; - } - if (deviceVersion == kHAL3_3) { - return CAMERA_DEVICE_API_VERSION_3_3; - } else if (deviceVersion == kHAL3_2) { - return CAMERA_DEVICE_API_VERSION_3_2; - } else if (deviceVersion == kHAL1_0) { - return CAMERA_DEVICE_API_VERSION_1_0; - } - return 0; -} - std::string CameraProvider::getHidlDeviceName( std::string cameraId, int deviceVersion) { // Maybe consider create a version check method and SortedVec to speed up? @@ -245,9 +226,16 @@ std::string CameraProvider::getHidlDeviceName( deviceVersion != CAMERA_DEVICE_API_VERSION_3_2 && deviceVersion != CAMERA_DEVICE_API_VERSION_3_3 && deviceVersion != CAMERA_DEVICE_API_VERSION_3_4 && - deviceVersion != CAMERA_DEVICE_API_VERSION_3_5) { + deviceVersion != CAMERA_DEVICE_API_VERSION_3_5 && + deviceVersion != CAMERA_DEVICE_API_VERSION_3_6) { return hidl_string(""); } + + // Supported combinations: + // CAMERA_DEVICE_API_VERSION_1_0 -> ICameraDevice@1.0 + // CAMERA_DEVICE_API_VERSION_3_[2-4] -> ICameraDevice@[3.2|3.3] + // CAMERA_DEVICE_API_VERSION_3_5 + CAMERA_MODULE_API_VERSION_2_4 -> ICameraDevice@3.4 + // CAMERA_DEVICE_API_VERSION_3_[5-6] + CAMERA_MODULE_API_VERSION_2_5 -> ICameraDevice@3.5 bool isV1 = deviceVersion == CAMERA_DEVICE_API_VERSION_1_0; int versionMajor = isV1 ? 1 : 3; int versionMinor = isV1 ? 0 : mPreferredHal3MinorVersion; @@ -257,6 +245,8 @@ std::string CameraProvider::getHidlDeviceName( } else { versionMinor = 4; } + } else if (deviceVersion == CAMERA_DEVICE_API_VERSION_3_6) { + versionMinor = 5; } char deviceName[kMaxCameraDeviceNameLen]; snprintf(deviceName, sizeof(deviceName), "device@%d.%d/legacy/%s", @@ -356,7 +346,8 @@ int CameraProvider::checkCameraVersion(int id, camera_info info) { // device_version undefined in CAMERA_MODULE_API_VERSION_1_0, // All CAMERA_MODULE_API_VERSION_1_0 devices are backward-compatible - if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_0) { + uint16_t moduleVersion = mModule->getModuleApiVersion(); + if (moduleVersion >= CAMERA_MODULE_API_VERSION_2_0) { // Verify the device version is in the supported range switch (info.device_version) { case CAMERA_DEVICE_API_VERSION_1_0: @@ -366,6 +357,20 @@ int CameraProvider::checkCameraVersion(int id, camera_info info) { case CAMERA_DEVICE_API_VERSION_3_5: // in support break; + case CAMERA_DEVICE_API_VERSION_3_6: + /** + * ICameraDevice@3.5 contains APIs from both + * CAMERA_DEVICE_API_VERSION_3_6 and CAMERA_MODULE_API_VERSION_2_5 + * so we require HALs to uprev both for simplified supported combinations. + * HAL can still opt in individual new APIs indepedently. + */ + if (moduleVersion < CAMERA_MODULE_API_VERSION_2_5) { + ALOGE("%s: Device %d has unsupported version combination:" + "HAL version %x and module version %x", + __FUNCTION__, id, info.device_version, moduleVersion); + return NO_INIT; + } + break; case CAMERA_DEVICE_API_VERSION_2_0: case CAMERA_DEVICE_API_VERSION_2_1: case CAMERA_DEVICE_API_VERSION_3_0: @@ -552,10 +557,11 @@ Return CameraProvider::getCameraDeviceInterface_V3_x( return Void(); } - // ICameraDevice 3.4 or upper sp deviceImpl; + + // ICameraDevice 3.4 or upper if (deviceVersion >= kHAL3_4) { - ALOGV("Constructing v3.4 camera device"); + ALOGV("Constructing v3.4+ camera device"); if (deviceVersion == kHAL3_4) { deviceImpl = new android::hardware::camera::device::V3_4::implementation::CameraDevice( mModule, cameraId, mCameraDeviceNames); diff --git a/camera/provider/2.4/default/CameraProvider.h b/camera/provider/2.4/default/CameraProvider.h index 0f0959f1f0..10e9b0d276 100644 --- a/camera/provider/2.4/default/CameraProvider.h +++ b/camera/provider/2.4/default/CameraProvider.h @@ -98,7 +98,6 @@ private: // extract legacy camera ID/device version from a HIDL device name static std::string getLegacyCameraId(const hidl_string& deviceName); - static int getCameraDeviceVersion(const hidl_string& deviceName); // convert conventional HAL status to HIDL Status static Status getHidlStatus(int); From 929fd21e064721f2e630d7bad38275ed93972baa Mon Sep 17 00:00:00 2001 From: Xusong Wang Date: Sun, 27 Jan 2019 23:08:12 -0800 Subject: [PATCH 426/718] Add VTS test for dynamic output shape. Test dynamic output shape with generated models when - Dimensions of output operands are fully specified - Dimensions of output operands are unspecified with sufficient buffer - Dimensions of output operands are unspecified with insufficient buffer Test: VTS on 1.2 sample driver Change-Id: I4d26395ce443687ccbd47445b36e3356d70035cc --- .../vts/functional/GeneratedTestHarness.cpp | 132 ++++++++++++++---- 1 file changed, 103 insertions(+), 29 deletions(-) diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp index 8d427b1227..1ef9c948c4 100644 --- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp +++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp @@ -120,13 +120,14 @@ static std::unique_ptr<::android::nn::ExecutionBurstController> CreateBurst( return ::android::nn::createExecutionBurstController(preparedModel, /*blocking=*/true); } enum class Executor { ASYNC, SYNC, BURST }; +enum class OutputType { FULLY_SPECIFIED, UNSPECIFIED, INSUFFICIENT }; const float kDefaultAtol = 1e-5f; const float kDefaultRtol = 1e-5f; template void EvaluatePreparedModel(sp& preparedModel, std::function is_ignored, const std::vector& examples, bool hasRelaxedFloat32Model, float fpAtol, float fpRtol, - Executor executor, MeasureTiming measure, bool testDynamicOutputShape) { + Executor executor, MeasureTiming measure, OutputType outputType) { const uint32_t INPUT = 0; const uint32_t OUTPUT = 1; @@ -174,8 +175,20 @@ void EvaluatePreparedModel(sp& preparedModel, std::function(index)) outputs_info.resize(index + 1); + if (index == 0) { + // On OutputType::INSUFFICIENT, set the output operand with index 0 with + // buffer size one byte less than needed. + if (outputType == OutputType::INSUFFICIENT) { + if (s > 1) + s -= 1; + else + sizeLargerThanOne = false; + } + } RequestArgument arg = { .location = {.poolIndex = OUTPUT, .offset = 0, .length = static_cast(s)}, .dimensions = {}, @@ -183,6 +196,9 @@ void EvaluatePreparedModel(sp& preparedModel, std::function& preparedModel, std::function& preparedModel, std::function 0) { for_each(test.operandDimensions, [&outputShapes](int idx, std::vector& dim) { dim = outputShapes[idx].dimensions; @@ -324,9 +359,9 @@ template void EvaluatePreparedModel(sp& preparedModel, std::function is_ignored, const std::vector& examples, bool hasRelaxedFloat32Model, Executor executor, MeasureTiming measure, - bool testDynamicOutputShape) { + OutputType outputType) { EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model, kDefaultAtol, - kDefaultRtol, executor, measure, testDynamicOutputShape); + kDefaultRtol, executor, measure, outputType); } static void getPreparedModel(sp callback, @@ -383,7 +418,7 @@ void Execute(const sp& device, std::function c float fpAtol = 1e-5f, fpRtol = 5.0f * 1.1920928955078125e-7f; EvaluatePreparedModel(preparedModel, is_ignored, examples, /*hasRelaxedFloat32Model=*/false, fpAtol, fpRtol, Executor::ASYNC, - MeasureTiming::NO, /*testDynamicOutputShape=*/false); + MeasureTiming::NO, OutputType::FULLY_SPECIFIED); } void Execute(const sp& device, std::function create_model, @@ -430,7 +465,7 @@ void Execute(const sp& device, std::function c EvaluatePreparedModel(preparedModel, is_ignored, examples, model.relaxComputationFloat32toFloat16, 1e-5f, 1e-5f, Executor::ASYNC, - MeasureTiming::NO, /*testDynamicOutputShape=*/false); + MeasureTiming::NO, OutputType::FULLY_SPECIFIED); } // TODO: Reduce code duplication. @@ -477,24 +512,63 @@ void Execute(const sp& device, std::function c EXPECT_EQ(ErrorStatus::NONE, prepareReturnStatus); ASSERT_NE(nullptr, preparedModel.get()); - EvaluatePreparedModel(preparedModel, is_ignored, examples, - model.relaxComputationFloat32toFloat16, Executor::ASYNC, - MeasureTiming::NO, testDynamicOutputShape); - EvaluatePreparedModel(preparedModel, is_ignored, examples, - model.relaxComputationFloat32toFloat16, Executor::SYNC, MeasureTiming::NO, - testDynamicOutputShape); - EvaluatePreparedModel(preparedModel, is_ignored, examples, - model.relaxComputationFloat32toFloat16, Executor::BURST, - MeasureTiming::NO, testDynamicOutputShape); - EvaluatePreparedModel(preparedModel, is_ignored, examples, - model.relaxComputationFloat32toFloat16, Executor::ASYNC, - MeasureTiming::YES, testDynamicOutputShape); - EvaluatePreparedModel(preparedModel, is_ignored, examples, - model.relaxComputationFloat32toFloat16, Executor::SYNC, - MeasureTiming::YES, testDynamicOutputShape); - EvaluatePreparedModel(preparedModel, is_ignored, examples, - model.relaxComputationFloat32toFloat16, Executor::BURST, - MeasureTiming::YES, testDynamicOutputShape); + if (testDynamicOutputShape) { + EvaluatePreparedModel(preparedModel, is_ignored, examples, + model.relaxComputationFloat32toFloat16, Executor::ASYNC, + MeasureTiming::NO, OutputType::UNSPECIFIED); + EvaluatePreparedModel(preparedModel, is_ignored, examples, + model.relaxComputationFloat32toFloat16, Executor::SYNC, + MeasureTiming::NO, OutputType::UNSPECIFIED); + EvaluatePreparedModel(preparedModel, is_ignored, examples, + model.relaxComputationFloat32toFloat16, Executor::BURST, + MeasureTiming::NO, OutputType::UNSPECIFIED); + EvaluatePreparedModel(preparedModel, is_ignored, examples, + model.relaxComputationFloat32toFloat16, Executor::ASYNC, + MeasureTiming::YES, OutputType::UNSPECIFIED); + EvaluatePreparedModel(preparedModel, is_ignored, examples, + model.relaxComputationFloat32toFloat16, Executor::SYNC, + MeasureTiming::YES, OutputType::UNSPECIFIED); + EvaluatePreparedModel(preparedModel, is_ignored, examples, + model.relaxComputationFloat32toFloat16, Executor::BURST, + MeasureTiming::YES, OutputType::UNSPECIFIED); + EvaluatePreparedModel(preparedModel, is_ignored, examples, + model.relaxComputationFloat32toFloat16, Executor::ASYNC, + MeasureTiming::NO, OutputType::INSUFFICIENT); + EvaluatePreparedModel(preparedModel, is_ignored, examples, + model.relaxComputationFloat32toFloat16, Executor::SYNC, + MeasureTiming::NO, OutputType::INSUFFICIENT); + EvaluatePreparedModel(preparedModel, is_ignored, examples, + model.relaxComputationFloat32toFloat16, Executor::BURST, + MeasureTiming::NO, OutputType::INSUFFICIENT); + EvaluatePreparedModel(preparedModel, is_ignored, examples, + model.relaxComputationFloat32toFloat16, Executor::ASYNC, + MeasureTiming::YES, OutputType::INSUFFICIENT); + EvaluatePreparedModel(preparedModel, is_ignored, examples, + model.relaxComputationFloat32toFloat16, Executor::SYNC, + MeasureTiming::YES, OutputType::INSUFFICIENT); + EvaluatePreparedModel(preparedModel, is_ignored, examples, + model.relaxComputationFloat32toFloat16, Executor::BURST, + MeasureTiming::YES, OutputType::INSUFFICIENT); + } else { + EvaluatePreparedModel(preparedModel, is_ignored, examples, + model.relaxComputationFloat32toFloat16, Executor::ASYNC, + MeasureTiming::NO, OutputType::FULLY_SPECIFIED); + EvaluatePreparedModel(preparedModel, is_ignored, examples, + model.relaxComputationFloat32toFloat16, Executor::SYNC, + MeasureTiming::NO, OutputType::FULLY_SPECIFIED); + EvaluatePreparedModel(preparedModel, is_ignored, examples, + model.relaxComputationFloat32toFloat16, Executor::BURST, + MeasureTiming::NO, OutputType::FULLY_SPECIFIED); + EvaluatePreparedModel(preparedModel, is_ignored, examples, + model.relaxComputationFloat32toFloat16, Executor::ASYNC, + MeasureTiming::YES, OutputType::FULLY_SPECIFIED); + EvaluatePreparedModel(preparedModel, is_ignored, examples, + model.relaxComputationFloat32toFloat16, Executor::SYNC, + MeasureTiming::YES, OutputType::FULLY_SPECIFIED); + EvaluatePreparedModel(preparedModel, is_ignored, examples, + model.relaxComputationFloat32toFloat16, Executor::BURST, + MeasureTiming::YES, OutputType::FULLY_SPECIFIED); + } } } // namespace generated_tests From 448e2cf84ce49b9f6d43f25225427dd7e908912d Mon Sep 17 00:00:00 2001 From: Kevin Chyn Date: Mon, 28 Jan 2019 12:44:32 -0800 Subject: [PATCH 427/718] Add ACQUIRED_START message Fixes: 123520106 Bug: 117060268 Test: Builds Change-Id: Ie2fda4f2cdbae1d9b5f2ed08975f3cd8e98c169b --- biometrics/face/1.0/types.hal | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/biometrics/face/1.0/types.hal b/biometrics/face/1.0/types.hal index 2bcd3d5e3e..89e809b3f7 100644 --- a/biometrics/face/1.0/types.hal +++ b/biometrics/face/1.0/types.hal @@ -323,10 +323,20 @@ enum FaceAcquiredInfo : int32_t { */ FACE_OBSCURED = 19, + /** + * This message represents the earliest message sent at the beginning of the authentication + * pipeline. It is expected to be used to measure latency. For example, in a camera-based + * authentication system it's expected to be sent prior to camera initialization. Note this + * should be sent whenever authentication is restarted (see IBiometricsFace#userActivity). + * The framework will measure latency based on the time between the last START message and the + * onAuthenticated callback. + */ + START = 20, + /** * Used to enable a vendor-specific acquisition message. */ - VENDOR = 20 + VENDOR = 21 }; /** From 794703db846798f0411b96cf234a86cab0ec99f2 Mon Sep 17 00:00:00 2001 From: Slava Shklyaev Date: Thu, 17 Jan 2019 15:37:05 +0000 Subject: [PATCH 428/718] Shorten NNAPI enum range names Test: mma Change-Id: I5138589acc127336e8c0e72ca7d6b49532a4eeb9 --- neuralnetworks/1.2/types.hal | 24 +++++++++---------- .../1.2/vts/functional/ValidateModel.cpp | 16 ++++++------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal index 0abe56dea6..4d5f0f4331 100644 --- a/neuralnetworks/1.2/types.hal +++ b/neuralnetworks/1.2/types.hal @@ -97,10 +97,10 @@ enum OperandType : @1.0::OperandType { */ TENSOR_QUANT16_ASYMM = 12, /* ADDING A NEW FUNDAMENTAL TYPE REQUIRES UPDATING THE VALUE OF - * OperandTypeRange::OPERAND_FUNDAMENTAL_MAX. + * OperandTypeRange::FUNDAMENTAL_MAX. */ /* ADDING A NEW OEM TYPE REQUIRES UPDATING THE VALUE OF - * OperandTypeRange::OPERAND_OEM_MAX. + * OperandTypeRange::OEM_MAX. */ }; @@ -108,10 +108,10 @@ enum OperandType : @1.0::OperandType { * The range of operand values in the OperandType enum. */ enum OperandTypeRange : uint32_t { - OPERAND_FUNDAMENTAL_MIN = 0, - OPERAND_FUNDAMENTAL_MAX = 12, - OPERAND_OEM_MIN = 10000, - OPERAND_OEM_MAX = 10001, + FUNDAMENTAL_MIN = 0, + FUNDAMENTAL_MAX = 12, + OEM_MIN = 10000, + OEM_MAX = 10001, }; /** @@ -178,10 +178,10 @@ enum OperationType : @1.1::OperationType { UNIDIRECTIONAL_SEQUENCE_LSTM = 92, UNIDIRECTIONAL_SEQUENCE_RNN = 93, /* ADDING A NEW FUNDAMENTAL OPERATION REQUIRES UPDATING THE VALUE OF - * OperationTypeRange::OPERATION_FUNDAMENTAL_MAX. + * OperationTypeRange::FUNDAMENTAL_MAX. */ /* ADDING A NEW OEM OPERATION REQUIRES UPDATING THE VALUE OF - * OperationTypeRange::OPERATION_OEM_MAX. + * OperationTypeRange::OEM_MAX. */ }; @@ -189,10 +189,10 @@ enum OperationType : @1.1::OperationType { * The range of values in the OperationType enum. */ enum OperationTypeRange : uint32_t { - OPERATION_FUNDAMENTAL_MIN = 0, - OPERATION_FUNDAMENTAL_MAX = 93, - OPERATION_OEM_MIN = 10000, - OPERATION_OEM_MAX = 10000, + FUNDAMENTAL_MIN = 0, + FUNDAMENTAL_MAX = 93, + OEM_MIN = 10000, + OEM_MAX = 10000, }; /** diff --git a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp index f3e528e40c..1bbb20392a 100644 --- a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp +++ b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp @@ -128,10 +128,10 @@ static uint32_t addOperand(Model* model, OperandLifeTime lifetime) { ///////////////////////// VALIDATE MODEL OPERAND TYPE ///////////////////////// static const uint32_t invalidOperandTypes[] = { - static_cast(OperandTypeRange::OPERAND_FUNDAMENTAL_MIN) - 1, - static_cast(OperandTypeRange::OPERAND_FUNDAMENTAL_MAX) + 1, - static_cast(OperandTypeRange::OPERAND_OEM_MIN) - 1, - static_cast(OperandTypeRange::OPERAND_OEM_MAX) + 1, + static_cast(OperandTypeRange::FUNDAMENTAL_MIN) - 1, + static_cast(OperandTypeRange::FUNDAMENTAL_MAX) + 1, + static_cast(OperandTypeRange::OEM_MIN) - 1, + static_cast(OperandTypeRange::OEM_MAX) + 1, }; static void mutateOperandTypeTest(const sp& device, const Model& model) { @@ -392,10 +392,10 @@ static void mutateOperationOperandTypeTest(const sp& device, const Mode ///////////////////////// VALIDATE MODEL OPERATION TYPE ///////////////////////// static const uint32_t invalidOperationTypes[] = { - static_cast(OperationTypeRange::OPERATION_FUNDAMENTAL_MIN) - 1, - static_cast(OperationTypeRange::OPERATION_FUNDAMENTAL_MAX) + 1, - static_cast(OperationTypeRange::OPERATION_OEM_MIN) - 1, - static_cast(OperationTypeRange::OPERATION_OEM_MAX) + 1, + static_cast(OperationTypeRange::FUNDAMENTAL_MIN) - 1, + static_cast(OperationTypeRange::FUNDAMENTAL_MAX) + 1, + static_cast(OperationTypeRange::OEM_MIN) - 1, + static_cast(OperationTypeRange::OEM_MAX) + 1, }; static void mutateOperationTypeTest(const sp& device, const Model& model) { From ba9d3c83b7c1a7cd6d48c1f49c7f3cfc418592fe Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Wed, 23 Jan 2019 15:14:20 -0800 Subject: [PATCH 429/718] Add reset to InputClassifier HAL The reset will be used to prevent an inconsistent stream of events to be sent to the HAL. Bug: 111480215 Test: make only Change-Id: I40c7d671f094065e3fcaff0d83e826c580dcae7a --- input/classifier/1.0/IInputClassifier.hal | 12 ++++++++++++ input/classifier/1.0/default/InputClassifier.cpp | 12 ++++++++++++ input/classifier/1.0/default/InputClassifier.h | 3 +++ 3 files changed, 27 insertions(+) diff --git a/input/classifier/1.0/IInputClassifier.hal b/input/classifier/1.0/IInputClassifier.hal index 5f8c2a564d..7397fea127 100644 --- a/input/classifier/1.0/IInputClassifier.hal +++ b/input/classifier/1.0/IInputClassifier.hal @@ -26,4 +26,16 @@ interface IInputClassifier { */ classify(MotionEvent event) generates (Classification classification); + /** + * Called by the framework to reset the HAL internal state. The reset may be called + * to prevent an inconsistent stream of events to be sent to the HAL. + */ + reset(); + + /** + * Called by the framework to reset the HAL internal state for a specific device. + * The reset may be called once device reset is received by the framework. + */ + resetDevice(int32_t deviceId); + }; diff --git a/input/classifier/1.0/default/InputClassifier.cpp b/input/classifier/1.0/default/InputClassifier.cpp index 7005e9d8b6..a78bbc5c94 100644 --- a/input/classifier/1.0/default/InputClassifier.cpp +++ b/input/classifier/1.0/default/InputClassifier.cpp @@ -57,6 +57,18 @@ Return InputClassifier::classify(const MotionEvent& event) { return Classification::NONE; } +Return InputClassifier::reset() { + // We don't have any internal state in this example implementation, + // so no work needed here. + return Void(); +} + +Return InputClassifier::resetDevice(int32_t /*deviceId*/) { + // We don't have any internal per-device state in this example implementation, + // so no work needed here. + return Void(); +} + } // namespace implementation } // namespace V1_0 } // namespace classifier diff --git a/input/classifier/1.0/default/InputClassifier.h b/input/classifier/1.0/default/InputClassifier.h index 39c4b17b38..eef370e706 100644 --- a/input/classifier/1.0/default/InputClassifier.h +++ b/input/classifier/1.0/default/InputClassifier.h @@ -34,6 +34,9 @@ struct InputClassifier : public IInputClassifier { Return classify( const android::hardware::input::common::V1_0::MotionEvent& event) override; + + Return reset() override; + Return resetDevice(int32_t deviceId) override; }; } // namespace implementation From 9212018558994b0dfc660fb20dc05a408b5e8487 Mon Sep 17 00:00:00 2001 From: Slava Shklyaev Date: Fri, 9 Nov 2018 16:48:19 +0000 Subject: [PATCH 430/718] Define NNAPI Extensions types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Machine Learning is a fast moving domain: new operations and data types are introduced at a staggering speed. The Android API, on the other hand, evolves on a yearly cycle. Many application developers, OEMs, and SoC vendors would like to be able to define new operations at a faster cycle. In OC-MR1, NNAPI provided a simple mechanism to mitigate this problem: two OEM data types and an OEM operation. The downside of this mechanism is that it is simplistic: There’s no guarantee of consistency between vendors. Examples of features that are required by the first parties' use cases that we would like to be able to define outside of the normal Android release cycle: - New data types: - Sparse tensor (used by some speech generation models). - 16 bit int tensor (needed by OCR). - 16 bit float tensor. - New operations: - 16 bit quantized LSTM (needed by OCR). - Basic primitives like sqrt and floor. - Logical operations. - Complex neural network layers. - Control flow. - Enhancement to existing operations: - Concatenate supporting different scales/zeroPoints for arguments. - High-dimensional tensors. - Ordering of dimensions. We are going to provide support for two types of extensions: - NNAPI Platform extension. This is functionality that will become part of future releases of NNAPI. These extensions provide generic, non-vendor-specific functionality. Only the Android team can define new platform extensions. These extensions will be defined in the master branch of AOSP. Each extension comes with: - Documentation defining the extension, - A header file for the new constants, - A parameter validation library to be used by drivers, and - Validation tests akin to the CTS and VTS tests. - Vendor extension. A vendor-specific extension is an alternative to OEM operation and data types. Its usage will be limited only to first party apps preinstalled on the /vendor or /odm partition. Each vendor will be identified by a specific value to prevent collisions between multiple IPs found on the same SoC. This effectively creates a vendor-specific namespace. These identifiers are assigned by Google. This change only defines the new interface. The implementation follows in changes Ie4e2530e4c81fabe4eb59b7a6ba4a3b4bb483bd1, I02aa12f4a8444012ddf3b20c2bfbba6a21ce9ce9, and Icf59ed04e602aa7a730eb1eb45e5f6b1204fafb3. Bug: 118605927 Test: mma Change-Id: Ia9b99015eec7a48bbf969cbe503862271f09adca --- neuralnetworks/1.2/types.hal | 156 +++++++++++++++++++++++++++++------ 1 file changed, 130 insertions(+), 26 deletions(-) diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal index 4d5f0f4331..9e7d8f0d1b 100644 --- a/neuralnetworks/1.2/types.hal +++ b/neuralnetworks/1.2/types.hal @@ -73,10 +73,11 @@ enum OperandType : @1.0::OperandType { * These fields are located inside Operand's extraParams union, inside the * SymmPerChannelQuantParams struct. * - * An Operand of this type must use 'channelQuant' field of its extraParams - * union. + * An Operand of this type must use the 'channelQuant' variant of its + * extraParams field. * - * The channel dimension of this tensor must not be unknown (dimensions[channelDim] != 0). + * The channel dimension of this tensor must be known, i.e. + * dimensions[channelDim] must be non-zero. * * The formula for real values: * realValue[..., C, ...] = @@ -108,10 +109,12 @@ enum OperandType : @1.0::OperandType { * The range of operand values in the OperandType enum. */ enum OperandTypeRange : uint32_t { + BASE_MIN = 0, FUNDAMENTAL_MIN = 0, FUNDAMENTAL_MAX = 12, - OEM_MIN = 10000, - OEM_MAX = 10001, + OEM_MIN = 10000, + OEM_MAX = 10001, + BASE_MAX = 0xFFFF, }; /** @@ -189,10 +192,12 @@ enum OperationType : @1.1::OperationType { * The range of values in the OperationType enum. */ enum OperationTypeRange : uint32_t { + BASE_MIN = 0, FUNDAMENTAL_MIN = 0, FUNDAMENTAL_MAX = 93, - OEM_MIN = 10000, - OEM_MAX = 10000, + OEM_MIN = 10000, + OEM_MAX = 10000, + BASE_MAX = 0xFFFF, }; /** @@ -221,6 +226,10 @@ enum DeviceType : int32_t { struct Operation { /** * The operation type. + * + * Besides the values listed in {@link OperationType}, any value above + * {@link OperationTypeRange::BASE_MAX} is possible and should be interpreted + * as an extension type according to {@link Model::extensionNameToPrefix}. */ OperationType type; @@ -247,21 +256,16 @@ struct SymmPerChannelQuantParams { uint32_t channelDim; }; -// TODO(slavash): Operand Extension support -// /** -// * Parameters for an unknown (as of 1.2) operand extension. This is -// * a vendor-specific extension or a platform extension (backport of -// * functionality from newer NNAPI interface). -// */ -// struct OperandParamsUnknown { -// }; - /** * Describes one operand of the model's graph. */ struct Operand { /** - * Data type of the operand. + * The data type. + * + * Besides the values listed in {@link OperandType}, any value above + * {@link OperandTypeRange::BASE_MAX} is possible and should be interpreted + * as an extension type according to {@link Model::extensionNameToPrefix}. */ OperandType type; @@ -351,25 +355,28 @@ struct Operand { DataLocation location; /** - * Union of extra parameters, used by some types of Operands that need additional - * information for the complete definition of an Operand. + * Additional parameters specific to a particular operand type. */ safe_union ExtraParams { /** - * Placeholder for operand with no extra parameters. + * No additional parameters. */ Monostate none; /** - * Used with TENSOR_QUANT8_SYMM_PER_CHANNEL operand type. + * Symmetric per-channel quantization parameters. + * + * Only applicable to operands of type TENSOR_QUANT8_SYMM_PER_CHANNEL. */ SymmPerChannelQuantParams channelQuant; - // TODO(slavash): Operand Extension support - // /** - // * Used with Extension operand type. - // */ - // OperandParamsUnknown unknown; + /** + * Extension operand parameters. + * + * The framework treats this as an opaque data blob. + * The format is up to individual extensions. + */ + vec extension; } extraParams; }; @@ -432,6 +439,63 @@ struct Model { * range and precision of the IEEE 754 32-bit floating-point format. */ bool relaxComputationFloat32toFloat16; + + /** + * The mapping between extension names and prefixes of operand and + * operation type values. + * + * An operand or operation whose numeric type value is above + * {@link OperandTypeRange::BASE_MAX} or + * {@link OperationTypeRange::BASE_MAX} respectively should be interpreted + * as an extension operand. The low + * {@link Model::ExtensionTypeEncoding::LOW_BITS_TYPE} bits of the value + * correspond to the value within the extension and the high + * {@link Model::ExtensionTypeEncoding::HIGH_BITS_PREFIX} bits encode + * the "prefix", which maps uniquely to the extension name. + * + * For example, if a model contains an operation whose value is + * 0xAAAABBBB and extensionNameToPrefix contains an entry with + * prefix=0xAAAA and name="vendor.test.test_extension", then + * the operation should be interpreted as the operation 0xBBBB + * of the extension named vendor.test.test_extension. + * + * This is a one-to-one correspondence. That is, there must be at most one + * prefix corresponding to each extension name and at most one extension + * name corresponding to each prefix. + */ + vec extensionNameToPrefix; + + /** + * A correspondence between an extension name and a prefix of operand and + * operation type values. + */ + struct ExtensionNameAndPrefix { + /** + * The extension name. + * + * See {@link Extension::name}. + */ + string name; + + /** + * The unique extension identifier within the model. + * + * See {@link Model::extensionNameToPrefix}. + */ + uint16_t prefix; + }; + + /** + * Numeric values of extension operand and operation types have the + * following structure: + * - 16 high bits represent the "prefix", which corresponds uniquely to the + * extension name. + * - 16 low bits represent the type ID within the extension. + */ + enum ExtensionTypeEncoding : uint8_t { + HIGH_BITS_PREFIX = 16, + LOW_BITS_TYPE = 16, + }; }; /** @@ -685,3 +749,43 @@ safe_union FmqResultDatum { */ Timing executionTiming; }; + +/** + * Information about an extension. + */ +struct Extension { + /** + * The extension name. + * + * The name must start with the reverse domain name of the vendor. + * Example: com.google.test_extension + */ + string name; + + /** + * Information about an extension operand type. + */ + struct OperandTypeInformation { + /** + * The extension operand type. + */ + uint16_t type; + + /** + * Indicates whether the extension operand type represents a tensor or + * a scalar. + */ + bool isTensor; + + /** + * The byte size of the operand (if scalar) or of a single element (if + * tensor). + */ + uint32_t byteSize; + }; + + /** + * Information about operand types defined by the extension. + */ + vec operandTypes; +}; From 6148d0f446d331f9e76f3efe6554e3f2cb1907aa Mon Sep 17 00:00:00 2001 From: Slava Shklyaev Date: Tue, 20 Nov 2018 15:29:01 +0000 Subject: [PATCH 431/718] Add getSupportedExtensions to NNAPI IDevice Bug: 118603011 Test: mma Change-Id: I5bd1cf2dfd8c4700819d52a87931df2959ef6929 --- neuralnetworks/1.2/IDevice.hal | 15 +++++++++++++++ .../1.2/vts/functional/BasicTests.cpp | 17 +++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/neuralnetworks/1.2/IDevice.hal b/neuralnetworks/1.2/IDevice.hal index de249b0e08..b9fa38870e 100644 --- a/neuralnetworks/1.2/IDevice.hal +++ b/neuralnetworks/1.2/IDevice.hal @@ -75,6 +75,21 @@ interface IDevice extends @1.1::IDevice { */ getType() generates (ErrorStatus status, DeviceType type); + /** + * Gets information about extensions supported by the driver implementation. + * + * All extension operations and operands must be fully supported for the + * extension to appear in the list of supported extensions. + * + * @return status Error status of the call, must be: + * - NONE if successful + * - DEVICE_UNAVAILABLE if driver is offline or busy + * - GENERAL_FAILURE if there is an unspecified error + * @return extensions A list of supported extensions. + */ + getSupportedExtensions() + generates (ErrorStatus status, vec extensions); + /** * Gets the supported operations in a model. * diff --git a/neuralnetworks/1.2/vts/functional/BasicTests.cpp b/neuralnetworks/1.2/vts/functional/BasicTests.cpp index 8c3ad15e2a..0eec3656e7 100644 --- a/neuralnetworks/1.2/vts/functional/BasicTests.cpp +++ b/neuralnetworks/1.2/vts/functional/BasicTests.cpp @@ -55,6 +55,23 @@ TEST_F(NeuralnetworksHidlTest, GetDeviceTypeTest) { }); EXPECT_TRUE(ret.isOk()); } + +// device supported extensions test +TEST_F(NeuralnetworksHidlTest, GetDeviceSupportedExtensionsTest) { + Return ret = device->getSupportedExtensions( + [](ErrorStatus status, const hidl_vec& extensions) { + EXPECT_EQ(ErrorStatus::NONE, status); + for (auto& extension : extensions) { + std::string extensionName = extension.name; + EXPECT_FALSE(extensionName.empty()); + EXPECT_NE(extensionName.find("."), std::string::npos) + << "Extension name must start with the reverse domain name of the " + "vendor"; + } + }); + EXPECT_TRUE(ret.isOk()); +} + } // namespace functional } // namespace vts } // namespace V1_2 From f9f0a25b26d93cf86ccb44c046f83b86ce962c3d Mon Sep 17 00:00:00 2001 From: Henry Fang Date: Thu, 17 Jan 2019 17:25:05 -0800 Subject: [PATCH 432/718] Update cas@1.0 hal to cas@1.1 Add sendSessionEvent to notify hal what happened on a session. Add onSessionEvent to listen notification from hal for a session Test: manual Bug: 122472761 Change-Id: I98434325915e7bee57e63bdeeedba9ed5578e493 --- cas/1.1/Android.bp | 20 ++ cas/1.1/ICas.hal | 42 ++++ cas/1.1/ICasListener.hal | 33 +++ cas/1.1/IMediaCasService.hal | 38 +++ cas/1.1/default/Android.bp | 49 ++++ cas/1.1/default/CasImpl.cpp | 222 ++++++++++++++++++ cas/1.1/default/CasImpl.h | 98 ++++++++ cas/1.1/default/DescramblerImpl.cpp | 195 +++++++++++++++ cas/1.1/default/DescramblerImpl.h | 67 ++++++ cas/1.1/default/FactoryLoader.h | 217 +++++++++++++++++ cas/1.1/default/MediaCasService.cpp | 126 ++++++++++ cas/1.1/default/MediaCasService.h | 66 ++++++ cas/1.1/default/SharedLibrary.cpp | 65 +++++ cas/1.1/default/SharedLibrary.h | 50 ++++ cas/1.1/default/TypeConvert.cpp | 94 ++++++++ cas/1.1/default/TypeConvert.h | 43 ++++ .../android.hardware.cas@1.1-service-lazy.rc | 9 + .../android.hardware.cas@1.1-service-lazy.xml | 11 + .../android.hardware.cas@1.1-service.rc | 6 + .../android.hardware.cas@1.1-service.xml | 11 + cas/1.1/default/service.cpp | 58 +++++ .../compatibility_matrix.current.xml | 2 +- 22 files changed, 1521 insertions(+), 1 deletion(-) create mode 100644 cas/1.1/Android.bp create mode 100644 cas/1.1/ICas.hal create mode 100644 cas/1.1/ICasListener.hal create mode 100644 cas/1.1/IMediaCasService.hal create mode 100644 cas/1.1/default/Android.bp create mode 100644 cas/1.1/default/CasImpl.cpp create mode 100644 cas/1.1/default/CasImpl.h create mode 100644 cas/1.1/default/DescramblerImpl.cpp create mode 100644 cas/1.1/default/DescramblerImpl.h create mode 100644 cas/1.1/default/FactoryLoader.h create mode 100644 cas/1.1/default/MediaCasService.cpp create mode 100644 cas/1.1/default/MediaCasService.h create mode 100644 cas/1.1/default/SharedLibrary.cpp create mode 100644 cas/1.1/default/SharedLibrary.h create mode 100644 cas/1.1/default/TypeConvert.cpp create mode 100644 cas/1.1/default/TypeConvert.h create mode 100644 cas/1.1/default/android.hardware.cas@1.1-service-lazy.rc create mode 100644 cas/1.1/default/android.hardware.cas@1.1-service-lazy.xml create mode 100644 cas/1.1/default/android.hardware.cas@1.1-service.rc create mode 100644 cas/1.1/default/android.hardware.cas@1.1-service.xml create mode 100644 cas/1.1/default/service.cpp diff --git a/cas/1.1/Android.bp b/cas/1.1/Android.bp new file mode 100644 index 0000000000..bb0edb970c --- /dev/null +++ b/cas/1.1/Android.bp @@ -0,0 +1,20 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +hidl_interface { + name: "android.hardware.cas@1.1", + root: "android.hardware", + vndk: { + enabled: true, + }, + srcs: [ + "ICas.hal", + "ICasListener.hal", + "IMediaCasService.hal", + ], + interfaces: [ + "android.hardware.cas@1.0", + "android.hidl.base@1.0", + ], + gen_java: true, +} + diff --git a/cas/1.1/ICas.hal b/cas/1.1/ICas.hal new file mode 100644 index 0000000000..027968e565 --- /dev/null +++ b/cas/1.1/ICas.hal @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.hardware.cas@1.1; + +import @1.0::HidlCasSessionId; +import @1.0::ICas; +import @1.0::Status; + +/** + * ICas is the API to control the cas system and is accessible from both + * Java and native level. It is used to manage sessions, provision/refresh + * the cas system, and process the EMM/ECM messages. It also allows bi-directional, + * scheme-specific communications between the client and the cas system. + */ + +interface ICas extends @1.0::ICas { + /** + * Send an scheme-specific session event to the CasPlugin. + * + * @param sessionId the id of an opened session. + * @param event an integer denoting a scheme-specific event to be sent. + * @param arg a scheme-specific integer argument for the event. + * @param data a byte array containing scheme-specific data for the event. + * @return status the status of the call. + */ + sendSessionEvent(HidlCasSessionId sessionId, int32_t event, int32_t arg, + vec eventData) + generates (Status status); +}; diff --git a/cas/1.1/ICasListener.hal b/cas/1.1/ICasListener.hal new file mode 100644 index 0000000000..5ec1154a3f --- /dev/null +++ b/cas/1.1/ICasListener.hal @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.hardware.cas@1.1; + +import @1.0::ICasListener; +import @1.0::HidlCasSessionId; + +interface ICasListener extends @1.0::ICasListener{ + /** + * Notify the listener of a scheme-specific session event from CA system. + * + * @param sessionId the id of an opened session. + * @param event an integer whose meaning is scheme-specific. + * @param arg an integer whose meaning is scheme-specific. + * @param data a byte array of data whose format and meaning are + * scheme-specific. + */ + onSessionEvent(HidlCasSessionId sessionId, int32_t event, int32_t arg, + vec data); +}; diff --git a/cas/1.1/IMediaCasService.hal b/cas/1.1/IMediaCasService.hal new file mode 100644 index 0000000000..e82b54c9db --- /dev/null +++ b/cas/1.1/IMediaCasService.hal @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.hardware.cas@1.1; + +import @1.1::ICas; +import @1.1::ICasListener; +import @1.0::IMediaCasService; + +/** + * IMediaCasService is the main entry point for interacting with a vendor's + * cas HAL to create cas and descrambler plugin instances. A cas plugin instance + * opens cas sessions which are used to obtain keys for a descrambler session, + * which can in turn be used to descramble protected video content. + */ + +interface IMediaCasService extends @1.0::IMediaCasService { + /** + * Construct a new instance of a @1.1 ICAS CasPlugin given a CA_system_id. + * + * @param caSystemId the id of the CA system. + * @param listener the event listener to receive events coming from the CasPlugin. + * @return cas the newly created CasPlugin interface. + */ + createPluginExt(int32_t caSystemId, ICasListener listener) generates (ICas cas); +}; diff --git a/cas/1.1/default/Android.bp b/cas/1.1/default/Android.bp new file mode 100644 index 0000000000..68a49cf5b1 --- /dev/null +++ b/cas/1.1/default/Android.bp @@ -0,0 +1,49 @@ +cc_defaults { + name: "cas_service_defaults@1.1", + defaults: ["hidl_defaults"], + vendor: true, + relative_install_path: "hw", + srcs: [ + "CasImpl.cpp", + "DescramblerImpl.cpp", + "MediaCasService.cpp", + "service.cpp", + "SharedLibrary.cpp", + "TypeConvert.cpp", + ], + + compile_multilib: "32", + + shared_libs: [ + "android.hardware.cas@1.0", + "android.hardware.cas@1.1", + "android.hardware.cas.native@1.0", + "android.hidl.memory@1.0", + "libbinder", + "libhidlbase", + "libhidlmemory", + "libhidltransport", + "liblog", + "libutils", + ], + header_libs: [ + "libstagefright_foundation_headers", + "media_plugin_headers", + ], +} + +cc_binary { + name: "android.hardware.cas@1.1-service", + vintf_fragments: ["android.hardware.cas@1.1-service.xml"], + defaults: ["cas_service_defaults@1.1"], + init_rc: ["android.hardware.cas@1.1-service.rc"], +} + +cc_binary { + name: "android.hardware.cas@1.1-service-lazy", + vintf_fragments: ["android.hardware.cas@1.1-service-lazy.xml"], + overrides: ["android.hardware.cas@1.1-service"], + defaults: ["cas_service_defaults@1.1"], + init_rc: ["android.hardware.cas@1.1-service-lazy.rc"], + cflags: ["-DLAZY_SERVICE"], +} diff --git a/cas/1.1/default/CasImpl.cpp b/cas/1.1/default/CasImpl.cpp new file mode 100644 index 0000000000..4cc6017028 --- /dev/null +++ b/cas/1.1/default/CasImpl.cpp @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "android.hardware.cas@1.1-CasImpl" + +#include +#include +#include + +#include "CasImpl.h" +#include "SharedLibrary.h" +#include "TypeConvert.h" + +namespace android { +namespace hardware { +namespace cas { +namespace V1_1 { +namespace implementation { + +CasImpl::CasImpl(const sp& listener) : mListener(listener) { + ALOGV("CTOR"); +} + +CasImpl::~CasImpl() { + ALOGV("DTOR"); + release(); +} + +// static +void CasImpl::OnEvent(void* appData, int32_t event, int32_t arg, uint8_t* data, size_t size) { + if (appData == NULL) { + ALOGE("Invalid appData!"); + return; + } + CasImpl* casImpl = static_cast(appData); + casImpl->onEvent(event, arg, data, size); +} + +// static +void CasImpl::CallBackExt(void* appData, int32_t event, int32_t arg, uint8_t* data, size_t size, + const CasSessionId* sessionId) { + if (appData == NULL) { + ALOGE("Invalid appData!"); + return; + } + CasImpl* casImpl = static_cast(appData); + casImpl->onEvent(sessionId, event, arg, data, size); +} + +void CasImpl::init(const sp& library, CasPlugin* plugin) { + mLibrary = library; + std::shared_ptr holder(plugin); + std::atomic_store(&mPluginHolder, holder); +} + +void CasImpl::onEvent(int32_t event, int32_t arg, uint8_t* data, size_t size) { + if (mListener == NULL) { + return; + } + + HidlCasData eventData; + if (data != NULL) { + eventData.setToExternal(data, size); + } + + mListener->onEvent(event, arg, eventData); +} + +void CasImpl::onEvent(const CasSessionId* sessionId, int32_t event, int32_t arg, uint8_t* data, + size_t size) { + if (mListener == NULL) { + return; + } + + HidlCasData eventData; + if (data != NULL) { + eventData.setToExternal(data, size); + } + + if (sessionId != NULL) { + mListener->onSessionEvent(*sessionId, event, arg, eventData); + } else { + mListener->onEvent(event, arg, eventData); + } +} + +Return CasImpl::setPrivateData(const HidlCasData& pvtData) { + ALOGV("%s", __FUNCTION__); + std::shared_ptr holder = std::atomic_load(&mPluginHolder); + if (holder.get() == nullptr) { + return toStatus(INVALID_OPERATION); + } + return toStatus(holder->setPrivateData(pvtData)); +} + +Return CasImpl::openSession(openSession_cb _hidl_cb) { + ALOGV("%s", __FUNCTION__); + CasSessionId sessionId; + + std::shared_ptr holder = std::atomic_load(&mPluginHolder); + status_t err = INVALID_OPERATION; + if (holder.get() != nullptr) { + err = holder->openSession(&sessionId); + holder.reset(); + } + + _hidl_cb(toStatus(err), sessionId); + + return Void(); +} + +Return CasImpl::setSessionPrivateData(const HidlCasSessionId& sessionId, + const HidlCasData& pvtData) { + ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).string()); + std::shared_ptr holder = std::atomic_load(&mPluginHolder); + if (holder.get() == nullptr) { + return toStatus(INVALID_OPERATION); + } + return toStatus(holder->setSessionPrivateData(sessionId, pvtData)); +} + +Return CasImpl::closeSession(const HidlCasSessionId& sessionId) { + ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).string()); + std::shared_ptr holder = std::atomic_load(&mPluginHolder); + if (holder.get() == nullptr) { + return toStatus(INVALID_OPERATION); + } + return toStatus(holder->closeSession(sessionId)); +} + +Return CasImpl::processEcm(const HidlCasSessionId& sessionId, const HidlCasData& ecm) { + ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).string()); + std::shared_ptr holder = std::atomic_load(&mPluginHolder); + if (holder.get() == nullptr) { + return toStatus(INVALID_OPERATION); + } + + return toStatus(holder->processEcm(sessionId, ecm)); +} + +Return CasImpl::processEmm(const HidlCasData& emm) { + ALOGV("%s", __FUNCTION__); + std::shared_ptr holder = std::atomic_load(&mPluginHolder); + if (holder.get() == nullptr) { + return toStatus(INVALID_OPERATION); + } + + return toStatus(holder->processEmm(emm)); +} + +Return CasImpl::sendEvent(int32_t event, int32_t arg, const HidlCasData& eventData) { + ALOGV("%s", __FUNCTION__); + std::shared_ptr holder = std::atomic_load(&mPluginHolder); + if (holder.get() == nullptr) { + return toStatus(INVALID_OPERATION); + } + + status_t err = holder->sendEvent(event, arg, eventData); + return toStatus(err); +} + +Return CasImpl::sendSessionEvent(const HidlCasSessionId& sessionId, int32_t event, + int32_t arg, const HidlCasData& eventData) { + ALOGV("%s", __FUNCTION__); + std::shared_ptr holder = std::atomic_load(&mPluginHolder); + if (holder.get() == nullptr) { + return toStatus(INVALID_OPERATION); + } + + status_t err = holder->sendSessionEvent(sessionId, event, arg, eventData); + return toStatus(err); +} + +Return CasImpl::provision(const hidl_string& provisionString) { + ALOGV("%s: provisionString=%s", __FUNCTION__, provisionString.c_str()); + std::shared_ptr holder = std::atomic_load(&mPluginHolder); + if (holder.get() == nullptr) { + return toStatus(INVALID_OPERATION); + } + + return toStatus(holder->provision(String8(provisionString.c_str()))); +} + +Return CasImpl::refreshEntitlements(int32_t refreshType, const HidlCasData& refreshData) { + ALOGV("%s", __FUNCTION__); + std::shared_ptr holder = std::atomic_load(&mPluginHolder); + if (holder.get() == nullptr) { + return toStatus(INVALID_OPERATION); + } + + status_t err = holder->refreshEntitlements(refreshType, refreshData); + return toStatus(err); +} + +Return CasImpl::release() { + ALOGV("%s: plugin=%p", __FUNCTION__, mPluginHolder.get()); + + std::shared_ptr holder(nullptr); + std::atomic_store(&mPluginHolder, holder); + + return Status::OK; +} + +} // namespace implementation +} // namespace V1_1 +} // namespace cas +} // namespace hardware +} // namespace android diff --git a/cas/1.1/default/CasImpl.h b/cas/1.1/default/CasImpl.h new file mode 100644 index 0000000000..18aee9e457 --- /dev/null +++ b/cas/1.1/default/CasImpl.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2019 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_CAS_V1_1_CAS_IMPL_H_ +#define ANDROID_HARDWARE_CAS_V1_1_CAS_IMPL_H_ + +#include +#include + +namespace android { +struct CasPlugin; + +namespace hardware { +namespace cas { +namespace V1_1 { +struct ICasListener; +namespace implementation { + +using ::android::hardware::cas::V1_0::HidlCasData; +using ::android::hardware::cas::V1_0::HidlCasSessionId; +using ::android::hardware::cas::V1_0::Status; + +class SharedLibrary; + +class CasImpl : public ICas { + public: + CasImpl(const sp& listener); + virtual ~CasImpl(); + + static void OnEvent(void* appData, int32_t event, int32_t arg, uint8_t* data, size_t size); + + static void CallBackExt(void* appData, int32_t event, int32_t arg, uint8_t* data, size_t size, + const CasSessionId* sessionId); + + void init(const sp& library, CasPlugin* plugin); + void onEvent(int32_t event, int32_t arg, uint8_t* data, size_t size); + + void onEvent(const CasSessionId* sessionId, int32_t event, int32_t arg, uint8_t* data, + size_t size); + + // ICas inherits + + virtual Return setPrivateData(const HidlCasData& pvtData) override; + + virtual Return openSession(openSession_cb _hidl_cb) override; + + virtual Return closeSession(const HidlCasSessionId& sessionId) override; + + virtual Return setSessionPrivateData(const HidlCasSessionId& sessionId, + const HidlCasData& pvtData) override; + + virtual Return processEcm(const HidlCasSessionId& sessionId, + const HidlCasData& ecm) override; + + virtual Return processEmm(const HidlCasData& emm) override; + + virtual Return sendEvent(int32_t event, int32_t arg, + const HidlCasData& eventData) override; + + virtual Return sendSessionEvent(const HidlCasSessionId& sessionId, int32_t event, + int32_t arg, const HidlCasData& eventData) override; + + virtual Return provision(const hidl_string& provisionString) override; + + virtual Return refreshEntitlements(int32_t refreshType, + const HidlCasData& refreshData) override; + + virtual Return release() override; + + private: + struct PluginHolder; + sp mLibrary; + std::shared_ptr mPluginHolder; + sp mListener; + + DISALLOW_EVIL_CONSTRUCTORS(CasImpl); +}; + +} // namespace implementation +} // namespace V1_1 +} // namespace cas +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_CAS_V1_1_CAS_IMPL_H_ diff --git a/cas/1.1/default/DescramblerImpl.cpp b/cas/1.1/default/DescramblerImpl.cpp new file mode 100644 index 0000000000..36dc1a51d0 --- /dev/null +++ b/cas/1.1/default/DescramblerImpl.cpp @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "android.hardware.cas@1.1-DescramblerImpl" + +#include +#include +#include +#include +#include + +#include "DescramblerImpl.h" +#include "SharedLibrary.h" +#include "TypeConvert.h" + +namespace android { +using hidl::memory::V1_0::IMemory; + +namespace hardware { +namespace cas { +namespace V1_1 { +namespace implementation { + +#define CHECK_SUBSAMPLE_DEF(type) \ + static_assert(sizeof(SubSample) == sizeof(type::SubSample), "SubSample: size doesn't match"); \ + static_assert(offsetof(SubSample, numBytesOfClearData) == \ + offsetof(type::SubSample, mNumBytesOfClearData), \ + "SubSample: numBytesOfClearData offset doesn't match"); \ + static_assert(offsetof(SubSample, numBytesOfEncryptedData) == \ + offsetof(type::SubSample, mNumBytesOfEncryptedData), \ + "SubSample: numBytesOfEncryptedData offset doesn't match") + +CHECK_SUBSAMPLE_DEF(DescramblerPlugin); +CHECK_SUBSAMPLE_DEF(CryptoPlugin); + +DescramblerImpl::DescramblerImpl(const sp& library, DescramblerPlugin* plugin) + : mLibrary(library), mPluginHolder(plugin) { + ALOGV("CTOR: plugin=%p", mPluginHolder.get()); +} + +DescramblerImpl::~DescramblerImpl() { + ALOGV("DTOR: plugin=%p", mPluginHolder.get()); + release(); +} + +Return DescramblerImpl::setMediaCasSession(const HidlCasSessionId& sessionId) { + ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).string()); + + std::shared_ptr holder = std::atomic_load(&mPluginHolder); + if (holder.get() == nullptr) { + return toStatus(INVALID_OPERATION); + } + + return toStatus(holder->setMediaCasSession(sessionId)); +} + +Return DescramblerImpl::requiresSecureDecoderComponent(const hidl_string& mime) { + std::shared_ptr holder = std::atomic_load(&mPluginHolder); + if (holder.get() == nullptr) { + return false; + } + + return holder->requiresSecureDecoderComponent(String8(mime.c_str())); +} + +static inline bool validateRangeForSize(uint64_t offset, uint64_t length, uint64_t size) { + return isInRange(0, size, offset, length); +} + +Return DescramblerImpl::descramble(ScramblingControl scramblingControl, + const hidl_vec& subSamples, + const SharedBuffer& srcBuffer, uint64_t srcOffset, + const DestinationBuffer& dstBuffer, uint64_t dstOffset, + descramble_cb _hidl_cb) { + ALOGV("%s", __FUNCTION__); + + // hidl_memory's size is stored in uint64_t, but mapMemory's mmap will map + // size in size_t. If size is over SIZE_MAX, mapMemory mapMemory could succeed + // but the mapped memory's actual size will be smaller than the reported size. + if (srcBuffer.heapBase.size() > SIZE_MAX) { + ALOGE("Invalid hidl_memory size: %llu", srcBuffer.heapBase.size()); + android_errorWriteLog(0x534e4554, "79376389"); + _hidl_cb(toStatus(BAD_VALUE), 0, NULL); + return Void(); + } + + sp srcMem = mapMemory(srcBuffer.heapBase); + + // Validate if the offset and size in the SharedBuffer is consistent with the + // mapped ashmem, since the offset and size is controlled by client. + if (srcMem == NULL) { + ALOGE("Failed to map src buffer."); + _hidl_cb(toStatus(BAD_VALUE), 0, NULL); + return Void(); + } + if (!validateRangeForSize(srcBuffer.offset, srcBuffer.size, (uint64_t)srcMem->getSize())) { + ALOGE("Invalid src buffer range: offset %llu, size %llu, srcMem size %llu", + srcBuffer.offset, srcBuffer.size, (uint64_t)srcMem->getSize()); + android_errorWriteLog(0x534e4554, "67962232"); + _hidl_cb(toStatus(BAD_VALUE), 0, NULL); + return Void(); + } + + // use 64-bit here to catch bad subsample size that might be overflowing. + uint64_t totalBytesInSubSamples = 0; + for (size_t i = 0; i < subSamples.size(); i++) { + totalBytesInSubSamples += + (uint64_t)subSamples[i].numBytesOfClearData + subSamples[i].numBytesOfEncryptedData; + } + // Further validate if the specified srcOffset and requested total subsample size + // is consistent with the source shared buffer size. + if (!validateRangeForSize(srcOffset, totalBytesInSubSamples, srcBuffer.size)) { + ALOGE("Invalid srcOffset and subsample size: " + "srcOffset %llu, totalBytesInSubSamples %llu, srcBuffer size %llu", + srcOffset, totalBytesInSubSamples, srcBuffer.size); + android_errorWriteLog(0x534e4554, "67962232"); + _hidl_cb(toStatus(BAD_VALUE), 0, NULL); + return Void(); + } + + void* srcPtr = (uint8_t*)(void*)srcMem->getPointer() + srcBuffer.offset; + void* dstPtr = NULL; + if (dstBuffer.type == BufferType::SHARED_MEMORY) { + // When using shared memory, src buffer is also used as dst, + // we don't map it again here. + dstPtr = srcPtr; + + // In this case the dst and src would be the same buffer, need to validate + // dstOffset against the buffer size too. + if (!validateRangeForSize(dstOffset, totalBytesInSubSamples, srcBuffer.size)) { + ALOGE("Invalid dstOffset and subsample size: " + "dstOffset %llu, totalBytesInSubSamples %llu, srcBuffer size %llu", + dstOffset, totalBytesInSubSamples, srcBuffer.size); + android_errorWriteLog(0x534e4554, "67962232"); + _hidl_cb(toStatus(BAD_VALUE), 0, NULL); + return Void(); + } + } else { + native_handle_t* handle = + const_cast(dstBuffer.secureMemory.getNativeHandle()); + dstPtr = static_cast(handle); + } + + // Get a local copy of the shared_ptr for the plugin. Note that before + // calling the HIDL callback, this shared_ptr must be manually reset, + // since the client side could proceed as soon as the callback is called + // without waiting for this method to go out of scope. + std::shared_ptr holder = std::atomic_load(&mPluginHolder); + if (holder.get() == nullptr) { + _hidl_cb(toStatus(INVALID_OPERATION), 0, NULL); + return Void(); + } + + // Casting hidl SubSample to DescramblerPlugin::SubSample, but need + // to ensure structs are actually idential + + int32_t result = + holder->descramble(dstBuffer.type != BufferType::SHARED_MEMORY, + (DescramblerPlugin::ScramblingControl)scramblingControl, + subSamples.size(), (DescramblerPlugin::SubSample*)subSamples.data(), + srcPtr, srcOffset, dstPtr, dstOffset, NULL); + + holder.reset(); + _hidl_cb(toStatus(result >= 0 ? OK : result), result, NULL); + return Void(); +} + +Return DescramblerImpl::release() { + ALOGV("%s: plugin=%p", __FUNCTION__, mPluginHolder.get()); + + std::shared_ptr holder(nullptr); + std::atomic_store(&mPluginHolder, holder); + + return Status::OK; +} + +} // namespace implementation +} // namespace V1_1 +} // namespace cas +} // namespace hardware +} // namespace android diff --git a/cas/1.1/default/DescramblerImpl.h b/cas/1.1/default/DescramblerImpl.h new file mode 100644 index 0000000000..a1f66ae464 --- /dev/null +++ b/cas/1.1/default/DescramblerImpl.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2019 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_CAS_V1_1_DESCRAMBLER_IMPL_H_ +#define ANDROID_HARDWARE_CAS_V1_1_DESCRAMBLER_IMPL_H_ + +#include +#include + +namespace android { +struct DescramblerPlugin; +using namespace hardware::cas::native::V1_0; + +namespace hardware { +namespace cas { +namespace V1_1 { +namespace implementation { + +using ::android::hardware::cas::V1_0::HidlCasSessionId; +using ::android::hardware::cas::V1_0::Status; + +class SharedLibrary; + +class DescramblerImpl : public IDescrambler { + public: + DescramblerImpl(const sp& library, DescramblerPlugin* plugin); + virtual ~DescramblerImpl(); + + virtual Return setMediaCasSession(const HidlCasSessionId& sessionId) override; + + virtual Return requiresSecureDecoderComponent(const hidl_string& mime) override; + + virtual Return descramble(ScramblingControl scramblingControl, + const hidl_vec& subSamples, + const SharedBuffer& srcBuffer, uint64_t srcOffset, + const DestinationBuffer& dstBuffer, uint64_t dstOffset, + descramble_cb _hidl_cb) override; + + virtual Return release() override; + + private: + sp mLibrary; + std::shared_ptr mPluginHolder; + + DISALLOW_EVIL_CONSTRUCTORS(DescramblerImpl); +}; + +} // namespace implementation +} // namespace V1_1 +} // namespace cas +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_CAS_V1_1_DESCRAMBLER_IMPL_H_ diff --git a/cas/1.1/default/FactoryLoader.h b/cas/1.1/default/FactoryLoader.h new file mode 100644 index 0000000000..c4a48e2852 --- /dev/null +++ b/cas/1.1/default/FactoryLoader.h @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2019 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_CAS_V1_1_FACTORY_LOADER_H_ +#define ANDROID_HARDWARE_CAS_V1_1_FACTORY_LOADER_H_ + +#include +#include +#include +#include +#include +#include "SharedLibrary.h" + +using namespace std; + +namespace android { +namespace hardware { +namespace cas { +namespace V1_1 { +namespace implementation { + +using ::android::hardware::cas::V1_0::HidlCasPluginDescriptor; + +template +class FactoryLoader { + public: + FactoryLoader(const char* name) : mFactory(NULL), mCreateFactoryFuncName(name) {} + + virtual ~FactoryLoader() { closeFactory(); } + + bool findFactoryForScheme(int32_t CA_system_id, sp* library = NULL, + T** factory = NULL); + + bool enumeratePlugins(vector* results); + + private: + typedef T* (*CreateFactoryFunc)(); + + Mutex mMapLock; + T* mFactory; + const char* mCreateFactoryFuncName; + sp mLibrary; + KeyedVector mCASystemIdToLibraryPathMap; + KeyedVector > mLibraryPathToOpenLibraryMap; + + bool loadFactoryForSchemeFromPath(const String8& path, int32_t CA_system_id, + sp* library, T** factory); + + bool queryPluginsFromPath(const String8& path, vector* results); + + bool openFactory(const String8& path); + void closeFactory(); +}; + +template +bool FactoryLoader::findFactoryForScheme(int32_t CA_system_id, sp* library, + T** factory) { + if (library != NULL) { + library->clear(); + } + if (factory != NULL) { + *factory = NULL; + } + + Mutex::Autolock autoLock(mMapLock); + + // first check cache + ssize_t index = mCASystemIdToLibraryPathMap.indexOfKey(CA_system_id); + if (index >= 0) { + return loadFactoryForSchemeFromPath(mCASystemIdToLibraryPathMap[index], CA_system_id, + library, factory); + } + + // no luck, have to search + String8 dirPath("/vendor/lib/mediacas"); + DIR* pDir = opendir(dirPath.string()); + + if (pDir == NULL) { + ALOGE("Failed to open plugin directory %s", dirPath.string()); + return false; + } + + struct dirent* pEntry; + while ((pEntry = readdir(pDir))) { + String8 pluginPath = dirPath + "/" + pEntry->d_name; + if (pluginPath.getPathExtension() == ".so") { + if (loadFactoryForSchemeFromPath(pluginPath, CA_system_id, library, factory)) { + mCASystemIdToLibraryPathMap.add(CA_system_id, pluginPath); + closedir(pDir); + + return true; + } + } + } + + closedir(pDir); + + ALOGE("Failed to find plugin"); + return false; +} + +template +bool FactoryLoader::enumeratePlugins(vector* results) { + ALOGI("enumeratePlugins"); + + results->clear(); + + String8 dirPath("/vendor/lib/mediacas"); + DIR* pDir = opendir(dirPath.string()); + + if (pDir == NULL) { + ALOGE("Failed to open plugin directory %s", dirPath.string()); + return false; + } + + Mutex::Autolock autoLock(mMapLock); + + struct dirent* pEntry; + while ((pEntry = readdir(pDir))) { + String8 pluginPath = dirPath + "/" + pEntry->d_name; + if (pluginPath.getPathExtension() == ".so") { + queryPluginsFromPath(pluginPath, results); + } + } + return true; +} + +template +bool FactoryLoader::loadFactoryForSchemeFromPath(const String8& path, int32_t CA_system_id, + sp* library, T** factory) { + closeFactory(); + + if (!openFactory(path) || !mFactory->isSystemIdSupported(CA_system_id)) { + closeFactory(); + return false; + } + + if (library != NULL) { + *library = mLibrary; + } + if (factory != NULL) { + *factory = mFactory; + } + return true; +} + +template +bool FactoryLoader::queryPluginsFromPath(const String8& path, + vector* results) { + closeFactory(); + + vector descriptors; + if (!openFactory(path) || mFactory->queryPlugins(&descriptors) != OK) { + closeFactory(); + return false; + } + + for (auto it = descriptors.begin(); it != descriptors.end(); it++) { + results->push_back( + HidlCasPluginDescriptor{.caSystemId = it->CA_system_id, .name = it->name.c_str()}); + } + return true; +} + +template +bool FactoryLoader::openFactory(const String8& path) { + // get strong pointer to open shared library + ssize_t index = mLibraryPathToOpenLibraryMap.indexOfKey(path); + if (index >= 0) { + mLibrary = mLibraryPathToOpenLibraryMap[index].promote(); + } else { + index = mLibraryPathToOpenLibraryMap.add(path, NULL); + } + + if (!mLibrary.get()) { + mLibrary = new SharedLibrary(path); + if (!*mLibrary) { + return false; + } + + mLibraryPathToOpenLibraryMap.replaceValueAt(index, mLibrary); + } + + CreateFactoryFunc createFactory = (CreateFactoryFunc)mLibrary->lookup(mCreateFactoryFuncName); + if (createFactory == NULL || (mFactory = createFactory()) == NULL) { + return false; + } + return true; +} + +template +void FactoryLoader::closeFactory() { + delete mFactory; + mFactory = NULL; + mLibrary.clear(); +} + +} // namespace implementation +} // namespace V1_1 +} // namespace cas +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_CAS_V1_1_FACTORY_LOADER_H_ diff --git a/cas/1.1/default/MediaCasService.cpp b/cas/1.1/default/MediaCasService.cpp new file mode 100644 index 0000000000..e2d3357023 --- /dev/null +++ b/cas/1.1/default/MediaCasService.cpp @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "android.hardware.cas@1.1-MediaCasService" + +#include +#include +#include +#include + +#include "CasImpl.h" +#include "DescramblerImpl.h" +#include "MediaCasService.h" + +namespace android { +namespace hardware { +namespace cas { +namespace V1_1 { +namespace implementation { + +MediaCasService::MediaCasService() + : mCasLoader("createCasFactory"), mDescramblerLoader("createDescramblerFactory") {} + +MediaCasService::~MediaCasService() {} + +Return MediaCasService::enumeratePlugins(enumeratePlugins_cb _hidl_cb) { + ALOGV("%s", __FUNCTION__); + + vector results; + mCasLoader.enumeratePlugins(&results); + + _hidl_cb(results); + return Void(); +} + +Return MediaCasService::isSystemIdSupported(int32_t CA_system_id) { + ALOGV("isSystemIdSupported: CA_system_id=%d", CA_system_id); + + return mCasLoader.findFactoryForScheme(CA_system_id); +} + +Return> MediaCasService::createPlugin(int32_t /* CA_system_id */, + const sp& /* listener */) { + ALOGE("%s:Use createPluginExt to create plugin with cas@1.1", __FUNCTION__); + + sp result; + /* + CasFactory *factory; + sp library; + if (mCasLoader.findFactoryForScheme(CA_system_id, &library, &factory)) { + CasPlugin *plugin = NULL; + sp casImpl = new CasImpl(listener); + if (factory->createPlugin(CA_system_id, casImpl.get(), + CasImpl::OnEvent, &plugin) == OK && plugin != NULL) { + casImpl->init(library, plugin); + result = casImpl; + } + } + */ + return result; +} + +Return> MediaCasService::createPluginExt(int32_t CA_system_id, + const sp& listener) { + ALOGV("%s: CA_system_id=%d", __FUNCTION__, CA_system_id); + + sp result; + + CasFactory* factory; + sp library; + if (mCasLoader.findFactoryForScheme(CA_system_id, &library, &factory)) { + CasPlugin* plugin = NULL; + sp casImpl = new CasImpl(listener); + if (factory->createPlugin(CA_system_id, casImpl.get(), &CasImpl::CallBackExt, &plugin) == + OK && + plugin != NULL) { + casImpl->init(library, plugin); + result = casImpl; + } + } + + return result; +} + +Return MediaCasService::isDescramblerSupported(int32_t CA_system_id) { + ALOGV("%s: CA_system_id=%d", __FUNCTION__, CA_system_id); + + return mDescramblerLoader.findFactoryForScheme(CA_system_id); +} + +Return> MediaCasService::createDescrambler(int32_t CA_system_id) { + ALOGV("%s: CA_system_id=%d", __FUNCTION__, CA_system_id); + + sp result; + + DescramblerFactory* factory; + sp library; + if (mDescramblerLoader.findFactoryForScheme(CA_system_id, &library, &factory)) { + DescramblerPlugin* plugin = NULL; + if (factory->createPlugin(CA_system_id, &plugin) == OK && plugin != NULL) { + result = new DescramblerImpl(library, plugin); + } + } + + return result; +} + +} // namespace implementation +} // namespace V1_1 +} // namespace cas +} // namespace hardware +} // namespace android diff --git a/cas/1.1/default/MediaCasService.h b/cas/1.1/default/MediaCasService.h new file mode 100644 index 0000000000..ec5a86d9b3 --- /dev/null +++ b/cas/1.1/default/MediaCasService.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2019 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_CAS_V1_1_MEDIA_CAS_SERVICE_H_ +#define ANDROID_HARDWARE_CAS_V1_1_MEDIA_CAS_SERVICE_H_ + +#include + +#include "FactoryLoader.h" + +namespace android { +struct CasFactory; +struct DescramblerFactory; +namespace hardware { +namespace cas { +namespace V1_1 { +namespace implementation { + +using ::android::hardware::cas::V1_0::HidlCasPluginDescriptor; +using ::android::hardware::cas::V1_0::IDescramblerBase; + +class MediaCasService : public IMediaCasService { + public: + MediaCasService(); + + virtual Return enumeratePlugins(enumeratePlugins_cb _hidl_cb) override; + + virtual Return isSystemIdSupported(int32_t CA_system_id) override; + + virtual Return> createPlugin(int32_t CA_system_id, + const sp& listener) override; + + virtual Return> createPluginExt(int32_t CA_system_id, + const sp& listener) override; + + virtual Return isDescramblerSupported(int32_t CA_system_id) override; + + virtual Return> createDescrambler(int32_t CA_system_id) override; + + private: + FactoryLoader mCasLoader; + FactoryLoader mDescramblerLoader; + + virtual ~MediaCasService(); +}; + +} // namespace implementation +} // namespace V1_1 +} // namespace cas +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_CAS_V1_1_MEDIA_CAS_SERVICE_H_ diff --git a/cas/1.1/default/SharedLibrary.cpp b/cas/1.1/default/SharedLibrary.cpp new file mode 100644 index 0000000000..ffe4bb977a --- /dev/null +++ b/cas/1.1/default/SharedLibrary.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "android.hardware.cas@1.1-SharedLibrary" + +#include "SharedLibrary.h" +#include +#include +#include + +namespace android { +namespace hardware { +namespace cas { +namespace V1_1 { +namespace implementation { + +SharedLibrary::SharedLibrary(const String8& path) { + mLibHandle = dlopen(path.string(), RTLD_NOW); +} + +SharedLibrary::~SharedLibrary() { + if (mLibHandle != NULL) { + dlclose(mLibHandle); + mLibHandle = NULL; + } +} + +bool SharedLibrary::operator!() const { + return mLibHandle == NULL; +} + +void* SharedLibrary::lookup(const char* symbol) const { + if (!mLibHandle) { + return NULL; + } + // Clear last error before we load the symbol again, + // in case the caller didn't retrieve it. + (void)dlerror(); + return dlsym(mLibHandle, symbol); +} + +const char* SharedLibrary::lastError() const { + const char* error = dlerror(); + return error ? error : "No errors or unknown error"; +} + +} // namespace implementation +} // namespace V1_1 +} // namespace cas +} // namespace hardware +} // namespace android diff --git a/cas/1.1/default/SharedLibrary.h b/cas/1.1/default/SharedLibrary.h new file mode 100644 index 0000000000..f4d2ff6b9d --- /dev/null +++ b/cas/1.1/default/SharedLibrary.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2019 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_CAS_V1_1_SHARED_LIBRARY_H_ +#define ANDROID_HARDWARE_CAS_V1_1_SHARED_LIBRARY_H_ + +#include +#include +#include + +namespace android { +namespace hardware { +namespace cas { +namespace V1_1 { +namespace implementation { + +class SharedLibrary : public RefBase { + public: + explicit SharedLibrary(const String8& path); + ~SharedLibrary(); + + bool operator!() const; + void* lookup(const char* symbol) const; + const char* lastError() const; + + private: + void* mLibHandle; + DISALLOW_EVIL_CONSTRUCTORS(SharedLibrary); +}; + +} // namespace implementation +} // namespace V1_1 +} // namespace cas +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_CAS_V1_1_SHARED_LIBRARY_H_ diff --git a/cas/1.1/default/TypeConvert.cpp b/cas/1.1/default/TypeConvert.cpp new file mode 100644 index 0000000000..09ef41ae8f --- /dev/null +++ b/cas/1.1/default/TypeConvert.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "android.hardware.cas@1.1-TypeConvert" + +#include "TypeConvert.h" +#include + +namespace android { +namespace hardware { +namespace cas { +namespace V1_1 { +namespace implementation { + +Status toStatus(status_t legacyStatus) { + Status status; + switch (legacyStatus) { + case android::OK: + status = Status::OK; + break; + case android::ERROR_CAS_NO_LICENSE: + status = Status::ERROR_CAS_NO_LICENSE; + break; + case android::ERROR_CAS_LICENSE_EXPIRED: + status = Status::ERROR_CAS_LICENSE_EXPIRED; + break; + case android::ERROR_CAS_SESSION_NOT_OPENED: + status = Status::ERROR_CAS_SESSION_NOT_OPENED; + break; + case android::ERROR_CAS_CANNOT_HANDLE: + status = Status::ERROR_CAS_CANNOT_HANDLE; + break; + case android::ERROR_CAS_TAMPER_DETECTED: + status = Status::ERROR_CAS_INVALID_STATE; + break; + case android::BAD_VALUE: + status = Status::BAD_VALUE; + break; + case android::ERROR_CAS_NOT_PROVISIONED: + status = Status::ERROR_CAS_NOT_PROVISIONED; + break; + case android::ERROR_CAS_RESOURCE_BUSY: + status = Status::ERROR_CAS_RESOURCE_BUSY; + break; + case android::ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION: + status = Status::ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION; + break; + case android::ERROR_CAS_DEVICE_REVOKED: + status = Status::ERROR_CAS_DEVICE_REVOKED; + break; + case android::ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED: + status = Status::ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED; + break; + case android::ERROR_CAS_DECRYPT: + status = Status::ERROR_CAS_DECRYPT; + break; + default: + ALOGW("Unable to convert legacy status: %d, defaulting to UNKNOWN", legacyStatus); + status = Status::ERROR_CAS_UNKNOWN; + break; + } + return status; +} + +String8 sessionIdToString(const CasSessionId& sessionId) { + String8 result; + for (size_t i = 0; i < sessionId.size(); i++) { + result.appendFormat("%02x ", sessionId[i]); + } + if (result.isEmpty()) { + result.append("(null)"); + } + return result; +} + +} // namespace implementation +} // namespace V1_1 +} // namespace cas +} // namespace hardware +} // namespace android diff --git a/cas/1.1/default/TypeConvert.h b/cas/1.1/default/TypeConvert.h new file mode 100644 index 0000000000..c4a0119926 --- /dev/null +++ b/cas/1.1/default/TypeConvert.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2019 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_CAS_V1_1_TYPE_CONVERT_H +#define ANDROID_HARDWARE_CAS_V1_1_TYPE_CONVERT_H + +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace cas { +namespace V1_1 { +namespace implementation { + +using ::android::hardware::cas::V1_0::Status; + +Status toStatus(status_t legacyStatus); + +String8 sessionIdToString(const CasSessionId& sessionId); + +} // namespace implementation +} // namespace V1_1 +} // namespace cas +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_CAS_V1_1_TYPE_CONVERT_H diff --git a/cas/1.1/default/android.hardware.cas@1.1-service-lazy.rc b/cas/1.1/default/android.hardware.cas@1.1-service-lazy.rc new file mode 100644 index 0000000000..9227b6f7e4 --- /dev/null +++ b/cas/1.1/default/android.hardware.cas@1.1-service-lazy.rc @@ -0,0 +1,9 @@ +service vendor.cas-hal-1-1 /vendor/bin/hw/android.hardware.cas@1.1-service-lazy + interface android.hardware.cas@1.1::IMediaCasService default + oneshot + disabled + class hal + user media + group mediadrm drmrpc + ioprio rt 4 + writepid /dev/cpuset/foreground/tasks diff --git a/cas/1.1/default/android.hardware.cas@1.1-service-lazy.xml b/cas/1.1/default/android.hardware.cas@1.1-service-lazy.xml new file mode 100644 index 0000000000..c9f13ba34a --- /dev/null +++ b/cas/1.1/default/android.hardware.cas@1.1-service-lazy.xml @@ -0,0 +1,11 @@ + + + android.hardware.cas + hwbinder + 1.1 + + IMediaCasService + default + + + diff --git a/cas/1.1/default/android.hardware.cas@1.1-service.rc b/cas/1.1/default/android.hardware.cas@1.1-service.rc new file mode 100644 index 0000000000..4081fe1e64 --- /dev/null +++ b/cas/1.1/default/android.hardware.cas@1.1-service.rc @@ -0,0 +1,6 @@ +service vendor.cas-hal-1-1 /vendor/bin/hw/android.hardware.cas@1.1-service + class hal + user media + group mediadrm drmrpc + ioprio rt 4 + writepid /dev/cpuset/foreground/tasks diff --git a/cas/1.1/default/android.hardware.cas@1.1-service.xml b/cas/1.1/default/android.hardware.cas@1.1-service.xml new file mode 100644 index 0000000000..c9f13ba34a --- /dev/null +++ b/cas/1.1/default/android.hardware.cas@1.1-service.xml @@ -0,0 +1,11 @@ + + + android.hardware.cas + hwbinder + 1.1 + + IMediaCasService + default + + + diff --git a/cas/1.1/default/service.cpp b/cas/1.1/default/service.cpp new file mode 100644 index 0000000000..962530370c --- /dev/null +++ b/cas/1.1/default/service.cpp @@ -0,0 +1,58 @@ +/* + * Copyright 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#ifdef LAZY_SERVICE +#define LOG_TAG "android.hardware.cas@1.1-service-lazy" +#else +#define LOG_TAG "android.hardware.cas@1.1-service" +#endif + +#include +#include +#include + +#include "MediaCasService.h" + +using android::hardware::configureRpcThreadpool; +using android::hardware::joinRpcThreadpool; +using android::hardware::LazyServiceRegistrar; +using android::hardware::cas::V1_1::IMediaCasService; +using android::hardware::cas::V1_1::implementation::MediaCasService; + +#ifdef LAZY_SERVICE +const bool kLazyService = true; +#else +const bool kLazyService = false; +#endif + +int main() { + configureRpcThreadpool(8, true /* callerWillJoin */); + + // Setup hwbinder service + android::sp service = new MediaCasService(); + android::status_t status; + if (kLazyService) { + auto serviceRegistrar = std::make_shared(); + status = serviceRegistrar->registerService(service); + } else { + status = service->registerAsService(); + } + LOG_ALWAYS_FATAL_IF(status != android::OK, "Error while registering cas service: %d", status); + + joinRpcThreadpool(); + return 0; +} diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml index 94ffe80aab..89855a0e65 100644 --- a/compatibility_matrices/compatibility_matrix.current.xml +++ b/compatibility_matrices/compatibility_matrix.current.xml @@ -121,7 +121,7 @@
android.hardware.cas - 1.0 + 1.0-1 IMediaCasService default From 3405878e5e0eb85549363b69b8dffb3f91c7b8ff Mon Sep 17 00:00:00 2001 From: Xusong Wang Date: Fri, 18 Jan 2019 17:28:26 -0800 Subject: [PATCH 433/718] Add VTS tests for NNAPI compilation caching. Add the following tests for compilation caching: - validation tests - Test isCachingSupported - Test prepareModelFromCache with invalid numFd and invalid access mode - Test saveToCache with invalid numFd, invalid access mode, invalid file size, and invalid fd offset - execution test - Save a mobilenet model to cache and then retrieve and run accuracy evaluation. - The same test but the file offsets for prepareModelFromCache is not at zero. - security test - CompilationCachingSecurityTest.CorruptedSecuritySensitiveCache Randomly flip one bit of security-sensitive cache. - CompilationCachingSecurityTest.WrongLengthSecuritySensitiveCache Randomly append bytes to security-sensitive cache. - CompilationCachingSecurityTest.WrongToken Randomly flip one bit of cache token. Bug: 119616526 Test: VtsHalNeuralnetworksV1_xTargetTest with 1.2 sample driver Test: VtsHalNeuralnetworksV1_xTargetTest with a test driver that can read and write cache entries Change-Id: Iae9211cb28ce972b29572dfedd45d1ade4dfdaf5 --- .../vts/functional/GeneratedTestHarness.cpp | 128 ++-- .../1.0/vts/functional/GeneratedTestHarness.h | 57 ++ .../1.0/vts/functional/GeneratedTests.cpp | 8 +- .../1.1/vts/functional/GeneratedTests.cpp | 8 +- .../1.1/vts/functional/GeneratedTestsV1_0.cpp | 8 +- neuralnetworks/1.2/vts/functional/Android.bp | 1 + .../1.2/vts/functional/BasicTests.cpp | 6 + .../functional/CompilationCachingTests.cpp | 652 ++++++++++++++++++ .../1.2/vts/functional/GeneratedTests.cpp | 9 +- .../1.2/vts/functional/GeneratedTestsV1_0.cpp | 9 +- .../1.2/vts/functional/GeneratedTestsV1_1.cpp | 9 +- 11 files changed, 783 insertions(+), 112 deletions(-) create mode 100644 neuralnetworks/1.0/vts/functional/GeneratedTestHarness.h create mode 100644 neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp index c2ecd9aed6..2e1385497b 100644 --- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp +++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include "GeneratedTestHarness.h" #include "Callbacks.h" #include "ExecutionBurstController.h" #include "TestHarness.h" @@ -364,6 +365,51 @@ void EvaluatePreparedModel(sp& preparedModel, std::function& preparedModel, + std::function is_ignored, + const std::vector& examples, + bool hasRelaxedFloat32Model, bool testDynamicOutputShape) { + if (testDynamicOutputShape) { + EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model, + Executor::ASYNC, MeasureTiming::NO, OutputType::UNSPECIFIED); + EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model, + Executor::SYNC, MeasureTiming::NO, OutputType::UNSPECIFIED); + EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model, + Executor::BURST, MeasureTiming::NO, OutputType::UNSPECIFIED); + EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model, + Executor::ASYNC, MeasureTiming::YES, OutputType::UNSPECIFIED); + EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model, + Executor::SYNC, MeasureTiming::YES, OutputType::UNSPECIFIED); + EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model, + Executor::BURST, MeasureTiming::YES, OutputType::UNSPECIFIED); + EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model, + Executor::ASYNC, MeasureTiming::NO, OutputType::INSUFFICIENT); + EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model, + Executor::SYNC, MeasureTiming::NO, OutputType::INSUFFICIENT); + EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model, + Executor::BURST, MeasureTiming::NO, OutputType::INSUFFICIENT); + EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model, + Executor::ASYNC, MeasureTiming::YES, OutputType::INSUFFICIENT); + EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model, + Executor::SYNC, MeasureTiming::YES, OutputType::INSUFFICIENT); + EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model, + Executor::BURST, MeasureTiming::YES, OutputType::INSUFFICIENT); + } else { + EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model, + Executor::ASYNC, MeasureTiming::NO, OutputType::FULLY_SPECIFIED); + EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model, + Executor::SYNC, MeasureTiming::NO, OutputType::FULLY_SPECIFIED); + EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model, + Executor::BURST, MeasureTiming::NO, OutputType::FULLY_SPECIFIED); + EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model, + Executor::ASYNC, MeasureTiming::YES, OutputType::FULLY_SPECIFIED); + EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model, + Executor::SYNC, MeasureTiming::YES, OutputType::FULLY_SPECIFIED); + EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model, + Executor::BURST, MeasureTiming::YES, OutputType::FULLY_SPECIFIED); + } +} + static void getPreparedModel(sp callback, sp* preparedModel) { *preparedModel = callback->getPreparedModel(); @@ -468,12 +514,8 @@ void Execute(const sp& device, std::function c MeasureTiming::NO, OutputType::FULLY_SPECIFIED); } -// TODO: Reduce code duplication. -void Execute(const sp& device, std::function create_model, - std::function is_ignored, const std::vector& examples, - bool testDynamicOutputShape) { - V1_2::Model model = create_model(); - +void PrepareModel(const sp& device, const V1_2::Model& model, + sp* preparedModel) { // see if service can handle model bool fullySupportsModel = false; Return supportedCall = device->getSupportedOperations_1_2( @@ -496,12 +538,11 @@ void Execute(const sp& device, std::function c // retrieve prepared model preparedModelCallback->wait(); ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus(); - sp preparedModel; - getPreparedModel(preparedModelCallback, &preparedModel); + getPreparedModel(preparedModelCallback, preparedModel); // early termination if vendor service cannot fully prepare model if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) { - ASSERT_EQ(nullptr, preparedModel.get()); + ASSERT_EQ(nullptr, preparedModel->get()); LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot " "prepare model that it does not support."; std::cout << "[ ] Early termination of test because vendor service cannot " @@ -510,65 +551,18 @@ void Execute(const sp& device, std::function c GTEST_SKIP(); } EXPECT_EQ(ErrorStatus::NONE, prepareReturnStatus); - ASSERT_NE(nullptr, preparedModel.get()); + ASSERT_NE(nullptr, preparedModel->get()); +} - if (testDynamicOutputShape) { - EvaluatePreparedModel(preparedModel, is_ignored, examples, - model.relaxComputationFloat32toFloat16, Executor::ASYNC, - MeasureTiming::NO, OutputType::UNSPECIFIED); - EvaluatePreparedModel(preparedModel, is_ignored, examples, - model.relaxComputationFloat32toFloat16, Executor::SYNC, - MeasureTiming::NO, OutputType::UNSPECIFIED); - EvaluatePreparedModel(preparedModel, is_ignored, examples, - model.relaxComputationFloat32toFloat16, Executor::BURST, - MeasureTiming::NO, OutputType::UNSPECIFIED); - EvaluatePreparedModel(preparedModel, is_ignored, examples, - model.relaxComputationFloat32toFloat16, Executor::ASYNC, - MeasureTiming::YES, OutputType::UNSPECIFIED); - EvaluatePreparedModel(preparedModel, is_ignored, examples, - model.relaxComputationFloat32toFloat16, Executor::SYNC, - MeasureTiming::YES, OutputType::UNSPECIFIED); - EvaluatePreparedModel(preparedModel, is_ignored, examples, - model.relaxComputationFloat32toFloat16, Executor::BURST, - MeasureTiming::YES, OutputType::UNSPECIFIED); - EvaluatePreparedModel(preparedModel, is_ignored, examples, - model.relaxComputationFloat32toFloat16, Executor::ASYNC, - MeasureTiming::NO, OutputType::INSUFFICIENT); - EvaluatePreparedModel(preparedModel, is_ignored, examples, - model.relaxComputationFloat32toFloat16, Executor::SYNC, - MeasureTiming::NO, OutputType::INSUFFICIENT); - EvaluatePreparedModel(preparedModel, is_ignored, examples, - model.relaxComputationFloat32toFloat16, Executor::BURST, - MeasureTiming::NO, OutputType::INSUFFICIENT); - EvaluatePreparedModel(preparedModel, is_ignored, examples, - model.relaxComputationFloat32toFloat16, Executor::ASYNC, - MeasureTiming::YES, OutputType::INSUFFICIENT); - EvaluatePreparedModel(preparedModel, is_ignored, examples, - model.relaxComputationFloat32toFloat16, Executor::SYNC, - MeasureTiming::YES, OutputType::INSUFFICIENT); - EvaluatePreparedModel(preparedModel, is_ignored, examples, - model.relaxComputationFloat32toFloat16, Executor::BURST, - MeasureTiming::YES, OutputType::INSUFFICIENT); - } else { - EvaluatePreparedModel(preparedModel, is_ignored, examples, - model.relaxComputationFloat32toFloat16, Executor::ASYNC, - MeasureTiming::NO, OutputType::FULLY_SPECIFIED); - EvaluatePreparedModel(preparedModel, is_ignored, examples, - model.relaxComputationFloat32toFloat16, Executor::SYNC, - MeasureTiming::NO, OutputType::FULLY_SPECIFIED); - EvaluatePreparedModel(preparedModel, is_ignored, examples, - model.relaxComputationFloat32toFloat16, Executor::BURST, - MeasureTiming::NO, OutputType::FULLY_SPECIFIED); - EvaluatePreparedModel(preparedModel, is_ignored, examples, - model.relaxComputationFloat32toFloat16, Executor::ASYNC, - MeasureTiming::YES, OutputType::FULLY_SPECIFIED); - EvaluatePreparedModel(preparedModel, is_ignored, examples, - model.relaxComputationFloat32toFloat16, Executor::SYNC, - MeasureTiming::YES, OutputType::FULLY_SPECIFIED); - EvaluatePreparedModel(preparedModel, is_ignored, examples, - model.relaxComputationFloat32toFloat16, Executor::BURST, - MeasureTiming::YES, OutputType::FULLY_SPECIFIED); - } +// TODO: Reduce code duplication. +void Execute(const sp& device, std::function create_model, + std::function is_ignored, const std::vector& examples, + bool testDynamicOutputShape) { + V1_2::Model model = create_model(); + sp preparedModel = nullptr; + PrepareModel(device, model, &preparedModel); + EvaluatePreparedModel(preparedModel, is_ignored, examples, + model.relaxComputationFloat32toFloat16, testDynamicOutputShape); } } // namespace generated_tests diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.h b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.h new file mode 100644 index 0000000000..c7d23993f4 --- /dev/null +++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2019 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 VTS_HAL_NEURALNETWORKS_GENERATED_TEST_HARNESS_H +#define VTS_HAL_NEURALNETWORKS_GENERATED_TEST_HARNESS_H + +#include "TestHarness.h" + +#include +#include +#include + +namespace android { +namespace hardware { +namespace neuralnetworks { + +namespace generated_tests { +using ::test_helper::MixedTypedExample; + +void PrepareModel(const sp& device, const V1_2::Model& model, + sp* preparedModel); + +void EvaluatePreparedModel(sp& preparedModel, + std::function is_ignored, + const std::vector& examples, + bool hasRelaxedFloat32Model, bool testDynamicOutputShape); + +void Execute(const sp& device, std::function create_model, + std::function is_ignored, const std::vector& examples); + +void Execute(const sp& device, std::function create_model, + std::function is_ignored, const std::vector& examples); + +void Execute(const sp& device, std::function create_model, + std::function is_ignored, const std::vector& examples, + bool testDynamicOutputShape = false); + +} // namespace generated_tests + +} // namespace neuralnetworks +} // namespace hardware +} // namespace android + +#endif // VTS_HAL_NEURALNETWORKS_GENERATED_TEST_HARNESS_H diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTests.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTests.cpp index 55e5861dec..d1c7de322f 100644 --- a/neuralnetworks/1.0/vts/functional/GeneratedTests.cpp +++ b/neuralnetworks/1.0/vts/functional/GeneratedTests.cpp @@ -19,6 +19,7 @@ #include "VtsHalNeuralnetworks.h" #include "Callbacks.h" +#include "GeneratedTestHarness.h" #include "TestHarness.h" #include "Utils.h" @@ -29,13 +30,6 @@ namespace android { namespace hardware { namespace neuralnetworks { - -namespace generated_tests { -using ::test_helper::MixedTypedExample; -extern void Execute(const sp&, std::function, - std::function, const std::vector&); -} // namespace generated_tests - namespace V1_0 { namespace vts { namespace functional { diff --git a/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp b/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp index d98ea04310..4db12769a7 100644 --- a/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp +++ b/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp @@ -19,6 +19,7 @@ #include "VtsHalNeuralnetworks.h" #include "Callbacks.h" +#include "GeneratedTestHarness.h" #include "TestHarness.h" #include "Utils.h" @@ -29,13 +30,6 @@ namespace android { namespace hardware { namespace neuralnetworks { - -namespace generated_tests { -using ::test_helper::MixedTypedExample; -extern void Execute(const sp&, std::function, - std::function, const std::vector&); -} // namespace generated_tests - namespace V1_1 { namespace vts { namespace functional { diff --git a/neuralnetworks/1.1/vts/functional/GeneratedTestsV1_0.cpp b/neuralnetworks/1.1/vts/functional/GeneratedTestsV1_0.cpp index 1df3218feb..e67ef8ed98 100644 --- a/neuralnetworks/1.1/vts/functional/GeneratedTestsV1_0.cpp +++ b/neuralnetworks/1.1/vts/functional/GeneratedTestsV1_0.cpp @@ -19,6 +19,7 @@ #include "VtsHalNeuralnetworks.h" #include "Callbacks.h" +#include "GeneratedTestHarness.h" #include "TestHarness.h" #include "Utils.h" @@ -29,13 +30,6 @@ namespace android { namespace hardware { namespace neuralnetworks { - -namespace generated_tests { -using ::test_helper::MixedTypedExample; -extern void Execute(const sp&, std::function, - std::function, const std::vector&); -} // namespace generated_tests - namespace V1_1 { namespace vts { namespace functional { diff --git a/neuralnetworks/1.2/vts/functional/Android.bp b/neuralnetworks/1.2/vts/functional/Android.bp index 0cb9e16fcf..510a0d5b3c 100644 --- a/neuralnetworks/1.2/vts/functional/Android.bp +++ b/neuralnetworks/1.2/vts/functional/Android.bp @@ -46,6 +46,7 @@ cc_test { defaults: ["VtsHalNeuralNetworksTargetTestDefaults"], srcs: [ "BasicTests.cpp", + "CompilationCachingTests.cpp", "GeneratedTests.cpp", ], cflags: [ diff --git a/neuralnetworks/1.2/vts/functional/BasicTests.cpp b/neuralnetworks/1.2/vts/functional/BasicTests.cpp index 0eec3656e7..2b88edd0f6 100644 --- a/neuralnetworks/1.2/vts/functional/BasicTests.cpp +++ b/neuralnetworks/1.2/vts/functional/BasicTests.cpp @@ -72,6 +72,12 @@ TEST_F(NeuralnetworksHidlTest, GetDeviceSupportedExtensionsTest) { EXPECT_TRUE(ret.isOk()); } +// isCachingSupported test +TEST_F(NeuralnetworksHidlTest, IsCachingSupported) { + Return ret = device->isCachingSupported( + [](ErrorStatus status, bool) { EXPECT_EQ(ErrorStatus::NONE, status); }); + EXPECT_TRUE(ret.isOk()); +} } // namespace functional } // namespace vts } // namespace V1_2 diff --git a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp new file mode 100644 index 0000000000..454aa1f921 --- /dev/null +++ b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp @@ -0,0 +1,652 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "neuralnetworks_hidl_hal_test" + +#include "VtsHalNeuralnetworks.h" + +#include "Callbacks.h" +#include "GeneratedTestHarness.h" +#include "TestHarness.h" +#include "Utils.h" + +#include +#include +#include +#include +#include +#include + +#include + +namespace android { +namespace hardware { +namespace neuralnetworks { +namespace V1_2 { +namespace vts { +namespace functional { + +using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback; +using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback; +using ::android::nn::allocateSharedMemory; +using ::test_helper::MixedTypedExample; + +namespace { + +// In frameworks/ml/nn/runtime/tests/generated/, creates a hidl model of mobilenet. +#include "examples/mobilenet_224_gender_basic_fixed.example.cpp" +#include "vts_models/mobilenet_224_gender_basic_fixed.model.cpp" + +// Prevent the compiler from complaining about an otherwise unused function. +[[maybe_unused]] auto dummy_createTestModel = createTestModel_dynamic_output_shape; +[[maybe_unused]] auto dummy_get_examples = get_examples_dynamic_output_shape; + +enum class AccessMode { READ_ONLY, WRITE_ONLY }; + +void createCacheHandle(const std::vector& files, AccessMode mode, + hidl_handle* handle) { + std::vector fds; + for (const auto& file : files) { + int fd; + if (mode == AccessMode::READ_ONLY) { + fd = open(file.c_str(), O_RDONLY); + } else if (mode == AccessMode::WRITE_ONLY) { + fd = open(file.c_str(), O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR); + } else { + FAIL(); + } + ASSERT_GE(fd, 0); + fds.push_back(fd); + } + native_handle_t* cacheNativeHandle = native_handle_create(fds.size(), 0); + ASSERT_NE(cacheNativeHandle, nullptr); + for (uint32_t i = 0; i < fds.size(); i++) { + cacheNativeHandle->data[i] = fds[i]; + } + handle->setTo(cacheNativeHandle, /*shouldOwn=*/true); +} + +} // namespace + +// Tag for the compilation caching tests. +class CompilationCachingTest : public NeuralnetworksHidlTest { + protected: + void SetUp() override { + NeuralnetworksHidlTest::SetUp(); + + // Create cache directory. + char cacheDirTemp[] = "/data/local/tmp/TestCompilationCachingXXXXXX"; + char* cacheDir = mkdtemp(cacheDirTemp); + ASSERT_NE(cacheDir, nullptr); + mCache1 = cacheDir + mCache1; + mCache2 = cacheDir + mCache2; + mCache3 = cacheDir + mCache3; + + // Check if caching is supported. + bool isCachingSupported; + Return ret = device->isCachingSupported( + [&isCachingSupported](ErrorStatus status, bool supported) { + EXPECT_EQ(ErrorStatus::NONE, status); + isCachingSupported = supported; + }); + EXPECT_TRUE(ret.isOk()); + if (isCachingSupported) { + mIsCachingSupported = true; + } else { + LOG(INFO) << "NN VTS: Early termination of test because vendor service does not " + "support compilation caching."; + std::cout << "[ ] Early termination of test because vendor service does not " + "support compilation caching." + << std::endl; + mIsCachingSupported = false; + } + + // Create empty cache files. + hidl_handle handle; + createCacheHandle({mCache1, mCache2, mCache3}, AccessMode::WRITE_ONLY, &handle); + } + + void saveModelToCache(sp preparedModel, const hidl_handle& cache1, + const hidl_handle& cache2, ErrorStatus* status) { + // Save IPreparedModel to cache. + hidl_array cacheToken(mToken); + Return saveToCacheStatus = + preparedModel->saveToCache(cache1, cache2, cacheToken); + ASSERT_TRUE(saveToCacheStatus.isOk()); + *status = static_cast(saveToCacheStatus); + } + + bool checkEarlyTermination(ErrorStatus status) { + if (status == ErrorStatus::GENERAL_FAILURE) { + LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot " + "save the prepared model that it does not support."; + std::cout << "[ ] Early termination of test because vendor service cannot " + "save the prepared model that it does not support." + << std::endl; + return true; + } + return false; + } + + void prepareModelFromCache(const hidl_handle& cache1, const hidl_handle& cache2, + sp* preparedModel, ErrorStatus* status) { + // Launch prepare model from cache. + sp preparedModelCallback = new PreparedModelCallback(); + ASSERT_NE(nullptr, preparedModelCallback.get()); + hidl_array cacheToken(mToken); + Return prepareLaunchStatus = + device->prepareModelFromCache(cache1, cache2, cacheToken, preparedModelCallback); + ASSERT_TRUE(prepareLaunchStatus.isOk()); + if (static_cast(prepareLaunchStatus) != ErrorStatus::NONE) { + *preparedModel = nullptr; + *status = static_cast(prepareLaunchStatus); + return; + } + + // Retrieve prepared model. + preparedModelCallback->wait(); + *status = preparedModelCallback->getStatus(); + *preparedModel = V1_2::IPreparedModel::castFrom(preparedModelCallback->getPreparedModel()) + .withDefault(nullptr); + } + + std::string mCache1 = "/cache1"; + std::string mCache2 = "/cache2"; + std::string mCache3 = "/cache3"; + uint8_t mToken[static_cast(Constant::BYTE_SIZE_OF_CACHE_TOKEN)] = {}; + bool mIsCachingSupported; +}; + +TEST_F(CompilationCachingTest, CacheSavingAndRetrieval) { + // Create test HIDL model and compile. + Model testModel = createTestModel(); + sp preparedModel = nullptr; + generated_tests::PrepareModel(device, testModel, &preparedModel); + // Terminate early if the driver cannot prepare the model. + if (preparedModel == nullptr) return; + + // Save the compilation to cache. + { + ErrorStatus status; + hidl_handle cache1, cache2; + createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1); + createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2); + saveModelToCache(preparedModel, cache1, cache2, &status); + if (!mIsCachingSupported) { + EXPECT_EQ(status, ErrorStatus::GENERAL_FAILURE); + } else { + if (checkEarlyTermination(status)) return; + ASSERT_EQ(status, ErrorStatus::NONE); + } + } + + // Retrieve preparedModel from cache. + { + preparedModel = nullptr; + ErrorStatus status; + hidl_handle cache1, cache2; + createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1); + createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2); + prepareModelFromCache(cache1, cache2, &preparedModel, &status); + if (!mIsCachingSupported) { + ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); + ASSERT_EQ(preparedModel, nullptr); + return; + } else { + ASSERT_EQ(status, ErrorStatus::NONE); + ASSERT_NE(preparedModel, nullptr); + } + } + + // Execute and verify results. + generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; }, get_examples(), + testModel.relaxComputationFloat32toFloat16, + /*testDynamicOutputShape=*/false); +} + +TEST_F(CompilationCachingTest, CacheSavingAndRetrievalNonZeroOffset) { + // Create test HIDL model and compile. + Model testModel = createTestModel(); + sp preparedModel = nullptr; + generated_tests::PrepareModel(device, testModel, &preparedModel); + // Terminate early if the driver cannot prepare the model. + if (preparedModel == nullptr) return; + + // Save the compilation to cache. + { + ErrorStatus status; + hidl_handle cache1, cache2; + createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1); + createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2); + saveModelToCache(preparedModel, cache1, cache2, &status); + if (!mIsCachingSupported) { + EXPECT_EQ(status, ErrorStatus::GENERAL_FAILURE); + } else { + if (checkEarlyTermination(status)) return; + ASSERT_EQ(status, ErrorStatus::NONE); + } + } + + // Retrieve preparedModel from cache. + { + preparedModel = nullptr; + ErrorStatus status; + hidl_handle cache1, cache2; + createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1); + createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2); + uint8_t dummyByte = 0; + // Advance offset by one byte. + ASSERT_GE(read(cache1.getNativeHandle()->data[0], &dummyByte, 1), 0); + ASSERT_GE(read(cache2.getNativeHandle()->data[0], &dummyByte, 1), 0); + prepareModelFromCache(cache1, cache2, &preparedModel, &status); + if (!mIsCachingSupported) { + ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); + ASSERT_EQ(preparedModel, nullptr); + return; + } else { + ASSERT_EQ(status, ErrorStatus::NONE); + ASSERT_NE(preparedModel, nullptr); + } + } + + // Execute and verify results. + generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; }, get_examples(), + testModel.relaxComputationFloat32toFloat16, + /*testDynamicOutputShape=*/false); +} + +TEST_F(CompilationCachingTest, SaveToCacheInvalidNumFd) { + // Create test HIDL model and compile. + Model testModel = createTestModel(); + sp preparedModel = nullptr; + generated_tests::PrepareModel(device, testModel, &preparedModel); + // Terminate early if the driver cannot prepare the model. + if (preparedModel == nullptr) return; + + // cache1 with invalid NumFd. + { + ErrorStatus status; + hidl_handle cache1, cache2; + createCacheHandle({mCache1, mCache3}, AccessMode::WRITE_ONLY, &cache1); + createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2); + saveModelToCache(preparedModel, cache1, cache2, &status); + if (status != ErrorStatus::GENERAL_FAILURE) { + ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT); + } + } + + // cache2 with invalid NumFd. + { + ErrorStatus status; + hidl_handle cache1, cache2; + createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1); + createCacheHandle({mCache2, mCache3}, AccessMode::WRITE_ONLY, &cache2); + saveModelToCache(preparedModel, cache1, cache2, &status); + if (status != ErrorStatus::GENERAL_FAILURE) { + ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT); + } + } +} + +TEST_F(CompilationCachingTest, PrepareModelFromCacheInvalidNumFd) { + // Create test HIDL model and compile. + Model testModel = createTestModel(); + sp preparedModel = nullptr; + generated_tests::PrepareModel(device, testModel, &preparedModel); + // Terminate early if the driver cannot prepare the model. + if (preparedModel == nullptr) return; + + // Save the compilation to cache. + { + ErrorStatus status; + hidl_handle cache1, cache2; + createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1); + createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2); + saveModelToCache(preparedModel, cache1, cache2, &status); + if (status != ErrorStatus::GENERAL_FAILURE) { + ASSERT_EQ(status, ErrorStatus::NONE); + } + } + + // cache1 with invalid NumFd. + { + preparedModel = nullptr; + ErrorStatus status; + hidl_handle cache1, cache2; + createCacheHandle({mCache1, mCache3}, AccessMode::READ_ONLY, &cache1); + createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2); + prepareModelFromCache(cache1, cache2, &preparedModel, &status); + if (status != ErrorStatus::GENERAL_FAILURE) { + ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT); + ASSERT_EQ(preparedModel, nullptr); + } + } + + // cache2 with invalid NumFd. + { + preparedModel = nullptr; + ErrorStatus status; + hidl_handle cache1, cache2; + createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1); + createCacheHandle({mCache2, mCache3}, AccessMode::READ_ONLY, &cache2); + prepareModelFromCache(cache1, cache2, &preparedModel, &status); + if (status != ErrorStatus::GENERAL_FAILURE) { + ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT); + ASSERT_EQ(preparedModel, nullptr); + } + } +} + +TEST_F(CompilationCachingTest, SaveToCacheInvalidAccessMode) { + // Create test HIDL model and compile. + Model testModel = createTestModel(); + sp preparedModel = nullptr; + generated_tests::PrepareModel(device, testModel, &preparedModel); + // Terminate early if the driver cannot prepare the model. + if (preparedModel == nullptr) return; + + // cache1 with invalid access mode. + { + ErrorStatus status; + hidl_handle cache1, cache2; + createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1); + createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2); + saveModelToCache(preparedModel, cache1, cache2, &status); + ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); + } + + // cache2 with invalid access mode. + { + ErrorStatus status; + hidl_handle cache1, cache2; + createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1); + createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2); + saveModelToCache(preparedModel, cache1, cache2, &status); + ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); + } +} + +TEST_F(CompilationCachingTest, PrepareModelFromCacheInvalidAccessMode) { + // Create test HIDL model and compile. + Model testModel = createTestModel(); + sp preparedModel = nullptr; + generated_tests::PrepareModel(device, testModel, &preparedModel); + // Terminate early if the driver cannot prepare the model. + if (preparedModel == nullptr) return; + + // Save the compilation to cache. + { + ErrorStatus status; + hidl_handle cache1, cache2; + createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1); + createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2); + saveModelToCache(preparedModel, cache1, cache2, &status); + if (status != ErrorStatus::GENERAL_FAILURE) { + ASSERT_EQ(status, ErrorStatus::NONE); + } + } + + // cache1 with invalid access mode. + { + preparedModel = nullptr; + ErrorStatus status; + hidl_handle cache1, cache2; + createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1); + createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2); + prepareModelFromCache(cache1, cache2, &preparedModel, &status); + ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); + ASSERT_EQ(preparedModel, nullptr); + } + + // cache2 with invalid access mode. + { + preparedModel = nullptr; + ErrorStatus status; + hidl_handle cache1, cache2; + createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1); + createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2); + prepareModelFromCache(cache1, cache2, &preparedModel, &status); + ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); + ASSERT_EQ(preparedModel, nullptr); + } +} + +TEST_F(CompilationCachingTest, SaveToCacheInvalidOffset) { + // Create test HIDL model and compile. + Model testModel = createTestModel(); + sp preparedModel = nullptr; + generated_tests::PrepareModel(device, testModel, &preparedModel); + // Terminate early if the driver cannot prepare the model. + if (preparedModel == nullptr) return; + + // cache1 with invalid file descriptor offset. + { + ErrorStatus status; + hidl_handle cache1, cache2; + createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1); + createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2); + uint8_t dummyByte = 0; + // Advance offset by one byte. + ASSERT_EQ(write(cache1.getNativeHandle()->data[0], &dummyByte, 1), 1); + saveModelToCache(preparedModel, cache1, cache2, &status); + ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); + } + + // cache2 with invalid file descriptor offset. + { + ErrorStatus status; + hidl_handle cache1, cache2; + createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1); + createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2); + uint8_t dummyByte = 0; + // Advance offset by one byte. + ASSERT_EQ(write(cache2.getNativeHandle()->data[0], &dummyByte, 1), 1); + saveModelToCache(preparedModel, cache1, cache2, &status); + ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); + } +} + +TEST_F(CompilationCachingTest, SaveToCacheInvalidFileSize) { + // Create test HIDL model and compile. + Model testModel = createTestModel(); + sp preparedModel = nullptr; + generated_tests::PrepareModel(device, testModel, &preparedModel); + // Terminate early if the driver cannot prepare the model. + if (preparedModel == nullptr) return; + + // cache1 with invalid file size. + { + ErrorStatus status; + hidl_handle cache1, cache2; + createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1); + createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2); + uint8_t dummyByte = 0; + // Write one byte and seek back to the beginning. + ASSERT_EQ(write(cache1.getNativeHandle()->data[0], &dummyByte, 1), 1); + ASSERT_EQ(lseek(cache1.getNativeHandle()->data[0], 0, SEEK_SET), 0); + saveModelToCache(preparedModel, cache1, cache2, &status); + ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); + } + + // cache2 with invalid file size. + { + ErrorStatus status; + hidl_handle cache1, cache2; + createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1); + createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2); + uint8_t dummyByte = 0; + // Write one byte and seek back to the beginning. + ASSERT_EQ(write(cache2.getNativeHandle()->data[0], &dummyByte, 1), 1); + ASSERT_EQ(lseek(cache2.getNativeHandle()->data[0], 0, SEEK_SET), 0); + saveModelToCache(preparedModel, cache1, cache2, &status); + ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); + } +} + +class CompilationCachingSecurityTest : public CompilationCachingTest, + public ::testing::WithParamInterface { + protected: + void SetUp() { + CompilationCachingTest::SetUp(); + generator.seed(kSeed); + } + + // Get a random integer within a closed range [lower, upper]. + template + T getRandomInt(T lower, T upper) { + std::uniform_int_distribution dis(lower, upper); + return dis(generator); + } + + const uint32_t kSeed = GetParam(); + std::mt19937 generator; +}; + +TEST_P(CompilationCachingSecurityTest, CorruptedSecuritySensitiveCache) { + if (!mIsCachingSupported) return; + + // Create test HIDL model and compile. + Model testModel = createTestModel(); + sp preparedModel = nullptr; + generated_tests::PrepareModel(device, testModel, &preparedModel); + // Terminate early if the driver cannot prepare the model. + if (preparedModel == nullptr) return; + + // Save the compilation to cache. + { + ErrorStatus status; + hidl_handle cache1, cache2; + createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1); + createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2); + saveModelToCache(preparedModel, cache1, cache2, &status); + if (checkEarlyTermination(status)) return; + ASSERT_EQ(status, ErrorStatus::NONE); + } + + // Randomly flip one single bit of the cache entry. + FILE* pFile = fopen(mCache1.c_str(), "r+"); + ASSERT_EQ(fseek(pFile, 0, SEEK_END), 0); + long int fileSize = ftell(pFile); + ASSERT_GT(fileSize, 0); + ASSERT_EQ(fseek(pFile, getRandomInt(0l, fileSize - 1), SEEK_SET), 0); + int readByte = fgetc(pFile); + ASSERT_NE(readByte, EOF); + ASSERT_EQ(fseek(pFile, -1, SEEK_CUR), 0); + ASSERT_NE(fputc(static_cast(readByte) ^ (1U << getRandomInt(0, 7)), pFile), EOF); + fclose(pFile); + + // Retrieve preparedModel from cache, expect failure. + { + preparedModel = nullptr; + ErrorStatus status; + hidl_handle cache1, cache2; + createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1); + createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2); + prepareModelFromCache(cache1, cache2, &preparedModel, &status); + ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); + ASSERT_EQ(preparedModel, nullptr); + } +} + +TEST_P(CompilationCachingSecurityTest, WrongLengthSecuritySensitiveCache) { + if (!mIsCachingSupported) return; + + // Create test HIDL model and compile. + Model testModel = createTestModel(); + sp preparedModel = nullptr; + generated_tests::PrepareModel(device, testModel, &preparedModel); + // Terminate early if the driver cannot prepare the model. + if (preparedModel == nullptr) return; + + // Save the compilation to cache. + { + ErrorStatus status; + hidl_handle cache1, cache2; + createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1); + createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2); + saveModelToCache(preparedModel, cache1, cache2, &status); + if (checkEarlyTermination(status)) return; + ASSERT_EQ(status, ErrorStatus::NONE); + } + + // Randomly append bytes to the cache entry. + FILE* pFile = fopen(mCache1.c_str(), "a"); + uint32_t appendLength = getRandomInt(1, 256); + for (uint32_t i = 0; i < appendLength; i++) { + ASSERT_NE(fputc(getRandomInt(0, 255), pFile), EOF); + } + fclose(pFile); + + // Retrieve preparedModel from cache, expect failure. + { + preparedModel = nullptr; + ErrorStatus status; + hidl_handle cache1, cache2; + createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1); + createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2); + prepareModelFromCache(cache1, cache2, &preparedModel, &status); + ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); + ASSERT_EQ(preparedModel, nullptr); + } +} + +TEST_P(CompilationCachingSecurityTest, WrongToken) { + if (!mIsCachingSupported) return; + + // Create test HIDL model and compile. + Model testModel = createTestModel(); + sp preparedModel = nullptr; + generated_tests::PrepareModel(device, testModel, &preparedModel); + // Terminate early if the driver cannot prepare the model. + if (preparedModel == nullptr) return; + + // Save the compilation to cache. + { + ErrorStatus status; + hidl_handle cache1, cache2; + createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1); + createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2); + saveModelToCache(preparedModel, cache1, cache2, &status); + if (checkEarlyTermination(status)) return; + ASSERT_EQ(status, ErrorStatus::NONE); + } + + // Randomly flip one single bit in mToken. + uint32_t ind = getRandomInt(0u, static_cast(Constant::BYTE_SIZE_OF_CACHE_TOKEN) - 1); + mToken[ind] ^= (1U << getRandomInt(0, 7)); + + // Retrieve the preparedModel from cache, expect failure. + { + preparedModel = nullptr; + ErrorStatus status; + hidl_handle cache1, cache2; + createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1); + createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2); + prepareModelFromCache(cache1, cache2, &preparedModel, &status); + ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); + ASSERT_EQ(preparedModel, nullptr); + } +} + +INSTANTIATE_TEST_CASE_P(TestCompilationCaching, CompilationCachingSecurityTest, + ::testing::Range(0U, 10U)); + +} // namespace functional +} // namespace vts +} // namespace V1_2 +} // namespace neuralnetworks +} // namespace hardware +} // namespace android diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp b/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp index 4bc891f3d1..2c3287ab35 100644 --- a/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp +++ b/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp @@ -19,6 +19,7 @@ #include "VtsHalNeuralnetworks.h" #include "Callbacks.h" +#include "GeneratedTestHarness.h" #include "TestHarness.h" #include "Utils.h" @@ -29,14 +30,6 @@ namespace android { namespace hardware { namespace neuralnetworks { - -namespace generated_tests { -using ::test_helper::MixedTypedExample; -extern void Execute(const sp&, std::function, - std::function, const std::vector&, - bool testDynamicOutputShape = false); -} // namespace generated_tests - namespace V1_2 { namespace vts { namespace functional { diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_0.cpp b/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_0.cpp index 956926aaff..990cab9161 100644 --- a/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_0.cpp +++ b/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_0.cpp @@ -19,6 +19,7 @@ #include "VtsHalNeuralnetworks.h" #include "Callbacks.h" +#include "GeneratedTestHarness.h" #include "TestHarness.h" #include "Utils.h" @@ -29,14 +30,6 @@ namespace android { namespace hardware { namespace neuralnetworks { - -namespace generated_tests { -using ::test_helper::MixedTypedExample; -extern void Execute(const sp&, std::function, - std::function, const std::vector&, - bool testDynamicOutputShape = false); -} // namespace generated_tests - namespace V1_2 { namespace vts { namespace functional { diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_1.cpp b/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_1.cpp index 425690f321..fa6d54d295 100644 --- a/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_1.cpp +++ b/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_1.cpp @@ -19,6 +19,7 @@ #include "VtsHalNeuralnetworks.h" #include "Callbacks.h" +#include "GeneratedTestHarness.h" #include "TestHarness.h" #include "Utils.h" @@ -29,14 +30,6 @@ namespace android { namespace hardware { namespace neuralnetworks { - -namespace generated_tests { -using ::test_helper::MixedTypedExample; -extern void Execute(const sp&, std::function, - std::function, const std::vector&, - bool testDynamicOutputShape = false); -} // namespace generated_tests - namespace V1_2 { namespace vts { namespace functional { From 1ffe69a8e9ac0dc0f95accdf8e62a80347e12571 Mon Sep 17 00:00:00 2001 From: Slava Shklyaev Date: Tue, 29 Jan 2019 13:35:05 +0000 Subject: [PATCH 434/718] Update NNAPI Extensions documentation This is a follow-up to change Ia9b99015eec7a48bbf969cbe503862271f09adca Bug: 118605927 Test: mma Change-Id: I7ddafca04bce6fd37a9c0877270cee325111d833 --- neuralnetworks/1.2/types.hal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal index 9e7d8f0d1b..77779a6281 100644 --- a/neuralnetworks/1.2/types.hal +++ b/neuralnetworks/1.2/types.hal @@ -449,7 +449,7 @@ struct Model { * {@link OperationTypeRange::BASE_MAX} respectively should be interpreted * as an extension operand. The low * {@link Model::ExtensionTypeEncoding::LOW_BITS_TYPE} bits of the value - * correspond to the value within the extension and the high + * correspond to the type ID within the extension and the high * {@link Model::ExtensionTypeEncoding::HIGH_BITS_PREFIX} bits encode * the "prefix", which maps uniquely to the extension name. * From bae91697b5397693a10f225de3d39102152e4f18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Guihot?= Date: Wed, 23 Jan 2019 19:18:59 -0800 Subject: [PATCH 435/718] Added TENSOR_QUANT8_SYMM type. Test: none Change-Id: I02fc8698b3f80e1ae2a318e5cde593c6d7222bac --- neuralnetworks/1.2/types.hal | 14 ++++++++++++-- .../1.2/vts/functional/ValidateModel.cpp | 5 +++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal index 9e7d8f0d1b..2e48ba016f 100644 --- a/neuralnetworks/1.2/types.hal +++ b/neuralnetworks/1.2/types.hal @@ -47,7 +47,7 @@ enum OperandType : @1.0::OperandType { * used to convert the 16 bit number to a real value in the following way: * realValue = integerValue * scale. * - * scale is a 32 bit floating point with value greater then zero. + * scale is a 32 bit floating point with value greater than zero. */ TENSOR_QUANT16_SYMM = 7, /** A tensor of IEEE 754 16 bit floating point values. */ @@ -97,6 +97,16 @@ enum OperandType : @1.0::OperandType { * real_value = (integer_value - zeroPoint) * scale. */ TENSOR_QUANT16_ASYMM = 12, + /** + * A tensor of 8 bit signed integers that represent real numbers. + * + * Attached to this tensor is a number representing real value scale that is + * used to convert the 8 bit number to a real value in the following way: + * realValue = integerValue * scale. + * + * scale is a 32 bit floating point with value greater than zero. + */ + TENSOR_QUANT8_SYMM = 13, /* ADDING A NEW FUNDAMENTAL TYPE REQUIRES UPDATING THE VALUE OF * OperandTypeRange::FUNDAMENTAL_MAX. */ @@ -111,7 +121,7 @@ enum OperandType : @1.0::OperandType { enum OperandTypeRange : uint32_t { BASE_MIN = 0, FUNDAMENTAL_MIN = 0, - FUNDAMENTAL_MAX = 12, + FUNDAMENTAL_MAX = 13, OEM_MIN = 10000, OEM_MAX = 10001, BASE_MAX = 0xFFFF, diff --git a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp index 1bbb20392a..a0f11ebbaf 100644 --- a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp +++ b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp @@ -161,6 +161,7 @@ static uint32_t getInvalidRank(OperandType type) { case OperandType::TENSOR_FLOAT32: case OperandType::TENSOR_INT32: case OperandType::TENSOR_QUANT8_ASYMM: + case OperandType::TENSOR_QUANT8_SYMM: case OperandType::TENSOR_QUANT16_ASYMM: case OperandType::TENSOR_QUANT16_SYMM: case OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL: @@ -199,6 +200,7 @@ static float getInvalidScale(OperandType type) { return 1.0f; case OperandType::TENSOR_INT32: return -1.0f; + case OperandType::TENSOR_QUANT8_SYMM: case OperandType::TENSOR_QUANT8_ASYMM: case OperandType::TENSOR_QUANT16_ASYMM: case OperandType::TENSOR_QUANT16_SYMM: @@ -235,6 +237,8 @@ static std::vector getInvalidZeroPoints(OperandType type) { return {1}; case OperandType::TENSOR_QUANT8_ASYMM: return {-1, 256}; + case OperandType::TENSOR_QUANT8_SYMM: + return {-129, -1, 1, 128}; case OperandType::TENSOR_QUANT16_ASYMM: return {-1, 65536}; case OperandType::TENSOR_QUANT16_SYMM: @@ -292,6 +296,7 @@ static void mutateOperand(Operand* operand, OperandType type) { newOperand.zeroPoint = 0; break; case OperandType::TENSOR_QUANT8_ASYMM: + case OperandType::TENSOR_QUANT8_SYMM: case OperandType::TENSOR_QUANT16_ASYMM: case OperandType::TENSOR_QUANT16_SYMM: newOperand.dimensions = From 913334e0368d63ae47748cb0ab9a17296cfff995 Mon Sep 17 00:00:00 2001 From: Brian Stack Date: Tue, 29 Jan 2019 15:39:13 -0800 Subject: [PATCH 436/718] Properly append META_DATA event on flush Bug: 123597380 Test: atest VtsHalSensorsV2_0TargetTest:SensorsHidlTest#FlushSensor Test: Framework properly receives and handles flush complete events Change-Id: I09d2b52555c27602e1fd2ee2282f8ad700a1be18 --- sensors/2.0/default/Sensor.cpp | 2 +- sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sensors/2.0/default/Sensor.cpp b/sensors/2.0/default/Sensor.cpp index 373ab1280d..e8067d00ba 100644 --- a/sensors/2.0/default/Sensor.cpp +++ b/sensors/2.0/default/Sensor.cpp @@ -83,7 +83,7 @@ Result Sensor::flush() { // to the Event FMQ prior to writing the flush complete event. Event ev; ev.sensorHandle = mSensorInfo.sensorHandle; - ev.sensorType = SensorType::ADDITIONAL_INFO; + ev.sensorType = SensorType::META_DATA; ev.u.meta.what = MetaDataEventType::META_DATA_FLUSH_COMPLETE; std::vector evs{ev}; mCallback->postEvents(evs, isWakeUpSensor()); diff --git a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp index 4a1f8f111d..39053fe75f 100644 --- a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp +++ b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp @@ -51,7 +51,7 @@ class EventCallback : public IEventCallback { } void onEvent(const ::android::hardware::sensors::V1_0::Event& event) override { - if (event.sensorType == SensorType::ADDITIONAL_INFO && + if (event.sensorType == SensorType::META_DATA && event.u.meta.what == MetaDataEventType::META_DATA_FLUSH_COMPLETE) { std::unique_lock lock(mFlushMutex); mFlushMap[event.sensorHandle]++; From e388f14db602eaebda488c7b1c052e3f6c2f0a84 Mon Sep 17 00:00:00 2001 From: Brian Stack Date: Mon, 28 Jan 2019 13:24:20 -0800 Subject: [PATCH 437/718] Use more realistic values for sensors Bug: 123597515 Test: Builds, cuttlefish device health checks pass Change-Id: Ifddf16761a218788ac7174e16b2d9f7ebb9685a9 --- sensors/2.0/default/Sensor.cpp | 56 ++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/sensors/2.0/default/Sensor.cpp b/sensors/2.0/default/Sensor.cpp index 373ab1280d..f6dd87e8c1 100644 --- a/sensors/2.0/default/Sensor.cpp +++ b/sensors/2.0/default/Sensor.cpp @@ -18,6 +18,8 @@ #include +#include + namespace android { namespace hardware { namespace sensors { @@ -28,6 +30,8 @@ using ::android::hardware::sensors::V1_0::MetaDataEventType; using ::android::hardware::sensors::V1_0::SensorFlagBits; using ::android::hardware::sensors::V1_0::SensorStatus; +static constexpr float kDefaultMaxDelayUs = 10 * 1000 * 1000; + Sensor::Sensor(ISensorsEventCallback* callback) : mIsEnabled(false), mSamplingPeriodNs(0), @@ -202,7 +206,7 @@ AccelSensor::AccelSensor(int32_t sensorHandle, ISensorsEventCallback* callback) mSensorInfo.resolution = 1.52e-5; mSensorInfo.power = 0.001f; // mA mSensorInfo.minDelay = 20 * 1000; // microseconds - mSensorInfo.maxDelay = 1000 * 1000; // microseconds + mSensorInfo.maxDelay = kDefaultMaxDelayUs; mSensorInfo.fifoReservedEventCount = 0; mSensorInfo.fifoMaxEventCount = 0; mSensorInfo.requiredPermission = ""; @@ -218,10 +222,10 @@ PressureSensor::PressureSensor(int32_t sensorHandle, ISensorsEventCallback* call mSensorInfo.type = SensorType::PRESSURE; mSensorInfo.typeAsString = ""; mSensorInfo.maxRange = 1100.0f; // hPa - mSensorInfo.resolution = 1.0f; // hPa + mSensorInfo.resolution = 0.005f; // hPa mSensorInfo.power = 0.001f; // mA - mSensorInfo.minDelay = 28571.0f; // microseconds - mSensorInfo.maxDelay = 0.0f; // microseconds + mSensorInfo.minDelay = 100 * 1000; // microseconds + mSensorInfo.maxDelay = kDefaultMaxDelayUs; mSensorInfo.fifoReservedEventCount = 0; mSensorInfo.fifoMaxEventCount = 0; mSensorInfo.requiredPermission = ""; @@ -236,11 +240,11 @@ MagnetometerSensor::MagnetometerSensor(int32_t sensorHandle, ISensorsEventCallba mSensorInfo.version = 1; mSensorInfo.type = SensorType::MAGNETIC_FIELD; mSensorInfo.typeAsString = ""; - mSensorInfo.maxRange = 4911.0f; - mSensorInfo.resolution = 1.00f; + mSensorInfo.maxRange = 1300.0f; + mSensorInfo.resolution = 0.01f; mSensorInfo.power = 0.001f; // mA - mSensorInfo.minDelay = 14284.0f; // microseconds - mSensorInfo.maxDelay = 0.0f; // microseconds + mSensorInfo.minDelay = 20 * 1000; // microseconds + mSensorInfo.maxDelay = kDefaultMaxDelayUs; mSensorInfo.fifoReservedEventCount = 0; mSensorInfo.fifoMaxEventCount = 0; mSensorInfo.requiredPermission = ""; @@ -255,11 +259,11 @@ LightSensor::LightSensor(int32_t sensorHandle, ISensorsEventCallback* callback) mSensorInfo.version = 1; mSensorInfo.type = SensorType::LIGHT; mSensorInfo.typeAsString = ""; - mSensorInfo.maxRange = 10000.0f; + mSensorInfo.maxRange = 43000.0f; mSensorInfo.resolution = 10.0f; mSensorInfo.power = 0.001f; // mA - mSensorInfo.minDelay = 20.0f * 1000; // microseconds - mSensorInfo.maxDelay = 0; // microseconds + mSensorInfo.minDelay = 200 * 1000; // microseconds + mSensorInfo.maxDelay = kDefaultMaxDelayUs; mSensorInfo.fifoReservedEventCount = 0; mSensorInfo.fifoMaxEventCount = 0; mSensorInfo.requiredPermission = ""; @@ -277,8 +281,8 @@ ProximitySensor::ProximitySensor(int32_t sensorHandle, ISensorsEventCallback* ca mSensorInfo.maxRange = 5.0f; mSensorInfo.resolution = 1.0f; mSensorInfo.power = 0.012f; // mA - mSensorInfo.minDelay = 500; // microseconds - mSensorInfo.maxDelay = 2 * mSensorInfo.minDelay; + mSensorInfo.minDelay = 200 * 1000; // microseconds + mSensorInfo.maxDelay = kDefaultMaxDelayUs; mSensorInfo.fifoReservedEventCount = 0; mSensorInfo.fifoMaxEventCount = 0; mSensorInfo.requiredPermission = ""; @@ -293,11 +297,11 @@ GyroSensor::GyroSensor(int32_t sensorHandle, ISensorsEventCallback* callback) : mSensorInfo.version = 1; mSensorInfo.type = SensorType::GYROSCOPE; mSensorInfo.typeAsString = ""; - mSensorInfo.maxRange = 8.726639f; - mSensorInfo.resolution = 1.0f; + mSensorInfo.maxRange = 1000.0f * M_PI / 180.0f; + mSensorInfo.resolution = 1000.0f * M_PI / (180.0f * 32768.0f); mSensorInfo.power = 0.001f; - mSensorInfo.minDelay = 4444; // microseonds - mSensorInfo.maxDelay = 0; // microseconds + mSensorInfo.minDelay = 2.5f * 1000; // microseconds + mSensorInfo.maxDelay = kDefaultMaxDelayUs; mSensorInfo.fifoReservedEventCount = 0; mSensorInfo.fifoMaxEventCount = 0; mSensorInfo.requiredPermission = ""; @@ -313,10 +317,10 @@ AmbientTempSensor::AmbientTempSensor(int32_t sensorHandle, ISensorsEventCallback mSensorInfo.type = SensorType::AMBIENT_TEMPERATURE; mSensorInfo.typeAsString = ""; mSensorInfo.maxRange = 80.0f; - mSensorInfo.resolution = 1.0f; + mSensorInfo.resolution = 0.01f; mSensorInfo.power = 0.001f; - mSensorInfo.minDelay = 4444; // microseonds - mSensorInfo.maxDelay = 0; // microseconds + mSensorInfo.minDelay = 40 * 1000; // microseconds + mSensorInfo.maxDelay = kDefaultMaxDelayUs; mSensorInfo.fifoReservedEventCount = 0; mSensorInfo.fifoMaxEventCount = 0; mSensorInfo.requiredPermission = ""; @@ -332,10 +336,10 @@ DeviceTempSensor::DeviceTempSensor(int32_t sensorHandle, ISensorsEventCallback* mSensorInfo.type = SensorType::TEMPERATURE; mSensorInfo.typeAsString = ""; mSensorInfo.maxRange = 80.0f; - mSensorInfo.resolution = 1.0f; + mSensorInfo.resolution = 0.01f; mSensorInfo.power = 0.001f; - mSensorInfo.minDelay = 4444; // microseonds - mSensorInfo.maxDelay = 0; // microseconds + mSensorInfo.minDelay = 40 * 1000; // microseconds + mSensorInfo.maxDelay = kDefaultMaxDelayUs; mSensorInfo.fifoReservedEventCount = 0; mSensorInfo.fifoMaxEventCount = 0; mSensorInfo.requiredPermission = ""; @@ -352,10 +356,10 @@ RelativeHumiditySensor::RelativeHumiditySensor(int32_t sensorHandle, mSensorInfo.type = SensorType::RELATIVE_HUMIDITY; mSensorInfo.typeAsString = ""; mSensorInfo.maxRange = 100.0f; - mSensorInfo.resolution = 1.0f; + mSensorInfo.resolution = 0.1f; mSensorInfo.power = 0.001f; - mSensorInfo.minDelay = 4444; // microseonds - mSensorInfo.maxDelay = 0; // microseconds + mSensorInfo.minDelay = 40 * 1000; // microseconds + mSensorInfo.maxDelay = kDefaultMaxDelayUs; mSensorInfo.fifoReservedEventCount = 0; mSensorInfo.fifoMaxEventCount = 0; mSensorInfo.requiredPermission = ""; From b1fc16aab5b1e675db9703a7191ad6365cbd680c Mon Sep 17 00:00:00 2001 From: Kai Date: Tue, 14 Aug 2018 13:35:13 -0700 Subject: [PATCH 438/718] Fix vts-hal-auto test Add min/maxSampleRate for some properties and add new static properties. Bug: 112596543 Test: Build and flash into Mojave Run vts-hal-auto test Change-Id: Ide0c09e4790770e5415ca223b2e09f5958b5e783 (cherry picked from commit 3acc549fa87fbe19b181edea39eead0772f75822) --- .../2.0/default/impl/vhal_v2_0/DefaultConfig.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) 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 7614cad1f7..08cdffa715 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 @@ -196,6 +196,15 @@ const ConfigDeclaration kVehicleProperties[]{ }, .initialValue = {.int32Values = {1}}}, + {.config = + { + .prop = toInt(VehicleProperty::INFO_DRIVER_SEAT), + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::STATIC, + .areaConfigs = {VehicleAreaConfig{.areaId = (0)}}, + }, + .initialValue = {.int32Values = {SEAT_1_LEFT}}}, + {.config = { .prop = toInt(VehicleProperty::INFO_FUEL_DOOR_LOCATION), @@ -321,6 +330,8 @@ const ConfigDeclaration kVehicleProperties[]{ .access = VehiclePropertyAccess::READ, .changeMode = VehiclePropertyChangeMode::CONTINUOUS, .areaConfigs = {VehicleAreaConfig{.areaId = (0)}}, + .minSampleRate = 1.0f, + .maxSampleRate = 2.0f, }, .initialValue = {.floatValues = {100.0f}}}, // units in meters @@ -328,6 +339,8 @@ const ConfigDeclaration kVehicleProperties[]{ {.prop = toInt(VehicleProperty::TIRE_PRESSURE), .access = VehiclePropertyAccess::READ, .changeMode = VehiclePropertyChangeMode::CONTINUOUS, + .minSampleRate = 1.0f, + .maxSampleRate = 2.0f, .areaConfigs = {VehicleAreaConfig{ .areaId = WHEEL_FRONT_LEFT, .minFloatValue = 100.0f, .maxFloatValue = 300.0f, From 2fa104b2d18d34858769a8345415ac029bc18d3c Mon Sep 17 00:00:00 2001 From: gomo Date: Sat, 26 Jan 2019 03:22:37 -0800 Subject: [PATCH 439/718] Bluesky add position uncertainty field Add the horizontal position uncertainty for the provided location by Bluesky at which the corrections are computed. This is a bug fix as these fields were missing in the original submit. Bug: 111441283 Test: Existing tests pass. Change-Id: I3c6df7bcd72d6bab11c4e1cc4908e24034958ad7 --- gnss/measurement_corrections/1.0/types.hal | 25 ++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/gnss/measurement_corrections/1.0/types.hal b/gnss/measurement_corrections/1.0/types.hal index 5f207347f2..edf26bf7c0 100644 --- a/gnss/measurement_corrections/1.0/types.hal +++ b/gnss/measurement_corrections/1.0/types.hal @@ -79,18 +79,35 @@ struct SingleSatCorrection { * toaGpsNanosecondsOfWeek */ struct MeasurementCorrections { - /** Represents latitude in degrees. */ + /** Represents latitude in degrees at which the corrections are computed.. */ double latitudeDegrees; - /** Represents longitude in degrees. */ + /** Represents longitude in degrees at which the corrections are computed.. */ double longitudeDegrees; /** - * Represents altitude in meters above the WGS 84 reference ellipsoid. + * Represents altitude in meters above the WGS 84 reference ellipsoid at which the corrections + * are computed. */ double altitudeMeters; - /** Time Of Applicability, GPS time of week */ + /** + * Represents the horizontal uncertainty (68% confidence) in meters on the device position at + * which the corrections are provided. + * + * This value is useful for example to judge how accurate the provided corrections are. + */ + double horizontalPositionUncertaintyMeters; + + /** + * Represents the vertical uncertainty (68% confidence) in meters on the device position at + * which the corrections are provided. + * + * This value is useful for example to judge how accurate the provided corrections are. + */ + double verticalPositionUncertaintyMeters; + + /** Time Of Applicability, GPS time of week in nanoseconds. */ uint64_t toaGpsNanosecondsOfWeek; /** From 113521924517e6196938d512ee563953a65985ff Mon Sep 17 00:00:00 2001 From: Jayant Chowdhary Date: Thu, 24 Jan 2019 18:17:10 -0800 Subject: [PATCH 440/718] Add SECURE camera capability. Bug: 123046494 Test: Builds Change-Id: I8d90edc2606e535bbf8ebe4e0ebaffeba6ad17dd Signed-off-by: Jayant Chowdhary --- camera/metadata/3.4/types.hal | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/camera/metadata/3.4/types.hal b/camera/metadata/3.4/types.hal index 9bbc90dc28..a79fe53dc1 100644 --- a/camera/metadata/3.4/types.hal +++ b/camera/metadata/3.4/types.hal @@ -111,6 +111,14 @@ enum CameraMetadataTag : @3.3::CameraMetadataTag { * Enumeration definitions for the various entries that need them */ +/** android.request.availableCapabilities enumeration values added since v3.3 + * @see ANDROID_REQUEST_AVAILABLE_CAPABILITIES + */ +enum CameraMetadataEnumAndroidRequestAvailableCapabilities : + @3.3::CameraMetadataEnumAndroidRequestAvailableCapabilities { + ANDROID_REQUEST_AVAILABLE_CAPABILITIES_SECURE_IMAGE_DATA, +}; + /** android.scaler.availableFormats enumeration values added since v3.2 * @see ANDROID_SCALER_AVAILABLE_FORMATS */ From 0f1c40ce46c2902fec8c1aecd64dde8a14cea15d Mon Sep 17 00:00:00 2001 From: Paul McLean Date: Wed, 23 Jan 2019 12:56:46 -0700 Subject: [PATCH 441/718] VTS test for MicrophoneDirection API (HAL V 5.0) Bug: 121201996 Test: atest VtsHalAudioV5_0TargetTest Change-Id: Icf8a054b50568f51a49b74f15de64232d1dc1c39 --- .../5.0/AudioPrimaryHidlHalTest.cpp | 55 +++++++++++++++++++ .../all-versions/vts/functional/Android.bp | 3 +- 2 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 audio/core/all-versions/vts/functional/5.0/AudioPrimaryHidlHalTest.cpp diff --git a/audio/core/all-versions/vts/functional/5.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/5.0/AudioPrimaryHidlHalTest.cpp new file mode 100644 index 0000000000..bdb17cdc3c --- /dev/null +++ b/audio/core/all-versions/vts/functional/5.0/AudioPrimaryHidlHalTest.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2019 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 + +// pull in all the <= 4.0 tests +#include "4.0/AudioPrimaryHidlHalTest.cpp" + +TEST_P(InputStreamTest, SetMicrophoneDirection) { + doc::test("Make sure setMicrophoneDirection correctly handles valid & invalid arguments"); + + // MicrophoneDirection dir = MicrophoneDirection::FRONT; + for (MicrophoneDirection dir : android::hardware::hidl_enum_range()) { + ASSERT_RESULT(okOrNotSupported, stream->setMicrophoneDirection(dir)); + } + + // Bogus values + for (auto dir : {42, -1, 4}) { + ASSERT_RESULT(invalidArgsOrNotSupported, + stream->setMicrophoneDirection(MicrophoneDirection(dir))); + } +} + +TEST_P(InputStreamTest, SetMicrophoneFieldDimension) { + doc::test("Make sure setMicrophoneFieldDimension correctly handles valid & invalid arguments"); + + // Valid zoom values -1.0 -> 1.0 + float incr = 0.1f; + for (float val = -1.0f; val <= 1.0; val += incr) { + ASSERT_RESULT(okOrNotSupported, stream->setMicrophoneFieldDimension(val)); + } + + // Bogus values + for (float val = 1.0f + incr; val <= 10.0f; val += incr) { + ASSERT_RESULT(invalidArgsOrNotSupported, stream->setMicrophoneFieldDimension(val)); + ASSERT_RESULT(invalidArgsOrNotSupported, stream->setMicrophoneFieldDimension(-val)); + } + // Some extremes + ASSERT_RESULT(invalidArgsOrNotSupported, stream->setMicrophoneFieldDimension(NAN)); + ASSERT_RESULT(invalidArgsOrNotSupported, stream->setMicrophoneFieldDimension(-NAN)); + ASSERT_RESULT(invalidArgsOrNotSupported, stream->setMicrophoneFieldDimension(INFINITY)); + ASSERT_RESULT(invalidArgsOrNotSupported, stream->setMicrophoneFieldDimension(-INFINITY)); +} diff --git a/audio/core/all-versions/vts/functional/Android.bp b/audio/core/all-versions/vts/functional/Android.bp index 6498289dd4..f434e4226c 100644 --- a/audio/core/all-versions/vts/functional/Android.bp +++ b/audio/core/all-versions/vts/functional/Android.bp @@ -73,8 +73,7 @@ cc_test { name: "VtsHalAudioV5_0TargetTest", defaults: ["VtsHalAudioTargetTest_defaults"], srcs: [ - // for now the tests are the same as V4 - "4.0/AudioPrimaryHidlHalTest.cpp", + "5.0/AudioPrimaryHidlHalTest.cpp", ], static_libs: [ "android.hardware.audio@5.0", From 1b066c8d1d1e544bcdb8aa7800db334208ad705c Mon Sep 17 00:00:00 2001 From: Xusong Wang Date: Thu, 31 Jan 2019 01:04:02 +0000 Subject: [PATCH 442/718] Revert "Update cas@1.0 hal to cas@1.1" This reverts commit f9f0a25b26d93cf86ccb44c046f83b86ce962c3d. Reason for revert: Change-Id: I32657e10fa8ff58dd351aa8e0b611195c2826f07 --- cas/1.1/Android.bp | 20 -- cas/1.1/ICas.hal | 42 ---- cas/1.1/ICasListener.hal | 33 --- cas/1.1/IMediaCasService.hal | 38 --- cas/1.1/default/Android.bp | 49 ---- cas/1.1/default/CasImpl.cpp | 222 ------------------ cas/1.1/default/CasImpl.h | 98 -------- cas/1.1/default/DescramblerImpl.cpp | 195 --------------- cas/1.1/default/DescramblerImpl.h | 67 ------ cas/1.1/default/FactoryLoader.h | 217 ----------------- cas/1.1/default/MediaCasService.cpp | 126 ---------- cas/1.1/default/MediaCasService.h | 66 ------ cas/1.1/default/SharedLibrary.cpp | 65 ----- cas/1.1/default/SharedLibrary.h | 50 ---- cas/1.1/default/TypeConvert.cpp | 94 -------- cas/1.1/default/TypeConvert.h | 43 ---- .../android.hardware.cas@1.1-service-lazy.rc | 9 - .../android.hardware.cas@1.1-service-lazy.xml | 11 - .../android.hardware.cas@1.1-service.rc | 6 - .../android.hardware.cas@1.1-service.xml | 11 - cas/1.1/default/service.cpp | 58 ----- .../compatibility_matrix.current.xml | 2 +- 22 files changed, 1 insertion(+), 1521 deletions(-) delete mode 100644 cas/1.1/Android.bp delete mode 100644 cas/1.1/ICas.hal delete mode 100644 cas/1.1/ICasListener.hal delete mode 100644 cas/1.1/IMediaCasService.hal delete mode 100644 cas/1.1/default/Android.bp delete mode 100644 cas/1.1/default/CasImpl.cpp delete mode 100644 cas/1.1/default/CasImpl.h delete mode 100644 cas/1.1/default/DescramblerImpl.cpp delete mode 100644 cas/1.1/default/DescramblerImpl.h delete mode 100644 cas/1.1/default/FactoryLoader.h delete mode 100644 cas/1.1/default/MediaCasService.cpp delete mode 100644 cas/1.1/default/MediaCasService.h delete mode 100644 cas/1.1/default/SharedLibrary.cpp delete mode 100644 cas/1.1/default/SharedLibrary.h delete mode 100644 cas/1.1/default/TypeConvert.cpp delete mode 100644 cas/1.1/default/TypeConvert.h delete mode 100644 cas/1.1/default/android.hardware.cas@1.1-service-lazy.rc delete mode 100644 cas/1.1/default/android.hardware.cas@1.1-service-lazy.xml delete mode 100644 cas/1.1/default/android.hardware.cas@1.1-service.rc delete mode 100644 cas/1.1/default/android.hardware.cas@1.1-service.xml delete mode 100644 cas/1.1/default/service.cpp diff --git a/cas/1.1/Android.bp b/cas/1.1/Android.bp deleted file mode 100644 index bb0edb970c..0000000000 --- a/cas/1.1/Android.bp +++ /dev/null @@ -1,20 +0,0 @@ -// This file is autogenerated by hidl-gen -Landroidbp. - -hidl_interface { - name: "android.hardware.cas@1.1", - root: "android.hardware", - vndk: { - enabled: true, - }, - srcs: [ - "ICas.hal", - "ICasListener.hal", - "IMediaCasService.hal", - ], - interfaces: [ - "android.hardware.cas@1.0", - "android.hidl.base@1.0", - ], - gen_java: true, -} - diff --git a/cas/1.1/ICas.hal b/cas/1.1/ICas.hal deleted file mode 100644 index 027968e565..0000000000 --- a/cas/1.1/ICas.hal +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.hardware.cas@1.1; - -import @1.0::HidlCasSessionId; -import @1.0::ICas; -import @1.0::Status; - -/** - * ICas is the API to control the cas system and is accessible from both - * Java and native level. It is used to manage sessions, provision/refresh - * the cas system, and process the EMM/ECM messages. It also allows bi-directional, - * scheme-specific communications between the client and the cas system. - */ - -interface ICas extends @1.0::ICas { - /** - * Send an scheme-specific session event to the CasPlugin. - * - * @param sessionId the id of an opened session. - * @param event an integer denoting a scheme-specific event to be sent. - * @param arg a scheme-specific integer argument for the event. - * @param data a byte array containing scheme-specific data for the event. - * @return status the status of the call. - */ - sendSessionEvent(HidlCasSessionId sessionId, int32_t event, int32_t arg, - vec eventData) - generates (Status status); -}; diff --git a/cas/1.1/ICasListener.hal b/cas/1.1/ICasListener.hal deleted file mode 100644 index 5ec1154a3f..0000000000 --- a/cas/1.1/ICasListener.hal +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.hardware.cas@1.1; - -import @1.0::ICasListener; -import @1.0::HidlCasSessionId; - -interface ICasListener extends @1.0::ICasListener{ - /** - * Notify the listener of a scheme-specific session event from CA system. - * - * @param sessionId the id of an opened session. - * @param event an integer whose meaning is scheme-specific. - * @param arg an integer whose meaning is scheme-specific. - * @param data a byte array of data whose format and meaning are - * scheme-specific. - */ - onSessionEvent(HidlCasSessionId sessionId, int32_t event, int32_t arg, - vec data); -}; diff --git a/cas/1.1/IMediaCasService.hal b/cas/1.1/IMediaCasService.hal deleted file mode 100644 index e82b54c9db..0000000000 --- a/cas/1.1/IMediaCasService.hal +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.hardware.cas@1.1; - -import @1.1::ICas; -import @1.1::ICasListener; -import @1.0::IMediaCasService; - -/** - * IMediaCasService is the main entry point for interacting with a vendor's - * cas HAL to create cas and descrambler plugin instances. A cas plugin instance - * opens cas sessions which are used to obtain keys for a descrambler session, - * which can in turn be used to descramble protected video content. - */ - -interface IMediaCasService extends @1.0::IMediaCasService { - /** - * Construct a new instance of a @1.1 ICAS CasPlugin given a CA_system_id. - * - * @param caSystemId the id of the CA system. - * @param listener the event listener to receive events coming from the CasPlugin. - * @return cas the newly created CasPlugin interface. - */ - createPluginExt(int32_t caSystemId, ICasListener listener) generates (ICas cas); -}; diff --git a/cas/1.1/default/Android.bp b/cas/1.1/default/Android.bp deleted file mode 100644 index 68a49cf5b1..0000000000 --- a/cas/1.1/default/Android.bp +++ /dev/null @@ -1,49 +0,0 @@ -cc_defaults { - name: "cas_service_defaults@1.1", - defaults: ["hidl_defaults"], - vendor: true, - relative_install_path: "hw", - srcs: [ - "CasImpl.cpp", - "DescramblerImpl.cpp", - "MediaCasService.cpp", - "service.cpp", - "SharedLibrary.cpp", - "TypeConvert.cpp", - ], - - compile_multilib: "32", - - shared_libs: [ - "android.hardware.cas@1.0", - "android.hardware.cas@1.1", - "android.hardware.cas.native@1.0", - "android.hidl.memory@1.0", - "libbinder", - "libhidlbase", - "libhidlmemory", - "libhidltransport", - "liblog", - "libutils", - ], - header_libs: [ - "libstagefright_foundation_headers", - "media_plugin_headers", - ], -} - -cc_binary { - name: "android.hardware.cas@1.1-service", - vintf_fragments: ["android.hardware.cas@1.1-service.xml"], - defaults: ["cas_service_defaults@1.1"], - init_rc: ["android.hardware.cas@1.1-service.rc"], -} - -cc_binary { - name: "android.hardware.cas@1.1-service-lazy", - vintf_fragments: ["android.hardware.cas@1.1-service-lazy.xml"], - overrides: ["android.hardware.cas@1.1-service"], - defaults: ["cas_service_defaults@1.1"], - init_rc: ["android.hardware.cas@1.1-service-lazy.rc"], - cflags: ["-DLAZY_SERVICE"], -} diff --git a/cas/1.1/default/CasImpl.cpp b/cas/1.1/default/CasImpl.cpp deleted file mode 100644 index 4cc6017028..0000000000 --- a/cas/1.1/default/CasImpl.cpp +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -//#define LOG_NDEBUG 0 -#define LOG_TAG "android.hardware.cas@1.1-CasImpl" - -#include -#include -#include - -#include "CasImpl.h" -#include "SharedLibrary.h" -#include "TypeConvert.h" - -namespace android { -namespace hardware { -namespace cas { -namespace V1_1 { -namespace implementation { - -CasImpl::CasImpl(const sp& listener) : mListener(listener) { - ALOGV("CTOR"); -} - -CasImpl::~CasImpl() { - ALOGV("DTOR"); - release(); -} - -// static -void CasImpl::OnEvent(void* appData, int32_t event, int32_t arg, uint8_t* data, size_t size) { - if (appData == NULL) { - ALOGE("Invalid appData!"); - return; - } - CasImpl* casImpl = static_cast(appData); - casImpl->onEvent(event, arg, data, size); -} - -// static -void CasImpl::CallBackExt(void* appData, int32_t event, int32_t arg, uint8_t* data, size_t size, - const CasSessionId* sessionId) { - if (appData == NULL) { - ALOGE("Invalid appData!"); - return; - } - CasImpl* casImpl = static_cast(appData); - casImpl->onEvent(sessionId, event, arg, data, size); -} - -void CasImpl::init(const sp& library, CasPlugin* plugin) { - mLibrary = library; - std::shared_ptr holder(plugin); - std::atomic_store(&mPluginHolder, holder); -} - -void CasImpl::onEvent(int32_t event, int32_t arg, uint8_t* data, size_t size) { - if (mListener == NULL) { - return; - } - - HidlCasData eventData; - if (data != NULL) { - eventData.setToExternal(data, size); - } - - mListener->onEvent(event, arg, eventData); -} - -void CasImpl::onEvent(const CasSessionId* sessionId, int32_t event, int32_t arg, uint8_t* data, - size_t size) { - if (mListener == NULL) { - return; - } - - HidlCasData eventData; - if (data != NULL) { - eventData.setToExternal(data, size); - } - - if (sessionId != NULL) { - mListener->onSessionEvent(*sessionId, event, arg, eventData); - } else { - mListener->onEvent(event, arg, eventData); - } -} - -Return CasImpl::setPrivateData(const HidlCasData& pvtData) { - ALOGV("%s", __FUNCTION__); - std::shared_ptr holder = std::atomic_load(&mPluginHolder); - if (holder.get() == nullptr) { - return toStatus(INVALID_OPERATION); - } - return toStatus(holder->setPrivateData(pvtData)); -} - -Return CasImpl::openSession(openSession_cb _hidl_cb) { - ALOGV("%s", __FUNCTION__); - CasSessionId sessionId; - - std::shared_ptr holder = std::atomic_load(&mPluginHolder); - status_t err = INVALID_OPERATION; - if (holder.get() != nullptr) { - err = holder->openSession(&sessionId); - holder.reset(); - } - - _hidl_cb(toStatus(err), sessionId); - - return Void(); -} - -Return CasImpl::setSessionPrivateData(const HidlCasSessionId& sessionId, - const HidlCasData& pvtData) { - ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).string()); - std::shared_ptr holder = std::atomic_load(&mPluginHolder); - if (holder.get() == nullptr) { - return toStatus(INVALID_OPERATION); - } - return toStatus(holder->setSessionPrivateData(sessionId, pvtData)); -} - -Return CasImpl::closeSession(const HidlCasSessionId& sessionId) { - ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).string()); - std::shared_ptr holder = std::atomic_load(&mPluginHolder); - if (holder.get() == nullptr) { - return toStatus(INVALID_OPERATION); - } - return toStatus(holder->closeSession(sessionId)); -} - -Return CasImpl::processEcm(const HidlCasSessionId& sessionId, const HidlCasData& ecm) { - ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).string()); - std::shared_ptr holder = std::atomic_load(&mPluginHolder); - if (holder.get() == nullptr) { - return toStatus(INVALID_OPERATION); - } - - return toStatus(holder->processEcm(sessionId, ecm)); -} - -Return CasImpl::processEmm(const HidlCasData& emm) { - ALOGV("%s", __FUNCTION__); - std::shared_ptr holder = std::atomic_load(&mPluginHolder); - if (holder.get() == nullptr) { - return toStatus(INVALID_OPERATION); - } - - return toStatus(holder->processEmm(emm)); -} - -Return CasImpl::sendEvent(int32_t event, int32_t arg, const HidlCasData& eventData) { - ALOGV("%s", __FUNCTION__); - std::shared_ptr holder = std::atomic_load(&mPluginHolder); - if (holder.get() == nullptr) { - return toStatus(INVALID_OPERATION); - } - - status_t err = holder->sendEvent(event, arg, eventData); - return toStatus(err); -} - -Return CasImpl::sendSessionEvent(const HidlCasSessionId& sessionId, int32_t event, - int32_t arg, const HidlCasData& eventData) { - ALOGV("%s", __FUNCTION__); - std::shared_ptr holder = std::atomic_load(&mPluginHolder); - if (holder.get() == nullptr) { - return toStatus(INVALID_OPERATION); - } - - status_t err = holder->sendSessionEvent(sessionId, event, arg, eventData); - return toStatus(err); -} - -Return CasImpl::provision(const hidl_string& provisionString) { - ALOGV("%s: provisionString=%s", __FUNCTION__, provisionString.c_str()); - std::shared_ptr holder = std::atomic_load(&mPluginHolder); - if (holder.get() == nullptr) { - return toStatus(INVALID_OPERATION); - } - - return toStatus(holder->provision(String8(provisionString.c_str()))); -} - -Return CasImpl::refreshEntitlements(int32_t refreshType, const HidlCasData& refreshData) { - ALOGV("%s", __FUNCTION__); - std::shared_ptr holder = std::atomic_load(&mPluginHolder); - if (holder.get() == nullptr) { - return toStatus(INVALID_OPERATION); - } - - status_t err = holder->refreshEntitlements(refreshType, refreshData); - return toStatus(err); -} - -Return CasImpl::release() { - ALOGV("%s: plugin=%p", __FUNCTION__, mPluginHolder.get()); - - std::shared_ptr holder(nullptr); - std::atomic_store(&mPluginHolder, holder); - - return Status::OK; -} - -} // namespace implementation -} // namespace V1_1 -} // namespace cas -} // namespace hardware -} // namespace android diff --git a/cas/1.1/default/CasImpl.h b/cas/1.1/default/CasImpl.h deleted file mode 100644 index 18aee9e457..0000000000 --- a/cas/1.1/default/CasImpl.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2019 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_CAS_V1_1_CAS_IMPL_H_ -#define ANDROID_HARDWARE_CAS_V1_1_CAS_IMPL_H_ - -#include -#include - -namespace android { -struct CasPlugin; - -namespace hardware { -namespace cas { -namespace V1_1 { -struct ICasListener; -namespace implementation { - -using ::android::hardware::cas::V1_0::HidlCasData; -using ::android::hardware::cas::V1_0::HidlCasSessionId; -using ::android::hardware::cas::V1_0::Status; - -class SharedLibrary; - -class CasImpl : public ICas { - public: - CasImpl(const sp& listener); - virtual ~CasImpl(); - - static void OnEvent(void* appData, int32_t event, int32_t arg, uint8_t* data, size_t size); - - static void CallBackExt(void* appData, int32_t event, int32_t arg, uint8_t* data, size_t size, - const CasSessionId* sessionId); - - void init(const sp& library, CasPlugin* plugin); - void onEvent(int32_t event, int32_t arg, uint8_t* data, size_t size); - - void onEvent(const CasSessionId* sessionId, int32_t event, int32_t arg, uint8_t* data, - size_t size); - - // ICas inherits - - virtual Return setPrivateData(const HidlCasData& pvtData) override; - - virtual Return openSession(openSession_cb _hidl_cb) override; - - virtual Return closeSession(const HidlCasSessionId& sessionId) override; - - virtual Return setSessionPrivateData(const HidlCasSessionId& sessionId, - const HidlCasData& pvtData) override; - - virtual Return processEcm(const HidlCasSessionId& sessionId, - const HidlCasData& ecm) override; - - virtual Return processEmm(const HidlCasData& emm) override; - - virtual Return sendEvent(int32_t event, int32_t arg, - const HidlCasData& eventData) override; - - virtual Return sendSessionEvent(const HidlCasSessionId& sessionId, int32_t event, - int32_t arg, const HidlCasData& eventData) override; - - virtual Return provision(const hidl_string& provisionString) override; - - virtual Return refreshEntitlements(int32_t refreshType, - const HidlCasData& refreshData) override; - - virtual Return release() override; - - private: - struct PluginHolder; - sp mLibrary; - std::shared_ptr mPluginHolder; - sp mListener; - - DISALLOW_EVIL_CONSTRUCTORS(CasImpl); -}; - -} // namespace implementation -} // namespace V1_1 -} // namespace cas -} // namespace hardware -} // namespace android - -#endif // ANDROID_HARDWARE_CAS_V1_1_CAS_IMPL_H_ diff --git a/cas/1.1/default/DescramblerImpl.cpp b/cas/1.1/default/DescramblerImpl.cpp deleted file mode 100644 index 36dc1a51d0..0000000000 --- a/cas/1.1/default/DescramblerImpl.cpp +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -//#define LOG_NDEBUG 0 -#define LOG_TAG "android.hardware.cas@1.1-DescramblerImpl" - -#include -#include -#include -#include -#include - -#include "DescramblerImpl.h" -#include "SharedLibrary.h" -#include "TypeConvert.h" - -namespace android { -using hidl::memory::V1_0::IMemory; - -namespace hardware { -namespace cas { -namespace V1_1 { -namespace implementation { - -#define CHECK_SUBSAMPLE_DEF(type) \ - static_assert(sizeof(SubSample) == sizeof(type::SubSample), "SubSample: size doesn't match"); \ - static_assert(offsetof(SubSample, numBytesOfClearData) == \ - offsetof(type::SubSample, mNumBytesOfClearData), \ - "SubSample: numBytesOfClearData offset doesn't match"); \ - static_assert(offsetof(SubSample, numBytesOfEncryptedData) == \ - offsetof(type::SubSample, mNumBytesOfEncryptedData), \ - "SubSample: numBytesOfEncryptedData offset doesn't match") - -CHECK_SUBSAMPLE_DEF(DescramblerPlugin); -CHECK_SUBSAMPLE_DEF(CryptoPlugin); - -DescramblerImpl::DescramblerImpl(const sp& library, DescramblerPlugin* plugin) - : mLibrary(library), mPluginHolder(plugin) { - ALOGV("CTOR: plugin=%p", mPluginHolder.get()); -} - -DescramblerImpl::~DescramblerImpl() { - ALOGV("DTOR: plugin=%p", mPluginHolder.get()); - release(); -} - -Return DescramblerImpl::setMediaCasSession(const HidlCasSessionId& sessionId) { - ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).string()); - - std::shared_ptr holder = std::atomic_load(&mPluginHolder); - if (holder.get() == nullptr) { - return toStatus(INVALID_OPERATION); - } - - return toStatus(holder->setMediaCasSession(sessionId)); -} - -Return DescramblerImpl::requiresSecureDecoderComponent(const hidl_string& mime) { - std::shared_ptr holder = std::atomic_load(&mPluginHolder); - if (holder.get() == nullptr) { - return false; - } - - return holder->requiresSecureDecoderComponent(String8(mime.c_str())); -} - -static inline bool validateRangeForSize(uint64_t offset, uint64_t length, uint64_t size) { - return isInRange(0, size, offset, length); -} - -Return DescramblerImpl::descramble(ScramblingControl scramblingControl, - const hidl_vec& subSamples, - const SharedBuffer& srcBuffer, uint64_t srcOffset, - const DestinationBuffer& dstBuffer, uint64_t dstOffset, - descramble_cb _hidl_cb) { - ALOGV("%s", __FUNCTION__); - - // hidl_memory's size is stored in uint64_t, but mapMemory's mmap will map - // size in size_t. If size is over SIZE_MAX, mapMemory mapMemory could succeed - // but the mapped memory's actual size will be smaller than the reported size. - if (srcBuffer.heapBase.size() > SIZE_MAX) { - ALOGE("Invalid hidl_memory size: %llu", srcBuffer.heapBase.size()); - android_errorWriteLog(0x534e4554, "79376389"); - _hidl_cb(toStatus(BAD_VALUE), 0, NULL); - return Void(); - } - - sp srcMem = mapMemory(srcBuffer.heapBase); - - // Validate if the offset and size in the SharedBuffer is consistent with the - // mapped ashmem, since the offset and size is controlled by client. - if (srcMem == NULL) { - ALOGE("Failed to map src buffer."); - _hidl_cb(toStatus(BAD_VALUE), 0, NULL); - return Void(); - } - if (!validateRangeForSize(srcBuffer.offset, srcBuffer.size, (uint64_t)srcMem->getSize())) { - ALOGE("Invalid src buffer range: offset %llu, size %llu, srcMem size %llu", - srcBuffer.offset, srcBuffer.size, (uint64_t)srcMem->getSize()); - android_errorWriteLog(0x534e4554, "67962232"); - _hidl_cb(toStatus(BAD_VALUE), 0, NULL); - return Void(); - } - - // use 64-bit here to catch bad subsample size that might be overflowing. - uint64_t totalBytesInSubSamples = 0; - for (size_t i = 0; i < subSamples.size(); i++) { - totalBytesInSubSamples += - (uint64_t)subSamples[i].numBytesOfClearData + subSamples[i].numBytesOfEncryptedData; - } - // Further validate if the specified srcOffset and requested total subsample size - // is consistent with the source shared buffer size. - if (!validateRangeForSize(srcOffset, totalBytesInSubSamples, srcBuffer.size)) { - ALOGE("Invalid srcOffset and subsample size: " - "srcOffset %llu, totalBytesInSubSamples %llu, srcBuffer size %llu", - srcOffset, totalBytesInSubSamples, srcBuffer.size); - android_errorWriteLog(0x534e4554, "67962232"); - _hidl_cb(toStatus(BAD_VALUE), 0, NULL); - return Void(); - } - - void* srcPtr = (uint8_t*)(void*)srcMem->getPointer() + srcBuffer.offset; - void* dstPtr = NULL; - if (dstBuffer.type == BufferType::SHARED_MEMORY) { - // When using shared memory, src buffer is also used as dst, - // we don't map it again here. - dstPtr = srcPtr; - - // In this case the dst and src would be the same buffer, need to validate - // dstOffset against the buffer size too. - if (!validateRangeForSize(dstOffset, totalBytesInSubSamples, srcBuffer.size)) { - ALOGE("Invalid dstOffset and subsample size: " - "dstOffset %llu, totalBytesInSubSamples %llu, srcBuffer size %llu", - dstOffset, totalBytesInSubSamples, srcBuffer.size); - android_errorWriteLog(0x534e4554, "67962232"); - _hidl_cb(toStatus(BAD_VALUE), 0, NULL); - return Void(); - } - } else { - native_handle_t* handle = - const_cast(dstBuffer.secureMemory.getNativeHandle()); - dstPtr = static_cast(handle); - } - - // Get a local copy of the shared_ptr for the plugin. Note that before - // calling the HIDL callback, this shared_ptr must be manually reset, - // since the client side could proceed as soon as the callback is called - // without waiting for this method to go out of scope. - std::shared_ptr holder = std::atomic_load(&mPluginHolder); - if (holder.get() == nullptr) { - _hidl_cb(toStatus(INVALID_OPERATION), 0, NULL); - return Void(); - } - - // Casting hidl SubSample to DescramblerPlugin::SubSample, but need - // to ensure structs are actually idential - - int32_t result = - holder->descramble(dstBuffer.type != BufferType::SHARED_MEMORY, - (DescramblerPlugin::ScramblingControl)scramblingControl, - subSamples.size(), (DescramblerPlugin::SubSample*)subSamples.data(), - srcPtr, srcOffset, dstPtr, dstOffset, NULL); - - holder.reset(); - _hidl_cb(toStatus(result >= 0 ? OK : result), result, NULL); - return Void(); -} - -Return DescramblerImpl::release() { - ALOGV("%s: plugin=%p", __FUNCTION__, mPluginHolder.get()); - - std::shared_ptr holder(nullptr); - std::atomic_store(&mPluginHolder, holder); - - return Status::OK; -} - -} // namespace implementation -} // namespace V1_1 -} // namespace cas -} // namespace hardware -} // namespace android diff --git a/cas/1.1/default/DescramblerImpl.h b/cas/1.1/default/DescramblerImpl.h deleted file mode 100644 index a1f66ae464..0000000000 --- a/cas/1.1/default/DescramblerImpl.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2019 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_CAS_V1_1_DESCRAMBLER_IMPL_H_ -#define ANDROID_HARDWARE_CAS_V1_1_DESCRAMBLER_IMPL_H_ - -#include -#include - -namespace android { -struct DescramblerPlugin; -using namespace hardware::cas::native::V1_0; - -namespace hardware { -namespace cas { -namespace V1_1 { -namespace implementation { - -using ::android::hardware::cas::V1_0::HidlCasSessionId; -using ::android::hardware::cas::V1_0::Status; - -class SharedLibrary; - -class DescramblerImpl : public IDescrambler { - public: - DescramblerImpl(const sp& library, DescramblerPlugin* plugin); - virtual ~DescramblerImpl(); - - virtual Return setMediaCasSession(const HidlCasSessionId& sessionId) override; - - virtual Return requiresSecureDecoderComponent(const hidl_string& mime) override; - - virtual Return descramble(ScramblingControl scramblingControl, - const hidl_vec& subSamples, - const SharedBuffer& srcBuffer, uint64_t srcOffset, - const DestinationBuffer& dstBuffer, uint64_t dstOffset, - descramble_cb _hidl_cb) override; - - virtual Return release() override; - - private: - sp mLibrary; - std::shared_ptr mPluginHolder; - - DISALLOW_EVIL_CONSTRUCTORS(DescramblerImpl); -}; - -} // namespace implementation -} // namespace V1_1 -} // namespace cas -} // namespace hardware -} // namespace android - -#endif // ANDROID_HARDWARE_CAS_V1_1_DESCRAMBLER_IMPL_H_ diff --git a/cas/1.1/default/FactoryLoader.h b/cas/1.1/default/FactoryLoader.h deleted file mode 100644 index c4a48e2852..0000000000 --- a/cas/1.1/default/FactoryLoader.h +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (C) 2019 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_CAS_V1_1_FACTORY_LOADER_H_ -#define ANDROID_HARDWARE_CAS_V1_1_FACTORY_LOADER_H_ - -#include -#include -#include -#include -#include -#include "SharedLibrary.h" - -using namespace std; - -namespace android { -namespace hardware { -namespace cas { -namespace V1_1 { -namespace implementation { - -using ::android::hardware::cas::V1_0::HidlCasPluginDescriptor; - -template -class FactoryLoader { - public: - FactoryLoader(const char* name) : mFactory(NULL), mCreateFactoryFuncName(name) {} - - virtual ~FactoryLoader() { closeFactory(); } - - bool findFactoryForScheme(int32_t CA_system_id, sp* library = NULL, - T** factory = NULL); - - bool enumeratePlugins(vector* results); - - private: - typedef T* (*CreateFactoryFunc)(); - - Mutex mMapLock; - T* mFactory; - const char* mCreateFactoryFuncName; - sp mLibrary; - KeyedVector mCASystemIdToLibraryPathMap; - KeyedVector > mLibraryPathToOpenLibraryMap; - - bool loadFactoryForSchemeFromPath(const String8& path, int32_t CA_system_id, - sp* library, T** factory); - - bool queryPluginsFromPath(const String8& path, vector* results); - - bool openFactory(const String8& path); - void closeFactory(); -}; - -template -bool FactoryLoader::findFactoryForScheme(int32_t CA_system_id, sp* library, - T** factory) { - if (library != NULL) { - library->clear(); - } - if (factory != NULL) { - *factory = NULL; - } - - Mutex::Autolock autoLock(mMapLock); - - // first check cache - ssize_t index = mCASystemIdToLibraryPathMap.indexOfKey(CA_system_id); - if (index >= 0) { - return loadFactoryForSchemeFromPath(mCASystemIdToLibraryPathMap[index], CA_system_id, - library, factory); - } - - // no luck, have to search - String8 dirPath("/vendor/lib/mediacas"); - DIR* pDir = opendir(dirPath.string()); - - if (pDir == NULL) { - ALOGE("Failed to open plugin directory %s", dirPath.string()); - return false; - } - - struct dirent* pEntry; - while ((pEntry = readdir(pDir))) { - String8 pluginPath = dirPath + "/" + pEntry->d_name; - if (pluginPath.getPathExtension() == ".so") { - if (loadFactoryForSchemeFromPath(pluginPath, CA_system_id, library, factory)) { - mCASystemIdToLibraryPathMap.add(CA_system_id, pluginPath); - closedir(pDir); - - return true; - } - } - } - - closedir(pDir); - - ALOGE("Failed to find plugin"); - return false; -} - -template -bool FactoryLoader::enumeratePlugins(vector* results) { - ALOGI("enumeratePlugins"); - - results->clear(); - - String8 dirPath("/vendor/lib/mediacas"); - DIR* pDir = opendir(dirPath.string()); - - if (pDir == NULL) { - ALOGE("Failed to open plugin directory %s", dirPath.string()); - return false; - } - - Mutex::Autolock autoLock(mMapLock); - - struct dirent* pEntry; - while ((pEntry = readdir(pDir))) { - String8 pluginPath = dirPath + "/" + pEntry->d_name; - if (pluginPath.getPathExtension() == ".so") { - queryPluginsFromPath(pluginPath, results); - } - } - return true; -} - -template -bool FactoryLoader::loadFactoryForSchemeFromPath(const String8& path, int32_t CA_system_id, - sp* library, T** factory) { - closeFactory(); - - if (!openFactory(path) || !mFactory->isSystemIdSupported(CA_system_id)) { - closeFactory(); - return false; - } - - if (library != NULL) { - *library = mLibrary; - } - if (factory != NULL) { - *factory = mFactory; - } - return true; -} - -template -bool FactoryLoader::queryPluginsFromPath(const String8& path, - vector* results) { - closeFactory(); - - vector descriptors; - if (!openFactory(path) || mFactory->queryPlugins(&descriptors) != OK) { - closeFactory(); - return false; - } - - for (auto it = descriptors.begin(); it != descriptors.end(); it++) { - results->push_back( - HidlCasPluginDescriptor{.caSystemId = it->CA_system_id, .name = it->name.c_str()}); - } - return true; -} - -template -bool FactoryLoader::openFactory(const String8& path) { - // get strong pointer to open shared library - ssize_t index = mLibraryPathToOpenLibraryMap.indexOfKey(path); - if (index >= 0) { - mLibrary = mLibraryPathToOpenLibraryMap[index].promote(); - } else { - index = mLibraryPathToOpenLibraryMap.add(path, NULL); - } - - if (!mLibrary.get()) { - mLibrary = new SharedLibrary(path); - if (!*mLibrary) { - return false; - } - - mLibraryPathToOpenLibraryMap.replaceValueAt(index, mLibrary); - } - - CreateFactoryFunc createFactory = (CreateFactoryFunc)mLibrary->lookup(mCreateFactoryFuncName); - if (createFactory == NULL || (mFactory = createFactory()) == NULL) { - return false; - } - return true; -} - -template -void FactoryLoader::closeFactory() { - delete mFactory; - mFactory = NULL; - mLibrary.clear(); -} - -} // namespace implementation -} // namespace V1_1 -} // namespace cas -} // namespace hardware -} // namespace android - -#endif // ANDROID_HARDWARE_CAS_V1_1_FACTORY_LOADER_H_ diff --git a/cas/1.1/default/MediaCasService.cpp b/cas/1.1/default/MediaCasService.cpp deleted file mode 100644 index e2d3357023..0000000000 --- a/cas/1.1/default/MediaCasService.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -//#define LOG_NDEBUG 0 -#define LOG_TAG "android.hardware.cas@1.1-MediaCasService" - -#include -#include -#include -#include - -#include "CasImpl.h" -#include "DescramblerImpl.h" -#include "MediaCasService.h" - -namespace android { -namespace hardware { -namespace cas { -namespace V1_1 { -namespace implementation { - -MediaCasService::MediaCasService() - : mCasLoader("createCasFactory"), mDescramblerLoader("createDescramblerFactory") {} - -MediaCasService::~MediaCasService() {} - -Return MediaCasService::enumeratePlugins(enumeratePlugins_cb _hidl_cb) { - ALOGV("%s", __FUNCTION__); - - vector results; - mCasLoader.enumeratePlugins(&results); - - _hidl_cb(results); - return Void(); -} - -Return MediaCasService::isSystemIdSupported(int32_t CA_system_id) { - ALOGV("isSystemIdSupported: CA_system_id=%d", CA_system_id); - - return mCasLoader.findFactoryForScheme(CA_system_id); -} - -Return> MediaCasService::createPlugin(int32_t /* CA_system_id */, - const sp& /* listener */) { - ALOGE("%s:Use createPluginExt to create plugin with cas@1.1", __FUNCTION__); - - sp result; - /* - CasFactory *factory; - sp library; - if (mCasLoader.findFactoryForScheme(CA_system_id, &library, &factory)) { - CasPlugin *plugin = NULL; - sp casImpl = new CasImpl(listener); - if (factory->createPlugin(CA_system_id, casImpl.get(), - CasImpl::OnEvent, &plugin) == OK && plugin != NULL) { - casImpl->init(library, plugin); - result = casImpl; - } - } - */ - return result; -} - -Return> MediaCasService::createPluginExt(int32_t CA_system_id, - const sp& listener) { - ALOGV("%s: CA_system_id=%d", __FUNCTION__, CA_system_id); - - sp result; - - CasFactory* factory; - sp library; - if (mCasLoader.findFactoryForScheme(CA_system_id, &library, &factory)) { - CasPlugin* plugin = NULL; - sp casImpl = new CasImpl(listener); - if (factory->createPlugin(CA_system_id, casImpl.get(), &CasImpl::CallBackExt, &plugin) == - OK && - plugin != NULL) { - casImpl->init(library, plugin); - result = casImpl; - } - } - - return result; -} - -Return MediaCasService::isDescramblerSupported(int32_t CA_system_id) { - ALOGV("%s: CA_system_id=%d", __FUNCTION__, CA_system_id); - - return mDescramblerLoader.findFactoryForScheme(CA_system_id); -} - -Return> MediaCasService::createDescrambler(int32_t CA_system_id) { - ALOGV("%s: CA_system_id=%d", __FUNCTION__, CA_system_id); - - sp result; - - DescramblerFactory* factory; - sp library; - if (mDescramblerLoader.findFactoryForScheme(CA_system_id, &library, &factory)) { - DescramblerPlugin* plugin = NULL; - if (factory->createPlugin(CA_system_id, &plugin) == OK && plugin != NULL) { - result = new DescramblerImpl(library, plugin); - } - } - - return result; -} - -} // namespace implementation -} // namespace V1_1 -} // namespace cas -} // namespace hardware -} // namespace android diff --git a/cas/1.1/default/MediaCasService.h b/cas/1.1/default/MediaCasService.h deleted file mode 100644 index ec5a86d9b3..0000000000 --- a/cas/1.1/default/MediaCasService.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2019 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_CAS_V1_1_MEDIA_CAS_SERVICE_H_ -#define ANDROID_HARDWARE_CAS_V1_1_MEDIA_CAS_SERVICE_H_ - -#include - -#include "FactoryLoader.h" - -namespace android { -struct CasFactory; -struct DescramblerFactory; -namespace hardware { -namespace cas { -namespace V1_1 { -namespace implementation { - -using ::android::hardware::cas::V1_0::HidlCasPluginDescriptor; -using ::android::hardware::cas::V1_0::IDescramblerBase; - -class MediaCasService : public IMediaCasService { - public: - MediaCasService(); - - virtual Return enumeratePlugins(enumeratePlugins_cb _hidl_cb) override; - - virtual Return isSystemIdSupported(int32_t CA_system_id) override; - - virtual Return> createPlugin(int32_t CA_system_id, - const sp& listener) override; - - virtual Return> createPluginExt(int32_t CA_system_id, - const sp& listener) override; - - virtual Return isDescramblerSupported(int32_t CA_system_id) override; - - virtual Return> createDescrambler(int32_t CA_system_id) override; - - private: - FactoryLoader mCasLoader; - FactoryLoader mDescramblerLoader; - - virtual ~MediaCasService(); -}; - -} // namespace implementation -} // namespace V1_1 -} // namespace cas -} // namespace hardware -} // namespace android - -#endif // ANDROID_HARDWARE_CAS_V1_1_MEDIA_CAS_SERVICE_H_ diff --git a/cas/1.1/default/SharedLibrary.cpp b/cas/1.1/default/SharedLibrary.cpp deleted file mode 100644 index ffe4bb977a..0000000000 --- a/cas/1.1/default/SharedLibrary.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -//#define LOG_NDEBUG 0 -#define LOG_TAG "android.hardware.cas@1.1-SharedLibrary" - -#include "SharedLibrary.h" -#include -#include -#include - -namespace android { -namespace hardware { -namespace cas { -namespace V1_1 { -namespace implementation { - -SharedLibrary::SharedLibrary(const String8& path) { - mLibHandle = dlopen(path.string(), RTLD_NOW); -} - -SharedLibrary::~SharedLibrary() { - if (mLibHandle != NULL) { - dlclose(mLibHandle); - mLibHandle = NULL; - } -} - -bool SharedLibrary::operator!() const { - return mLibHandle == NULL; -} - -void* SharedLibrary::lookup(const char* symbol) const { - if (!mLibHandle) { - return NULL; - } - // Clear last error before we load the symbol again, - // in case the caller didn't retrieve it. - (void)dlerror(); - return dlsym(mLibHandle, symbol); -} - -const char* SharedLibrary::lastError() const { - const char* error = dlerror(); - return error ? error : "No errors or unknown error"; -} - -} // namespace implementation -} // namespace V1_1 -} // namespace cas -} // namespace hardware -} // namespace android diff --git a/cas/1.1/default/SharedLibrary.h b/cas/1.1/default/SharedLibrary.h deleted file mode 100644 index f4d2ff6b9d..0000000000 --- a/cas/1.1/default/SharedLibrary.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2019 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_CAS_V1_1_SHARED_LIBRARY_H_ -#define ANDROID_HARDWARE_CAS_V1_1_SHARED_LIBRARY_H_ - -#include -#include -#include - -namespace android { -namespace hardware { -namespace cas { -namespace V1_1 { -namespace implementation { - -class SharedLibrary : public RefBase { - public: - explicit SharedLibrary(const String8& path); - ~SharedLibrary(); - - bool operator!() const; - void* lookup(const char* symbol) const; - const char* lastError() const; - - private: - void* mLibHandle; - DISALLOW_EVIL_CONSTRUCTORS(SharedLibrary); -}; - -} // namespace implementation -} // namespace V1_1 -} // namespace cas -} // namespace hardware -} // namespace android - -#endif // ANDROID_HARDWARE_CAS_V1_1_SHARED_LIBRARY_H_ diff --git a/cas/1.1/default/TypeConvert.cpp b/cas/1.1/default/TypeConvert.cpp deleted file mode 100644 index 09ef41ae8f..0000000000 --- a/cas/1.1/default/TypeConvert.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -//#define LOG_NDEBUG 0 -#define LOG_TAG "android.hardware.cas@1.1-TypeConvert" - -#include "TypeConvert.h" -#include - -namespace android { -namespace hardware { -namespace cas { -namespace V1_1 { -namespace implementation { - -Status toStatus(status_t legacyStatus) { - Status status; - switch (legacyStatus) { - case android::OK: - status = Status::OK; - break; - case android::ERROR_CAS_NO_LICENSE: - status = Status::ERROR_CAS_NO_LICENSE; - break; - case android::ERROR_CAS_LICENSE_EXPIRED: - status = Status::ERROR_CAS_LICENSE_EXPIRED; - break; - case android::ERROR_CAS_SESSION_NOT_OPENED: - status = Status::ERROR_CAS_SESSION_NOT_OPENED; - break; - case android::ERROR_CAS_CANNOT_HANDLE: - status = Status::ERROR_CAS_CANNOT_HANDLE; - break; - case android::ERROR_CAS_TAMPER_DETECTED: - status = Status::ERROR_CAS_INVALID_STATE; - break; - case android::BAD_VALUE: - status = Status::BAD_VALUE; - break; - case android::ERROR_CAS_NOT_PROVISIONED: - status = Status::ERROR_CAS_NOT_PROVISIONED; - break; - case android::ERROR_CAS_RESOURCE_BUSY: - status = Status::ERROR_CAS_RESOURCE_BUSY; - break; - case android::ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION: - status = Status::ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION; - break; - case android::ERROR_CAS_DEVICE_REVOKED: - status = Status::ERROR_CAS_DEVICE_REVOKED; - break; - case android::ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED: - status = Status::ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED; - break; - case android::ERROR_CAS_DECRYPT: - status = Status::ERROR_CAS_DECRYPT; - break; - default: - ALOGW("Unable to convert legacy status: %d, defaulting to UNKNOWN", legacyStatus); - status = Status::ERROR_CAS_UNKNOWN; - break; - } - return status; -} - -String8 sessionIdToString(const CasSessionId& sessionId) { - String8 result; - for (size_t i = 0; i < sessionId.size(); i++) { - result.appendFormat("%02x ", sessionId[i]); - } - if (result.isEmpty()) { - result.append("(null)"); - } - return result; -} - -} // namespace implementation -} // namespace V1_1 -} // namespace cas -} // namespace hardware -} // namespace android diff --git a/cas/1.1/default/TypeConvert.h b/cas/1.1/default/TypeConvert.h deleted file mode 100644 index c4a0119926..0000000000 --- a/cas/1.1/default/TypeConvert.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2019 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_CAS_V1_1_TYPE_CONVERT_H -#define ANDROID_HARDWARE_CAS_V1_1_TYPE_CONVERT_H - -#include -#include -#include -#include - -namespace android { -namespace hardware { -namespace cas { -namespace V1_1 { -namespace implementation { - -using ::android::hardware::cas::V1_0::Status; - -Status toStatus(status_t legacyStatus); - -String8 sessionIdToString(const CasSessionId& sessionId); - -} // namespace implementation -} // namespace V1_1 -} // namespace cas -} // namespace hardware -} // namespace android - -#endif // ANDROID_HARDWARE_CAS_V1_1_TYPE_CONVERT_H diff --git a/cas/1.1/default/android.hardware.cas@1.1-service-lazy.rc b/cas/1.1/default/android.hardware.cas@1.1-service-lazy.rc deleted file mode 100644 index 9227b6f7e4..0000000000 --- a/cas/1.1/default/android.hardware.cas@1.1-service-lazy.rc +++ /dev/null @@ -1,9 +0,0 @@ -service vendor.cas-hal-1-1 /vendor/bin/hw/android.hardware.cas@1.1-service-lazy - interface android.hardware.cas@1.1::IMediaCasService default - oneshot - disabled - class hal - user media - group mediadrm drmrpc - ioprio rt 4 - writepid /dev/cpuset/foreground/tasks diff --git a/cas/1.1/default/android.hardware.cas@1.1-service-lazy.xml b/cas/1.1/default/android.hardware.cas@1.1-service-lazy.xml deleted file mode 100644 index c9f13ba34a..0000000000 --- a/cas/1.1/default/android.hardware.cas@1.1-service-lazy.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - android.hardware.cas - hwbinder - 1.1 - - IMediaCasService - default - - - diff --git a/cas/1.1/default/android.hardware.cas@1.1-service.rc b/cas/1.1/default/android.hardware.cas@1.1-service.rc deleted file mode 100644 index 4081fe1e64..0000000000 --- a/cas/1.1/default/android.hardware.cas@1.1-service.rc +++ /dev/null @@ -1,6 +0,0 @@ -service vendor.cas-hal-1-1 /vendor/bin/hw/android.hardware.cas@1.1-service - class hal - user media - group mediadrm drmrpc - ioprio rt 4 - writepid /dev/cpuset/foreground/tasks diff --git a/cas/1.1/default/android.hardware.cas@1.1-service.xml b/cas/1.1/default/android.hardware.cas@1.1-service.xml deleted file mode 100644 index c9f13ba34a..0000000000 --- a/cas/1.1/default/android.hardware.cas@1.1-service.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - android.hardware.cas - hwbinder - 1.1 - - IMediaCasService - default - - - diff --git a/cas/1.1/default/service.cpp b/cas/1.1/default/service.cpp deleted file mode 100644 index 962530370c..0000000000 --- a/cas/1.1/default/service.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -//#define LOG_NDEBUG 0 -#ifdef LAZY_SERVICE -#define LOG_TAG "android.hardware.cas@1.1-service-lazy" -#else -#define LOG_TAG "android.hardware.cas@1.1-service" -#endif - -#include -#include -#include - -#include "MediaCasService.h" - -using android::hardware::configureRpcThreadpool; -using android::hardware::joinRpcThreadpool; -using android::hardware::LazyServiceRegistrar; -using android::hardware::cas::V1_1::IMediaCasService; -using android::hardware::cas::V1_1::implementation::MediaCasService; - -#ifdef LAZY_SERVICE -const bool kLazyService = true; -#else -const bool kLazyService = false; -#endif - -int main() { - configureRpcThreadpool(8, true /* callerWillJoin */); - - // Setup hwbinder service - android::sp service = new MediaCasService(); - android::status_t status; - if (kLazyService) { - auto serviceRegistrar = std::make_shared(); - status = serviceRegistrar->registerService(service); - } else { - status = service->registerAsService(); - } - LOG_ALWAYS_FATAL_IF(status != android::OK, "Error while registering cas service: %d", status); - - joinRpcThreadpool(); - return 0; -} diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml index 89855a0e65..94ffe80aab 100644 --- a/compatibility_matrices/compatibility_matrix.current.xml +++ b/compatibility_matrices/compatibility_matrix.current.xml @@ -121,7 +121,7 @@ android.hardware.cas - 1.0-1 + 1.0 IMediaCasService default From 811024860a5bf4dbbb095c6ed83cd3967741885a Mon Sep 17 00:00:00 2001 From: Victor Chang Date: Fri, 11 Jan 2019 13:44:45 +0000 Subject: [PATCH 443/718] Remove the dependency on ICU Static libxml2 no longer requires ICU4C. Remove the depedency from the build file. Bug: 121468463 Test: Treehugger Change-Id: Ib843fb1071a634f25e27e5291b00d11852ac08a9 --- audio/core/all-versions/vts/functional/Android.bp | 3 --- audio/effect/all-versions/vts/functional/Android.bp | 3 --- 2 files changed, 6 deletions(-) diff --git a/audio/core/all-versions/vts/functional/Android.bp b/audio/core/all-versions/vts/functional/Android.bp index f434e4226c..88fdb5a1dd 100644 --- a/audio/core/all-versions/vts/functional/Android.bp +++ b/audio/core/all-versions/vts/functional/Android.bp @@ -20,9 +20,6 @@ cc_defaults { static_libs: [ "android.hardware.audio.common.test.utility", "libaudiopolicycomponents", - "libicuuc", - "libicuuc_stubdata", - "libandroidicu", "libmedia_helper", "libxml2", ], diff --git a/audio/effect/all-versions/vts/functional/Android.bp b/audio/effect/all-versions/vts/functional/Android.bp index de6cad9ad0..cccb5c86aa 100644 --- a/audio/effect/all-versions/vts/functional/Android.bp +++ b/audio/effect/all-versions/vts/functional/Android.bp @@ -26,9 +26,6 @@ cc_defaults { "android.hidl.allocator@1.0", "android.hidl.memory@1.0", "libeffectsconfig", - "libicuuc", - "libicuuc_stubdata", - "libandroidicu", "libxml2", ], header_libs: [ From 923b8c5842ee07caae4ec3d78ef1421a8e0c3a29 Mon Sep 17 00:00:00 2001 From: Lev Proleev Date: Wed, 30 Jan 2019 17:14:40 +0000 Subject: [PATCH 444/718] Fix VTS tests. * Adds a specification of invalid scale and zero point for TENSOR_BOOL8. This fixes vts failures for comparison ops. * Removes (FUNDAMENTAL_MIN - 1) from invalid OperationTypes. FUNDAMENTAL_MIN is equal to 0 and resulting -1 was statically casted to uint32_t and passed 4294967295 as an invalid OperationType. However, our validateOperation function interpreted this ID as an extension ID and didn't fail. * Adds mutateOperationOperandTypeSkip for QUANTIZE and DEQUANTIZE. * Adds removeOperandSkip for BIDIRECTIONAL_SEQUENCE_RNN. Fix: 121130841 Fix: 123247345 Test: VtsHalNeuralnetworksV1_2TargetTest --hal_service_instance=android.hardware.neuralnetworks@1.2::IDevice/sample-all Change-Id: Iefb502c6b9301d5470eb4cdaa46d398f1a0e512a --- .../1.2/vts/functional/ValidateModel.cpp | 34 +++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp index a0f11ebbaf..3b8e3dd4c2 100644 --- a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp +++ b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp @@ -157,6 +157,7 @@ static uint32_t getInvalidRank(OperandType type) { case OperandType::UINT32: case OperandType::BOOL: return 1; + case OperandType::TENSOR_BOOL8: case OperandType::TENSOR_FLOAT16: case OperandType::TENSOR_FLOAT32: case OperandType::TENSOR_INT32: @@ -194,6 +195,7 @@ static float getInvalidScale(OperandType type) { case OperandType::INT32: case OperandType::UINT32: case OperandType::BOOL: + case OperandType::TENSOR_BOOL8: case OperandType::TENSOR_FLOAT16: case OperandType::TENSOR_FLOAT32: case OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL: @@ -230,6 +232,7 @@ static std::vector getInvalidZeroPoints(OperandType type) { case OperandType::INT32: case OperandType::UINT32: case OperandType::BOOL: + case OperandType::TENSOR_BOOL8: case OperandType::TENSOR_FLOAT16: case OperandType::TENSOR_FLOAT32: case OperandType::TENSOR_INT32: @@ -283,6 +286,7 @@ static void mutateOperand(Operand* operand, OperandType type) { newOperand.scale = 0.0f; newOperand.zeroPoint = 0; break; + case OperandType::TENSOR_BOOL8: case OperandType::TENSOR_FLOAT16: case OperandType::TENSOR_FLOAT32: newOperand.dimensions = @@ -339,6 +343,10 @@ static bool mutateOperationOperandTypeSkip(size_t operand, OperandType type, con // TENSOR_(FLOAT16|FLOAT32|INT32|QUANT8_ASYMM). // - CAST's argument can be any of TENSOR_(FLOAT16|FLOAT32|INT32|QUANT8_ASYMM). // - RANDOM_MULTINOMIAL's argument can be either TENSOR_FLOAT16 or TENSOR_FLOAT32. + // - DEQUANTIZE input can be any of + // TENSOR_(QUANT8_ASYMM|QUANT8_SYMM|QUANT8_SYMM_PER_CHANNEL), output can + // be of either TENSOR_FLOAT16 or TENSOR_FLOAT32. + // - QUANTIZE input can be either TENSOR_FLOAT16 or TENSOR_FLOAT32 // - CONV_2D filter type (arg 1) can be QUANT8_ASYMM or QUANT8_SYMM_PER_CHANNEL // - DEPTHWISE_CONV_2D filter type (arg 1) can be QUANT8_ASYMM or QUANT8_SYMM_PER_CHANNEL // - GROUPED_CONV_2D filter type (arg 1) can be QUANT8_ASYMM or QUANT8_SYMM_PER_CHANNEL @@ -357,8 +365,22 @@ static bool mutateOperationOperandTypeSkip(size_t operand, OperandType type, con return true; } } break; + case OperationType::QUANTIZE: case OperationType::RANDOM_MULTINOMIAL: { - if (type == OperandType::TENSOR_FLOAT16 || type == OperandType::TENSOR_FLOAT32) { + if (operand == operation.inputs[0] && + (type == OperandType::TENSOR_FLOAT16 || type == OperandType::TENSOR_FLOAT32)) { + return true; + } + } break; + case OperationType::DEQUANTIZE: { + if (operand == operation.inputs[0] && + (type == OperandType::TENSOR_QUANT8_ASYMM || + type == OperandType::TENSOR_QUANT8_SYMM || + type == OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL)) { + return true; + } + if (operand == operation.outputs[0] && + (type == OperandType::TENSOR_FLOAT16 || type == OperandType::TENSOR_FLOAT32)) { return true; } } break; @@ -397,7 +419,6 @@ static void mutateOperationOperandTypeTest(const sp& device, const Mode ///////////////////////// VALIDATE MODEL OPERATION TYPE ///////////////////////// static const uint32_t invalidOperationTypes[] = { - static_cast(OperationTypeRange::FUNDAMENTAL_MIN) - 1, static_cast(OperationTypeRange::FUNDAMENTAL_MAX) + 1, static_cast(OperationTypeRange::OEM_MIN) - 1, static_cast(OperationTypeRange::OEM_MAX) + 1, @@ -484,6 +505,15 @@ static bool removeOperandSkip(size_t operand, const Model& model) { } } } + // BIDIRECTIONAL_SEQUENCE_RNN can have either on or two outputs + // depending on a mergeOutputs parameter + if (operation.type == OperationType::BIDIRECTIONAL_SEQUENCE_RNN) { + for (const size_t outOprand : operation.outputs) { + if (operand == outOprand) { + return true; + } + } + } } return false; } From 100a4eddcfc9e57e2c10409c5a4d4aca9170c8ad Mon Sep 17 00:00:00 2001 From: Jeff Tinker Date: Thu, 31 Jan 2019 09:44:26 -0800 Subject: [PATCH 445/718] Fix comment on removeOfflineLicense bug:117570956 Change-Id: Iad1a15d81066d01387ec9addd420040155216a75 --- drm/1.2/IDrmPlugin.hal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drm/1.2/IDrmPlugin.hal b/drm/1.2/IDrmPlugin.hal index 3c2181573c..7d266f4c7a 100644 --- a/drm/1.2/IDrmPlugin.hal +++ b/drm/1.2/IDrmPlugin.hal @@ -74,7 +74,7 @@ interface IDrmPlugin extends @1.1::IDrmPlugin { * @return status the status of the call. Must be one of OK on * success, BAD_VALUE if the license is not found or * ERROR_DRM_INVALID_STATE if the HAL is in a state where the - * KeySetIds can't be returned. + * KeySetIds can't be removed. */ removeOfflineLicense(KeySetId keySetId) generates (@1.0::Status status); From 49cbed0a714816878debfc38dcfb112eed4a0b80 Mon Sep 17 00:00:00 2001 From: Yu-Han Yang Date: Wed, 23 Jan 2019 12:11:01 -0800 Subject: [PATCH 446/718] Add OTHER to GnssMeasurementCodeType Bug: 112260995 Test: atest VtsHalGnssV2_0TargetTest Change-Id: I3e1b466186bff382bddb76975616d8408a951da5 --- gnss/2.0/IGnssMeasurementCallback.hal | 50 +++++++++++++------ gnss/2.0/default/GnssMeasurement.cpp | 6 +-- .../vts/functional/gnss_hal_test_cases.cpp | 14 ++++-- 3 files changed, 48 insertions(+), 22 deletions(-) diff --git a/gnss/2.0/IGnssMeasurementCallback.hal b/gnss/2.0/IGnssMeasurementCallback.hal index 226934e876..a19c6cd715 100644 --- a/gnss/2.0/IGnssMeasurementCallback.hal +++ b/gnss/2.0/IGnssMeasurementCallback.hal @@ -23,48 +23,48 @@ import @1.1::IGnssMeasurementCallback; interface IGnssMeasurementCallback extends @1.1::IGnssMeasurementCallback { /** * Enumeration of available values for the GNSS Measurement's code type. Similar to the - * Attribute field described in Rinex 3.03, e.g., in Tables 4-10, and Table A2 at the Rinex 3.03 + * Attribute field described in RINEX 3.03, e.g., in Tables 4-10, and Table A2 at the RINEX 3.03 * Update 1 Document. */ enum GnssMeasurementCodeType : uint8_t { /** GALILEO E1A, GALILEO E6A, IRNSS L5A, IRNSS SA. */ - CODE_TYPE_A = 0, + A = 0, /** GALILEO E1B, GALILEO E6B, IRNSS L5B, IRNSS SB. */ - CODE_TYPE_B = 1, + B = 1, /** * GPS L1 C/A, GPS L2 C/A, GLONASS G1 C/A, GLONASS G2 C/A, GALILEO E1C, GALILEO E6C, SBAS * L1 C/A, QZSS L1 C/A, IRNSS L5C. */ - CODE_TYPE_C = 2, + C = 2, /** * GPS L5 I, GLONASS G3 I, GALILEO E5a I, GALILEO E5b I, GALILEO E5a+b I, SBAS L5 I, QZSS L5 * I, BDS B1 I, BDS B2 I, BDS B3 I. */ - CODE_TYPE_I = 3, + I = 3, /** GPS L1C (P), GPS L2C (L), QZSS L1C (P), QZSS L2C (L), LEX(6) L. */ - CODE_TYPE_L = 4, + L = 4, /** GPS L1M, GPS L2M. */ - CODE_TYPE_M = 5, + M = 5, /** GPS L1P, GPS L2P, GLONASS G1P, GLONASS G2P. */ - CODE_TYPE_P = 6, + P = 6, /** * GPS L5 Q, GLONASS G3 Q, GALILEO E5a Q, GALILEO E5b Q, GALILEO E5a+b Q, SBAS L5 Q, QZSS L5 * Q, BDS B1 Q, BDS B2 Q, BDS B3 Q. */ - CODE_TYPE_Q = 7, + Q = 7, /** GPS L1C (D), GPS L2C (M), QZSS L1C (D), QZSS L2C (M), LEX(6) S. */ - CODE_TYPE_S = 8, + S = 8, /** GPS L1 Z-tracking, GPS L2 Z-tracking. */ - CODE_TYPE_W = 9, + W = 9, /** * GPS L1C (D+P), GPS L2C (M+L), GPS L5 (I+Q), GLONASS G3 (I+Q), GALILEO E1 (B+C), GALILEO @@ -72,16 +72,25 @@ interface IGnssMeasurementCallback extends @1.1::IGnssMeasurementCallback { * L1C (D+P), QZSS L2C (M+L), QZSS L5 (I+Q), LEX(6) (S+L), BDS B1 (I+Q), BDS B2 (I+Q), BDS * B3 (I+Q), IRNSS L5 (B+C). */ - CODE_TYPE_X = 10, + X = 10, /** GPS L1Y, GPS L2Y. */ - CODE_TYPE_Y = 11, + Y = 11, /** GALILEO E1 (A+B+C), GALILEO E6 (A+B+C), QZSS L1-SAIF. */ - CODE_TYPE_Z = 12, + Z = 12, /** GPS L1 codeless, GPS L2 codeless. */ - CODE_TYPE_CODELESS = 13 + N = 13, + + /** + * Other code type that does not belong to any of the above code types. + * + * This code type is used in the case that the above code types do not cover all the code + * types introduced in a new version of RINEX standard. When this code type is set, the + * field GnssMeasurement.otherCodeTypeName must specify the new code type. + */ + OTHER = 255 }; /** @@ -106,6 +115,17 @@ interface IGnssMeasurementCallback extends @1.1::IGnssMeasurementCallback { * in-order to properly apply code specific corrections to the psuedorange measurements. */ GnssMeasurementCodeType codeType; + + /** + * The name of the code type when codeType is OTHER. + * + * This is used to specify the observation descriptor defined in GNSS Observation Data File + * Header Section Description in the RINEX standard (Version 3.XX). In RINEX Version 3.03, + * in Appendix Table A2 Attributes are listed as uppercase letters (for instance, "A" for + * "A channel"). In the future, if for instance a code "G" was added in the official RINEX + * standard, "G" could be specified here. + */ + string otherCodeTypeName; }; /** diff --git a/gnss/2.0/default/GnssMeasurement.cpp b/gnss/2.0/default/GnssMeasurement.cpp index dc23db3163..2d34b20446 100644 --- a/gnss/2.0/default/GnssMeasurement.cpp +++ b/gnss/2.0/default/GnssMeasurement.cpp @@ -115,9 +115,9 @@ GnssData GnssMeasurement::getMockMeasurement() { .multipathIndicator = V1_0::IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_UNKNOWN}; V1_1::IGnssMeasurementCallback::GnssMeasurement measurement_1_1 = {.v1_0 = measurement_1_0}; - V2_0::IGnssMeasurementCallback::GnssMeasurement measurement_2_0 = { - .v1_1 = measurement_1_1, - .codeType = IGnssMeasurementCallback::GnssMeasurementCodeType::CODE_TYPE_C}; + V2_0::IGnssMeasurementCallback::GnssMeasurement measurement_2_0 = {.v1_1 = measurement_1_1, + .codeType = IGnssMeasurementCallback::GnssMeasurementCodeType::C, + .otherCodeTypeName = ""}; hidl_vec measurements(1); measurements[0] = measurement_2_0; diff --git a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp index 552cf1b5b1..48f2be8802 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp +++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp @@ -185,10 +185,16 @@ TEST_F(GnssHalTest, TestGnssMeasurementCodeType) { ASSERT_TRUE(last_measurement_.measurements.size() > 0); for (auto measurement : last_measurement_.measurements) { ASSERT_TRUE( - (int)measurement.codeType >= - (int)IGnssMeasurementCallback_2_0::GnssMeasurementCodeType::CODE_TYPE_A && - (int)measurement.codeType <= - (int)IGnssMeasurementCallback_2_0::GnssMeasurementCodeType::CODE_TYPE_CODELESS); + ((int)measurement.codeType >= + (int)IGnssMeasurementCallback_2_0::GnssMeasurementCodeType::A && + (int)measurement.codeType <= + (int)IGnssMeasurementCallback_2_0::GnssMeasurementCodeType::N) || + (int)measurement.codeType == + (int)IGnssMeasurementCallback_2_0::GnssMeasurementCodeType::OTHER); + if ((int)measurement.codeType == + (int)IGnssMeasurementCallback_2_0::GnssMeasurementCodeType::OTHER) { + ASSERT_NE(measurement.otherCodeTypeName, ""); + } } iGnssMeasurement->close(); From 5d2ec0f5f0d94b66a41384feff474933ee87112b Mon Sep 17 00:00:00 2001 From: Lev Proleev Date: Wed, 30 Jan 2019 12:26:50 +0000 Subject: [PATCH 447/718] Sync docs between NeuralNetworks.h and HAL file Test: VtsHalNeuralnetworksV1_2TargetTest Fix: 116445845 Change-Id: I4287a947faa260f69ba50c746bd40a0981548e50 --- neuralnetworks/1.2/types.hal | 4289 +++++++++++++++++++++++++++++++++- 1 file changed, 4274 insertions(+), 15 deletions(-) diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal index 2e48ba016f..3eda14f686 100644 --- a/neuralnetworks/1.2/types.hal +++ b/neuralnetworks/1.2/types.hal @@ -38,6 +38,8 @@ enum OperandType : @1.0::OperandType { * * Values of this operand type are either true or false. A zero value * represents false; any other value represents true. + * + * Available since API level 29. */ BOOL = 6, /** @@ -48,41 +50,49 @@ enum OperandType : @1.0::OperandType { * realValue = integerValue * scale. * * scale is a 32 bit floating point with value greater than zero. + * + * Available since API level 29. */ TENSOR_QUANT16_SYMM = 7, - /** A tensor of IEEE 754 16 bit floating point values. */ + /** + * A tensor of IEEE 754 16 bit floating point values. + * + * Available since API level 29. + */ TENSOR_FLOAT16 = 8, /** * A tensor of 8 bit boolean values. * * Values of this operand type are either true or false. A zero value * represents false; any other value represents true. + * + * Available since API level 29. */ TENSOR_BOOL8 = 9, - /** An IEEE 754 16 bit floating point scalar value. */ + /** + * An IEEE 754 16 bit floating point scalar value. + * + * Available since API level 29. + */ FLOAT16 = 10, /** * A tensor of 8 bit signed integers that represent real numbers. * - * This tensor is associated with additional fields that are - * used to convert the 8 bit signed integer to the real value and vice versa. + * This tensor is associated with additional fields that can + * be used to convert the 8 bit signed integer to the real value and vice versa. * These fields are: * - channelDim: a 32 bit unsigned integer indicating channel dimension. * - scales: an array of positive 32 bit floating point values. * The size of the scales array must be equal to dimensions[channelDim]. - * These fields are located inside Operand's extraParams union, inside the - * SymmPerChannelQuantParams struct. * - * An Operand of this type must use the 'channelQuant' variant of its - * extraParams field. + * The channel dimension of this tensor must not be unknown (dimensions[channelDim] != 0). * - * The channel dimension of this tensor must be known, i.e. - * dimensions[channelDim] must be non-zero. - * - * The formula for real values: + * The formula is: * realValue[..., C, ...] = * integerValue[..., C, ...] * scales[C] * where C is an index in the Channel dimension. + * + * Available since API level 29. */ TENSOR_QUANT8_SYMM_PER_CHANNEL = 11, /** @@ -95,6 +105,8 @@ enum OperandType : @1.0::OperandType { * * The formula is: * real_value = (integer_value - zeroPoint) * scale. + * + * Available since API level 29. */ TENSOR_QUANT16_ASYMM = 12, /** @@ -105,8 +117,24 @@ enum OperandType : @1.0::OperandType { * realValue = integerValue * scale. * * scale is a 32 bit floating point with value greater than zero. + * + * Available since API level 29. */ TENSOR_QUANT8_SYMM = 13, + /* + * DEPRECATED. Since NNAPI 1.2, extensions are the preferred alternative to + * OEM operation and data types. + * + * OEM specific scalar value. + * OEM = 10000, + */ + /* + * DEPRECATED. Since NNAPI 1.2, extensions are the preferred alternative to + * OEM operation and data types. + * + * A tensor of OEM specific values. + * TENSOR_OEM_BYTE = 10001, + */ /* ADDING A NEW FUNDAMENTAL TYPE REQUIRES UPDATING THE VALUE OF * OperandTypeRange::FUNDAMENTAL_MAX. */ @@ -132,64 +160,4295 @@ enum OperandTypeRange : uint32_t { * * The type of an operation in a model. */ -enum OperationType : @1.1::OperationType { - // TODO(b/116445845): Sync docs when all ops are implemented. +enum OperationType : int32_t { + /** + * Adds two tensors, element-wise. + * + * Takes two input tensors of identical {@link OperandType} and compatible + * dimensions. The output is the sum of both input tensors, optionally + * modified by an activation function. + * + * Two dimensions are compatible when: + * 1. they are equal, or + * 2. one of them is 1 + * + * The size of the output is the maximum size along each dimension of the + * input operands. It starts with the trailing dimensions, and works its + * way forward. + * + * Example: + * + * input1.dimension = {4, 1, 2} + * input2.dimension = {5, 4, 3, 1} + * output.dimension = {5, 4, 3, 2} + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: up to 4 + * + * Inputs: + * * 0: A tensor. + * * 1: A tensor of the same {@link OperandType}, and compatible dimensions + * as input0. + * * 2: An {@link OperandType::INT32} scalar, and has to be one of the + * {@link FusedActivationFunc} values. Specifies the activation to + * invoke on the result. + * + * Outputs: + * * 0: The sum, a tensor of the same {@link OperandType} as input0. + * + * Available since API level 27. + */ + ADD = @1.1::OperationType:ADD, + + /** + * Performs a 2-D average pooling operation. + * + * The output dimensions are functions of the filter dimensions, stride, and + * padding. + * + * The values in the output tensor are computed as: + * + * output[b, i, j, channel] = + * sum_{di, dj}( + * input[b, strides[1] * i + di, strides[2] * j + dj, channel] + * ) / sum(1) + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: 4, with "NHWC" or "NCHW" data layout. + * With the default data layout NHWC, the data is stored in the order of: + * [batch, height, width, channels]. Alternatively, the data layout could + * be NCHW, the data storage order of: [batch, channels, height, width]. + * + * Both explicit padding and implicit padding are supported. + * + * Inputs (explicit padding): + * * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying + * the input. + * * 1: An {@link OperandType::INT32} scalar, specifying the padding on + * the left, in the ‘width’ dimension. + * * 2: An {@link OperandType::INT32} scalar, specifying the padding on + * the right, in the ‘width’ dimension. + * * 3: An {@link OperandType::INT32} scalar, specifying the padding on + * the top, in the ‘height’ dimension. + * * 4: An {@link OperandType::INT32} scalar, specifying the padding on + * the bottom, in the ‘height’ dimension. + * * 5: An {@link OperandType::INT32} scalar, specifying the stride when + * walking through input in the ‘width’ dimension. + * * 6: An {@link OperandType::INT32} scalar, specifying the stride when + * walking through input in the ‘height’ dimension. + * * 7: An {@link OperandType::INT32} scalar, specifying the filter + * width. + * * 8: An {@link OperandType::INT32} scalar, specifying the filter + * height. + * * 9: An {@link OperandType::INT32} scalar, and has to be one of the + * {@link FusedActivationFunc} values. Specifies the activation to + * invoke on the result. + * * 10: An optional {@link OperandType::BOOL} scalar, default to false. + * Set to true to specify NCHW data layout for input0 and output0. + * Available since API level 29. + * + * Inputs (implicit padding): + * * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying + * the input. + * * 1: An {@link OperandType::INT32} scalar, specifying the implicit + * padding scheme, has to be one of the + * following values: {0 (NONE), 1 (SAME), 2 (VALID)}. + * * 2: An {@link OperandType::INT32} scalar, specifying the stride when + * walking through input in the ‘width’ dimension. + * * 3: An {@link OperandType::INT32} scalar, specifying the stride when + * walking through input in the ‘height’ dimension. + * * 4: An {@link OperandType::INT32} scalar, specifying the filter + * width. + * * 5: An {@link OperandType::INT32} scalar, specifying the filter + * height. + * * 6: An {@link OperandType::INT32} scalar, and has to be one of the + * {@link FusedActivationFunc} values. Specifies the activation to + * invoke on the result. + * * 7: An optional {@link OperandType::BOOL} scalar, default to false. + * Set to true to specify NCHW data layout for input0 and output0. + * Available since API level 29. + * + * Outputs: + * * 0: The output 4-D tensor, of shape + * [batches, out_height, out_width, depth]. + * + * Available since API level 27. + */ + AVERAGE_POOL_2D = @1.1::OperationType:AVERAGE_POOL_2D, + + /** + * Concatenates the input tensors along the given dimension. + * + * The input tensors must have identical {@link OperandType} and the same + * dimensions except the dimension along the concatenation axis. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} (full support since API + * level 29, see the input section) + * + * Supported tensor rank: up to 4 + * + * Inputs: + * * 0 ~ n-1: The list of n input tensors, of shape + * [D0, D1, ..., Daxis(i), ..., Dm]. + * Before API level 29, all input tensors of + * {@link OperandType::TENSOR_QUANT8_ASYMM} + * must have the same scale and zeroPoint as the output tensor. + * * n: An {@link OperandType::INT32} scalar, specifying the + * concatenation axis. + * + * Outputs: + * * 0: The output, a tensor of the same {@link OperandType} as the input + * tensors. The output shape is [D0, D1, ..., sum(Daxis(i)), ..., Dm]. + * + * Available since API level 27. + */ + CONCATENATION = @1.1::OperationType:CONCATENATION, + + /** + * Performs an 2-D convolution operation. + * + * The CONV_2D op sweeps a 2-D filter that can mix channels together over a + * batch of images, applying the filter to each window of each image of the + * appropriate size. + * + * The output dimensions are functions of the filter dimensions, stride, and + * padding. + * + * The values in the output tensor are computed as: + * + * output[b, i, j, channel] = + * sum_{di, dj, k} ( + * input[b, strides[1] * i + di, strides[2] * j + dj, k] * + * filter[channel, di, dj, k] + * ) + bias[channel] + * + * Supported tensor {@link OperandType} configurations: + * * 32 bit Floating point : + * * * {@link OperandType::TENSOR_FLOAT32} for input, filter, output, and bias. + * + * * Quantized: + * * * {@link OperandType::TENSOR_QUANT8_ASYMM} for input, filter, and output. + * * * {@link OperandType::TENSOR_INT32} for bias (with scale set to + * * * input.scale * filter.scale). + * + * Available since API level 29: + * * Quantized with symetric per channel quantization for the filter: + * * * {@link OperandType::TENSOR_QUANT8_ASYMM} for input, and output. + * * * {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} for filter. + * * * {@link OperandType::TENSOR_INT32} for bias (scale set to 0.0, + * * * each value scaling is separate and equal to input.scale * filter.scales[channel]). + * + * * 16 bit Floating point: + * * {@link OperandType::TENSOR_FLOAT16} for input, filter, output, and bias. + * + * Supported tensor rank: 4, with "NHWC" or "NCHW" data layout. + * With the default data layout NHWC, the data is stored in the order of: + * [batch, height, width, channels]. Alternatively, the data layout could + * be NCHW, the data storage order of: [batch, channels, height, width]. + * + * Both explicit padding and implicit padding are supported. + * + * Inputs (explicit padding): + * * 0: A 4-D tensor, of shape [batches, height, width, depth_in], + * specifying the input. + * * 1: A 4-D tensor, of shape + * [depth_out, filter_height, filter_width, depth_in], specifying the + * filter. For tensor of type + * {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} the channel + * dimension (extraParams.channelQuant.channelDim) must be set to 0. + * * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input + * tensor of type {@link OperandType::TENSOR_FLOAT32} or + * {@link OperandType::TENSOR_FLOAT16}, the bias must be of the same + * type. For filter tensor of {@link OperandType::TENSOR_QUANT8_ASYMM}, + * the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint + * of 0 and bias_scale == input_scale * filter_scale. For filter tensor + * of {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL}, the bias + * should be of {@link OperandType::TENSOR_INT32}, with zeroPoint of + * 0 and bias_scale of 0. The actual scale of each value 'i' is equal to + * bias_scale[i] = input_scale * filter_scale[i]. + * * 3: An {@link OperandType::INT32} scalar, specifying the padding on + * the left, in the ‘width’ dimension. + * * 4: An {@link OperandType::INT32} scalar, specifying the padding on + * the right, in the ‘width’ dimension. + * * 5: An {@link OperandType::INT32} scalar, specifying the padding on + * the top, in the ‘height’ dimension. + * * 6: An {@link OperandType::INT32} scalar, specifying the padding on + * the bottom, in the ‘height’ dimension. + * * 7: An {@link OperandType::INT32} scalar, specifying the stride when + * walking through input in the ‘width’ dimension. + * * 8: An {@link OperandType::INT32} scalar, specifying the stride when + * walking through input in the ‘height’ dimension. + * * 9: An {@link OperandType::INT32} scalar, and has to be one of the + * {@link FusedActivationFunc} values. Specifies the activation to + * invoke on the result. + * * 10: An optional {@link OperandType::BOOL} scalar, default to false. + * Set to true to specify NCHW data layout for input0 and output0. + * Available since API level 29. + * * 11: An optional {@link OperandType::INT32} scalar, specifying the dilation + * factor for width. Defaults to 1. If set to k > 1, there will be k-1 skipped + * cells between each filter element on width dimension. If this input is set, + * input 12 (dilation factor for height) must be specified as well. + * Available since API level 29. + * * 12: An optional {@link OperandType::INT32} scalar, specifying the dilation + * factor for height. Defaults to 1. If set to k > 1, there will be k-1 skipped + * cells between each filter element on height dimension. If this input is set, + * input 11 (dilation factor for width) must be specified as well. + * Available since API level 29. + * + * Inputs (implicit padding): + * * 0: A 4-D tensor, of shape [batches, height, width, depth_in], + * specifying the input. + * * 1: A 4-D tensor, of shape + * [depth_out, filter_height, filter_width, depth_in], specifying the + * filter. For tensor of type + * {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} the channel + * dimension (extraParams.channelQuant.channelDim) must be set to 0. + * * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input + * tensor of type {@link OperandType::TENSOR_FLOAT32} or + * {@link OperandType::TENSOR_FLOAT16}, the bias must be of the same + * type. For filter tensor of {@link OperandType::TENSOR_QUANT8_ASYMM}, + * the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint + * of 0 and bias_scale == input_scale * filter_scale. For filter tensor + * of {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL}, the bias + * should be of {@link OperandType::TENSOR_INT32}, with zeroPoint of + * 0 and bias_scale of 0. The actual scale of each value 'i' is equal to + * bias_scale[i] = input_scale * filter_scale[i]. + * * 3: An {@link OperandType::INT32} scalar, specifying the implicit + * padding scheme, has to be one of the + * following values: {0 (NONE), 1 (SAME), 2 (VALID)}. + * * 4: An {@link OperandType::INT32} scalar, specifying the stride when + * walking through input in the ‘width’ dimension. + * * 5: An {@link OperandType::INT32} scalar, specifying the stride when + * walking through input in the ‘height’ dimension. + * * 6: An {@link OperandType::INT32} scalar, and has to be one of the + * {@link FusedActivationFunc} values. Specifies the activation to + * invoke on the result. + * * 7: An optional {@link OperandType::BOOL} scalar, default to false. + * Set to true to specify NCHW data layout for input0 and output0. + * Available since API level 29. + * * 8: An optional {@link OperandType::INT32} scalar, specifying the dilation + * factor for width. Defaults to 1. If set to k > 1, there will be k-1 skipped + * cells between each filter element on width dimension. If this input is set, + * input 9 (dilation factor for height) must be specified as well. + * Available since API level 29. + * * 9: An optional {@link OperandType::INT32} scalar, specifying the dilation + * factor for height. Defaults to 1. If set to k > 1, there will be k-1 skipped + * cells between each filter element on height dimension. If this input is set, + * input 8 (dilation factor for width) must be specified as well. + * Available since API level 29. + * + * Outputs: + * * 0: The output 4-D tensor, of shape + * [batches, out_height, out_width, depth_out]. For output tensor of + * {@link OperandType::TENSOR_QUANT8_ASYMM}, the following condition + * must be satisfied: output_scale > input_scale * filter_scale (for + * filter tensor of {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} + * this condition must be true for all filter scales). + * + * Available since API level 27. + */ + CONV_2D = @1.1::OperationType:CONV_2D, + + /** + * Performs a depthwise 2-D convolution operation. + * + * Given an input tensor of shape [batches, height, width, depth_in] and a + * filter tensor of shape [1, filter_height, filter_width, depth_out] + * containing depth_out convolutional filters of depth 1, DEPTHWISE_CONV + * applies a different filter to each input channel (expanding from 1 + * channel to channel_multiplier channels for each), then concatenates the + * results together. + * + * The output has depth_out = depth_in * depth_multiplier channels. + * The output dimensions are functions of the filter dimensions, stride, and + * padding. + * + * The values in the output tensor are computed as: + * + * output[b, i, j, k * channel_multiplier + q] = + * sum_{di, dj} ( + * input[b, strides[1] * i + di, strides[2] * j + dj, k] * + * filter[1, di, dj, k * channel_multiplier + q] + * ) + bias[k * channel_multiplier + q] + * + * Supported tensor {@link OperandType} configurations: + * * 32 bit Floating point : + * * * {@link OperandType::TENSOR_FLOAT32} for input, filter, output, and bias. + * + * * Quantized: + * * * {@link OperandType::TENSOR_QUANT8_ASYMM} for input, filter, and output. + * * * {@link OperandType::TENSOR_INT32} for bias (with scale set to + * * * input.scale * filter.scale). + * + * Available since API level 29: + * * Quantized with symetric per channel quantization for the filter: + * * * {@link OperandType::TENSOR_QUANT8_ASYMM} for input, and output. + * * * {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} for filter. + * * * {@link OperandType::TENSOR_INT32} for bias (scale set to 0.0, + * * * each value scaling is separate and equal to input.scale * filter.scales[channel]). + * + * Supported tensor rank: 4, with "NHWC" or "NCHW" data layout. + * With the default data layout NHWC, the data is stored in the order of: + * [batch, height, width, channels]. Alternatively, the data layout could + * be NCHW, the data storage order of: [batch, channels, height, width]. + * + * Both explicit padding and implicit padding are supported. + * + * Inputs (explicit padding): + * * 0: A 4-D tensor, of shape [batches, height, width, depth_in], + * specifying the input. + * * 1: A 4-D tensor, of shape [1, filter_height, filter_width, depth_out], + * specifying the filter. For tensor of type + * {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} the channel + * dimension (extraParams.channelQuant.channelDim) must be set to 3. + * * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input + * tensor of type {@link OperandType::TENSOR_FLOAT32} or + * {@link OperandType::TENSOR_FLOAT16}, the bias must be of the same + * type. For filter tensor of {@link OperandType::TENSOR_QUANT8_ASYMM}, + * the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint + * of 0 and bias_scale == input_scale * filter_scale. For filter tensor + * of {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL}, the bias + * should be of {@link OperandType::TENSOR_INT32}, with zeroPoint of + * 0 and bias_scale of 0. The actual scale of each value 'i' is equal to + * bias_scale[i] = input_scale * filter_scale[i]. + * * 3: An {@link OperandType::INT32} scalar, specifying the padding on + * the left, in the ‘width’ dimension. + * * 4: An {@link OperandType::INT32} scalar, specifying the padding on + * the right, in the ‘width’ dimension. + * * 5: An {@link OperandType::INT32} scalar, specifying the padding on + * the top, in the ‘height’ dimension. + * * 6: An {@link OperandType::INT32} scalar, specifying the padding on + * the bottom, in the ‘height’ dimension. + * * 7: An {@link OperandType::INT32} scalar, specifying the stride when + * walking through input in the ‘width’ dimension. + * * 8: An {@link OperandType::INT32} scalar, specifying the stride when + * walking through input in the ‘height’ dimension. + * * 9: An {@link OperandType::INT32} scalar, specifying the depthwise + * multiplier. + * * 10: An {@link OperandType::INT32} scalar, and has to be one of the + * {@link FusedActivationFunc} values. Specifies the activation to + * invoke on the result. + * * 11: An optional {@link OperandType::BOOL} scalar, default to false. + * Set to true to specify NCHW data layout for input0 and output0. + * Available since API level 29. + * * 12: An optional {@link OperandType::INT32} scalar, specifying the dilation + * factor for width. Defaults to 1. If set to k > 1, there will be k-1 skipped + * cells between each filter element on width dimension. If this input is set, + * input 13 (dilation factor for height) must be specified as well. + * Available since API level 29. + * * 13: An optional {@link OperandType::INT32} scalar, specifying the dilation + * factor for height. Defaults to 1. If set to k > 1, there will be k-1 skipped + * cells between each filter element on height dimension. If this input is set, + * input 12 (dilation factor for width) must be specified as well. + * Available since API level 29. + * + * Inputs (implicit padding): + * * 0: A 4-D tensor, of shape [batches, height, width, depth_in], + * specifying the input. + * * 1: A 4-D tensor, of shape [1, filter_height, filter_width, depth_out], + * specifying the filter. + * * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input + * tensor of type {@link OperandType::TENSOR_FLOAT32} or + * {@link OperandType::TENSOR_FLOAT16}, the bias must be of the same + * type. For filter tensor of {@link OperandType::TENSOR_QUANT8_ASYMM}, + * the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint + * of 0 and bias_scale == input_scale * filter_scale. For filter tensor + * of {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL}, the bias + * should be of {@link OperandType::TENSOR_INT32}, with zeroPoint of + * 0 and bias_scale of 0. The actual scale of each value 'i' is equal to + * bias_scale[i] = input_scale * filter_scale[i]. + * * 3: An {@link OperandType::INT32} scalar, specifying the implicit + * padding scheme, has to be one of the + * following values: {0 (NONE), 1 (SAME), 2 (VALID)}. + * * 4: An {@link OperandType::INT32} scalar, specifying the stride when + * walking through input in the ‘width’ dimension. + * * 5: An {@link OperandType::INT32} scalar, specifying the stride when + * walking through input in the ‘height’ dimension. + * * 6: An {@link OperandType::INT32} scalar, specifying the depthwise + * multiplier. + * * 7: An {@link OperandType::INT32} scalar, and has to be one of the + * {@link FusedActivationFunc} values. Specifies the activation to + * invoke on the result. + * * 8: An optional {@link OperandType::BOOL} scalar, default to false. + * Set to true to specify NCHW data layout for input0 and output0. + * Available since API level 29. + * * 9: An optional {@link OperandType::INT32} scalar, specifying the dilation + * factor for width. Defaults to 1. If set to k > 1, there will be k-1 skipped + * cells between each filter element on width dimension. If this input is set, + * input 10 (dilation factor for height) must be specified as well. + * Available since API level 29. + * * 10: An optional {@link OperandType::INT32} scalar, specifying the dilation + * factor for height. Defaults to 1. If set to k > 1, there will be k-1 skipped + * cells between each filter element on height dimension. If this input is set, + * input 9 (dilation factor for width) must be specified as well. + * Available since API level 29. + + * + * Outputs: + * * 0: The output 4-D tensor, of shape + * [batches, out_height, out_width, depth_out]. For output tensor of + * {@link OperandType::TENSOR_QUANT8_ASYMM}, the following condition + * must be satisfied: output_scale > input_scale * filter_scale (for + * filter tensor of {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} + * this condition must be true for all filter scales). + * + * Available since API level 27. + */ + DEPTHWISE_CONV_2D = @1.1::OperationType:DEPTHWISE_CONV_2D, + + /** + * Rearranges data from depth into blocks of spatial data. + * + * More specifically, this op outputs a copy of the input tensor where + * values from the depth dimension are moved in spatial blocks to the height + * and width dimensions. The value block_size indicates the input block size + * and how the data is moved. + * + * Chunks of data of size block_size * block_size from depth are rearranged + * into non-overlapping blocks of size block_size x block_size. + * + * The width of the output tensor is input_depth * block_size, whereas the + * height is input_height * block_size. The depth of the input tensor must + * be divisible by block_size * block_size + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: 4, with "NHWC" or "NCHW" data layout. + * With the default data layout NHWC, the data is stored in the order of: + * [batch, height, width, channels]. Alternatively, the data layout could + * be NCHW, the data storage order of: [batch, channels, height, width]. + * + * Inputs: + * * 0: A 4-D tensor, of shape [batches, height, width, depth_in], + * specifying the input. + * * 1: An {@link OperandType::INT32} scalar, specifying the block_size. + * block_size must be >=1 and block_size * block_size must be a divisor + * of the input depth. + * * 2: An optional {@link OperandType::BOOL} scalar, default to false. + * Set to true to specify NCHW data layout for input0 and output0. + * Available since API level 29. + * + * Outputs: + * * 0: The output 4-D tensor, of shape [batch, height*block_size, + * width*block_size, depth/(block_size*block_size)]. + * + * Available since API level 27. + */ + DEPTH_TO_SPACE = @1.1::OperationType:DEPTH_TO_SPACE, + + /** + * Dequantizes the input tensor. + * + * The formula is: + * + * output = (input - zeroPoint) * scale. + * + * Supported input tensor {@link OperandType}: + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * * {@link OperandType::TENSOR_QUANT8_SYMM} (since API level 29) + * * {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} (since API level 29) + * + * Supported output tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) + * * {@link OperandType::TENSOR_FLOAT32}. + * + * Supported tensor rank: up to 4 + * + * Inputs: + * * 0: A tensor. + * + * Outputs: + * * 0: A tensor with the same shape as input0. + * + * Available since API level 27. + */ + DEQUANTIZE = @1.1::OperationType:DEQUANTIZE, + + /** + * Looks up sub-tensors in the input tensor. + * + * This operator takes for input a tensor of values (Values) and + * a one-dimensional tensor of selection indices (Lookups). + * The output tensor is the concatenation of sub-tensors of Values as + * selected by Lookups. + * + * Think of Values as being sliced along its first dimension: + * The entries in Lookups select which slices are concatenated together + * to create the output tensor. + * + * For example, if Values has shape of [40, 200, 300] and + * Lookups has shape of [3], all three values found in Lookups are + * expected to be between 0 and 39. The resulting tensor must + * have shape of [3, 200, 300]. + * + * If a value in Lookups is out of bounds, the operation must fail + * and an error must be reported. + * + * Supported value tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_INT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported value tensor rank: from 2 + * + * Inputs: + * * 0: Lookups. A 1-D tensor of {@link OperandType::TENSOR_INT32}. + * The values are indices into the first dimension of Values. + * * 1: Values. An n-D tensor, where n >= 2, from which sub-tensors are + * extracted. + * + * Output: + * * 0: A n-D tensor with the same rank and shape as the Values + * tensor, except for the first dimension which has the same size + * as Lookups' only dimension. + * + * Available since API level 27. + */ + EMBEDDING_LOOKUP = @1.1::OperationType:EMBEDDING_LOOKUP, + + /** + * Computes element-wise floor() on the input tensor. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) + * * {@link OperandType::TENSOR_FLOAT32} + * + * Supported tensor rank: up to 4 + * + * Inputs: + * * 0: A tensor. + * + * Outputs: + * * 0: The output tensor, of the same {@link OperandType} and dimensions as + * the input tensor. + * + * Available since API level 27. + */ + FLOOR = @1.1::OperationType:FLOOR, + + /** + * Denotes a fully (densely) connected layer, which connects all elements + * in the input tensor with each element in the output tensor. + * + * This layer implements the operation: + * + * outputs = activation(inputs * weights’ + bias) + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: up to 4. + * + * Inputs: + * * 0: A tensor of at least rank 2, specifying the input. If rank is + * greater than 2, then it gets flattened to a 2-D Tensor. The + * (flattened) 2-D Tensor is reshaped (if necessary) to + * [batch_size, input_size], where "input_size" corresponds to the + * number of inputs to the layer, matching the second dimension of + * weights, and "batch_size" is calculated by dividing the number of + * elements by "input_size". + * * 1: A 2-D tensor, specifying the weights, of shape + * [num_units, input_size], where "num_units" corresponds to the number + * of output nodes. + * * 2: A 1-D tensor, of shape [num_units], specifying the bias. For input + * tensor of {@link OperandType::TENSOR_FLOAT32}, the bias should + * also be of {@link OperandType::TENSOR_FLOAT32}. For input tensor + * of {@link OperandType::TENSOR_QUANT8_ASYMM}, the bias should be + * of {@link OperandType::TENSOR_INT32}, with zeroPoint of 0 and + * bias_scale == input_scale * filter_scale. + * * 3: An {@link OperandType::INT32} scalar, and has to be one of the + * {@link FusedActivationFunc} values. Specifies the activation to + * invoke on the result. + * + * Outputs: + * * 0: The output tensor, of shape [batch_size, num_units]. For output + * tensor of {@link OperandType::TENSOR_QUANT8_ASYMM}, the following + * condition must be satisfied: + * output_scale > input_scale * filter_scale. + * + * Available since API level 27. + */ + FULLY_CONNECTED = @1.1::OperationType:FULLY_CONNECTED, + + /** + * Looks up sub-tensors in the input tensor using a key-value map. + * + * This operator takes for input a tensor of values (Values), + * a one-dimensional tensor of selection values (Lookups) and + * a one-dimensional tensor that maps these values to Values + * indexes. The output tensor is the concatenation of sub-tensors of + * Values as selected by Lookups via Keys. + * + * Think of Values as being sliced along its outer-most dimension. + * The output is a concatenation of selected slices, with one slice + * for each entry of Lookups. The slice selected is the one at the + * same index as the Maps entry that matches the value in Lookups. + * + * For a hit, the corresponding sub-tensor of Values is included + * in the Output tensor. For a miss, the corresponding sub-tensor in + * Output must have zero values. + * + * For example, if Values has shape of [40, 200, 300], + * Keys should have a shape of [40]. If Lookups tensor has shape + * of [3], three slices are being concatenated, so the resulting tensor + * must have the shape of [3, 200, 300]. If the first entry in Lookups + * has the value 123456, that value must be located in Keys tensor. + * If the sixth entry of Keys contains 123456, the sixth slice of Values + * must be selected. If no entry in Keys has 123456, a slice of zeroes + * must be concatenated. + * + * Supported value tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_INT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported value tensor rank: from 2 + * + * Inputs: + * * 0: Lookups. A 1-D {@link OperandType::TENSOR_INT32} tensor with + * shape [ k ]. + * * 1: Keys. A 1-D {@link OperandType::TENSOR_INT32} tensor with shape + * [ n ]; Keys and Values pair represent a map, i.e., the ith element + * in Keys (Keys[i]) is the key to select the ith sub-tensor in Values + * (Values[i]), where 0 <= i <= n-1. Keys tensor *MUST* be sorted in + * ascending order. + * * 2: Values. A tensor with shape of [ n, … ]; i.e., the first dimension + * must be n. + * + * Outputs: + * * 0: Output. A tensor with shape [ k …]. + * * 1: Hits. A boolean tensor with shape [ k ] indicates whether the lookup + * hits (True) or not (False). + * Stored as {@link OperandType::TENSOR_QUANT8_ASYMM} with offset 0 + * and scale 1.0f. + * A non-zero byte represents True, a hit. A zero indicates otherwise. + * + * Available since API level 27. + */ + HASHTABLE_LOOKUP = @1.1::OperationType:HASHTABLE_LOOKUP, + + /** + * Applies L2 normalization along the depth dimension. + * + * The values in the output tensor are computed as: + * + * output[batch, row, col, channel] = + * input[batch, row, col, channel] / + * sqrt(sum_{c} pow(input[batch, row, col, c], 2)) + * + * For input tensor with rank less than 4, independently normalizes each + * 1-D slice along dimension dim. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) + * * {@link OperandType::TENSOR_FLOAT32} + * + * Supported tensor rank: up to 4 + * Tensors with rank less than 4 are only supported since API level 29. + * + * Inputs: + * * 0: An n-D tensor, specifying the tensor to be normalized. + * * 1: An optional {@link OperandType::INT32} scalar, default to -1, + * specifying the dimension normalization would be performed on. + * Negative index is used to specify axis from the end (e.g. -1 for + * the last axis). Must be in the range [-n, n). + * Available since API level 29. + * + * Outputs: + * * 0: A tensor of the same {@link OperandType} and same shape as input0. + * + * Available since API level 27. + */ + L2_NORMALIZATION = @1.1::OperationType:L2_NORMALIZATION, + + /** + * Performs an 2-D L2 pooling operation. + * + * The output dimensions are functions of the filter dimensions, stride, and + * padding. + * + * The values in the output tensor are computed as: + * + * output[b, i, j, c] = + * sqrt(sum_{di, dj} pow(input[b, strides[1] * i + di, strides[2] * j + dj, c], 2) / + * sum(1)) + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) + * * {@link OperandType::TENSOR_FLOAT32} + * + * Supported tensor rank: 4, with "NHWC" or "NCHW" data layout. + * With the default data layout NHWC, the data is stored in the order of: + * [batch, height, width, channels]. Alternatively, the data layout could + * be NCHW, the data storage order of: [batch, channels, height, width]. + * + * Both explicit padding and implicit padding are supported. + * + * Inputs (explicit padding): + * * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying + * the input. + * * 1: An {@link OperandType::INT32} scalar, specifying the padding on + * the left, in the ‘width’ dimension. + * * 2: An {@link OperandType::INT32} scalar, specifying the padding on + * the right, in the ‘width’ dimension. + * * 3: An {@link OperandType::INT32} scalar, specifying the padding on + * the top, in the ‘height’ dimension. + * * 4: An {@link OperandType::INT32} scalar, specifying the padding on + * the bottom, in the ‘height’ dimension. + * * 5: An {@link OperandType::INT32} scalar, specifying the stride when + * walking through input in the ‘width’ dimension. + * * 6: An {@link OperandType::INT32} scalar, specifying the stride when + * walking through input in the ‘height’ dimension. + * * 7: An {@link OperandType::INT32} scalar, specifying the filter + * width. + * * 8: An {@link OperandType::INT32} scalar, specifying the filter + * height. + * * 9: An {@link OperandType::INT32} scalar, and has to be one of the + * {@link FusedActivationFunc} values. Specifies the activation to + * invoke on the result. + * * 10: An optional {@link OperandType::BOOL} scalar, default to false. + * Set to true to specify NCHW data layout for input0 and output0. + * Available since API level 29. + * + * Inputs (implicit padding): + * * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying + * the input. + * * 1: An {@link OperandType::INT32} scalar, specifying the implicit + * padding scheme, has to be one of the + * following values: {0 (NONE), 1 (SAME), 2 (VALID)}. + * * 2: An {@link OperandType::INT32} scalar, specifying the stride when + * walking through input in the ‘width’ dimension. + * * 3: An {@link OperandType::INT32} scalar, specifying the stride when + * walking through input in the ‘height’ dimension. + * * 4: An {@link OperandType::INT32} scalar, specifying the filter + * width. + * * 5: An {@link OperandType::INT32} scalar, specifying the filter + * height. + * * 6: An {@link OperandType::INT32} scalar, and has to be one of the + * {@link FusedActivationFunc} values. Specifies the activation to + * invoke on the result. + * * 7: An optional {@link OperandType::BOOL} scalar, default to false. + * Set to true to specify NCHW data layout for input0 and output0. + * Available since API level 29. + * + * Outputs: + * * 0: The output 4-D tensor, of shape + * [batches, out_height, out_width, depth]. + * + * Available since API level 27. + */ + L2_POOL_2D = @1.1::OperationType:L2_POOL_2D, + + /** + * Applies Local Response Normalization along the depth dimension. + * + * The 4-D input tensor is treated as a 3-D array of 1-D vectors (along the + * last dimension), and each vector is normalized independently. Within a + * given vector, each component is divided by the weighted, squared sum of + * inputs within depth_radius. + * + * The output is calculated using this formula: + * + * sqr_sum[a, b, c, d] = sum( + * pow(input[a, b, c, d - depth_radius : d + depth_radius + 1], 2)) + * output = input / pow((bias + alpha * sqr_sum), beta) + * + * For input tensor with rank less than 4, independently normalizes each + * 1-D slice along specified dimension. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) + * * {@link OperandType::TENSOR_FLOAT32} + * + * Supported tensor rank: up to 4 + * Tensors with rank less than 4 are only supported since API level 29. + * + * Inputs: + * * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying + * the input. + * * 1: An {@link OperandType::INT32} scalar, specifying the radius of + * the normalization window. + * * 2: An {@link OperandType::FLOAT32} scalar, specifying the bias, must + * not be zero. + * * 3: An {@link OperandType::FLOAT32} scalar, specifying the scale + * factor, alpha. + * * 4: An {@link OperandType::FLOAT32} scalar, specifying the exponent, + * beta. + * * 5: An optional {@link OperandType::INT32} scalar, default to -1, + * specifying the dimension normalization would be performed on. + * Negative index is used to specify axis from the end (e.g. -1 for + * the last axis). Must be in the range [-n, n). + * Available since API level 29. + * + * Outputs: + * * 0: The output tensor of same shape as input0. + * + * Available since API level 27. + */ + LOCAL_RESPONSE_NORMALIZATION = @1.1::OperationType:LOCAL_RESPONSE_NORMALIZATION, + + /** + * Computes sigmoid activation on the input tensor element-wise. + * + * The output is calculated using this formula: + * + * output = 1 / (1 + exp(-input)) + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: up to 4. + * + * Inputs: + * * 0: A tensor, specifying the input. + * + * Outputs: + * * 0: The output tensor of same shape as input0. + * For {@link OperandType::TENSOR_QUANT8_ASYMM}, + * the scale must be 1.f / 256 and the zeroPoint must be 0. + * + * Available since API level 27. + */ + LOGISTIC = @1.1::OperationType:LOGISTIC, + + /** + * Projects an input to a bit vector via locality senstive hashing. + * + * Supported input tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_INT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported input tensor rank: from 1 + * + * Inputs: + * * 0: Hash functions. Dim.size == 2, DataType: Float. + * Tensor[0].Dim[0]: Number of hash functions. + * Tensor[0].Dim[1]: Number of projected output bits generated by each + * hash function. + * If the projection type is Sparse: + * Tensor[0].Dim[1] + ceil(log2(Tensor[0].Dim[0])) <= 32 + * + * * 1: Input. Dim.size >= 1, no restriction on DataType. + * * 2: Weight. Optional. Dim.size == 1, DataType: Float. + * If not set, each input element is considered to have the same weight + * of 1.0. + * Tensor[1].Dim[0] == Tensor[2].Dim[0] + * * 3: Type: + * Sparse: + * Value LSHProjectionType_SPARSE(=3) (since API level 29). + * Computed bit vector is considered to be sparse. + * Each output element is an int32 made up of multiple bits + * computed from hash functions. + * + * NOTE: To avoid collisions across hash functions, an offset value + * of k * (1 << Tensor[0].Dim[1]) will be added to each signature, + * where k is the index of the hash function. + * + * Value LSHProjectionType_SPARSE_DEPRECATED(=1). + * Legacy behavior that does not include the offset value. + * + * Dense: + * Value LSHProjectionType_DENSE(=2). + * Computed bit vector is considered to be dense. Each output + * element represents a bit and can take the value of either + * 0 or 1. + * + * Outputs: + * * 0: If the projection type is Sparse: + * Output.Dim == { Tensor[0].Dim[0] } + * A tensor of int32 that represents hash signatures, + * + * If the projection type is Dense: + * Output.Dim == { Tensor[0].Dim[0] * Tensor[0].Dim[1] } + * A flattened tensor that represents projected bit vectors. + * + * Available since API level 27. + * The offset value for sparse projections was added in API level 29. + */ + LSH_PROJECTION = @1.1::OperationType:LSH_PROJECTION, + + /** + * Performs a single time step in a Long Short-Term Memory (LSTM) layer + * + * The LSTM operation is described by the following equations. + * + * \f{eqnarray*}{ + * i_t =& \sigma(W_{xi}x_t+W_{hi}h_{t-1}+W_{ci}C_{t-1}+b_i) & \\ + * f_t =& \sigma(W_{xf}x_t+W_{hf}h_{t-1}+W_{cf}C_{t-1}+b_f) & \\ + * C_t =& clip(f_t \odot C_{t-1} + i_t \odot + * g(W_{xc}x_t+W_{hc}h_{t-1}+b_c),\ t_{cell}) & \\ + * o_t =& \sigma(W_{xo}x_t+W_{ho}h_{t-1}+W_{co}C_t+b_o) & \\ + * & & \\ + * & clip(W_{proj}(o_t \odot g(C_t))+b_{proj},\ t_{proj}) + * & if\ there\ is\ a\ projection; \\ + * h_t =& & \\ + * & o_t \odot g(C_t) & otherwise. \\ + * \f} + * Where: + * * \f$x_t\f$ is the input, + * * \f$i_t\f$ is the input gate, + * * \f$f_t\f$ is the forget gate, + * * \f$C_t\f$ is the cell state, + * * \f$o_t\f$ is the output, + * * \f$h_t\f$ is the output state, + * * \f$\sigma\f$ is the logistic sigmoid function, + * * \f$g\f$ is the cell input and cell output activation function, usually + * \f$tahn\f$, + * * \f$W_{xi}\f$ is the input-to-input weight matrix, + * * \f$W_{hi}\f$ is the recurrent to input weight matrix, + * * \f$W_{ci}\f$ is the cell-to-input weight matrix, + * * \f$b_i\f$ is the input gate bias, + * * \f$W_{xf}\f$ is the input-to-forget weight matrix, + * * \f$W_{hf}\f$ is the recurrent-to-forget weight matrix, + * * \f$W_{cf}\f$ is the cell-to-forget weight matrix, + * * \f$b_f\f$ is the forget gate bias, + * * \f$W_{xc}\f$ is the input-to-cell weight matrix, + * * \f$W_{hc}\f$ is the recurrent-to-cell weight matrix, + * * \f$b_c\f$ is the cell bias, + * * \f$W_{xo}\f$ is the input-to-output weight matrix, + * * \f$W_{ho}\f$ is the recurrent-to-output weight matrix, + * * \f$W_{co}\f$ is the cell-to-output weight matrix, + * * \f$b_o\f$ is the output gate bias, + * * \f$W_{proj}\f$ is the projection weight matrix, + * * \f$b_{proj}\f$ is the projection bias, + * * \f$t_{cell}\f$ is the threshold for clipping the cell state, and + * * \f$t_{proj}\f$ is the threshold for clipping the projected output. + * * \f$\odot\f$ is the + * + * Hadamard product that takes two matrices and produces another + * matrix, each element of which is the product of the corresponding + * elements of the input matrices. + * + * Since API level 29 LSTM supports layer normalization. + * In case layer normalization is used, the inputs to internal activation + * functions (sigmoid and \f$g\f$) are normalized, rescaled and recentered + * following an approach from section 3.1 from + * https://arxiv.org/pdf/1607.06450.pdf + * + * The operation has the following independently optional inputs: + * * The input-to-input weights (\f$W_{xi}\f$), recurrent-to-input weights + * (\f$W_{hi}\f$), cell-to-input (\f$W_{ci}\f$) weights, and input gate + * bias (\f$b_i\f$) either all have values, or none of them have values + * (i.e., all set to null). If they have no values, coupling of input and + * forget gates (CIFG) is used, in which case the input gate (\f$i_t\f$) + * is calculated using the following equation instead. + * \f{eqnarray*}{ + * i_t = 1 - f_t + * \f} + * * The cell-to-forget weights (\f$W_{cf}\f$) and cell-to-output weights + * (\f$W_{co}\f$) either both have values or neither of them have values. + * If they have values, the peephole optimization is used. Additionally, + * if CIFG is not used, cell-to-input weights (\f$W_{ci}\f$) is also + * required to have values for peephole optimization. + * * The projection weights (\f$W_{proj}\f$) is required only for the + * recurrent projection layer, and should otherwise have no value. + * * The projection bias (\f$b_{proj}\f$) may (but not required to) have a + * value if the recurrent projection layer exists, and should otherwise + * have no value. + * * (API level >= 29) The four layer normalization weights either all have + * values or none of them have values. Layer normalization is used when + * values are present. + * + * References: + * + * The default non-peephole non-CIFG implementation is based on: + * http://www.bioinf.jku.at/publications/older/2604.pdf + * S. Hochreiter and J. Schmidhuber. "Long Short-Term Memory". Neural + * Computation, 9(8):1735-1780, 1997. + * + * The peephole implementation and projection layer is based on: + * https://research.google.com/pubs/archive/43905.pdf + * Hasim Sak, Andrew Senior, and Francoise Beaufays. "Long short-term memory + * recurrent neural network architectures for large scale acoustic + * modeling." INTERSPEECH, 2014. + * (However, the concept of peephole optimization was introduced in work + * prior to this paper.) + * + * The coupling of input and forget gate (CIFG) is based on: + * http://arxiv.org/pdf/1503.04069.pdf + * Greff et al. "LSTM: A Search Space Odyssey" + * + * The layer normalization is based on: + * https://arxiv.org/pdf/1607.06450.pdf + * Jimmy Ba et al. "Layer Normalization" + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) + * * {@link OperandType::TENSOR_FLOAT32} + * + * All input and output tensors must be of the same type. + * + * Inputs: + * * 0: The input (\f$x_t\f$). + * A 2-D tensor of shape [batch_size, input_size], where “batch_size” + * corresponds to the batching dimension, and “input_size” is the size + * of the input. + * * 1: The input-to-input weights (\f$W_{xi}\f$). Optional. + * A 2-D tensor of shape [num_units, input_size], where “num_units” + * corresponds to the number of cell units. + * * 2: The input-to-forget weights (\f$W_{xf}\f$). + * A 2-D tensor of shape [num_units, input_size]. + * * 3: The input-to-cell weights (\f$W_{xc}\f$). + * A 2-D tensor of shape [num_units, input_size]. + * * 4: The input-to-output weights (\f$W_{xo}\f$). + * A 2-D tensor of shape [num_units, input_size]. + * * 5: The recurrent-to-input weights (\f$W_{hi}\f$). Optional. + * A 2-D tensor of shape [num_units, output_size], where “output_size” + * corresponds to either the number of cell units (i.e., “num_units”), + * or the second dimension of the “projection_weights”, if defined. + * * 6: The recurrent-to-forget weights (\f$W_{hf}\f$). + * A 2-D tensor of shape [num_units, output_size]. + * * 7: The recurrent-to-cell weights (\f$W_{hc}\f$). + * A 2-D tensor of shape [num_units, output_size]. + * * 8: The recurrent-to-output weights (\f$W_{ho}\f$). + * A 2-D tensor of shape [num_units, output_size]. + * * 9: The cell-to-input weights (\f$W_{ci}\f$). Optional. + * A 1-D tensor of shape [num_units]. + * * 10:The cell-to-forget weights (\f$W_{cf}\f$). Optional. + * A 1-D tensor of shape [num_units]. + * * 11:The cell-to-output weights (\f$W_{co}\f$). Optional. + * A 1-D tensor of shape [num_units]. + * * 12:The input gate bias (\f$b_i\f$). Optional. + * A 1-D tensor of shape [num_units]. + * * 13:The forget gate bias (\f$b_f\f$). + * A 1-D tensor of shape [num_units]. + * * 14:The cell bias (\f$b_c\f$). + * A 1-D tensor of shape [num_units]. + * * 15:The output gate bias (\f$b_o\f$). + * A 1-D tensor of shape [num_units]. + * * 16:The projection weights (\f$W_{proj}\f$). Optional. + * A 2-D tensor of shape [output_size, num_units]. + * * 17:The projection bias (\f$b_{proj}\f$). Optional. + * A 1-D tensor of shape [output_size]. + * * 18:The output state (in) (\f$h_{t-1}\f$). + * A 2-D tensor of shape [batch_size, output_size]. + * * 19:The cell state (in) (\f$C_{t-1}\f$). + * A 2-D tensor of shape [batch_size, num_units]. + * * 20:The activation function (\f$g\f$). + * A value indicating the activation function: + *
    + *
  • 0: None; + *
  • 1: Relu; + *
  • 3: Relu6; + *
  • 4: Tanh; + *
  • 6: Sigmoid. + *
+ * * 21:The clipping threshold (\f$t_{cell}\f$) for the cell state, such + * that values are bound within [-cell_clip, cell_clip]. If set to 0.0 + * then clipping is disabled. + * Until API level 29 this scalar must be of type {@link + * FLOAT32}. Since API level 29, if all the input + * tensors have type {@link OperandType::TENSOR_FLOAT32}, this + * scalar must be of the type {@link OperandType::FLOAT32}, + * otherwise if all the input tensors have the type {@link + * TENSOR_FLOAT16}, this scalar must be of type {@link + * FLOAT16}. + * * 22:The clipping threshold (\f$t_{proj}\f$) for the output from the + * projection layer, such that values are bound within + * [-proj_clip, proj_clip]. If set to 0.0 then clipping is disabled. + * Until API level 29 this scalar must be of type {@link + * FLOAT32}. Since API level 29, if all the input + * tensors have type {@link OperandType::TENSOR_FLOAT32}, this + * scalar must be of the type {@link OperandType::FLOAT32}, + * otherwise if all the input tensors have the type {@link + * TENSOR_FLOAT16}, this scalar must be of type {@link + * FLOAT16}. + * Since API level 29 there are additional inputs to this op: + * * 23:The input layer normalization weights. + * A 1-D tensor of shape [num_units]. Used to rescale normalized inputs + * to activation at input gate. + * * 24:The forget layer normalization weights. + * A 1-D tensor of shape [num_units]. Used to rescale normalized inputs + * to activation at forget gate. + * * 25:The cell layer normalization weights. + * A 1-D tensor of shape [num_units]. Used to rescale normalized inputs + * to activation at cell gate. + * * 26:The output layer normalization weights. + * A 1-D tensor of shape [num_units]. Used to rescale normalized inputs + * to activation at output gate. + * + * Outputs: + * * 0: The scratch buffer. + * A 2-D tensor of shape [batch_size, num_units * 3] with CIFG, or + * [batch_size, num_units * 4] without CIFG. + * * 1: The output state (out) (\f$h_t\f$). + * A 2-D tensor of shape [batch_size, output_size]. + * * 2: The cell state (out) (\f$C_t\f$). + * A 2-D tensor of shape [batch_size, num_units]. + * * 3: The output (\f$o_t\f$). + * A 2-D tensor of shape [batch_size, output_size]. This is effectively + * the same as the current “output state (out)” value. + * + * Available since API level 27. + */ + LSTM = @1.1::OperationType:LSTM, + + /** + * Performs an 2-D max pooling operation. + * + * The output dimensions are functions of the filter dimensions, stride, and + * padding. + * + * The values in the output tensor are computed as: + * + * output[b, i, j, channel] = + * max_{di, dj} ( + * input[b, strides[1] * i + di, strides[2] * j + dj, channel] + * ) + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: 4, with "NHWC" or "NCHW" data layout. + * With the default data layout NHWC, the data is stored in the order of: + * [batch, height, width, channels]. Alternatively, the data layout could + * be NCHW, the data storage order of: [batch, channels, height, width]. + * + * Both explicit padding and implicit padding are supported. + * + * Inputs (explicit padding): + * * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying + * the input. + * * 1: An {@link OperandType::INT32} scalar, specifying the padding on + * the left, in the ‘width’ dimension. + * * 2: An {@link OperandType::INT32} scalar, specifying the padding on + * the right, in the ‘width’ dimension. + * * 3: An {@link OperandType::INT32} scalar, specifying the padding on + * the top, in the ‘height’ dimension. + * * 4: An {@link OperandType::INT32} scalar, specifying the padding on + * the bottom, in the ‘height’ dimension. + * * 5: An {@link OperandType::INT32} scalar, specifying the stride when + * walking through input in the ‘width’ dimension. + * * 6: An {@link OperandType::INT32} scalar, specifying the stride when + * walking through input in the ‘height’ dimension. + * * 7: An {@link OperandType::INT32} scalar, specifying the filter + * width. + * * 8: An {@link OperandType::INT32} scalar, specifying the filter + * height. + * * 9: An {@link OperandType::INT32} scalar, and has to be one of the + * {@link FusedActivationFunc} values. Specifies the activation to + * invoke on the result. + * * 10: An optional {@link OperandType::BOOL} scalar, default to false. + * Set to true to specify NCHW data layout for input0 and output0. + * Available since API level 29. + * + * Inputs (implicit padding): + * * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying + * the input. + * * 1: An {@link OperandType::INT32} scalar, specifying the implicit + * padding scheme, has to be one of the + * following values: {0 (NONE), 1 (SAME), 2 (VALID)}. + * * 2: An {@link OperandType::INT32} scalar, specifying the stride when + * walking through input in the ‘width’ dimension. + * * 3: An {@link OperandType::INT32} scalar, specifying the stride when + * walking through input in the ‘height’ dimension. + * * 4: An {@link OperandType::INT32} scalar, specifying the filter + * width. + * * 5: An {@link OperandType::INT32} scalar, specifying the filter + * height. + * * 6: An {@link OperandType::INT32} scalar, and has to be one of the + * {@link FusedActivationFunc} values. Specifies the activation to + * invoke on the result. + * * 7: An optional {@link OperandType::BOOL} scalar, default to false. + * Set to true to specify NCHW data layout for input0 and output0. + * Available since API level 29. + * + * Outputs: + * * 0: The output 4-D tensor, of shape + * [batches, out_height, out_width, depth]. + * + * Available since API level 27. + */ + MAX_POOL_2D = @1.1::OperationType:MAX_POOL_2D, + + /** + * Multiplies two tensors, element-wise. + * + * Takes two input tensors of identical {@link OperandType} and compatible + * dimensions. The output is the product of both input tensors, optionally + * modified by an activation function. + * + * Two dimensions are compatible when: + * 1. they are equal, or + * 2. one of them is 1 + * + * The size of the resulting output is the maximum size along each dimension + * of the input operands. It starts with the trailing dimensions, and works + * its way forward. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: up to 4 + * + * Inputs: + * * 0: A tensor. + * * 1: A tensor of the same {@link OperandType}, and compatible dimensions + * as input0. + * * 2: An {@link OperandType::INT32} scalar, and has to be one of the + * {@link FusedActivationFunc} values. Specifies the activation to + * invoke on the result. + * + * Outputs: + * * 0: The product, a tensor of the same {@link OperandType} as input0. + * For output tensor of {@link OperandType::TENSOR_QUANT8_ASYMM}, + * the following condition must be satisfied: + * output_scale > input1_scale * input2_scale. + * + * Available since API level 27. + */ + MUL = @1.1::OperationType:MUL, + + /** + * Computes rectified linear activation on the input tensor element-wise. + * + * The output is calculated using this formula: + * + * output = max(0, input) + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: up to 4. + * + * Inputs: + * * 0: A tensor, specifying the input. + * + * Outputs: + * * 0: The output tensor of same shape as input0. + * + * Available since API level 27. + */ + RELU = @1.1::OperationType:RELU, + + /** + * Computes rectified linear 1 activation on the input tensor element-wise. + * + * The output is calculated using this formula: + * + * output = min(1.f, max(-1.f, input)) + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: up to 4. + * + * Inputs: + * * 0: A tensor, specifying the input. + * + * Outputs: + * * 0: The output tensor of same shape as input0. + * + * Available since API level 27. + */ + RELU1 = @1.1::OperationType:RELU1, + + /** + * Computes rectified linear 6 activation on the input tensor element-wise. + * + * The output is calculated using this formula: + * + * output = min(6, max(0, input)) + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: up to 4. + * + * Inputs: + * * 0: A tensor, specifying the input. + * + * Outputs: + * * 0: The output tensor of same shape as input0. + * + * Available since API level 27. + */ + RELU6 = @1.1::OperationType:RELU6, + + /** + * Reshapes a tensor. + * + * Given tensor, this operation returns a tensor that has the same values as + * tensor, but with a newly specified shape. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: up to 4. + * + * Inputs: + * * 0: A tensor, specifying the tensor to be reshaped. + * * 1: A 1-D tensor of {@link OperandType::TENSOR_INT32}, defining the + * shape of the output tensor. The number of elements implied by shape + * must be the same as the number of elements in the input tensor. + * + * Outputs: + * * 0: The output tensor, of shape specified by the input shape. + * + * Available since API level 27. + */ + RESHAPE = @1.1::OperationType:RESHAPE, + + /** + * Resizes images to given size using the bilinear interpretation. + * + * Resized images must be distorted if their output aspect ratio is not the + * same as input aspect ratio. The corner pixels of output may not be the + * same as corner pixels of input. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) + * * {@link OperandType::TENSOR_FLOAT32} + * + * Supported tensor rank: 4, with "NHWC" or "NCHW" data layout. + * With the default data layout NHWC, the data is stored in the order of: + * [batch, height, width, channels]. Alternatively, the data layout could + * be NCHW, the data storage order of: [batch, channels, height, width]. + * + * Inputs: + * * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying + * the input. + * * 1: An {@link OperandType::INT32} scalar, specifying the output + * height of the output tensor. + * * 2: An {@link OperandType::INT32} scalar, specifying the output + * width of the output tensor. + * * 3: An optional {@link OperandType::BOOL} scalar, default to false. + * Set to true to specify NCHW data layout for input0 and output0. + * Available since API level 29. + * + * Outputs: + * * 0: The output 4-D tensor, of shape + * [batches, new_height, new_width, depth]. + * + * Available since API level 27. + */ + RESIZE_BILINEAR = @1.1::OperationType:RESIZE_BILINEAR, + + /** + * A basic recurrent neural network layer. + * + * This layer implements the operation: + * outputs = state = activation(inputs * input_weights + + * state * recurrent_weights + bias) + * + * Where: + * * “input_weights” is a weight matrix that multiplies the inputs; + * * “recurrent_weights” is a weight matrix that multiplies the current + * “state” which itself is the output from the previous time step + * computation; + * * “bias” is a bias vector (added to each output vector in the batch); + * * “activation” is the function passed as the “fused_activation_function” + * argument (if not “NONE”). + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) + * * {@link OperandType::TENSOR_FLOAT32} + * + * The input tensors must all be the same type. + * + * Inputs: + * * 0: input. + * A 2-D tensor of shape [batch_size, input_size], where “batch_size” + * corresponds to the batching dimension, and “input_size” is the size + * of the input. + * * 1: weights. + * A 2-D tensor of shape [num_units, input_size], where “num_units” + * corresponds to the number of units. + * * 2: recurrent_weights. + * A 2-D tensor of shape [num_units, num_units], with columns + * corresponding to the weights from each unit. + * * 3: bias. + * A 1-D tensor of shape [num_units]. + * * 4: hidden state (in). + * A 2-D tensor of shape [batch_size, num_units]. + * * 5: fused_activation_function. + * An optional {@link FusedActivationFunc} value indicating the + * activation function. If “NONE” is specified then it results in a + * linear activation. + * + * Outputs: + * * 0: hidden state (out). + * A 2-D tensor of shape [batch_size, num_units]. + * + * * 1: output. + * A 2-D tensor of shape [batch_size, num_units]. This is effectively + * the same as the current state value. + * + * Available since API level 27. + */ + RNN = @1.1::OperationType:RNN, + + /** + * Computes the softmax activation on the input tensor element-wise, per + * batch, by normalizing the input vector so the maximum coefficient is + * zero. + * + * The output is calculated using this formula: + * + * output[batch, i] = + * exp((input[batch, i] - max(input[batch, :])) * beta) / + * sum_{k}{exp((input[batch, k] - max(input[batch, :])) * beta)} + * + * For input tensor with rank other than 2, the activation will be applied + * independently on each 1-D slice along specified dimension. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: up to 4. + * Tensors with rank other than 2 or 4 are only supported since API level 29. + * + * Inputs: + * * 0: A 2-D or 4-D tensor, specifying the tensor to be reshaped. + * * 1: An {@link OperandType::FLOAT32} scalar, specifying the positive + * scaling factor for the exponent, beta. + * * 2: An optional {@link OperandType::INT32} scalar, default to -1, + * specifying the dimension the activation would be performed on. + * Negative index is used to specify axis from the end (e.g. -1 for + * the last axis). Must be in the range [-n, n). + * Available since API level 29. + * + * Outputs: + * * 0: The output tensor of same shape as input0. + * For {@link OperandType::TENSOR_QUANT8_ASYMM}, + * the scale must be 1.f / 256 and the zeroPoint must be 0. + * + * Available since API level 27. + */ + SOFTMAX = @1.1::OperationType:SOFTMAX, + + /** + * Rearranges blocks of spatial data, into depth. + * + * More specifically, this op outputs a copy of the input tensor where + * values from the height and width dimensions are moved to the depth + * dimension. The value block_size indicates the input block size and how + * the data is moved. + * + * Chunks of data of size block_size * block_size from depth are rearranged + * into non-overlapping blocks of size block_size x block_size. + * + * The depth of the output tensor is input_depth * block_size * block_size. + * The input tensor's height and width must be divisible by block_size. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: 4, with "NHWC" or "NCHW" data layout. + * With the default data layout NHWC, the data is stored in the order of: + * [batch, height, width, channels]. Alternatively, the data layout could + * be NCHW, the data storage order of: [batch, channels, height, width]. + * + * Inputs: + * * 0: A 4-D tensor, of shape [batches, height, width, depth_in], + * specifying the input. + * * 1: An {@link OperandType::INT32} scalar, specifying the block_size. + * block_size must be >=1 and block_size must be a divisor of both the + * input height and width. + * * 2: An optional {@link OperandType::BOOL} scalar, default to false. + * Set to true to specify NCHW data layout for input0 and output0. + * Available since API level 29. + * + * Outputs: + * * 0: The output 4-D tensor, of shape [batches, height/block_size, + * width/block_size, depth_in*block_size*block_size]. + * + * Available since API level 27. + */ + SPACE_TO_DEPTH = @1.1::OperationType:SPACE_TO_DEPTH, + + /** + * SVDF op is a kind of stateful layer derived from the notion that a + * densely connected layer that's processing a sequence of input frames can + * be approximated by using a singular value decomposition of each of its + * nodes. The implementation is based on: + * + * https://research.google.com/pubs/archive/43813.pdf + * + * P. Nakkiran, R. Alvarez, R. Prabhavalkar, C. Parada. + * “Compressing Deep Neural Networks using a Rank-Constrained Topology”. + * INTERSPEECH, 2015. + * + * It processes the incoming input using a 2-stage filtering mechanism: + * * stage 1 performs filtering on the "features" dimension, whose outputs + * get pushed into a memory of fixed-size memory_size. + * * stage 2 performs filtering on the "time" dimension of the memory_size + * memoized outputs of stage 1. + * + * Specifically, for rank 1, this layer implements the operation: + * + * memory = push(conv1d(inputs, weights_feature, feature_dim, + * "PADDING_VALID")); + * outputs = activation(memory * weights_time + bias); + * + * Where: + * * “weights_feature” is a weights matrix that processes the inputs (by + * convolving the input with every “feature filter”), and whose outputs + * get pushed, stacked in order, into the fixed-size “memory” (the oldest + * entry gets dropped); + * * “weights_time” is a weights matrix that processes the “memory” (by a + * batched matrix multiplication on the num_units); + * * “bias” is an optional bias vector (added to each output vector in the + * batch); and + * * “activation” is the function passed as the “fused_activation_function” + * argument (if not “NONE”). + * + * Each rank adds a dimension to the weights matrices by means of stacking + * the filters. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) + * * {@link OperandType::TENSOR_FLOAT32} + * + * All input tensors must be the same type. + * + * Inputs: + * * 0: input. + * A 2-D tensor of shape [batch_size, input_size], where “batch_size” + * corresponds to the batching dimension, and “input_size” is the size + * of the input. + * * 1: weights_feature. + * A 2-D tensor of shape [num_units, input_size], where “num_units” + * corresponds to the number of units. + * * 2: weights_time. + * A 2-D tensor of shape [num_units, memory_size], where “memory_size” + * corresponds to the fixed-size of the memory. + * * 3: bias. + * An optional 1-D tensor of shape [num_units]. + * * 4: state (in). + * A 2-D tensor of shape [batch_size, (memory_size - 1) * num_units * rank]. + * * 5: rank. + * The rank of the SVD approximation. + * * 6: fused_activation_function. + * An optional {@link FusedActivationFunc} value indicating the + * activation function. If “NONE” is specified then it results in a + * linear activation. + * + * Outputs: + * * 0: state (out). + * A 2-D tensor of the same {@link OperandType} as the inputs, with shape + * [batch_size, (memory_size - 1) * num_units * rank]. + * * 1: output. + * A 2-D tensor of the same {@link OperandType} as the inputs, with shape + * [batch_size, num_units]. + * + * Available since API level 27. + */ + SVDF = @1.1::OperationType:SVDF, + + /** + * Computes hyperbolic tangent of input tensor element-wise. + * + * The output is calculated using this formula: + * + * output = tanh(input) + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} (since API level 29) + * + * Supported tensor rank: up to 4. + * + * Inputs: + * * 0: A tensor, specifying the input. + * + * Outputs: + * * 0: The output tensor of same shape as input0. + * For {@link OperandType::TENSOR_QUANT8_ASYMM}, + * the scale must be 1.f / 128 and the zeroPoint must be 128. + * + * Available since API level 27. + */ + TANH = @1.1::OperationType:TANH, + + /** + * BatchToSpace for N-dimensional tensors. + * + * This operation reshapes the batch dimension (dimension 0) into M + 1 + * dimensions of shape block_shape + [batch], interleaves these blocks back + * into the grid defined by the spatial dimensions [1, ..., M], to obtain a + * result with the same rank as the input. + * + * This is the reverse of SpaceToBatch. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: 4, with "NHWC" or "NCHW" data layout. + * With the default data layout NHWC, the data is stored in the order of: + * [batch, height, width, channels]. Alternatively, the data layout could + * be NCHW, the data storage order of: [batch, channels, height, width]. + * + * Inputs: + * * 0: An n-D tensor, specifying the tensor to be reshaped + * * 1: A 1-D Tensor of {@link OperandType::TENSOR_INT32}, the block + * sizes for each spatial dimension of the input tensor. All values + * must be >= 1. + * * 2: An optional {@link OperandType::BOOL} scalar, default to false. + * Set to true to specify NCHW data layout for input0 and output0. + * Available since API level 29. + * + * Outputs: + * * 0: A tensor of the same {@link OperandType} as input0. + * + * Available since API level 28. + */ + BATCH_TO_SPACE_ND = @1.1::OperationType:BATCH_TO_SPACE_ND, + + /** + * Element-wise division of two tensors. + * + * Takes two input tensors of identical {@link OperandType} and compatible + * dimensions. The output is the result of dividing the first input tensor + * by the second, optionally modified by an activation function. + * + * Two dimensions are compatible when: + * 1. they are equal, or + * 2. one of them is 1 + * + * The size of the output is the maximum size along each dimension of the + * input operands. It starts with the trailing dimensions, and works its way + * forward. + * + * Example: + * input1.dimension = {4, 1, 2} + * input2.dimension = {5, 4, 3, 1} + * output.dimension = {5, 4, 3, 2} + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) + * * {@link OperandType::TENSOR_FLOAT32} + * + * Supported tensor rank: up to 4 + * + * Inputs: + * * 0: An n-D tensor, specifying the first input. + * * 1: A tensor of the same {@link OperandType}, and compatible dimensions + * as input0. + * * 2: An {@link OperandType::INT32} scalar, and has to be one of the + * {@link FusedActivationFunc} values. Specifies the activation to + * invoke on the result. + * + * Outputs: + * * 0: A tensor of the same {@link OperandType} as input0. + * + * Available since API level 28. + */ + DIV = @1.1::OperationType:DIV, + + /** + * Computes the mean of elements across dimensions of a tensor. + * + * Reduces the input tensor along the given dimensions to reduce. Unless + * keep_dims is true, the rank of the tensor is reduced by 1 for each entry + * in axis. If keep_dims is true, the reduced dimensions are retained with + * length 1. + * + * If dimensions to reduce have no entries, all dimensions are reduced, and + * a tensor with a single element is returned. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: up to 4 + * + * Inputs: + * * 0: A tensor, specifying the input. + * * 1: A 1-D Tensor of {@link OperandType::TENSOR_INT32}. The dimensions + * to reduce. If None (the default), reduces all dimensions. Must be in + * the range [-rank(input_tensor), rank(input_tensor)). + * * 2: An {@link OperandType::INT32} scalar, keep_dims. If positive, + * retains reduced dimensions with length 1. + * + * Outputs: + * * 0: A tensor of the same {@link OperandType} as input0. + * + * Available since API level 28. + */ + MEAN = @1.1::OperationType:MEAN, + + /** + * Pads a tensor with zeros. + * + * This operation pads a tensor according to the specified paddings. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: up to 4 + * + * Inputs: + * * 0: An n-D tensor, specifying the tensor to be padded. + * * 1: A 2-D Tensor of {@link OperandType::TENSOR_INT32}, the paddings + * for each spatial dimension of the input tensor. The shape of the + * tensor must be {rank(input0), 2}. + * padding[i, 0] specifies the number of elements to be padded in the + * front of dimension i. + * padding[i, 1] specifies the number of elements to be padded after the + * end of dimension i. + * + * Outputs: + * * 0: A tensor of the same {@link OperandType} as input0. The + * output tensor has the same rank as input0, and each + * dimension of the output tensor has the same size as the + * corresponding dimension of the input tensor plus the size + * of the padding: + * output0.dimension[i] = + * padding[i, 0] + input0.dimension[i] + padding[i, 1] + * + * Available since API level 28. + */ + PAD = @1.1::OperationType:PAD, + + /** + * SpaceToBatch for N-Dimensional tensors. + * + * This operation divides "spatial" dimensions [1, ..., M] of the input into + * a grid of blocks of shape block_shape, and interleaves these blocks with + * the "batch" dimension (0) such that in the output, the spatial dimensions + * [1, ..., M] correspond to the position within the grid, and the batch + * dimension combines both the position within a spatial block and the + * original batch position. Prior to division into blocks, the spatial + * dimensions of the input are optionally zero padded according to paddings. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: 4, with "NHWC" or "NCHW" data layout. + * With the default data layout NHWC, the data is stored in the order of: + * [batch, height, width, channels]. Alternatively, the data layout could + * be NCHW, the data storage order of: [batch, channels, height, width]. + * + * Inputs: + * * 0: An n-D tensor, specifying the input. + * * 1: A 1-D Tensor of {@link OperandType::TENSOR_INT32}, the block + * sizes for each spatial dimension of the input tensor. All values + * must be >= 1. + * * 2: A 2-D Tensor of {@link OperandType::TENSOR_INT32}, the paddings + * for each spatial dimension of the input tensor. All values must be + * >= 0. The shape of the tensor must be {rank(input0), 2}. + * padding[i, 0] specifies the number of element to be padded in the + * front of dimension i. + * padding[i, 1] specifies the number of element to be padded after the + * end of dimension i. + * * 3: An optional {@link OperandType::BOOL} scalar, default to false. + * Set to true to specify NCHW data layout for input0 and output0. + * Available since API level 29. + * + * Outputs: + * * 0: A tensor of the same {@link OperandType} as input0. + * + * Available since API level 28. + */ + SPACE_TO_BATCH_ND = @1.1::OperationType:SPACE_TO_BATCH_ND, + + /** + * Removes dimensions of size 1 from the shape of a tensor. + * + * Given a tensor input, this operation returns a tensor of the same + * {@link OperandType} with all dimensions of size 1 removed. If you don't + * want to remove all size 1 dimensions, you can remove specific size 1 + * dimensions by specifying the axes (input1). + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: up to 4 + * + * Inputs: + * * 0: An n-D tensor, the tensor to be squeezed. + * * 1: An optional 1-D tensor of {@link OperandType::TENSOR_INT32}. The + * dimensions to squeeze. If specified only squeezes the dimensions + * listed. Otherwise, squeezes all dimensions. The dimension index + * starts at 0. An error must be reported if squeezing a dimension that + * is not 1. + * + * Outputs: + * * 0: A tensor of the same {@link OperandType} as input0. Contains the + * same data as input, but has one or more dimensions of size 1 + * removed. + * + * Available since API level 28. + */ + SQUEEZE = @1.1::OperationType:SQUEEZE, + + /** + * Extracts a strided slice of a tensor. + * + * Roughly speaking, this op extracts a slice of size (end - begin) / stride + * from the given input tensor. Starting at the location specified by begin + * the slice continues by adding stride to the index until all dimensions + * are not less than end. Note that a stride can be negative, which causes a + * reverse slice. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: up to 4 + * + * Inputs: + * * 0: An n-D tensor, specifying the tensor to be sliced. + * * 1: begin, a 1-D tensor of {@link OperandType::TENSOR_INT32}. The + * starts of the dimensions of the input tensor to be sliced. The + * length must be of rank(input0). + * * 2: end, a 1-D tensor of {@link OperandType::TENSOR_INT32}. The + * ends of the dimensions of the input tensor to be sliced. The length + * must be of rank(input0). + * * 3: strides, a 1-D tensor of {@link OperandType::TENSOR_INT32}. The + * strides of the dimensions of the input tensor to be sliced. The + * length must be of rank(input0). The entries must be non-zero. + * * 4: begin_mask, an {@link OperandType::INT32} scalar. If the ith bit + * of begin_mask is set, begin[i] is ignored and the fullest possible + * range in that dimension is used instead. + * * 5: end_mask, an {@link OperandType::INT32} scalar. If the ith bit of + * end_mask is set, end[i] is ignored and the fullest possible range in + * that dimension is used instead. + * * 6: shrink_axis_mask, an {@link OperandType::INT32} scalar. If the + * ith bit of shrink_axis_mask is set, the ith dimension specification + * shrinks the dimensionality by 1, taking on the value at index + * begin[i]. In this case, the ith specification must define a + * slice of size 1, e.g. begin[i] = x, end[i] = x + 1. + * + * Outputs: + * * 0: A tensor of the same {@link OperandType} as input0 and rank (n - k), + * where k is the number of bits set in shrink_axis_mask. + * + * Available since API level 28. + */ + STRIDED_SLICE = @1.1::OperationType:STRIDED_SLICE, + + /** + * Element-wise subtraction of two tensors. + * + * Takes two input tensors of identical {@link OperandType} and compatible + * dimensions. The output is the result of subtracting the second input + * tensor from the first one, optionally modified by an activation function. + * + * Two dimensions are compatible when: + * 1. they are equal, or + * 2. one of them is 1 + * + * The size of the output is the maximum size along each dimension of the + * input operands. It starts with the trailing dimensions, and works its way + * forward. + * + * Example: + * input1.dimension = {4, 1, 2} + * input2.dimension = {5, 4, 3, 1} + * output.dimension = {5, 4, 3, 2} + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} (since API level 29) + * + * Supported tensor rank: up to 4 + * + * Inputs: + * * 0: An n-D tensor, specifying the first input. + * * 1: A tensor of the same {@link OperandType}, and compatible dimensions + * as input0. + * * 2: An {@link OperandType::INT32} scalar, and has to be one of the + * {@link FusedActivationFunc} values. Specifies the activation to + * invoke on the result. + * + * Outputs: + * * 0: A tensor of the same {@link OperandType} as input0. + * + * Available since API level 28. + */ + SUB = @1.1::OperationType:SUB, + + /** + * Transposes the input tensor, permuting the dimensions according to the + * perm tensor. + * + * The returned tensor's dimension i corresponds to the input dimension + * perm[i]. If perm is not given, it is set to (n-1...0), where n is the + * rank of the input tensor. Hence by default, this operation performs a + * regular matrix transpose on 2-D input Tensors. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: up to 4 + * + * Inputs: + * * 0: An n-D tensor, specifying the tensor to be transposed. + * * 1: An optional 1-D Tensor of {@link OperandType::TENSOR_INT32}, + * the permutation of the dimensions of the input tensor. + * + * Outputs: + * * 0: A tensor of the same {@link OperandType} as input0. + * + * Available since API level 28. + */ + TRANSPOSE = @1.1::OperationType:TRANSPOSE, + + /** + * Computes the absolute value of a tensor, element-wise. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * + * Supported tensor rank: from 1. + * + * Inputs: + * * 0: A tensor. + * + * Outputs: + * * 0: The output tensor of same shape as input0. + * + * Available since API level 29. + */ ABS = 38, + + /** + * Returns the index of the largest element along an axis. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_INT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: from 1 + * + * Inputs: + * * 0: An n-D tensor specifying the input. Must be non-empty. + * * 1: An {@link OperandType::INT32} scalar specifying the axis to + * reduce across. Negative index is used to specify axis from the + * end (e.g. -1 for the last axis). Must be in the range [-n, n). + * + * Outputs: + * * 0: An (n - 1)-D {@link OperandType::TENSOR_INT32} tensor. + * + * Available since API level 29. + */ + // There is no underscore in ARG_MAX to avoid name conflict with + // the macro defined in libc/kernel/uapi/linux/limits.h. ARGMAX = 39, - ARGMIN = 40, + + /** + * Returns the index of the smallest element along an axis. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_INT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: from 1 + * + * Inputs: + * * 0: An n-D tensor specifying the input. Must be non-empty. + * * 1: An {@link OperandType::INT32} scalar specifying the axis to + * reduce across. Negative index is used to specify axis from the + * end (e.g. -1 for the last axis). Must be in the range [-n, n). + * + * Outputs: + * * 0: An (n - 1)-D {@link OperandType::TENSOR_INT32} tensor. + * + * Available since API level 29. + */ + ARGMIN = 40, // See ARGMAX for naming discussion. + + /** + * Transform axis-aligned bounding box proposals using bounding box deltas. + * + * Given the positions of bounding box proposals and the corresponding + * bounding box deltas for each class, return the refined bounding box + * regions. The resulting bounding boxes are cliped against the edges of + * the image. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * + * Inputs: + * * 0: A 2-D Tensor of shape [num_rois, 4], specifying the locations of the + * bounding box proposals, each line with format [x1, y1, x2, y2]. + * For tensor of type {@link OperandType::TENSOR_QUANT16_ASYMM}, + * the zeroPoint must be 0 and the scale must be 0.125. + * * 1: A 2-D Tensor of shape [num_rois, num_classes * 4], specifying the + * bounding box delta for each region of interest and each class. The + * bounding box deltas are organized in the following order + * [dx, dy, dw, dh], where dx and dy is the relative correction factor + * for the center position of the bounding box with respect to the width + * and height, dw and dh is the log-scale relative correction factor + * for the width and height. For input0 of type + * {@link OperandType::TENSOR_QUANT16_ASYMM}, this tensor should be + * of {@link OperandType::TENSOR_QUANT8_ASYMM}. + * * 2: An 1-D {@link OperandType::TENSOR_INT32} tensor, of shape + * [batches], specifying the number of output boxes for each batch. + * * 3: A 2-D Tensor of shape [batches, 2], specifying the information of + * each image in the batch, each line with format + * [image_height, image_width]. + * + * Outputs: + * * 0: A tensor of the same {@link OperandType} as input0, with shape + * [num_rois, num_classes * 4], specifying the coordinates of each + * output bounding box for each class, with format [x1, y1, x2, y2]. + * + * Available since API level 29. + */ AXIS_ALIGNED_BBOX_TRANSFORM = 41, + + /** + * Performs a forward LSTM on the input followed by a backward LSTM. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * + * Supported tensor rank: 3, either time-major or batch-major. + * + * All input and output tensors must be of the same type. + * + * + * Inputs: + * * 0: The input. + * A 3-D tensor of shape: + * If time-major: [max_time, batch_size, output_size] + * If batch-major: [batch_size, max_time, output_size] + * where "max_time" is the number of timesteps (sequence length), + * "batch_size" corresponds to the batching dimension, and + * "input_size" is the size of the input. + * * 1: The forward input-to-input weights. Optional. + * A 2-D tensor of shape [num_units, input_size], where “num_units” + * corresponds to the number of cell units. + * * 2: The forward input-to-forget weights. + * A 2-D tensor of shape [num_units, input_size]. + * * 3: The forward input-to-cell weights. + * A 2-D tensor of shape [num_units, input_size]. + * * 4: The forward input-to-output weights. + * A 2-D tensor of shape [num_units, input_size]. + * * 5: The forward recurrent-to-input weights. Optional. + * A 2-D tensor of shape [num_units, output_size], where “output_size” + * corresponds to either the number of cell units (i.e., “num_units”), + * or the second dimension of the “projection_weights”, if defined. + * * 6: The forward recurrent-to-forget weights. + * A 2-D tensor of shape [num_units, output_size]. + * * 7: The forward recurrent-to-cell weights. + * A 2-D tensor of shape [num_units, output_size]. + * * 8: The forward recurrent-to-output weights. + * A 2-D tensor of shape [num_units, output_size]. + * * 9: The forward cell-to-input weights. Optional. + * A 1-D tensor of shape [num_units]. + * * 10: The forward cell-to-forget weights. Optional. + * A 1-D tensor of shape [num_units]. + * * 11: The forward cell-to-output weights. Optional. + * A 1-D tensor of shape [num_units]. + * * 12: The forward input gate bias. Optional. + * A 1-D tensor of shape [num_units]. + * * 13: The forward forget gate bias. + * A 1-D tensor of shape [num_units]. + * * 14: The forward cell gate bias. + * A 1-D tensor of shape [num_units]. + * * 15: The forward output gate bias. + * A 1-D tensor of shape [num_units]. + * * 16: The forward projection weights. Optional. + * A 2-D tensor of shape [output_size, num_units]. + * * 17: The forward projection bias. Optional. + * A 1-D tensor of shape [output_size]. + * * 18: The backward input-to-input weights. Optional. + * A 2-D tensor of shape [num_units, input_size], where “num_units” + * corresponds to the number of cell units. + * * 19: The backward input-to-forget weights. + * A 2-D tensor of shape [num_units, input_size]. + * * 20: The backward input-to-cell weights. + * A 2-D tensor of shape [num_units, input_size]. + * * 21: The backward input-to-output weights. + * A 2-D tensor of shape [num_units, input_size]. + * * 22: The backward recurrent-to-input weights. Optional. + * A 2-D tensor of shape [num_units, output_size], where “output_size” + * corresponds to either the number of cell units (i.e., “num_units”), + * or the second dimension of the “projection_weights”, if defined. + * * 23: The backward recurrent-to-forget weights. + * A 2-D tensor of shape [num_units, output_size]. + * * 24: The backward recurrent-to-cell weights. + * A 2-D tensor of shape [num_units, output_size]. + * * 25: The backward recurrent-to-output weights. + * A 2-D tensor of shape [num_units, output_size]. + * * 26: The backward cell-to-input weights. Optional. + * A 1-D tensor of shape [num_units]. + * * 27: The backward cell-to-forget weights. Optional. + * A 1-D tensor of shape [num_units]. + * * 28: The backward cell-to-output weights. Optional. + * A 1-D tensor of shape [num_units]. + * * 29: The backward input gate bias. Optional. + * A 1-D tensor of shape [num_units]. + * * 30: The backward forget gate bias. + * A 1-D tensor of shape [num_units]. + * * 31: The backward cell gate bias. + * A 1-D tensor of shape [num_units]. + * * 32: The backward output gate bias. + * A 1-D tensor of shape [num_units]. + * * 33: The backward projection weights. Optional. + * A 2-D tensor of shape [output_size, num_units]. + * * 34: The backward projection bias. Optional. + * A 1-D tensor of shape [output_size]. + * * 35: The forward input activation state. + * A 2-D tensor of shape [batch_size, output_size]. + * * 36: The forward input cell state. + * A 2-D tensor of shape [batch_size, num_units]. + * * 37: The backward input activation state. + * A 2-D tensor of shape [batch_size, output_size]. + * * 38: The backward input cell state. + * A 2-D tensor of shape [batch_size, num_units]. + * * 39: The auxiliary input. Optional. + * A 3-D tensor of shape [max_time, batch_size, input_size], where “batch_size” + * corresponds to the batching dimension, and “input_size” is the size + * of the input. + * * 40: The forward auxiliary input-to-input weights. Optional. + * A 2-D tensor of shape [num_units, input_size]. + * * 41: The forward auxiliary input-to-forget weights. Optional. + * A 2-D tensor of shape [num_units, input_size]. + * * 42: The forward auxiliary input-to-cell weights. Optional. + * A 2-D tensor of shape [num_units, input_size]. + * * 43: The forward auxiliary input-to-output weights. Optional. + * A 2-D tensor of shape [num_units, input_size]. + * * 44: The backward auxiliary input-to-input weights. Optional. + * A 2-D tensor of shape [num_units, input_size]. + * * 45: The backward auxiliary input-to-forget weights. Optional. + * A 2-D tensor of shape [num_units, input_size]. + * * 46: The backward auxiliary input-to-cell weights. Optional. + * A 2-D tensor of shape [num_units, input_size]. + * * 47: The backward auxiliary input-to-output weights. Optional. + * A 2-D tensor of shape [num_units, input_size]. + * * 48: The activation function. + * A value indicating the activation function: + *
    + *
  • 0: None; + *
  • 1: Relu; + *
  • 3: Relu6; + *
  • 4: Tanh; + *
  • 6: Sigmoid. + *
+ * * 49: The clipping threshold for the cell state, such + * that values are bound within [-cell_clip, cell_clip]. If set to 0.0 + * then clipping is disabled. + * If all the input tensors have type {@link OperandType::TENSOR_FLOAT32}, + * this scalar must be of the type {@link OperandType::FLOAT32}, + * otherwise if all the input tensors have the type {@link + * TENSOR_FLOAT16}, this scalar must be of type {@link + * FLOAT16}. + * * 50: The clipping threshold for the output from the + * projection layer, such that values are bound within + * [-proj_clip, proj_clip]. If set to 0.0 then clipping is disabled. + * If all the input tensors have type {@link OperandType::TENSOR_FLOAT32}, + * this scalar must be of the type {@link OperandType::FLOAT32}, + * otherwise if all the input tensors have the type {@link + * TENSOR_FLOAT16}, this scalar must be of type {@link + * FLOAT16}. + * * 51: merge_outputs + * An {@link OperandType::BOOL} scalar specifying if the outputs + * from forward and backward cells should be merged. + * * 52: time_major + * An {@link OperandType::BOOL} scalar specifying the shape format + * of input and output tensors. + * + * Outputs: + * * 0: The forward output. + * A 3-D tensor of shape: + * If time-major: [max_time, batch_size, output_size] + * If batch-major: [batch_size, max_time, output_size] + * * 1: The backward output. Unused if merge_outputs is true. + * A 3-D tensor of shape: + * If time-major: [max_time, batch_size, output_size] + * If batch-major: [batch_size, max_time, output_size] + * + * Available since API level 29. + */ BIDIRECTIONAL_SEQUENCE_LSTM = 42, + + /** + * A recurrent neural network layer that applies a basic RNN cell to a + * sequence of inputs in forward and backward directions. + * + * This Op unrolls the input along the sequence dimension, and implements + * the following operation for each element in the sequence s = + * 1...sequence_length: + * fw_outputs[s] = fw_state = activation(inputs[s] * fw_input_weights’ + + * fw_state * fw_recurrent_weights’ + fw_bias) + * + * And for each element in sequence t = sequence_length : 1 + * bw_outputs[t] = bw_state = activation(inputs[t] * bw_input_weights’ + + * bw_state * bw_recurrent_weights’ + bw_bias) + * + * Where: + * * “{fw,bw}_input_weights” is a weight matrix that multiplies the inputs; + * * “{fw,bw}_recurrent_weights” is a weight matrix that multiplies the + * current “state” which itself is the output from the previous time step + * computation; + * * “{fw,bw}_bias” is a bias vector (added to each output vector in the + * batch); + * * “activation” is the function passed as the “fused_activation_function” + * argument (if not “NONE”). + * + * The op also supports an auxiliary input. Regular cell feeds one input + * into the two RNN cells in the following way: + * + * INPUT (INPUT_REVERSED) + * | | + * --------------------- + * | FW_RNN BW_RNN | + * --------------------- + * | | + * FW_OUT BW_OUT + * + * An op with an auxiliary input takes two inputs and feeds them into the + * RNN cells in the following way: + * + * AUX_INPUT (AUX_INPUT_REVERSED) + * | | + * INPUT | (INPUT_R'D.)| + * | | | | + * ----------------------- + * | \ / \ / | + * | FW_RNN BW_RNN | + * ----------------------- + * | | + * FW_OUT BW_OUT + * + * While stacking this op on top of itself, this allows to connect both + * forward and backward outputs from previous cell to the next cell's + * inputs. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * + * The input tensors must all be the same type. + * + * Inputs: + * * 0: input. + * A 3-D tensor. The shape is defined by the input 6 (timeMajor). If + * it is set to true, then the input has a shape [maxTime, batchSize, + * inputSize], otherwise the input has a shape [batchSize, maxTime, + * inputSize]. + * * 1: fwWeights. + * A 2-D tensor of shape [fwNumUnits, inputSize]. + * * 2: fwRecurrentWeights. + * A 2-D tensor of shape [fwNumUnits, fwNumUnits]. + * * 3: fwBias. + * A 1-D tensor of shape [fwNumUnits]. + * * 4: fwHiddenState. + * A 2-D tensor of shape [batchSize, fwNumUnits]. Specifies a hidden + * state input for the first time step of the computation. + * * 5: bwWeights. + * A 2-D tensor of shape [bwNumUnits, inputSize]. + * * 6: bwRecurrentWeights. + * A 2-D tensor of shape [bwNumUnits, bwNumUnits]. + * * 7: bwBias. + * A 1-D tensor of shape [bwNumUnits]. + * * 8: bwHiddenState + * A 2-D tensor of shape [batchSize, bwNumUnits]. Specifies a hidden + * state input for the first time step of the computation. + * * 9: auxInput. + * A 3-D tensor. The shape is the same as of the input 0. + * * 10:fwAuxWeights. + * A 2-D tensor of shape [fwNumUnits, inputSize]. + * * 11:bwAuxWeights. + * A 2-D tensor of shape [bwNumUnits, inputSize]. + * * 12:fusedActivationFunction. + * A {@link FusedActivationFunc} value indicating the activation function. If + * “NONE” is specified then it results in a linear activation. + * * 13:timeMajor + * An {@link OperandType::BOOL} scalar specifying the shape format + * of input and output tensors. + * * 14:mergeOutputs + * An {@link OperandType::BOOL} scalar specifying if the outputs + * from forward and backward cells are separate (if set to false) or + * concatenated (if set to true). + * Outputs: + * * 0: fwOutput. + * A 3-D tensor. The first two dimensions of the shape are defined by + * the input 6 (timeMajor) and the third dimension is defined by the + * input 14 (mergeOutputs). If timeMajor is set to true, then the first + * two dimensions are [maxTime, batchSize], otherwise they are set to + * [batchSize, maxTime]. If mergeOutputs is set to true, then the third + * dimension is equal to (fwNumUnits + bwNumUnits), otherwise it is set + * to fwNumUnits. + * * 1: bwOutput. + * A 3-D tensor. If the input 14 (mergeOutputs) is set to true, then + * this tensor is not produced. The shape is defined by the input 6 + * (timeMajor). If it is set to true, then the shape is set to + * [maxTime, batchSize, bwNumUnits], otherwise the shape is set to + * [batchSize, maxTime, bwNumUnits]. + * + * Available since API level 29. + */ BIDIRECTIONAL_SEQUENCE_RNN = 43, + + /** + * Greedily selects a subset of bounding boxes in descending order of score. + * + * This op applies hard NMS algorithm to each class. In each loop of + * execution, the box with maximum score gets selected, and any boxes with + * the intersection-over-union (IOU) greater than a threshold are removed + * from the pending set. + * + * Axis-aligned bounding boxes are represented by its upper-left corner + * coordinate (x1,y1) and lower-right corner coordinate (x2,y2). A valid + * bounding box should satisfy x1 <= x2 and y1 <= y2. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Inputs: + * * 0: A 2-D Tensor of shape [num_rois, num_classes], specifying the score + * of each bounding box proposal. The boxes are grouped by batches in the + * first dimension. + * * 1: A 2-D Tensor specifying the bounding boxes of shape + * [num_rois, num_classes * 4], organized in the order [x1, y1, x2, y2]. + * The boxes are grouped by batches in the first dimension. The sequential + * order of the boxes corresponds with input0. For input0 of type + * {@link OperandType::TENSOR_QUANT8_ASYMM}, this tensor should be of + * {@link OperandType::TENSOR_QUANT16_ASYMM}, with zeroPoint of 0 and + * scale of 0.125. + * * 2: A 1-D Tensor of shape [batches], specifying the number of boxes + * for each image in the batch. + * * 3: An {@link OperandType::FLOAT32} scalar, score_threshold. Boxes + * with scores lower than the threshold are filtered before sending + * to the NMS algorithm. + * * 4: An {@link OperandType::FLOAT32} scalar, specifying the IoU + * threshold. + * * 5: An {@link OperandType::INT32} scalar, specifying the maximum + * number of selected bounding boxes for each image. Set to a negative + * value for unlimited number of output bounding boxes. + * + * Outputs: + * * 0: A 1-D Tensor of the same {@link OperandType} as input0, with shape + * [num_output_rois], specifying the score of each output box. The boxes + * are grouped by batches, but the sequential order in each batch is not + * guaranteed. For type of {@link OperandType::TENSOR_QUANT8_ASYMM}, + * the scale and zero point must be the same as input0. + * * 1: A 2-D Tensor of the same {@link OperandType} as input1, with shape + * [num_output_rois, 4], specifying the coordinates of each + * output bounding box with the same format as input1. The sequential + * order of the boxes corresponds with output0. For type of + * {@link OperandType::TENSOR_QUANT16_ASYMM}, the scale must be + * 0.125 and the zero point must be 0. + * * 2: A 1-D {@link OperandType::TENSOR_INT32} tensor, of shape + * [num_output_rois], specifying the class of each output box. The + * sequential order of the boxes corresponds with output0. + * * 3: A 1-D {@link OperandType::TENSOR_INT32} tensor, of shape + * [batches], specifying the number of output boxes for each image. + * + * Available since API level 29. + */ BOX_WITH_NMS_LIMIT = 44, + + /** + * Casts a tensor to a new type. + * + * This operation ignores the scale and zeroPoint of quanized tensors, + * e.g. it treats a {@link OperandType::TENSOR_QUANT8_ASYMM} input + * as a tensor of uint8 values. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_INT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: from 1 + * + * Inputs: + * * 0: A tensor. + * + * Outputs: + * * 0: A tensor with the same shape as input0. + * + * Available since API level 29. + */ CAST = 45, + + /** + * Shuffle the channels of the input tensor. + * + * Given an input tensor and a integer value of num_groups, CHANNEL_SHUFFLE + * divide the channel dimension into num_groups groups, and reorganize the + * channels by grouping channels with the same index in each group. + * + * Along the channel dimension, the output is calculated using this formula: + * + * output_channel[k * num_groups + g] = input_channel[g * group_size + k] + * + * where group_size = num_channels / num_groups + * + * The number of channels must be divisible by num_groups. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: up to 4 + * + * Inputs: + * * 0: An n-D tensor, specifying the tensor to be shuffled. + * * 1: An {@link OperandType::INT32} scalar, specifying the number of + * groups. + * * 2: An {@link OperandType::INT32} scalar, specifying the dimension + * channel shuffle would be performed on. Negative index is used to + * specify axis from the end (e.g. -1 for the last axis). Must be in + * the range [-n, n). + * + * Outputs: + * * 0: A tensor of the same {@link OperandType} and same shape as input0. + * + * Available since API level 29. + */ CHANNEL_SHUFFLE = 46, + + /** + * Apply postprocessing steps to bounding box detections. + * + * Bounding box detections are generated by applying transformation on a set + * of predefined anchors with the bounding box deltas from bounding box + * regression. A final step of hard NMS is applied to limit the number of + * returned boxes. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * + * Inputs: + * * 0: A 3-D Tensor of shape [batches, num_anchors, num_classes], specifying + * the score of each anchor with each class. Class 0 for each + * [batches, num_anchors, 0] is background and will be ignored. + * * 1: A 3-D Tensor of shape [batches, num_anchors, length_box_encoding], with + * the first four values in length_box_encoding specifying the bounding + * box deltas. The box deltas are encoded in the order of [dy, dx, dh, dw], + * where dy and dx is the linear-scale relative correction factor for the + * center position of the bounding box with respect to the width and height, + * dh and dw is the log-scale relative correction factor for the width and + * height. All the entries in length_box_encoding beyond the first four + * values are ignored in this operation. + * * 2: A 2-D Tensor of shape [num_anchors, 4], specifying the shape of each + * predefined anchor, with format [ctr_y, ctr_x, h, w], where ctr_y and + * ctr_x are the center position of the box, and h and w are the height + * and the width. + * * 3: An {@link OperandType::FLOAT32} scalar, specifying the scaling + * factor for dy in bounding box deltas. + * * 4: An {@link OperandType::FLOAT32} scalar, specifying the scaling + * factor for dx in bounding box deltas. + * * 5: An {@link OperandType::FLOAT32} scalar, specifying the scaling + * factor for dh in bounding box deltas. + * * 6: An {@link OperandType::FLOAT32} scalar, specifying the scaling + * factor for dw in bounding box deltas. + * * 7: An {@link OperandType::BOOL} scalar, set to true to use regular + * multi-class NMS algorithm that do NMS separately for each class, + * set to false for a faster algorithm that only do one single NMS + * using the highest class score.. + * * 8: An {@link OperandType::INT32} scalar, max_num_detections, specifying + * the maximum number of boxes for the output. Boxes with the lowest + * scores are discarded to meet the limit. + * * 9: An {@link OperandType::INT32} scalar, only used when input7 is + * set to false, specifying the maximum number of classes per detection. + * * 10: An {@link OperandType::INT32} scalar, only used when input7 is + * set to true, specifying the maximum number of detections when + * applying NMS algorithm for each single class. + * * 11: An {@link OperandType::FLOAT32} scalar, score_threshold. Boxes + * with scores lower than the threshold are filtered before sending + * to the NMS algorithm. + * * 12: An {@link OperandType::FLOAT32} scalar, specifying the IoU + * threshold for hard NMS. + * * 13: An {@link OperandType::BOOL} scalar, set to true to include + * background class in the list of label map for the output, set + * to false to not include the background. When the background + * class is included, it has label 0 and the output classes start + * at 1 in the label map, otherwise, the output classes start at 0. + * + * Outputs: + * * 0: A 2-D tensor of the same {@link OperandType} as input0, with shape + * [batches, max_num_detections], specifying the score of each output + * detections. + * * 1: A 3-D tensor of shape [batches, max_num_detections, 4], specifying the + * coordinates of each output bounding box, with format + * [y1, x1, y2, x2]. + * * 2: A 2-D {@link OperandType::TENSOR_INT32} tensor, of shape + * [batches, max_num_detections], specifying the class label for each + * output detection. + * * 3: An 1-D {@link OperandType::TENSOR_INT32} tensor, of shape [batches], + * specifying the number of valid output detections for each batch. + * + * Available since API level 29. + */ DETECTION_POSTPROCESSING = 47, + + /** + * For input tensors x and y, computes x == y elementwise. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_BOOL8} + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_INT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: from 1 + * + * This operation supports broadcasting. + * + * Inputs: + * * 0: A tensor. + * * 1: A tensor of the same {@link OperandType} and dimensions compatible + * with input0. + * + * Outputs: + * * 0: A tensor of {@link OperandType::TENSOR_BOOL8}. + * + * Available since API level 29. + */ EQUAL = 48, + + /** + * Computes exponential of x element-wise. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * + * Supported tensor rank: from 1. + * + * Inputs: + * * 0: A tensor. + * + * Outputs: + * * 0: The output tensor of same shape as input0. + * + * Available since API level 29. + */ EXP = 49, + + /** + * Inserts a dimension of 1 into a tensor's shape. + * + * Given a tensor input, this operation inserts a dimension of 1 at the + * given dimension index of input's shape. The dimension index starts at + * zero; if you specify a negative dimension index, it is counted backward + * from the end. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_INT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: from 1 + * + * Inputs: + * * 0: An n-D tensor. + * * 1: An {@link OperandType::INT32} scalar specifying the dimension + * index to expand. Must be in the range [-(n + 1), (n + 1)). + * + * Outputs: + * * 0: An (n + 1)-D tensor with the same {@link OperandType} and data as + * input0. + * + * Available since API level 29. + */ EXPAND_DIMS = 50, + + /** + * Gathers values along an axis. + * + * Produces an output tensor with shape + * input0.dimension[:axis] + indices.dimension + input0.dimension[axis + 1:] + * where: + * # Vector indices (output is rank(input0)). + * output[a_0, ..., a_n, i, b_0, ..., b_n] = + * input0[a_0, ..., a_n, indices[i], b_0, ..., b_n] + * + * # Higher rank indices (output is rank(input0) + rank(indices) - 1). + * output[a_0, ..., a_n, i, ..., j, b_0, ... b_n] = + * input0[a_0, ..., a_n, indices[i, ..., j], b_0, ..., b_n] + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_INT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: from 1 + * + * Inputs: + * * 0: An n-D tensor from which to gather values. + * * 1: An {@link OperandType::INT32} scalar specifying the axis. + * Negative index is used to specify axis from the end + * (e.g. -1 for the last axis). Must be in the range [-n, n). + * * 2: A k-D tensor {@link OperandType::TENSOR_INT32} of indices. + * The values must be in the bounds of the corresponding dimensions + * of input0. + * + * Outputs: + * * 0: An (n + k - 1)-D tensor with the same {@link OperandType} as input0. + * + * Available since API level 29. + */ GATHER = 51, + + /** + * Generate aixs-aligned bounding box proposals. + * + * Bounding box proposals are generated by applying transformation on a set + * of predefined anchors with the bounding box deltas from bounding box + * regression. A final step of hard NMS is applied to limit the number of + * returned boxes. + * + * Axis-aligned bounding boxes are represented by its upper-left corner + * coordinate (x1,y1) and lower-right corner coordinate (x2,y2). A valid + * bounding box should satisfy x1 <= x2 and y1 <= y2. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Inputs: + * * 0: A 4-D Tensor specifying the score of each anchor at each + * location. With "NHWC" data layout, the tensor shape is + * [batches, height, width, num_anchors]. With "NCHW" data layout, + * the tensor shape is [batches, num_anchors, height, width]. + * * 1: A 4-D Tensor specifying the bounding box deltas. With "NHWC" data + * layout, the tensor shape is [batches, height, width, num_anchors * 4]. + * With "NCHW" data layout, the tensor shape is + * [batches, num_anchors * 4, height, width]. The box deltas are encoded + * in the order of [dx, dy, dw, dh], where dx and dy is the linear-scale + * relative correction factor for the center position of the bounding box + * with respect to the width and height, dw and dh is the log-scale + * relative correction factor for the width and height. The last + * dimensions is the channel dimension. + * * 2: A 2-D Tensor of shape [num_anchors, 4], specifying the shape of each + * predefined anchor, with format [x1, y1, x2, y2]. For input0 of type + * {@link OperandType::TENSOR_QUANT8_ASYMM}, this tensor should be of + * {@link OperandType::TENSOR_QUANT16_SYMM}, with scale of 0.125. + * * 3: A 2-D Tensor of shape [batches, 2], specifying the size of + * each image in the batch, with format [image_height, image_width]. + * * 4: An {@link OperandType::FLOAT32} scalar, specifying the ratio + * from the height of original image to the height of feature map. + * * 5: An {@link OperandType::FLOAT32} scalar, specifying the ratio + * from the width of original image to the width of feature map. + * * 6: An {@link OperandType::INT32} scalar, specifying the maximum + * number of boxes before going into the hard NMS algorithm. Boxes + * with the lowest scores are discarded to meet the limit. Set to + * a non-positive value for unlimited number. + * * 7: An {@link OperandType::INT32} scalar, specifying the maximum + * number of boxes returning from the hard NMS algorithm. Boxes + * with the lowest scores are discarded to meet the limit. Set to + * a non-positive value for unlimited number. + * * 8: An {@link OperandType::FLOAT32} scalar, specifying the IoU + * threshold for hard NMS. + * * 9: An {@link OperandType::FLOAT32} scalar, min_size. Boxes with + * height or width lower than the absolute threshold are filtered out. + * * 10: An {@link OperandType::BOOL} scalar, set to true to specify + * NCHW data layout for input0 and input1. Set to false for NHWC. + * + * Outputs: + * * 0: A tensor of the same {@link OperandType} as input0, of shape + * [num_output_rois], specifying the score of each output box. + * The boxes are grouped by batches, but the sequential order in + * each batch is not guaranteed. For type of + * {@link OperandType::TENSOR_QUANT8_ASYMM}, the scale and zero + * point must be the same as input0. + * * 1: A tensor of the same {@link OperandType} as input1, of shape + * [num_output_rois, 4], specifying the coordinates of each output + * bounding box for each class, with format [x1, y1, x2, y2]. + * The sequential order of the boxes corresponds with output0. + * For type of {@link OperandType::TENSOR_QUANT16_ASYMM}, the + * scale must be 0.125 and the zero point must be 0. + * * 2: A 1-D {@link OperandType::TENSOR_INT32} tensor, of shape + * [batches], specifying the number of output boxes for each image. + * + * Available since API level 29. + */ GENERATE_PROPOSALS = 52, + + /** + * For input tensors x and y, computes x > y elementwise. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_BOOL8} + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_INT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: from 1 + * + * This operation supports broadcasting. + * + * Inputs: + * * 0: A tensor. + * * 1: A tensor of the same {@link OperandType} and dimensions compatible + * with input0. + * + * Outputs: + * * 0: A tensor of {@link OperandType::TENSOR_BOOL8}. + * + * Available since API level 29. + */ GREATER = 53, + /** + * For input tensors x and y, computes x >= y elementwise. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_BOOL8} + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_INT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: from 1 + * + * This operation supports broadcasting. + * + * Inputs: + * * 0: A tensor. + * * 1: A tensor of the same {@link OperandType} and dimensions compatible + * with input0. + * + * Outputs: + * * 0: A tensor of {@link OperandType::TENSOR_BOOL8}. + * + * Available since API level 29. + */ GREATER_EQUAL = 54, + + /** + * Performs a grouped 2-D convolution operation. + * + * Given an input tensor of shape [batches, height, width, depth_in] and a + * filter tensor of shape [depth_out, filter_height, filter_width, depth_group] + * containing depth_out convolutional filters of depth depth_group, GROUPED_CONV + * applies a group of different filters to each input channel group, then + * concatenates the results together. + * + * Specifically, the input channels are divided into num_groups groups, each with + * depth depth_group, i.e. depth_in = num_groups * depth_group. The convolutional + * filters are also divided into num_groups groups, i.e. depth_out is divisible + * by num_groups. GROUPED_CONV applies each group of filters to the corresponding + * input channel group, and the result are concatenated together. + * + * The output dimensions are functions of the filter dimensions, stride, and + * padding. + * + * The values in the output tensor are computed as: + * + * output[b, i, j, g * channel_multiplier + q] = + * sum_{di, dj, dk} ( + * input[b, strides[1] * i + di, strides[2] * j + dj, + * g * depth_group + dk] * + * filter[g * channel_multiplier + q, di, dj, dk] + * ) + bias[channel] + * + * where channel_multiplier = depth_out / num_groups + * + * Supported tensor {@link OperandType} configurations: + * * 32 bit Floating point : + * * * {@link OperandType::TENSOR_FLOAT32} for input, filter, output, and bias. + * + * * 16 bit Floating point: + * * {@link OperandType::TENSOR_FLOAT16} for input, filter, output, and bias. + * + * * Quantized: + * * * {@link OperandType::TENSOR_QUANT8_ASYMM} for input, filter, and output. + * * * {@link OperandType::TENSOR_INT32} for bias (with scale set to + * * * input.scale * filter.scale). + * + * * Quantized with symetric per channel quantization for the filter: + * * * {@link OperandType::TENSOR_QUANT8_ASYMM} for input, and output. + * * * {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} for filter. + * * * {@link OperandType::TENSOR_INT32} for bias (scale set to 0.0, + * * * each value scaling is separate and equal to input.scale * filter.scales[channel]). + * + * Supported tensor rank: 4, with "NHWC" or "NCHW" data layout. + * With the default data layout NHWC, the data is stored in the order of: + * [batch, height, width, channels]. Alternatively, the data layout could + * be NCHW, the data storage order of: [batch, channels, height, width]. + * + * Both explicit padding and implicit padding are supported. + * + * Inputs (explicit padding): + * * 0: A 4-D tensor, of shape [batches, height, width, depth_in], + * specifying the input, where depth_in = num_groups * depth_group. + * * 1: A 4-D tensor, of shape + * [depth_out, filter_height, filter_width, depth_group], specifying + * the filter, where depth_out must be divisible by num_groups. For + * tensor of type {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} + * the channel dimension must be set to 0. + * * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input + * tensor of type {@link OperandType::TENSOR_FLOAT32} or + * {@link OperandType::TENSOR_FLOAT16}, the bias must be of the same + * type. For filter tensor of {@link OperandType::TENSOR_QUANT8_ASYMM}, + * the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint + * of 0 and bias_scale == input_scale * filter_scale. For filter tensor + * of {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL}, the bias + * should be of {@link OperandType::TENSOR_INT32}, with zeroPoint of + * 0 and bias_scale of 0. The actual scale of each value 'i' is equal to + * bias_scale[i] = input_scale * filter_scale[i]. + * * 3: An {@link OperandType::INT32} scalar, specifying the padding on + * the left, in the ‘width’ dimension. + * * 4: An {@link OperandType::INT32} scalar, specifying the padding on + * the right, in the ‘width’ dimension. + * * 5: An {@link OperandType::INT32} scalar, specifying the padding on + * the top, in the ‘height’ dimension. + * * 6: An {@link OperandType::INT32} scalar, specifying the padding on + * the bottom, in the ‘height’ dimension. + * * 7: An {@link OperandType::INT32} scalar, specifying the stride when + * walking through input in the ‘width’ dimension. + * * 8: An {@link OperandType::INT32} scalar, specifying the stride when + * walking through input in the ‘height’ dimension. + * * 9: An {@link OperandType::INT32} scalar, specifying the number of + groups. + * * 10: An {@link OperandType::INT32} scalar, and has to be one of the + * {@link FusedActivationFunc} values. Specifies the activation to + * invoke on the result. + * * 11: An {@link OperandType::BOOL} scalar, set to true to specify + * NCHW data layout for input0 and output0. Set to false for NHWC. + * + * Inputs (implicit padding): + * * 0: A 4-D tensor, of shape [batches, height, width, depth_in], + * specifying the input, where depth_in = num_groups * depth_group. + * * 1: A 4-D tensor, of shape + * [depth_out, filter_height, filter_width, depth_group], specifying + * the filter, where depth_out must be divisible by num_groups. For + * tensor of type {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} + * the channel dimension must be set to 0. + * * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input + * tensor of type {@link OperandType::TENSOR_FLOAT32} or + * {@link OperandType::TENSOR_FLOAT16}, the bias must be of the same + * type. For filter tensor of {@link OperandType::TENSOR_QUANT8_ASYMM}, + * the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint + * of 0 and bias_scale == input_scale * filter_scale. For filter tensor + * of {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL}, the bias + * should be of {@link OperandType::TENSOR_INT32}, with zeroPoint of + * 0 and bias_scale of 0. The actual scale of each value 'i' is equal to + * bias_scale[i] = input_scale * filter_scale[i]. + * * 3: An {@link OperandType::INT32} scalar, specifying the implicit + * padding scheme, has to be one of the + * following values: {0 (NONE), 1 (SAME), 2 (VALID)}. + * * 4: An {@link OperandType::INT32} scalar, specifying the stride when + * walking through input in the ‘width’ dimension. + * * 5: An {@link OperandType::INT32} scalar, specifying the stride when + * walking through input in the ‘height’ dimension. + * * 6: An {@link OperandType::INT32} scalar, specifying the number of + * groups. + * * 7: An {@link OperandType::INT32} scalar, and has to be one of the + * {@link FusedActivationFunc} values. Specifies the activation to + * invoke on the result. + * * 8: An {@link OperandType::BOOL} scalar, set to true to specify + * NCHW data layout for input0 and output0. Set to false for NHWC. + * + * Outputs: + * * 0: The output 4-D tensor, of shape + * [batches, out_height, out_width, depth_out]. For output tensor of + * {@link OperandType::TENSOR_QUANT8_ASYMM}, the following condition + * must be satisfied: output_scale > input_scale * filter_scale (for + * filter tensor of type {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} + * this condition must be true for all filter scales). + * + * Available since API level 29. + */ GROUPED_CONV_2D = 55, + + /** + * Localize the maximum keypoints from heatmaps. + * + * This operation approximates the accurate maximum keypoint scores and + * indices after bicubic upscaling by using Taylor expansion up to the + * quadratic term. + * + * The bounding box is represented by its upper-left corner coordinate + * (x1,y1) and lower-right corner coordinate (x2,y2) in the original image. + * A valid bounding box should satisfy x1 <= x2 and y1 <= y2. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: 4, with "NHWC" or "NCHW" data layout. + * With the default data layout NHWC, the data is stored in the order of: + * [batch, height, width, channels]. Alternatively, the data layout could + * be NCHW, the data storage order of: [batch, channels, height, width]. + * + * Inputs: + * * 0: A 4-D Tensor of shape + * [num_boxes, heatmap_size, heatmap_size, num_keypoints], + * specifying the heatmaps, the height and width of heatmaps should + * be the same, and must be greater than or equal to 2. + * * 1: A 2-D Tensor of shape [num_boxes, 4], specifying the bounding boxes, + * each with format [x1, y1, x2, y2]. For input0 of type + * {@link OperandType::TENSOR_QUANT8_ASYMM}, this tensor should + * be of {@link OperandType::TENSOR_QUANT16_ASYMM}, with zeroPoint + * of 0 and scale of 0.125. + * * 2: An {@link OperandType::BOOL} scalar, set to true to specify + * NCHW data layout for input0. Set to false for NHWC. + * + * Outputs: + * * 0: A tensor of the same {@link OperandType} as input0, with shape + * [num_boxes, num_keypoints], specifying score of the keypoints. + * * 1: A tensor of the same {@link OperandType} as input1, with shape + * [num_boxes, num_keypoints, 2], specifying the location of + * the keypoints, the second dimension is organized as + * [keypoint_x, keypoint_y]. + * + * Available since API level 29. + */ HEATMAP_MAX_KEYPOINT = 56, + + /** + * Applies instance normalization to the input tensor. + * + * The values in the output tensor are computed as: + * + * output[b, h, w, c] = + * (input[b, h, w, c] - mean[b, c]) * gamma / + * sqrt(var[b, c] + epsilon) + beta + * + * Where the mean and variance are computed across the spatial dimensions: + * + * mean[b, c] = + * sum_{h, w}(input[b, h, w, c]) / sum(1) + * + * var[b, c] = + * sum_{h, w}(pow(input[b, h, w, c] - mean[b, c], 2)) / sum(1) + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * + * Supported tensor rank: 4, with "NHWC" or "NCHW" data layout. + * With the default data layout NHWC, the data is stored in the order of: + * [batch, height, width, channels]. Alternatively, the data layout could + * be NCHW, the data storage order of: [batch, channels, height, width]. + * + * Inputs: + * * 0: An n-D tensor, specifying the tensor to be normalized. + * * 1: An {@link OperandType::FLOAT32} scalar, specifying gamma, the + * scale applied to the normalized tensor. + * * 2: An {@link OperandType::FLOAT32} scalar, specifying beta, the + * offset applied to the normalized tensor. + * * 3: An {@link OperandType::FLOAT32} scalar, specifying epsilon, the + * small value added to variance to avoid dividing by zero. + * * 4: An {@link OperandType::BOOL} scalar, set to true to specify + * NCHW data layout for input0 and output0. Set to false for NHWC. + * + * Outputs: + * * 0: A tensor of the same {@link OperandType} and same shape as input0. + * + * Available since API level 29. + */ INSTANCE_NORMALIZATION = 57, + + /** + * For input tensors x and y, computes x < y elementwise. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_BOOL8} + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_INT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: from 1 + * + * This operation supports broadcasting. + * + * Inputs: + * * 0: A tensor. + * * 1: A tensor of the same {@link OperandType} and dimensions compatible + * with input0. + * + * Outputs: + * * 0: A tensor of {@link OperandType::TENSOR_BOOL8}. + * + * Available since API level 29. + */ LESS = 58, + + /** + * For input tensors x and y, computes x <= y elementwise. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_BOOL8} + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_INT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: from 1 + * + * This operation supports broadcasting. + * + * Inputs: + * * 0: A tensor. + * * 1: A tensor of the same {@link OperandType} and dimensions compatible + * with input0. + * + * Outputs: + * * 0: A tensor of {@link OperandType::TENSOR_BOOL8}. + * + * Available since API level 29. + */ LESS_EQUAL = 59, + + /** + * Computes natural logarithm of x element-wise. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * + * Supported tensor rank: from 1. + * + * Inputs: + * * 0: A tensor. + * + * Outputs: + * * 0: The output tensor of same shape as input0. + * + * Available since API level 29. + */ LOG = 60, + + /** + * Returns the truth value of x AND y element-wise. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_BOOL8} + * + * Supported tensor rank: from 1 + * + * This operation supports broadcasting. + * + * Inputs: + * * 0: A tensor of {@link OperandType::TENSOR_BOOL8}. + * * 1: A tensor of {@link OperandType::TENSOR_BOOL8} and dimensions + * compatible with input0. + * + * Outputs: + * * 0: A tensor of {@link OperandType::TENSOR_BOOL8}. + * + * Available since API level 29. + */ LOGICAL_AND = 61, + + /** + * Computes the truth value of NOT x element-wise. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_BOOL8} + * + * Supported tensor rank: from 1. + * + * Inputs: + * * 0: A tensor. + * + * Outputs: + * * 0: The output tensor of same shape as input0. + * + * Available since API level 29. + */ LOGICAL_NOT = 62, + + /** + * Returns the truth value of x OR y element-wise. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_BOOL8} + * + * Supported tensor rank: from 1 + * + * This operation supports broadcasting. + * + * Inputs: + * * 0: A tensor of {@link OperandType::TENSOR_BOOL8}. + * * 1: A tensor of {@link OperandType::TENSOR_BOOL8} and dimensions + * compatible with input0. + * + * Outputs: + * * 0: A tensor of {@link OperandType::TENSOR_BOOL8}. + * + * Available since API level 29. + */ LOGICAL_OR = 63, + + /** + * Computes the log softmax activations given logits. + * + * The output is calculated using this formula: + * + * output = logits * beta - log(reduce_sum(exp(logits * beta), axis)) + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * + * Supported tensor rank: from 1. + * + * Inputs: + * * 0: A tensor specifying the input logits. + * * 1: An {@link OperandType::FLOAT32} scalar, specifying the positive + * scaling factor for the exponent, beta. + * * 2: An {@link OperandType::INT32} scalar specifying the axis to + * reduce across. Negative index is used to specify axis from the + * end (e.g. -1 for the last axis). Must be in the range [-n, n). + * + * Outputs: + * * 0: The output tensor of the same {@link OperandType} and shape as + * input0. + * + * Available since API level 29. + */ LOG_SOFTMAX = 64, + + /** + * Returns the element-wise maximum of two tensors. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_INT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Inputs: + * * 0: A tensor. + * * 1: A tensor of the same {@link OperandType} and compatible dimensions + * with input0. + * + * Outputs: + * * 0: The sum, a tensor of the same {@link OperandType} as input0. + * + * Available since API level 29. + */ MAXIMUM = 65, + + /** + * Returns the element-wise minimum of two tensors. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_INT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Inputs: + * * 0: A tensor. + * * 1: A tensor of the same {@link OperandType} and compatible dimensions + * with input0. + * + * Outputs: + * * 0: The sum, a tensor of the same {@link OperandType} as input0. + * + * Available since API level 29. + */ MINIMUM = 66, + + /** + * Computes numerical negative value element-wise. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_INT32} + * + * Supported tensor rank: from 1. + * + * Inputs: + * * 0: A tensor. + * + * Outputs: + * * 0: The output tensor of same shape as input0. + * + * Available since API level 29. + */ NEG = 67, + + /** + * For input tensors x and y, computes x != y elementwise. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_BOOL8} + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_INT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: from 1 + * + * This operation supports broadcasting. + * + * Inputs: + * * 0: A tensor. + * * 1: A tensor of the same {@link OperandType} and dimensions compatible + * with input0. + * + * Outputs: + * * 0: A tensor of {@link OperandType::TENSOR_BOOL8}. + * + * Available since API level 29. + */ NOT_EQUAL = 68, + + /** + * Pads a tensor with the given constant value according to the specified + * paddings. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: up to 4 + * + * Inputs: + * * 0: An n-D tensor, specifying the tensor to be padded. + * * 1: A 2-D Tensor of {@link OperandType::TENSOR_INT32}, the paddings + * for each spatial dimension of the input tensor. The shape of the + * tensor must be {rank(input0), 2}. + * padding[i, 0] specifies the number of elements to be padded in the + * front of dimension i. + * padding[i, 1] specifies the number of elements to be padded after + * the end of dimension i. + * * 2: An scalar specifying the value to use for padding input0. + * For input tensor of {@link OperandType::TENSOR_FLOAT32}, the + * pad value should be of {@link OperandType::FLOAT32}. + * For input tensor of {@link OperandType::TENSOR_QUANT8_ASYMM}, + * the pad value should be of {@link OperandType::INT32}. The + * scale and zeroPoint are assumed to be the same as in input0. + * + * Outputs: + * * 0: A tensor of the same {@link OperandType} as input0. The + * output tensor has the same rank as input0, and each + * dimension of the output tensor has the same size as the + * corresponding dimension of the input tensor plus the size + * of the padding: + * output0.dimension[i] = + * padding[i, 0] + input0.dimension[i] + padding[i, 1] + * + * Available since API level 29. + */ PAD_V2 = 69, + + /** + * Computes the power of one value to another. + * + * Given a tensor base and a tensor exponent, this operation computes + * base^exponent elementwise. + * + * This operations supports broadcasting. The size of the output is the + * maximum size along each dimension of the input operands. It starts with + * the trailing dimensions, and works its way forward. + * + * For example: + * base.dimension = {4, 1, 2} + * exponent.dimension = {5, 4, 3, 1} + * output.dimension = {5, 4, 3, 2} + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * + * Supported tensor rank: from 1 + * + * Inputs: + * * 0: A tensor specifying the base. + * * 1: A tensor specifying the exponent. + * + * Outputs: + * * 0: An output tensor. + * + * Available since API level 29. + */ POW = 70, + + /** + * Parametric Rectified Linear Unit. + * + * It follows: f(x) = alpha * x for x < 0, f(x) = x for x >= 0, where alpha + * is a learned array with the same {@link OperandType} and compatible + * dimensions as input x. + * + * Two dimensions are compatible when: + * 1. they are equal, or + * 2. one of them is 1 + * + * The size of the output is the maximum size along each dimension of the + * input operands. It starts with the trailing dimensions, and works its way + * forward. + * + * Example: + * input.dimension = {4, 1, 2} + * alpha.dimension = {5, 4, 3, 1} + * output.dimension = {5, 4, 3, 2} + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: from 1 + * + * Inputs: + * * 0: A tensor, specifying the input. + * * 1: A tensor of the same {@link OperandType}, and compatible dimensions + * as input0, specifying the alpha. + * + * Outputs: + * * 0: A tensor of the same {@link OperandType} as input0. + * + * Available since API level 29. + */ PRELU = 71, + + /** + * Quantizes the input tensor. + * + * The formula is: + * + * output = max(0, min(255, round(input / scale) + zeroPoint) + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * + * Supported tensor rank: from 1 + * + * Inputs: + * * 0: A tensor. + * + * Outputs: + * * 0: The output tensor of same shape as input0, but with + * {@link OperandType::TENSOR_QUANT8_ASYMM}. + * + * Available since API level 29. + */ QUANTIZE = 72, + + /** + * A version of quantized LSTM, using 16 bit quantization for internal + * state. + * + * There is no projection layer, so cell state size is equal to the output + * size. + * + * Inputs: + * * 0: A 2-D tensor of type {@link OperandType::TENSOR_QUANT8_ASYMM} + * and shape [numBatches, inputSize] specifying the input to the LSTM + * cell. Tensor is quantized with a fixed quantization range of + * [-1, 127/128] (scale = 1/128, zeroPoint = 128). + * * 1: The input-to-input weights. + * A 2-D tensor of type {@link OperandType::TENSOR_QUANT8_ASYMM} + * and shape [outputSize, inputSize] specifying input-to-input part of + * weights for fully-connected layer inside the LSTM cell. + * Quantization zero point and scale must be the same across all the + * weights. + * * 2: The input-to-forget weights. + * A 2-D tensor of type {@link OperandType::TENSOR_QUANT8_ASYMM} + * and shape [outputSize, inputSize] specifying input-to-forget part of + * weights for fully-connected layer inside the LSTM cell. + * Quantization zero point and scale must be the same across all the + * weights. + * * 3: The input-to-cell weights. + * A 2-D tensor of type {@link OperandType::TENSOR_QUANT8_ASYMM} + * and shape [outputSize, inputSize] specifying input-to-cell part of + * weights for fully-connected layer inside the LSTM cell. + * Quantization zero point and scale must be the same across all the + * weights. + * * 4: The input-to-output weights. + * A 2-D tensor of type {@link OperandType::TENSOR_QUANT8_ASYMM} + * and shape [outputSize, inputSize] specifying input-to-output part of + * weights for fully-connected layer inside the LSTM cell. + * Quantization zero point and scale must be the same across all the + * weights. + * * 5: The recurrent-to-input weights. + * A 2-D tensor of type {@link OperandType::TENSOR_QUANT8_ASYMM} + * and shape [outputSize, inputSize] specifying recurrent-to-input part + * of weights for fully-connected layer inside the LSTM cell. + * Quantization zero point and scale must be the same across all the + * weights. + * * 6: The recurrent-to-forget weights. + * A 2-D tensor of type {@link OperandType::TENSOR_QUANT8_ASYMM} + * and shape [outputSize, inputSize] specifying recurrent-to-forget + * part of weights for fully-connected layer inside the LSTM cell. + * Quantization zero point and scale must be the same across all the + * weights. + * * 7: The recurrent-to-cell weights. + * A 2-D tensor of type {@link OperandType::TENSOR_QUANT8_ASYMM} + * and shape [outputSize, inputSize] specifying recurrent-to-cell part + * of weights for fully-connected layer inside the LSTM cell. + * Quantization zero point and scale must be the same across all the + * weights. + * * 8: The recurrent-to-output weights. + * A 2-D tensor of type {@link OperandType::TENSOR_QUANT8_ASYMM} + * and shape [outputSize, inputSize] specifying recurrent-to-output + * part of weights for fully-connected layer inside the LSTM cell. + * Quantization zero point and scale must be the same across all the + * weights. + * * 9: The input gate bias. + * A 1-D tensor of type {@link OperandType::TENSOR_INT32} and shape + * [outputSize] specifying the bias for the fully-connected layer + * inside the LSTM cell. Bias is quantized with scale being a product + * of input and weights scales and zeroPoint equal to 0. + * * 10:The forget gate bias. + * A 1-D tensor of type {@link OperandType::TENSOR_INT32} and shape + * [outputSize] specifying the bias for the fully-connected layer + * inside the LSTM cell. Bias is quantized with scale being a product + * of input and weights scales and zeroPoint equal to 0. + * * 11:The cell bias. + * A 1-D tensor of type {@link OperandType::TENSOR_INT32} and shape + * [outputSize] specifying the bias for the fully-connected layer + * inside the LSTM cell. Bias is quantized with scale being a product + * of input and weights scales and zeroPoint equal to 0. + * * 12:The output gate bias. + * A 1-D tensor of type {@link OperandType::TENSOR_INT32} and shape + * [outputSize] specifying the bias for the fully-connected layer + * inside the LSTM cell. Bias is quantized with scale being a product + * of input and weights scales and zeroPoint equal to 0. + * * 13: A 2-D tensor of type {@link OperandType::TENSOR_QUANT16_SYMM} + * and shape [numBatches, outputSize] specifying the cell state from the + * previous time step of the LSTM cell. It is quantized using a + * quantization range of [-2^4, 2^4 * 32767/32768] (scale = 2^4 / + * 32768, zeroPoint = 0). + * * 14: A 2-D tensor of type {@link OperandType::TENSOR_QUANT8_ASYMM} + * and shape [numBathes, outputSize] specifying the output of the LSTM + * cell from previous time-step. Tensor is quantized with a fixed + * quantization range of [-1, 127/128] (scale = 1/128, zeroPoint = + * 128). + * + * + * Outputs: + * * 0: A 2-D tensor of type {@link OperandType::TENSOR_QUANT16_SYMM} + * and shape [numBatches, outputSize] which contains a cell state from + * the current time step. Tensor is quantized using a quantization + * range of [-2^4, 2^4 * 32767/32768] (scale = 2^4 / 32768, zeroPoint = + * 0). + * * 1: A 2-D tensor of type {@link OperandType::TENSOR_QUANT8_ASYMM} + * and shape [numBathes, outputSize] which contains the output value. + * Tensor is quantized with a fixed quantization range of [-1, 127/128] + * (scale = 1/128, zeroPoint = 128). + */ QUANTIZED_16BIT_LSTM = 73, + + /** + * Draws samples from a multinomial distribution. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * + * Inputs: + * * 0: A 2-D tensor with shape [batches, classes], specifying the + * unnormalized log-probabilities for all classes. + * * 1: A scalar {@link OperandType::INT32}, specifying the number of + * independent samples to draw for each row slice. + * * 2: A 1-D {@link OperandType::TENSOR_INT32} tensor with shape [2], + * specifying seeds used to initialize the random distribution. + * Outputs: + * * 0: A 2-D {@link OperandType::TENSOR_INT32} tensor with shape + * [batches, samples], containing the drawn samples. + * + * Available since API level 29. + */ RANDOM_MULTINOMIAL = 74, + + /** + * Reduces a tensor by computing the "logical and" of elements along given + * dimensions. + * + * If keep_dims is true, the reduced dimensions are + * retained with length 1. Otherwise, the rank of the tensor is reduced by + * 1 for each entry in dimensions. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_BOOL8} + * + * Supported tensor rank: up to 4 + * + * Inputs: + * * 0: An n-D tensor. + * * 1: A 1-D tensor of {@link OperandType::TENSOR_INT32}. The dimensions + * to reduce. Dimension values must be in the range [-n, n). + * * 2: An {@link OperandType::BOOL} scalar, keep_dims. If true, + * retains reduced dimensions with length 1. + * + * Outputs: + * * 0: A tensor of the same {@link OperandType} as input0. + * + * Available since API level 29. + */ REDUCE_ALL = 75, + + /** + * Reduces a tensor by computing the "logical or" of elements along given + * dimensions. + * + * If keep_dims is true, the reduced dimensions are + * retained with length 1. Otherwise, the rank of the tensor is reduced by + * 1 for each entry in dimensions. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_BOOL8} + * + * Supported tensor rank: up to 4 + * + * Inputs: + * * 0: An n-D tensor. + * * 1: A 1-D tensor of {@link OperandType::TENSOR_INT32}. The dimensions + * to reduce. Dimension values must be in the range [-n, n). + * * 2: An {@link OperandType::BOOL} scalar, keep_dims. If true, + * retains reduced dimensions with length 1. + * + * Outputs: + * * 0: A tensor of the same {@link OperandType} as input0. + * + * Available since API level 29. + */ REDUCE_ANY = 76, + + /** + * Reduces a tensor by computing the maximum of elements along given + * dimensions. + * + * If keep_dims is true, the reduced dimensions are + * retained with length 1. Otherwise, the rank of the tensor is reduced by + * 1 for each entry in dimensions. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: up to 4 + * + * Inputs: + * * 0: An n-D tensor. + * * 1: A 1-D tensor of {@link OperandType::TENSOR_INT32}. The dimensions + * to reduce. Dimension values must be in the range [-n, n). + * * 2: An {@link OperandType::BOOL} scalar, keep_dims. If true, + * retains reduced dimensions with length 1. + * + * Outputs: + * * 0: A tensor of the same {@link OperandType} as input0. + * + * Available since API level 29. + */ REDUCE_MAX = 77, + + /** + * Reduces a tensor by computing the minimum of elements along given + * dimensions. + * + * If keep_dims is true, the reduced dimensions are + * retained with length 1. Otherwise, the rank of the tensor is reduced by + * 1 for each entry in dimensions. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: up to 4 + * + * Inputs: + * * 0: An n-D tensor. + * * 1: A 1-D tensor of {@link OperandType::TENSOR_INT32}. The dimensions + * to reduce. Dimension values must be in the range [-n, n). + * * 2: An {@link OperandType::BOOL} scalar, keep_dims. If true, + * retains reduced dimensions with length 1. + * + * Outputs: + * * 0: A tensor of the same {@link OperandType} as input0. + * + * Available since API level 29. + */ REDUCE_MIN = 78, + + /** + * Reduces a tensor by multiplying elements along given dimensions. + * + * If keep_dims is true, the reduced dimensions are + * retained with length 1. Otherwise, the rank of the tensor is reduced by + * 1 for each entry in dimensions. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * + * Supported tensor rank: up to 4 + * + * Inputs: + * * 0: An n-D tensor. + * * 1: A 1-D tensor of {@link OperandType::TENSOR_INT32}. The dimensions + * to reduce. Dimension values must be in the range [-n, n). + * * 2: An {@link OperandType::BOOL} scalar, keep_dims. If true, + * retains reduced dimensions with length 1. + * + * Outputs: + * * 0: A tensor of the same {@link OperandType} as input0. + * + * Available since API level 29. + */ REDUCE_PROD = 79, + + /** + * Reduces a tensor by summing elements along given dimensions. + * + * If keep_dims is true, the reduced dimensions are + * retained with length 1. Otherwise, the rank of the tensor is reduced by + * 1 for each entry in dimensions. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * + * Supported tensor rank: up to 4 + * + * Inputs: + * * 0: An n-D tensor. + * * 1: A 1-D tensor of {@link OperandType::TENSOR_INT32}. The dimensions + * to reduce. Dimension values must be in the range [-n, n). + * * 2: An {@link OperandType::BOOL} scalar, keep_dims. If true, + * retains reduced dimensions with length 1. + * + * Outputs: + * * 0: A tensor of the same {@link OperandType} as input0. + * + * Available since API level 29. + */ REDUCE_SUM = 80, + + /** + * Select and scale the feature map of each region of interest to a unified + * output size by average pooling sampling points from bilinear interpolation. + * + * The region of interest is represented by its upper-left corner coordinate + * (x1,y1) and lower-right corner coordinate (x2,y2) in the original image. + * A spatial scaling factor is applied to map into feature map coordinate. + * A valid region of interest should satisfy x1 <= x2 and y1 <= y2. + * + * No rounding is applied in this operation. The sampling points are unified + * distributed in the pooling bin and their values are calculated by bilinear + * interpolation. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: 4, with "NHWC" or "NCHW" data layout. + * With the default data layout NHWC, the data is stored in the order of: + * [batch, height, width, channels]. Alternatively, the data layout could + * be NCHW, the data storage order of: [batch, channels, height, width]. + * + * Inputs: + * * 0: A 4-D tensor, specifying the feature map. + * * 1: A 2-D Tensor of shape [num_rois, 4], specifying the locations of + * the regions of interest, each line with format [x1, y1, x2, y2]. + * For input0 of type {@link OperandType::TENSOR_QUANT8_ASYMM}, + * this tensor should be of {@link OperandType::TENSOR_QUANT16_ASYMM}, + * with zeroPoint of 0 and scale of 0.125. + * * 2: An 1-D {@link OperandType::TENSOR_INT32} tensor, of shape + * [batches], specifying the number of output boxes for each batch. + * * 3: An {@link OperandType::INT32} scalar, specifying the output + * height of the output tensor. + * * 4: An {@link OperandType::INT32} scalar, specifying the output + * width of the output tensor. + * * 5: An {@link OperandType::FLOAT32} scalar, specifying the ratio + * from the height of original image to the height of feature map. + * * 6: An {@link OperandType::FLOAT32} scalar, specifying the ratio + * from the width of original image to the width of feature map. + * * 7: An {@link OperandType::INT32} scalar, specifying the number of + * sampling points in height dimension used to compute the output. + * Set to 0 for adaptive value of ceil(roi_height/out_height). + * * 8: An {@link OperandType::INT32} scalar, specifying the number of + * sampling points in width dimension used to compute the output. + * Set to 0 for adaptive value of ceil(roi_width/out_width). + * * 9: An {@link OperandType::BOOL} scalar, set to true to specify + * NCHW data layout for input0 and output0. Set to false for NHWC. + * + * Outputs: + * * 0: A tensor of the same {@link OperandType} as input0. The output + * shape is [num_rois, out_height, out_width, depth]. + * + * Available since API level 29. + */ ROI_ALIGN = 81, + + /** + * Select and scale the feature map of each region of interest to a unified + * output size by max-pooling. + * + * The region of interest is represented by its upper-left corner coordinate + * (x1,y1) and lower-right corner coordinate (x2,y2) in the original image. + * A spatial scaling factor is applied to map into feature map coordinate. + * A valid region of interest should satisfy x1 <= x2 and y1 <= y2. + * + * Rounding is applied in this operation to ensure integer boundary for + * regions of interest and pooling bins. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: 4, with "NHWC" or "NCHW" data layout. + * With the default data layout NHWC, the data is stored in the order of: + * [batch, height, width, channels]. Alternatively, the data layout could + * be NCHW, the data storage order of: [batch, channels, height, width]. + * + * Inputs: + * * 0: A 4-D tensor, specifying the feature map. + * * 1: A 2-D Tensor of shape [num_rois, 4], specifying the locations of + * the regions of interest, each line with format [x1, y1, x2, y2]. + * For input0 of type {@link OperandType::TENSOR_QUANT8_ASYMM}, + * this tensor should be of {@link OperandType::TENSOR_QUANT16_ASYMM}, + * with zeroPoint of 0 and scale of 0.125. + * * 2: An 1-D {@link OperandType::TENSOR_INT32} tensor, of shape + * [batches], specifying the number of output boxes for each batch. + * * 3: An {@link OperandType::INT32} scalar, specifying the output + * height of the output tensor. + * * 4: An {@link OperandType::INT32} scalar, specifying the output + * width of the output tensor. + * * 5: An {@link OperandType::FLOAT32} scalar, specifying the ratio + * from the height of original image to the height of feature map. + * * 6: An {@link OperandType::FLOAT32} scalar, specifying the ratio + * from the width of original image to the width of feature map. + * * 7: An {@link OperandType::BOOL} scalar, set to true to specify + * NCHW data layout for input0 and output0. Set to false for NHWC. + * + * Outputs: + * * 0: A tensor of the same {@link OperandType} as input0. The output + * shape is [num_rois, out_height, out_width, depth]. + * + * Available since API level 29. + */ ROI_POOLING = 82, + + /** + * Computes reciprocal of square root of x element-wise. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * + * Supported tensor rank: from 1. + * + * Inputs: + * * 0: A tensor. + * + * Outputs: + * * 0: The output tensor of same shape as input0. + * + * Available since API level 29. + */ RSQRT = 83, + + /** + * Using a tensor of booleans c and input tensors x and y select values + * elementwise from both input tensors: + * + * O[i] = C[i] ? x[i] : y[i]. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_INT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: from 1 + * + * Inputs: + * * 0: A tensor of type {@link OperandType::TENSOR_BOOL8} acting as a + * mask that chooses, based on the value at each element, whether the + * corresponding element in the output should be taken from input1 (if + * true) or input2 (if false). + * * 1: An input tensor of the same shape as input0. + * * 2: An input tensor of the same shape and type as input1. + * + * Outputs: + * * 0: A tensor of the same type and shape as input1 and input2. + * + */ SELECT = 84, + + /** + * Computes sin of x element-wise. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * + * Supported tensor rank: from 1. + * + * Inputs: + * * 0: A tensor. + * + * Outputs: + * * 0: The output tensor of same shape as input0. + * + * Available since API level 29. + */ SIN = 85, + + /** + * Extracts a slice of specified size from the input tensor starting at a + * specified location. + * + * The starting location is specified as a 1-D tensor containing offsets + * for each dimension. The size is specified as a 1-D tensor containing + * either size of a slice along corresponding dimension or -1. In the latter + * case, all the remaining elements in dimension are included in the slice. + * Slice size in each dimension cannot be zero. + * + * A sum of begin offset and a size of a slice must not exceed size of a + * corresponding dimension. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_INT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: from 1 + * + * Inputs: + * * 0: An n-D tensor to take slice from. + * * 1: A 1-D tensor of type {@link OperandType::TENSOR_INT32} specifying + * the beginning indices of the slice in each dimension. + * * 2: A 1-D tensor of type {@link OperandType::TENSOR_INT32} specifying + * the size of the slice in each dimension. + * + * Outputs: + * * 0: An n-D tensor of the same type as the input containing the slice. + * + * Available since API level 29. + */ SLICE = 86, + + /** + * Splits a tensor along a given axis into num_splits subtensors. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_INT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: from 1 + * + * Inputs: + * * 0: An n-D tensor to split. + * * 1: An {@link OperandType::INT32} scalar specifying the axis along + * which to split. + * * 2: An {@link OperandType::INT32} scalar indicating the number of + * splits along given axis. Must evenly divide axis size. + * + * Outputs: + * * 0 ~ (num_splits - 1): Resulting subtensors. + * + * Available since API level 29. + */ SPLIT = 87, + + /** + * Computes square root of x element-wise. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * + * Supported tensor rank: from 1. + * + * Inputs: + * * 0: A tensor. + * + * Outputs: + * * 0: The output tensor of same shape as input0. + * + * Available since API level 29. + */ SQRT = 88, + + /** + * Constructs a tensor by tiling a given tensor. + * + * This operation creates a new tensor by replicating `input` `multiples` + * times. The output tensor's i-th dimension has `input.dims(i) * multiples[i]` + * elements, and the values of `input` are replicated `multiples[i]` times + * along the i-th dimension. + * For example, tiling `[a b c d]` by `[2]` produces `[a b c d a b c d]`. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_INT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: from 1 + * + * Inputs: + * * 0: input, an n-D tensor specifying the input. + * * 1: multiples, a 1-D tensor of {@link OperandType::TENSOR_INT32}. + * The length of multiples must be n. + * + * Outputs: + * * 0: A tiled tensor of the same {@link OperandType} and rank as `input`. + * + * Available since API level 29. + */ TILE = 89, + + /** + * Finds values and indices of the k largest entries for the last dimension. + * + * Resulting values in each dimensions are sorted in descending order. If + * two values are equal, the one with larger index appears first. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_INT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: from 1 + * + * Inputs: + * * 0: input, an n-D tensor specifying the input. + * * 1: k, an {@link OperandType::INT32} scalar, specifying the number of + * top elements to look for along the last dimension. + * + * Outputs: + * * 0: An n-D tensor of the same type as the input, containing the k + * largest elements along each last dimensional slice. + * * 1: An n-D tensor of type {@link OperandType::TENSOR_INT32} + * containing the indices of values within the last dimension of input. + * + * Available since API level 29. + */ TOPK_V2 = 90, + + /** + * Performs the tranpose of 2-D convolution operation. + * + * This operation is sometimes called "deconvolution" after Deconvolutional + * Networks, but is actually the transpose (gradient) of + * {@link OperandType::CONV_2D} rather than an actual deconvolution. + * + * The output dimensions are functions of the filter dimensions, stride, and + * padding. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: 4, with "NHWC" or "NCHW" data layout. + * With the default data layout NHWC, the data is stored in the order of: + * [batch, height, width, channels]. Alternatively, the data layout could + * be NCHW, the data storage order of: [batch, channels, height, width]. + * + * Both explicit padding and implicit padding are supported. + * + * Inputs (explicit padding): + * * 0: A 4-D tensor, of shape [batches, height, width, depth_in], + * specifying the input. + * * 1: A 4-D tensor, of shape + * [depth_out, filter_height, filter_width, depth_in], specifying the + * filter. + * * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input + * tensor of type {@link OperandType::TENSOR_FLOAT32} or + * {@link OperandType::TENSOR_FLOAT16}, the bias should be of the + * same type. For input tensor of type + * {@link OperandType::TENSOR_QUANT8_ASYMM}, the bias should be + * of {@link OperandType::TENSOR_INT32}, with zeroPoint of 0 and + * bias_scale == input_scale * filter_scale. + * * 3: An {@link OperandType::INT32} scalar, specifying the padding on + * the left, in the ‘width’ dimension. + * * 4: An {@link OperandType::INT32} scalar, specifying the padding on + * the right, in the ‘width’ dimension. + * * 5: An {@link OperandType::INT32} scalar, specifying the padding on + * the top, in the ‘height’ dimension. + * * 6: An {@link OperandType::INT32} scalar, specifying the padding on + * the bottom, in the ‘height’ dimension. + * * 7: An {@link OperandType::INT32} scalar, specifying the stride when + * walking through input in the ‘width’ dimension. + * * 8: An {@link OperandType::INT32} scalar, specifying the stride when + * walking through input in the ‘height’ dimension. + * * 9: An {@link OperandType::INT32} scalar, and has to be one of the + * {@link FusedActivationFunc} values. Specifies the activation to + * invoke on the result. + * * 10: An {@link OperandType::BOOL} scalar, set to true to specify + * NCHW data layout for input0 and output0. Set to false for NHWC. + * + * Inputs (implicit padding): + * * 0: A 4-D tensor, of shape [batches, height, width, depth_in], + * specifying the input. + * * 1: A 4-D tensor, of shape + * [depth_out, filter_height, filter_width, depth_in], specifying the + * filter. + * * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input + * tensor of type {@link OperandType::TENSOR_FLOAT32} or + * {@link OperandType::TENSOR_FLOAT16}, the bias should be of the + * same type. For input tensor of type + * {@link OperandType::TENSOR_QUANT8_ASYMM}, the bias should be + * of {@link OperandType::TENSOR_INT32}, with zeroPoint of 0 and + * bias_scale == input_scale * filter_scale. + * * 3: An {@link OperandType::TENSOR_INT32} tensor, specifying the output + * tensor shape. + * * 4: An {@link OperandType::INT32} scalar, specifying the implicit + * padding scheme, has to be one of the + * following values: {0 (NONE), 1 (SAME), 2 (VALID)}. + * * 5: An {@link OperandType::INT32} scalar, specifying the stride when + * walking through input in the ‘width’ dimension. + * * 6: An {@link OperandType::INT32} scalar, specifying the stride when + * walking through input in the ‘height’ dimension. + * * 7: An {@link OperandType::INT32} scalar, and has to be one of the + * {@link FusedActivationFunc} values. Specifies the activation to + * invoke on the result. + * * 8: An {@link OperandType::BOOL} scalar, set to true to specify + * NCHW data layout for input0 and output0. Set to false for NHWC. + * + * Outputs: + * * 0: The output 4-D tensor, of shape + * [batches, out_height, out_width, depth_out]. For output tensor of + * {@link OperandType::TENSOR_QUANT8_ASYMM}, the following condition + * must be satisfied: output_scale > input_scale * filter_scale. + * + * Available since API level 29. + */ TRANSPOSE_CONV_2D = 91, + + /** + * A recurrent neural network specified by an LSTM cell. + * + * Performs (fully) dynamic unrolling of input. + * + * This Op unrolls the input along the time dimension, and implements the + * following operation for each element in the sequence + * s = 1...sequence_length: + * outputs[s] = projection(state = activation(LSTMOp(inputs[s]))) + * + * Where LSTMOp is the LSTM op as in {@link OperandType::LSTM}, + * the "projection" is an optional projection layer from state and output + * and the “activation” is the function passed as the + * “fused_activation_function” argument (if not “NONE”). + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * + * Supported tensor rank: 3, either time-major or batch-major. + * + * All input and output tensors must be of the same type. + * + * Inputs: + * * 0: The input (\f$x_t\f$). + * A 3-D tensor of shape: + * If time-major: [max_time, batch_size, output_size] + * If batch-major: [batch_size, max_time, output_size] + * where “max_size” is the number of timesteps (sequence length), + * “batch_size” corresponds to the batching dimension, and + * “input_size” is the size of the input. + * * 1: The input-to-input weights (\f$W_{xi}\f$). Optional. + * A 2-D tensor of shape [num_units, input_size], where “num_units” + * corresponds to the number of cell units. + * * 2: The input-to-forget weights (\f$W_{xf}\f$). + * A 2-D tensor of shape [num_units, input_size]. + * * 3: The input-to-cell weights (\f$W_{xc}\f$). + * A 2-D tensor of shape [num_units, input_size]. + * * 4: The input-to-output weights (\f$W_{xo}\f$). + * A 2-D tensor of shape [num_units, input_size]. + * * 5: The recurrent-to-input weights (\f$W_{hi}\f$). Optional. + * A 2-D tensor of shape [num_units, output_size], where “output_size” + * corresponds to either the number of cell units (i.e., “num_units”), + * or the second dimension of the “projection_weights”, if defined. + * * 6: The recurrent-to-forget weights (\f$W_{hf}\f$). + * A 2-D tensor of shape [num_units, output_size]. + * * 7: The recurrent-to-cell weights (\f$W_{hc}\f$). + * A 2-D tensor of shape [num_units, output_size]. + * * 8: The recurrent-to-output weights (\f$W_{ho}\f$). + * A 2-D tensor of shape [num_units, output_size]. + * * 9: The cell-to-input weights (\f$W_{ci}\f$). Optional. + * A 1-D tensor of shape [num_units]. + * * 10:The cell-to-forget weights (\f$W_{cf}\f$). Optional. + * A 1-D tensor of shape [num_units]. + * * 11:The cell-to-output weights (\f$W_{co}\f$). Optional. + * A 1-D tensor of shape [num_units]. + * * 12:The input gate bias (\f$b_i\f$). Optional. + * A 1-D tensor of shape [num_units]. + * * 13:The forget gate bias (\f$b_f\f$). + * A 1-D tensor of shape [num_units]. + * * 14:The cell bias (\f$b_c\f$). + * A 1-D tensor of shape [num_units]. + * * 15:The output gate bias (\f$b_o\f$). + * A 1-D tensor of shape [num_units]. + * * 16:The projection weights (\f$W_{proj}\f$). Optional. + * A 2-D tensor of shape [output_size, num_units]. + * * 17:The projection bias (\f$b_{proj}\f$). Optional. + * A 1-D tensor of shape [output_size]. + * * 18:The output state (in) (\f$h_{t-1}\f$). + * A 2-D tensor of shape [batch_size, output_size]. + * * 19:The cell state (in) (\f$C_{t-1}\f$). + * A 2-D tensor of shape [batch_size, num_units]. + * * 20:The activation function (\f$g\f$). + * A value indicating the activation function: + *
    + *
  • 0: None; + *
  • 1: Relu; + *
  • 3: Relu6; + *
  • 4: Tanh; + *
  • 6: Sigmoid. + *
+ * * 21:The clipping threshold (\f$t_{cell}\f$) for the cell state, such + * that values are bound within [-cell_clip, cell_clip]. If set to 0.0 + * then clipping is disabled. + * * 22:The clipping threshold (\f$t_{proj}\f$) for the output from the + * projection layer, such that values are bound within + * [-proj_clip, proj_clip]. If set to 0.0 then clipping is disabled. + * * 23:Time-major if true, batch-major if false. + * * 24:The input layer normalization weights. + * A 1-D tensor of shape [num_units]. Used to rescale normalized inputs + * to activation at input gate. + * * 25:The forget layer normalization weights. + * A 1-D tensor of shape [num_units]. Used to rescale normalized inputs + * to activation at forget gate. + * * 26:The cell layer normalization weights. + * A 1-D tensor of shape [num_units]. Used to rescale normalized inputs + * to activation at cell gate. + * * 27:The output layer normalization weights. + * A 1-D tensor of shape [num_units]. Used to rescale normalized inputs + * to activation at output gate. + * + * Outputs: + * * 0: The output (\f$o_t\f$). + * A 3-D tensor of shape: + * If time-major: [max_time, batch_size, output_size] + * If batch-major: [batch_size, max_time, output_size] + * + * Available since API level 29. + */ UNIDIRECTIONAL_SEQUENCE_LSTM = 92, + + /** + * A recurrent neural network layer that applies a basic RNN cell to a + * sequence of inputs. + * + * This layer unrolls the input along the sequence dimension, and implements + * the following operation + * for each element in the sequence s = 1...sequence_length: + * outputs[s] = state = activation(inputs[s] * input_weights’ + state * + * recurrent_weights’ + bias) + * + * Where: + * * “input_weights” is a weight matrix that multiplies the inputs; + * * “recurrent_weights” is a weight matrix that multiplies the current + * “state” which itself is the output from the previous time step + * computation; + * * “bias” is a bias vector (added to each output vector in the batch); + * * “activation” is the function passed as the “fused_activation_function” + * argument (if not “NONE”). + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * + * The input tensors must all be the same type. + * + * Inputs: + * * 0: input. + * A 3-D tensor. The shape is defined by the input 6 (timeMajor). If + * it is set to 1, then the input has a shape [maxTime, batchSize, + * inputSize], otherwise the input has a shape [batchSize, maxTime, + * inputSize]. + * * 1: weights. + * A 2-D tensor of shape [numUnits, inputSize]. + * * 2: recurrent_weights. + * A 2-D tensor of shape [numUnits, numUnits]. + * * 3: bias. + * A 1-D tensor of shape [numUnits]. + * * 4: hidden state + * A 2-D tensor of shape [batchSize, numUnits]. Specifies a hidden + * state input for the first time step of the computation. + * * 5: fusedActivationFunction. + * A {@link FusedActivationFunc} value indicating the activation function. If + * “NONE” is specified then it results in a linear activation. + * * 6: timeMajor + * An {@link OperandType::INT32} scalar specifying the shape format + * of input and output tensors. Must be set to either 0 or 1. + * Outputs: + * * 0: output. + * A 3-D tensor. The shape is defined by the input 6 (timeMajor). If + * it is set to 1, then the output has a shape [maxTime, batchSize, + * numUnits], otherwise the output has a shape [batchSize, maxTime, + * numUnits]. + * + * Available since API level 29. + */ UNIDIRECTIONAL_SEQUENCE_RNN = 93, + /** + * DEPRECATED. Since NNAPI 1.2, extensions are the preferred alternative to + * OEM operation and data types. + * + * This operation is OEM specific. It should only be used for OEM + * applications. + */ + OEM_OPERATION = @1.1::OperationType:OEM_OPERATION, /* ADDING A NEW FUNDAMENTAL OPERATION REQUIRES UPDATING THE VALUE OF * OperationTypeRange::FUNDAMENTAL_MAX. */ From 3e3cbb7c2193945ce9a09f202a856f53c982ca72 Mon Sep 17 00:00:00 2001 From: Henry Fang Date: Thu, 31 Jan 2019 22:46:57 +0000 Subject: [PATCH 448/718] Revert "Revert "Update cas@1.0 hal to cas@1.1"" This reverts commit 1b066c8d1d1e544bcdb8aa7800db334208ad705c. Reason for revert: Change-Id: If1fa2a244e5f4ee7f978cda79421172da02220f1 --- cas/1.1/Android.bp | 20 ++ cas/1.1/ICas.hal | 42 ++++ cas/1.1/ICasListener.hal | 33 +++ cas/1.1/IMediaCasService.hal | 38 +++ cas/1.1/default/Android.bp | 49 ++++ cas/1.1/default/CasImpl.cpp | 222 ++++++++++++++++++ cas/1.1/default/CasImpl.h | 98 ++++++++ cas/1.1/default/DescramblerImpl.cpp | 195 +++++++++++++++ cas/1.1/default/DescramblerImpl.h | 67 ++++++ cas/1.1/default/FactoryLoader.h | 217 +++++++++++++++++ cas/1.1/default/MediaCasService.cpp | 126 ++++++++++ cas/1.1/default/MediaCasService.h | 66 ++++++ cas/1.1/default/SharedLibrary.cpp | 65 +++++ cas/1.1/default/SharedLibrary.h | 50 ++++ cas/1.1/default/TypeConvert.cpp | 94 ++++++++ cas/1.1/default/TypeConvert.h | 43 ++++ .../android.hardware.cas@1.1-service-lazy.rc | 9 + .../android.hardware.cas@1.1-service-lazy.xml | 11 + .../android.hardware.cas@1.1-service.rc | 6 + .../android.hardware.cas@1.1-service.xml | 11 + cas/1.1/default/service.cpp | 58 +++++ .../compatibility_matrix.current.xml | 2 +- 22 files changed, 1521 insertions(+), 1 deletion(-) create mode 100644 cas/1.1/Android.bp create mode 100644 cas/1.1/ICas.hal create mode 100644 cas/1.1/ICasListener.hal create mode 100644 cas/1.1/IMediaCasService.hal create mode 100644 cas/1.1/default/Android.bp create mode 100644 cas/1.1/default/CasImpl.cpp create mode 100644 cas/1.1/default/CasImpl.h create mode 100644 cas/1.1/default/DescramblerImpl.cpp create mode 100644 cas/1.1/default/DescramblerImpl.h create mode 100644 cas/1.1/default/FactoryLoader.h create mode 100644 cas/1.1/default/MediaCasService.cpp create mode 100644 cas/1.1/default/MediaCasService.h create mode 100644 cas/1.1/default/SharedLibrary.cpp create mode 100644 cas/1.1/default/SharedLibrary.h create mode 100644 cas/1.1/default/TypeConvert.cpp create mode 100644 cas/1.1/default/TypeConvert.h create mode 100644 cas/1.1/default/android.hardware.cas@1.1-service-lazy.rc create mode 100644 cas/1.1/default/android.hardware.cas@1.1-service-lazy.xml create mode 100644 cas/1.1/default/android.hardware.cas@1.1-service.rc create mode 100644 cas/1.1/default/android.hardware.cas@1.1-service.xml create mode 100644 cas/1.1/default/service.cpp diff --git a/cas/1.1/Android.bp b/cas/1.1/Android.bp new file mode 100644 index 0000000000..bb0edb970c --- /dev/null +++ b/cas/1.1/Android.bp @@ -0,0 +1,20 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +hidl_interface { + name: "android.hardware.cas@1.1", + root: "android.hardware", + vndk: { + enabled: true, + }, + srcs: [ + "ICas.hal", + "ICasListener.hal", + "IMediaCasService.hal", + ], + interfaces: [ + "android.hardware.cas@1.0", + "android.hidl.base@1.0", + ], + gen_java: true, +} + diff --git a/cas/1.1/ICas.hal b/cas/1.1/ICas.hal new file mode 100644 index 0000000000..027968e565 --- /dev/null +++ b/cas/1.1/ICas.hal @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.hardware.cas@1.1; + +import @1.0::HidlCasSessionId; +import @1.0::ICas; +import @1.0::Status; + +/** + * ICas is the API to control the cas system and is accessible from both + * Java and native level. It is used to manage sessions, provision/refresh + * the cas system, and process the EMM/ECM messages. It also allows bi-directional, + * scheme-specific communications between the client and the cas system. + */ + +interface ICas extends @1.0::ICas { + /** + * Send an scheme-specific session event to the CasPlugin. + * + * @param sessionId the id of an opened session. + * @param event an integer denoting a scheme-specific event to be sent. + * @param arg a scheme-specific integer argument for the event. + * @param data a byte array containing scheme-specific data for the event. + * @return status the status of the call. + */ + sendSessionEvent(HidlCasSessionId sessionId, int32_t event, int32_t arg, + vec eventData) + generates (Status status); +}; diff --git a/cas/1.1/ICasListener.hal b/cas/1.1/ICasListener.hal new file mode 100644 index 0000000000..5ec1154a3f --- /dev/null +++ b/cas/1.1/ICasListener.hal @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.hardware.cas@1.1; + +import @1.0::ICasListener; +import @1.0::HidlCasSessionId; + +interface ICasListener extends @1.0::ICasListener{ + /** + * Notify the listener of a scheme-specific session event from CA system. + * + * @param sessionId the id of an opened session. + * @param event an integer whose meaning is scheme-specific. + * @param arg an integer whose meaning is scheme-specific. + * @param data a byte array of data whose format and meaning are + * scheme-specific. + */ + onSessionEvent(HidlCasSessionId sessionId, int32_t event, int32_t arg, + vec data); +}; diff --git a/cas/1.1/IMediaCasService.hal b/cas/1.1/IMediaCasService.hal new file mode 100644 index 0000000000..e82b54c9db --- /dev/null +++ b/cas/1.1/IMediaCasService.hal @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.hardware.cas@1.1; + +import @1.1::ICas; +import @1.1::ICasListener; +import @1.0::IMediaCasService; + +/** + * IMediaCasService is the main entry point for interacting with a vendor's + * cas HAL to create cas and descrambler plugin instances. A cas plugin instance + * opens cas sessions which are used to obtain keys for a descrambler session, + * which can in turn be used to descramble protected video content. + */ + +interface IMediaCasService extends @1.0::IMediaCasService { + /** + * Construct a new instance of a @1.1 ICAS CasPlugin given a CA_system_id. + * + * @param caSystemId the id of the CA system. + * @param listener the event listener to receive events coming from the CasPlugin. + * @return cas the newly created CasPlugin interface. + */ + createPluginExt(int32_t caSystemId, ICasListener listener) generates (ICas cas); +}; diff --git a/cas/1.1/default/Android.bp b/cas/1.1/default/Android.bp new file mode 100644 index 0000000000..68a49cf5b1 --- /dev/null +++ b/cas/1.1/default/Android.bp @@ -0,0 +1,49 @@ +cc_defaults { + name: "cas_service_defaults@1.1", + defaults: ["hidl_defaults"], + vendor: true, + relative_install_path: "hw", + srcs: [ + "CasImpl.cpp", + "DescramblerImpl.cpp", + "MediaCasService.cpp", + "service.cpp", + "SharedLibrary.cpp", + "TypeConvert.cpp", + ], + + compile_multilib: "32", + + shared_libs: [ + "android.hardware.cas@1.0", + "android.hardware.cas@1.1", + "android.hardware.cas.native@1.0", + "android.hidl.memory@1.0", + "libbinder", + "libhidlbase", + "libhidlmemory", + "libhidltransport", + "liblog", + "libutils", + ], + header_libs: [ + "libstagefright_foundation_headers", + "media_plugin_headers", + ], +} + +cc_binary { + name: "android.hardware.cas@1.1-service", + vintf_fragments: ["android.hardware.cas@1.1-service.xml"], + defaults: ["cas_service_defaults@1.1"], + init_rc: ["android.hardware.cas@1.1-service.rc"], +} + +cc_binary { + name: "android.hardware.cas@1.1-service-lazy", + vintf_fragments: ["android.hardware.cas@1.1-service-lazy.xml"], + overrides: ["android.hardware.cas@1.1-service"], + defaults: ["cas_service_defaults@1.1"], + init_rc: ["android.hardware.cas@1.1-service-lazy.rc"], + cflags: ["-DLAZY_SERVICE"], +} diff --git a/cas/1.1/default/CasImpl.cpp b/cas/1.1/default/CasImpl.cpp new file mode 100644 index 0000000000..4cc6017028 --- /dev/null +++ b/cas/1.1/default/CasImpl.cpp @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "android.hardware.cas@1.1-CasImpl" + +#include +#include +#include + +#include "CasImpl.h" +#include "SharedLibrary.h" +#include "TypeConvert.h" + +namespace android { +namespace hardware { +namespace cas { +namespace V1_1 { +namespace implementation { + +CasImpl::CasImpl(const sp& listener) : mListener(listener) { + ALOGV("CTOR"); +} + +CasImpl::~CasImpl() { + ALOGV("DTOR"); + release(); +} + +// static +void CasImpl::OnEvent(void* appData, int32_t event, int32_t arg, uint8_t* data, size_t size) { + if (appData == NULL) { + ALOGE("Invalid appData!"); + return; + } + CasImpl* casImpl = static_cast(appData); + casImpl->onEvent(event, arg, data, size); +} + +// static +void CasImpl::CallBackExt(void* appData, int32_t event, int32_t arg, uint8_t* data, size_t size, + const CasSessionId* sessionId) { + if (appData == NULL) { + ALOGE("Invalid appData!"); + return; + } + CasImpl* casImpl = static_cast(appData); + casImpl->onEvent(sessionId, event, arg, data, size); +} + +void CasImpl::init(const sp& library, CasPlugin* plugin) { + mLibrary = library; + std::shared_ptr holder(plugin); + std::atomic_store(&mPluginHolder, holder); +} + +void CasImpl::onEvent(int32_t event, int32_t arg, uint8_t* data, size_t size) { + if (mListener == NULL) { + return; + } + + HidlCasData eventData; + if (data != NULL) { + eventData.setToExternal(data, size); + } + + mListener->onEvent(event, arg, eventData); +} + +void CasImpl::onEvent(const CasSessionId* sessionId, int32_t event, int32_t arg, uint8_t* data, + size_t size) { + if (mListener == NULL) { + return; + } + + HidlCasData eventData; + if (data != NULL) { + eventData.setToExternal(data, size); + } + + if (sessionId != NULL) { + mListener->onSessionEvent(*sessionId, event, arg, eventData); + } else { + mListener->onEvent(event, arg, eventData); + } +} + +Return CasImpl::setPrivateData(const HidlCasData& pvtData) { + ALOGV("%s", __FUNCTION__); + std::shared_ptr holder = std::atomic_load(&mPluginHolder); + if (holder.get() == nullptr) { + return toStatus(INVALID_OPERATION); + } + return toStatus(holder->setPrivateData(pvtData)); +} + +Return CasImpl::openSession(openSession_cb _hidl_cb) { + ALOGV("%s", __FUNCTION__); + CasSessionId sessionId; + + std::shared_ptr holder = std::atomic_load(&mPluginHolder); + status_t err = INVALID_OPERATION; + if (holder.get() != nullptr) { + err = holder->openSession(&sessionId); + holder.reset(); + } + + _hidl_cb(toStatus(err), sessionId); + + return Void(); +} + +Return CasImpl::setSessionPrivateData(const HidlCasSessionId& sessionId, + const HidlCasData& pvtData) { + ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).string()); + std::shared_ptr holder = std::atomic_load(&mPluginHolder); + if (holder.get() == nullptr) { + return toStatus(INVALID_OPERATION); + } + return toStatus(holder->setSessionPrivateData(sessionId, pvtData)); +} + +Return CasImpl::closeSession(const HidlCasSessionId& sessionId) { + ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).string()); + std::shared_ptr holder = std::atomic_load(&mPluginHolder); + if (holder.get() == nullptr) { + return toStatus(INVALID_OPERATION); + } + return toStatus(holder->closeSession(sessionId)); +} + +Return CasImpl::processEcm(const HidlCasSessionId& sessionId, const HidlCasData& ecm) { + ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).string()); + std::shared_ptr holder = std::atomic_load(&mPluginHolder); + if (holder.get() == nullptr) { + return toStatus(INVALID_OPERATION); + } + + return toStatus(holder->processEcm(sessionId, ecm)); +} + +Return CasImpl::processEmm(const HidlCasData& emm) { + ALOGV("%s", __FUNCTION__); + std::shared_ptr holder = std::atomic_load(&mPluginHolder); + if (holder.get() == nullptr) { + return toStatus(INVALID_OPERATION); + } + + return toStatus(holder->processEmm(emm)); +} + +Return CasImpl::sendEvent(int32_t event, int32_t arg, const HidlCasData& eventData) { + ALOGV("%s", __FUNCTION__); + std::shared_ptr holder = std::atomic_load(&mPluginHolder); + if (holder.get() == nullptr) { + return toStatus(INVALID_OPERATION); + } + + status_t err = holder->sendEvent(event, arg, eventData); + return toStatus(err); +} + +Return CasImpl::sendSessionEvent(const HidlCasSessionId& sessionId, int32_t event, + int32_t arg, const HidlCasData& eventData) { + ALOGV("%s", __FUNCTION__); + std::shared_ptr holder = std::atomic_load(&mPluginHolder); + if (holder.get() == nullptr) { + return toStatus(INVALID_OPERATION); + } + + status_t err = holder->sendSessionEvent(sessionId, event, arg, eventData); + return toStatus(err); +} + +Return CasImpl::provision(const hidl_string& provisionString) { + ALOGV("%s: provisionString=%s", __FUNCTION__, provisionString.c_str()); + std::shared_ptr holder = std::atomic_load(&mPluginHolder); + if (holder.get() == nullptr) { + return toStatus(INVALID_OPERATION); + } + + return toStatus(holder->provision(String8(provisionString.c_str()))); +} + +Return CasImpl::refreshEntitlements(int32_t refreshType, const HidlCasData& refreshData) { + ALOGV("%s", __FUNCTION__); + std::shared_ptr holder = std::atomic_load(&mPluginHolder); + if (holder.get() == nullptr) { + return toStatus(INVALID_OPERATION); + } + + status_t err = holder->refreshEntitlements(refreshType, refreshData); + return toStatus(err); +} + +Return CasImpl::release() { + ALOGV("%s: plugin=%p", __FUNCTION__, mPluginHolder.get()); + + std::shared_ptr holder(nullptr); + std::atomic_store(&mPluginHolder, holder); + + return Status::OK; +} + +} // namespace implementation +} // namespace V1_1 +} // namespace cas +} // namespace hardware +} // namespace android diff --git a/cas/1.1/default/CasImpl.h b/cas/1.1/default/CasImpl.h new file mode 100644 index 0000000000..18aee9e457 --- /dev/null +++ b/cas/1.1/default/CasImpl.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2019 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_CAS_V1_1_CAS_IMPL_H_ +#define ANDROID_HARDWARE_CAS_V1_1_CAS_IMPL_H_ + +#include +#include + +namespace android { +struct CasPlugin; + +namespace hardware { +namespace cas { +namespace V1_1 { +struct ICasListener; +namespace implementation { + +using ::android::hardware::cas::V1_0::HidlCasData; +using ::android::hardware::cas::V1_0::HidlCasSessionId; +using ::android::hardware::cas::V1_0::Status; + +class SharedLibrary; + +class CasImpl : public ICas { + public: + CasImpl(const sp& listener); + virtual ~CasImpl(); + + static void OnEvent(void* appData, int32_t event, int32_t arg, uint8_t* data, size_t size); + + static void CallBackExt(void* appData, int32_t event, int32_t arg, uint8_t* data, size_t size, + const CasSessionId* sessionId); + + void init(const sp& library, CasPlugin* plugin); + void onEvent(int32_t event, int32_t arg, uint8_t* data, size_t size); + + void onEvent(const CasSessionId* sessionId, int32_t event, int32_t arg, uint8_t* data, + size_t size); + + // ICas inherits + + virtual Return setPrivateData(const HidlCasData& pvtData) override; + + virtual Return openSession(openSession_cb _hidl_cb) override; + + virtual Return closeSession(const HidlCasSessionId& sessionId) override; + + virtual Return setSessionPrivateData(const HidlCasSessionId& sessionId, + const HidlCasData& pvtData) override; + + virtual Return processEcm(const HidlCasSessionId& sessionId, + const HidlCasData& ecm) override; + + virtual Return processEmm(const HidlCasData& emm) override; + + virtual Return sendEvent(int32_t event, int32_t arg, + const HidlCasData& eventData) override; + + virtual Return sendSessionEvent(const HidlCasSessionId& sessionId, int32_t event, + int32_t arg, const HidlCasData& eventData) override; + + virtual Return provision(const hidl_string& provisionString) override; + + virtual Return refreshEntitlements(int32_t refreshType, + const HidlCasData& refreshData) override; + + virtual Return release() override; + + private: + struct PluginHolder; + sp mLibrary; + std::shared_ptr mPluginHolder; + sp mListener; + + DISALLOW_EVIL_CONSTRUCTORS(CasImpl); +}; + +} // namespace implementation +} // namespace V1_1 +} // namespace cas +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_CAS_V1_1_CAS_IMPL_H_ diff --git a/cas/1.1/default/DescramblerImpl.cpp b/cas/1.1/default/DescramblerImpl.cpp new file mode 100644 index 0000000000..36dc1a51d0 --- /dev/null +++ b/cas/1.1/default/DescramblerImpl.cpp @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "android.hardware.cas@1.1-DescramblerImpl" + +#include +#include +#include +#include +#include + +#include "DescramblerImpl.h" +#include "SharedLibrary.h" +#include "TypeConvert.h" + +namespace android { +using hidl::memory::V1_0::IMemory; + +namespace hardware { +namespace cas { +namespace V1_1 { +namespace implementation { + +#define CHECK_SUBSAMPLE_DEF(type) \ + static_assert(sizeof(SubSample) == sizeof(type::SubSample), "SubSample: size doesn't match"); \ + static_assert(offsetof(SubSample, numBytesOfClearData) == \ + offsetof(type::SubSample, mNumBytesOfClearData), \ + "SubSample: numBytesOfClearData offset doesn't match"); \ + static_assert(offsetof(SubSample, numBytesOfEncryptedData) == \ + offsetof(type::SubSample, mNumBytesOfEncryptedData), \ + "SubSample: numBytesOfEncryptedData offset doesn't match") + +CHECK_SUBSAMPLE_DEF(DescramblerPlugin); +CHECK_SUBSAMPLE_DEF(CryptoPlugin); + +DescramblerImpl::DescramblerImpl(const sp& library, DescramblerPlugin* plugin) + : mLibrary(library), mPluginHolder(plugin) { + ALOGV("CTOR: plugin=%p", mPluginHolder.get()); +} + +DescramblerImpl::~DescramblerImpl() { + ALOGV("DTOR: plugin=%p", mPluginHolder.get()); + release(); +} + +Return DescramblerImpl::setMediaCasSession(const HidlCasSessionId& sessionId) { + ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).string()); + + std::shared_ptr holder = std::atomic_load(&mPluginHolder); + if (holder.get() == nullptr) { + return toStatus(INVALID_OPERATION); + } + + return toStatus(holder->setMediaCasSession(sessionId)); +} + +Return DescramblerImpl::requiresSecureDecoderComponent(const hidl_string& mime) { + std::shared_ptr holder = std::atomic_load(&mPluginHolder); + if (holder.get() == nullptr) { + return false; + } + + return holder->requiresSecureDecoderComponent(String8(mime.c_str())); +} + +static inline bool validateRangeForSize(uint64_t offset, uint64_t length, uint64_t size) { + return isInRange(0, size, offset, length); +} + +Return DescramblerImpl::descramble(ScramblingControl scramblingControl, + const hidl_vec& subSamples, + const SharedBuffer& srcBuffer, uint64_t srcOffset, + const DestinationBuffer& dstBuffer, uint64_t dstOffset, + descramble_cb _hidl_cb) { + ALOGV("%s", __FUNCTION__); + + // hidl_memory's size is stored in uint64_t, but mapMemory's mmap will map + // size in size_t. If size is over SIZE_MAX, mapMemory mapMemory could succeed + // but the mapped memory's actual size will be smaller than the reported size. + if (srcBuffer.heapBase.size() > SIZE_MAX) { + ALOGE("Invalid hidl_memory size: %llu", srcBuffer.heapBase.size()); + android_errorWriteLog(0x534e4554, "79376389"); + _hidl_cb(toStatus(BAD_VALUE), 0, NULL); + return Void(); + } + + sp srcMem = mapMemory(srcBuffer.heapBase); + + // Validate if the offset and size in the SharedBuffer is consistent with the + // mapped ashmem, since the offset and size is controlled by client. + if (srcMem == NULL) { + ALOGE("Failed to map src buffer."); + _hidl_cb(toStatus(BAD_VALUE), 0, NULL); + return Void(); + } + if (!validateRangeForSize(srcBuffer.offset, srcBuffer.size, (uint64_t)srcMem->getSize())) { + ALOGE("Invalid src buffer range: offset %llu, size %llu, srcMem size %llu", + srcBuffer.offset, srcBuffer.size, (uint64_t)srcMem->getSize()); + android_errorWriteLog(0x534e4554, "67962232"); + _hidl_cb(toStatus(BAD_VALUE), 0, NULL); + return Void(); + } + + // use 64-bit here to catch bad subsample size that might be overflowing. + uint64_t totalBytesInSubSamples = 0; + for (size_t i = 0; i < subSamples.size(); i++) { + totalBytesInSubSamples += + (uint64_t)subSamples[i].numBytesOfClearData + subSamples[i].numBytesOfEncryptedData; + } + // Further validate if the specified srcOffset and requested total subsample size + // is consistent with the source shared buffer size. + if (!validateRangeForSize(srcOffset, totalBytesInSubSamples, srcBuffer.size)) { + ALOGE("Invalid srcOffset and subsample size: " + "srcOffset %llu, totalBytesInSubSamples %llu, srcBuffer size %llu", + srcOffset, totalBytesInSubSamples, srcBuffer.size); + android_errorWriteLog(0x534e4554, "67962232"); + _hidl_cb(toStatus(BAD_VALUE), 0, NULL); + return Void(); + } + + void* srcPtr = (uint8_t*)(void*)srcMem->getPointer() + srcBuffer.offset; + void* dstPtr = NULL; + if (dstBuffer.type == BufferType::SHARED_MEMORY) { + // When using shared memory, src buffer is also used as dst, + // we don't map it again here. + dstPtr = srcPtr; + + // In this case the dst and src would be the same buffer, need to validate + // dstOffset against the buffer size too. + if (!validateRangeForSize(dstOffset, totalBytesInSubSamples, srcBuffer.size)) { + ALOGE("Invalid dstOffset and subsample size: " + "dstOffset %llu, totalBytesInSubSamples %llu, srcBuffer size %llu", + dstOffset, totalBytesInSubSamples, srcBuffer.size); + android_errorWriteLog(0x534e4554, "67962232"); + _hidl_cb(toStatus(BAD_VALUE), 0, NULL); + return Void(); + } + } else { + native_handle_t* handle = + const_cast(dstBuffer.secureMemory.getNativeHandle()); + dstPtr = static_cast(handle); + } + + // Get a local copy of the shared_ptr for the plugin. Note that before + // calling the HIDL callback, this shared_ptr must be manually reset, + // since the client side could proceed as soon as the callback is called + // without waiting for this method to go out of scope. + std::shared_ptr holder = std::atomic_load(&mPluginHolder); + if (holder.get() == nullptr) { + _hidl_cb(toStatus(INVALID_OPERATION), 0, NULL); + return Void(); + } + + // Casting hidl SubSample to DescramblerPlugin::SubSample, but need + // to ensure structs are actually idential + + int32_t result = + holder->descramble(dstBuffer.type != BufferType::SHARED_MEMORY, + (DescramblerPlugin::ScramblingControl)scramblingControl, + subSamples.size(), (DescramblerPlugin::SubSample*)subSamples.data(), + srcPtr, srcOffset, dstPtr, dstOffset, NULL); + + holder.reset(); + _hidl_cb(toStatus(result >= 0 ? OK : result), result, NULL); + return Void(); +} + +Return DescramblerImpl::release() { + ALOGV("%s: plugin=%p", __FUNCTION__, mPluginHolder.get()); + + std::shared_ptr holder(nullptr); + std::atomic_store(&mPluginHolder, holder); + + return Status::OK; +} + +} // namespace implementation +} // namespace V1_1 +} // namespace cas +} // namespace hardware +} // namespace android diff --git a/cas/1.1/default/DescramblerImpl.h b/cas/1.1/default/DescramblerImpl.h new file mode 100644 index 0000000000..a1f66ae464 --- /dev/null +++ b/cas/1.1/default/DescramblerImpl.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2019 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_CAS_V1_1_DESCRAMBLER_IMPL_H_ +#define ANDROID_HARDWARE_CAS_V1_1_DESCRAMBLER_IMPL_H_ + +#include +#include + +namespace android { +struct DescramblerPlugin; +using namespace hardware::cas::native::V1_0; + +namespace hardware { +namespace cas { +namespace V1_1 { +namespace implementation { + +using ::android::hardware::cas::V1_0::HidlCasSessionId; +using ::android::hardware::cas::V1_0::Status; + +class SharedLibrary; + +class DescramblerImpl : public IDescrambler { + public: + DescramblerImpl(const sp& library, DescramblerPlugin* plugin); + virtual ~DescramblerImpl(); + + virtual Return setMediaCasSession(const HidlCasSessionId& sessionId) override; + + virtual Return requiresSecureDecoderComponent(const hidl_string& mime) override; + + virtual Return descramble(ScramblingControl scramblingControl, + const hidl_vec& subSamples, + const SharedBuffer& srcBuffer, uint64_t srcOffset, + const DestinationBuffer& dstBuffer, uint64_t dstOffset, + descramble_cb _hidl_cb) override; + + virtual Return release() override; + + private: + sp mLibrary; + std::shared_ptr mPluginHolder; + + DISALLOW_EVIL_CONSTRUCTORS(DescramblerImpl); +}; + +} // namespace implementation +} // namespace V1_1 +} // namespace cas +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_CAS_V1_1_DESCRAMBLER_IMPL_H_ diff --git a/cas/1.1/default/FactoryLoader.h b/cas/1.1/default/FactoryLoader.h new file mode 100644 index 0000000000..c4a48e2852 --- /dev/null +++ b/cas/1.1/default/FactoryLoader.h @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2019 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_CAS_V1_1_FACTORY_LOADER_H_ +#define ANDROID_HARDWARE_CAS_V1_1_FACTORY_LOADER_H_ + +#include +#include +#include +#include +#include +#include "SharedLibrary.h" + +using namespace std; + +namespace android { +namespace hardware { +namespace cas { +namespace V1_1 { +namespace implementation { + +using ::android::hardware::cas::V1_0::HidlCasPluginDescriptor; + +template +class FactoryLoader { + public: + FactoryLoader(const char* name) : mFactory(NULL), mCreateFactoryFuncName(name) {} + + virtual ~FactoryLoader() { closeFactory(); } + + bool findFactoryForScheme(int32_t CA_system_id, sp* library = NULL, + T** factory = NULL); + + bool enumeratePlugins(vector* results); + + private: + typedef T* (*CreateFactoryFunc)(); + + Mutex mMapLock; + T* mFactory; + const char* mCreateFactoryFuncName; + sp mLibrary; + KeyedVector mCASystemIdToLibraryPathMap; + KeyedVector > mLibraryPathToOpenLibraryMap; + + bool loadFactoryForSchemeFromPath(const String8& path, int32_t CA_system_id, + sp* library, T** factory); + + bool queryPluginsFromPath(const String8& path, vector* results); + + bool openFactory(const String8& path); + void closeFactory(); +}; + +template +bool FactoryLoader::findFactoryForScheme(int32_t CA_system_id, sp* library, + T** factory) { + if (library != NULL) { + library->clear(); + } + if (factory != NULL) { + *factory = NULL; + } + + Mutex::Autolock autoLock(mMapLock); + + // first check cache + ssize_t index = mCASystemIdToLibraryPathMap.indexOfKey(CA_system_id); + if (index >= 0) { + return loadFactoryForSchemeFromPath(mCASystemIdToLibraryPathMap[index], CA_system_id, + library, factory); + } + + // no luck, have to search + String8 dirPath("/vendor/lib/mediacas"); + DIR* pDir = opendir(dirPath.string()); + + if (pDir == NULL) { + ALOGE("Failed to open plugin directory %s", dirPath.string()); + return false; + } + + struct dirent* pEntry; + while ((pEntry = readdir(pDir))) { + String8 pluginPath = dirPath + "/" + pEntry->d_name; + if (pluginPath.getPathExtension() == ".so") { + if (loadFactoryForSchemeFromPath(pluginPath, CA_system_id, library, factory)) { + mCASystemIdToLibraryPathMap.add(CA_system_id, pluginPath); + closedir(pDir); + + return true; + } + } + } + + closedir(pDir); + + ALOGE("Failed to find plugin"); + return false; +} + +template +bool FactoryLoader::enumeratePlugins(vector* results) { + ALOGI("enumeratePlugins"); + + results->clear(); + + String8 dirPath("/vendor/lib/mediacas"); + DIR* pDir = opendir(dirPath.string()); + + if (pDir == NULL) { + ALOGE("Failed to open plugin directory %s", dirPath.string()); + return false; + } + + Mutex::Autolock autoLock(mMapLock); + + struct dirent* pEntry; + while ((pEntry = readdir(pDir))) { + String8 pluginPath = dirPath + "/" + pEntry->d_name; + if (pluginPath.getPathExtension() == ".so") { + queryPluginsFromPath(pluginPath, results); + } + } + return true; +} + +template +bool FactoryLoader::loadFactoryForSchemeFromPath(const String8& path, int32_t CA_system_id, + sp* library, T** factory) { + closeFactory(); + + if (!openFactory(path) || !mFactory->isSystemIdSupported(CA_system_id)) { + closeFactory(); + return false; + } + + if (library != NULL) { + *library = mLibrary; + } + if (factory != NULL) { + *factory = mFactory; + } + return true; +} + +template +bool FactoryLoader::queryPluginsFromPath(const String8& path, + vector* results) { + closeFactory(); + + vector descriptors; + if (!openFactory(path) || mFactory->queryPlugins(&descriptors) != OK) { + closeFactory(); + return false; + } + + for (auto it = descriptors.begin(); it != descriptors.end(); it++) { + results->push_back( + HidlCasPluginDescriptor{.caSystemId = it->CA_system_id, .name = it->name.c_str()}); + } + return true; +} + +template +bool FactoryLoader::openFactory(const String8& path) { + // get strong pointer to open shared library + ssize_t index = mLibraryPathToOpenLibraryMap.indexOfKey(path); + if (index >= 0) { + mLibrary = mLibraryPathToOpenLibraryMap[index].promote(); + } else { + index = mLibraryPathToOpenLibraryMap.add(path, NULL); + } + + if (!mLibrary.get()) { + mLibrary = new SharedLibrary(path); + if (!*mLibrary) { + return false; + } + + mLibraryPathToOpenLibraryMap.replaceValueAt(index, mLibrary); + } + + CreateFactoryFunc createFactory = (CreateFactoryFunc)mLibrary->lookup(mCreateFactoryFuncName); + if (createFactory == NULL || (mFactory = createFactory()) == NULL) { + return false; + } + return true; +} + +template +void FactoryLoader::closeFactory() { + delete mFactory; + mFactory = NULL; + mLibrary.clear(); +} + +} // namespace implementation +} // namespace V1_1 +} // namespace cas +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_CAS_V1_1_FACTORY_LOADER_H_ diff --git a/cas/1.1/default/MediaCasService.cpp b/cas/1.1/default/MediaCasService.cpp new file mode 100644 index 0000000000..e2d3357023 --- /dev/null +++ b/cas/1.1/default/MediaCasService.cpp @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "android.hardware.cas@1.1-MediaCasService" + +#include +#include +#include +#include + +#include "CasImpl.h" +#include "DescramblerImpl.h" +#include "MediaCasService.h" + +namespace android { +namespace hardware { +namespace cas { +namespace V1_1 { +namespace implementation { + +MediaCasService::MediaCasService() + : mCasLoader("createCasFactory"), mDescramblerLoader("createDescramblerFactory") {} + +MediaCasService::~MediaCasService() {} + +Return MediaCasService::enumeratePlugins(enumeratePlugins_cb _hidl_cb) { + ALOGV("%s", __FUNCTION__); + + vector results; + mCasLoader.enumeratePlugins(&results); + + _hidl_cb(results); + return Void(); +} + +Return MediaCasService::isSystemIdSupported(int32_t CA_system_id) { + ALOGV("isSystemIdSupported: CA_system_id=%d", CA_system_id); + + return mCasLoader.findFactoryForScheme(CA_system_id); +} + +Return> MediaCasService::createPlugin(int32_t /* CA_system_id */, + const sp& /* listener */) { + ALOGE("%s:Use createPluginExt to create plugin with cas@1.1", __FUNCTION__); + + sp result; + /* + CasFactory *factory; + sp library; + if (mCasLoader.findFactoryForScheme(CA_system_id, &library, &factory)) { + CasPlugin *plugin = NULL; + sp casImpl = new CasImpl(listener); + if (factory->createPlugin(CA_system_id, casImpl.get(), + CasImpl::OnEvent, &plugin) == OK && plugin != NULL) { + casImpl->init(library, plugin); + result = casImpl; + } + } + */ + return result; +} + +Return> MediaCasService::createPluginExt(int32_t CA_system_id, + const sp& listener) { + ALOGV("%s: CA_system_id=%d", __FUNCTION__, CA_system_id); + + sp result; + + CasFactory* factory; + sp library; + if (mCasLoader.findFactoryForScheme(CA_system_id, &library, &factory)) { + CasPlugin* plugin = NULL; + sp casImpl = new CasImpl(listener); + if (factory->createPlugin(CA_system_id, casImpl.get(), &CasImpl::CallBackExt, &plugin) == + OK && + plugin != NULL) { + casImpl->init(library, plugin); + result = casImpl; + } + } + + return result; +} + +Return MediaCasService::isDescramblerSupported(int32_t CA_system_id) { + ALOGV("%s: CA_system_id=%d", __FUNCTION__, CA_system_id); + + return mDescramblerLoader.findFactoryForScheme(CA_system_id); +} + +Return> MediaCasService::createDescrambler(int32_t CA_system_id) { + ALOGV("%s: CA_system_id=%d", __FUNCTION__, CA_system_id); + + sp result; + + DescramblerFactory* factory; + sp library; + if (mDescramblerLoader.findFactoryForScheme(CA_system_id, &library, &factory)) { + DescramblerPlugin* plugin = NULL; + if (factory->createPlugin(CA_system_id, &plugin) == OK && plugin != NULL) { + result = new DescramblerImpl(library, plugin); + } + } + + return result; +} + +} // namespace implementation +} // namespace V1_1 +} // namespace cas +} // namespace hardware +} // namespace android diff --git a/cas/1.1/default/MediaCasService.h b/cas/1.1/default/MediaCasService.h new file mode 100644 index 0000000000..ec5a86d9b3 --- /dev/null +++ b/cas/1.1/default/MediaCasService.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2019 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_CAS_V1_1_MEDIA_CAS_SERVICE_H_ +#define ANDROID_HARDWARE_CAS_V1_1_MEDIA_CAS_SERVICE_H_ + +#include + +#include "FactoryLoader.h" + +namespace android { +struct CasFactory; +struct DescramblerFactory; +namespace hardware { +namespace cas { +namespace V1_1 { +namespace implementation { + +using ::android::hardware::cas::V1_0::HidlCasPluginDescriptor; +using ::android::hardware::cas::V1_0::IDescramblerBase; + +class MediaCasService : public IMediaCasService { + public: + MediaCasService(); + + virtual Return enumeratePlugins(enumeratePlugins_cb _hidl_cb) override; + + virtual Return isSystemIdSupported(int32_t CA_system_id) override; + + virtual Return> createPlugin(int32_t CA_system_id, + const sp& listener) override; + + virtual Return> createPluginExt(int32_t CA_system_id, + const sp& listener) override; + + virtual Return isDescramblerSupported(int32_t CA_system_id) override; + + virtual Return> createDescrambler(int32_t CA_system_id) override; + + private: + FactoryLoader mCasLoader; + FactoryLoader mDescramblerLoader; + + virtual ~MediaCasService(); +}; + +} // namespace implementation +} // namespace V1_1 +} // namespace cas +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_CAS_V1_1_MEDIA_CAS_SERVICE_H_ diff --git a/cas/1.1/default/SharedLibrary.cpp b/cas/1.1/default/SharedLibrary.cpp new file mode 100644 index 0000000000..ffe4bb977a --- /dev/null +++ b/cas/1.1/default/SharedLibrary.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "android.hardware.cas@1.1-SharedLibrary" + +#include "SharedLibrary.h" +#include +#include +#include + +namespace android { +namespace hardware { +namespace cas { +namespace V1_1 { +namespace implementation { + +SharedLibrary::SharedLibrary(const String8& path) { + mLibHandle = dlopen(path.string(), RTLD_NOW); +} + +SharedLibrary::~SharedLibrary() { + if (mLibHandle != NULL) { + dlclose(mLibHandle); + mLibHandle = NULL; + } +} + +bool SharedLibrary::operator!() const { + return mLibHandle == NULL; +} + +void* SharedLibrary::lookup(const char* symbol) const { + if (!mLibHandle) { + return NULL; + } + // Clear last error before we load the symbol again, + // in case the caller didn't retrieve it. + (void)dlerror(); + return dlsym(mLibHandle, symbol); +} + +const char* SharedLibrary::lastError() const { + const char* error = dlerror(); + return error ? error : "No errors or unknown error"; +} + +} // namespace implementation +} // namespace V1_1 +} // namespace cas +} // namespace hardware +} // namespace android diff --git a/cas/1.1/default/SharedLibrary.h b/cas/1.1/default/SharedLibrary.h new file mode 100644 index 0000000000..f4d2ff6b9d --- /dev/null +++ b/cas/1.1/default/SharedLibrary.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2019 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_CAS_V1_1_SHARED_LIBRARY_H_ +#define ANDROID_HARDWARE_CAS_V1_1_SHARED_LIBRARY_H_ + +#include +#include +#include + +namespace android { +namespace hardware { +namespace cas { +namespace V1_1 { +namespace implementation { + +class SharedLibrary : public RefBase { + public: + explicit SharedLibrary(const String8& path); + ~SharedLibrary(); + + bool operator!() const; + void* lookup(const char* symbol) const; + const char* lastError() const; + + private: + void* mLibHandle; + DISALLOW_EVIL_CONSTRUCTORS(SharedLibrary); +}; + +} // namespace implementation +} // namespace V1_1 +} // namespace cas +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_CAS_V1_1_SHARED_LIBRARY_H_ diff --git a/cas/1.1/default/TypeConvert.cpp b/cas/1.1/default/TypeConvert.cpp new file mode 100644 index 0000000000..09ef41ae8f --- /dev/null +++ b/cas/1.1/default/TypeConvert.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "android.hardware.cas@1.1-TypeConvert" + +#include "TypeConvert.h" +#include + +namespace android { +namespace hardware { +namespace cas { +namespace V1_1 { +namespace implementation { + +Status toStatus(status_t legacyStatus) { + Status status; + switch (legacyStatus) { + case android::OK: + status = Status::OK; + break; + case android::ERROR_CAS_NO_LICENSE: + status = Status::ERROR_CAS_NO_LICENSE; + break; + case android::ERROR_CAS_LICENSE_EXPIRED: + status = Status::ERROR_CAS_LICENSE_EXPIRED; + break; + case android::ERROR_CAS_SESSION_NOT_OPENED: + status = Status::ERROR_CAS_SESSION_NOT_OPENED; + break; + case android::ERROR_CAS_CANNOT_HANDLE: + status = Status::ERROR_CAS_CANNOT_HANDLE; + break; + case android::ERROR_CAS_TAMPER_DETECTED: + status = Status::ERROR_CAS_INVALID_STATE; + break; + case android::BAD_VALUE: + status = Status::BAD_VALUE; + break; + case android::ERROR_CAS_NOT_PROVISIONED: + status = Status::ERROR_CAS_NOT_PROVISIONED; + break; + case android::ERROR_CAS_RESOURCE_BUSY: + status = Status::ERROR_CAS_RESOURCE_BUSY; + break; + case android::ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION: + status = Status::ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION; + break; + case android::ERROR_CAS_DEVICE_REVOKED: + status = Status::ERROR_CAS_DEVICE_REVOKED; + break; + case android::ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED: + status = Status::ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED; + break; + case android::ERROR_CAS_DECRYPT: + status = Status::ERROR_CAS_DECRYPT; + break; + default: + ALOGW("Unable to convert legacy status: %d, defaulting to UNKNOWN", legacyStatus); + status = Status::ERROR_CAS_UNKNOWN; + break; + } + return status; +} + +String8 sessionIdToString(const CasSessionId& sessionId) { + String8 result; + for (size_t i = 0; i < sessionId.size(); i++) { + result.appendFormat("%02x ", sessionId[i]); + } + if (result.isEmpty()) { + result.append("(null)"); + } + return result; +} + +} // namespace implementation +} // namespace V1_1 +} // namespace cas +} // namespace hardware +} // namespace android diff --git a/cas/1.1/default/TypeConvert.h b/cas/1.1/default/TypeConvert.h new file mode 100644 index 0000000000..c4a0119926 --- /dev/null +++ b/cas/1.1/default/TypeConvert.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2019 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_CAS_V1_1_TYPE_CONVERT_H +#define ANDROID_HARDWARE_CAS_V1_1_TYPE_CONVERT_H + +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace cas { +namespace V1_1 { +namespace implementation { + +using ::android::hardware::cas::V1_0::Status; + +Status toStatus(status_t legacyStatus); + +String8 sessionIdToString(const CasSessionId& sessionId); + +} // namespace implementation +} // namespace V1_1 +} // namespace cas +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_CAS_V1_1_TYPE_CONVERT_H diff --git a/cas/1.1/default/android.hardware.cas@1.1-service-lazy.rc b/cas/1.1/default/android.hardware.cas@1.1-service-lazy.rc new file mode 100644 index 0000000000..9227b6f7e4 --- /dev/null +++ b/cas/1.1/default/android.hardware.cas@1.1-service-lazy.rc @@ -0,0 +1,9 @@ +service vendor.cas-hal-1-1 /vendor/bin/hw/android.hardware.cas@1.1-service-lazy + interface android.hardware.cas@1.1::IMediaCasService default + oneshot + disabled + class hal + user media + group mediadrm drmrpc + ioprio rt 4 + writepid /dev/cpuset/foreground/tasks diff --git a/cas/1.1/default/android.hardware.cas@1.1-service-lazy.xml b/cas/1.1/default/android.hardware.cas@1.1-service-lazy.xml new file mode 100644 index 0000000000..c9f13ba34a --- /dev/null +++ b/cas/1.1/default/android.hardware.cas@1.1-service-lazy.xml @@ -0,0 +1,11 @@ + + + android.hardware.cas + hwbinder + 1.1 + + IMediaCasService + default + + + diff --git a/cas/1.1/default/android.hardware.cas@1.1-service.rc b/cas/1.1/default/android.hardware.cas@1.1-service.rc new file mode 100644 index 0000000000..4081fe1e64 --- /dev/null +++ b/cas/1.1/default/android.hardware.cas@1.1-service.rc @@ -0,0 +1,6 @@ +service vendor.cas-hal-1-1 /vendor/bin/hw/android.hardware.cas@1.1-service + class hal + user media + group mediadrm drmrpc + ioprio rt 4 + writepid /dev/cpuset/foreground/tasks diff --git a/cas/1.1/default/android.hardware.cas@1.1-service.xml b/cas/1.1/default/android.hardware.cas@1.1-service.xml new file mode 100644 index 0000000000..c9f13ba34a --- /dev/null +++ b/cas/1.1/default/android.hardware.cas@1.1-service.xml @@ -0,0 +1,11 @@ + + + android.hardware.cas + hwbinder + 1.1 + + IMediaCasService + default + + + diff --git a/cas/1.1/default/service.cpp b/cas/1.1/default/service.cpp new file mode 100644 index 0000000000..962530370c --- /dev/null +++ b/cas/1.1/default/service.cpp @@ -0,0 +1,58 @@ +/* + * Copyright 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#ifdef LAZY_SERVICE +#define LOG_TAG "android.hardware.cas@1.1-service-lazy" +#else +#define LOG_TAG "android.hardware.cas@1.1-service" +#endif + +#include +#include +#include + +#include "MediaCasService.h" + +using android::hardware::configureRpcThreadpool; +using android::hardware::joinRpcThreadpool; +using android::hardware::LazyServiceRegistrar; +using android::hardware::cas::V1_1::IMediaCasService; +using android::hardware::cas::V1_1::implementation::MediaCasService; + +#ifdef LAZY_SERVICE +const bool kLazyService = true; +#else +const bool kLazyService = false; +#endif + +int main() { + configureRpcThreadpool(8, true /* callerWillJoin */); + + // Setup hwbinder service + android::sp service = new MediaCasService(); + android::status_t status; + if (kLazyService) { + auto serviceRegistrar = std::make_shared(); + status = serviceRegistrar->registerService(service); + } else { + status = service->registerAsService(); + } + LOG_ALWAYS_FATAL_IF(status != android::OK, "Error while registering cas service: %d", status); + + joinRpcThreadpool(); + return 0; +} diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml index 94ffe80aab..89855a0e65 100644 --- a/compatibility_matrices/compatibility_matrix.current.xml +++ b/compatibility_matrices/compatibility_matrix.current.xml @@ -121,7 +121,7 @@
android.hardware.cas - 1.0 + 1.0-1 IMediaCasService default From 1f6e6e3a65bec008c41cf6d646ba09e5b1974e06 Mon Sep 17 00:00:00 2001 From: Peter Kalauskas Date: Mon, 14 Jan 2019 17:11:31 -0800 Subject: [PATCH 449/718] Add new lazy wifi HAL target Devices can use the lazy wifi HAL to allow it to exit when wifi is not in use. Test: Flash walleye_svelte-userdebug and check that HAL only runs when wifi is on. Bug: 123307146 Change-Id: If20120f902a7e102372666447b39cf9fdad7d352 --- wifi/1.3/default/Android.mk | 31 +++++++++++++++++++ .../android.hardware.wifi@1.0-service-lazy.rc | 8 +++++ wifi/1.3/default/service.cpp | 18 +++++++++-- 3 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 wifi/1.3/default/android.hardware.wifi@1.0-service-lazy.rc diff --git a/wifi/1.3/default/Android.mk b/wifi/1.3/default/Android.mk index 8312c314ad..01fa934a00 100644 --- a/wifi/1.3/default/Android.mk +++ b/wifi/1.3/default/Android.mk @@ -97,6 +97,37 @@ LOCAL_STATIC_LIBRARIES := \ LOCAL_INIT_RC := android.hardware.wifi@1.0-service.rc include $(BUILD_EXECUTABLE) +### +### android.hardware.wifi daemon +### +include $(CLEAR_VARS) +LOCAL_MODULE := android.hardware.wifi@1.0-service-lazy +LOCAL_OVERRIDES_MODULES := android.hardware.wifi@1.0-service +LOCAL_CFLAGS := -DLAZY_SERVICE +LOCAL_MODULE_RELATIVE_PATH := hw +LOCAL_PROPRIETARY_MODULE := true +LOCAL_CPPFLAGS := -Wall -Werror -Wextra +LOCAL_SRC_FILES := \ + service.cpp +LOCAL_SHARED_LIBRARIES := \ + libbase \ + libcutils \ + libhidlbase \ + libhidltransport \ + liblog \ + libnl \ + libutils \ + libwifi-hal \ + libwifi-system-iface \ + android.hardware.wifi@1.0 \ + android.hardware.wifi@1.1 \ + android.hardware.wifi@1.2 \ + android.hardware.wifi@1.3 +LOCAL_STATIC_LIBRARIES := \ + android.hardware.wifi@1.0-service-lib +LOCAL_INIT_RC := android.hardware.wifi@1.0-service-lazy.rc +include $(BUILD_EXECUTABLE) + ### ### android.hardware.wifi unit tests. ### diff --git a/wifi/1.3/default/android.hardware.wifi@1.0-service-lazy.rc b/wifi/1.3/default/android.hardware.wifi@1.0-service-lazy.rc new file mode 100644 index 0000000000..cf917b5458 --- /dev/null +++ b/wifi/1.3/default/android.hardware.wifi@1.0-service-lazy.rc @@ -0,0 +1,8 @@ +service vendor.wifi_hal_legacy /vendor/bin/hw/android.hardware.wifi@1.0-service-lazy + interface android.hardware.wifi@1.0::IWifi default + oneshot + disabled + class hal + capabilities NET_ADMIN NET_RAW SYS_MODULE + user wifi + group wifi gps diff --git a/wifi/1.3/default/service.cpp b/wifi/1.3/default/service.cpp index 5fd83c1aa8..5daf659dfd 100644 --- a/wifi/1.3/default/service.cpp +++ b/wifi/1.3/default/service.cpp @@ -15,6 +15,7 @@ */ #include +#include #include #include #include @@ -26,12 +27,19 @@ using android::hardware::configureRpcThreadpool; using android::hardware::joinRpcThreadpool; +using android::hardware::LazyServiceRegistrar; using android::hardware::wifi::V1_3::implementation::feature_flags:: WifiFeatureFlags; using android::hardware::wifi::V1_3::implementation::legacy_hal::WifiLegacyHal; using android::hardware::wifi::V1_3::implementation::mode_controller:: WifiModeController; +#ifdef LAZY_SERVICE +const bool kLazyService = true; +#else +const bool kLazyService = false; +#endif + int main(int /*argc*/, char** argv) { android::base::InitLogging( argv, android::base::LogdLogger(android::base::SYSTEM)); @@ -45,8 +53,14 @@ int main(int /*argc*/, char** argv) { std::make_shared(), std::make_shared(), std::make_shared()); - CHECK_EQ(service->registerAsService(), android::NO_ERROR) - << "Failed to register wifi HAL"; + if (kLazyService) { + LazyServiceRegistrar registrar; + CHECK_EQ(registrar.registerService(service), android::NO_ERROR) + << "Failed to register wifi HAL"; + } else { + CHECK_EQ(service->registerAsService(), android::NO_ERROR) + << "Failed to register wifi HAL"; + } joinRpcThreadpool(); From a4c77b9edd4fffb87eff90e9b51026208e3c9ec5 Mon Sep 17 00:00:00 2001 From: Zachary Iqbal Date: Thu, 31 Jan 2019 15:54:34 -0800 Subject: [PATCH 450/718] Removed completed TODOs from IBiometricsFace HIDL. Change-Id: I6ef9de184acfe3e1b7dd7f3519c64cc74fb6506d Test: Built locally. --- biometrics/face/1.0/IBiometricsFace.hal | 3 --- 1 file changed, 3 deletions(-) diff --git a/biometrics/face/1.0/IBiometricsFace.hal b/biometrics/face/1.0/IBiometricsFace.hal index e3c256a2bf..813f04000b 100644 --- a/biometrics/face/1.0/IBiometricsFace.hal +++ b/biometrics/face/1.0/IBiometricsFace.hal @@ -18,9 +18,6 @@ package android.hardware.biometrics.face@1.0; import IBiometricsFaceClientCallback; -// TODO(b/78538290): Update comments with state machine transitions when ready. -// TODO(b/78537981): Update comments with callback interaction contract. -// TODO(b/79496983): Update comments with status returns fully enumerated. /** * The HAL interface for biometric face authentication. */ From fbdc22e7b8da054040427588469fc6b308aa1b8a Mon Sep 17 00:00:00 2001 From: Kevin Chyn Date: Thu, 31 Jan 2019 16:16:28 -0800 Subject: [PATCH 451/718] Fix incorrect comments in types.hal Bug: 123262389 Test: Builds Change-Id: I56f60c5ac61be6fdd1f1c49f5a7d8ac0e41d2572 --- biometrics/face/1.0/types.hal | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/biometrics/face/1.0/types.hal b/biometrics/face/1.0/types.hal index 89e809b3f7..b5db966b47 100644 --- a/biometrics/face/1.0/types.hal +++ b/biometrics/face/1.0/types.hal @@ -297,7 +297,7 @@ enum FaceAcquiredInfo : int32_t { * capture plane is too high. * * The tilt angle is defined as the angle swept out by the user’s face looking up - * and down. The pan angle would be zero if the user faced the camera directly. + * and down. The tilt angle would be zero if the user faced the camera directly. * * The user should be informed to look more directly at the camera. */ @@ -308,8 +308,8 @@ enum FaceAcquiredInfo : int32_t { * capture plane is too high. * * The roll angle is defined as the angle swept out by the user’s face tilting their head - * towards their shoulders to the left and right. The pan angle would be zero if the user - * faced the camera directly. + * towards their shoulders to the left and right. The roll angle would be zero if the user's + * head is vertically aligned with the camera. * * The user should be informed to look more directly at the camera. */ From 9e2eaf1d2e472573d3761a73079f3a6a9c461c53 Mon Sep 17 00:00:00 2001 From: Yu-Han Yang Date: Wed, 23 Jan 2019 11:58:01 -0800 Subject: [PATCH 452/718] Add STATE_2ND_CODE_LOCK to GnssMeasurementState Bug: 123297074 Test: atest VtsHalGnssV2_0TargetTest Change-Id: I289669de2c88bbab85d510602b042491c09c4315 --- gnss/2.0/IGnssMeasurementCallback.hal | 355 ++++++++++++++++++++++++++ 1 file changed, 355 insertions(+) diff --git a/gnss/2.0/IGnssMeasurementCallback.hal b/gnss/2.0/IGnssMeasurementCallback.hal index a19c6cd715..fc4446571e 100644 --- a/gnss/2.0/IGnssMeasurementCallback.hal +++ b/gnss/2.0/IGnssMeasurementCallback.hal @@ -93,6 +93,347 @@ interface IGnssMeasurementCallback extends @1.1::IGnssMeasurementCallback { OTHER = 255 }; + /** + * Flags indicating the GNSS measurement state. + * + *

The expected behavior here is for GNSS HAL to set all the flags that apply. For example, + * if the state for a satellite is only C/A code locked and bit synchronized, and there is still + * millisecond ambiguity, the state must be set as: + * + * STATE_CODE_LOCK | STATE_BIT_SYNC | STATE_MSEC_AMBIGUOUS + * + *

If GNSS is still searching for a satellite, the corresponding state must be set to + * STATE_UNKNOWN(0). + * + *

In @2.0::IGnssMeasurementCallback.GnssMeasurement, v1_1.v1_0.receivedSvTimeInNs, the + * received satellite time, is relative to the beginning of the system week for all + * constellations except for Glonass where it is relative to the beginning of the Glonass system + * day. + * + *

The table below indicates the valid range of the received GNSS satellite time. These + * ranges depend on the constellation and code being tracked and the state of the tracking + * algorithms given by the getState method. If the state flag is set, then the valid measurement + * range is zero to the value in the table. The state flag with the widest range indicates the + * range of the received GNSS satellite time value. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
+ * GPS/QZSSGLNSBDSGALSBAS
State FlagL1 C/AL5IL5QL1OFB1I (D1)B1I  (D2)E1BE1CE5AQL1 C/A
+ * STATE_UNKNOWN + * 0000000000
+ * STATE_CODE_LOCK + * 1 ms1 ms1 ms1 ms1 ms1 ms--1 ms1 ms
+ * STATE_SYMBOL_SYNC + * 20 ms (optional)10 ms1 ms (optional)10 ms20 ms (optional)2 ms4 ms (optional)4 ms (optional)1 ms (optional)2 ms
+ * STATE_BIT_SYNC + * 20 ms20 ms1 ms (optional)20 ms20 ms-8 ms-1 ms (optional)4 ms
+ * STATE_SUBFRAME_SYNC + * 6s6s-2 s6 s---100 ms-
+ * STATE_TOW_DECODED + * 1 week-1 day1 week1 week-1 week
+ * STATE_TOW_KNOWN + * 1 week1 day1 week1 week1 week
+ * STATE_GLO_STRING_SYNC + * ---2 s------
+ * STATE_GLO_TOD_DECODED + * ---1 day------
+ * STATE_GLO_TOD_KNOWN + * ---1 day------
+ * STATE_BDS_D2_BIT_SYNC + * -----2 ms----
+ * STATE_BDS_D2_SUBFRAME_SYNC + * -----600 ms----
+ * STATE_GAL_E1BC_CODE_LOCK + * ------4 ms4 ms--
+ * STATE_GAL_E1C_2ND_CODE_LOCK + * -------100 ms--
+ * STATE_2ND_CODE_LOCK + * -10 ms (optional)20 ms----100 ms (optional)100 ms-
+ * STATE_GAL_E1B_PAGE_SYNC + * ------2 s---
+ * STATE_SBAS_SYNC + * ---------1 s
+ * + *

Note: TOW Known refers to the case where TOW is possibly not decoded over the air but has + * been determined from other sources. If TOW decoded is set then TOW Known must also be set. + * + *

Note well: if there is any ambiguity in integer millisecond, STATE_MSEC_AMBIGUOUS must be + * set accordingly, in the 'state' field. This value must be populated if 'state' != + * STATE_UNKNOWN. + * + *

Note on optional flags: + *

    + *
  • For L1 C/A and B1I, STATE_SYMBOL_SYNC is optional since the symbol length is the + * same as the bit length. + *
  • For L5Q and E5aQ, STATE_BIT_SYNC and STATE_SYMBOL_SYNC are optional since they are + * implied by STATE_CODE_LOCK. + *
  • STATE_2ND_CODE_LOCK for L5I is optional since it is implied by STATE_SYMBOL_SYNC. + *
  • STATE_2ND_CODE_LOCK for E1C is optional since it is implied by + * STATE_GAL_E1C_2ND_CODE_LOCK. + *
  • For E1B and E1C, STATE_SYMBOL_SYNC is optional, because it is implied by + * STATE_GAL_E1BC_CODE_LOCK. + *
+ * + */ + @export(name="", value_prefix="GNSS_MEASUREMENT_") + enum GnssMeasurementState : uint32_t { + STATE_UNKNOWN = 0, + STATE_CODE_LOCK = 1 << 0, + STATE_BIT_SYNC = 1 << 1, + STATE_SUBFRAME_SYNC = 1 << 2, + STATE_TOW_DECODED = 1 << 3, + STATE_MSEC_AMBIGUOUS = 1 << 4, + STATE_SYMBOL_SYNC = 1 << 5, + STATE_GLO_STRING_SYNC = 1 << 6, + STATE_GLO_TOD_DECODED = 1 << 7, + STATE_BDS_D2_BIT_SYNC = 1 << 8, + STATE_BDS_D2_SUBFRAME_SYNC = 1 << 9, + STATE_GAL_E1BC_CODE_LOCK = 1 << 10, + STATE_GAL_E1C_2ND_CODE_LOCK = 1 << 11, + STATE_GAL_E1B_PAGE_SYNC = 1 << 12, + STATE_SBAS_SYNC = 1 << 13, + STATE_TOW_KNOWN = 1 << 14, + STATE_GLO_TOD_KNOWN = 1 << 15, + STATE_2ND_CODE_LOCK = 1 << 16, + }; + /** * Extends a GNSS Measurement, adding a GnssMeasurementCodeType. */ @@ -105,6 +446,10 @@ interface IGnssMeasurementCallback extends @1.1::IGnssMeasurementCallback { * quarter cycle offset as they do when transmitted from the satellites. If the measurement * is from a combination of the in-phase and quadrature phase components, then the alignment * of the phase measurement will be aligned to the in-phase component. + * + * In this version of the HAL, the field 'state' in the v1_1.v1_0 struct is deprecated, and + * is no longer used by the framework. The satellite sync state is instead reported in + * @2.0::IGnssMeasurementCallback.GnssMeasurement.state. */ @1.1::IGnssMeasurementCallback.GnssMeasurement v1_1; @@ -126,6 +471,16 @@ interface IGnssMeasurementCallback extends @1.1::IGnssMeasurementCallback { * standard, "G" could be specified here. */ string otherCodeTypeName; + + /** + * Per satellite sync state. It represents the current sync state for the associated + * satellite. + * + * Based on the sync state, the receivedSvTimeInNs field must be interpreted accordingly. + * + * This value is mandatory. + */ + bitfield state; }; /** From 4135a8e94c9d81856beec036d9910def878918c5 Mon Sep 17 00:00:00 2001 From: Miao Wang Date: Fri, 1 Feb 2019 14:00:08 -0800 Subject: [PATCH 453/718] Fix the usage of GTEST_SKIP Test: mm Test: VtsHalNeuralnetworksV1_0TargetTest Change-Id: I6baaf54c626778129c1aab4f6622af570b34ec3f --- neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp index 2e1385497b..0724c09ece 100644 --- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp +++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp @@ -548,7 +548,7 @@ void PrepareModel(const sp& device, const V1_2::Model& model, std::cout << "[ ] Early termination of test because vendor service cannot " "prepare model that it does not support." << std::endl; - GTEST_SKIP(); + return; } EXPECT_EQ(ErrorStatus::NONE, prepareReturnStatus); ASSERT_NE(nullptr, preparedModel->get()); @@ -561,6 +561,9 @@ void Execute(const sp& device, std::function c V1_2::Model model = create_model(); sp preparedModel = nullptr; PrepareModel(device, model, &preparedModel); + if (preparedModel == nullptr) { + GTEST_SKIP(); + } EvaluatePreparedModel(preparedModel, is_ignored, examples, model.relaxComputationFloat32toFloat16, testDynamicOutputShape); } From 031738baa645963f673b73985dfc570193715318 Mon Sep 17 00:00:00 2001 From: Yu-Han Yang Date: Fri, 1 Feb 2019 19:58:04 -0800 Subject: [PATCH 454/718] Use V2_0 GnssMeasurement.state in default implementation Bug: 123297074 Test: tested on cuttlefish Change-Id: Ia4479a3f3bf6f962acdebf9cf01ec5cbeab5fff7 --- gnss/2.0/default/GnssMeasurement.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/gnss/2.0/default/GnssMeasurement.cpp b/gnss/2.0/default/GnssMeasurement.cpp index 2d34b20446..0f707b4d4a 100644 --- a/gnss/2.0/default/GnssMeasurement.cpp +++ b/gnss/2.0/default/GnssMeasurement.cpp @@ -26,7 +26,7 @@ namespace implementation { using GnssConstellationType = V1_0::GnssConstellationType; using GnssMeasurementFlags = V1_0::IGnssMeasurementCallback::GnssMeasurementFlags; -using GnssMeasurementState = V1_0::IGnssMeasurementCallback::GnssMeasurementState; +using GnssMeasurementState = V2_0::IGnssMeasurementCallback::GnssMeasurementState; sp GnssMeasurement::sCallback = nullptr; @@ -97,11 +97,6 @@ GnssData GnssMeasurement::getMockMeasurement() { .svid = (int16_t)6, .constellation = GnssConstellationType::GLONASS, .timeOffsetNs = 0.0, - .state = GnssMeasurementState::STATE_CODE_LOCK | GnssMeasurementState::STATE_BIT_SYNC | - GnssMeasurementState::STATE_SUBFRAME_SYNC | - GnssMeasurementState::STATE_TOW_DECODED | - GnssMeasurementState::STATE_GLO_STRING_SYNC | - GnssMeasurementState::STATE_GLO_TOD_DECODED, .receivedSvTimeInNs = 8195997131077, .receivedSvTimeUncertaintyInNs = 15, .cN0DbHz = 30.0, @@ -115,9 +110,15 @@ GnssData GnssMeasurement::getMockMeasurement() { .multipathIndicator = V1_0::IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_UNKNOWN}; V1_1::IGnssMeasurementCallback::GnssMeasurement measurement_1_1 = {.v1_0 = measurement_1_0}; - V2_0::IGnssMeasurementCallback::GnssMeasurement measurement_2_0 = {.v1_1 = measurement_1_1, + V2_0::IGnssMeasurementCallback::GnssMeasurement measurement_2_0 = { + .v1_1 = measurement_1_1, .codeType = IGnssMeasurementCallback::GnssMeasurementCodeType::C, - .otherCodeTypeName = ""}; + .otherCodeTypeName = "", + .state = GnssMeasurementState::STATE_CODE_LOCK | GnssMeasurementState::STATE_BIT_SYNC | + GnssMeasurementState::STATE_SUBFRAME_SYNC | + GnssMeasurementState::STATE_TOW_DECODED | + GnssMeasurementState::STATE_GLO_STRING_SYNC | + GnssMeasurementState::STATE_GLO_TOD_DECODED}; hidl_vec measurements(1); measurements[0] = measurement_2_0; From e8631244adb875650c6e8e331a5bddd4381c2f36 Mon Sep 17 00:00:00 2001 From: "Harpreet \"Eli\" Sangha" Date: Thu, 31 Jan 2019 15:43:36 +0900 Subject: [PATCH 455/718] vibrator: Add Example Implementation for HAL 1.3 Bug: 121352767 Test: Ran 'cmd vibrator' on 'cf_x86_phone'. Change-Id: I1e59cf6e0df31a8f47ee026c0333a5d39a9cdc5a Signed-off-by: Harpreet "Eli" Sangha --- vibrator/1.3/example/Android.bp | 34 +++ vibrator/1.3/example/Vibrator.cpp | 242 ++++++++++++++++++ vibrator/1.3/example/Vibrator.h | 78 ++++++ ...d.hardware.vibrator@1.3-service.example.rc | 4 + ....hardware.vibrator@1.3-service.example.xml | 11 + vibrator/1.3/example/service.cpp | 46 ++++ 6 files changed, 415 insertions(+) create mode 100644 vibrator/1.3/example/Android.bp create mode 100644 vibrator/1.3/example/Vibrator.cpp create mode 100644 vibrator/1.3/example/Vibrator.h create mode 100644 vibrator/1.3/example/android.hardware.vibrator@1.3-service.example.rc create mode 100644 vibrator/1.3/example/android.hardware.vibrator@1.3-service.example.xml create mode 100644 vibrator/1.3/example/service.cpp diff --git a/vibrator/1.3/example/Android.bp b/vibrator/1.3/example/Android.bp new file mode 100644 index 0000000000..36f2ff82c2 --- /dev/null +++ b/vibrator/1.3/example/Android.bp @@ -0,0 +1,34 @@ +// +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +cc_binary { + name: "android.hardware.vibrator@1.3-service.example", + vendor: true, + relative_install_path: "hw", + init_rc: ["android.hardware.vibrator@1.3-service.example.rc"], + vintf_fragments: ["android.hardware.vibrator@1.3-service.example.xml"], + srcs: ["service.cpp", "Vibrator.cpp"], + cflags: ["-Wall", "-Werror"], + shared_libs: [ + "libhidlbase", + "libhidltransport", + "liblog", + "libutils", + "android.hardware.vibrator@1.0", + "android.hardware.vibrator@1.1", + "android.hardware.vibrator@1.2", + "android.hardware.vibrator@1.3", + ], +} diff --git a/vibrator/1.3/example/Vibrator.cpp b/vibrator/1.3/example/Vibrator.cpp new file mode 100644 index 0000000000..bb9a057697 --- /dev/null +++ b/vibrator/1.3/example/Vibrator.cpp @@ -0,0 +1,242 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "VibratorService" + +#include + +#include "Vibrator.h" + +namespace android { +namespace hardware { +namespace vibrator { +namespace V1_3 { +namespace implementation { + +static constexpr uint32_t MS_PER_S = 1000; +static constexpr uint32_t NS_PER_MS = 1000000; + +Vibrator::Vibrator() { + sigevent se{}; + se.sigev_notify = SIGEV_THREAD; + se.sigev_value.sival_ptr = this; + se.sigev_notify_function = timerCallback; + se.sigev_notify_attributes = nullptr; + + if (timer_create(CLOCK_REALTIME, &se, &mTimer) < 0) { + ALOGE("Can not create timer!%s", strerror(errno)); + } +} + +// Methods from ::android::hardware::vibrator::V1_0::IVibrator follow. + +Return Vibrator::on(uint32_t timeoutMs) { + return activate(timeoutMs); +} + +Return Vibrator::off() { + return activate(0); +} + +Return Vibrator::supportsAmplitudeControl() { + return true; +} + +Return Vibrator::setAmplitude(uint8_t amplitude) { + ALOGI("Amplitude: %u -> %u\n", mAmplitude, amplitude); + mAmplitude = amplitude; + return Status::OK; +} + +Return Vibrator::perform(V1_0::Effect effect, EffectStrength strength, perform_cb _hidl_cb) { + return perform_1_1(static_cast(effect), strength, _hidl_cb); +} + +// Methods from ::android::hardware::vibrator::V1_1::IVibrator follow. + +Return Vibrator::perform_1_1(V1_1::Effect_1_1 effect, EffectStrength strength, + perform_cb _hidl_cb) { + return perform_1_2(static_cast(effect), strength, _hidl_cb); +} + +// Methods from ::android::hardware::vibrator::V1_2::IVibrator follow. + +Return Vibrator::perform_1_2(Effect effect, EffectStrength strength, perform_cb _hidl_cb) { + uint8_t amplitude; + uint32_t ms; + Status status; + + ALOGI("Perform: Effect %s\n", effectToName(effect)); + + amplitude = strengthToAmplitude(strength); + setAmplitude(amplitude); + + ms = effectToMs(effect); + status = activate(ms); + + _hidl_cb(status, ms); + + return Void(); +} + +// Methods from ::android::hardware::vibrator::V1_3::IVibrator follow. + +Return Vibrator::supportsExternalControl() { + return true; +} + +Return Vibrator::setExternalControl(bool enabled) { + if (mEnabled) { + ALOGW("Setting external control while the vibrator is enabled is unsupported!"); + return Status::UNSUPPORTED_OPERATION; + } else { + ALOGI("ExternalControl: %s -> %s\n", mExternalControl ? "true" : "false", + enabled ? "true" : "false"); + mExternalControl = enabled; + return Status::OK; + } +} + +// Private methods follow. + +Status Vibrator::enable(bool enabled) { + if (mExternalControl) { + ALOGW("Enabling/disabling while the vibrator is externally controlled is unsupported!"); + return Status::UNSUPPORTED_OPERATION; + } else { + ALOGI("Enabled: %s -> %s\n", mEnabled ? "true" : "false", enabled ? "true" : "false"); + mEnabled = enabled; + return Status::OK; + } +} + +Status Vibrator::activate(uint32_t ms) { + std::lock_guard lock{mMutex}; + Status status = Status::OK; + + if (ms > 0) { + status = enable(true); + if (status != Status::OK) { + return status; + } + } + + itimerspec ts{}; + ts.it_value.tv_sec = ms / MS_PER_S; + ts.it_value.tv_nsec = ms % MS_PER_S * NS_PER_MS; + + if (timer_settime(mTimer, 0, &ts, nullptr) < 0) { + ALOGE("Can not set timer!"); + status = Status::UNKNOWN_ERROR; + } + + if ((status != Status::OK) || !ms) { + Status _status; + + _status = enable(false); + + if (status == Status::OK) { + status = _status; + } + } + + return status; +} + +void Vibrator::timeout() { + std::lock_guard lock{mMutex}; + itimerspec ts{}; + + if (timer_gettime(mTimer, &ts) < 0) { + ALOGE("Can not read timer!"); + } + + if (ts.it_value.tv_sec == 0 && ts.it_value.tv_nsec == 0) { + enable(false); + } +} + +void Vibrator::timerCallback(union sigval sigval) { + static_cast(sigval.sival_ptr)->timeout(); +} + +const char* Vibrator::effectToName(Effect effect) { + return toString(effect).c_str(); +} + +uint32_t Vibrator::effectToMs(Effect effect) { + switch (effect) { + case Effect::CLICK: + return 10; + case Effect::DOUBLE_CLICK: + return 15; + case Effect::TICK: + return 5; + case Effect::THUD: + return 5; + case Effect::POP: + return 5; + case Effect::HEAVY_CLICK: + return 10; + case Effect::RINGTONE_1: + return 30000; + case Effect::RINGTONE_2: + return 30000; + case Effect::RINGTONE_3: + return 30000; + case Effect::RINGTONE_4: + return 30000; + case Effect::RINGTONE_5: + return 30000; + case Effect::RINGTONE_6: + return 30000; + case Effect::RINGTONE_7: + return 30000; + case Effect::RINGTONE_8: + return 30000; + case Effect::RINGTONE_9: + return 30000; + case Effect::RINGTONE_10: + return 30000; + case Effect::RINGTONE_11: + return 30000; + case Effect::RINGTONE_12: + return 30000; + case Effect::RINGTONE_13: + return 30000; + case Effect::RINGTONE_14: + return 30000; + case Effect::RINGTONE_15: + return 30000; + } +} + +uint8_t Vibrator::strengthToAmplitude(EffectStrength strength) { + switch (strength) { + case EffectStrength::LIGHT: + return 128; + case EffectStrength::MEDIUM: + return 192; + case EffectStrength::STRONG: + return 255; + } +} + +} // namespace implementation +} // namespace V1_3 +} // namespace vibrator +} // namespace hardware +} // namespace android diff --git a/vibrator/1.3/example/Vibrator.h b/vibrator/1.3/example/Vibrator.h new file mode 100644 index 0000000000..a931b63b09 --- /dev/null +++ b/vibrator/1.3/example/Vibrator.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2019 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_VIBRATOR_V1_3_VIBRATOR_H +#define ANDROID_HARDWARE_VIBRATOR_V1_3_VIBRATOR_H + +#include +#include + +namespace android { +namespace hardware { +namespace vibrator { +namespace V1_3 { +namespace implementation { + +using android::hardware::vibrator::V1_0::EffectStrength; +using android::hardware::vibrator::V1_0::Status; +using android::hardware::vibrator::V1_2::Effect; + +class Vibrator : public IVibrator { + public: + Vibrator(); + + // Methods from ::android::hardware::vibrator::V1_0::IVibrator follow. + Return on(uint32_t timeoutMs) override; + Return off() override; + Return supportsAmplitudeControl() override; + Return setAmplitude(uint8_t amplitude) override; + Return perform(V1_0::Effect effect, EffectStrength strength, + perform_cb _hidl_cb) override; + + // Methods from ::android::hardware::vibrator::V1_1::IVibrator follow. + Return perform_1_1(V1_1::Effect_1_1 effect, EffectStrength strength, + perform_cb _hidl_cb) override; + + // Methods from ::android::hardware::vibrator::V1_2::IVibrator follow. + Return perform_1_2(Effect effect, EffectStrength strength, perform_cb _hidl_cb) override; + + // Methods from ::android::hardware::vibrator::V1_3::IVibrator follow. + Return supportsExternalControl() override; + Return setExternalControl(bool enabled) override; + + private: + Status enable(bool enabled); + Status activate(uint32_t ms); + void timeout(); + + static void timerCallback(union sigval sigval); + static const char* effectToName(Effect effect); + static uint32_t effectToMs(Effect effect); + static uint8_t strengthToAmplitude(EffectStrength strength); + + private: + bool mEnabled{false}; + uint8_t mAmplitude{UINT8_MAX}; + bool mExternalControl{false}; + std::mutex mMutex; + timer_t mTimer{nullptr}; +}; +} // namespace implementation +} // namespace V1_3 +} // namespace vibrator +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_VIBRATOR_V1_3_VIBRATOR_H diff --git a/vibrator/1.3/example/android.hardware.vibrator@1.3-service.example.rc b/vibrator/1.3/example/android.hardware.vibrator@1.3-service.example.rc new file mode 100644 index 0000000000..ed7a562cfc --- /dev/null +++ b/vibrator/1.3/example/android.hardware.vibrator@1.3-service.example.rc @@ -0,0 +1,4 @@ +service vendor.vibrator-1-3 /vendor/bin/hw/android.hardware.vibrator@1.3-service.example + class hal + user system + group system diff --git a/vibrator/1.3/example/android.hardware.vibrator@1.3-service.example.xml b/vibrator/1.3/example/android.hardware.vibrator@1.3-service.example.xml new file mode 100644 index 0000000000..172aa2178c --- /dev/null +++ b/vibrator/1.3/example/android.hardware.vibrator@1.3-service.example.xml @@ -0,0 +1,11 @@ + + + android.hardware.vibrator + hwbinder + 1.3 + + IVibrator + default + + + diff --git a/vibrator/1.3/example/service.cpp b/vibrator/1.3/example/service.cpp new file mode 100644 index 0000000000..449996e280 --- /dev/null +++ b/vibrator/1.3/example/service.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define LOG_TAG "android.hardware.vibrator@1.3-service.example" + +#include +#include + +#include "Vibrator.h" + +using android::hardware::configureRpcThreadpool; +using android::hardware::joinRpcThreadpool; +using android::hardware::vibrator::V1_3::IVibrator; +using android::hardware::vibrator::V1_3::implementation::Vibrator; +using namespace android; + +status_t registerVibratorService() { + sp vibrator = new Vibrator(); + + return vibrator->registerAsService(); +} + +int main() { + configureRpcThreadpool(1, true); + status_t status = registerVibratorService(); + + if (status != OK) { + return status; + } + + joinRpcThreadpool(); + + return 1; +} From 55386823a318309bfe1cc40175afa615225cabb1 Mon Sep 17 00:00:00 2001 From: Shuzhen Wang Date: Tue, 4 Dec 2018 18:14:35 -0800 Subject: [PATCH 456/718] Camera: Add HAL interface change for HEIC - Add new usage flag to indicate the consumer of the buffer is HEIC encoder. - Add new data space to indicate that the BLOB buffer is HEIC encoded. - Add new BlobId to specify JPEG APPs segments. Test: testHeic CTS test Bug: 79465976 Change-Id: Iaa6a1d017223e84fc1c5dd0a9d90d9f09240e827 --- camera/device/3.5/types.hal | 33 +++++++ camera/metadata/3.4/types.hal | 86 ++++++++++++++++++- .../VtsHalCameraProviderV2_4TargetTest.cpp | 35 ++++++++ graphics/common/1.2/types.hal | 38 ++++++++ 4 files changed, 191 insertions(+), 1 deletion(-) diff --git a/camera/device/3.5/types.hal b/camera/device/3.5/types.hal index 613187d96e..7cb97277db 100644 --- a/camera/device/3.5/types.hal +++ b/camera/device/3.5/types.hal @@ -18,6 +18,7 @@ package android.hardware.camera.device@3.5; import @3.2::StreamBuffer; import @3.4::StreamConfiguration; +import @3.2::CameraBlobId; /** * StreamConfiguration: @@ -129,3 +130,35 @@ struct BufferRequest { uint32_t numBuffersRequested; }; +/** + * CameraBlob: + * + * Identical to @3.2::CameraBlob, except that it also supports transport of JPEG + * APP segments blob, which contains JPEG APP1 to APPn (Application Marker) + * segments as specified in JEITA CP-3451. + * + * To capture a JPEG APP segments blob, a stream is created using the pixel format + * HAL_PIXEL_FORMAT_BLOB and dataspace HAL_DATASPACE_JPEG_APP_SEGMENTS. The buffer + * size for the stream is calculated by the framework, based on the static + * metadata field android.heic.maxAppSegmentsCount. + * + * Similar to JPEG image, the JPEG APP segment images can be of variable size, + * so the HAL needs to include the final size of all APP segments using this + * structure inside the output stream buffer. The camera blob ID field must be + * set to CameraBlobId::JPEG_APP_SEGMENTS. + * + * The transport header must be at the end of the JPEG APP segments output stream + * buffer. That means the blobId must start at byte[buffer_size - + * sizeof(CameraBlob)], where the buffer_size is the size of gralloc + * buffer. The JPEG APP segments data itself starts at the beginning of the + * buffer and must be blobSize bytes long. + */ +enum CameraBlobId : @3.2::CameraBlobId { + JPEG_APP_SEGMENTS = 0x100, +}; + +struct CameraBlob { + CameraBlobId blobId; + uint32_t blobSize; +}; + diff --git a/camera/metadata/3.4/types.hal b/camera/metadata/3.4/types.hal index 9bbc90dc28..4caf3e3ea2 100644 --- a/camera/metadata/3.4/types.hal +++ b/camera/metadata/3.4/types.hal @@ -26,7 +26,34 @@ package android.hardware.camera.metadata@3.4; import android.hardware.camera.metadata@3.2; import android.hardware.camera.metadata@3.3; -// No new metadata sections added in this revision +/** + * Top level hierarchy definitions for camera metadata. *_INFO sections are for + * the static metadata that can be retrived without opening the camera device. + */ +enum CameraMetadataSection : @3.3::CameraMetadataSection { + ANDROID_HEIC = + android.hardware.camera.metadata@3.3::CameraMetadataSection:ANDROID_SECTION_COUNT, + + ANDROID_HEIC_INFO, + + ANDROID_SECTION_COUNT_3_4, + + VENDOR_SECTION_3_4 = 0x8000, + +}; + +/** + * Hierarchy positions in enum space. All vendor extension sections must be + * defined with tag >= VENDOR_SECTION_START + */ +enum CameraMetadataSectionStart : android.hardware.camera.metadata@3.3::CameraMetadataSectionStart { + ANDROID_HEIC_START = CameraMetadataSection:ANDROID_HEIC << 16, + + ANDROID_HEIC_INFO_START = CameraMetadataSection:ANDROID_HEIC_INFO << 16, + + VENDOR_SECTION_START_3_4 = CameraMetadataSection:VENDOR_SECTION_3_4 << 16, + +}; /** * Main enumeration for defining camera metadata tags added in this revision @@ -105,6 +132,47 @@ enum CameraMetadataTag : @3.3::CameraMetadataTag { ANDROID_LOGICAL_MULTI_CAMERA_END_3_4, + /** android.heic.availableHeicStreamConfigurations [static, enum[], ndk_public] + * + *

The available HEIC (ISO/IEC 23008-12) stream + * configurations that this camera device supports + * (i.e. format, width, height, output/input stream).

+ */ + ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS = CameraMetadataSectionStart:ANDROID_HEIC_START, + + /** android.heic.availableHeicMinFrameDurations [static, int64[], ndk_public] + * + *

This lists the minimum frame duration for each + * format/size combination for HEIC output formats.

+ */ + ANDROID_HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS, + + /** android.heic.availableHeicStallDurations [static, int64[], ndk_public] + * + *

This lists the maximum stall duration for each + * output format/size combination for HEIC streams.

+ */ + ANDROID_HEIC_AVAILABLE_HEIC_STALL_DURATIONS, + + ANDROID_HEIC_END_3_4, + + /** android.heic.info.supported [static, enum, system] + * + *

Whether this camera device can support identical set of stream combinations + * involving HEIC image format, compared to the + * table of combinations + * involving JPEG image format required for the device's hardware level and capabilities.

+ */ + ANDROID_HEIC_INFO_SUPPORTED = CameraMetadataSectionStart:ANDROID_HEIC_INFO_START, + + /** android.heic.info.maxJpegAppSegmentsCount [static, byte, system] + * + *

The maximum number of Jpeg APP segments supported by the camera HAL device.

+ */ + ANDROID_HEIC_INFO_MAX_JPEG_APP_SEGMENTS_COUNT, + + ANDROID_HEIC_INFO_END_3_4, + }; /* @@ -166,3 +234,19 @@ enum CameraMetadataEnumAndroidDepthAvailableDynamicDepthStreamConfigurations : u ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS_OUTPUT, ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS_INPUT, }; + +/** android.heic.availableHeicStreamConfigurations enumeration values + * @see ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS + */ +enum CameraMetadataEnumAndroidHeicAvailableHeicStreamConfigurations : uint32_t { + ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS_OUTPUT, + ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS_INPUT, +}; + +/** android.heic.info.supported enumeration values + * @see ANDROID_HEIC_INFO_SUPPORTED + */ +enum CameraMetadataEnumAndroidHeicInfoSupported : uint32_t { + ANDROID_HEIC_INFO_SUPPORTED_FALSE, + ANDROID_HEIC_INFO_SUPPORTED_TRUE, +}; diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp index 211240a06b..d5e1b39c88 100644 --- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp +++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp @@ -5539,6 +5539,41 @@ void CameraHidlTest::verifyCameraCharacteristics(Status status, const CameraMeta ADD_FAILURE() << "ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS" << " per API contract should never be set by Hal!"; } + + retcode = find_camera_metadata_ro_entry(metadata, + ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS, &entry); + if (0 == retcode || entry.count > 0) { + ADD_FAILURE() << "ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS " + << " per API contract should never be set by Hal!"; + } + + retcode = find_camera_metadata_ro_entry(metadata, + ANDROID_HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS, &entry); + if (0 == retcode || entry.count > 0) { + ADD_FAILURE() << "ANDROID_HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS " + << " per API contract should never be set by Hal!"; + } + + retcode = find_camera_metadata_ro_entry(metadata, + ANDROID_HEIC_AVAILABLE_HEIC_STALL_DURATIONS, &entry); + if (0 == retcode || entry.count > 0) { + ADD_FAILURE() << "ANDROID_HEIC_AVAILABLE_HEIC_STALL_DURATIONS " + << " per API contract should never be set by Hal!"; + } + + retcode = find_camera_metadata_ro_entry(metadata, + ANDROID_HEIC_INFO_SUPPORTED, &entry); + if (0 == retcode && entry.count > 0) { + retcode = find_camera_metadata_ro_entry(metadata, + ANDROID_HEIC_INFO_MAX_JPEG_APP_SEGMENTS_COUNT, &entry); + if (0 == retcode && entry.count > 0) { + uint8_t maxJpegAppSegmentsCount = entry.data.u8[0]; + ASSERT_TRUE(maxJpegAppSegmentsCount >= 1 && + maxJpegAppSegmentsCount <= 16); + } else { + ADD_FAILURE() << "Get Heic maxJpegAppSegmentsCount failed!"; + } + } } void CameraHidlTest::verifyMonochromeCharacteristics(const CameraMetadata& chars, diff --git a/graphics/common/1.2/types.hal b/graphics/common/1.2/types.hal index 3da6176342..ebea1dcc7b 100644 --- a/graphics/common/1.2/types.hal +++ b/graphics/common/1.2/types.hal @@ -49,6 +49,32 @@ enum Dataspace : @1.1::Dataspace { * Embedded depth metadata following the dynamic depth specification. */ DYNAMIC_DEPTH = 0x1002, + + /** + * JPEG APP segments format as specified by JEIDA spec + * + * The buffer must only contain APP1 (Application Marker) segment followed + * by zero or more APPn segments, as is specified by JEITA CP-3451C section 4.5.4. + * The APP1 segment optionally contains a thumbnail. The buffer will not + * contain main compressed image. + * + * This value is valid with formats: + * HAL_PIXEL_FORMAT_BLOB: JPEG APP segments optionally containing thumbnail image + * in APP1. BLOB buffer with this dataspace is output by HAL, and used by + * camera framework to encode into a HEIC image. + */ + JPEG_APP_SEGMENTS = 0x1003, + + /** + * ISO/IEC 23008-12 + * + * High Efficiency Image File Format (HEIF) + * + * This value is valid with formats: + * HAL_PIXEL_FORMAT_BLOB: A HEIC image encoded by HEIC or HEVC encoder + * according to ISO/IEC 23008-12. + */ + HEIF = 0x1004, }; enum ColorMode : @1.1::ColorMode { @@ -69,6 +95,18 @@ enum ColorMode : @1.1::ColorMode { DISPLAY_BT2020 = 13, }; +/** + * Buffer usage definitions. + */ +enum BufferUsage : @1.1::BufferUsage { + /** + * Buffer is used as input for HEIC encoder. + */ + HW_IMAGE_ENCODER = 1ULL << 27, + + /* bits 28 and 32-47 must be zero and are reserved for future versions */ +}; + /** * HIDL counterpart of `AHardwareBuffer_Desc`. * From 4609857ee4313961df3eaf5ccd6850a2a2cdd288 Mon Sep 17 00:00:00 2001 From: Manisha Jajoo Date: Thu, 21 Jun 2018 14:05:31 +0530 Subject: [PATCH 457/718] omx:component: add support for tunneled components in ComponentTest Test: make vts -j99 BUILD_GOOGLE_VTS=true TARGET_PRODUCT=aosp_arm64 \ && vts-tradefed run commandAndExit vts \ --skip-all-system-status-check --primary-abi-only \ --skip-preconditions --module VtsHalMediaOmxV1_0Host \ -l INFO bug: 70933963 Change-Id: I5695820b225041f5b764506cdafacf7c95d836aa --- .../common/media_hidl_test_common.cpp | 38 +++++++++++++++---- .../VtsHalMediaOmxV1_0TargetComponentTest.cpp | 20 +++++++++- .../VtsHalMediaOmxV1_0TargetVideoDecTest.cpp | 10 +++++ 3 files changed, 58 insertions(+), 10 deletions(-) diff --git a/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp b/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp index 34a96a0ce7..29be2a09b3 100644 --- a/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp +++ b/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp @@ -387,17 +387,28 @@ void changeStateLoadedtoIdle(sp omxNode, sp observer, OMX_StateIdle); ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); + OMX_PARAM_PORTDEFINITIONTYPE portDefInput; + OMX_PARAM_PORTDEFINITIONTYPE portDefOutput; + status = getPortParam(omxNode, OMX_IndexParamPortDefinition, kPortIndexInput, &portDefInput); + EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); + status = getPortParam(omxNode, OMX_IndexParamPortDefinition, kPortIndexOutput, &portDefOutput); + EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); + // Dont switch states until the ports are populated - status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer); - ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT); + if (portDefInput.nBufferCountActual || portDefOutput.nBufferCountActual) { + status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer); + ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT); + } // allocate buffers on input port ASSERT_NO_FATAL_FAILURE(allocatePortBuffers( omxNode, iBuffer, kPortIndexInput, pm[0], allocGrap)); // Dont switch states until the ports are populated - status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer); - ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT); + if (portDefOutput.nBufferCountActual) { + status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer); + ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT); + } // allocate buffers on output port ASSERT_NO_FATAL_FAILURE(allocatePortBuffers( @@ -430,9 +441,18 @@ void changeStateIdletoLoaded(sp omxNode, sp observer, OMX_StateLoaded); ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); + OMX_PARAM_PORTDEFINITIONTYPE portDefInput; + OMX_PARAM_PORTDEFINITIONTYPE portDefOutput; + status = getPortParam(omxNode, OMX_IndexParamPortDefinition, kPortIndexInput, &portDefInput); + EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); + status = getPortParam(omxNode, OMX_IndexParamPortDefinition, kPortIndexOutput, &portDefOutput); + EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); + // dont change state until all buffers are freed - status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer); - ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT); + if (portDefInput.nBufferCountActual || portDefOutput.nBufferCountActual) { + status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer); + ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT); + } for (size_t i = 0; i < iBuffer->size(); ++i) { status = omxNode->freeBuffer(kPortIndexInput, (*iBuffer)[i].id); @@ -440,8 +460,10 @@ void changeStateIdletoLoaded(sp omxNode, sp observer, } // dont change state until all buffers are freed - status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer); - ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT); + if (portDefOutput.nBufferCountActual) { + status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer); + ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT); + } for (size_t i = 0; i < oBuffer->size(); ++i) { status = omxNode->freeBuffer(kPortIndexOutput, (*oBuffer)[i].id); diff --git a/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp b/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp index 7750a12fac..2223583740 100644 --- a/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp +++ b/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp @@ -115,6 +115,7 @@ class ComponentHidlTest : public ::testing::VtsHalHidlTargetTestBase { } if (compClass == unknown_class) disableTest = true; isSecure = false; + mTunnel = false; size_t suffixLen = strlen(".secure"); if (strlen(gEnv->getComponent().c_str()) >= suffixLen) { isSecure = @@ -122,6 +123,18 @@ class ComponentHidlTest : public ::testing::VtsHalHidlTargetTestBase { strlen(gEnv->getComponent().c_str()) - suffixLen, ".secure"); } + if (compClass == video_decoder) { + omxNode->configureVideoTunnelMode( + 1, OMX_TRUE, 0, + [&](android::hardware::media::omx::V1_0::Status _s, + const ::android::hardware::hidl_handle& sidebandHandle) { + (void)sidebandHandle; + if (_s == android::hardware::media::omx::V1_0::Status::OK) + this->mTunnel = true; + }); + } + // NOTES: secure components are not covered in these tests. + // we are disabling tests for them if (disableTest) std::cout << "[ WARN ] Test Disabled \n"; } @@ -149,6 +162,7 @@ class ComponentHidlTest : public ::testing::VtsHalHidlTargetTestBase { sp observer; sp omxNode; standardCompClass compClass; + bool mTunnel; bool isSecure; bool disableTest; @@ -991,7 +1005,8 @@ TEST_F(ComponentHidlTest, PortEnableDisable_Idle) { ASSERT_NO_FATAL_FAILURE( changeStateLoadedtoIdle(omxNode, observer, &pBuffer[0], &pBuffer[1], kPortIndexInput, kPortIndexOutput, portMode)); - for (size_t i = portBase; i < portBase + 2; i++) { + int range = mTunnel ? 1 : 2; + for (size_t i = portBase; i < portBase + range; i++) { status = omxNode->sendCommand(toRawCommandType(OMX_CommandPortDisable), i); ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); @@ -1104,7 +1119,8 @@ TEST_F(ComponentHidlTest, PortEnableDisable_Execute) { dispatchOutputBuffer(omxNode, &pBuffer[1], i, portMode[1])); } - for (size_t i = portBase; i < portBase + 2; i++) { + int range = mTunnel ? 1 : 2; + for (size_t i = portBase; i < portBase + range; i++) { status = omxNode->sendCommand(toRawCommandType(OMX_CommandPortDisable), i); ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); diff --git a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp index 1db9f7531a..df048c6bf2 100644 --- a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp +++ b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp @@ -153,7 +153,17 @@ class VideoDecHidlTest : public ::testing::VtsHalHidlTargetTestBase { ".secure"); } if (isSecure) disableTest = true; + omxNode->configureVideoTunnelMode( + 1, OMX_TRUE, 0, + [&](android::hardware::media::omx::V1_0::Status _s, + const ::android::hardware::hidl_handle& sidebandHandle) { + (void)sidebandHandle; + if (_s == android::hardware::media::omx::V1_0::Status::OK) + this->disableTest = true; + }); if (disableTest) std::cout << "[ WARN ] Test Disabled \n"; + // NOTES: secure and tunneled components are not covered in these tests. + // we are disabling tests for them } virtual void TearDown() override { From 2a82e974a45d57062b44efe0fc60bdf0095a8eb5 Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Wed, 6 Feb 2019 11:01:58 -0800 Subject: [PATCH 458/718] DRM: optional 1.0 to 1.2. Before: 1.0-1.1 is optional, but an implementation of 1.2 is required. After: 1.0-1.2 can be used. Bug: N/A Test: N/A Change-Id: I631c253ee44f858e3c1912106cb42682eb044c05 --- .../compatibility_matrix.current.xml | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml index 0540ef1810..90c8fdc1c0 100644 --- a/compatibility_matrices/compatibility_matrix.current.xml +++ b/compatibility_matrices/compatibility_matrix.current.xml @@ -153,19 +153,7 @@
android.hardware.drm - 1.0-1 - - ICryptoFactory - .* - - - IDrmFactory - .* - - - - android.hardware.drm - 1.2 + 1.0-2 ICryptoFactory .* From e42843f4add7342ee8923f11f21a4a3a2589ddaa Mon Sep 17 00:00:00 2001 From: Brian Stack Date: Thu, 7 Feb 2019 10:42:28 -0800 Subject: [PATCH 459/718] Rename Sensors 2.0 Default Implementation Rename the default implementation to include ".mock" to indicate that the default implementation is a mock service and not intended to be used on production devices. Bug: 124020028 Test: Builds, cuttlefish loads sensors Change-Id: I28c29f23615324cb2ae1dbe1767f18d40cf8d8e1 --- sensors/2.0/default/Android.bp | 2 +- sensors/2.0/default/android.hardware.sensors@2.0-service.rc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sensors/2.0/default/Android.bp b/sensors/2.0/default/Android.bp index d83a9c36fe..d05634b77a 100644 --- a/sensors/2.0/default/Android.bp +++ b/sensors/2.0/default/Android.bp @@ -14,7 +14,7 @@ // limitations under the License. cc_binary { - name: "android.hardware.sensors@2.0-service", + name: "android.hardware.sensors@2.0-service.mock", defaults: ["hidl_defaults"], vendor: true, relative_install_path: "hw", diff --git a/sensors/2.0/default/android.hardware.sensors@2.0-service.rc b/sensors/2.0/default/android.hardware.sensors@2.0-service.rc index 321d760b0d..1fee4f262e 100644 --- a/sensors/2.0/default/android.hardware.sensors@2.0-service.rc +++ b/sensors/2.0/default/android.hardware.sensors@2.0-service.rc @@ -1,4 +1,4 @@ -service vendor.sensors-hal-2-0 /vendor/bin/hw/android.hardware.sensors@2.0-service +service vendor.sensors-hal-2-0-mock /vendor/bin/hw/android.hardware.sensors@2.0-service.mock class hal user system group system From 443e98b12d829a83f25b845f31a7eccd71aa01db Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Thu, 7 Feb 2019 15:42:06 -0800 Subject: [PATCH 460/718] Remove impl from InputClassifier HAL Make the reference implementation for InputClassifier HAL do nothing. This is to allow cuttlefish to install this implementation. It is safe for any device to install this implementation, and is equivalent to not having the HAL running at all. Test: boot up cuttlefish, and interact with the virtual device to ensure that input works okay. Then 'ps -A | grep -i input' and ensure that the HAL is running on the device. Bug: 122600147 Change-Id: I841811bc0da3d78db8d7c1589cf1c59819d901a1 --- input/classifier/1.0/default/Android.bp | 4 +-- .../1.0/default/InputClassifier.cpp | 33 +++++-------------- ...e.input.classifier@1.0-service.default.rc} | 2 +- 3 files changed, 11 insertions(+), 28 deletions(-) rename input/classifier/1.0/default/{android.hardware.input.classifier@1.0-service-example.rc => android.hardware.input.classifier@1.0-service.default.rc} (91%) diff --git a/input/classifier/1.0/default/Android.bp b/input/classifier/1.0/default/Android.bp index ddd883ce38..ceb2aca9f8 100644 --- a/input/classifier/1.0/default/Android.bp +++ b/input/classifier/1.0/default/Android.bp @@ -1,6 +1,6 @@ cc_binary { - name: "android.hardware.input.classifier@1.0-service-example", - init_rc: ["android.hardware.input.classifier@1.0-service-example.rc"], + name: "android.hardware.input.classifier@1.0-service.default", + init_rc: ["android.hardware.input.classifier@1.0-service.default.rc"], relative_install_path: "hw", vendor: true, vintf_fragments: ["manifest_input.classifier.xml"], diff --git a/input/classifier/1.0/default/InputClassifier.cpp b/input/classifier/1.0/default/InputClassifier.cpp index a78bbc5c94..cce9190cc8 100644 --- a/input/classifier/1.0/default/InputClassifier.cpp +++ b/input/classifier/1.0/default/InputClassifier.cpp @@ -31,41 +31,24 @@ namespace V1_0 { namespace implementation { // Methods from ::android::hardware::input::classifier::V1_0::IInputClassifier follow. -Return InputClassifier::classify(const MotionEvent& event) { +Return InputClassifier::classify(const MotionEvent& /*event*/) { /** - * In this example implementation, we will see how many "pixels" inside the video frame - * exceed the value of 250. If more than 6 such pixels are present, then treat the event - * as a "DEEP_PRESS". + * The touchscreen data is highly device-dependent. + * As a result, the implementation of this method will likely be hardware-specific. + * Here we just report gesture as not having any classification, which means that the + * default action will be taken in the framework. + * This is equivalent to not having the InputClassifier HAL at all. */ - if (event.frames.size() == 0) { - return Classification::NONE; - } - ALOGI("Frame(O) timestamp = %" PRIu64 ", received %zu frame(s)", event.frames[0].timestamp, - event.frames.size()); - for (const VideoFrame& frame : event.frames) { - size_t count = 0; - for (size_t i = 0; i < frame.data.size(); i++) { - if (frame.data[i] > 250) { - count++; - } - } - if (count > 6) { - return Classification::DEEP_PRESS; - } - } - return Classification::NONE; } Return InputClassifier::reset() { - // We don't have any internal state in this example implementation, - // so no work needed here. + // We don't have any internal state, so no work needed here. return Void(); } Return InputClassifier::resetDevice(int32_t /*deviceId*/) { - // We don't have any internal per-device state in this example implementation, - // so no work needed here. + // We don't have any internal per-device state, so no work needed here. return Void(); } diff --git a/input/classifier/1.0/default/android.hardware.input.classifier@1.0-service-example.rc b/input/classifier/1.0/default/android.hardware.input.classifier@1.0-service.default.rc similarity index 91% rename from input/classifier/1.0/default/android.hardware.input.classifier@1.0-service-example.rc rename to input/classifier/1.0/default/android.hardware.input.classifier@1.0-service.default.rc index f799bf4359..e7d16ae05e 100644 --- a/input/classifier/1.0/default/android.hardware.input.classifier@1.0-service-example.rc +++ b/input/classifier/1.0/default/android.hardware.input.classifier@1.0-service.default.rc @@ -1,4 +1,4 @@ -service vendor.input.classifier-1-0 /vendor/bin/hw/android.hardware.input.classifier@1.0-service-example +service vendor.input.classifier-1-0 /vendor/bin/hw/android.hardware.input.classifier@1.0-service.default # Must be specified if "disabled" is set. This HAL will only start if requested via getService interface android.hardware.input.classifier@1.0::IInputClassifier default class hal From 918a7de8d52ccd8436e4e5d1bb32a16a7e13a15a Mon Sep 17 00:00:00 2001 From: Eino-Ville Talvala Date: Tue, 4 Dec 2018 14:48:35 -0800 Subject: [PATCH 461/718] camera.provider: Add @2.5 to support notifyDeviceStatusChange Sometimes, the camera service needs to notify a camera HAL that the overall device physical state has changed, so that the HAL can properly remap how it handles logical multicamera devices or similar. Test: Builds, new VTS tests pass Bug: 121379978 Change-Id: I0982fdecaf53a0529289d63c08c5a31264ee7ec7 --- camera/provider/2.5/Android.bp | 25 +++++++ camera/provider/2.5/ICameraProvider.hal | 68 +++++++++++++++++++ camera/provider/2.5/types.hal | 52 ++++++++++++++ .../compatibility_matrix.current.xml | 2 +- 4 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 camera/provider/2.5/Android.bp create mode 100644 camera/provider/2.5/ICameraProvider.hal create mode 100644 camera/provider/2.5/types.hal diff --git a/camera/provider/2.5/Android.bp b/camera/provider/2.5/Android.bp new file mode 100644 index 0000000000..3de010a11b --- /dev/null +++ b/camera/provider/2.5/Android.bp @@ -0,0 +1,25 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +hidl_interface { + name: "android.hardware.camera.provider@2.5", + root: "android.hardware", + vndk: { + enabled: true, + }, + srcs: [ + "types.hal", + "ICameraProvider.hal", + ], + interfaces: [ + "android.hardware.camera.common@1.0", + "android.hardware.camera.device@1.0", + "android.hardware.camera.device@3.2", + "android.hardware.camera.provider@2.4", + "android.hidl.base@1.0", + ], + types: [ + "DeviceState", + ], + gen_java: false, +} + diff --git a/camera/provider/2.5/ICameraProvider.hal b/camera/provider/2.5/ICameraProvider.hal new file mode 100644 index 0000000000..b4cda6a04f --- /dev/null +++ b/camera/provider/2.5/ICameraProvider.hal @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.camera.provider@2.5; + +import android.hardware.camera.common@1.0::Status; +import android.hardware.camera.provider@2.4::ICameraProvider; + +/** + * Camera provider HAL + * + * Version 2.5 adds support for the notifyDeviceStateChange method + */ +interface ICameraProvider extends @2.4::ICameraProvider { + + /** + * notifyDeviceStateChange: + * + * Notify the HAL provider that the state of the overall device has + * changed in some way that the HAL may want to know about. + * + * For example, a physical shutter may have been uncovered or covered, + * or a camera may have been covered or uncovered by an add-on keyboard + * or other accessory. + * + * The state is a bitfield of potential states, and some physical configurations + * could plausibly correspond to multiple different combinations of state bits. + * The HAL must ignore any state bits it is not actively using to determine + * the appropriate camera configuration. + * + * For example, on some devices the FOLDED state could mean that + * backward-facing cameras are covered by the fold, so FOLDED by itself implies + * BACK_COVERED. But other devices may support folding but not cover any cameras + * when folded, so for those FOLDED would not imply any of the other flags. + * Since these relationships are very device-specific, it is difficult to specify + * a comprehensive policy. But as a recommendation, it is suggested that if a flag + * necessarily implies other flags are set as well, then those flags should be set. + * So even though FOLDED would be enough to infer BACK_COVERED on some devices, the + * BACK_COVERED flag should also be set for clarity. + * + * This method may be invoked by the HAL client at any time. It must not + * cause any active camera device sessions to be closed, but may dynamically + * change which physical camera a logical multi-camera is using for its + * active and future output. + * + * The method must be invoked by the HAL client at least once before the + * client calls ICameraDevice::open on any camera device interfaces listed + * by this provider, to establish the initial device state. + * + * @param newState + * The new state of the device. + */ + notifyDeviceStateChange(bitfield newState); + +}; diff --git a/camera/provider/2.5/types.hal b/camera/provider/2.5/types.hal new file mode 100644 index 0000000000..6a8ae83c45 --- /dev/null +++ b/camera/provider/2.5/types.hal @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.camera.provider@2.5; + +/** + * DeviceState: + * + * Possible physical states of the overall device, for use with + * ICameraProvider::notifyDeviceStateChange. + * + */ +enum DeviceState : uint64_t { + /** + * The device is in its normal physical configuration. This is the default if the + * device does not support multiple different states. + */ + NORMAL = 0, + + /** + * Camera device(s) facing backward are covered. + */ + BACK_COVERED = 1 << 0, + + /** + * Camera device(s) facing foward are covered. + */ + FRONT_COVERED = 1 << 1, + + /** + * The device is folded. If not set, the device is unfolded or does not + * support folding. + * + * The exact point when this status change happens during the folding + * operation is device-specific. + */ + FOLDED = 1 << 2, + +}; diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml index 89855a0e65..b8bd54ac8a 100644 --- a/compatibility_matrices/compatibility_matrix.current.xml +++ b/compatibility_matrices/compatibility_matrix.current.xml @@ -113,7 +113,7 @@ android.hardware.camera.provider - 2.4 + 2.5 ICameraProvider [^/]+/[0-9]+ From 2951804146cd3239f3b4371021cb95b4aa52fc2f Mon Sep 17 00:00:00 2001 From: Eino-Ville Talvala Date: Fri, 18 Jan 2019 17:32:06 -0800 Subject: [PATCH 462/718] Camera: Restructure default camera.provider 2.4 To allow for implementation inheritance of @2.4 legacy wrapper and @2.4 external webcamera HALs in the @2.5 implementations, restructure the existing default provider to separate the service interface into a thin shim that calls the implementations. Test: Camera starts as usual after refactor, VTS tests pass Bug: 121379978 Change-Id: Id40790ed4fb495577fd2b885c706b2ed7a96d64e --- camera/common/1.0/default/CameraModule.cpp | 11 ++ .../common/1.0/default/include/CameraModule.h | 1 + camera/metadata/3.4/Android.bp | 3 + camera/provider/2.4/default/Android.bp | 173 ++++++++++++++---- .../2.4/default/CameraProvider_2_4.cpp | 69 +++++++ .../provider/2.4/default/CameraProvider_2_4.h | 86 +++++++++ ...cpp => ExternalCameraProviderImpl_2_4.cpp} | 45 +++-- ...der.h => ExternalCameraProviderImpl_2_4.h} | 44 +++-- ...r.cpp => LegacyCameraProviderImpl_2_4.cpp} | 92 ++++------ ...vider.h => LegacyCameraProviderImpl_2_4.h} | 43 +++-- camera/provider/2.4/default/service.cpp | 5 +- 11 files changed, 420 insertions(+), 152 deletions(-) create mode 100644 camera/provider/2.4/default/CameraProvider_2_4.cpp create mode 100644 camera/provider/2.4/default/CameraProvider_2_4.h rename camera/provider/2.4/default/{ExternalCameraProvider.cpp => ExternalCameraProviderImpl_2_4.cpp} (88%) rename camera/provider/2.4/default/{ExternalCameraProvider.h => ExternalCameraProviderImpl_2_4.h} (72%) rename camera/provider/2.4/default/{CameraProvider.cpp => LegacyCameraProviderImpl_2_4.cpp} (90%) rename camera/provider/2.4/default/{CameraProvider.h => LegacyCameraProviderImpl_2_4.h} (79%) diff --git a/camera/common/1.0/default/CameraModule.cpp b/camera/common/1.0/default/CameraModule.cpp index 08354b312d..3e3ef433a5 100644 --- a/camera/common/1.0/default/CameraModule.cpp +++ b/camera/common/1.0/default/CameraModule.cpp @@ -462,6 +462,17 @@ int CameraModule::isStreamCombinationSupported(int cameraId, camera_stream_combi return res; } +void CameraModule::notifyDeviceStateChange(uint64_t deviceState) { + if (getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_5 && + mModule->notify_device_state_change != NULL) { + ATRACE_BEGIN("camera_module->notify_device_state_change"); + ALOGI("%s: calling notify_device_state_change with state %" PRId64, __FUNCTION__, + deviceState); + mModule->notify_device_state_change(deviceState); + ATRACE_END(); + } +} + status_t CameraModule::filterOpenErrorCode(status_t err) { switch(err) { case NO_ERROR: diff --git a/camera/common/1.0/default/include/CameraModule.h b/camera/common/1.0/default/include/CameraModule.h index ee75e722d1..32c387f107 100644 --- a/camera/common/1.0/default/include/CameraModule.h +++ b/camera/common/1.0/default/include/CameraModule.h @@ -67,6 +67,7 @@ public: void removeCamera(int cameraId); int getPhysicalCameraInfo(int physicalCameraId, camera_metadata_t **physicalInfo); int isStreamCombinationSupported(int cameraId, camera_stream_combination_t *streams); + void notifyDeviceStateChange(uint64_t deviceState); private: // Derive camera characteristics keys defined after HAL device version diff --git a/camera/metadata/3.4/Android.bp b/camera/metadata/3.4/Android.bp index 388df6848c..17a2675218 100644 --- a/camera/metadata/3.4/Android.bp +++ b/camera/metadata/3.4/Android.bp @@ -15,6 +15,9 @@ hidl_interface { ], types: [ "CameraMetadataEnumAndroidInfoSupportedBufferManagementVersion", + "CameraMetadataEnumAndroidScalerAvailableFormats", + "CameraMetadataEnumAndroidScalerAvailableRecommendedStreamConfigurations", + "CameraMetadataEnumAndroidSensorInfoColorFilterArrangement", "CameraMetadataTag", ], gen_java: true, diff --git a/camera/provider/2.4/default/Android.bp b/camera/provider/2.4/default/Android.bp index 81e5738cee..9d73934de0 100644 --- a/camera/provider/2.4/default/Android.bp +++ b/camera/provider/2.4/default/Android.bp @@ -1,46 +1,126 @@ cc_library_shared { - name: "android.hardware.camera.provider@2.4-impl", + name: "android.hardware.camera.provider@2.4-legacy", defaults: ["hidl_defaults"], proprietary: true, - relative_install_path: "hw", - srcs: ["CameraProvider.cpp", - "ExternalCameraProvider.cpp"], + srcs: ["LegacyCameraProviderImpl_2_4.cpp"], shared_libs: [ - "libhidlbase", - "libhidltransport", - "libutils", - "libcutils", + "android.hardware.camera.common@1.0", "android.hardware.camera.device@1.0", "android.hardware.camera.device@3.2", "android.hardware.camera.device@3.3", "android.hardware.camera.device@3.4", "android.hardware.camera.device@3.5", + "android.hardware.camera.provider@2.4", + "android.hardware.graphics.mapper@2.0", + "android.hidl.allocator@1.0", + "android.hidl.memory@1.0", "camera.device@1.0-impl", "camera.device@3.2-impl", "camera.device@3.3-impl", "camera.device@3.4-impl", "camera.device@3.5-impl", - "camera.device@3.4-external-impl", - "camera.device@3.5-external-impl", - "android.hardware.camera.provider@2.4", - "android.hardware.camera.common@1.0", - "android.hardware.graphics.mapper@2.0", - "android.hidl.allocator@1.0", - "android.hidl.memory@1.0", - "liblog", - "libhardware", "libcamera_metadata", - "libtinyxml2" - ], - header_libs: [ - "camera.device@3.4-impl_headers", - "camera.device@3.5-impl_headers", - "camera.device@3.4-external-impl_headers", - "camera.device@3.5-external-impl_headers" + "libcutils", + "libhardware", + "libhidlbase", + "libhidltransport", + "liblog", + "libutils", ], static_libs: [ "android.hardware.camera.common@1.0-helper", ], + header_libs: [ + "camera.device@3.4-impl_headers", + "camera.device@3.5-impl_headers", + ], + export_include_dirs: ["."], +} + +cc_library_shared { + name: "android.hardware.camera.provider@2.4-external", + proprietary: true, + srcs: ["ExternalCameraProviderImpl_2_4.cpp"], + shared_libs: [ + "android.hardware.camera.common@1.0", + "android.hardware.camera.device@1.0", + "android.hardware.camera.device@3.2", + "android.hardware.camera.device@3.3", + "android.hardware.camera.device@3.4", + "android.hardware.camera.device@3.5", + "android.hardware.camera.provider@2.4", + "android.hardware.graphics.mapper@2.0", + "android.hidl.allocator@1.0", + "android.hidl.memory@1.0", + "camera.device@3.3-impl", + "camera.device@3.4-external-impl", + "camera.device@3.4-impl", + "camera.device@3.5-external-impl", + "camera.device@3.5-impl", + "libcamera_metadata", + "libcutils", + "libhardware", + "libhidlbase", + "libhidltransport", + "liblog", + "libtinyxml2", + "libutils", + ], + static_libs: [ + "android.hardware.camera.common@1.0-helper", + ], + header_libs: [ + "camera.device@3.4-external-impl_headers", + "camera.device@3.5-external-impl_headers" + ], + export_include_dirs: ["."], +} + +cc_library_shared { + name: "android.hardware.camera.provider@2.4-impl", + defaults: ["hidl_defaults"], + proprietary: true, + relative_install_path: "hw", + srcs: ["CameraProvider_2_4.cpp"], + shared_libs: [ + "android.hardware.camera.common@1.0", + "android.hardware.camera.device@1.0", + "android.hardware.camera.device@3.2", + "android.hardware.camera.device@3.3", + "android.hardware.camera.device@3.4", + "android.hardware.camera.device@3.5", + "android.hardware.camera.provider@2.4", + "android.hardware.camera.provider@2.4-external", + "android.hardware.camera.provider@2.4-legacy", + "android.hardware.graphics.mapper@2.0", + "android.hidl.allocator@1.0", + "android.hidl.memory@1.0", + "camera.device@1.0-impl", + "camera.device@3.2-impl", + "camera.device@3.3-impl", + "camera.device@3.4-external-impl", + "camera.device@3.4-impl", + "camera.device@3.5-external-impl", + "camera.device@3.5-impl", + "libcamera_metadata", + "libcutils", + "libhardware", + "libhidlbase", + "libhidltransport", + "liblog", + "libtinyxml2", + "libutils", + ], + header_libs: [ + "camera.device@3.4-external-impl_headers", + "camera.device@3.4-impl_headers", + "camera.device@3.5-external-impl_headers", + "camera.device@3.5-impl_headers", + ], + static_libs: [ + "android.hardware.camera.common@1.0-helper", + ], + export_include_dirs: ["."], } cc_defaults { @@ -50,18 +130,32 @@ cc_defaults { relative_install_path: "hw", srcs: ["service.cpp"], shared_libs: [ - "libhidlbase", - "libhidltransport", - "libbinder", - "liblog", - "libutils", + "android.hardware.camera.common@1.0", "android.hardware.camera.device@1.0", "android.hardware.camera.device@3.2", "android.hardware.camera.device@3.3", "android.hardware.camera.device@3.4", "android.hardware.camera.device@3.5", "android.hardware.camera.provider@2.4", - "android.hardware.camera.common@1.0", + "android.hardware.graphics.mapper@2.0", + "android.hidl.allocator@1.0", + "android.hidl.memory@1.0", + "libbinder", + "libcamera_metadata", + "libhardware", + "libhidlbase", + "libhidltransport", + "liblog", + "libutils", + ], + static_libs: [ + "android.hardware.camera.common@1.0-helper", + ], + header_libs: [ + "camera.device@3.4-external-impl_headers", + "camera.device@3.4-impl_headers", + "camera.device@3.5-external-impl_headers", + "camera.device@3.5-impl_headers", ], } @@ -106,17 +200,24 @@ cc_binary { compile_multilib: "32", init_rc: ["android.hardware.camera.provider@2.4-external-service.rc"], shared_libs: [ - "libhidlbase", - "libhidltransport", - "libbinder", - "liblog", - "libutils", + "android.hardware.camera.common@1.0", "android.hardware.camera.device@1.0", "android.hardware.camera.device@3.2", "android.hardware.camera.device@3.3", "android.hardware.camera.device@3.4", "android.hardware.camera.device@3.5", "android.hardware.camera.provider@2.4", - "android.hardware.camera.common@1.0", + "libbinder", + "libhidlbase", + "libhidltransport", + "liblog", + "libtinyxml2", + "libutils", + ], + header_libs: [ + "camera.device@3.4-external-impl_headers", + "camera.device@3.4-impl_headers", + "camera.device@3.5-external-impl_headers", + "camera.device@3.5-impl_headers", ], } diff --git a/camera/provider/2.4/default/CameraProvider_2_4.cpp b/camera/provider/2.4/default/CameraProvider_2_4.cpp new file mode 100644 index 0000000000..15fc702aa5 --- /dev/null +++ b/camera/provider/2.4/default/CameraProvider_2_4.cpp @@ -0,0 +1,69 @@ +/* + * Copyright 2019 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 "CameraProvider_2_4.h" +#include "LegacyCameraProviderImpl_2_4.h" +#include "ExternalCameraProviderImpl_2_4.h" + +const char *kLegacyProviderName = "legacy/0"; +const char *kExternalProviderName = "external/0"; + +namespace android { +namespace hardware { +namespace camera { +namespace provider { +namespace V2_4 { +namespace implementation { + +using android::hardware::camera::provider::V2_4::ICameraProvider; + +extern "C" ICameraProvider* HIDL_FETCH_ICameraProvider(const char* name); + +template +CameraProvider* getProviderImpl() { + CameraProvider *provider = new CameraProvider(); + if (provider == nullptr) { + ALOGE("%s: cannot allocate camera provider!", __FUNCTION__); + return nullptr; + } + if (provider->isInitFailed()) { + ALOGE("%s: camera provider init failed!", __FUNCTION__); + delete provider; + return nullptr; + } + return provider; +} + +ICameraProvider* HIDL_FETCH_ICameraProvider(const char* name) { + using namespace android::hardware::camera::provider::V2_4::implementation; + ICameraProvider* provider = nullptr; + if (strcmp(name, kLegacyProviderName) == 0) { + provider = getProviderImpl(); + } else if (strcmp(name, kExternalProviderName) == 0) { + provider = getProviderImpl(); + } else { + ALOGE("%s: unknown instance name: %s", __FUNCTION__, name); + } + + return provider; +} + +} // namespace implementation +} // namespace V2_4 +} // namespace provider +} // namespace camera +} // namespace hardware +} // namespace android diff --git a/camera/provider/2.4/default/CameraProvider_2_4.h b/camera/provider/2.4/default/CameraProvider_2_4.h new file mode 100644 index 0000000000..d2e5b942d3 --- /dev/null +++ b/camera/provider/2.4/default/CameraProvider_2_4.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_CAMERA_PROVIDER_V2_4_CAMERAPROVIDER_H +#define ANDROID_HARDWARE_CAMERA_PROVIDER_V2_4_CAMERAPROVIDER_H + +#include +#include +#include + +namespace android { +namespace hardware { +namespace camera { +namespace provider { +namespace V2_4 { +namespace implementation { + +using ::android::hardware::camera::common::V1_0::Status; +using ::android::hardware::camera::provider::V2_4::ICameraProvider; +using ::android::hardware::camera::provider::V2_4::ICameraProviderCallback; +using ::android::hardware::Return; +using ::android::hardware::hidl_string; +using ::android::sp; + +template +struct CameraProvider : public ICameraProvider { + CameraProvider() : impl() {} + ~CameraProvider() {} + + // Caller must use this method to check if CameraProvider ctor failed + bool isInitFailed() { return impl.isInitFailed(); } + + // Methods from ::android::hardware::camera::provider::V2_4::ICameraProvider follow. + Return setCallback(const sp& callback) override { + return impl.setCallback(callback); + } + + Return getVendorTags(getVendorTags_cb _hidl_cb) override { + return impl.getVendorTags(_hidl_cb); + } + + Return getCameraIdList(getCameraIdList_cb _hidl_cb) override { + return impl.getCameraIdList(_hidl_cb); + } + + Return isSetTorchModeSupported(isSetTorchModeSupported_cb _hidl_cb) override { + return impl.isSetTorchModeSupported(_hidl_cb); + } + + Return getCameraDeviceInterface_V1_x( + const hidl_string& cameraDeviceName, + getCameraDeviceInterface_V1_x_cb _hidl_cb) override { + return impl.getCameraDeviceInterface_V1_x(cameraDeviceName, _hidl_cb); + } + + Return getCameraDeviceInterface_V3_x( + const hidl_string& cameraDeviceName, + getCameraDeviceInterface_V3_x_cb _hidl_cb) override { + return impl.getCameraDeviceInterface_V3_x(cameraDeviceName, _hidl_cb); + } + +private: + IMPL impl; +}; + +} // namespace implementation +} // namespace V2_4 +} // namespace provider +} // namespace camera +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_CAMERA_PROVIDER_V2_4_CAMERAPROVIDER_H diff --git a/camera/provider/2.4/default/ExternalCameraProvider.cpp b/camera/provider/2.4/default/ExternalCameraProviderImpl_2_4.cpp similarity index 88% rename from camera/provider/2.4/default/ExternalCameraProvider.cpp rename to camera/provider/2.4/default/ExternalCameraProviderImpl_2_4.cpp index 604df5c0cf..a6fd288125 100644 --- a/camera/provider/2.4/default/ExternalCameraProvider.cpp +++ b/camera/provider/2.4/default/ExternalCameraProviderImpl_2_4.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#define LOG_TAG "CamPvdr@2.4-external" +#define LOG_TAG "CamPrvdr@2.4-external" //#define LOG_NDEBUG 0 #include @@ -22,10 +22,10 @@ #include #include #include -#include "ExternalCameraProvider.h" +#include +#include "ExternalCameraProviderImpl_2_4.h" #include "ExternalCameraDevice_3_4.h" #include "ExternalCameraDevice_3_5.h" -#include namespace android { namespace hardware { @@ -34,6 +34,8 @@ namespace provider { namespace V2_4 { namespace implementation { +template struct CameraProvider; + namespace { // "device@/external/" const std::regex kDeviceNameRE("device@([0-9]+\\.[0-9]+)/external/(.+)"); @@ -60,7 +62,7 @@ bool matchDeviceName(const hidl_string& deviceName, std::string* deviceVersion, } // anonymous namespace -ExternalCameraProvider::ExternalCameraProvider() : +ExternalCameraProviderImpl_2_4::ExternalCameraProviderImpl_2_4() : mCfg(ExternalCameraConfig::loadFromCfg()), mHotPlugThread(this) { mHotPlugThread.run("ExtCamHotPlug", PRIORITY_BACKGROUND); @@ -81,12 +83,12 @@ ExternalCameraProvider::ExternalCameraProvider() : } } -ExternalCameraProvider::~ExternalCameraProvider() { +ExternalCameraProviderImpl_2_4::~ExternalCameraProviderImpl_2_4() { mHotPlugThread.requestExit(); } -Return ExternalCameraProvider::setCallback( +Return ExternalCameraProviderImpl_2_4::setCallback( const sp& callback) { { Mutex::Autolock _l(mLock); @@ -105,14 +107,16 @@ Return ExternalCameraProvider::setCallback( return Status::OK; } -Return ExternalCameraProvider::getVendorTags(getVendorTags_cb _hidl_cb) { +Return ExternalCameraProviderImpl_2_4::getVendorTags( + ICameraProvider::getVendorTags_cb _hidl_cb) { // No vendor tag support for USB camera hidl_vec zeroSections; _hidl_cb(Status::OK, zeroSections); return Void(); } -Return ExternalCameraProvider::getCameraIdList(getCameraIdList_cb _hidl_cb) { +Return ExternalCameraProviderImpl_2_4::getCameraIdList( + ICameraProvider::getCameraIdList_cb _hidl_cb) { // External camera HAL always report 0 camera, and extra cameras // are just reported via cameraDeviceStatusChange callbacks hidl_vec hidlDeviceNameList; @@ -120,25 +124,25 @@ Return ExternalCameraProvider::getCameraIdList(getCameraIdList_cb _hidl_cb return Void(); } -Return ExternalCameraProvider::isSetTorchModeSupported( - isSetTorchModeSupported_cb _hidl_cb) { +Return ExternalCameraProviderImpl_2_4::isSetTorchModeSupported( + ICameraProvider::isSetTorchModeSupported_cb _hidl_cb) { // setTorchMode API is supported, though right now no external camera device // has a flash unit. _hidl_cb (Status::OK, true); return Void(); } -Return ExternalCameraProvider::getCameraDeviceInterface_V1_x( +Return ExternalCameraProviderImpl_2_4::getCameraDeviceInterface_V1_x( const hidl_string&, - getCameraDeviceInterface_V1_x_cb _hidl_cb) { + ICameraProvider::getCameraDeviceInterface_V1_x_cb _hidl_cb) { // External Camera HAL does not support HAL1 _hidl_cb(Status::OPERATION_NOT_SUPPORTED, nullptr); return Void(); } -Return ExternalCameraProvider::getCameraDeviceInterface_V3_x( +Return ExternalCameraProviderImpl_2_4::getCameraDeviceInterface_V3_x( const hidl_string& cameraDeviceName, - getCameraDeviceInterface_V3_x_cb _hidl_cb) { + ICameraProvider::getCameraDeviceInterface_V3_x_cb _hidl_cb) { std::string cameraId, deviceVersion; bool match = matchDeviceName(cameraDeviceName, &deviceVersion, &cameraId); @@ -194,7 +198,7 @@ Return ExternalCameraProvider::getCameraDeviceInterface_V3_x( return Void(); } -void ExternalCameraProvider::addExternalCamera(const char* devName) { +void ExternalCameraProviderImpl_2_4::addExternalCamera(const char* devName) { ALOGI("ExtCam: adding %s to External Camera HAL!", devName); Mutex::Autolock _l(mLock); std::string deviceName; @@ -209,7 +213,7 @@ void ExternalCameraProvider::addExternalCamera(const char* devName) { } } -void ExternalCameraProvider::deviceAdded(const char* devName) { +void ExternalCameraProviderImpl_2_4::deviceAdded(const char* devName) { { base::unique_fd fd(::open(devName, O_RDWR)); if (fd.get() < 0) { @@ -242,7 +246,7 @@ void ExternalCameraProvider::deviceAdded(const char* devName) { return; } -void ExternalCameraProvider::deviceRemoved(const char* devName) { +void ExternalCameraProviderImpl_2_4::deviceRemoved(const char* devName) { Mutex::Autolock _l(mLock); std::string deviceName; if (mPreferredHal3MinorVersion == 5) { @@ -260,14 +264,15 @@ void ExternalCameraProvider::deviceRemoved(const char* devName) { } } -ExternalCameraProvider::HotplugThread::HotplugThread(ExternalCameraProvider* parent) : +ExternalCameraProviderImpl_2_4::HotplugThread::HotplugThread( + ExternalCameraProviderImpl_2_4* parent) : Thread(/*canCallJava*/false), mParent(parent), mInternalDevices(parent->mCfg.mInternalDevices) {} -ExternalCameraProvider::HotplugThread::~HotplugThread() {} +ExternalCameraProviderImpl_2_4::HotplugThread::~HotplugThread() {} -bool ExternalCameraProvider::HotplugThread::threadLoop() { +bool ExternalCameraProviderImpl_2_4::HotplugThread::threadLoop() { // Find existing /dev/video* devices DIR* devdir = opendir(kDevicePath); if(devdir == 0) { diff --git a/camera/provider/2.4/default/ExternalCameraProvider.h b/camera/provider/2.4/default/ExternalCameraProviderImpl_2_4.h similarity index 72% rename from camera/provider/2.4/default/ExternalCameraProvider.h rename to camera/provider/2.4/default/ExternalCameraProviderImpl_2_4.h index a69cf8bcf1..8c79f68f10 100644 --- a/camera/provider/2.4/default/ExternalCameraProvider.h +++ b/camera/provider/2.4/default/ExternalCameraProviderImpl_2_4.h @@ -20,13 +20,14 @@ #include #include #include -#include "utils/Mutex.h" -#include "utils/Thread.h" -#include +#include +#include #include #include #include "ExternalCameraUtils.h" +#include "CameraProvider_2_4.h" + namespace android { namespace hardware { namespace camera { @@ -47,25 +48,32 @@ using ::android::hardware::hidl_string; using ::android::sp; using ::android::Mutex; -struct ExternalCameraProvider : public ICameraProvider { - ExternalCameraProvider(); - ~ExternalCameraProvider(); +/** + * The implementation of external webcam CameraProvider 2.4, separated + * from the HIDL interface layer to allow for implementation reuse by later + * provider versions. + * + * This camera provider supports standard UVC webcameras via the Linux V4L2 + * UVC driver. + */ +struct ExternalCameraProviderImpl_2_4 { + ExternalCameraProviderImpl_2_4(); + ~ExternalCameraProviderImpl_2_4(); + + // Caller must use this method to check if CameraProvider ctor failed + bool isInitFailed() { return false;} // Methods from ::android::hardware::camera::provider::V2_4::ICameraProvider follow. - Return setCallback(const sp& callback) override; - - Return getVendorTags(getVendorTags_cb _hidl_cb) override; - - Return getCameraIdList(getCameraIdList_cb _hidl_cb) override; - - Return isSetTorchModeSupported(isSetTorchModeSupported_cb _hidl_cb) override; - + Return setCallback(const sp& callback); + Return getVendorTags(ICameraProvider::getVendorTags_cb _hidl_cb); + Return getCameraIdList(ICameraProvider::getCameraIdList_cb _hidl_cb); + Return isSetTorchModeSupported(ICameraProvider::isSetTorchModeSupported_cb _hidl_cb); Return getCameraDeviceInterface_V1_x( const hidl_string&, - getCameraDeviceInterface_V1_x_cb) override; + ICameraProvider::getCameraDeviceInterface_V1_x_cb); Return getCameraDeviceInterface_V3_x( const hidl_string&, - getCameraDeviceInterface_V3_x_cb) override; + ICameraProvider::getCameraDeviceInterface_V3_x_cb); private: @@ -77,13 +85,13 @@ private: class HotplugThread : public android::Thread { public: - HotplugThread(ExternalCameraProvider* parent); + HotplugThread(ExternalCameraProviderImpl_2_4* parent); ~HotplugThread(); virtual bool threadLoop() override; private: - ExternalCameraProvider* mParent = nullptr; + ExternalCameraProviderImpl_2_4* mParent = nullptr; const std::unordered_set mInternalDevices; int mINotifyFD = -1; diff --git a/camera/provider/2.4/default/CameraProvider.cpp b/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.cpp similarity index 90% rename from camera/provider/2.4/default/CameraProvider.cpp rename to camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.cpp index e02cc7e490..4cff1b79a1 100644 --- a/camera/provider/2.4/default/CameraProvider.cpp +++ b/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.cpp @@ -14,21 +14,21 @@ * limitations under the License. */ -#define LOG_TAG "CamProvider@2.4-impl" +#define LOG_TAG "CamPrvdr@2.4-legacy" //#define LOG_NDEBUG 0 #include -#include "CameraProvider.h" -#include "ExternalCameraProvider.h" +#include "LegacyCameraProviderImpl_2_4.h" #include "CameraDevice_1_0.h" #include "CameraDevice_3_3.h" #include "CameraDevice_3_4.h" #include "CameraDevice_3_5.h" +#include "CameraProvider_2_4.h" #include +#include #include #include - namespace android { namespace hardware { namespace camera { @@ -36,9 +36,9 @@ namespace provider { namespace V2_4 { namespace implementation { +template struct CameraProvider; + namespace { -const char *kLegacyProviderName = "legacy/0"; -const char *kExternalProviderName = "external/0"; // "device@/legacy/" const std::regex kDeviceNameRE("device@([0-9]+\\.[0-9]+)/legacy/(.+)"); const char *kHAL3_4 = "3.4"; @@ -67,7 +67,7 @@ bool matchDeviceName(const hidl_string& deviceName, std::string* deviceVersion, using ::android::hardware::camera::common::V1_0::CameraMetadataType; using ::android::hardware::camera::common::V1_0::Status; -void CameraProvider::addDeviceNames(int camera_id, CameraDeviceStatus status, bool cam_new) +void LegacyCameraProviderImpl_2_4::addDeviceNames(int camera_id, CameraDeviceStatus status, bool cam_new) { char cameraId[kMaxCameraIdLen]; snprintf(cameraId, sizeof(cameraId), "%d", camera_id); @@ -107,7 +107,7 @@ void CameraProvider::addDeviceNames(int camera_id, CameraDeviceStatus status, bo } } -void CameraProvider::removeDeviceNames(int camera_id) +void LegacyCameraProviderImpl_2_4::removeDeviceNames(int camera_id) { std::string cameraIdStr = std::to_string(camera_id); @@ -134,13 +134,12 @@ void CameraProvider::removeDeviceNames(int camera_id) /** * static callback forwarding methods from HAL to instance */ -void CameraProvider::sCameraDeviceStatusChange( +void LegacyCameraProviderImpl_2_4::sCameraDeviceStatusChange( const struct camera_module_callbacks* callbacks, int camera_id, int new_status) { - CameraProvider* cp = const_cast( - static_cast(callbacks)); - + LegacyCameraProviderImpl_2_4* cp = const_cast( + static_cast(callbacks)); if (cp == nullptr) { ALOGE("%s: callback ops is null", __FUNCTION__); return; @@ -181,12 +180,12 @@ void CameraProvider::sCameraDeviceStatusChange( } } -void CameraProvider::sTorchModeStatusChange( +void LegacyCameraProviderImpl_2_4::sTorchModeStatusChange( const struct camera_module_callbacks* callbacks, const char* camera_id, int new_status) { - CameraProvider* cp = const_cast( - static_cast(callbacks)); + LegacyCameraProviderImpl_2_4* cp = const_cast( + static_cast(callbacks)); if (cp == nullptr) { ALOGE("%s: callback ops is null", __FUNCTION__); @@ -206,7 +205,7 @@ void CameraProvider::sTorchModeStatusChange( } } -Status CameraProvider::getHidlStatus(int status) { +Status LegacyCameraProviderImpl_2_4::getHidlStatus(int status) { switch (status) { case 0: return Status::OK; case -ENODEV: return Status::INTERNAL_ERROR; @@ -217,13 +216,13 @@ Status CameraProvider::getHidlStatus(int status) { } } -std::string CameraProvider::getLegacyCameraId(const hidl_string& deviceName) { +std::string LegacyCameraProviderImpl_2_4::getLegacyCameraId(const hidl_string& deviceName) { std::string cameraId; matchDeviceName(deviceName, nullptr, &cameraId); return cameraId; } -std::string CameraProvider::getHidlDeviceName( +std::string LegacyCameraProviderImpl_2_4::getHidlDeviceName( std::string cameraId, int deviceVersion) { // Maybe consider create a version check method and SortedVec to speed up? if (deviceVersion != CAMERA_DEVICE_API_VERSION_1_0 && @@ -258,15 +257,15 @@ std::string CameraProvider::getHidlDeviceName( return deviceName; } -CameraProvider::CameraProvider() : +LegacyCameraProviderImpl_2_4::LegacyCameraProviderImpl_2_4() : camera_module_callbacks_t({sCameraDeviceStatusChange, sTorchModeStatusChange}) { mInitFailed = initialize(); } -CameraProvider::~CameraProvider() {} +LegacyCameraProviderImpl_2_4::~LegacyCameraProviderImpl_2_4() {} -bool CameraProvider::initialize() { +bool LegacyCameraProviderImpl_2_4::initialize() { camera_module_t *rawModule; int err = hw_get_module(CAMERA_HARDWARE_MODULE_ID, (const hw_module_t **)&rawModule); @@ -343,7 +342,7 @@ bool CameraProvider::initialize() { /** * Check that the device HAL version is still in supported. */ -int CameraProvider::checkCameraVersion(int id, camera_info info) { +int LegacyCameraProviderImpl_2_4::checkCameraVersion(int id, camera_info info) { if (mModule == nullptr) { return NO_INIT; } @@ -390,7 +389,7 @@ int CameraProvider::checkCameraVersion(int id, camera_info info) { return OK; } -bool CameraProvider::setUpVendorTags() { +bool LegacyCameraProviderImpl_2_4::setUpVendorTags() { ATRACE_CALL(); vendor_tag_ops_t vOps = vendor_tag_ops_t(); @@ -447,11 +446,8 @@ bool CameraProvider::setUpVendorTags() { } // Methods from ::android::hardware::camera::provider::V2_4::ICameraProvider follow. -Return CameraProvider::setCallback(const sp& callback) { - if (callback == nullptr) { - return Status::ILLEGAL_ARGUMENT; - } - +Return LegacyCameraProviderImpl_2_4::setCallback( + const sp& callback) { Mutex::Autolock _l(mCbLock); mCallbacks = callback; @@ -467,12 +463,14 @@ Return CameraProvider::setCallback(const sp& ca return Status::OK; } -Return CameraProvider::getVendorTags(getVendorTags_cb _hidl_cb) { +Return LegacyCameraProviderImpl_2_4::getVendorTags( + ICameraProvider::getVendorTags_cb _hidl_cb) { _hidl_cb(Status::OK, mVendorTagSections); return Void(); } -Return CameraProvider::getCameraIdList(getCameraIdList_cb _hidl_cb) { +Return LegacyCameraProviderImpl_2_4::getCameraIdList( + ICameraProvider::getCameraIdList_cb _hidl_cb) { std::vector deviceNameList; for (auto const& deviceNamePair : mCameraDeviceNames) { if (std::stoi(deviceNamePair.first) >= mNumberOfLegacyCameras) { @@ -489,14 +487,16 @@ Return CameraProvider::getCameraIdList(getCameraIdList_cb _hidl_cb) { return Void(); } -Return CameraProvider::isSetTorchModeSupported(isSetTorchModeSupported_cb _hidl_cb) { +Return LegacyCameraProviderImpl_2_4::isSetTorchModeSupported( + ICameraProvider::isSetTorchModeSupported_cb _hidl_cb) { bool support = mModule->isSetTorchModeSupported(); _hidl_cb (Status::OK, support); return Void(); } -Return CameraProvider::getCameraDeviceInterface_V1_x( - const hidl_string& cameraDeviceName, getCameraDeviceInterface_V1_x_cb _hidl_cb) { +Return LegacyCameraProviderImpl_2_4::getCameraDeviceInterface_V1_x( + const hidl_string& cameraDeviceName, + ICameraProvider::getCameraDeviceInterface_V1_x_cb _hidl_cb) { std::string cameraId, deviceVersion; bool match = matchDeviceName(cameraDeviceName, &deviceVersion, &cameraId); if (!match) { @@ -548,8 +548,9 @@ Return CameraProvider::getCameraDeviceInterface_V1_x( return Void(); } -Return CameraProvider::getCameraDeviceInterface_V3_x( - const hidl_string& cameraDeviceName, getCameraDeviceInterface_V3_x_cb _hidl_cb) { +Return LegacyCameraProviderImpl_2_4::getCameraDeviceInterface_V3_x( + const hidl_string& cameraDeviceName, + ICameraProvider::getCameraDeviceInterface_V3_x_cb _hidl_cb) { std::string cameraId, deviceVersion; bool match = matchDeviceName(cameraDeviceName, &deviceVersion, &cameraId); if (!match) { @@ -647,27 +648,6 @@ Return CameraProvider::getCameraDeviceInterface_V3_x( return Void(); } -ICameraProvider* HIDL_FETCH_ICameraProvider(const char* name) { - if (strcmp(name, kLegacyProviderName) == 0) { - CameraProvider* provider = new CameraProvider(); - if (provider == nullptr) { - ALOGE("%s: cannot allocate camera provider!", __FUNCTION__); - return nullptr; - } - if (provider->isInitFailed()) { - ALOGE("%s: camera provider init failed!", __FUNCTION__); - delete provider; - return nullptr; - } - return provider; - } else if (strcmp(name, kExternalProviderName) == 0) { - ExternalCameraProvider* provider = new ExternalCameraProvider(); - return provider; - } - ALOGE("%s: unknown instance name: %s", __FUNCTION__, name); - return nullptr; -} - } // namespace implementation } // namespace V2_4 } // namespace provider diff --git a/camera/provider/2.4/default/CameraProvider.h b/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.h similarity index 79% rename from camera/provider/2.4/default/CameraProvider.h rename to camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.h index 10e9b0d276..b4914b3cfe 100644 --- a/camera/provider/2.4/default/CameraProvider.h +++ b/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.h @@ -14,16 +14,14 @@ * limitations under the License. */ -#ifndef ANDROID_HARDWARE_CAMERA_PROVIDER_V2_4_CAMERAPROVIDER_H -#define ANDROID_HARDWARE_CAMERA_PROVIDER_V2_4_CAMERAPROVIDER_H +#ifndef ANDROID_HARDWARE_CAMERA_PROVIDER_V2_4_LEGACYCAMERAPROVIDER_H +#define ANDROID_HARDWARE_CAMERA_PROVIDER_V2_4_LEGACYCAMERAPROVIDER_H -#include +#include #include "hardware/camera_common.h" #include "utils/Mutex.h" #include "utils/SortedVector.h" -#include -#include -#include + #include "CameraModule.h" #include "VendorTagDescriptor.h" @@ -50,26 +48,34 @@ using ::android::hardware::hidl_string; using ::android::sp; using ::android::Mutex; -struct CameraProvider : public ICameraProvider, public camera_module_callbacks_t { - CameraProvider(); - ~CameraProvider(); +/** + * The implementation of legacy wrapper CameraProvider 2.4, separated + * from the HIDL interface layer to allow for implementation reuse by later + * provider versions. + * + * This implementation supports cameras implemented via the legacy libhardware + * camera HAL definitions. + */ +struct LegacyCameraProviderImpl_2_4 : public camera_module_callbacks_t { + LegacyCameraProviderImpl_2_4(); + ~LegacyCameraProviderImpl_2_4(); // Caller must use this method to check if CameraProvider ctor failed bool isInitFailed() { return mInitFailed; } // Methods from ::android::hardware::camera::provider::V2_4::ICameraProvider follow. - Return setCallback(const sp& callback) override; - Return getVendorTags(getVendorTags_cb _hidl_cb) override; - Return getCameraIdList(getCameraIdList_cb _hidl_cb) override; - Return isSetTorchModeSupported(isSetTorchModeSupported_cb _hidl_cb) override; + Return setCallback(const sp& callback); + Return getVendorTags(ICameraProvider::getVendorTags_cb _hidl_cb); + Return getCameraIdList(ICameraProvider::getCameraIdList_cb _hidl_cb); + Return isSetTorchModeSupported(ICameraProvider::isSetTorchModeSupported_cb _hidl_cb); Return getCameraDeviceInterface_V1_x( const hidl_string& cameraDeviceName, - getCameraDeviceInterface_V1_x_cb _hidl_cb) override; + ICameraProvider::getCameraDeviceInterface_V1_x_cb _hidl_cb); Return getCameraDeviceInterface_V3_x( const hidl_string& cameraDeviceName, - getCameraDeviceInterface_V3_x_cb _hidl_cb) override; + ICameraProvider::getCameraDeviceInterface_V3_x_cb _hidl_cb); -private: +protected: Mutex mCbLock; sp mCallbacks = nullptr; @@ -115,9 +121,8 @@ private: void addDeviceNames(int camera_id, CameraDeviceStatus status = CameraDeviceStatus::PRESENT, bool cam_new = false); void removeDeviceNames(int camera_id); -}; -extern "C" ICameraProvider* HIDL_FETCH_ICameraProvider(const char* name); +}; } // namespace implementation } // namespace V2_4 @@ -126,4 +131,4 @@ extern "C" ICameraProvider* HIDL_FETCH_ICameraProvider(const char* name); } // namespace hardware } // namespace android -#endif // ANDROID_HARDWARE_CAMERA_PROVIDER_V2_4_CAMERAPROVIDER_H +#endif // ANDROID_HARDWARE_CAMERA_PROVIDER_V2_4_LEGACYCAMERAPROVIDER_H diff --git a/camera/provider/2.4/default/service.cpp b/camera/provider/2.4/default/service.cpp index 15d0ea6371..4475f7d981 100644 --- a/camera/provider/2.4/default/service.cpp +++ b/camera/provider/2.4/default/service.cpp @@ -21,9 +21,8 @@ #endif #include -#include - #include +#include using android::status_t; using android::hardware::defaultLazyPassthroughServiceImplementation; @@ -38,7 +37,7 @@ const bool kLazyService = false; int main() { - ALOGI("Camera provider Service is starting."); + ALOGI("CameraProvider@2.4 legacy service is starting."); // The camera HAL may communicate to other vendor components via // /dev/vndbinder android::ProcessState::initWithDriver("/dev/vndbinder"); From aa04b3ba106392e4c5dfb33d4f3c6c26f48a7d6d Mon Sep 17 00:00:00 2001 From: Eino-Ville Talvala Date: Fri, 18 Jan 2019 17:33:14 -0800 Subject: [PATCH 463/718] Camera: Add default 2.5 provider for legacy and external webcam HALs Add 2.5 implementations, which do not support passthrough mode and therefore doesn't need the HIDL_Fetch methods or a specially-named -impl library in the /hw directory. Instead, the service directly instantiates the necessary service. Also add VTS tests for the new notification Test: Verify device state changes are logged by HAL Test: Camera starts as usual with both 2.4 and 2.5 providers on walleye. Camera CTS completes. Test: New VTS tests pass Bug: 121379978 Change-Id: I0fc99379eb7e01c5b2efb20afb5753bb6ce8b627 --- camera/provider/2.4/vts/functional/Android.bp | 1 + .../VtsHalCameraProviderV2_4TargetTest.cpp | 35 ++++ camera/provider/2.5/default/Android.bp | 187 ++++++++++++++++++ .../provider/2.5/default/CameraProvider_2_5.h | 94 +++++++++ .../ExternalCameraProviderImpl_2_5.cpp | 47 +++++ .../default/ExternalCameraProviderImpl_2_5.h | 62 ++++++ .../default/LegacyCameraProviderImpl_2_5.cpp | 53 +++++ .../default/LegacyCameraProviderImpl_2_5.h | 62 ++++++ camera/provider/2.5/default/OWNERS | 7 + ...re.camera.provider@2.5-external-service.rc | 9 + ...rdware.camera.provider@2.5-service-lazy.rc | 11 ++ ...are.camera.provider@2.5-service-lazy_64.rc | 11 ++ ...id.hardware.camera.provider@2.5-service.rc | 9 + ...hardware.camera.provider@2.5-service_64.rc | 9 + .../provider/2.5/default/external-service.cpp | 46 +++++ camera/provider/2.5/default/service.cpp | 63 ++++++ 16 files changed, 706 insertions(+) create mode 100644 camera/provider/2.5/default/Android.bp create mode 100644 camera/provider/2.5/default/CameraProvider_2_5.h create mode 100644 camera/provider/2.5/default/ExternalCameraProviderImpl_2_5.cpp create mode 100644 camera/provider/2.5/default/ExternalCameraProviderImpl_2_5.h create mode 100644 camera/provider/2.5/default/LegacyCameraProviderImpl_2_5.cpp create mode 100644 camera/provider/2.5/default/LegacyCameraProviderImpl_2_5.h create mode 100644 camera/provider/2.5/default/OWNERS create mode 100644 camera/provider/2.5/default/android.hardware.camera.provider@2.5-external-service.rc create mode 100644 camera/provider/2.5/default/android.hardware.camera.provider@2.5-service-lazy.rc create mode 100644 camera/provider/2.5/default/android.hardware.camera.provider@2.5-service-lazy_64.rc create mode 100644 camera/provider/2.5/default/android.hardware.camera.provider@2.5-service.rc create mode 100644 camera/provider/2.5/default/android.hardware.camera.provider@2.5-service_64.rc create mode 100644 camera/provider/2.5/default/external-service.cpp create mode 100644 camera/provider/2.5/default/service.cpp diff --git a/camera/provider/2.4/vts/functional/Android.bp b/camera/provider/2.4/vts/functional/Android.bp index f8f058e26b..5fb1fd852d 100644 --- a/camera/provider/2.4/vts/functional/Android.bp +++ b/camera/provider/2.4/vts/functional/Android.bp @@ -40,6 +40,7 @@ cc_test { "android.hardware.camera.device@3.5", "android.hardware.camera.metadata@3.4", "android.hardware.camera.provider@2.4", + "android.hardware.camera.provider@2.5", "android.hardware.graphics.allocator@2.0", "android.hardware.graphics.common@1.0", "android.hardware.graphics.mapper@2.0", diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp index 211240a06b..5965cc1bd4 100644 --- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp +++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -65,6 +66,7 @@ using namespace ::android::hardware::camera::device; using ::android::hardware::Return; using ::android::hardware::Void; +using ::android::hardware::hidl_bitfield; using ::android::hardware::hidl_handle; using ::android::hardware::hidl_string; using ::android::hardware::hidl_vec; @@ -543,6 +545,9 @@ public: uint32_t id; ASSERT_TRUE(parseProviderName(service_name, &mProviderType, &id)); + + castProvider(mProvider, &mProvider2_5); + notifyDeviceState(provider::V2_5::DeviceState::NORMAL); } virtual void TearDown() override {} @@ -680,6 +685,8 @@ public: CameraHidlTest *mParent; // Parent object }; + void notifyDeviceState(::android::hardware::camera::provider::V2_5::DeviceState newState); + void openCameraDevice(const std::string &name, sp provider, sp<::android::hardware::camera::device::V1_0::ICameraDevice> *device /*out*/); void setupPreviewWindow( @@ -709,6 +716,8 @@ public: sp *session /*out*/, camera_metadata_t **staticMeta /*out*/, ::android::sp *device = nullptr/*out*/); + void castProvider(const sp &provider, + sp *provider2_5 /*out*/); void castSession(const sp &session, int32_t deviceVersion, sp *session3_3 /*out*/, sp *session3_4 /*out*/, @@ -898,6 +907,8 @@ protected: // Camera provider service sp mProvider; + sp<::android::hardware::camera::provider::V2_5::ICameraProvider> mProvider2_5; + // Camera provider type. std::string mProviderType; }; @@ -4681,6 +4692,13 @@ TEST_F(CameraHidlTest, flushEmpty) { } } +// Test camera provider@2.5 notify method +TEST_F(CameraHidlTest, providerDeviceStateNotification) { + + notifyDeviceState(provider::V2_5::DeviceState::BACK_COVERED); + notifyDeviceState(provider::V2_5::DeviceState::NORMAL); +} + // Retrieve all valid output stream resolutions from the camera // static characteristics. Status CameraHidlTest::getAvailableOutputStreams(camera_metadata_t *staticMeta, @@ -5362,6 +5380,16 @@ void CameraHidlTest::castDevice(const sp &device, } } +//Cast camera provider to corresponding version if available +void CameraHidlTest::castProvider(const sp &provider, + sp *provider2_5 /*out*/) { + ASSERT_NE(nullptr, provider2_5); + auto castResult = provider::V2_5::ICameraProvider::castFrom(provider); + if (castResult.isOk()) { + *provider2_5 = castResult; + } +} + //Cast camera device session to corresponding version void CameraHidlTest::castSession(const sp &session, int32_t deviceVersion, sp *session3_3 /*out*/, @@ -5774,6 +5802,13 @@ void CameraHidlTest::openEmptyDeviceSession(const std::string &name, spnotifyDeviceStateChange( + static_cast>(newState)); +} + // Open a particular camera device. void CameraHidlTest::openCameraDevice(const std::string &name, sp provider, diff --git a/camera/provider/2.5/default/Android.bp b/camera/provider/2.5/default/Android.bp new file mode 100644 index 0000000000..cd1caebe37 --- /dev/null +++ b/camera/provider/2.5/default/Android.bp @@ -0,0 +1,187 @@ +cc_library_shared { + name: "android.hardware.camera.provider@2.5-legacy", + proprietary: true, + srcs: ["LegacyCameraProviderImpl_2_5.cpp"], + shared_libs: [ + "android.hardware.camera.common@1.0", + "android.hardware.camera.device@1.0", + "android.hardware.camera.device@3.2", + "android.hardware.camera.device@3.3", + "android.hardware.camera.device@3.4", + "android.hardware.camera.device@3.5", + "android.hardware.camera.provider@2.4", + "android.hardware.camera.provider@2.4-legacy", + "android.hardware.camera.provider@2.5", + "android.hardware.graphics.mapper@2.0", + "android.hidl.allocator@1.0", + "android.hidl.memory@1.0", + "camera.device@1.0-impl", + "camera.device@3.2-impl", + "camera.device@3.3-impl", + "camera.device@3.4-impl", + "camera.device@3.5-impl", + "libcamera_metadata", + "libcutils", + "libhardware", + "libhidlbase", + "libhidltransport", + "liblog", + "libutils", + ], + static_libs: [ + "android.hardware.camera.common@1.0-helper", + ], + header_libs: [ + "camera.device@3.4-impl_headers", + "camera.device@3.5-impl_headers", + ], + export_include_dirs: ["."], +} + +cc_library_shared { + name: "android.hardware.camera.provider@2.5-external", + proprietary: true, + srcs: ["ExternalCameraProviderImpl_2_5.cpp"], + shared_libs: [ + "android.hardware.camera.common@1.0", + "android.hardware.camera.device@1.0", + "android.hardware.camera.device@3.2", + "android.hardware.camera.device@3.3", + "android.hardware.camera.device@3.4", + "android.hardware.camera.device@3.5", + "android.hardware.camera.provider@2.4", + "android.hardware.camera.provider@2.4-external", + "android.hardware.camera.provider@2.5", + "android.hardware.graphics.mapper@2.0", + "android.hidl.allocator@1.0", + "android.hidl.memory@1.0", + "camera.device@3.3-impl", + "camera.device@3.4-external-impl", + "camera.device@3.4-impl", + "camera.device@3.5-external-impl", + "camera.device@3.5-impl", + "libcamera_metadata", + "libcutils", + "libhardware", + "libhidlbase", + "libhidltransport", + "liblog", + "libtinyxml2", + "libutils", + ], + static_libs: [ + "android.hardware.camera.common@1.0-helper", + ], + header_libs: [ + "camera.device@3.4-external-impl_headers", + "camera.device@3.5-external-impl_headers" + ], + export_include_dirs: ["."], +} + +cc_defaults { + name: "camera_service_2_5_defaults", + defaults: ["hidl_defaults"], + proprietary: true, + relative_install_path: "hw", + srcs: ["service.cpp"], + shared_libs: [ + "android.hardware.camera.common@1.0", + "android.hardware.camera.device@1.0", + "android.hardware.camera.device@3.2", + "android.hardware.camera.device@3.3", + "android.hardware.camera.device@3.4", + "android.hardware.camera.device@3.5", + "android.hardware.camera.provider@2.4", + "android.hardware.camera.provider@2.4-legacy", + "android.hardware.camera.provider@2.5", + "android.hardware.camera.provider@2.5-legacy", + "android.hardware.graphics.mapper@2.0", + "android.hidl.allocator@1.0", + "android.hidl.memory@1.0", + "libbinder", + "libcamera_metadata", + "libhardware", + "libhidlbase", + "libhidltransport", + "liblog", + "libutils", + ], + static_libs: [ + "android.hardware.camera.common@1.0-helper", + ], + header_libs: [ + "camera.device@3.4-impl_headers", + "camera.device@3.5-impl_headers" + ], +} + +cc_binary { + name: "android.hardware.camera.provider@2.5-service", + defaults: ["camera_service_2_5_defaults"], + compile_multilib: "32", + init_rc: ["android.hardware.camera.provider@2.5-service.rc"], +} + +cc_binary { + name: "android.hardware.camera.provider@2.5-service_64", + defaults: ["camera_service_2_5_defaults"], + compile_multilib: "64", + init_rc: ["android.hardware.camera.provider@2.5-service_64.rc"], +} + +cc_binary { + name: "android.hardware.camera.provider@2.5-service-lazy", + overrides: ["android.hardware.camera.provider@2.5-service"], + defaults: ["camera_service_2_5_defaults"], + compile_multilib: "32", + init_rc: ["android.hardware.camera.provider@2.5-service-lazy.rc"], + cflags: ["-DLAZY_SERVICE"], +} + +cc_binary { + name: "android.hardware.camera.provider@2.5-service-lazy_64", + overrides: ["android.hardware.camera.provider@2.5-service_64"], + defaults: ["camera_service_2_5_defaults"], + compile_multilib: "64", + init_rc: ["android.hardware.camera.provider@2.5-service-lazy_64.rc"], + cflags: ["-DLAZY_SERVICE"], +} + +cc_binary { + name: "android.hardware.camera.provider@2.5-external-service", + defaults: ["hidl_defaults"], + proprietary: true, + relative_install_path: "hw", + srcs: ["external-service.cpp"], + compile_multilib: "32", + init_rc: ["android.hardware.camera.provider@2.5-external-service.rc"], + shared_libs: [ + "android.hardware.camera.common@1.0", + "android.hardware.camera.device@1.0", + "android.hardware.camera.device@3.2", + "android.hardware.camera.device@3.3", + "android.hardware.camera.device@3.4", + "android.hardware.camera.device@3.5", + "android.hardware.camera.provider@2.4", + "android.hardware.camera.provider@2.4-external", + "android.hardware.camera.provider@2.5", + "android.hardware.camera.provider@2.5-external", + "android.hardware.graphics.mapper@2.0", + "libbinder", + "libhidlbase", + "libhidltransport", + "liblog", + "libtinyxml2", + "libutils", + ], + static_libs: [ + "android.hardware.camera.common@1.0-helper", + ], + header_libs: [ + "camera.device@3.4-external-impl_headers", + "camera.device@3.4-impl_headers", + "camera.device@3.5-external-impl_headers", + "camera.device@3.5-impl_headers", + ], +} diff --git a/camera/provider/2.5/default/CameraProvider_2_5.h b/camera/provider/2.5/default/CameraProvider_2_5.h new file mode 100644 index 0000000000..d0f1ddaaf5 --- /dev/null +++ b/camera/provider/2.5/default/CameraProvider_2_5.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2019 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_CAMERA_PROVIDER_V2_5_CAMERAPROVIDER_H +#define ANDROID_HARDWARE_CAMERA_PROVIDER_V2_5_CAMERAPROVIDER_H + +#include +#include +#include + +namespace android { +namespace hardware { +namespace camera { +namespace provider { +namespace V2_5 { +namespace implementation { + +using ::android::hardware::camera::common::V1_0::Status; +using ::android::hardware::camera::provider::V2_5::ICameraProvider; +using ::android::hardware::camera::provider::V2_4::ICameraProviderCallback; +using ::android::hardware::Return; +using ::android::hardware::hidl_string; +using ::android::sp; + +// Default recommended RPC thread count for camera provider implementations +const int HWBINDER_THREAD_COUNT = 6; + +template +struct CameraProvider : public ICameraProvider { + CameraProvider() : impl() {} + ~CameraProvider() {} + + // Caller must use this method to check if CameraProvider ctor failed + bool isInitFailed() { return impl.isInitFailed(); } + + // Methods from ::android::hardware::camera::provider::V2_4::ICameraProvider follow. + Return setCallback(const sp& callback) override { + return impl.setCallback(callback); + } + + Return getVendorTags(getVendorTags_cb _hidl_cb) override { + return impl.getVendorTags(_hidl_cb); + } + + Return getCameraIdList(getCameraIdList_cb _hidl_cb) override { + return impl.getCameraIdList(_hidl_cb); + } + + Return isSetTorchModeSupported(isSetTorchModeSupported_cb _hidl_cb) override { + return impl.isSetTorchModeSupported(_hidl_cb); + } + + Return getCameraDeviceInterface_V1_x( + const hidl_string& cameraDeviceName, + getCameraDeviceInterface_V1_x_cb _hidl_cb) override { + return impl.getCameraDeviceInterface_V1_x(cameraDeviceName, _hidl_cb); + } + + Return getCameraDeviceInterface_V3_x( + const hidl_string& cameraDeviceName, + getCameraDeviceInterface_V3_x_cb _hidl_cb) override { + return impl.getCameraDeviceInterface_V3_x(cameraDeviceName, _hidl_cb); + } + + // Methods from ::android::hardware::camera::provider::V2_5::ICameraProvider follow. + Return notifyDeviceStateChange(hardware::hidl_bitfield newState) override { + return impl.notifyDeviceStateChange(newState); + } + +private: + IMPL impl; +}; + +} // namespace implementation +} // namespace V2_5 +} // namespace provider +} // namespace camera +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_CAMERA_PROVIDER_V2_5_CAMERAPROVIDER_H diff --git a/camera/provider/2.5/default/ExternalCameraProviderImpl_2_5.cpp b/camera/provider/2.5/default/ExternalCameraProviderImpl_2_5.cpp new file mode 100644 index 0000000000..87851cd4b1 --- /dev/null +++ b/camera/provider/2.5/default/ExternalCameraProviderImpl_2_5.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "CamPrvdr@2.5-external" +//#define LOG_NDEBUG 0 +#include + +#include "ExternalCameraProviderImpl_2_5.h" + +namespace android { +namespace hardware { +namespace camera { +namespace provider { +namespace V2_5 { +namespace implementation { + +ExternalCameraProviderImpl_2_5::ExternalCameraProviderImpl_2_5() : + ExternalCameraProviderImpl_2_4() { +} + +ExternalCameraProviderImpl_2_5::~ExternalCameraProviderImpl_2_5() { +} + +Return ExternalCameraProviderImpl_2_5::notifyDeviceStateChange( + hidl_bitfield /*newState*/) { + return Void(); +} + +} // namespace implementation +} // namespace V2_5 +} // namespace provider +} // namespace camera +} // namespace hardware +} // namespace android diff --git a/camera/provider/2.5/default/ExternalCameraProviderImpl_2_5.h b/camera/provider/2.5/default/ExternalCameraProviderImpl_2_5.h new file mode 100644 index 0000000000..eeaa7cca06 --- /dev/null +++ b/camera/provider/2.5/default/ExternalCameraProviderImpl_2_5.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2019 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_CAMERA_PROVIDER_V2_5_EXTCAMERAPROVIDER_H +#define ANDROID_HARDWARE_CAMERA_PROVIDER_V2_5_EXTCAMERAPROVIDER_H + +#include + +#include +#include +#include + +namespace android { +namespace hardware { +namespace camera { +namespace provider { +namespace V2_5 { +namespace implementation { + +using namespace ::android::hardware::camera::provider; + +using ::android::hardware::camera::common::V1_0::CameraDeviceStatus; +using ::android::hardware::camera::common::V1_0::Status; +using ::android::hardware::camera::common::V1_0::VendorTagSection; +using ::android::hardware::camera::external::common::ExternalCameraConfig; +using ::android::hardware::camera::provider::V2_5::ICameraProvider; +using ::android::hardware::camera::provider::V2_4::ICameraProviderCallback; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::hidl_bitfield; + +struct ExternalCameraProviderImpl_2_5 : + public V2_4::implementation::ExternalCameraProviderImpl_2_4 { + ExternalCameraProviderImpl_2_5(); + ~ExternalCameraProviderImpl_2_5(); + + // Methods from ::android::hardware::camera::provider::V2_5::ICameraProvider follow. + Return notifyDeviceStateChange(hidl_bitfield newState); +private: +}; + +} // namespace implementation +} // namespace V2_5 +} // namespace provider +} // namespace camera +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_CAMERA_PROVIDER_V2_5_EXTCAMERAPROVIDER_H diff --git a/camera/provider/2.5/default/LegacyCameraProviderImpl_2_5.cpp b/camera/provider/2.5/default/LegacyCameraProviderImpl_2_5.cpp new file mode 100644 index 0000000000..5233397bb8 --- /dev/null +++ b/camera/provider/2.5/default/LegacyCameraProviderImpl_2_5.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "CamPrvdr@2.5-legacy" +//#define LOG_NDEBUG 0 +#include +#include + +#include "LegacyCameraProviderImpl_2_5.h" +#include "CameraProvider_2_5.h" + +namespace android { +namespace hardware { +namespace camera { +namespace provider { +namespace V2_5 { +namespace implementation { + +template struct CameraProvider; + +LegacyCameraProviderImpl_2_5::LegacyCameraProviderImpl_2_5() : + LegacyCameraProviderImpl_2_4() { +} + +LegacyCameraProviderImpl_2_5::~LegacyCameraProviderImpl_2_5() {} + +Return LegacyCameraProviderImpl_2_5::notifyDeviceStateChange( + hidl_bitfield newState) { + ALOGD("%s: New device state: 0x%" PRIx64, __FUNCTION__, newState); + uint64_t state = static_cast(newState); + mModule->notifyDeviceStateChange(state); + return Void(); +} + +} // namespace implementation +} // namespace V2_5 +} // namespace provider +} // namespace camera +} // namespace hardware +} // namespace android diff --git a/camera/provider/2.5/default/LegacyCameraProviderImpl_2_5.h b/camera/provider/2.5/default/LegacyCameraProviderImpl_2_5.h new file mode 100644 index 0000000000..62dd97f590 --- /dev/null +++ b/camera/provider/2.5/default/LegacyCameraProviderImpl_2_5.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2019 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_CAMERA_PROVIDER_V2_5_LEGACYCAMERAPROVIDER_H +#define ANDROID_HARDWARE_CAMERA_PROVIDER_V2_5_LEGACYCAMERAPROVIDER_H + +#include + +#include +#include +#include + +namespace android { +namespace hardware { +namespace camera { +namespace provider { +namespace V2_5 { +namespace implementation { + +using namespace ::android::hardware::camera::provider; + +using ::android::hardware::camera::common::V1_0::CameraDeviceStatus; +using ::android::hardware::camera::common::V1_0::Status; +using ::android::hardware::camera::common::V1_0::TorchModeStatus; +using ::android::hardware::camera::common::V1_0::VendorTag; +using ::android::hardware::camera::common::V1_0::VendorTagSection; +using ::android::hardware::camera::common::V1_0::helper::CameraModule; +using ::android::hardware::camera::common::V1_0::helper::VendorTagDescriptor; +using ::android::hardware::camera::provider::V2_5::DeviceState; +using ::android::hardware::hidl_bitfield; +using ::android::hardware::Return; + +struct LegacyCameraProviderImpl_2_5 : public V2_4::implementation::LegacyCameraProviderImpl_2_4 { + LegacyCameraProviderImpl_2_5(); + ~LegacyCameraProviderImpl_2_5(); + + // Methods from ::android::hardware::camera::provider::V2_5::ICameraProvider follow. + Return notifyDeviceStateChange(hidl_bitfield newState); +private: +}; + +} // namespace implementation +} // namespace V2_5 +} // namespace provider +} // namespace camera +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_CAMERA_PROVIDER_V2_5_CAMERAPROVIDER_H diff --git a/camera/provider/2.5/default/OWNERS b/camera/provider/2.5/default/OWNERS new file mode 100644 index 0000000000..369b2048cb --- /dev/null +++ b/camera/provider/2.5/default/OWNERS @@ -0,0 +1,7 @@ +cychen@google.com +epeev@google.com +etalvala@google.com +jchowdhary@google.com +shuzhenwang@google.com +yinchiayeh@google.com +zhijunhe@google.com diff --git a/camera/provider/2.5/default/android.hardware.camera.provider@2.5-external-service.rc b/camera/provider/2.5/default/android.hardware.camera.provider@2.5-external-service.rc new file mode 100644 index 0000000000..107097e661 --- /dev/null +++ b/camera/provider/2.5/default/android.hardware.camera.provider@2.5-external-service.rc @@ -0,0 +1,9 @@ +service vendor.camera-provider-2-5-ext /vendor/bin/hw/android.hardware.camera.provider@2.5-external-service + interface android.hardware.camera.provider@2.5::ICameraProvider external/0 + interface android.hardware.camera.provider@2.4::ICameraProvider external/0 + class hal + user cameraserver + group audio camera input drmrpc usb + ioprio rt 4 + capabilities SYS_NICE + writepid /dev/cpuset/camera-daemon/tasks /dev/stune/top-app/tasks diff --git a/camera/provider/2.5/default/android.hardware.camera.provider@2.5-service-lazy.rc b/camera/provider/2.5/default/android.hardware.camera.provider@2.5-service-lazy.rc new file mode 100644 index 0000000000..b45158a082 --- /dev/null +++ b/camera/provider/2.5/default/android.hardware.camera.provider@2.5-service-lazy.rc @@ -0,0 +1,11 @@ +service vendor.camera-provider-2-5 /vendor/bin/hw/android.hardware.camera.provider@2.5-service-lazy + interface android.hardware.camera.provider@2.5::ICameraProvider legacy/0 + interface android.hardware.camera.provider@2.4::ICameraProvider legacy/0 + oneshot + disabled + class hal + user cameraserver + group audio camera input drmrpc + ioprio rt 4 + capabilities SYS_NICE + writepid /dev/cpuset/camera-daemon/tasks /dev/stune/top-app/tasks diff --git a/camera/provider/2.5/default/android.hardware.camera.provider@2.5-service-lazy_64.rc b/camera/provider/2.5/default/android.hardware.camera.provider@2.5-service-lazy_64.rc new file mode 100644 index 0000000000..aa070d9b3a --- /dev/null +++ b/camera/provider/2.5/default/android.hardware.camera.provider@2.5-service-lazy_64.rc @@ -0,0 +1,11 @@ +service vendor.camera-provider-2-5 /vendor/bin/hw/android.hardware.camera.provider@2.5-service-lazy_64 + interface android.hardware.camera.provider@2.5::ICameraProvider legacy/0 + interface android.hardware.camera.provider@2.5::ICameraProvider legacy/0 + oneshot + disabled + class hal + user cameraserver + group audio camera input drmrpc + ioprio rt 4 + capabilities SYS_NICE + writepid /dev/cpuset/camera-daemon/tasks /dev/stune/top-app/tasks diff --git a/camera/provider/2.5/default/android.hardware.camera.provider@2.5-service.rc b/camera/provider/2.5/default/android.hardware.camera.provider@2.5-service.rc new file mode 100644 index 0000000000..c065815fab --- /dev/null +++ b/camera/provider/2.5/default/android.hardware.camera.provider@2.5-service.rc @@ -0,0 +1,9 @@ +service vendor.camera-provider-2-5 /vendor/bin/hw/android.hardware.camera.provider@2.5-service + interface android.hardware.camera.provider@2.5::ICameraProvider legacy/0 + interface android.hardware.camera.provider@2.4::ICameraProvider legacy/0 + class hal + user cameraserver + group audio camera input drmrpc + ioprio rt 4 + capabilities SYS_NICE + writepid /dev/cpuset/camera-daemon/tasks /dev/stune/top-app/tasks diff --git a/camera/provider/2.5/default/android.hardware.camera.provider@2.5-service_64.rc b/camera/provider/2.5/default/android.hardware.camera.provider@2.5-service_64.rc new file mode 100644 index 0000000000..63dd11d349 --- /dev/null +++ b/camera/provider/2.5/default/android.hardware.camera.provider@2.5-service_64.rc @@ -0,0 +1,9 @@ +service vendor.camera-provider-2-5 /vendor/bin/hw/android.hardware.camera.provider@2.5-service_64 + interface android.hardware.camera.provider@2.5::ICameraProvider legacy/0 + interface android.hardware.camera.provider@2.4::ICameraProvider legacy/0 + class hal + user cameraserver + group audio camera input drmrpc + ioprio rt 4 + capabilities SYS_NICE + writepid /dev/cpuset/camera-daemon/tasks /dev/stune/top-app/tasks diff --git a/camera/provider/2.5/default/external-service.cpp b/camera/provider/2.5/default/external-service.cpp new file mode 100644 index 0000000000..8788916cf3 --- /dev/null +++ b/camera/provider/2.5/default/external-service.cpp @@ -0,0 +1,46 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "android.hardware.camera.provider@2.5-external-service" + +#include +#include +#include + +#include "CameraProvider_2_5.h" +#include "ExternalCameraProviderImpl_2_5.h" + +using android::status_t; +using android::hardware::camera::provider::V2_5::ICameraProvider; + +int main() +{ + using namespace android::hardware::camera::provider::V2_5::implementation; + + ALOGI("CameraProvider@2.5 external webcam service is starting."); + + ::android::hardware::configureRpcThreadpool(/*threads*/ HWBINDER_THREAD_COUNT, /*willJoin*/ true); + + ::android::sp provider = new CameraProvider(); + + status_t status = provider->registerAsService("external/0"); + LOG_ALWAYS_FATAL_IF(status != android::OK, "Error while registering provider service: %d", + status); + + ::android::hardware::joinRpcThreadpool(); + + return 0; +} diff --git a/camera/provider/2.5/default/service.cpp b/camera/provider/2.5/default/service.cpp new file mode 100644 index 0000000000..604215d71c --- /dev/null +++ b/camera/provider/2.5/default/service.cpp @@ -0,0 +1,63 @@ +/* + * Copyright 2019 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. + */ + +#ifdef LAZY_SERVICE +#define LOG_TAG "android.hardware.camera.provider@2.5-service-lazy" +#else +#define LOG_TAG "android.hardware.camera.provider@2.5-service" +#endif + +#include +#include +#include +#include + +#include "CameraProvider_2_5.h" +#include "LegacyCameraProviderImpl_2_5.h" + +using android::status_t; +using android::hardware::camera::provider::V2_5::ICameraProvider; + +#ifdef LAZY_SERVICE +const bool kLazyService = true; +#else +const bool kLazyService = false; +#endif + +int main() +{ + using namespace android::hardware::camera::provider::V2_5::implementation; + + ALOGI("CameraProvider@2.5 legacy service is starting."); + + ::android::hardware::configureRpcThreadpool(/*threads*/ HWBINDER_THREAD_COUNT, /*willJoin*/ true); + + ::android::sp provider = new CameraProvider(); + + status_t status; + if (kLazyService) { + auto serviceRegistrar = std::make_shared<::android::hardware::LazyServiceRegistrar>(); + status = serviceRegistrar->registerService(provider, "legacy/0"); + } else { + status = provider->registerAsService("legacy/0"); + } + LOG_ALWAYS_FATAL_IF(status != android::OK, "Error while registering provider service: %d", + status); + + ::android::hardware::joinRpcThreadpool(); + + return 0; +} From 592b59273488f1bf1e5d167d524e929b795d4448 Mon Sep 17 00:00:00 2001 From: Henry Fang Date: Fri, 8 Feb 2019 11:31:16 -0800 Subject: [PATCH 464/718] Clean cas@1.0 file for Incremental build after enable cas@1.1 Clean cas@1.0 files from build for Incremental build Test: Manual bug: 124116613 Change-Id: I40a136dfbd0a8558e593897df3d3dd32114dd436 --- CleanSpec.mk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CleanSpec.mk b/CleanSpec.mk index 0900eea0cf..fa711cabbc 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -69,3 +69,5 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/seccomp_policy/configsto $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/seccomp_policy/configstore@1.1.policy) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/bin/hw/android.hardware.configstore@1.1-service) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/init/android.hardware.configstore@1.1-service.rc) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/bin/hw/android.hardware.cas@1.0*) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/init/android.hardware.cas@1.0*) From 4001118df8ff580a3d17301510e2c705850cce3e Mon Sep 17 00:00:00 2001 From: Sundong Ahn Date: Mon, 11 Feb 2019 15:00:43 +0900 Subject: [PATCH 465/718] Change class and variable names The rule to generate class and variable names is changed. So update api names according to this rule. Test: make update-api && make checkapi Bug: 123777669 Change-Id: I5ba41679c863d8f57e9c43821b311ca09e9b4ea2 --- audio/effect/5.0/xml/api/current.txt | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/audio/effect/5.0/xml/api/current.txt b/audio/effect/5.0/xml/api/current.txt index 473bb10358..ef467c9a54 100644 --- a/audio/effect/5.0/xml/api/current.txt +++ b/audio/effect/5.0/xml/api/current.txt @@ -1,27 +1,27 @@ // Signature format: 2.0 package audio.effects.V5_0 { - public class Audioeffectsconf { - ctor public Audioeffectsconf(); + public class AudioEffectsConf { + ctor public AudioEffectsConf(); method public audio.effects.V5_0.EffectsType getEffects(); method public audio.effects.V5_0.LibrariesType getLibraries(); - method public audio.effects.V5_0.Audioeffectsconf.Postprocess getPostprocess(); - method public audio.effects.V5_0.Audioeffectsconf.Preprocess getPreprocess(); + method public audio.effects.V5_0.AudioEffectsConf.Postprocess getPostprocess(); + method public audio.effects.V5_0.AudioEffectsConf.Preprocess getPreprocess(); method public audio.effects.V5_0.VersionType getVersion(); method public void setEffects(audio.effects.V5_0.EffectsType); method public void setLibraries(audio.effects.V5_0.LibrariesType); - method public void setPostprocess(audio.effects.V5_0.Audioeffectsconf.Postprocess); - method public void setPreprocess(audio.effects.V5_0.Audioeffectsconf.Preprocess); + method public void setPostprocess(audio.effects.V5_0.AudioEffectsConf.Postprocess); + method public void setPreprocess(audio.effects.V5_0.AudioEffectsConf.Preprocess); method public void setVersion(audio.effects.V5_0.VersionType); } - public static class Audioeffectsconf.Postprocess { - ctor public Audioeffectsconf.Postprocess(); + public static class AudioEffectsConf.Postprocess { + ctor public AudioEffectsConf.Postprocess(); method public java.util.List getStream(); } - public static class Audioeffectsconf.Preprocess { - ctor public Audioeffectsconf.Preprocess(); + public static class AudioEffectsConf.Preprocess { + ctor public AudioEffectsConf.Preprocess(); method public java.util.List getStream(); } @@ -123,7 +123,7 @@ package audio.effects.V5_0 { public class XmlParser { ctor public XmlParser(); - method public static audio.effects.V5_0.Audioeffectsconf read(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException; + method public static audio.effects.V5_0.AudioEffectsConf read(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; } From 4cd0dbf6bbb2e53c4b1c9fb83818c841464ff664 Mon Sep 17 00:00:00 2001 From: Etan Cohen Date: Mon, 11 Feb 2019 12:50:40 -0800 Subject: [PATCH 466/718] Revert "[AWARE] Disable NANv3 data-path capabilities" This reverts commit e338c81190db1ed025bc9c5e209ed577a951d531. Cannot be supported without additional HAL APIs to provide the device's capability to the host. These aren't necessary since this capability should be enabled by default by the firmware. Bug: 112586769 Test: (ACTS) act.py ThroughputTest:test_iperf_max_ndi_aware_only_passphrases Test: (CTS) atest SingleDeviceTest --- wifi/1.3/default/hidl_struct_util.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/wifi/1.3/default/hidl_struct_util.cpp b/wifi/1.3/default/hidl_struct_util.cpp index 49c14771f9..2e4db70480 100644 --- a/wifi/1.3/default/hidl_struct_util.cpp +++ b/wifi/1.3/default/hidl_struct_util.cpp @@ -1259,10 +1259,6 @@ bool convertHidlNanEnableRequestToLegacy( hidl_request.debugConfigs .useSdfInBandVal[(size_t)NanBandIndex::NAN_BAND_5GHZ]; - // disable NANv3 NDPe - legacy_request->config_ndpe_attr = 1; - legacy_request->use_ndpe_attr = 0; - return true; } @@ -1774,10 +1770,6 @@ bool convertHidlNanConfigRequestToLegacy( hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ] .discoveryWindowIntervalVal; - // disable NANv3 NDPe - legacy_request->config_ndpe_attr = 1; - legacy_request->use_ndpe_attr = 0; - return true; } From 4e8633ec30b1b17319260fb73b0be9e7d9a2d1af Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Tue, 5 Feb 2019 11:26:32 -0800 Subject: [PATCH 467/718] Add VTS tests for InputClassifier HAL The VTS tests are needed to test the InputClassifier HAL. Add some basic tests here. Test: atest VtsHalInputClassifierV1_0TargetTest Bug: 117935272 Change-Id: I9a33729ad8dddbacab0500ee2953036c07e566dd --- input/classifier/1.0/vts/OWNERS | 3 + .../classifier/1.0/vts/functional/Android.bp | 27 +++ .../VtsHalInputClassifierV1_0TargetTest.cpp | 193 ++++++++++++++++++ 3 files changed, 223 insertions(+) create mode 100644 input/classifier/1.0/vts/OWNERS create mode 100644 input/classifier/1.0/vts/functional/Android.bp create mode 100644 input/classifier/1.0/vts/functional/VtsHalInputClassifierV1_0TargetTest.cpp diff --git a/input/classifier/1.0/vts/OWNERS b/input/classifier/1.0/vts/OWNERS new file mode 100644 index 0000000000..447f3d9b67 --- /dev/null +++ b/input/classifier/1.0/vts/OWNERS @@ -0,0 +1,3 @@ +michaelwr@google.com +pquinn@google.com +svv@google.com \ No newline at end of file diff --git a/input/classifier/1.0/vts/functional/Android.bp b/input/classifier/1.0/vts/functional/Android.bp new file mode 100644 index 0000000000..ef49d70dfb --- /dev/null +++ b/input/classifier/1.0/vts/functional/Android.bp @@ -0,0 +1,27 @@ +// +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +cc_test { + name: "VtsHalInputClassifierV1_0TargetTest", + defaults: ["VtsHalTargetTestDefaults"], + srcs: ["VtsHalInputClassifierV1_0TargetTest.cpp"], + static_libs: [ + "android.hardware.input.classifier@1.0", + "android.hardware.input.common@1.0", + ], + test_suites: ["general-tests"], +} + diff --git a/input/classifier/1.0/vts/functional/VtsHalInputClassifierV1_0TargetTest.cpp b/input/classifier/1.0/vts/functional/VtsHalInputClassifierV1_0TargetTest.cpp new file mode 100644 index 0000000000..f033c2a102 --- /dev/null +++ b/input/classifier/1.0/vts/functional/VtsHalInputClassifierV1_0TargetTest.cpp @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "input_classifier_hal_test" + +#include +#include +#include +#include +#include +#include +#include + +using ::android::ReservedInputDeviceId; +using ::android::sp; +using ::android::hardware::Return; +using ::android::hardware::input::classifier::V1_0::IInputClassifier; +using ::android::hardware::input::common::V1_0::Action; +using ::android::hardware::input::common::V1_0::Axis; +using ::android::hardware::input::common::V1_0::Button; +using ::android::hardware::input::common::V1_0::EdgeFlag; +using ::android::hardware::input::common::V1_0::MotionEvent; +using ::android::hardware::input::common::V1_0::PointerCoords; +using ::android::hardware::input::common::V1_0::PointerProperties; +using ::android::hardware::input::common::V1_0::Source; +using ::android::hardware::input::common::V1_0::ToolType; +using ::android::hardware::input::common::V1_0::VideoFrame; + +static MotionEvent getSimpleMotionEvent() { + MotionEvent event; + event.action = Action::DOWN; + event.actionButton = Button::NONE; + event.actionIndex = 0; + event.buttonState = 0; + event.deviceId = 0; + event.deviceTimestamp = 0; + event.displayId = 1; + event.downTime = 2; + event.edgeFlags = 0; + event.eventTime = 3; + event.flags = 0; + event.frames = {}; + event.metaState = 0; + event.policyFlags = 0; + event.source = Source::TOUCHSCREEN; + event.xPrecision = 0; + event.yPrecision = 0; + + PointerCoords coords; + coords.bits = Axis::X | Axis::Y; + coords.values = {1 /*X*/, 2 /*Y*/}; + event.pointerCoords = {coords}; + + PointerProperties properties; + properties.id = 0; + properties.toolType = ToolType::FINGER; + event.pointerProperties = {properties}; + + return event; +} + +// Test environment for Input Classifier HIDL HAL. +class InputClassifierHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { + public: + // get the test environment singleton + static InputClassifierHidlEnvironment* Instance() { + static InputClassifierHidlEnvironment* instance = new InputClassifierHidlEnvironment; + return instance; + } + + virtual void registerTestServices() override { registerTestService(); } + + private: + InputClassifierHidlEnvironment() {} +}; + +// The main test class for INPUT CLASSIFIER HIDL HAL 1.0. +class InputClassifierHidlTest_1_0 : public ::testing::VtsHalHidlTargetTestBase { + public: + virtual void SetUp() override { + classifier = ::testing::VtsHalHidlTargetTestBase::getService( + InputClassifierHidlEnvironment::Instance()->getServiceName()); + ASSERT_NE(classifier, nullptr); + } + + virtual void TearDown() override {} + + sp classifier; +}; + +/** + * Call resetDevice(..) for a few common device id values, and make sure that the HAL + * can handle the resets gracefully. + */ +TEST_F(InputClassifierHidlTest_1_0, ResetDevice) { + EXPECT_TRUE(classifier->resetDevice(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID).isOk()); + EXPECT_TRUE(classifier->resetDevice(ReservedInputDeviceId::BUILT_IN_KEYBOARD_ID).isOk()); + EXPECT_TRUE(classifier->resetDevice(1).isOk()); + EXPECT_TRUE(classifier->resetDevice(2).isOk()); +} + +/** + * Call reset() on the HAL to ensure no fatal failure there. + */ +TEST_F(InputClassifierHidlTest_1_0, ResetHal) { + EXPECT_TRUE(classifier->reset().isOk()); +} + +/** + * Classify an event without any video frames. + */ +TEST_F(InputClassifierHidlTest_1_0, Classify_NoVideoFrame) { + // Create a MotionEvent that does not have any video data + MotionEvent event = getSimpleMotionEvent(); + + EXPECT_TRUE(classifier->classify(event).isOk()); + // We are not checking the actual classification here, + // because the HAL operation is highly device-specific. + + // Return HAL to a consistent state by doing a reset + classifier->reset(); +} + +/** + * Classify an event with one video frame. Should be the most common scenario. + */ +TEST_F(InputClassifierHidlTest_1_0, Classify_OneVideoFrame) { + MotionEvent event = getSimpleMotionEvent(); + VideoFrame frame; + frame.data = {1, 2, 3, 4}; + frame.height = 2; + frame.width = 2; + frame.timestamp = event.eventTime; + event.frames = {frame}; + + EXPECT_TRUE(classifier->classify(event).isOk()); + // We are not checking the actual classification here, + // because the HAL operation is highly device-specific. + + // Return HAL to a consistent state by doing a reset + classifier->reset(); +} + +/** + * Classify an event with 2 video frames. This could happen if there's slowness in the system, + * or if simply the video rate is somehow higher that the input event rate. + * The HAL should be able to handle events with more than 1 video frame. + * + * The frames should be in chronological order, but it is not guaranteed that they will have + * monotonically increasing timestamps. Still, we provide consistent timestamps here since that + * is the most realistic mode of operation. + */ +TEST_F(InputClassifierHidlTest_1_0, Classify_TwoVideoFrames) { + MotionEvent event = getSimpleMotionEvent(); + VideoFrame frame1; + frame1.data = {1, 2, 3, 4}; + frame1.height = 2; + frame1.width = 2; + frame1.timestamp = event.eventTime; + VideoFrame frame2 = frame1; + frame2.data = {5, 5, 5, -1}; + frame2.timestamp += 1; + event.frames = {frame1, frame2}; + + EXPECT_TRUE(classifier->classify(event).isOk()); + // We are not checking the actual classification here, + // because the HAL operation is highly device-specific. + + // Return HAL to a consistent state by doing a reset + classifier->reset(); +} + +int main(int argc, char** argv) { + ::testing::AddGlobalTestEnvironment(InputClassifierHidlEnvironment::Instance()); + ::testing::InitGoogleTest(&argc, argv); + InputClassifierHidlEnvironment::Instance()->init(&argc, argv); + int status = RUN_ALL_TESTS(); + LOG(INFO) << "Test result = " << status; + return status; +} From 3cb3667e238fde061806cfc9a42aaa3d8e0b3e1a Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Mon, 11 Feb 2019 15:35:12 -0800 Subject: [PATCH 468/718] CleanSpec: cas@1.0 manifest fragments Change-Id: Id96b46ffd9c443d6bcfdf87a16aa7758859b668c Fixes: 124121446 Test: manual --- CleanSpec.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/CleanSpec.mk b/CleanSpec.mk index fa711cabbc..1af439a97e 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -71,3 +71,4 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/bin/hw/android.hardware.conf $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/init/android.hardware.configstore@1.1-service.rc) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/bin/hw/android.hardware.cas@1.0*) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/init/android.hardware.cas@1.0*) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/vintf/manifest/android.hardware.cas@1.0*) From f8a47b7f01a521564149c43dc25bb3158b52ea09 Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Mon, 11 Feb 2019 21:14:16 -0800 Subject: [PATCH 469/718] Update makefiles. Bug: 123976090 Test: N/A Change-Id: I5fb6c126a090a3fe0fa4829ea9224564133dc1ae --- audio/5.0/Android.bp | 1 + biometrics/face/1.0/Android.bp | 1 + bluetooth/audio/2.0/Android.bp | 1 + camera/device/3.5/Android.bp | 2 ++ camera/metadata/3.4/Android.bp | 6 ++++++ drm/1.2/Android.bp | 1 + graphics/common/1.2/Android.bp | 3 +++ input/common/1.0/Android.bp | 3 --- neuralnetworks/1.2/Android.bp | 1 + sensors/2.0/Android.bp | 1 + wifi/1.3/Android.bp | 6 +++--- wifi/supplicant/1.2/Android.bp | 8 ++++---- 12 files changed, 24 insertions(+), 10 deletions(-) diff --git a/audio/5.0/Android.bp b/audio/5.0/Android.bp index 3586b8e308..7c2db1d8a9 100644 --- a/audio/5.0/Android.bp +++ b/audio/5.0/Android.bp @@ -30,6 +30,7 @@ hidl_interface { "AudioMicrophoneDirectionality", "AudioMicrophoneLocation", "MessageQueueFlagBits", + "MicrophoneDirection", "MicrophoneInfo", "MmapBufferFlag", "MmapBufferInfo", diff --git a/biometrics/face/1.0/Android.bp b/biometrics/face/1.0/Android.bp index 45dbad9d3a..0f8c6e646b 100644 --- a/biometrics/face/1.0/Android.bp +++ b/biometrics/face/1.0/Android.bp @@ -17,6 +17,7 @@ hidl_interface { types: [ "FaceAcquiredInfo", "FaceError", + "Feature", "OptionalBool", "OptionalUint64", "Status", diff --git a/bluetooth/audio/2.0/Android.bp b/bluetooth/audio/2.0/Android.bp index 542c812590..e72b6ab9fd 100644 --- a/bluetooth/audio/2.0/Android.bp +++ b/bluetooth/audio/2.0/Android.bp @@ -15,6 +15,7 @@ hidl_interface { interfaces: [ "android.hardware.audio.common@5.0", "android.hidl.base@1.0", + "android.hidl.safe_union@1.0", ], types: [ "AacObjectType", diff --git a/camera/device/3.5/Android.bp b/camera/device/3.5/Android.bp index 2a9ba05571..6d1836720d 100644 --- a/camera/device/3.5/Android.bp +++ b/camera/device/3.5/Android.bp @@ -23,6 +23,8 @@ hidl_interface { types: [ "BufferRequest", "BufferRequestStatus", + "CameraBlob", + "CameraBlobId", "StreamBufferRequestError", "StreamBufferRet", "StreamBuffersVal", diff --git a/camera/metadata/3.4/Android.bp b/camera/metadata/3.4/Android.bp index 17a2675218..d1cba14d0d 100644 --- a/camera/metadata/3.4/Android.bp +++ b/camera/metadata/3.4/Android.bp @@ -14,10 +14,16 @@ hidl_interface { "android.hardware.camera.metadata@3.3", ], types: [ + "CameraMetadataEnumAndroidDepthAvailableDynamicDepthStreamConfigurations", + "CameraMetadataEnumAndroidHeicAvailableHeicStreamConfigurations", + "CameraMetadataEnumAndroidHeicInfoSupported", "CameraMetadataEnumAndroidInfoSupportedBufferManagementVersion", + "CameraMetadataEnumAndroidRequestAvailableCapabilities", "CameraMetadataEnumAndroidScalerAvailableFormats", "CameraMetadataEnumAndroidScalerAvailableRecommendedStreamConfigurations", "CameraMetadataEnumAndroidSensorInfoColorFilterArrangement", + "CameraMetadataSection", + "CameraMetadataSectionStart", "CameraMetadataTag", ], gen_java: true, diff --git a/drm/1.2/Android.bp b/drm/1.2/Android.bp index fa2962ac75..4e0e8ba6e7 100644 --- a/drm/1.2/Android.bp +++ b/drm/1.2/Android.bp @@ -20,6 +20,7 @@ hidl_interface { "android.hidl.base@1.0", ], types: [ + "HdcpLevel", "OfflineLicenseState", "Status", ], diff --git a/graphics/common/1.2/Android.bp b/graphics/common/1.2/Android.bp index a3ebdbf219..b6cd865dd0 100644 --- a/graphics/common/1.2/Android.bp +++ b/graphics/common/1.2/Android.bp @@ -15,9 +15,12 @@ hidl_interface { "android.hardware.graphics.common@1.1", ], types: [ + "BufferUsage", "ColorMode", "Dataspace", "HardwareBuffer", + "Hdr", + "PixelFormat", ], gen_java: true, gen_java_constants: true, diff --git a/input/common/1.0/Android.bp b/input/common/1.0/Android.bp index 68a77f13d9..3de18b4961 100644 --- a/input/common/1.0/Android.bp +++ b/input/common/1.0/Android.bp @@ -9,9 +9,6 @@ hidl_interface { srcs: [ "types.hal", ], - interfaces: [ - "android.hidl.base@1.0", - ], types: [ "Action", "Axis", diff --git a/neuralnetworks/1.2/Android.bp b/neuralnetworks/1.2/Android.bp index 0642dceb2e..daf0c18e0f 100644 --- a/neuralnetworks/1.2/Android.bp +++ b/neuralnetworks/1.2/Android.bp @@ -24,6 +24,7 @@ hidl_interface { types: [ "Constant", "DeviceType", + "Extension", "FmqRequestDatum", "FmqResultDatum", "MeasureTiming", diff --git a/sensors/2.0/Android.bp b/sensors/2.0/Android.bp index 3b948a9cee..57d45ff473 100644 --- a/sensors/2.0/Android.bp +++ b/sensors/2.0/Android.bp @@ -18,6 +18,7 @@ hidl_interface { types: [ "EventQueueFlagBits", "SensorTimeout", + "WakeLockQueueFlagBits", ], gen_java: false, } diff --git a/wifi/1.3/Android.bp b/wifi/1.3/Android.bp index 45e2e88c15..8af1dc484e 100644 --- a/wifi/1.3/Android.bp +++ b/wifi/1.3/Android.bp @@ -19,9 +19,9 @@ hidl_interface { "android.hidl.base@1.0", ], types: [ - "StaLinkLayerRadioStats", - "StaLinkLayerStats", - "WifiChannelStats", + "StaLinkLayerRadioStats", + "StaLinkLayerStats", + "WifiChannelStats", ], gen_java: true, } diff --git a/wifi/supplicant/1.2/Android.bp b/wifi/supplicant/1.2/Android.bp index 18e1cca7e1..addcc2a85c 100644 --- a/wifi/supplicant/1.2/Android.bp +++ b/wifi/supplicant/1.2/Android.bp @@ -7,12 +7,12 @@ hidl_interface { enabled: true, }, srcs: [ + "types.hal", "ISupplicant.hal", "ISupplicantP2pIface.hal", "ISupplicantStaIface.hal", "ISupplicantStaIfaceCallback.hal", "ISupplicantStaNetwork.hal", - "types.hal", ], interfaces: [ "android.hardware.wifi.supplicant@1.0", @@ -21,10 +21,10 @@ hidl_interface { ], types: [ "DppAkm", - "DppNetRole", - "DppSuccessCode", - "DppProgressCode", "DppFailureCode", + "DppNetRole", + "DppProgressCode", + "DppSuccessCode", ], gen_java: true, } From 892e826a3286a138f246a7e8303051e161a19318 Mon Sep 17 00:00:00 2001 From: Shuzhen Wang Date: Fri, 8 Feb 2019 16:12:30 -0800 Subject: [PATCH 470/718] Camera: Handle binder call failure due to static metadata size For physical camera static metadata, we should reduce its size before passing it across binder if possible. Test: Camera CTS Bug: 124129552 Change-Id: I0d9129642ddcbb4c1a1c7fcf7a88bac734be4f5a --- camera/common/1.0/default/CameraModule.cpp | 74 ++++++++++++++++++- .../common/1.0/default/include/CameraModule.h | 7 ++ .../3.4/default/CameraDeviceSession.cpp | 31 ++------ 3 files changed, 84 insertions(+), 28 deletions(-) diff --git a/camera/common/1.0/default/CameraModule.cpp b/camera/common/1.0/default/CameraModule.cpp index 3e3ef433a5..467c121a94 100644 --- a/camera/common/1.0/default/CameraModule.cpp +++ b/camera/common/1.0/default/CameraModule.cpp @@ -253,6 +253,14 @@ CameraModule::~CameraModule() } mCameraInfoMap.removeItemsAt(0); } + + while (mPhysicalCameraInfoMap.size() > 0) { + camera_metadata_t* metadata = mPhysicalCameraInfoMap.editValueAt(0); + if (metadata != NULL) { + free_camera_metadata(metadata); + } + mPhysicalCameraInfoMap.removeItemsAt(0); + } } int CameraModule::init() { @@ -351,7 +359,14 @@ int CameraModule::getPhysicalCameraInfo(int physicalCameraId, camera_metadata_t return ret; } - index = mPhysicalCameraInfoMap.add(physicalCameraId, info); + // The camera_metadata_t returned by get_physical_camera_info could be using + // more memory than necessary due to unused reserved space. Reduce the + // size by appending it to a new CameraMetadata object, which internally + // calls resizeIfNeeded. + CameraMetadata m; + m.append(info); + camera_metadata_t* derivedMetadata = m.release(); + index = mPhysicalCameraInfoMap.add(physicalCameraId, derivedMetadata); } assert(index != NAME_NOT_FOUND); @@ -473,6 +488,43 @@ void CameraModule::notifyDeviceStateChange(uint64_t deviceState) { } } +bool CameraModule::isLogicalMultiCamera( + const common::V1_0::helper::CameraMetadata& metadata, + std::unordered_set* physicalCameraIds) { + if (physicalCameraIds == nullptr) { + ALOGE("%s: physicalCameraIds must not be null", __FUNCTION__); + return false; + } + + bool isLogicalMultiCamera = false; + camera_metadata_ro_entry_t capabilities = + metadata.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES); + for (size_t i = 0; i < capabilities.count; i++) { + if (capabilities.data.u8[i] == + ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA) { + isLogicalMultiCamera = true; + break; + } + } + + if (isLogicalMultiCamera) { + camera_metadata_ro_entry_t entry = + metadata.find(ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS); + const uint8_t* ids = entry.data.u8; + size_t start = 0; + for (size_t i = 0; i < entry.count; ++i) { + if (ids[i] == '\0') { + if (start != i) { + const char* physicalId = reinterpret_cast(ids+start); + physicalCameraIds->emplace(physicalId); + } + start = i + 1; + } + } + } + return isLogicalMultiCamera; +} + status_t CameraModule::filterOpenErrorCode(status_t err) { switch(err) { case NO_ERROR: @@ -487,8 +539,24 @@ status_t CameraModule::filterOpenErrorCode(status_t err) { } void CameraModule::removeCamera(int cameraId) { - free_camera_metadata(const_cast( - mCameraInfoMap.valueFor(cameraId).static_camera_characteristics)); + std::unordered_set physicalIds; + camera_metadata_t *metadata = const_cast( + mCameraInfoMap.valueFor(cameraId).static_camera_characteristics); + common::V1_0::helper::CameraMetadata hidlMetadata(metadata); + + if (isLogicalMultiCamera(hidlMetadata, &physicalIds)) { + for (const auto& id : physicalIds) { + int idInt = std::stoi(id); + if (mPhysicalCameraInfoMap.indexOfKey(idInt) >= 0) { + free_camera_metadata(mPhysicalCameraInfoMap[idInt]); + mPhysicalCameraInfoMap.removeItem(idInt); + } else { + ALOGE("%s: Cannot find corresponding static metadata for physical id %s", + __FUNCTION__, id.c_str()); + } + } + } + free_camera_metadata(metadata); mCameraInfoMap.removeItem(cameraId); mDeviceVersionMap.removeItem(cameraId); } diff --git a/camera/common/1.0/default/include/CameraModule.h b/camera/common/1.0/default/include/CameraModule.h index 32c387f107..c89e934655 100644 --- a/camera/common/1.0/default/include/CameraModule.h +++ b/camera/common/1.0/default/include/CameraModule.h @@ -17,6 +17,9 @@ #ifndef CAMERA_COMMON_1_0_CAMERAMODULE_H #define CAMERA_COMMON_1_0_CAMERAMODULE_H +#include +#include + #include #include #include @@ -69,6 +72,10 @@ public: int isStreamCombinationSupported(int cameraId, camera_stream_combination_t *streams); void notifyDeviceStateChange(uint64_t deviceState); + static bool isLogicalMultiCamera( + const common::V1_0::helper::CameraMetadata& metadata, + std::unordered_set* physicalCameraIds); + private: // Derive camera characteristics keys defined after HAL device version static void deriveCameraCharacteristicsKeys(uint32_t deviceVersion, CameraMetadata &chars); diff --git a/camera/device/3.4/default/CameraDeviceSession.cpp b/camera/device/3.4/default/CameraDeviceSession.cpp index e52577cfb9..c937834928 100644 --- a/camera/device/3.4/default/CameraDeviceSession.cpp +++ b/camera/device/3.4/default/CameraDeviceSession.cpp @@ -22,6 +22,7 @@ #include #include #include "CameraDeviceSession.h" +#include "CameraModule.h" namespace android { namespace hardware { @@ -30,6 +31,8 @@ namespace device { namespace V3_4 { namespace implementation { +using ::android::hardware::camera::common::V1_0::helper::CameraModule; + CameraDeviceSession::CameraDeviceSession( camera3_device_t* device, const camera_metadata_t* deviceInfo, @@ -54,31 +57,9 @@ CameraDeviceSession::CameraDeviceSession( mResultBatcher_3_4.setNumPartialResults(mNumPartialResults); - camera_metadata_entry_t capabilities = - mDeviceInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES); - bool isLogicalMultiCamera = false; - for (size_t i = 0; i < capabilities.count; i++) { - if (capabilities.data.u8[i] == - ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA) { - isLogicalMultiCamera = true; - break; - } - } - if (isLogicalMultiCamera) { - camera_metadata_entry entry = - mDeviceInfo.find(ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS); - const uint8_t* ids = entry.data.u8; - size_t start = 0; - for (size_t i = 0; i < entry.count; ++i) { - if (ids[i] == '\0') { - if (start != i) { - const char* physicalId = reinterpret_cast(ids+start); - mPhysicalCameraIds.emplace(physicalId); - } - start = i + 1; - } - } - } + // Parse and store current logical camera's physical ids. + (void)CameraModule::isLogicalMultiCamera(mDeviceInfo, &mPhysicalCameraIds); + } CameraDeviceSession::~CameraDeviceSession() { From a757b1bc0df1cd41916dcc7cf8ed1fedc7bb22ab Mon Sep 17 00:00:00 2001 From: Henry Fang Date: Thu, 7 Feb 2019 15:01:05 -0800 Subject: [PATCH 471/718] Add VTS for cas@1.1 hal interface Added sendSessionEvent and onSessionEvent test case, so vts can cover new interface in cas@1.1 Test: Manual bug: 123642769 Change-Id: I3e82a5a7c9d1e8721b2e4fdc2aaffacfe96b91d9 --- cas/1.1/default/MediaCasService.cpp | 55 +- cas/1.1/vts/functional/Android.bp | 35 ++ cas/1.1/vts/functional/OWNERS | 3 + .../functional/VtsHalCasV1_1TargetTest.cpp | 571 ++++++++++++++++++ 4 files changed, 647 insertions(+), 17 deletions(-) create mode 100644 cas/1.1/vts/functional/Android.bp create mode 100644 cas/1.1/vts/functional/OWNERS create mode 100644 cas/1.1/vts/functional/VtsHalCasV1_1TargetTest.cpp diff --git a/cas/1.1/default/MediaCasService.cpp b/cas/1.1/default/MediaCasService.cpp index e2d3357023..eb3fa6b599 100644 --- a/cas/1.1/default/MediaCasService.cpp +++ b/cas/1.1/default/MediaCasService.cpp @@ -32,6 +32,34 @@ namespace cas { namespace V1_1 { namespace implementation { +class Wrapper : public V1_1::ICasListener { + public: + static sp wrap(sp impl) { + sp cast = V1_1::ICasListener::castFrom(impl); + if (cast == NULL) { + cast = new Wrapper(impl); + } + return cast; + } + + virtual Return onEvent(int32_t event, int32_t arg, + const hidl_vec& data) override { + mImpl->onEvent(event, arg, data); + return Void(); + } + + virtual Return onSessionEvent(const hidl_vec& /* sessionId */, + int32_t /* event */, int32_t /* arg */, + const hidl_vec& /*data*/) override { + ALOGV("Do nothing on Session Event for cas@1.0 client in cas@1.1"); + return Void(); + } + + private: + Wrapper(sp impl) : mImpl(impl){}; + sp mImpl; +}; + MediaCasService::MediaCasService() : mCasLoader("createCasFactory"), mDescramblerLoader("createDescramblerFactory") {} @@ -53,30 +81,23 @@ Return MediaCasService::isSystemIdSupported(int32_t CA_system_id) { return mCasLoader.findFactoryForScheme(CA_system_id); } -Return> MediaCasService::createPlugin(int32_t /* CA_system_id */, - const sp& /* listener */) { - ALOGE("%s:Use createPluginExt to create plugin with cas@1.1", __FUNCTION__); +Return> MediaCasService::createPlugin(int32_t CA_system_id, + const sp& listener) { + ALOGV("%s:Use createPluginExt to create plugin in cas@1.1", __FUNCTION__); + + sp result; + + sp listenerV1_1 = Wrapper::wrap(listener); + + result = createPluginExt(CA_system_id, listenerV1_1); - sp result; - /* - CasFactory *factory; - sp library; - if (mCasLoader.findFactoryForScheme(CA_system_id, &library, &factory)) { - CasPlugin *plugin = NULL; - sp casImpl = new CasImpl(listener); - if (factory->createPlugin(CA_system_id, casImpl.get(), - CasImpl::OnEvent, &plugin) == OK && plugin != NULL) { - casImpl->init(library, plugin); - result = casImpl; - } - } - */ return result; } Return> MediaCasService::createPluginExt(int32_t CA_system_id, const sp& listener) { ALOGV("%s: CA_system_id=%d", __FUNCTION__, CA_system_id); + if (listener == NULL) ALOGV("%s: Listener is NULL", __FUNCTION__); sp result; diff --git a/cas/1.1/vts/functional/Android.bp b/cas/1.1/vts/functional/Android.bp new file mode 100644 index 0000000000..8afd19abda --- /dev/null +++ b/cas/1.1/vts/functional/Android.bp @@ -0,0 +1,35 @@ +// +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +cc_test { + name: "VtsHalCasV1_1TargetTest", + defaults: ["VtsHalTargetTestDefaults"], + srcs: ["VtsHalCasV1_1TargetTest.cpp"], + static_libs: [ + "android.hardware.cas@1.0", + "android.hardware.cas@1.1", + "android.hardware.cas.native@1.0", + "android.hidl.allocator@1.0", + "android.hidl.memory@1.0", + "libhidlallocatorutils", + "libhidlmemory", + ], + shared_libs: [ + "libbinder", + ], + test_suites: ["general-tests"], +} + diff --git a/cas/1.1/vts/functional/OWNERS b/cas/1.1/vts/functional/OWNERS new file mode 100644 index 0000000000..29246edc81 --- /dev/null +++ b/cas/1.1/vts/functional/OWNERS @@ -0,0 +1,3 @@ +nchalko@google.com +chz@google.com +quxiangfang@google.com diff --git a/cas/1.1/vts/functional/VtsHalCasV1_1TargetTest.cpp b/cas/1.1/vts/functional/VtsHalCasV1_1TargetTest.cpp new file mode 100644 index 0000000000..88f1fb01d6 --- /dev/null +++ b/cas/1.1/vts/functional/VtsHalCasV1_1TargetTest.cpp @@ -0,0 +1,571 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "mediacas_hidl_hal_test" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CLEAR_KEY_SYSTEM_ID 0xF6D8 +#define INVALID_SYSTEM_ID 0 +#define WAIT_TIMEOUT 3000000000 + +#define PROVISION_STR \ + "{ " \ + " \"id\": 21140844, " \ + " \"name\": \"Test Title\", " \ + " \"lowercase_organization_name\": \"Android\", " \ + " \"asset_key\": { " \ + " \"encryption_key\": \"nezAr3CHFrmBR9R8Tedotw==\" " \ + " }, " \ + " \"cas_type\": 1, " \ + " \"track_types\": [ ] " \ + "} " + +using android::Condition; +using android::IMemory; +using android::IMemoryHeap; +using android::MemoryDealer; +using android::Mutex; +using android::sp; +using android::hardware::fromHeap; +using android::hardware::hidl_string; +using android::hardware::hidl_vec; +using android::hardware::HidlMemory; +using android::hardware::Return; +using android::hardware::Void; +using android::hardware::cas::native::V1_0::BufferType; +using android::hardware::cas::native::V1_0::DestinationBuffer; +using android::hardware::cas::native::V1_0::IDescrambler; +using android::hardware::cas::native::V1_0::ScramblingControl; +using android::hardware::cas::native::V1_0::SharedBuffer; +using android::hardware::cas::native::V1_0::SubSample; +using android::hardware::cas::V1_0::HidlCasPluginDescriptor; +using android::hardware::cas::V1_0::IDescramblerBase; +using android::hardware::cas::V1_0::Status; +using android::hardware::cas::V1_1::ICas; +using android::hardware::cas::V1_1::ICasListener; +using android::hardware::cas::V1_1::IMediaCasService; + +namespace { + +const uint8_t kEcmBinaryBuffer[] = { + 0x00, 0x00, 0x01, 0xf0, 0x00, 0x50, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x46, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x27, 0x10, 0x02, 0x00, + 0x01, 0x77, 0x01, 0x42, 0x95, 0x6c, 0x0e, 0xe3, 0x91, 0xbc, 0xfd, 0x05, 0xb1, 0x60, 0x4f, + 0x17, 0x82, 0xa4, 0x86, 0x9b, 0x23, 0x56, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x27, 0x10, 0x02, 0x00, 0x01, 0x77, 0x01, 0x42, 0x95, 0x6c, 0xd7, 0x43, 0x62, 0xf8, 0x1c, + 0x62, 0x19, 0x05, 0xc7, 0x3a, 0x42, 0xcd, 0xfd, 0xd9, 0x13, 0x48, +}; + +const SubSample kSubSamples[] = {{162, 0}, {0, 184}, {0, 184}}; + +const uint8_t kInBinaryBuffer[] = { + 0x00, 0x00, 0x00, 0x01, 0x09, 0xf0, 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0xc0, 0x1e, 0xdb, + 0x01, 0x40, 0x16, 0xec, 0x04, 0x40, 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x0f, 0x03, + 0xc5, 0x8b, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x68, 0xca, 0x8c, 0xb2, 0x00, 0x00, 0x01, 0x06, + 0x05, 0xff, 0xff, 0x70, 0xdc, 0x45, 0xe9, 0xbd, 0xe6, 0xd9, 0x48, 0xb7, 0x96, 0x2c, 0xd8, + 0x20, 0xd9, 0x23, 0xee, 0xef, 0x78, 0x32, 0x36, 0x34, 0x20, 0x2d, 0x20, 0x63, 0x6f, 0x72, + 0x65, 0x20, 0x31, 0x34, 0x32, 0x20, 0x2d, 0x20, 0x48, 0x2e, 0x32, 0x36, 0x34, 0x2f, 0x4d, + 0x50, 0x45, 0x47, 0x2d, 0x34, 0x20, 0x41, 0x56, 0x43, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x63, + 0x20, 0x2d, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x32, 0x30, 0x30, + 0x33, 0x2d, 0x32, 0x30, 0x31, 0x34, 0x20, 0x2d, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, + 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x6c, 0x61, 0x6e, 0x2e, 0x6f, + 0x72, 0x67, 0x2f, 0x78, 0x32, 0x36, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x6e, 0x45, 0x21, + 0x82, 0x38, 0xf0, 0x9d, 0x7d, 0x96, 0xe6, 0x94, 0xae, 0xe2, 0x87, 0x8f, 0x04, 0x49, 0xe5, + 0xf6, 0x8c, 0x8b, 0x9a, 0x10, 0x18, 0xba, 0x94, 0xe9, 0x22, 0x31, 0x04, 0x7e, 0x60, 0x5b, + 0xc4, 0x24, 0x00, 0x90, 0x62, 0x0d, 0xdc, 0x85, 0x74, 0x75, 0x78, 0xd0, 0x14, 0x08, 0xcb, + 0x02, 0x1d, 0x7d, 0x9d, 0x34, 0xe8, 0x81, 0xb9, 0xf7, 0x09, 0x28, 0x79, 0x29, 0x8d, 0xe3, + 0x14, 0xed, 0x5f, 0xca, 0xaf, 0xf4, 0x1c, 0x49, 0x15, 0xe1, 0x80, 0x29, 0x61, 0x76, 0x80, + 0x43, 0xf8, 0x58, 0x53, 0x40, 0xd7, 0x31, 0x6d, 0x61, 0x81, 0x41, 0xe9, 0x77, 0x9f, 0x9c, + 0xe1, 0x6d, 0xf2, 0xee, 0xd9, 0xc8, 0x67, 0xd2, 0x5f, 0x48, 0x73, 0xe3, 0x5c, 0xcd, 0xa7, + 0x45, 0x58, 0xbb, 0xdd, 0x28, 0x1d, 0x68, 0xfc, 0xb4, 0xc6, 0xf6, 0x92, 0xf6, 0x30, 0x03, + 0xaa, 0xe4, 0x32, 0xf6, 0x34, 0x51, 0x4b, 0x0f, 0x8c, 0xf9, 0xac, 0x98, 0x22, 0xfb, 0x49, + 0xc8, 0xbf, 0xca, 0x8c, 0x80, 0x86, 0x5d, 0xd7, 0xa4, 0x52, 0xb1, 0xd9, 0xa6, 0x04, 0x4e, + 0xb3, 0x2d, 0x1f, 0xb8, 0x35, 0xcc, 0x45, 0x6d, 0x9c, 0x20, 0xa7, 0xa4, 0x34, 0x59, 0x72, + 0xe3, 0xae, 0xba, 0x49, 0xde, 0xd1, 0xaa, 0xee, 0x3d, 0x77, 0xfc, 0x5d, 0xc6, 0x1f, 0x9d, + 0xac, 0xc2, 0x15, 0x66, 0xb8, 0xe1, 0x54, 0x4e, 0x74, 0x93, 0xdb, 0x9a, 0x24, 0x15, 0x6e, + 0x20, 0xa3, 0x67, 0x3e, 0x5a, 0x24, 0x41, 0x5e, 0xb0, 0xe6, 0x35, 0x87, 0x1b, 0xc8, 0x7a, + 0xf9, 0x77, 0x65, 0xe0, 0x01, 0xf2, 0x4c, 0xe4, 0x2b, 0xa9, 0x64, 0x96, 0x96, 0x0b, 0x46, + 0xca, 0xea, 0x79, 0x0e, 0x78, 0xa3, 0x5f, 0x43, 0xfc, 0x47, 0x6a, 0x12, 0xfa, 0xc4, 0x33, + 0x0e, 0x88, 0x1c, 0x19, 0x3a, 0x00, 0xc3, 0x4e, 0xb5, 0xd8, 0xfa, 0x8e, 0xf1, 0xbc, 0x3d, + 0xb2, 0x7e, 0x50, 0x8d, 0x67, 0xc3, 0x6b, 0xed, 0xe2, 0xea, 0xa6, 0x1f, 0x25, 0x24, 0x7c, + 0x94, 0x74, 0x50, 0x49, 0xe3, 0xc6, 0x58, 0x2e, 0xfd, 0x28, 0xb4, 0xc6, 0x73, 0xb1, 0x53, + 0x74, 0x27, 0x94, 0x5c, 0xdf, 0x69, 0xb7, 0xa1, 0xd7, 0xf5, 0xd3, 0x8a, 0x2c, 0x2d, 0xb4, + 0x5e, 0x8a, 0x16, 0x14, 0x54, 0x64, 0x6e, 0x00, 0x6b, 0x11, 0x59, 0x8a, 0x63, 0x38, 0x80, + 0x76, 0xc3, 0xd5, 0x59, 0xf7, 0x3f, 0xd2, 0xfa, 0xa5, 0xca, 0x82, 0xff, 0x4a, 0x62, 0xf0, + 0xe3, 0x42, 0xf9, 0x3b, 0x38, 0x27, 0x8a, 0x89, 0xaa, 0x50, 0x55, 0x4b, 0x29, 0xf1, 0x46, + 0x7c, 0x75, 0xef, 0x65, 0xaf, 0x9b, 0x0d, 0x6d, 0xda, 0x25, 0x94, 0x14, 0xc1, 0x1b, 0xf0, + 0xc5, 0x4c, 0x24, 0x0e, 0x65, +}; + +const uint8_t kOutRefBinaryBuffer[] = { + 0x00, 0x00, 0x00, 0x01, 0x09, 0xf0, 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0xc0, 0x1e, 0xdb, + 0x01, 0x40, 0x16, 0xec, 0x04, 0x40, 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x0f, 0x03, + 0xc5, 0x8b, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x68, 0xca, 0x8c, 0xb2, 0x00, 0x00, 0x01, 0x06, + 0x05, 0xff, 0xff, 0x70, 0xdc, 0x45, 0xe9, 0xbd, 0xe6, 0xd9, 0x48, 0xb7, 0x96, 0x2c, 0xd8, + 0x20, 0xd9, 0x23, 0xee, 0xef, 0x78, 0x32, 0x36, 0x34, 0x20, 0x2d, 0x20, 0x63, 0x6f, 0x72, + 0x65, 0x20, 0x31, 0x34, 0x32, 0x20, 0x2d, 0x20, 0x48, 0x2e, 0x32, 0x36, 0x34, 0x2f, 0x4d, + 0x50, 0x45, 0x47, 0x2d, 0x34, 0x20, 0x41, 0x56, 0x43, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x63, + 0x20, 0x2d, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x32, 0x30, 0x30, + 0x33, 0x2d, 0x32, 0x30, 0x31, 0x34, 0x20, 0x2d, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, + 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x6c, 0x61, 0x6e, 0x2e, 0x6f, + 0x72, 0x67, 0x2f, 0x78, 0x32, 0x36, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20, 0x2d, 0x20, + 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x20, 0x63, 0x61, 0x62, 0x61, 0x63, 0x3d, + 0x30, 0x20, 0x72, 0x65, 0x66, 0x3d, 0x32, 0x20, 0x64, 0x65, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x3d, 0x31, 0x3a, 0x30, 0x3a, 0x30, 0x20, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x65, 0x3d, + 0x30, 0x78, 0x31, 0x3a, 0x30, 0x78, 0x31, 0x31, 0x31, 0x20, 0x6d, 0x65, 0x3d, 0x68, 0x65, + 0x78, 0x20, 0x73, 0x75, 0x62, 0x6d, 0x65, 0x3d, 0x37, 0x20, 0x70, 0x73, 0x79, 0x3d, 0x31, + 0x20, 0x70, 0x73, 0x79, 0x5f, 0x72, 0x64, 0x3d, 0x31, 0x2e, 0x30, 0x30, 0x3a, 0x30, 0x2e, + 0x30, 0x30, 0x20, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x3d, 0x31, 0x20, + 0x6d, 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x3d, 0x31, 0x36, 0x20, 0x63, 0x68, 0x72, + 0x6f, 0x6d, 0x61, 0x5f, 0x6d, 0x65, 0x3d, 0x31, 0x20, 0x74, 0x72, 0x65, 0x6c, 0x6c, 0x69, + 0x73, 0x3d, 0x31, 0x20, 0x38, 0x78, 0x38, 0x64, 0x63, 0x74, 0x3d, 0x30, 0x20, 0x63, 0x71, + 0x6d, 0x3d, 0x30, 0x20, 0x64, 0x65, 0x61, 0x64, 0x7a, 0x6f, 0x6e, 0x65, 0x3d, 0x32, 0x31, + 0x2c, 0x31, 0x31, 0x20, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x70, 0x73, 0x6b, 0x69, 0x70, 0x3d, + 0x31, 0x20, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x5f, 0x71, 0x70, 0x5f, 0x6f, 0x66, 0x66, + 0x73, 0x65, 0x74, 0x3d, 0x2d, 0x32, 0x20, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, + 0x36, 0x30, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x61, 0x68, 0x65, 0x61, 0x64, 0x5f, 0x74, 0x68, + 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, 0x35, 0x20, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x64, 0x5f, + 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, 0x30, 0x20, 0x6e, 0x72, 0x3d, 0x30, 0x20, + 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x3d, 0x31, 0x20, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6c, 0x61, 0x63, 0x65, 0x64, 0x3d, 0x30, 0x20, 0x62, 0x6c, 0x75, 0x72, 0x61, 0x79, + 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x3d, 0x30, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, + 0x72, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x72, 0x61, 0x3d, 0x30, 0x20, + 0x62, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x3d, 0x30, 0x20, 0x77, 0x65, 0x69, 0x67, 0x68, + 0x74, 0x70, 0x3d, 0x30, 0x20, 0x6b, 0x65, 0x79, 0x69, 0x6e, 0x74, 0x3d, 0x32, 0x35, 0x30, + 0x20, 0x6b, 0x65, 0x79, 0x69, 0x6e, 0x74, 0x5f, 0x6d, 0x69, 0x6e, 0x3d, 0x32, 0x35, 0x20, + 0x73, 0x63, 0x65, 0x6e, 0x65, +}; + +class MediaCasListener : public ICasListener { + public: + virtual Return onEvent(int32_t event, int32_t arg, + const hidl_vec& data) override { + android::Mutex::Autolock autoLock(mMsgLock); + mEvent = event; + mEventArg = arg; + mEventData = data; + + mEventReceived = true; + mMsgCondition.signal(); + return Void(); + } + + virtual Return onSessionEvent(const hidl_vec& sessionId, int32_t event, + int32_t arg, const hidl_vec& data) override { + android::Mutex::Autolock autoLock(mMsgLock); + mSessionId = sessionId; + mEvent = event; + mEventArg = arg; + mEventData = data; + + mEventReceived = true; + mMsgCondition.signal(); + return Void(); + } + + void testEventEcho(sp& mediaCas, int32_t& event, int32_t& eventArg, + hidl_vec& eventData); + + void testSessionEventEcho(sp& mediaCas, const hidl_vec& sessionId, + int32_t& event, int32_t& eventArg, hidl_vec& eventData); + + private: + int32_t mEvent = -1; + int32_t mEventArg = -1; + bool mEventReceived = false; + hidl_vec mEventData; + hidl_vec mSessionId; + android::Mutex mMsgLock; + android::Condition mMsgCondition; +}; + +void MediaCasListener::testEventEcho(sp& mediaCas, int32_t& event, int32_t& eventArg, + hidl_vec& eventData) { + mEventReceived = false; + auto returnStatus = mediaCas->sendEvent(event, eventArg, eventData); + EXPECT_TRUE(returnStatus.isOk()); + EXPECT_EQ(Status::OK, returnStatus); + + android::Mutex::Autolock autoLock(mMsgLock); + while (!mEventReceived) { + if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) { + EXPECT_TRUE(false) << "event not received within timeout"; + return; + } + } + + EXPECT_EQ(mEvent, event); + EXPECT_EQ(mEventArg, eventArg); + EXPECT_TRUE(mEventData == eventData); +} + +void MediaCasListener::testSessionEventEcho(sp& mediaCas, const hidl_vec& sessionId, + int32_t& event, int32_t& eventArg, + hidl_vec& eventData) { + mEventReceived = false; + auto returnStatus = mediaCas->sendSessionEvent(sessionId, event, eventArg, eventData); + EXPECT_TRUE(returnStatus.isOk()); + EXPECT_EQ(Status::OK, returnStatus); + + android::Mutex::Autolock autoLock(mMsgLock); + while (!mEventReceived) { + if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) { + EXPECT_TRUE(false) << "event not received within timeout"; + return; + } + } + + EXPECT_TRUE(mSessionId == sessionId); + EXPECT_EQ(mEvent, event); + EXPECT_EQ(mEventArg, eventArg); + EXPECT_TRUE(mEventData == eventData); +} + +// Test environment for Cas HIDL HAL. +class CasHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { + public: + // get the test environment singleton + static CasHidlEnvironment* Instance() { + static CasHidlEnvironment* instance = new CasHidlEnvironment; + return instance; + } + + virtual void registerTestServices() override { registerTestService(); } +}; + +class MediaCasHidlTest : public ::testing::VtsHalHidlTargetTestBase { + public: + virtual void SetUp() override { + mService = ::testing::VtsHalHidlTargetTestBase::getService( + CasHidlEnvironment::Instance()->getServiceName()); + ASSERT_NE(mService, nullptr); + } + + sp mService; + + protected: + static void description(const std::string& description) { + RecordProperty("description", description); + } + + sp mMediaCas; + sp mDescramblerBase; + sp mCasListener; + typedef struct _OobInputTestParams { + const SubSample* subSamples; + uint32_t numSubSamples; + size_t imemSizeActual; + uint64_t imemOffset; + uint64_t imemSize; + uint64_t srcOffset; + uint64_t dstOffset; + } OobInputTestParams; + + ::testing::AssertionResult createCasPlugin(int32_t caSystemId); + ::testing::AssertionResult openCasSession(std::vector* sessionId); + ::testing::AssertionResult descrambleTestInputBuffer(const sp& descrambler, + Status* descrambleStatus, + sp* hidlInMemory); + ::testing::AssertionResult descrambleTestOobInput(const sp& descrambler, + Status* descrambleStatus, + const OobInputTestParams& params); +}; + +::testing::AssertionResult MediaCasHidlTest::createCasPlugin(int32_t caSystemId) { + auto status = mService->isSystemIdSupported(caSystemId); + if (!status.isOk() || !status) { + return ::testing::AssertionFailure(); + } + status = mService->isDescramblerSupported(caSystemId); + if (!status.isOk() || !status) { + return ::testing::AssertionFailure(); + } + + mCasListener = new MediaCasListener(); + auto pluginStatus = mService->createPluginExt(caSystemId, mCasListener); + if (!pluginStatus.isOk()) { + return ::testing::AssertionFailure(); + } + mMediaCas = pluginStatus; + if (mMediaCas == nullptr) { + return ::testing::AssertionFailure(); + } + + auto descramblerStatus = mService->createDescrambler(caSystemId); + if (!descramblerStatus.isOk()) { + return ::testing::AssertionFailure(); + } + mDescramblerBase = descramblerStatus; + return ::testing::AssertionResult(mDescramblerBase != nullptr); +} + +::testing::AssertionResult MediaCasHidlTest::openCasSession(std::vector* sessionId) { + Status sessionStatus; + auto returnVoid = mMediaCas->openSession([&](Status status, const hidl_vec& id) { + sessionStatus = status; + *sessionId = id; + }); + return ::testing::AssertionResult(returnVoid.isOk() && (Status::OK == sessionStatus)); +} + +::testing::AssertionResult MediaCasHidlTest::descrambleTestInputBuffer( + const sp& descrambler, Status* descrambleStatus, sp* inMemory) { + hidl_vec hidlSubSamples; + hidlSubSamples.setToExternal(const_cast(kSubSamples), + (sizeof(kSubSamples) / sizeof(SubSample)), false /*own*/); + + sp dealer = new MemoryDealer(sizeof(kInBinaryBuffer), "vts-cas"); + if (nullptr == dealer.get()) { + ALOGE("couldn't get MemoryDealer!"); + return ::testing::AssertionFailure(); + } + + sp mem = dealer->allocate(sizeof(kInBinaryBuffer)); + if (nullptr == mem.get()) { + ALOGE("couldn't allocate IMemory!"); + return ::testing::AssertionFailure(); + } + *inMemory = mem; + + // build HidlMemory from memory heap + ssize_t offset; + size_t size; + sp heap = mem->getMemory(&offset, &size); + if (nullptr == heap.get()) { + ALOGE("couldn't get memory heap!"); + return ::testing::AssertionFailure(); + } + + uint8_t* ipBuffer = static_cast(static_cast(mem->pointer())); + memcpy(ipBuffer, kInBinaryBuffer, sizeof(kInBinaryBuffer)); + + // hidlMemory is not to be passed out of scope! + sp hidlMemory = fromHeap(heap); + + SharedBuffer srcBuffer = { + .heapBase = *hidlMemory, .offset = (uint64_t)offset, .size = (uint64_t)size}; + + DestinationBuffer dstBuffer; + dstBuffer.type = BufferType::SHARED_MEMORY; + dstBuffer.nonsecureMemory = srcBuffer; + + uint32_t outBytes; + hidl_string detailedError; + auto returnVoid = descrambler->descramble( + ScramblingControl::EVENKEY /*2*/, hidlSubSamples, srcBuffer, 0, dstBuffer, 0, + [&](Status status, uint32_t bytesWritten, const hidl_string& detailedErr) { + *descrambleStatus = status; + outBytes = bytesWritten; + detailedError = detailedErr; + }); + if (!returnVoid.isOk() || *descrambleStatus != Status::OK) { + ALOGI("descramble failed, trans=%s, status=%d, outBytes=%u, error=%s", + returnVoid.description().c_str(), *descrambleStatus, outBytes, detailedError.c_str()); + } + return ::testing::AssertionResult(returnVoid.isOk()); +} + +::testing::AssertionResult MediaCasHidlTest::descrambleTestOobInput( + const sp& descrambler, Status* descrambleStatus, + const OobInputTestParams& params) { + hidl_vec hidlSubSamples; + hidlSubSamples.setToExternal(const_cast(params.subSamples), params.numSubSamples, + false /*own*/); + + sp dealer = new MemoryDealer(params.imemSizeActual, "vts-cas"); + if (nullptr == dealer.get()) { + ALOGE("couldn't get MemoryDealer!"); + return ::testing::AssertionFailure(); + } + + sp mem = dealer->allocate(params.imemSizeActual); + if (nullptr == mem.get()) { + ALOGE("couldn't allocate IMemory!"); + return ::testing::AssertionFailure(); + } + + // build HidlMemory from memory heap + ssize_t offset; + size_t size; + sp heap = mem->getMemory(&offset, &size); + if (nullptr == heap.get()) { + ALOGE("couldn't get memory heap!"); + return ::testing::AssertionFailure(); + } + + // hidlMemory is not to be passed out of scope! + sp hidlMemory = fromHeap(heap); + + SharedBuffer srcBuffer = { + .heapBase = *hidlMemory, + .offset = (uint64_t)offset + params.imemOffset, + .size = (uint64_t)params.imemSize, + }; + + DestinationBuffer dstBuffer; + dstBuffer.type = BufferType::SHARED_MEMORY; + dstBuffer.nonsecureMemory = srcBuffer; + + uint32_t outBytes; + hidl_string detailedError; + auto returnVoid = descrambler->descramble( + ScramblingControl::EVENKEY /*2*/, hidlSubSamples, srcBuffer, params.srcOffset, + dstBuffer, params.dstOffset, + [&](Status status, uint32_t bytesWritten, const hidl_string& detailedErr) { + *descrambleStatus = status; + outBytes = bytesWritten; + detailedError = detailedErr; + }); + if (!returnVoid.isOk() || *descrambleStatus != Status::OK) { + ALOGI("descramble failed, trans=%s, status=%d, outBytes=%u, error=%s", + returnVoid.description().c_str(), *descrambleStatus, outBytes, detailedError.c_str()); + } + return ::testing::AssertionResult(returnVoid.isOk()); +} + +TEST_F(MediaCasHidlTest, TestClearKeyApisWithSession) { + description("Test that valid call sequences with SessionEvent send and receive"); + + ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID)); + + auto returnStatus = mMediaCas->provision(hidl_string(PROVISION_STR)); + EXPECT_TRUE(returnStatus.isOk()); + EXPECT_EQ(Status::OK, returnStatus); + + hidl_vec hidlPvtData; + hidlPvtData.resize(256); + returnStatus = mMediaCas->setPrivateData(hidlPvtData); + EXPECT_TRUE(returnStatus.isOk()); + EXPECT_EQ(Status::OK, returnStatus); + + std::vector sessionId; + ASSERT_TRUE(openCasSession(&sessionId)); + returnStatus = mMediaCas->setSessionPrivateData(sessionId, hidlPvtData); + EXPECT_TRUE(returnStatus.isOk()); + EXPECT_EQ(Status::OK, returnStatus); + + std::vector streamSessionId; + ASSERT_TRUE(openCasSession(&streamSessionId)); + returnStatus = mMediaCas->setSessionPrivateData(streamSessionId, hidlPvtData); + EXPECT_TRUE(returnStatus.isOk()); + EXPECT_EQ(Status::OK, returnStatus); + + returnStatus = mDescramblerBase->setMediaCasSession(sessionId); + EXPECT_TRUE(returnStatus.isOk()); + EXPECT_EQ(Status::OK, returnStatus); + + returnStatus = mDescramblerBase->setMediaCasSession(streamSessionId); + EXPECT_TRUE(returnStatus.isOk()); + EXPECT_EQ(Status::OK, returnStatus); + + hidl_vec hidlNullPtr; + hidlNullPtr.setToExternal(static_cast(nullptr), 0); + returnStatus = mMediaCas->refreshEntitlements(3, hidlNullPtr); + EXPECT_TRUE(returnStatus.isOk()); + EXPECT_EQ(Status::OK, returnStatus); + + uint8_t refreshData[] = {0, 1, 2, 3}; + hidl_vec hidlRefreshData; + hidlRefreshData.setToExternal(static_cast(refreshData), sizeof(refreshData)); + returnStatus = mMediaCas->refreshEntitlements(10, hidlRefreshData); + EXPECT_TRUE(returnStatus.isOk()); + EXPECT_EQ(Status::OK, returnStatus); + + int32_t eventID = 1; + int32_t eventArg = 2; + mCasListener->testEventEcho(mMediaCas, eventID, eventArg, hidlNullPtr); + mCasListener->testSessionEventEcho(mMediaCas, sessionId, eventID, eventArg, hidlNullPtr); + + eventID = 3; + eventArg = 4; + uint8_t eventData[] = {'e', 'v', 'e', 'n', 't', 'd', 'a', 't', 'a'}; + hidl_vec hidlEventData; + hidlEventData.setToExternal(static_cast(eventData), sizeof(eventData)); + mCasListener->testEventEcho(mMediaCas, eventID, eventArg, hidlEventData); + mCasListener->testSessionEventEcho(mMediaCas, sessionId, eventID, eventArg, hidlEventData); + + uint8_t clearKeyEmmData[] = {'c', 'l', 'e', 'a', 'r', 'k', 'e', 'y', 'e', 'm', 'm'}; + hidl_vec hidlClearKeyEmm; + hidlClearKeyEmm.setToExternal(static_cast(clearKeyEmmData), sizeof(clearKeyEmmData)); + returnStatus = mMediaCas->processEmm(hidlClearKeyEmm); + EXPECT_TRUE(returnStatus.isOk()); + EXPECT_EQ(Status::OK, returnStatus); + + hidl_vec hidlEcm; + hidlEcm.setToExternal(const_cast(kEcmBinaryBuffer), sizeof(kEcmBinaryBuffer)); + returnStatus = mMediaCas->processEcm(sessionId, hidlEcm); + EXPECT_TRUE(returnStatus.isOk()); + EXPECT_EQ(Status::OK, returnStatus); + returnStatus = mMediaCas->processEcm(streamSessionId, hidlEcm); + EXPECT_TRUE(returnStatus.isOk()); + EXPECT_EQ(Status::OK, returnStatus); + + EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent("video/avc")); + + sp descrambler; + descrambler = IDescrambler::castFrom(mDescramblerBase); + ASSERT_NE(descrambler, nullptr); + + Status descrambleStatus = Status::OK; + sp dataMemory; + + ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory)); + EXPECT_EQ(Status::OK, descrambleStatus); + + ASSERT_NE(nullptr, dataMemory.get()); + uint8_t* opBuffer = static_cast(static_cast(dataMemory->pointer())); + + int compareResult = + memcmp(static_cast(opBuffer), + static_cast(kOutRefBinaryBuffer), sizeof(kOutRefBinaryBuffer)); + EXPECT_EQ(0, compareResult); + + returnStatus = mDescramblerBase->release(); + EXPECT_TRUE(returnStatus.isOk()); + EXPECT_EQ(Status::OK, returnStatus); + + returnStatus = mMediaCas->release(); + EXPECT_TRUE(returnStatus.isOk()); + EXPECT_EQ(Status::OK, returnStatus); +} + +} // anonymous namespace + +int main(int argc, char** argv) { + ::testing::AddGlobalTestEnvironment(CasHidlEnvironment::Instance()); + ::testing::InitGoogleTest(&argc, argv); + CasHidlEnvironment::Instance()->init(&argc, argv); + int status = RUN_ALL_TESTS(); + LOG(INFO) << "Test result = " << status; + return status; +} From 22eac5f667dfca8de336ddc45ad60a08250f6b30 Mon Sep 17 00:00:00 2001 From: Emilian Peev Date: Wed, 23 Jan 2019 11:14:11 -0800 Subject: [PATCH 472/718] Camera: Enable session parameter reconfiguration queries Check with Hal whether stream reconfiguration is required in case of session parameter updates. Bug: 122609098 Test: Manual using application, vts-tradefed run commandAndExit vts --skip-all-system-status-check --skip-preconditions --module VtsHalCameraProviderV2_4Target -l INFO Change-Id: Ic02525871aa079393b28b2da53764093f95f881d --- camera/device/3.5/ICameraDeviceSession.hal | 46 +++++++++++++++ .../3.5/default/CameraDeviceSession.cpp | 29 ++++++++++ .../default/ExternalCameraDeviceSession.cpp | 9 +++ .../device_v3_5_impl/CameraDeviceSession.h | 8 +++ .../ExternalCameraDeviceSession.h | 10 ++++ .../VtsHalCameraProviderV2_4TargetTest.cpp | 58 +++++++++++++++++-- 6 files changed, 155 insertions(+), 5 deletions(-) diff --git a/camera/device/3.5/ICameraDeviceSession.hal b/camera/device/3.5/ICameraDeviceSession.hal index b2b71cdd35..d0cfe392ae 100644 --- a/camera/device/3.5/ICameraDeviceSession.hal +++ b/camera/device/3.5/ICameraDeviceSession.hal @@ -17,6 +17,7 @@ package android.hardware.camera.device@3.5; import android.hardware.camera.common@1.0::Status; +import @3.2::CameraMetadata; import @3.4::ICameraDeviceSession; import @3.4::HalStreamConfiguration; @@ -99,4 +100,49 @@ interface ICameraDeviceSession extends @3.4::ICameraDeviceSession { vec streamIds, uint32_t streamConfigCounter ); + + /** + * isReconfigurationRequired: + * + * Check whether complete stream reconfiguration is required for possible new session + * parameter values. + * + * This method must be called by the camera framework in case the client changes + * the value of any advertised session parameters. Depending on the specific values + * the HAL can decide whether a complete stream reconfiguration is required. In case + * the HAL returns false, the camera framework must skip the internal reconfiguration. + * In case Hal returns true, the framework must reconfigure the streams and pass the + * new session parameter values accordingly. + * This call may be done by the framework some time before the request with new parameters + * is submitted to the HAL, and the request may be cancelled before it ever gets submitted. + * Therefore, the HAL must not use this query as an indication to change its behavior in any + * way. + * ------------------------------------------------------------------------ + * + * Preconditions: + * + * The framework can call this method at any time after active + * session configuration. There must be no impact on the performance of + * pending camera requests in any way. In particular there must not be + * any glitches or delays during normal camera streaming. + * + * Performance requirements: + * HW and SW camera settings must not be changed and there must not be + * a user-visible impact on camera performance. + * + * @param oldSessionParams Before session parameters, usually the current session parameters. + * @param newSessionParams The new session parameters which may be set by client. + * + * @return Status Status code for the operation, one of: + * OK: + * On successful reconfiguration required query. + * METHOD_NOT_SUPPORTED: + * The camera device does not support the reconfiguration query. + * INTERNAL_ERROR: + * The reconfiguration query cannot complete due to internal + * error. + * @return true in case the stream reconfiguration is required, false otherwise. + */ + isReconfigurationRequired(CameraMetadata oldSessionParams, CameraMetadata newSessionParams) + generates(Status status, bool reconfigurationNeeded); }; diff --git a/camera/device/3.5/default/CameraDeviceSession.cpp b/camera/device/3.5/default/CameraDeviceSession.cpp index 0770f0418c..d9c6eef5ad 100644 --- a/camera/device/3.5/default/CameraDeviceSession.cpp +++ b/camera/device/3.5/default/CameraDeviceSession.cpp @@ -356,6 +356,35 @@ void CameraDeviceSession::sReturnStreamBuffers( d->returnStreamBuffers(num_buffers, buffers); } +Return CameraDeviceSession::isReconfigurationRequired( + const V3_2::CameraMetadata& oldSessionParams, const V3_2::CameraMetadata& newSessionParams, + ICameraDeviceSession::isReconfigurationRequired_cb _hidl_cb) { + if (mDevice->ops->is_reconfiguration_required != nullptr) { + const camera_metadata_t *oldParams, *newParams; + V3_2::implementation::convertFromHidl(oldSessionParams, &oldParams); + V3_2::implementation::convertFromHidl(newSessionParams, &newParams); + auto ret = mDevice->ops->is_reconfiguration_required(mDevice, oldParams, newParams); + switch (ret) { + case 0: + _hidl_cb(Status::OK, true); + break; + case -EINVAL: + _hidl_cb(Status::OK, false); + break; + case -ENOSYS: + _hidl_cb(Status::METHOD_NOT_SUPPORTED, true); + break; + default: + _hidl_cb(Status::INTERNAL_ERROR, true); + break; + }; + } else { + _hidl_cb(Status::METHOD_NOT_SUPPORTED, true); + } + + return Void(); +} + } // namespace implementation } // namespace V3_5 } // namespace device diff --git a/camera/device/3.5/default/ExternalCameraDeviceSession.cpp b/camera/device/3.5/default/ExternalCameraDeviceSession.cpp index ae7c45e081..00c1d0de39 100644 --- a/camera/device/3.5/default/ExternalCameraDeviceSession.cpp +++ b/camera/device/3.5/default/ExternalCameraDeviceSession.cpp @@ -295,6 +295,15 @@ int ExternalCameraDeviceSession::OutputThread::waitForBufferRequestDone( return 0; } +Return ExternalCameraDeviceSession::isReconfigurationRequired( + const V3_2::CameraMetadata& /*oldSessionParams*/, + const V3_2::CameraMetadata& /*newSessionParams*/, + ICameraDeviceSession::isReconfigurationRequired_cb _hidl_cb) { + //Stub implementation + _hidl_cb(Status::OK, true); + return Void(); +} + } // namespace implementation } // namespace V3_5 } // namespace device diff --git a/camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h b/camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h index 4f7284c5fe..87d616c5e1 100644 --- a/camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h +++ b/camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h @@ -93,6 +93,9 @@ protected: hidl_vec& allBufPtrs, hidl_vec& allFences) override; + Return isReconfigurationRequired(const V3_2::CameraMetadata& oldSessionParams, + const V3_2::CameraMetadata& newSessionParams, + ICameraDeviceSession::isReconfigurationRequired_cb _hidl_cb); /** * Static callback forwarding methods from HAL to instance */ @@ -238,6 +241,11 @@ private: return mParent->signalStreamFlush(requests, streamConfigCounter); } + virtual Return isReconfigurationRequired(const V3_2::CameraMetadata& oldSessionParams, + const V3_2::CameraMetadata& newSessionParams, + ICameraDeviceSession::isReconfigurationRequired_cb _hidl_cb) override { + return mParent->isReconfigurationRequired(oldSessionParams, newSessionParams, _hidl_cb); + } private: sp mParent; }; diff --git a/camera/device/3.5/default/include/ext_device_v3_5_impl/ExternalCameraDeviceSession.h b/camera/device/3.5/default/include/ext_device_v3_5_impl/ExternalCameraDeviceSession.h index aa119fc183..d2b5e8936f 100644 --- a/camera/device/3.5/default/include/ext_device_v3_5_impl/ExternalCameraDeviceSession.h +++ b/camera/device/3.5/default/include/ext_device_v3_5_impl/ExternalCameraDeviceSession.h @@ -106,6 +106,10 @@ protected: const hidl_vec& requests, uint32_t streamConfigCounter); + Return isReconfigurationRequired(const V3_2::CameraMetadata& oldSessionParams, + const V3_2::CameraMetadata& newSessionParams, + ICameraDeviceSession::isReconfigurationRequired_cb _hidl_cb); + virtual void initOutputThread() override; virtual void closeOutputThread() override; void closeOutputThreadImpl(); @@ -247,6 +251,12 @@ private: return mParent->signalStreamFlush(requests, streamConfigCounter); } + virtual Return isReconfigurationRequired(const V3_2::CameraMetadata& oldSessionParams, + const V3_2::CameraMetadata& newSessionParams, + ICameraDeviceSession::isReconfigurationRequired_cb _hidl_cb) override { + return mParent->isReconfigurationRequired(oldSessionParams, newSessionParams, _hidl_cb); + } + private: sp mParent; }; diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp index fb7848372e..394934626f 100644 --- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp +++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp @@ -779,6 +779,9 @@ public: hidl_vec streamIds, sp cb, uint32_t streamConfigCounter = 0); + void verifySessionReconfigurationQuery(sp session3_5, + camera_metadata* oldSessionParams, camera_metadata* newSessionParams); + static Status getAvailableOutputStreams(camera_metadata_t *staticMeta, std::vector &outputStreams, const AvailableStream *threshold = nullptr); @@ -3303,7 +3306,8 @@ TEST_F(CameraHidlTest, configureStreamsWithSessionParameters) { } android::hardware::camera::common::V1_0::helper::CameraMetadata previewRequestSettings; - android::hardware::camera::common::V1_0::helper::CameraMetadata sessionParams; + android::hardware::camera::common::V1_0::helper::CameraMetadata sessionParams, + modifiedSessionParams; constructFilteredSettings(session, availableSessionKeys, RequestTemplate::PREVIEW, &previewRequestSettings, &sessionParams); if (sessionParams.isEmpty()) { @@ -3334,13 +3338,28 @@ TEST_F(CameraHidlTest, configureStreamsWithSessionParameters) { ::android::hardware::camera::device::V3_5::StreamConfiguration config3_5; config.streams = streams; config.operationMode = StreamConfigurationMode::NORMAL_MODE; - const camera_metadata_t *sessionParamsBuffer = sessionParams.getAndLock(); - config.sessionParams.setToExternal( - reinterpret_cast (const_cast (sessionParamsBuffer)), + modifiedSessionParams = sessionParams; + auto sessionParamsBuffer = sessionParams.release(); + config.sessionParams.setToExternal(reinterpret_cast (sessionParamsBuffer), get_camera_metadata_size(sessionParamsBuffer)); config3_5.v3_4 = config; config3_5.streamConfigCounter = 0; if (session3_5 != nullptr) { + bool newSessionParamsAvailable = false; + for (const auto& it : availableSessionKeys) { + if (modifiedSessionParams.exists(it)) { + modifiedSessionParams.erase(it); + newSessionParamsAvailable = true; + break; + } + } + if (newSessionParamsAvailable) { + auto modifiedSessionParamsBuffer = modifiedSessionParams.release(); + verifySessionReconfigurationQuery(session3_5, sessionParamsBuffer, + modifiedSessionParamsBuffer); + modifiedSessionParams.acquire(modifiedSessionParamsBuffer); + } + ret = session3_5->configureStreams_3_5(config3_5, [](Status s, device::V3_4::HalStreamConfiguration halConfig) { ASSERT_EQ(Status::OK, s); @@ -3353,7 +3372,7 @@ TEST_F(CameraHidlTest, configureStreamsWithSessionParameters) { ASSERT_EQ(1u, halConfig.streams.size()); }); } - + sessionParams.acquire(sessionParamsBuffer); ASSERT_TRUE(ret.isOk()); free_camera_metadata(staticMetaBuffer); @@ -6096,6 +6115,35 @@ void CameraHidlTest::verifyRecommendedConfigs(const CameraMetadata& chars) { } } +void CameraHidlTest::verifySessionReconfigurationQuery( + sp session3_5, camera_metadata* oldSessionParams, + camera_metadata* newSessionParams) { + ASSERT_NE(nullptr, session3_5.get()); + ASSERT_NE(nullptr, oldSessionParams); + ASSERT_NE(nullptr, newSessionParams); + + android::hardware::hidl_vec oldParams, newParams; + oldParams.setToExternal(reinterpret_cast(oldSessionParams), + get_camera_metadata_size(oldSessionParams)); + newParams.setToExternal(reinterpret_cast(newSessionParams), + get_camera_metadata_size(newSessionParams)); + android::hardware::camera::common::V1_0::Status callStatus; + auto hidlCb = [&callStatus] (android::hardware::camera::common::V1_0::Status s, + bool /*requiredFlag*/) { + callStatus = s; + }; + auto ret = session3_5->isReconfigurationRequired(oldParams, newParams, hidlCb); + ASSERT_TRUE(ret.isOk()); + switch (callStatus) { + case android::hardware::camera::common::V1_0::Status::OK: + case android::hardware::camera::common::V1_0::Status::METHOD_NOT_SUPPORTED: + break; + case android::hardware::camera::common::V1_0::Status::INTERNAL_ERROR: + default: + ADD_FAILURE() << "Query calllback failed"; + } +} + int main(int argc, char **argv) { ::testing::AddGlobalTestEnvironment(CameraHidlEnvironment::Instance()); ::testing::InitGoogleTest(&argc, argv); From 70d25b813e26defdef6defee3f238e8065a89bb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Guihot?= Date: Tue, 12 Feb 2019 16:22:44 -0800 Subject: [PATCH 473/718] Added missing ASSERT_NE. Test was failing with segmentation fault (and crashing whole VTS) when device was not available. Change-Id: Id0f28d061dc5858fa00ef1bac5f7aa467d860864 --- neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp index 454aa1f921..d715d24b0b 100644 --- a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp +++ b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp @@ -86,6 +86,7 @@ class CompilationCachingTest : public NeuralnetworksHidlTest { protected: void SetUp() override { NeuralnetworksHidlTest::SetUp(); + ASSERT_NE(device.get(), nullptr); // Create cache directory. char cacheDirTemp[] = "/data/local/tmp/TestCompilationCachingXXXXXX"; From 99625ae67088cb8207e4bb75d5a29d1d7875d394 Mon Sep 17 00:00:00 2001 From: Kevin Chyn Date: Tue, 12 Feb 2019 15:56:24 -0800 Subject: [PATCH 474/718] Add onLockoutChanged for IBiometricsFace Lockout is moved to the HAL (as compared to IBiometricsFingerprint@2.1) To maintain public API behavior (BiometricPrompt) there needs to be a way to synchronously retrieve the lockout status. Bug: 121196511 Bug: 121198195 Bug: 123262389 Test: Builds Change-Id: Idb0a1225451e9f123ccb42accbbbd2914ad6cabc --- .../face/1.0/IBiometricsFaceClientCallback.hal | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/biometrics/face/1.0/IBiometricsFaceClientCallback.hal b/biometrics/face/1.0/IBiometricsFaceClientCallback.hal index 93848c57bb..c9dd0e2628 100644 --- a/biometrics/face/1.0/IBiometricsFaceClientCallback.hal +++ b/biometrics/face/1.0/IBiometricsFaceClientCallback.hal @@ -113,4 +113,19 @@ interface IBiometricsFaceClientCallback { */ oneway onEnumerate(uint64_t deviceId, vec faceIds, int32_t userId); + + /** + * A callback invoked when the lockout state changes. + * + * This method must only be invoked when setActiveUser() is called, + * when lockout starts, and when lockout ends. When lockout starts, + * duration must be greater than 0, and when lockout ends, duration must + * be 0. This must be called before calling onError() with parameters + * LOCKOUT or LOCKOUT_PERMANENT. If the user is permanently locked out, + * the duration must be MAX_UINT64. + * + * @param duration the remaining lockout duration in milliseconds, or 0 + * if the user is not locked out. + */ + oneway onLockoutChanged(uint64_t duration); }; From 350d91b1df1053a8d1061106e6c94cb9a2779ea9 Mon Sep 17 00:00:00 2001 From: Xusong Wang Date: Tue, 12 Feb 2019 18:00:37 -0800 Subject: [PATCH 475/718] Remove tmp directory after CompilationCachingTest if cache not supported. The tmp directory is only removed when the driver reports caching not supported, otherwise it is kept for debugging purpose. Test: 1.2 VTS tests with sample driver Change-Id: I5969beb1ec365c992765f40d7693630606f16e18 --- .../functional/CompilationCachingTests.cpp | 36 +++++++++++++------ 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp index 454aa1f921..2ae05da5af 100644 --- a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp +++ b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp @@ -87,13 +87,20 @@ class CompilationCachingTest : public NeuralnetworksHidlTest { void SetUp() override { NeuralnetworksHidlTest::SetUp(); - // Create cache directory. + // Create cache directory. The cache directory and cache files are always created to test + // the behavior of prepareModelFromCache, even when caching is not supported. char cacheDirTemp[] = "/data/local/tmp/TestCompilationCachingXXXXXX"; char* cacheDir = mkdtemp(cacheDirTemp); ASSERT_NE(cacheDir, nullptr); - mCache1 = cacheDir + mCache1; - mCache2 = cacheDir + mCache2; - mCache3 = cacheDir + mCache3; + mCacheDir = cacheDir; + + // Create empty cache files. + mCache1 = mCacheDir + "/cache1"; + mCache2 = mCacheDir + "/cache2"; + mCache3 = mCacheDir + "/cache3"; + // A dummy handle, use AccessMode::WRITE_ONLY for createCacheHandle to create files. + hidl_handle handle; + createCacheHandle({mCache1, mCache2, mCache3}, AccessMode::WRITE_ONLY, &handle); // Check if caching is supported. bool isCachingSupported; @@ -113,10 +120,18 @@ class CompilationCachingTest : public NeuralnetworksHidlTest { << std::endl; mIsCachingSupported = false; } + } - // Create empty cache files. - hidl_handle handle; - createCacheHandle({mCache1, mCache2, mCache3}, AccessMode::WRITE_ONLY, &handle); + void TearDown() override { + // The tmp directory is only removed when the driver reports caching not supported, + // otherwise it is kept for debugging purpose. + if (!mIsCachingSupported) { + remove(mCache1.c_str()); + remove(mCache2.c_str()); + remove(mCache3.c_str()); + rmdir(mCacheDir.c_str()); + } + NeuralnetworksHidlTest::TearDown(); } void saveModelToCache(sp preparedModel, const hidl_handle& cache1, @@ -163,9 +178,10 @@ class CompilationCachingTest : public NeuralnetworksHidlTest { .withDefault(nullptr); } - std::string mCache1 = "/cache1"; - std::string mCache2 = "/cache2"; - std::string mCache3 = "/cache3"; + std::string mCacheDir; + std::string mCache1; + std::string mCache2; + std::string mCache3; uint8_t mToken[static_cast(Constant::BYTE_SIZE_OF_CACHE_TOKEN)] = {}; bool mIsCachingSupported; }; From b9319bd3bf64e4a643045ad0493bedce60786474 Mon Sep 17 00:00:00 2001 From: Xusong Wang Date: Thu, 7 Feb 2019 12:28:35 -0800 Subject: [PATCH 476/718] Modify several 1.2 nn operation specs. - Add TENSOR_QUANT8_ASYMM to RESIZE_BILINEAR - Change the spec of batch_split in * GENERATE_PROPOSALS * ROI_ALIGN * ROI_POOLING * AXIS_ALIGNED_BBOX_TRANSFORM * BOX_WITH_NMS_LIMIT - Add new op RESIZE_NEAREST_NEIGHBOR - Fix minor specification error in * AXIS_ALIGNED_BBOX_TRANSFORM * GENERATE_PROPOSALS Bug: 124060811 Bug: 124061329 Bug: 124061327 Test: 1.2 VTS tests with sample driver Change-Id: If8b8cabd249f17247d8a5278b8360685c97c68e6 --- current.txt | 2 +- neuralnetworks/1.2/types.hal | 65 +++++++++++++++++++++++++++++++----- 2 files changed, 57 insertions(+), 10 deletions(-) diff --git a/current.txt b/current.txt index 0b58830075..82092993a2 100644 --- a/current.txt +++ b/current.txt @@ -421,7 +421,7 @@ dd1ec219f5d2e2b33c6c0bcb92e63bbedb36f7c716413462848f6b6ae74fc864 android.hardwar 92714960d1a53fc2ec557302b41c7cc93d2636d8364a44bd0f85be0c92927ff8 android.hardware.neuralnetworks@1.2::IExecutionCallback 83885d366f22ada42c00d8854f0b7e7ba4cf73ddf80bb0d8e168ce132cec57ea android.hardware.neuralnetworks@1.2::IPreparedModel e1c734d1545e1a4ae749ff1dd9704a8e594c59aea7c8363159dc258e93e0df3b android.hardware.neuralnetworks@1.2::IPreparedModelCallback -a42fb6a33e242e0035de32cdcd4b743d46ae93d65a1e316f3bffe7218ade82cb android.hardware.neuralnetworks@1.2::types +313b341f1f6196a48cf304eaf067f67510c1ebc04df8c7cd536db5611df5c5c2 android.hardware.neuralnetworks@1.2::types cf7a4ba516a638f9b82a249c91fb603042c2d9ca43fd5aad9cf6c0401ed2a5d7 android.hardware.nfc@1.2::INfc abf98c2ae08bf765db54edc8068e36d52eb558cff6706b6fd7c18c65a1f3fc18 android.hardware.nfc@1.2::types 4cb252dc6372a874aef666b92a6e9529915aa187521a700f0789065c3c702ead android.hardware.power.stats@1.0::IPowerStats diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal index 3bddbe8208..06bdc6adf4 100644 --- a/neuralnetworks/1.2/types.hal +++ b/neuralnetworks/1.2/types.hal @@ -1528,6 +1528,7 @@ enum OperationType : int32_t { * Supported tensor {@link OperandType}: * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} (since API level 29) * * Supported tensor rank: 4, with "NHWC" or "NCHW" data layout. * With the default data layout NHWC, the data is stored in the order of: @@ -2212,6 +2213,7 @@ enum OperationType : int32_t { * Supported tensor {@link OperandType}: * * {@link OperandType::TENSOR_FLOAT16} * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT16_ASYMM} * * Inputs: * * 0: A 2-D Tensor of shape [num_rois, 4], specifying the locations of the @@ -2228,7 +2230,8 @@ enum OperationType : int32_t { * {@link OperandType::TENSOR_QUANT16_ASYMM}, this tensor should be * of {@link OperandType::TENSOR_QUANT8_ASYMM}. * * 2: An 1-D {@link OperandType::TENSOR_INT32} tensor, of shape - * [batches], specifying the number of output boxes for each batch. + * [num_rois], specifying the batch index of each box. Boxes with + * the same batch index are grouped together. * * 3: A 2-D Tensor of shape [batches, 2], specifying the information of * each image in the batch, each line with format * [image_height, image_width]. @@ -2557,8 +2560,9 @@ enum OperationType : int32_t { * {@link OperandType::TENSOR_QUANT8_ASYMM}, this tensor should be of * {@link OperandType::TENSOR_QUANT16_ASYMM}, with zeroPoint of 0 and * scale of 0.125. - * * 2: A 1-D Tensor of shape [batches], specifying the number of boxes - * for each image in the batch. + * * 2: A 1-D {@link OperandType::TENSOR_INT32} tensor, of shape + * [num_rois], specifying the batch index of each box. Boxes with + * the same batch index are grouped together. * * 3: An {@link OperandType::FLOAT32} scalar, score_threshold. Boxes * with scores lower than the threshold are filtered before sending * to the NMS algorithm. @@ -2584,7 +2588,8 @@ enum OperationType : int32_t { * [num_output_rois], specifying the class of each output box. The * sequential order of the boxes corresponds with output0. * * 3: A 1-D {@link OperandType::TENSOR_INT32} tensor, of shape - * [batches], specifying the number of output boxes for each image. + * [num_rois], specifying the batch index of each box. Boxes with + * the same batch index are grouped together. * * Available since API level 29. */ @@ -2878,6 +2883,9 @@ enum OperationType : int32_t { * {@link OperandType::TENSOR_QUANT16_SYMM}, with scale of 0.125. * * 3: A 2-D Tensor of shape [batches, 2], specifying the size of * each image in the batch, with format [image_height, image_width]. + * For input0 of type {@link OperandType::TENSOR_QUANT8_ASYMM}, this + * tensor should be of {@link OperandType::TENSOR_QUANT16_SYMM}, with + * scale of 0.125. * * 4: An {@link OperandType::FLOAT32} scalar, specifying the ratio * from the height of original image to the height of feature map. * * 5: An {@link OperandType::FLOAT32} scalar, specifying the ratio @@ -2904,14 +2912,15 @@ enum OperationType : int32_t { * each batch is not guaranteed. For type of * {@link OperandType::TENSOR_QUANT8_ASYMM}, the scale and zero * point must be the same as input0. - * * 1: A tensor of the same {@link OperandType} as input1, of shape + * * 1: A tensor of the same {@link OperandType} as input3, of shape * [num_output_rois, 4], specifying the coordinates of each output * bounding box for each class, with format [x1, y1, x2, y2]. * The sequential order of the boxes corresponds with output0. * For type of {@link OperandType::TENSOR_QUANT16_ASYMM}, the * scale must be 0.125 and the zero point must be 0. * * 2: A 1-D {@link OperandType::TENSOR_INT32} tensor, of shape - * [batches], specifying the number of output boxes for each image. + * [num_rois], specifying the batch index of each box. Boxes with + * the same batch index are grouped together. * * Available since API level 29. */ @@ -3904,7 +3913,8 @@ enum OperationType : int32_t { * this tensor should be of {@link OperandType::TENSOR_QUANT16_ASYMM}, * with zeroPoint of 0 and scale of 0.125. * * 2: An 1-D {@link OperandType::TENSOR_INT32} tensor, of shape - * [batches], specifying the number of output boxes for each batch. + * [num_rois], specifying the batch index of each box. Boxes with + * the same batch index are grouped together. * * 3: An {@link OperandType::INT32} scalar, specifying the output * height of the output tensor. * * 4: An {@link OperandType::INT32} scalar, specifying the output @@ -3960,7 +3970,8 @@ enum OperationType : int32_t { * this tensor should be of {@link OperandType::TENSOR_QUANT16_ASYMM}, * with zeroPoint of 0 and scale of 0.125. * * 2: An 1-D {@link OperandType::TENSOR_INT32} tensor, of shape - * [batches], specifying the number of output boxes for each batch. + * [num_rois], specifying the batch index of each box. Boxes with + * the same batch index are grouped together. * * 3: An {@link OperandType::INT32} scalar, specifying the output * height of the output tensor. * * 4: An {@link OperandType::INT32} scalar, specifying the output @@ -4441,6 +4452,42 @@ enum OperationType : int32_t { * Available since API level 29. */ UNIDIRECTIONAL_SEQUENCE_RNN = 93, + + /** + * Resizes images to given size using the nearest neighbor interpretation. + * + * Resized images must be distorted if their output aspect ratio is not the + * same as input aspect ratio. The corner pixels of output may not be the + * same as corner pixels of input. + * + * Supported tensor {@link OperandType}: + * * {@link OperandType::TENSOR_FLOAT16} + * * {@link OperandType::TENSOR_FLOAT32} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * + * Supported tensor rank: 4, with "NHWC" or "NCHW" data layout. + * With the default data layout NHWC, the data is stored in the order of: + * [batch, height, width, channels]. Alternatively, the data layout could + * be NCHW, the data storage order of: [batch, channels, height, width]. + * + * Inputs: + * * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying + * the input. + * * 1: An {@link OperandType::INT32} scalar, specifying the output + * height of the output tensor. + * * 2: An {@link OperandType::INT32} scalar, specifying the output + * width of the output tensor. + * * 3: An {@link OperandType::BOOL} scalar, default to false. + * Set to true to specify NCHW data layout for input0 and output0. + * + * Outputs: + * * 0: The output 4-D tensor, of shape + * [batches, new_height, new_width, depth]. + * + * Available since API level 29. + */ + RESIZE_NEAREST_NEIGHBOR = 94, + /** * DEPRECATED. Since NNAPI 1.2, extensions are the preferred alternative to * OEM operation and data types. @@ -4463,7 +4510,7 @@ enum OperationType : int32_t { enum OperationTypeRange : uint32_t { BASE_MIN = 0, FUNDAMENTAL_MIN = 0, - FUNDAMENTAL_MAX = 93, + FUNDAMENTAL_MAX = 94, OEM_MIN = 10000, OEM_MAX = 10000, BASE_MAX = 0xFFFF, From 1c16445989b79bbc2aba008762e8a2927104ea0f Mon Sep 17 00:00:00 2001 From: Kevin Chyn Date: Wed, 13 Feb 2019 10:16:52 -0800 Subject: [PATCH 477/718] resetLockout should return Status instead of bool The actual lockout reset is asynchronous and returns its result in the onLockoutChanged() callback Bug: 121196511 Bug: 121198195 Bug: 123262389 Test: Builds Change-Id: Ia5fd34d77ae1f8dba1a943e0e1fc51d458753090 --- biometrics/face/1.0/IBiometricsFace.hal | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/biometrics/face/1.0/IBiometricsFace.hal b/biometrics/face/1.0/IBiometricsFace.hal index 813f04000b..0499c5d0fd 100644 --- a/biometrics/face/1.0/IBiometricsFace.hal +++ b/biometrics/face/1.0/IBiometricsFace.hal @@ -242,8 +242,10 @@ interface IBiometricsFace { * Reset lockout for the current user. * * @param hat A valid Hardware Authentication Token, generated when the - * user authenticates with Pin/Pattern/Pass. - * @return true if lockout was reset, false otherwise. + * user authenticates with Pin/Pattern/Pass. When the Hardware + * Authentication Token is verified, lockout must be reset and + * onLockoutChanged must be called with duration 0. + * @return status The status of this method call. */ - resetLockout(vec hat) generates (bool success); + resetLockout(vec hat) generates (Status status); }; From 7a0e3d17d4d28ef40a118584b6c7f918cadfeb6e Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Wed, 13 Feb 2019 14:11:43 -0800 Subject: [PATCH 478/718] Freeze HALs for Android Q (internal) This freezes HALs for Android Q that were not developed in AOSP. Bug: 119518846 Test: none Change-Id: Ie125d9bb014ee747ce56a59feaca577ab2d9e96c --- current.txt | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/current.txt b/current.txt index 0b58830075..17e38d7c61 100644 --- a/current.txt +++ b/current.txt @@ -410,11 +410,98 @@ e78cf871f9fd1c072874e481e06e18e2681763cf2aa38c1fd777d53bab4eb69b android.hardwar # HALs released in Android Q 438dc52ab820befb7a11e953e82110f0d8c91cdf96ef62be921efc64f5a3d580 android.hardware.atrace@1.0::IAtraceDevice 20b9f81bb0b1f812f150ec94d42648b01087f2344ea91df0416bce0fb6cdfbd4 android.hardware.atrace@1.0::types +dfdb4d04b65dc363e5621c85bfdf3023c277b75c31d821d8e71b3f44f198e214 android.hardware.audio@5.0::IDevice +0a911297821854985cfcdb17b63d7948af0f0f51ce8c68cc86367c185bbc772e android.hardware.audio@5.0::IDevicesFactory +ce2e8c6c8559fd42bd69e0dee27b4d9c93cd9b2eff487b4e6b6395b6a1a993d6 android.hardware.audio@5.0::IPrimaryDevice +4a4e5e5d9357004a1256bde8d36010ee00c51cea811a1c1e0dd969a9fc0bf862 android.hardware.audio@5.0::IStream +e05e48c583de14c1e5a6fa9d48ea50244e3e0924b76b342374e7471dc8007ba9 android.hardware.audio@5.0::IStreamIn +9471b12b1c255bb530695720bc4174bd74987b75b1f820854af8944bc8c215c9 android.hardware.audio@5.0::IStreamOut +1b0500367ed2b32a841667ac3200edf3d3a164e8004aca445ff1b085ac831e93 android.hardware.audio@5.0::IStreamOutCallback +83e365479cc77d8717c155e1787ee668cd2ae4c557b467cf75b8e7cd53697ad8 android.hardware.audio@5.0::types +edda213e520f387a3e367834b0772978b308a0f59b54479990aa9411aee9bcc4 android.hardware.audio.common@5.0::types +f269297866765b95ddd1825676cc8a772f0c7c9863286df596fc302781a42ff5 android.hardware.audio.effect@5.0::IAcousticEchoCancelerEffect +fa187b602d8939644ef708ed7627f2e3deac97899a4bda1de07f2ff126abe243 android.hardware.audio.effect@5.0::IAutomaticGainControlEffect +e1bf864ccb8458c0da1dcc74a2e748b1dca8ac360df590591cf82d98292d7981 android.hardware.audio.effect@5.0::IBassBoostEffect +d3867dcf1f46f1962d258c56151b5afb2ef26e9835fef73f01115492d58da5b7 android.hardware.audio.effect@5.0::IDownmixEffect +445a65ea2edd1ccba8a8d8e1c88d24c6ea67e57d355fa446ab390e20f0db14aa android.hardware.audio.effect@5.0::IEffect +0ac2e951f359e87644dcf642f488194f6b02563f89cfe8dd668ab7c422be89b1 android.hardware.audio.effect@5.0::IEffectBufferProviderCallback +9019e7ac057b8105a9b9ac8974b13e1ded46d1006e5a544aec510dfaf92755c6 android.hardware.audio.effect@5.0::IEffectsFactory +c8e5a7e450a5b201c286814d484d04c7b9c6cab71b4982b34b84177e818909db android.hardware.audio.effect@5.0::IEnvironmentalReverbEffect +cf356f430a1bb42fd91af65f105e07fa84a5927dc45c36d8ffce5b6c132c1f3c android.hardware.audio.effect@5.0::IEqualizerEffect +8c31b0cad211968dc6008dcb2b116bf5f12079c8dce920e79242e7839104138e android.hardware.audio.effect@5.0::ILoudnessEnhancerEffect +6f0f86b549e30382619877784857c40d4c64978c1e9eef3c034bdd367aac7468 android.hardware.audio.effect@5.0::INoiseSuppressionEffect +ca15a738dedc2f4981925f7d7ff29c22bc3f8a848403dcf0c592c167de09d9af android.hardware.audio.effect@5.0::IPresetReverbEffect +443659bb9e27221e5da0d16c7a0ecb2dc3a9a03acc8a0b2196b47c50735e2d2e android.hardware.audio.effect@5.0::IVirtualizerEffect +78fed26a781cdca1b3bcb37520bff705d7764ee81db9cfd37014953c7ad2596e android.hardware.audio.effect@5.0::IVisualizerEffect +6385b6accab8a544e2ee54ba7bf5aa55dff6153bcedd80fdaae16fe9e0be7050 android.hardware.audio.effect@5.0::types +2f11e4c10ebe2b600426e0695f3c720d21663501c1c9449537055f13f37600d3 android.hardware.biometrics.face@1.0::IBiometricsFace +dfb0666af59eb306c82a6f576c65a160e6829d3324211a10429fd63768df70df android.hardware.biometrics.face@1.0::IBiometricsFaceClientCallback +cc40d308f38b6a218fcf99f264ebb49544fce670a6abdf294c617357a3d83dad android.hardware.biometrics.face@1.0::types +ecedc58dbcdb13503c19c0ab160ac1dd0530bb1471164149282dd1463c684185 android.hardware.bluetooth.audio@2.0::IBluetoothAudioPort +fb9c40e4deab40be5476477078fe3d8a4a4495fd9deef4321878d169d675c633 android.hardware.bluetooth.audio@2.0::IBluetoothAudioProvider +f7431f3e3e4e3387fc6f27a6cf423eddcd824a395dc4349d302c995ab44a9895 android.hardware.bluetooth.audio@2.0::IBluetoothAudioProvidersFactory +447a5c9bb0f1a5ed3f1dfe5216afe4be2f4362111d95479670eec4cae4d7d5f7 android.hardware.bluetooth.audio@2.0::types +09ab9b24994429d9bb32a3fb420b6f6be3e47eb655139a2c08c4e80d3f33ff95 android.hardware.camera.device@3.5::ICameraDevice +06237de53c42890029e3f8fe7d1480d078469c0d07608e51c37b4d485d342992 android.hardware.camera.device@3.5::ICameraDeviceCallback +08c68b196e2fc4e5ba67ba0d0917bde828a87cbe2cffec19d04733972da9eb49 android.hardware.camera.device@3.5::ICameraDeviceSession +d487ab209944df8987eeca70cf09307fc1429cedf64b0ea9e77c61d8caeb8c15 android.hardware.camera.device@3.5::types +74ec7732fdacb22292c907b49f8f933510851ea1b3ed195c4dcdff35a20387f5 android.hardware.camera.metadata@3.4::types +0fb39a7809ad1c52b3efbbed5ef4749b06c2a4f1f19cdc3efa2e3d9b28f1205c android.hardware.camera.provider@2.5::ICameraProvider +f5777403d65135a5407723671bc7a864cdca83aea13ee3ce2894b95e6588ca3a android.hardware.camera.provider@2.5::types +44c88954b3c201b26f64fcdb6f278024ab3aae864a9e1ec70e8a74274ae9d6aa android.hardware.cas@1.1::ICas +25012d1778f7396f967bbc0231397d544bde421ba5b98706c9e48ac790612683 android.hardware.cas@1.1::ICasListener +dffacdbe0bcf8443013de5bdc56a83479ad979d4919ed15a5585539f46091f07 android.hardware.cas@1.1::IMediaCasService +bc742c6b17c834010f90c06ce2939c845198eecd2706be18da99e14bceb2acc0 android.hardware.configstore@1.2::ISurfaceFlingerConfigs +aadac6b9fcf660384d73cbb97f3732ff9eeb8e8c67001e3fdbf4add108e5b1dc android.hardware.configstore@1.2::types +5b1f4a4fb88c239e07d76026467a1f2ee0d08f4d52c1805bd93bd7c05e3fe69c android.hardware.drm@1.2::ICryptoFactory +4895f98e9ef210e9acb01982f5d07b654538377e1404b8db5e19e7858835e9d8 android.hardware.drm@1.2::ICryptoPlugin +976116b9033b2c222b940109fdf0ffcc29b77cbe631ef6b4fcc2ad5ce8e605f7 android.hardware.drm@1.2::IDrmFactory +b2efccc6425085f84795a2ca15a09d9a81ffd02f9dc3d30ba21d1a59bdfa253f android.hardware.drm@1.2::IDrmPlugin +39ca9e88404b6c090f7650455a7ed3fdee9cce4e3a356c9d547f8ff02f2e7fc8 android.hardware.drm@1.2::IDrmPluginListener +f27baaa587bc3dd9b740cb6928ab812b9b7d105b5187663938aee578105f3c39 android.hardware.drm@1.2::types 44480c912e4ab90b9ed17e56569cd5ca98413a8a2372efb028f4181204b6b73e android.hardware.fastboot@1.0::IFastboot 7b2989744e3c555292d4b5b829acd09a7b40f96ead62ce54174cd959503b64bb android.hardware.fastboot@1.0::types +7f460e795f5d1ed5e378935f98c6db4d39497de988aef1b4c2a4a07a6c400392 android.hardware.gnss@2.0::IAGnss +2e5ad983734069e84a760004b32da0d09e4170c05380abe27e6eb80e4aa70d5a android.hardware.gnss@2.0::IAGnssCallback +1f4ac068a88a72360280d94a7f6fd7c63813c1eea4891a0eb01394d3e7e775f2 android.hardware.gnss@2.0::IAGnssRil +52e56490d35b4214d68c44f013e22bdf681fd6f8e5947c643dbb8453f9a03dcd android.hardware.gnss@2.0::IGnss +0676e99eda39ff32f6891bcb56ea27df17007c439b9f900aa9a3919776920c23 android.hardware.gnss@2.0::IGnssCallback +ecc966c68bddbd95c8dae782b84204cf01c75734675e8769963f3b5106ec128b android.hardware.gnss@2.0::IGnssConfiguration +c67759f5d6387d273b66729180d03690e827f0b6b8d4e13ce2ff42d31b224065 android.hardware.gnss@2.0::IGnssMeasurement +08615296d42451856f82c4953b45c4257d0a7b935fd98557c2ee2812c79fe0c3 android.hardware.gnss@2.0::IGnssMeasurementCallback +141269652bcf30a7557edc4cd4311aa3e2ac67a252a7e8d3959b956d35793344 android.hardware.gnss@2.0::types +50623a69a88b1c8a05738e4af7d5f78e905f415ccb0e84c99d0a71ea182e9393 android.hardware.gnss.measurement_corrections@1.0::IMeasurementCorrections +6ef12cd95df73f8f80c25eb035d98ca4594f9cee571fdabea838a0b6016dd908 android.hardware.gnss.measurement_corrections@1.0::types +0d278956d7fc6fdf9ca9c42962ff2d73967bbb1c9f0b3e0b58d71b7095c286bc android.hardware.gnss.visibility_control@1.0::IGnssVisibilityControl +0d99e34500cfc2d40b684cb4dea7ebd89d4aff9f5315ed36b33442a7a88c138c android.hardware.gnss.visibility_control@1.0::IGnssVisibilityControlCallback +6b2d8dfa3db505c34a3a19082d8737c86bd859ec00f0e6c5fd19cce3c1ef95d1 android.hardware.graphics.allocator@3.0::IAllocator +2a81d3132df91614a30ca45dfe088d67ddbb30240ab8c25feb6b8110d7ec3800 android.hardware.graphics.bufferqueue@2.0::IGraphicBufferProducer +b826892686850a9cf2b60ca5845db7185c2196ea4dd765cd80cd163169678a78 android.hardware.graphics.bufferqueue@2.0::IProducerListener +01c6398c90fc6be0640810e2c5d8a4863b457280132bb3f97dd5682e19632b62 android.hardware.graphics.bufferqueue@2.0::types +7a2d64095252f85781b2d521f4f11d04ce774544feececcec2088c568656e93c android.hardware.graphics.common@1.2::types +3dff04a36b86660b5807414587e530bb0c294ed56fdff06f8915ba0a9b73f974 android.hardware.graphics.composer@2.3::IComposer +ed0cf91532e88dff073cf7f45b9c65ee1c88553ebcb97892f7b7072abb9b822a android.hardware.graphics.composer@2.3::IComposerClient +5c8bf8e1af9efe225a4661db8c08ff1b7e13fdc8ed49f35291bd0b6c9436b8f2 android.hardware.graphics.mapper@3.0::IMapper +7183d9d9acfa41a61a64bdfed548e98299265a7bb1821a3ed204173b5c2cfd4a android.hardware.graphics.mapper@3.0::types c3f831a66d5815baf74f5b82fe79cf099542ddae4dfab3f388e1d41828e794fc android.hardware.health.storage@1.0::IGarbageCollectCallback dd1ec219f5d2e2b33c6c0bcb92e63bbedb36f7c716413462848f6b6ae74fc864 android.hardware.health.storage@1.0::IStorage 2b4a14661e6a38617b7dd0c6ebb66a56a90e564674ac7697a14cb8a0cab92b2f android.hardware.health.storage@1.0::types +30006fde4cb1f255f2530208728bff692100411b20af5b66fa31a9196d51f00b android.hardware.input.classifier@1.0::IInputClassifier +97d8757bb05eb23d6a218bda374e095dfbb064c47714e2f859963c11f433e822 android.hardware.input.common@1.0::types +24ae089981d58bc4cc74d75a6055bf357338ae6744ce1b467c5b4a9c470aba6d android.hardware.media.bufferpool@2.0::IAccessor +897f45ee7db24ef227dea83ca3e4de72d53ff6bb7adc7983c90a650a1a6ff576 android.hardware.media.bufferpool@2.0::IClientManager +aee53b2865b4f7939fb3df6fae758d9750c14f93dd454b479fc74aa7978fda4f android.hardware.media.bufferpool@2.0::IConnection +0bf3758eeeb05767830ea87041214be80968c4679fb73577ac5b3091841ee71f android.hardware.media.bufferpool@2.0::IObserver +82255e252ae215382473ad2e5ac7a2814a439a24f0092551aad7a2f89c6e9546 android.hardware.media.bufferpool@2.0::types +fd4725732511b8ae124b868fd0b2090386663dffc5e67dfd0d0b4a0b49c335db android.hardware.media.c2@1.0::IComponent +389d06e4a4ecf60f828a260045b0c327a5ae883ee0856a3c054556dd22b1f450 android.hardware.media.c2@1.0::IComponentInterface +5ee0c02265c5505ade189796bef46697df4e0563e3544bb0c934855b34694b07 android.hardware.media.c2@1.0::IComponentListener +43d70bcdc63b3d042bac3c3297f5d941dfabbd08f3ceb96b6016cc14f6e34ba3 android.hardware.media.c2@1.0::IComponentStore +d36f747f9c9a8f2f21db2f8323c2d755dd08b34ce813932d7339979f7d490dab android.hardware.media.c2@1.0::IConfigurable +cd2bd9f424515aeb0c2b91f3bb879797defb5b846b8660784b68d225285bcdff android.hardware.media.c2@1.0::IInputSink +c3dfaa1fcd452c6cfc26d8dcbb67b71b08a1fe6dad5f87427e93d11a95372b05 android.hardware.media.c2@1.0::IInputSurface +0a786a19e6753f9774a7ca7781c2a2edfe5c0b5fa112355dfa0e50ebedeb08b9 android.hardware.media.c2@1.0::IInputSurfaceConnection +4cb139f729c29d8d6f4ecdab149c4feb571dad8a06e56cd57fcb52e70208bab4 android.hardware.media.c2@1.0::types 4880af120fc1640225abdc2c60bda6d79617d73484d5124913c7278af3b11e2d android.hardware.neuralnetworks@1.2::IBurstCallback 19877e466ad8c6ed42b38050b77bd010cf7800ff365fdc8574f45bbfda03a758 android.hardware.neuralnetworks@1.2::IBurstContext 96249c852dabeefa3a9496ecdfc44681a071c665bfbf88527bf775c88bf1ab1b android.hardware.neuralnetworks@1.2::IDevice @@ -443,3 +530,26 @@ d8e7717e8187dd7453d4142f8f331e7c325e7a6f9e8d44ac0d52b3be502bfe83 android.hardwar 93b8102078e25057ae347ac9704e87529eb26121c2a1b419b362dd36eccefc4d android.hardware.radio.config@1.2::types 08d439c463e4044fa78874037d8e8379aa3cabecde32f08a775897eea5a538af android.hardware.secure_element@1.1::ISecureElement b53ac9d61c24efb16a2d63a861cef20680f6d57adb244a03b9778c675550628b android.hardware.secure_element@1.1::ISecureElementHalCallback +3702b1c52c0bb3427244618e9e7975c05228bf4ceb8720da7a93603a71cb0368 android.hardware.sensors@2.0::ISensors +ae5faa38538a9f50eb71eb7f9b998271124d2c64b761cb11c4d820c7732b4ddc android.hardware.sensors@2.0::ISensorsCallback +3a98242a57d0820dacaca0f7db52bec433eae1f21c498763c6f1ece611c3967b android.hardware.sensors@2.0::types +ce4b98211959449361146d4b1e5554dc841ceb4d4577154d7b2fb6d1eb504f76 android.hardware.soundtrigger@2.2::ISoundTriggerHw +5cc81d517c5f3fef12e719b0f5683c7c99e3e8895fcb80e6f6653b454f463320 android.hardware.thermal@2.0::IThermal +cc4d2ef36da776c475ad054f0f3416d8a8865def9d9e2129f10074b28e36d203 android.hardware.thermal@2.0::IThermalChangedCallback +b47f90302595874dfddb19bd05a054727bf18b3a930bc810ea14957b859ae8bf android.hardware.thermal@2.0::types +61bc302e7c974c59b25898c585c6e9685e8a81021b1bed3eedf5224198f2785a android.hardware.usb@1.2::IUsb +46996cd2a1c66261a75a1f6ecada77eeb5861eb264fa39b996548fe0a7f22dd3 android.hardware.usb@1.2::IUsbCallback +3bbaa8cbc5d6b1da21f5509b2b641e05fc7eeca1354751eb1bb3cf37f89aa32f android.hardware.usb@1.2::types +92c1a726c80970d623b891f7c2f9a989a40a15ee1244092b49f4eb6adcdce4e9 android.hardware.vibrator@1.3::IVibrator +f19832856a3f53ced5ef91d3cc630a57fb7f4d4ce15f364dbed09099b89f6830 android.hardware.wifi@1.3::IWifi +7c6799c19bfdb3dec016b751556fe246cf7d37191ee7bb82a0091ab9fbf6f2fb android.hardware.wifi@1.3::IWifiChip +3bef30e8b61ab050c0f6fd26572712be5ebb7707d624c9aa6c74bbb9d6a5b4a9 android.hardware.wifi@1.3::IWifiStaIface +f3dbd8dd0d6333c005610288a4785d0ef79a72a7bbe6d0a46d46fa89fc886f1e android.hardware.wifi@1.3::types +2fae61e962f68091335f7ff4581fcfe2e28ce7f6132d7a712fa13d7965543e4d android.hardware.wifi.hostapd@1.1::IHostapd +913e66d8790c4e494950f1cbc259173b45d9e7bf9f1e8fc0c6a3623128290f4d android.hardware.wifi.hostapd@1.1::IHostapdCallback +067b22efc50529a88d650fe7400603429d1164a47ee96a17476fdb0aadd6b4d3 android.hardware.wifi.supplicant@1.2::ISupplicant +120211371fdd29fb134837071d432a302d7b60e9b95af611dd8dde86bd1f77ee android.hardware.wifi.supplicant@1.2::ISupplicantP2pIface +7efe2b057e9f9387b3500e67af97942aa7c8008e6ee7d8dcaae4107fda84016b android.hardware.wifi.supplicant@1.2::ISupplicantStaIface +eb569df2e80f8e276a91a510c75e83fbf957ff1988691726418d44c2be01c520 android.hardware.wifi.supplicant@1.2::ISupplicantStaIfaceCallback +efbb061c969fa9553d243da6ee23b83fe5d4aa663a7b8896adc52e2b015bc2f3 android.hardware.wifi.supplicant@1.2::ISupplicantStaNetwork +4851210036650ce6c86498c012db5ff618afce8508a2b06a0e9b902d1840f4bd android.hardware.wifi.supplicant@1.2::types From 369f17b7e0aed4ca223939dae81e2df14245ece8 Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Wed, 13 Feb 2019 17:36:12 -0800 Subject: [PATCH 479/718] target-level 4: allow camera provider 2.4-5 Bug: N/A Test: N/A Change-Id: I9171d94f2188bf37ec01e1bc1028c9a33e1aa7af --- compatibility_matrices/compatibility_matrix.current.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml index 1d3f254c78..22aacd80a5 100644 --- a/compatibility_matrices/compatibility_matrix.current.xml +++ b/compatibility_matrices/compatibility_matrix.current.xml @@ -113,7 +113,7 @@ android.hardware.camera.provider - 2.5 + 2.4-5 ICameraProvider [^/]+/[0-9]+ From 42a35bee10225e6257d145f0cb88e2a612a35721 Mon Sep 17 00:00:00 2001 From: Michael Butler Date: Tue, 12 Feb 2019 13:50:25 -0800 Subject: [PATCH 480/718] Pretty-print ErrorStatus and DeviceStatus test failure logs Argument-dependent lookup will only work for operator>> if the operator is in one of the argument's namespaces. This caused the enumerations to pretty-print for V1_0, but not for V1_1 or V1_2. This change ensures the V1_0 namespace is used. Test: mma Test: atest VtsHalNeuralnetworksV1_0TargetTest (verified the test output "OFFLINE" for DeviceStatus and "DEVICE_UNAVAILABLE" for ErrorStatus instead of raw byte value representation) Test: atest VtsHalNeuralnetworksV1_1TargetTest (verified the test output "OFFLINE" for DeviceStatus and "DEVICE_UNAVAILABLE" for ErrorStatus instead of raw byte value representation) Test: atest VtsHalNeuralnetworksV1_2TargetTest (verified ran and passed tests) Fixes: 124316129 Change-Id: I764a46e2d87615b1f3da0ab0e6edb134bb533887 --- .../1.0/vts/functional/VtsHalNeuralnetworks.cpp | 11 +++++++---- .../1.0/vts/functional/VtsHalNeuralnetworks.h | 13 ++++++++----- .../1.1/vts/functional/VtsHalNeuralnetworks.cpp | 11 +++++++---- .../1.1/vts/functional/VtsHalNeuralnetworks.h | 13 ++++++++----- .../1.2/vts/functional/VtsHalNeuralnetworks.cpp | 11 +++++++---- .../1.2/vts/functional/VtsHalNeuralnetworks.h | 13 ++++++++----- 6 files changed, 45 insertions(+), 27 deletions(-) diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp index 1ff3b66808..9ebc0aac47 100644 --- a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp +++ b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp @@ -60,6 +60,12 @@ void NeuralnetworksHidlTest::TearDown() { } // namespace functional } // namespace vts +} // namespace V1_0 +} // namespace neuralnetworks +} // namespace hardware +} // namespace android + +namespace android::hardware::neuralnetworks::V1_0 { ::std::ostream& operator<<(::std::ostream& os, ErrorStatus errorStatus) { return os << toString(errorStatus); @@ -69,10 +75,7 @@ void NeuralnetworksHidlTest::TearDown() { return os << toString(deviceStatus); } -} // namespace V1_0 -} // namespace neuralnetworks -} // namespace hardware -} // namespace android +} // namespace android::hardware::neuralnetworks::V1_0 using android::hardware::neuralnetworks::V1_0::vts::functional::NeuralnetworksHidlEnvironment; diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h index e79129b09f..d4c114d3a2 100644 --- a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h +++ b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h @@ -72,14 +72,17 @@ class GeneratedTest : public NeuralnetworksHidlTest {}; } // namespace functional } // namespace vts - -// pretty-print values for error messages -::std::ostream& operator<<(::std::ostream& os, ErrorStatus errorStatus); -::std::ostream& operator<<(::std::ostream& os, DeviceStatus deviceStatus); - } // namespace V1_0 } // namespace neuralnetworks } // namespace hardware } // namespace android +namespace android::hardware::neuralnetworks::V1_0 { + +// pretty-print values for error messages +::std::ostream& operator<<(::std::ostream& os, ErrorStatus errorStatus); +::std::ostream& operator<<(::std::ostream& os, DeviceStatus deviceStatus); + +} // namespace android::hardware::neuralnetworks::V1_0 + #endif // VTS_HAL_NEURALNETWORKS_V1_0_TARGET_TESTS_H diff --git a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp index 62381e6796..4165953df2 100644 --- a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp +++ b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp @@ -60,6 +60,12 @@ void NeuralnetworksHidlTest::TearDown() { } // namespace functional } // namespace vts +} // namespace V1_1 +} // namespace neuralnetworks +} // namespace hardware +} // namespace android + +namespace android::hardware::neuralnetworks::V1_0 { ::std::ostream& operator<<(::std::ostream& os, ErrorStatus errorStatus) { return os << toString(errorStatus); @@ -69,10 +75,7 @@ void NeuralnetworksHidlTest::TearDown() { return os << toString(deviceStatus); } -} // namespace V1_1 -} // namespace neuralnetworks -} // namespace hardware -} // namespace android +} // namespace android::hardware::neuralnetworks::V1_0 using android::hardware::neuralnetworks::V1_1::vts::functional::NeuralnetworksHidlEnvironment; diff --git a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h index 970e8b5537..1c8c0e18cb 100644 --- a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h +++ b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h @@ -81,14 +81,17 @@ class GeneratedTest : public NeuralnetworksHidlTest {}; } // namespace functional } // namespace vts - -// pretty-print values for error messages -::std::ostream& operator<<(::std::ostream& os, ErrorStatus errorStatus); -::std::ostream& operator<<(::std::ostream& os, DeviceStatus deviceStatus); - } // namespace V1_1 } // namespace neuralnetworks } // namespace hardware } // namespace android +namespace android::hardware::neuralnetworks::V1_0 { + +// pretty-print values for error messages +::std::ostream& operator<<(::std::ostream& os, ErrorStatus errorStatus); +::std::ostream& operator<<(::std::ostream& os, DeviceStatus deviceStatus); + +} // namespace android::hardware::neuralnetworks::V1_0 + #endif // VTS_HAL_NEURALNETWORKS_V1_1_H diff --git a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp index 4eced82352..34c73ef05d 100644 --- a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp +++ b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp @@ -66,6 +66,12 @@ sp getPreparedModel_1_2( } // namespace functional } // namespace vts +} // namespace V1_2 +} // namespace neuralnetworks +} // namespace hardware +} // namespace android + +namespace android::hardware::neuralnetworks::V1_0 { ::std::ostream& operator<<(::std::ostream& os, ErrorStatus errorStatus) { return os << toString(errorStatus); @@ -75,10 +81,7 @@ sp getPreparedModel_1_2( return os << toString(deviceStatus); } -} // namespace V1_2 -} // namespace neuralnetworks -} // namespace hardware -} // namespace android +} // namespace android::hardware::neuralnetworks::V1_0 using android::hardware::neuralnetworks::V1_2::vts::functional::NeuralnetworksHidlEnvironment; diff --git a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h index c0c21bddf0..404eec06db 100644 --- a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h +++ b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h @@ -88,14 +88,17 @@ sp getPreparedModel_1_2( } // namespace functional } // namespace vts - -// pretty-print values for error messages -::std::ostream& operator<<(::std::ostream& os, ErrorStatus errorStatus); -::std::ostream& operator<<(::std::ostream& os, DeviceStatus deviceStatus); - } // namespace V1_2 } // namespace neuralnetworks } // namespace hardware } // namespace android +namespace android::hardware::neuralnetworks::V1_0 { + +// pretty-print values for error messages +::std::ostream& operator<<(::std::ostream& os, ErrorStatus errorStatus); +::std::ostream& operator<<(::std::ostream& os, DeviceStatus deviceStatus); + +} // namespace android::hardware::neuralnetworks::V1_0 + #endif // VTS_HAL_NEURALNETWORKS_V1_2_H From 71e6298ea6fa05e1bb1cd26d64a8f1d43091497e Mon Sep 17 00:00:00 2001 From: Yin-Chia Yeh Date: Fri, 8 Feb 2019 14:35:58 -0800 Subject: [PATCH 481/718] Camera: fix per stream error code for HAL buffer manager Also some refactoring to make the code more readable and less indent. Also clarify the unknown error case that per stream error code might still be provided. Test: GCA smoke test and camera CTS Bug: 120986771 Change-Id: I3b7d3eadfe3895a3fdf3888735a3932d5c6c03bc --- .../3.5/default/CameraDeviceSession.cpp | 203 +++++++++--------- camera/device/3.5/types.hal | 4 +- current.txt | 2 +- 3 files changed, 109 insertions(+), 100 deletions(-) diff --git a/camera/device/3.5/default/CameraDeviceSession.cpp b/camera/device/3.5/default/CameraDeviceSession.cpp index d9c6eef5ad..873ddd0460 100644 --- a/camera/device/3.5/default/CameraDeviceSession.cpp +++ b/camera/device/3.5/default/CameraDeviceSession.cpp @@ -186,111 +186,118 @@ camera3_buffer_request_status_t CameraDeviceSession::requestStreamBuffers( } ATRACE_END(); - if (status == BufferRequestStatus::OK || status == BufferRequestStatus::FAILED_PARTIAL) { - if (bufRets.size() != num_buffer_reqs) { - ALOGE("%s: expect %d buffer requests returned, only got %zu", - __FUNCTION__, num_buffer_reqs, bufRets.size()); - return CAMERA3_BUF_REQ_FAILED_UNKNOWN; - } - - for (size_t i = 0; i < num_buffer_reqs; i++) { - // maybe we can query all streams in one call to avoid frequent locking device here? - Camera3Stream* stream = getStreamPointer(bufRets[i].streamId); - if (stream == nullptr) { - ALOGE("%s: unknown streamId %d", __FUNCTION__, bufRets[i].streamId); - return CAMERA3_BUF_REQ_FAILED_UNKNOWN; - } - returned_buf_reqs[i].stream = stream; - } - - std::vector importedFences; - std::vector> importedBuffers; - for (size_t i = 0; i < num_buffer_reqs; i++) { - int streamId = bufRets[i].streamId; - switch (bufRets[i].val.getDiscriminator()) { - case StreamBuffersVal::hidl_discriminator::error: - returned_buf_reqs[i].num_output_buffers = 0; - switch (bufRets[i].val.error()) { - case StreamBufferRequestError::NO_BUFFER_AVAILABLE: - returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_NO_BUFFER_AVAILABLE; - break; - case StreamBufferRequestError::MAX_BUFFER_EXCEEDED: - returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_MAX_BUFFER_EXCEEDED; - break; - case StreamBufferRequestError::STREAM_DISCONNECTED: - returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_STREAM_DISCONNECTED; - break; - case StreamBufferRequestError::UNKNOWN_ERROR: - returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_UNKNOWN_ERROR; - break; - default: - ALOGE("%s: Unknown StreamBufferRequestError %d", - __FUNCTION__, bufRets[i].val.error()); - cleanupInflightBufferFences(importedFences, importedBuffers); - return CAMERA3_BUF_REQ_FAILED_UNKNOWN; - } - break; - case StreamBuffersVal::hidl_discriminator::buffers: { - const hidl_vec& hBufs = bufRets[i].val.buffers(); - camera3_stream_buffer_t* outBufs = returned_buf_reqs[i].output_buffers; - for (size_t b = 0; b < hBufs.size(); b++) { - const StreamBuffer& hBuf = hBufs[b]; - camera3_stream_buffer_t& outBuf = outBufs[b]; - // maybe add importBuffers API to avoid frequent locking device? - Status s = importBuffer(streamId, - hBuf.bufferId, hBuf.buffer.getNativeHandle(), - /*out*/&(outBuf.buffer), - /*allowEmptyBuf*/false); - if (s != Status::OK) { - ALOGE("%s: import stream %d bufferId %" PRIu64 " failed!", - __FUNCTION__, streamId, hBuf.bufferId); - cleanupInflightBufferFences(importedFences, importedBuffers); - // Buffer import should never fail - restart HAL since something is very - // wrong. - assert(false); - return CAMERA3_BUF_REQ_FAILED_UNKNOWN; - } - - pushBufferId(*(outBuf.buffer), hBuf.bufferId, streamId); - importedBuffers.push_back(std::make_pair(*(outBuf.buffer), streamId)); - - if (!sHandleImporter.importFence( - hBuf.acquireFence, - outBuf.acquire_fence)) { - ALOGE("%s: stream %d bufferId %" PRIu64 "acquire fence is invalid", - __FUNCTION__, streamId, hBuf.bufferId); - cleanupInflightBufferFences(importedFences, importedBuffers); - return CAMERA3_BUF_REQ_FAILED_UNKNOWN; - } - importedFences.push_back(outBuf.acquire_fence); - outBuf.stream = returned_buf_reqs[i].stream; - outBuf.status = CAMERA3_BUFFER_STATUS_OK; - outBuf.release_fence = -1; - } - returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_OK; - } break; - default: - ALOGE("%s: unknown StreamBuffersVal discrimator!", __FUNCTION__); - cleanupInflightBufferFences(importedFences, importedBuffers); - return CAMERA3_BUF_REQ_FAILED_UNKNOWN; - } - } - - *num_returned_buf_reqs = num_buffer_reqs; - - return (status == BufferRequestStatus::OK) ? - CAMERA3_BUF_REQ_OK : CAMERA3_BUF_REQ_FAILED_PARTIAL; - } - switch (status) { case BufferRequestStatus::FAILED_CONFIGURING: return CAMERA3_BUF_REQ_FAILED_CONFIGURING; case BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS: return CAMERA3_BUF_REQ_FAILED_ILLEGAL_ARGUMENTS; - case BufferRequestStatus::FAILED_UNKNOWN: default: - return CAMERA3_BUF_REQ_FAILED_UNKNOWN; + break; // Other status Handled by following code } + + if (status != BufferRequestStatus::OK && status != BufferRequestStatus::FAILED_PARTIAL && + status != BufferRequestStatus::FAILED_UNKNOWN) { + ALOGE("%s: unknown buffer request error code %d", __FUNCTION__, status); + return CAMERA3_BUF_REQ_FAILED_UNKNOWN; + } + + // Only OK, FAILED_PARTIAL and FAILED_UNKNOWN reaches here + if (bufRets.size() != num_buffer_reqs) { + ALOGE("%s: expect %d buffer requests returned, only got %zu", + __FUNCTION__, num_buffer_reqs, bufRets.size()); + return CAMERA3_BUF_REQ_FAILED_UNKNOWN; + } + + *num_returned_buf_reqs = num_buffer_reqs; + for (size_t i = 0; i < num_buffer_reqs; i++) { + // maybe we can query all streams in one call to avoid frequent locking device here? + Camera3Stream* stream = getStreamPointer(bufRets[i].streamId); + if (stream == nullptr) { + ALOGE("%s: unknown streamId %d", __FUNCTION__, bufRets[i].streamId); + return CAMERA3_BUF_REQ_FAILED_UNKNOWN; + } + returned_buf_reqs[i].stream = stream; + } + + // Handle failed streams + for (size_t i = 0; i < num_buffer_reqs; i++) { + if (bufRets[i].val.getDiscriminator() == StreamBuffersVal::hidl_discriminator::error) { + returned_buf_reqs[i].num_output_buffers = 0; + switch (bufRets[i].val.error()) { + case StreamBufferRequestError::NO_BUFFER_AVAILABLE: + returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_NO_BUFFER_AVAILABLE; + break; + case StreamBufferRequestError::MAX_BUFFER_EXCEEDED: + returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_MAX_BUFFER_EXCEEDED; + break; + case StreamBufferRequestError::STREAM_DISCONNECTED: + returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_STREAM_DISCONNECTED; + break; + case StreamBufferRequestError::UNKNOWN_ERROR: + returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_UNKNOWN_ERROR; + break; + default: + ALOGE("%s: Unknown StreamBufferRequestError %d", + __FUNCTION__, bufRets[i].val.error()); + return CAMERA3_BUF_REQ_FAILED_UNKNOWN; + } + } + } + + if (status == BufferRequestStatus::FAILED_UNKNOWN) { + return CAMERA3_BUF_REQ_FAILED_UNKNOWN; + } + + // Only BufferRequestStatus::OK and BufferRequestStatus::FAILED_PARTIAL reaches here + std::vector importedFences; + std::vector> importedBuffers; + for (size_t i = 0; i < num_buffer_reqs; i++) { + if (bufRets[i].val.getDiscriminator() != + StreamBuffersVal::hidl_discriminator::buffers) { + continue; + } + int streamId = bufRets[i].streamId; + const hidl_vec& hBufs = bufRets[i].val.buffers(); + camera3_stream_buffer_t* outBufs = returned_buf_reqs[i].output_buffers; + for (size_t b = 0; b < hBufs.size(); b++) { + const StreamBuffer& hBuf = hBufs[b]; + camera3_stream_buffer_t& outBuf = outBufs[b]; + // maybe add importBuffers API to avoid frequent locking device? + Status s = importBuffer(streamId, + hBuf.bufferId, hBuf.buffer.getNativeHandle(), + /*out*/&(outBuf.buffer), + /*allowEmptyBuf*/false); + if (s != Status::OK) { + ALOGE("%s: import stream %d bufferId %" PRIu64 " failed!", + __FUNCTION__, streamId, hBuf.bufferId); + cleanupInflightBufferFences(importedFences, importedBuffers); + // Buffer import should never fail - restart HAL since something is very + // wrong. + assert(false); + return CAMERA3_BUF_REQ_FAILED_UNKNOWN; + } + + pushBufferId(*(outBuf.buffer), hBuf.bufferId, streamId); + importedBuffers.push_back(std::make_pair(*(outBuf.buffer), streamId)); + + if (!sHandleImporter.importFence( + hBuf.acquireFence, + outBuf.acquire_fence)) { + ALOGE("%s: stream %d bufferId %" PRIu64 "acquire fence is invalid", + __FUNCTION__, streamId, hBuf.bufferId); + cleanupInflightBufferFences(importedFences, importedBuffers); + return CAMERA3_BUF_REQ_FAILED_UNKNOWN; + } + importedFences.push_back(outBuf.acquire_fence); + outBuf.stream = returned_buf_reqs[i].stream; + outBuf.status = CAMERA3_BUFFER_STATUS_OK; + outBuf.release_fence = -1; + } + returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_OK; + } + + return (status == BufferRequestStatus::OK) ? + CAMERA3_BUF_REQ_OK : CAMERA3_BUF_REQ_FAILED_PARTIAL; } void CameraDeviceSession::returnStreamBuffers( diff --git a/camera/device/3.5/types.hal b/camera/device/3.5/types.hal index 7cb97277db..e3c235018f 100644 --- a/camera/device/3.5/types.hal +++ b/camera/device/3.5/types.hal @@ -120,7 +120,9 @@ enum BufferRequestStatus : uint32_t { /** * Method call failed for all streams and no buffers are returned at all. - * Failure due to unknown reason. + * Failure due to unknown reason, or all streams has individual failing + * reason. For the latter case, check per stream status for each returned + * StreamBufferRet. */ FAILED_UNKNOWN = 4, }; diff --git a/current.txt b/current.txt index 796e0ffa12..7cf8f4388b 100644 --- a/current.txt +++ b/current.txt @@ -444,7 +444,7 @@ f7431f3e3e4e3387fc6f27a6cf423eddcd824a395dc4349d302c995ab44a9895 android.hardwar 09ab9b24994429d9bb32a3fb420b6f6be3e47eb655139a2c08c4e80d3f33ff95 android.hardware.camera.device@3.5::ICameraDevice 06237de53c42890029e3f8fe7d1480d078469c0d07608e51c37b4d485d342992 android.hardware.camera.device@3.5::ICameraDeviceCallback 08c68b196e2fc4e5ba67ba0d0917bde828a87cbe2cffec19d04733972da9eb49 android.hardware.camera.device@3.5::ICameraDeviceSession -d487ab209944df8987eeca70cf09307fc1429cedf64b0ea9e77c61d8caeb8c15 android.hardware.camera.device@3.5::types +acaba39216973e58949f50978762bcda1c29f5f7e0bca3e08db21f0767356130 android.hardware.camera.device@3.5::types 74ec7732fdacb22292c907b49f8f933510851ea1b3ed195c4dcdff35a20387f5 android.hardware.camera.metadata@3.4::types 0fb39a7809ad1c52b3efbbed5ef4749b06c2a4f1f19cdc3efa2e3d9b28f1205c android.hardware.camera.provider@2.5::ICameraProvider f5777403d65135a5407723671bc7a864cdca83aea13ee3ce2894b95e6588ca3a android.hardware.camera.provider@2.5::types From 9e3079b0de9ce00681c623eddc6613ae4d96b6f5 Mon Sep 17 00:00:00 2001 From: Yin-Chia Yeh Date: Wed, 13 Feb 2019 15:18:16 -0800 Subject: [PATCH 482/718] Camera: remove stream_configuration_counter from camera3.h Handle the race issue in the wrapper HAL instead of letting HAL implementation handing it. Test: Pixel 3 + camera CTS + GCA Bug: 120986771 Change-Id: Iff97fcaa969bea6668679c57642e4322c4ca5c19 --- .../3.4/default/CameraDeviceSession.cpp | 4 +++- .../device_v3_4_impl/CameraDeviceSession.h | 4 ++++ .../3.5/default/CameraDeviceSession.cpp | 22 +++++++++++++++---- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/camera/device/3.4/default/CameraDeviceSession.cpp b/camera/device/3.4/default/CameraDeviceSession.cpp index c937834928..e00b3f83d0 100644 --- a/camera/device/3.4/default/CameraDeviceSession.cpp +++ b/camera/device/3.4/default/CameraDeviceSession.cpp @@ -128,7 +128,9 @@ void CameraDeviceSession::configureStreams_3_4_Impl( } camera3_stream_configuration_t stream_list{}; - stream_list.stream_configuration_counter = streamConfigCounter; + // Block reading mStreamConfigCounter until configureStream returns + Mutex::Autolock _sccl(mStreamConfigCounterLock); + mStreamConfigCounter = streamConfigCounter; hidl_vec streams; stream_list.session_parameters = paramBuffer; if (!preProcessConfigurationLocked_3_4(requestedConfiguration, &stream_list, &streams)) { diff --git a/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h b/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h index 00500b15f8..1db7b41dec 100644 --- a/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h +++ b/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h @@ -123,6 +123,10 @@ protected: // Physical camera ids for the logical multi-camera. Empty if this // is not a logical multi-camera. std::unordered_set mPhysicalCameraIds; + + Mutex mStreamConfigCounterLock; + uint32_t mStreamConfigCounter = 1; + private: struct TrampolineSessionInterface_3_4 : public ICameraDeviceSession { diff --git a/camera/device/3.5/default/CameraDeviceSession.cpp b/camera/device/3.5/default/CameraDeviceSession.cpp index 873ddd0460..bea1be6d53 100644 --- a/camera/device/3.5/default/CameraDeviceSession.cpp +++ b/camera/device/3.5/default/CameraDeviceSession.cpp @@ -72,6 +72,22 @@ Return CameraDeviceSession::configureStreams_3_5( Return CameraDeviceSession::signalStreamFlush( const hidl_vec& streamIds, uint32_t streamConfigCounter) { + if (mDevice->ops->signal_stream_flush == nullptr) { + return Void(); + } + + uint32_t currentCounter = 0; + { + Mutex::Autolock _l(mStreamConfigCounterLock); + currentCounter = mStreamConfigCounter; + } + + if (streamConfigCounter < currentCounter) { + ALOGV("%s: streamConfigCounter %d is stale (current %d), skipping signal_stream_flush call", + __FUNCTION__, streamConfigCounter, mStreamConfigCounter); + return Void(); + } + std::vector streams(streamIds.size()); { Mutex::Autolock _l(mInflightLock); @@ -84,10 +100,8 @@ Return CameraDeviceSession::signalStreamFlush( streams[i] = &mStreamMap[id]; } } - if (mDevice->ops->signal_stream_flush != nullptr) { - mDevice->ops->signal_stream_flush(mDevice, - streamConfigCounter, streams.size(), streams.data()); - } + + mDevice->ops->signal_stream_flush(mDevice, streams.size(), streams.data()); return Void(); } From d0dc2bd3416cd049df1128b9d8b35ee674fafee5 Mon Sep 17 00:00:00 2001 From: Changyeon Jo Date: Sat, 9 Feb 2019 19:49:23 +0000 Subject: [PATCH 483/718] Updates openDisplay() API description This change corrects the description of openDisplay()'s behavior when new client requests to access a display resource. Bug: 122671398 Test: N/A Change-Id: Ic7380748f4907376563771498e8823ed739e09a6 Signed-off-by: Changyeon Jo --- automotive/evs/1.0/IEvsEnumerator.hal | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/automotive/evs/1.0/IEvsEnumerator.hal b/automotive/evs/1.0/IEvsEnumerator.hal index e1193d030c..ee51e7e994 100644 --- a/automotive/evs/1.0/IEvsEnumerator.hal +++ b/automotive/evs/1.0/IEvsEnumerator.hal @@ -57,7 +57,8 @@ interface IEvsEnumerator { * * There can be at most one EVS display object for the system and this function * requests access to it. If the EVS display is not available or is already in use, - * a null pointer is returned. + * the old instance shall be closed and give the new caller exclusive + * access. * When done using the display, the caller may release it by calling closeDisplay(). * TODO(b/36122635) Reliance on the sp<> going out of scope is not recommended because the * resources may not be released right away due to asynchronos behavior in the hardware binder. From 44015c090ae4d7df4b723b1928c2a446d49be6bf Mon Sep 17 00:00:00 2001 From: Lev Proleev Date: Fri, 8 Feb 2019 11:42:37 +0000 Subject: [PATCH 484/718] Update TRANSPOSE_CONV_2D docs * Add info about per-channel quantization * Update current.txt Test: mma Change-Id: I197d984c8b65b4c46bf526eb137f212ad8844926 --- current.txt | 2 +- neuralnetworks/1.2/types.hal | 49 +++++++++++++++++++++++++++--------- 2 files changed, 38 insertions(+), 13 deletions(-) diff --git a/current.txt b/current.txt index fd55d7cb1f..9c29fc986d 100644 --- a/current.txt +++ b/current.txt @@ -508,7 +508,7 @@ c3dfaa1fcd452c6cfc26d8dcbb67b71b08a1fe6dad5f87427e93d11a95372b05 android.hardwar 92714960d1a53fc2ec557302b41c7cc93d2636d8364a44bd0f85be0c92927ff8 android.hardware.neuralnetworks@1.2::IExecutionCallback 83885d366f22ada42c00d8854f0b7e7ba4cf73ddf80bb0d8e168ce132cec57ea android.hardware.neuralnetworks@1.2::IPreparedModel e1c734d1545e1a4ae749ff1dd9704a8e594c59aea7c8363159dc258e93e0df3b android.hardware.neuralnetworks@1.2::IPreparedModelCallback -313b341f1f6196a48cf304eaf067f67510c1ebc04df8c7cd536db5611df5c5c2 android.hardware.neuralnetworks@1.2::types +769f8650631eef7a3ceedc8cf130f4b99eb52fe698a11609d55de32985a3dddf android.hardware.neuralnetworks@1.2::types cf7a4ba516a638f9b82a249c91fb603042c2d9ca43fd5aad9cf6c0401ed2a5d7 android.hardware.nfc@1.2::INfc abf98c2ae08bf765db54edc8068e36d52eb558cff6706b6fd7c18c65a1f3fc18 android.hardware.nfc@1.2::types 4cb252dc6372a874aef666b92a6e9529915aa187521a700f0789065c3c702ead android.hardware.power.stats@1.0::IPowerStats diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal index 06bdc6adf4..ab17598d1c 100644 --- a/neuralnetworks/1.2/types.hal +++ b/neuralnetworks/1.2/types.hal @@ -342,7 +342,7 @@ enum OperationType : int32_t { * * * input.scale * filter.scale). * * Available since API level 29: - * * Quantized with symetric per channel quantization for the filter: + * * Quantized with symmetric per channel quantization for the filter: * * * {@link OperandType::TENSOR_QUANT8_ASYMM} for input, and output. * * * {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} for filter. * * * {@link OperandType::TENSOR_INT32} for bias (scale set to 0.0, @@ -491,7 +491,7 @@ enum OperationType : int32_t { * * * input.scale * filter.scale). * * Available since API level 29: - * * Quantized with symetric per channel quantization for the filter: + * * Quantized with symmetric per channel quantization for the filter: * * * {@link OperandType::TENSOR_QUANT8_ASYMM} for input, and output. * * * {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} for filter. * * * {@link OperandType::TENSOR_INT32} for bias (scale set to 0.0, @@ -3018,7 +3018,7 @@ enum OperationType : int32_t { * * * {@link OperandType::TENSOR_INT32} for bias (with scale set to * * * input.scale * filter.scale). * - * * Quantized with symetric per channel quantization for the filter: + * * Quantized with symmetric per channel quantization for the filter: * * * {@link OperandType::TENSOR_QUANT8_ASYMM} for input, and output. * * * {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} for filter. * * * {@link OperandType::TENSOR_INT32} for bias (scale set to 0.0, @@ -4204,10 +4204,21 @@ enum OperationType : int32_t { * The output dimensions are functions of the filter dimensions, stride, and * padding. * - * Supported tensor {@link OperandType}: - * * {@link OperandType::TENSOR_FLOAT16} - * * {@link OperandType::TENSOR_FLOAT32} - * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * Supported tensor {@link OperandCode} configurations: + * * 32 bit Floating point : + * * * {@link OperandType::TENSOR_FLOAT32} for input, filter, output, and bias. + * + * * Quantized: + * * * {@link OperandType::TENSOR_QUANT8_ASYMM} for input, filter, and output. + * * * {@link OperandType::TENSOR_INT32} for bias (with scale set to + * * * input.scale * filter.scale). + * + * Available since API level 29: + * * Quantized with symmetric per channel quantization for the filter: + * * * {@link OperandType::TENSOR_QUANT8_ASYMM} for input, and output. + * * * {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} for filter. + * * * {@link OperandType::TENSOR_INT32} for bias (scale set to 0.0, + * * * each value scaling is separate and equal to input.scale * filter.scales[channel]). * * Supported tensor rank: 4, with "NHWC" or "NCHW" data layout. * With the default data layout NHWC, the data is stored in the order of: @@ -4221,14 +4232,20 @@ enum OperationType : int32_t { * specifying the input. * * 1: A 4-D tensor, of shape * [depth_out, filter_height, filter_width, depth_in], specifying the - * filter. + * filter. For tensor of type + * {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} the channel + * dimension (extraParams.channelQuant.channelDim) must be set to 0. * * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input * tensor of type {@link OperandType::TENSOR_FLOAT32} or * {@link OperandType::TENSOR_FLOAT16}, the bias should be of the * same type. For input tensor of type * {@link OperandType::TENSOR_QUANT8_ASYMM}, the bias should be * of {@link OperandType::TENSOR_INT32}, with zeroPoint of 0 and - * bias_scale == input_scale * filter_scale. + * bias_scale == input_scale * filter_scale. For filter tensor of + * {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL}, the bias + * must be of {@link OperandType::TENSOR_INT32}, with zeroPoint of + * 0 and bias_scale of 0. The actual scale of each value 'i' is equal + * to bias_scale[i] = input_scale * filter_scale[i]. * * 3: An {@link OperandType::INT32} scalar, specifying the padding on * the left, in the ‘width’ dimension. * * 4: An {@link OperandType::INT32} scalar, specifying the padding on @@ -4252,14 +4269,20 @@ enum OperationType : int32_t { * specifying the input. * * 1: A 4-D tensor, of shape * [depth_out, filter_height, filter_width, depth_in], specifying the - * filter. + * filter. For tensor of type + * {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} the channel + * dimension (extraParams.channelQuant.channelDim) must be set to 0. * * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input * tensor of type {@link OperandType::TENSOR_FLOAT32} or * {@link OperandType::TENSOR_FLOAT16}, the bias should be of the * same type. For input tensor of type * {@link OperandType::TENSOR_QUANT8_ASYMM}, the bias should be * of {@link OperandType::TENSOR_INT32}, with zeroPoint of 0 and - * bias_scale == input_scale * filter_scale. + * bias_scale == input_scale * filter_scale. For filter tensor of + * {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL}, the bias + * must be of {@link OperandType::TENSOR_INT32}, with zeroPoint of + * 0 and bias_scale of 0. The actual scale of each value 'i' is equal + * to bias_scale[i] = input_scale * filter_scale[i]. * * 3: An {@link OperandType::TENSOR_INT32} tensor, specifying the output * tensor shape. * * 4: An {@link OperandType::INT32} scalar, specifying the implicit @@ -4279,7 +4302,9 @@ enum OperationType : int32_t { * * 0: The output 4-D tensor, of shape * [batches, out_height, out_width, depth_out]. For output tensor of * {@link OperandType::TENSOR_QUANT8_ASYMM}, the following condition - * must be satisfied: output_scale > input_scale * filter_scale. + * must be satisfied: output_scale > input_scale * filter_scale (for + * filter tensor of {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} + * this condition must be true for all filter scales). * * Available since API level 29. */ From a509861a59bf214c54a84d1b08089fc9bc8ef4b8 Mon Sep 17 00:00:00 2001 From: Yu-Han Yang Date: Fri, 8 Feb 2019 16:22:07 -0800 Subject: [PATCH 485/718] Report mock locations in 2.0 default implementation - Create android.hardware.gnss@common-default-lib for sharing common default implementation code. - Create android.hardware.gnss@common-vts-lib for sharing common VTS code. Bug: 121217686 Change-Id: I35c127c23d97ab9a5c6ee13b36fbfe9c3708e3f3 Fixes: 121217686 Test: tested on cuttlefish --- gnss/1.1/default/Android.bp | 3 + gnss/1.1/default/Gnss.cpp | 48 +++------ gnss/1.1/default/Gnss.h | 3 - gnss/1.1/default/GnssDebug.cpp | 4 +- gnss/1.1/vts/functional/Android.bp | 1 + gnss/1.1/vts/functional/gnss_hal_test.cpp | 68 +------------ gnss/2.0/default/Android.bp | 3 + gnss/2.0/default/Gnss.cpp | 47 +++++++-- gnss/2.0/default/Gnss.h | 21 +++- gnss/2.0/vts/functional/Android.bp | 1 + gnss/2.0/vts/functional/gnss_hal_test.cpp | 87 ++++++++++++++++- gnss/2.0/vts/functional/gnss_hal_test.h | 42 ++++++++ gnss/common/OWNERS | 7 ++ gnss/common/utils/default/Android.bp | 33 +++++++ gnss/common/utils/default/Utils.cpp | 57 +++++++++++ .../utils/default/include/Constants.h} | 16 +-- gnss/common/utils/default/include/Utils.h | 42 ++++++++ gnss/common/utils/vts/Android.bp | 36 +++++++ gnss/common/utils/vts/Utils.cpp | 97 +++++++++++++++++++ gnss/common/utils/vts/include/Utils.h | 39 ++++++++ 20 files changed, 530 insertions(+), 125 deletions(-) create mode 100644 gnss/common/OWNERS create mode 100644 gnss/common/utils/default/Android.bp create mode 100644 gnss/common/utils/default/Utils.cpp rename gnss/{1.1/default/GnssConstants.h => common/utils/default/include/Constants.h} (78%) create mode 100644 gnss/common/utils/default/include/Utils.h create mode 100644 gnss/common/utils/vts/Android.bp create mode 100644 gnss/common/utils/vts/Utils.cpp create mode 100644 gnss/common/utils/vts/include/Utils.h diff --git a/gnss/1.1/default/Android.bp b/gnss/1.1/default/Android.bp index 44aed2b069..8c3aac4278 100644 --- a/gnss/1.1/default/Android.bp +++ b/gnss/1.1/default/Android.bp @@ -18,4 +18,7 @@ cc_binary { "android.hardware.gnss@1.1", "android.hardware.gnss@1.0", ], + static_libs: [ + "android.hardware.gnss@common-default-lib", + ], } diff --git a/gnss/1.1/default/Gnss.cpp b/gnss/1.1/default/Gnss.cpp index bbf1cd31de..4abe707d4a 100644 --- a/gnss/1.1/default/Gnss.cpp +++ b/gnss/1.1/default/Gnss.cpp @@ -4,9 +4,9 @@ #include #include "Gnss.h" -#include "GnssConstants.h" #include "GnssDebug.h" #include "GnssMeasurement.h" +#include "Utils.h" namespace android { namespace hardware { @@ -14,6 +14,7 @@ namespace gnss { namespace V1_1 { namespace implementation { +using ::android::hardware::gnss::common::Utils; using GnssSvFlags = IGnssCallback::GnssSvFlags; const uint32_t MIN_INTERVAL_MILLIS = 100; @@ -43,7 +44,7 @@ Return Gnss::start() { auto svStatus = this->getMockSvStatus(); this->reportSvStatus(svStatus); - auto location = this->getMockLocation(); + auto location = Utils::getMockLocation(); this->reportLocation(location); std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMs)); @@ -193,44 +194,17 @@ Return Gnss::injectBestLocation(const GnssLocation&) { return true; } -Return Gnss::getMockLocation() const { - GnssLocation location = {.gnssLocationFlags = 0xFF, - .latitudeDegrees = kMockLatitudeDegrees, - .longitudeDegrees = kMockLongitudeDegrees, - .altitudeMeters = kMockAltitudeMeters, - .speedMetersPerSec = kMockSpeedMetersPerSec, - .bearingDegrees = kMockBearingDegrees, - .horizontalAccuracyMeters = kMockHorizontalAccuracyMeters, - .verticalAccuracyMeters = kMockVerticalAccuracyMeters, - .speedAccuracyMetersPerSecond = kMockSpeedAccuracyMetersPerSecond, - .bearingAccuracyDegrees = kMockBearingAccuracyDegrees, - .timestamp = kMockTimestamp}; - return location; -} - -Return Gnss::getSvInfo(int16_t svid, GnssConstellationType type, float cN0DbHz, - float elevationDegrees, float azimuthDegrees) const { - GnssSvInfo svInfo = {.svid = svid, - .constellation = type, - .cN0Dbhz = cN0DbHz, - .elevationDegrees = elevationDegrees, - .azimuthDegrees = azimuthDegrees, - .svFlag = GnssSvFlags::USED_IN_FIX | GnssSvFlags::HAS_EPHEMERIS_DATA | - GnssSvFlags::HAS_ALMANAC_DATA}; - return svInfo; -} - Return Gnss::getMockSvStatus() const { std::unique_lock lock(mGnssConfiguration->getMutex()); GnssSvInfo mockGnssSvInfoList[] = { - getSvInfo(3, GnssConstellationType::GPS, 32.5, 59.1, 166.5), - getSvInfo(5, GnssConstellationType::GPS, 27.0, 29.0, 56.5), - getSvInfo(17, GnssConstellationType::GPS, 30.5, 71.0, 77.0), - getSvInfo(26, GnssConstellationType::GPS, 24.1, 28.0, 253.0), - getSvInfo(5, GnssConstellationType::GLONASS, 20.5, 11.5, 116.0), - getSvInfo(17, GnssConstellationType::GLONASS, 21.5, 28.5, 186.0), - getSvInfo(18, GnssConstellationType::GLONASS, 28.3, 38.8, 69.0), - getSvInfo(10, GnssConstellationType::GLONASS, 25.0, 66.0, 247.0)}; + Utils::getSvInfo(3, GnssConstellationType::GPS, 32.5, 59.1, 166.5), + Utils::getSvInfo(5, GnssConstellationType::GPS, 27.0, 29.0, 56.5), + Utils::getSvInfo(17, GnssConstellationType::GPS, 30.5, 71.0, 77.0), + Utils::getSvInfo(26, GnssConstellationType::GPS, 24.1, 28.0, 253.0), + Utils::getSvInfo(5, GnssConstellationType::GLONASS, 20.5, 11.5, 116.0), + Utils::getSvInfo(17, GnssConstellationType::GLONASS, 21.5, 28.5, 186.0), + Utils::getSvInfo(18, GnssConstellationType::GLONASS, 28.3, 38.8, 69.0), + Utils::getSvInfo(10, GnssConstellationType::GLONASS, 25.0, 66.0, 247.0)}; GnssSvStatus svStatus = {.numSvs = sizeof(mockGnssSvInfoList) / sizeof(GnssSvInfo)}; for (uint32_t i = 0; i < svStatus.numSvs; i++) { diff --git a/gnss/1.1/default/Gnss.h b/gnss/1.1/default/Gnss.h index 99af34cdcf..21b66a213f 100644 --- a/gnss/1.1/default/Gnss.h +++ b/gnss/1.1/default/Gnss.h @@ -84,10 +84,7 @@ struct Gnss : public IGnss { // Methods from ::android::hidl::base::V1_0::IBase follow. private: - Return getMockLocation() const; Return getMockSvStatus() const; - Return getSvInfo(int16_t svid, GnssConstellationType type, float cN0DbHz, - float elevationDegress, float azimuthDegress) const; Return reportLocation(const GnssLocation&) const; Return reportSvStatus(const GnssSvStatus&) const; diff --git a/gnss/1.1/default/GnssDebug.cpp b/gnss/1.1/default/GnssDebug.cpp index 62870e4c53..471ed2421d 100644 --- a/gnss/1.1/default/GnssDebug.cpp +++ b/gnss/1.1/default/GnssDebug.cpp @@ -18,9 +18,11 @@ #include -#include "GnssConstants.h" +#include "Constants.h" #include "GnssDebug.h" +using namespace ::android::hardware::gnss::common; + namespace android { namespace hardware { namespace gnss { diff --git a/gnss/1.1/vts/functional/Android.bp b/gnss/1.1/vts/functional/Android.bp index 9892eca129..147a470f8a 100644 --- a/gnss/1.1/vts/functional/Android.bp +++ b/gnss/1.1/vts/functional/Android.bp @@ -25,6 +25,7 @@ cc_test { static_libs: [ "android.hardware.gnss@1.0", "android.hardware.gnss@1.1", + "android.hardware.gnss@common-vts-lib", ], test_suites: ["general-tests"], } diff --git a/gnss/1.1/vts/functional/gnss_hal_test.cpp b/gnss/1.1/vts/functional/gnss_hal_test.cpp index 433f5cb4ea..381ac1d3af 100644 --- a/gnss/1.1/vts/functional/gnss_hal_test.cpp +++ b/gnss/1.1/vts/functional/gnss_hal_test.cpp @@ -17,8 +17,10 @@ #define LOG_TAG "GnssHalTest" #include - #include +#include "Utils.h" + +using ::android::hardware::gnss::common::Utils; // Implementations for the main test class for GNSS HAL GnssHalTest::GnssHalTest() @@ -124,69 +126,7 @@ bool GnssHalTest::StartAndCheckFirstLocation() { void GnssHalTest::CheckLocation(GnssLocation& location, bool check_speed) { bool check_more_accuracies = (info_called_count_ > 0 && last_info_.yearOfHw >= 2017); - EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_LAT_LONG); - EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_ALTITUDE); - if (check_speed) { - EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_SPEED); - } - EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_HORIZONTAL_ACCURACY); - // New uncertainties available in O must be provided, - // at least when paired with modern hardware (2017+) - if (check_more_accuracies) { - EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY); - if (check_speed) { - EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_SPEED_ACCURACY); - if (location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) { - EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING_ACCURACY); - } - } - } - EXPECT_GE(location.latitudeDegrees, -90.0); - EXPECT_LE(location.latitudeDegrees, 90.0); - EXPECT_GE(location.longitudeDegrees, -180.0); - EXPECT_LE(location.longitudeDegrees, 180.0); - EXPECT_GE(location.altitudeMeters, -1000.0); - EXPECT_LE(location.altitudeMeters, 30000.0); - if (check_speed) { - EXPECT_GE(location.speedMetersPerSec, 0.0); - EXPECT_LE(location.speedMetersPerSec, 5.0); // VTS tests are stationary. - - // Non-zero speeds must be reported with an associated bearing - if (location.speedMetersPerSec > 0.0) { - EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING); - } - } - - /* - * Tolerating some especially high values for accuracy estimate, in case of - * first fix with especially poor geometry (happens occasionally) - */ - EXPECT_GT(location.horizontalAccuracyMeters, 0.0); - EXPECT_LE(location.horizontalAccuracyMeters, 250.0); - - /* - * Some devices may define bearing as -180 to +180, others as 0 to 360. - * Both are okay & understandable. - */ - if (location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) { - EXPECT_GE(location.bearingDegrees, -180.0); - EXPECT_LE(location.bearingDegrees, 360.0); - } - if (location.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY) { - EXPECT_GT(location.verticalAccuracyMeters, 0.0); - EXPECT_LE(location.verticalAccuracyMeters, 500.0); - } - if (location.gnssLocationFlags & GnssLocationFlags::HAS_SPEED_ACCURACY) { - EXPECT_GT(location.speedAccuracyMetersPerSecond, 0.0); - EXPECT_LE(location.speedAccuracyMetersPerSecond, 50.0); - } - if (location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING_ACCURACY) { - EXPECT_GT(location.bearingAccuracyDegrees, 0.0); - EXPECT_LE(location.bearingAccuracyDegrees, 360.0); - } - - // Check timestamp > 1.48e12 (47 years in msec - 1970->2017+) - EXPECT_GT(location.timestamp, 1.48e12); + Utils::checkLocation(location, check_speed, check_more_accuracies); } void GnssHalTest::StartAndCheckLocations(int count) { diff --git a/gnss/2.0/default/Android.bp b/gnss/2.0/default/Android.bp index 985aa2ba88..f327197f62 100644 --- a/gnss/2.0/default/Android.bp +++ b/gnss/2.0/default/Android.bp @@ -40,4 +40,7 @@ cc_binary { "android.hardware.gnss@1.0", "android.hardware.gnss@1.1", ], + static_libs: [ + "android.hardware.gnss@common-default-lib", + ], } diff --git a/gnss/2.0/default/Gnss.cpp b/gnss/2.0/default/Gnss.cpp index 217f0f358b..1efc9f5b48 100644 --- a/gnss/2.0/default/Gnss.cpp +++ b/gnss/2.0/default/Gnss.cpp @@ -23,8 +23,10 @@ #include "GnssConfiguration.h" #include "GnssMeasurement.h" #include "GnssVisibilityControl.h" +#include "Utils.h" using ::android::hardware::Status; +using ::android::hardware::gnss::common::Utils; using ::android::hardware::gnss::visibility_control::V1_0::implementation::GnssVisibilityControl; namespace android { @@ -33,9 +35,17 @@ namespace gnss { namespace V2_0 { namespace implementation { +using GnssSvFlags = IGnssCallback::GnssSvFlags; + sp Gnss::sGnssCallback_2_0 = nullptr; sp Gnss::sGnssCallback_1_1 = nullptr; +Gnss::Gnss() : mMinIntervalMs(1000) {} + +Gnss::~Gnss() { + stop(); +} + // Methods from V1_0::IGnss follow. Return Gnss::setCallback(const sp&) { // TODO implement @@ -43,13 +53,29 @@ Return Gnss::setCallback(const sp&) { } Return Gnss::start() { - // TODO implement - return bool{}; + if (mIsActive) { + ALOGW("Gnss has started. Restarting..."); + stop(); + } + + mIsActive = true; + mThread = std::thread([this]() { + while (mIsActive == true) { + const auto location = Utils::getMockLocation(); + this->reportLocation(location); + + std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMs)); + } + }); + return true; } Return Gnss::stop() { - // TODO implement - return bool{}; + mIsActive = false; + if (mThread.joinable()) { + mThread.join(); + } + return true; } Return Gnss::cleanup() { @@ -164,8 +190,7 @@ Return Gnss::setCallback_1_1(const sp& callback) { Return Gnss::setPositionMode_1_1(V1_0::IGnss::GnssPositionMode, V1_0::IGnss::GnssPositionRecurrence, uint32_t, uint32_t, uint32_t, bool) { - // TODO implement - return bool{}; + return true; } Return> Gnss::getExtensionGnssConfiguration_1_1() { @@ -243,6 +268,16 @@ Return Gnss::setCallback_2_0(const sp& callback) { return true; } +Return Gnss::reportLocation(const GnssLocation& location) const { + std::unique_lock lock(mMutex); + if (sGnssCallback_1_1 == nullptr) { + ALOGE("%s: sGnssCallback is null.", __func__); + return Void(); + } + sGnssCallback_1_1->gnssLocationCb(location); + return Void(); +} + } // namespace implementation } // namespace V2_0 } // namespace gnss diff --git a/gnss/2.0/default/Gnss.h b/gnss/2.0/default/Gnss.h index 890b026749..7d9e7831cd 100644 --- a/gnss/2.0/default/Gnss.h +++ b/gnss/2.0/default/Gnss.h @@ -20,6 +20,9 @@ #include #include #include +#include +#include +#include namespace android { namespace hardware { @@ -35,7 +38,14 @@ using ::android::hardware::hidl_vec; using ::android::hardware::Return; using ::android::hardware::Void; +using GnssConstellationType = V1_0::GnssConstellationType; +using GnssLocation = V1_0::GnssLocation; +using GnssSvInfo = V1_0::IGnssCallback::GnssSvInfo; +using GnssSvStatus = V1_0::IGnssCallback::GnssSvStatus; + struct Gnss : public IGnss { + Gnss(); + ~Gnss(); // Methods from V1_0::IGnss follow. Return setCallback(const sp& callback) override; Return start() override; @@ -69,7 +79,7 @@ struct Gnss : public IGnss { uint32_t preferredTimeMs, bool lowPowerMode) override; Return> getExtensionGnssConfiguration_1_1() override; Return> getExtensionGnssMeasurement_1_1() override; - Return injectBestLocation(const V1_0::GnssLocation& location) override; + Return injectBestLocation(const GnssLocation& location) override; // Methods from V2_0::IGnss follow. Return> getExtensionGnssConfiguration_2_0() override; @@ -83,8 +93,13 @@ struct Gnss : public IGnss { override; private: - static sp sGnssCallback_2_0; - static sp sGnssCallback_1_1; + Return reportLocation(const GnssLocation&) const; + static sp sGnssCallback_2_0; + static sp sGnssCallback_1_1; + std::atomic mMinIntervalMs; + std::atomic mIsActive; + std::thread mThread; + mutable std::mutex mMutex; }; } // namespace implementation diff --git a/gnss/2.0/vts/functional/Android.bp b/gnss/2.0/vts/functional/Android.bp index 684b381ae2..278d87b117 100644 --- a/gnss/2.0/vts/functional/Android.bp +++ b/gnss/2.0/vts/functional/Android.bp @@ -28,5 +28,6 @@ cc_test { "android.hardware.gnss@1.0", "android.hardware.gnss@1.1", "android.hardware.gnss@2.0", + "android.hardware.gnss@common-vts-lib", ], } diff --git a/gnss/2.0/vts/functional/gnss_hal_test.cpp b/gnss/2.0/vts/functional/gnss_hal_test.cpp index 3a48c9e268..1580c28841 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test.cpp +++ b/gnss/2.0/vts/functional/gnss_hal_test.cpp @@ -17,8 +17,10 @@ #define LOG_TAG "GnssHalTest" #include - #include +#include "Utils.h" + +using ::android::hardware::gnss::common::Utils; // Implementations for the main test class for GNSS HAL GnssHalTest::GnssHalTest() @@ -77,9 +79,88 @@ void GnssHalTest::SetUpGnssCallback() { EXPECT_EQ(name_called_count_, 1); } +void GnssHalTest::StopAndClearLocations() { + const auto result = gnss_hal_->stop(); + + EXPECT_TRUE(result.isOk()); + EXPECT_TRUE(result); + + /* + * Clear notify/waiting counter, allowing up till the timeout after + * the last reply for final startup messages to arrive (esp. system + * info.) + */ + while (wait(TIMEOUT_SEC) == std::cv_status::no_timeout) { + } + location_called_count_ = 0; +} + +void GnssHalTest::SetPositionMode(const int min_interval_msec, const bool low_power_mode) { + const int kPreferredAccuracy = 0; // Ideally perfect (matches GnssLocationProvider) + const int kPreferredTimeMsec = 0; // Ideally immediate + + const auto result = gnss_hal_->setPositionMode_1_1( + IGnss::GnssPositionMode::MS_BASED, IGnss::GnssPositionRecurrence::RECURRENCE_PERIODIC, + min_interval_msec, kPreferredAccuracy, kPreferredTimeMsec, low_power_mode); + + ASSERT_TRUE(result.isOk()); + EXPECT_TRUE(result); +} + +bool GnssHalTest::StartAndCheckFirstLocation() { + const auto result = gnss_hal_->start(); + + EXPECT_TRUE(result.isOk()); + EXPECT_TRUE(result); + + /* + * GnssLocationProvider support of AGPS SUPL & XtraDownloader is not available in VTS, + * so allow time to demodulate ephemeris over the air. + */ + const int kFirstGnssLocationTimeoutSeconds = 75; + + wait(kFirstGnssLocationTimeoutSeconds); + EXPECT_EQ(location_called_count_, 1); + + if (location_called_count_ > 0) { + // don't require speed on first fix + CheckLocation(last_location_, false); + return true; + } + return false; +} + +void GnssHalTest::CheckLocation(const GnssLocation& location, bool check_speed) { + const bool check_more_accuracies = (info_called_count_ > 0 && last_info_.yearOfHw >= 2017); + + Utils::checkLocation(location, check_speed, check_more_accuracies); +} + +void GnssHalTest::StartAndCheckLocations(int count) { + const int kMinIntervalMsec = 500; + const int kLocationTimeoutSubsequentSec = 2; + const bool kLowPowerMode = false; + + SetPositionMode(kMinIntervalMsec, kLowPowerMode); + + EXPECT_TRUE(StartAndCheckFirstLocation()); + + for (int i = 1; i < count; i++) { + EXPECT_EQ(std::cv_status::no_timeout, wait(kLocationTimeoutSubsequentSec)); + EXPECT_EQ(location_called_count_, i + 1); + // Don't cause confusion by checking details if no location yet + if (location_called_count_ > 0) { + // Should be more than 1 location by now, but if not, still don't check first fix speed + CheckLocation(last_location_, location_called_count_ > 1); + } + } +} + void GnssHalTest::notify() { - std::unique_lock lock(mtx_); - notify_count_++; + { + std::unique_lock lock(mtx_); + notify_count_++; + } cv_.notify_one(); } diff --git a/gnss/2.0/vts/functional/gnss_hal_test.h b/gnss/2.0/vts/functional/gnss_hal_test.h index 5649b45bbd..2c16651d8d 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test.h +++ b/gnss/2.0/vts/functional/gnss_hal_test.h @@ -130,9 +130,51 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase { */ void SetUpGnssCallback(); + /* + * StartAndCheckFirstLocation: + * Helper function to start location, and check the first one. + * + *

Note this leaves the Location request active, to enable Stop call vs. other call + * reordering tests. + * + * returns true if a location was successfully generated + */ + bool StartAndCheckFirstLocation(); + + /* + * CheckLocation: + * Helper function to vet Location fields + * + * check_speed: true if speed related fields are also verified. + */ + void CheckLocation(const GnssLocation& location, const bool check_speed); + + /* + * StartAndCheckLocations: + * Helper function to collect, and check a number of + * normal ~1Hz locations. + * + * Note this leaves the Location request active, to enable Stop call vs. other call + * reordering tests. + */ + void StartAndCheckLocations(int count); + + /* + * StopAndClearLocations: + * Helper function to stop locations, and clear any remaining notifications + */ + void StopAndClearLocations(); + + /* + * SetPositionMode: + * Helper function to set positioning mode and verify output + */ + void SetPositionMode(const int min_interval_msec, const bool low_power_mode); + sp gnss_hal_; // GNSS HAL to call into sp gnss_cb_; // Primary callback interface + // TODO: make these variables thread-safe. /* Count of calls to set the following items, and the latest item (used by * test.) */ diff --git a/gnss/common/OWNERS b/gnss/common/OWNERS new file mode 100644 index 0000000000..3ed36dae8a --- /dev/null +++ b/gnss/common/OWNERS @@ -0,0 +1,7 @@ +wyattriley@google.com +gomo@google.com +smalkos@google.com +yuhany@google.com + +# VTS team +yim@google.com diff --git a/gnss/common/utils/default/Android.bp b/gnss/common/utils/default/Android.bp new file mode 100644 index 0000000000..4ea97fac67 --- /dev/null +++ b/gnss/common/utils/default/Android.bp @@ -0,0 +1,33 @@ +// +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +cc_library_static { + name: "android.hardware.gnss@common-default-lib", + vendor_available: true, + relative_install_path: "hw", + cflags: [ + "-Wall", + "-Wextra", + "-Werror", + ], + srcs: [ + "Utils.cpp", + ], + export_include_dirs: ["include"], + shared_libs: [ + "android.hardware.gnss@1.0", + ], +} diff --git a/gnss/common/utils/default/Utils.cpp b/gnss/common/utils/default/Utils.cpp new file mode 100644 index 0000000000..b9a06e8d6d --- /dev/null +++ b/gnss/common/utils/default/Utils.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2019 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 +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace common { + +using GnssSvFlags = V1_0::IGnssCallback::GnssSvFlags; + +GnssLocation Utils::getMockLocation() { + GnssLocation location = {.gnssLocationFlags = 0xFF, + .latitudeDegrees = kMockLatitudeDegrees, + .longitudeDegrees = kMockLongitudeDegrees, + .altitudeMeters = kMockAltitudeMeters, + .speedMetersPerSec = kMockSpeedMetersPerSec, + .bearingDegrees = kMockBearingDegrees, + .horizontalAccuracyMeters = kMockHorizontalAccuracyMeters, + .verticalAccuracyMeters = kMockVerticalAccuracyMeters, + .speedAccuracyMetersPerSecond = kMockSpeedAccuracyMetersPerSecond, + .bearingAccuracyDegrees = kMockBearingAccuracyDegrees, + .timestamp = kMockTimestamp}; + return location; +} + +GnssSvInfo Utils::getSvInfo(int16_t svid, GnssConstellationType type, float cN0DbHz, + float elevationDegrees, float azimuthDegrees) { + GnssSvInfo svInfo = {.svid = svid, + .constellation = type, + .cN0Dbhz = cN0DbHz, + .elevationDegrees = elevationDegrees, + .azimuthDegrees = azimuthDegrees, + .svFlag = GnssSvFlags::USED_IN_FIX | GnssSvFlags::HAS_EPHEMERIS_DATA | + GnssSvFlags::HAS_ALMANAC_DATA}; + return svInfo; +} + +} // namespace common +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/gnss/1.1/default/GnssConstants.h b/gnss/common/utils/default/include/Constants.h similarity index 78% rename from gnss/1.1/default/GnssConstants.h rename to gnss/common/utils/default/include/Constants.h index 9ce1a12633..000a9ec7d2 100644 --- a/gnss/1.1/default/GnssConstants.h +++ b/gnss/common/utils/default/include/Constants.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Android Open Source Project + * Copyright (C) 2019 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. @@ -14,14 +14,15 @@ * limitations under the License. */ -#ifndef android_hardware_gnss_V1_1_GnssConstants_H_ -#define android_hardware_gnss_V1_1_GnssConstants_H_ +#ifndef android_hardware_gnss_common_Constants_H_ +#define android_hardware_gnss_common_Constants_H_ + +#include namespace android { namespace hardware { namespace gnss { -namespace V1_1 { -namespace implementation { +namespace common { const float kMockLatitudeDegrees = 37.4219999; const float kMockLongitudeDegrees = -122.0840575; @@ -34,10 +35,9 @@ const float kMockSpeedAccuracyMetersPerSecond = 1; const float kMockBearingAccuracyDegrees = 90; const int64_t kMockTimestamp = 1519930775453L; -} // namespace implementation -} // namespace V1_1 +} // namespace common } // namespace gnss } // namespace hardware } // namespace android -#endif // android_hardware_gnss_V1_1_GnssConstants_H_ +#endif // android_hardware_gnss_common_Constants_H_ diff --git a/gnss/common/utils/default/include/Utils.h b/gnss/common/utils/default/include/Utils.h new file mode 100644 index 0000000000..47c88129f3 --- /dev/null +++ b/gnss/common/utils/default/include/Utils.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2019 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_Utils_H_ +#define android_hardware_gnss_common_default_Utils_H_ + +#include + +using GnssConstellationType = ::android::hardware::gnss::V1_0::GnssConstellationType; +using GnssLocation = ::android::hardware::gnss::V1_0::GnssLocation; +using GnssSvInfo = ::android::hardware::gnss::V1_0::IGnssCallback::GnssSvInfo; + +namespace android { +namespace hardware { +namespace gnss { +namespace common { + +struct Utils { + static GnssLocation getMockLocation(); + static GnssSvInfo getSvInfo(int16_t svid, GnssConstellationType type, float cN0DbHz, + float elevationDegrees, float azimuthDegrees); +}; + +} // namespace common +} // namespace gnss +} // namespace hardware +} // namespace android + +#endif // android_hardware_gnss_common_default_Utils_H_ diff --git a/gnss/common/utils/vts/Android.bp b/gnss/common/utils/vts/Android.bp new file mode 100644 index 0000000000..99d8cf9185 --- /dev/null +++ b/gnss/common/utils/vts/Android.bp @@ -0,0 +1,36 @@ +// +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +cc_library_static { + name: "android.hardware.gnss@common-vts-lib", + vendor_available: true, + relative_install_path: "hw", + cflags: [ + "-Wall", + "-Wextra", + "-Werror", + ], + srcs: [ + "Utils.cpp", + ], + export_include_dirs: ["include"], + shared_libs: [ + "android.hardware.gnss@1.0", + ], + static_libs: [ + "libgtest", + ], +} diff --git a/gnss/common/utils/vts/Utils.cpp b/gnss/common/utils/vts/Utils.cpp new file mode 100644 index 0000000000..24d68839a8 --- /dev/null +++ b/gnss/common/utils/vts/Utils.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2019 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 +#include "gtest/gtest.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace common { + +using V1_0::GnssLocationFlags; + +void Utils::checkLocation(const GnssLocation& location, bool check_speed, + bool check_more_accuracies) { + EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_LAT_LONG); + EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_ALTITUDE); + if (check_speed) { + EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_SPEED); + } + EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_HORIZONTAL_ACCURACY); + // New uncertainties available in O must be provided, + // at least when paired with modern hardware (2017+) + if (check_more_accuracies) { + EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY); + if (check_speed) { + EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_SPEED_ACCURACY); + if (location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) { + EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING_ACCURACY); + } + } + } + EXPECT_GE(location.latitudeDegrees, -90.0); + EXPECT_LE(location.latitudeDegrees, 90.0); + EXPECT_GE(location.longitudeDegrees, -180.0); + EXPECT_LE(location.longitudeDegrees, 180.0); + EXPECT_GE(location.altitudeMeters, -1000.0); + EXPECT_LE(location.altitudeMeters, 30000.0); + if (check_speed) { + EXPECT_GE(location.speedMetersPerSec, 0.0); + EXPECT_LE(location.speedMetersPerSec, 5.0); // VTS tests are stationary. + + // Non-zero speeds must be reported with an associated bearing + if (location.speedMetersPerSec > 0.0) { + EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING); + } + } + + /* + * Tolerating some especially high values for accuracy estimate, in case of + * first fix with especially poor geometry (happens occasionally) + */ + EXPECT_GT(location.horizontalAccuracyMeters, 0.0); + EXPECT_LE(location.horizontalAccuracyMeters, 250.0); + + /* + * Some devices may define bearing as -180 to +180, others as 0 to 360. + * Both are okay & understandable. + */ + if (location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) { + EXPECT_GE(location.bearingDegrees, -180.0); + EXPECT_LE(location.bearingDegrees, 360.0); + } + if (location.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY) { + EXPECT_GT(location.verticalAccuracyMeters, 0.0); + EXPECT_LE(location.verticalAccuracyMeters, 500.0); + } + if (location.gnssLocationFlags & GnssLocationFlags::HAS_SPEED_ACCURACY) { + EXPECT_GT(location.speedAccuracyMetersPerSecond, 0.0); + EXPECT_LE(location.speedAccuracyMetersPerSecond, 50.0); + } + if (location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING_ACCURACY) { + EXPECT_GT(location.bearingAccuracyDegrees, 0.0); + EXPECT_LE(location.bearingAccuracyDegrees, 360.0); + } + + // Check timestamp > 1.48e12 (47 years in msec - 1970->2017+) + EXPECT_GT(location.timestamp, 1.48e12); +} + +} // namespace common +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/gnss/common/utils/vts/include/Utils.h b/gnss/common/utils/vts/include/Utils.h new file mode 100644 index 0000000000..f8eeff6864 --- /dev/null +++ b/gnss/common/utils/vts/include/Utils.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2019 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_vts_Utils_H_ +#define android_hardware_gnss_common_vts_Utils_H_ + +#include + +using GnssLocation = ::android::hardware::gnss::V1_0::GnssLocation; + +namespace android { +namespace hardware { +namespace gnss { +namespace common { + +struct Utils { + static void checkLocation(const GnssLocation& location, bool check_speed, + bool check_more_accuracies); +}; + +} // namespace common +} // namespace gnss +} // namespace hardware +} // namespace android + +#endif // android_hardware_gnss_common_vts_Utils_H_ From 6398207a8ced4d00bdaa70a1548166c7d14bafa3 Mon Sep 17 00:00:00 2001 From: Hai Shalom Date: Thu, 14 Feb 2019 16:44:42 -0800 Subject: [PATCH 486/718] [DPP] Replace HAL interface onSuccess with onSuccessConfigSent Following ANAPIC Review: onSuccess callback was returning only a single status code, CONFIGURATION_SENT. Renamed the callback to onSuccessConfigSent and eliminated the status code. Bug: 124459312 Test: atest DppManagerTest Test: atest SupplicantStaIfaceHalTest Test: act.py -c ../WifiDppConfig.json -tc WifiDppTest Test: vts-tradefed run commandAndExit vts --skip-all-system-status-check --primary-abi-only --skip-preconditions --module VtsHalWifiSupplicantV1_2Host Change-Id: I4d7c5732ded55902b1f235d40d3babe3be372bf7 --- current.txt | 4 ++-- wifi/supplicant/1.2/Android.bp | 1 - .../1.2/ISupplicantStaIfaceCallback.hal | 2 +- wifi/supplicant/1.2/types.hal | 7 ------- .../functional/supplicant_sta_iface_hidl_test.cpp | 15 ++++++--------- 5 files changed, 9 insertions(+), 20 deletions(-) diff --git a/current.txt b/current.txt index 796e0ffa12..3641d8abdc 100644 --- a/current.txt +++ b/current.txt @@ -550,6 +550,6 @@ f3dbd8dd0d6333c005610288a4785d0ef79a72a7bbe6d0a46d46fa89fc886f1e android.hardwar 067b22efc50529a88d650fe7400603429d1164a47ee96a17476fdb0aadd6b4d3 android.hardware.wifi.supplicant@1.2::ISupplicant 120211371fdd29fb134837071d432a302d7b60e9b95af611dd8dde86bd1f77ee android.hardware.wifi.supplicant@1.2::ISupplicantP2pIface 7efe2b057e9f9387b3500e67af97942aa7c8008e6ee7d8dcaae4107fda84016b android.hardware.wifi.supplicant@1.2::ISupplicantStaIface -eb569df2e80f8e276a91a510c75e83fbf957ff1988691726418d44c2be01c520 android.hardware.wifi.supplicant@1.2::ISupplicantStaIfaceCallback +09e08b5d12b109562ecdd8882532fd1f2c4639588e07769d5c7396b7c5b9f34f android.hardware.wifi.supplicant@1.2::ISupplicantStaIfaceCallback efbb061c969fa9553d243da6ee23b83fe5d4aa663a7b8896adc52e2b015bc2f3 android.hardware.wifi.supplicant@1.2::ISupplicantStaNetwork -4851210036650ce6c86498c012db5ff618afce8508a2b06a0e9b902d1840f4bd android.hardware.wifi.supplicant@1.2::types +cfa81f229b69f9011c58f48264fcb552447430fe68610eac514e811e65bc306a android.hardware.wifi.supplicant@1.2::types diff --git a/wifi/supplicant/1.2/Android.bp b/wifi/supplicant/1.2/Android.bp index addcc2a85c..a0fc2b1b59 100644 --- a/wifi/supplicant/1.2/Android.bp +++ b/wifi/supplicant/1.2/Android.bp @@ -24,7 +24,6 @@ hidl_interface { "DppFailureCode", "DppNetRole", "DppProgressCode", - "DppSuccessCode", ], gen_java: true, } diff --git a/wifi/supplicant/1.2/ISupplicantStaIfaceCallback.hal b/wifi/supplicant/1.2/ISupplicantStaIfaceCallback.hal index 5d5cccfb4a..3eac398f9a 100644 --- a/wifi/supplicant/1.2/ISupplicantStaIfaceCallback.hal +++ b/wifi/supplicant/1.2/ISupplicantStaIfaceCallback.hal @@ -37,7 +37,7 @@ interface ISupplicantStaIfaceCallback extends @1.1::ISupplicantStaIfaceCallback /** * Indicates DPP configuration sent success event (Configurator mode). */ - oneway onDppSuccess(DppSuccessCode code); + oneway onDppSuccessConfigSent(); /** * Indicates a DPP progress event. diff --git a/wifi/supplicant/1.2/types.hal b/wifi/supplicant/1.2/types.hal index eaf2546b25..303af195eb 100644 --- a/wifi/supplicant/1.2/types.hal +++ b/wifi/supplicant/1.2/types.hal @@ -34,13 +34,6 @@ enum DppNetRole: uint32_t { AP, }; -/** - * DppSuccessCode: Success codes for DPP (Easy Connect) - */ -enum DppSuccessCode : uint32_t { - CONFIGURATION_SENT, -}; - /** * DppProgressCode: Progress codes for DPP (Easy Connect) */ diff --git a/wifi/supplicant/1.2/vts/functional/supplicant_sta_iface_hidl_test.cpp b/wifi/supplicant/1.2/vts/functional/supplicant_sta_iface_hidl_test.cpp index 4425281b75..2ff7751fa8 100644 --- a/wifi/supplicant/1.2/vts/functional/supplicant_sta_iface_hidl_test.cpp +++ b/wifi/supplicant/1.2/vts/functional/supplicant_sta_iface_hidl_test.cpp @@ -40,7 +40,6 @@ using ::android::hardware::wifi::supplicant::V1_2::DppAkm; using ::android::hardware::wifi::supplicant::V1_2::DppFailureCode; using ::android::hardware::wifi::supplicant::V1_2::DppNetRole; using ::android::hardware::wifi::supplicant::V1_2::DppProgressCode; -using ::android::hardware::wifi::supplicant::V1_2::DppSuccessCode; using ::android::hardware::wifi::supplicant::V1_2::ISupplicantStaIface; using ::android::hardware::wifi::supplicant::V1_2::ISupplicantStaIfaceCallback; using ::android::hardware::wifi::supplicant::V1_2::ISupplicantStaNetwork; @@ -64,7 +63,7 @@ class SupplicantStaIfaceHidlTest : public ::testing::VtsHalHidlTargetTestBase { ANY_CALLBACK = -2, INVALID = -1, - EVENT_SUCCESS = 0, + EVENT_SUCCESS_CONFIG_SENT = 0, EVENT_SUCCESS_CONFIG_RECEIVED, EVENT_PROGRESS, EVENT_FAILURE, @@ -202,9 +201,7 @@ class IfaceCallback : public ISupplicantStaIfaceCallback { DppAkm /* securityAkm */) override { return Void(); } - Return onDppSuccess(DppSuccessCode /* code */) override { - return Void(); - } + Return onDppSuccessConfigSent() override { return Void(); } Return onDppProgress(DppProgressCode /* code */) override { return Void(); } @@ -226,10 +223,10 @@ class IfaceDppCallback : public IfaceCallback { parent_.notify(); return Void(); } - Return onDppSuccess(DppSuccessCode code) override { - parent_.code = (uint32_t)code; - parent_.dppCallbackType = - SupplicantStaIfaceHidlTest::DppCallbackType::EVENT_SUCCESS; + Return onDppSuccessConfigSent() override { + parent_.code = 0; + parent_.dppCallbackType = SupplicantStaIfaceHidlTest::DppCallbackType:: + EVENT_SUCCESS_CONFIG_SENT; parent_.notify(); return Void(); } From ed682336975e3899709ecebcdceda3d0f2d2a0dd Mon Sep 17 00:00:00 2001 From: Michael Butler Date: Thu, 7 Feb 2019 13:22:30 -0800 Subject: [PATCH 487/718] Add presubmit tests to NNAPI -- hardware/interfaces/neuralnetworks This CL creates a new suite of tests to enable presubmit tests: * PresubmitHalNeuralnetworksV1_0TargetTest * PresubmitHalNeuralnetworksV1_1TargetTest * PresubmitHalNeuralnetworksV1_2TargetTest These tests are the same as the VTS tests, with the exception that they will skip running all tests (but still pass) if the service cannot be found and its name starts with "service-". This change does not affect the existing NNAPI VTS tests. Test: mma Test: atest Bug: 124040554 Change-Id: I36a38b66b21fd51d0ca381bb4e05a39266dd353f --- neuralnetworks/1.0/vts/functional/Android.bp | 14 +++++++++- .../vts/functional/VtsHalNeuralnetworks.cpp | 12 +++++++- neuralnetworks/1.1/vts/functional/Android.bp | 14 ++++++++-- .../vts/functional/VtsHalNeuralnetworks.cpp | 12 +++++++- neuralnetworks/1.2/vts/functional/Android.bp | 16 +++++++++-- .../vts/functional/VtsHalNeuralnetworks.cpp | 12 +++++++- neuralnetworks/TEST_MAPPING | 28 +++++++++++++++++++ 7 files changed, 99 insertions(+), 9 deletions(-) create mode 100644 neuralnetworks/TEST_MAPPING diff --git a/neuralnetworks/1.0/vts/functional/Android.bp b/neuralnetworks/1.0/vts/functional/Android.bp index 52d63286b7..9057695e92 100644 --- a/neuralnetworks/1.0/vts/functional/Android.bp +++ b/neuralnetworks/1.0/vts/functional/Android.bp @@ -80,6 +80,7 @@ cc_defaults { }, }, }, + test_suites: ["general-tests"], } cc_test { @@ -89,5 +90,16 @@ cc_test { "BasicTests.cpp", "GeneratedTests.cpp", ], - test_suites: ["general-tests"], +} + +cc_test { + name: "PresubmitHalNeuralnetworksV1_0TargetTest", + defaults: ["VtsHalNeuralNetworksTargetTestDefaults"], + srcs: [ + "BasicTests.cpp", + "GeneratedTests.cpp", + ], + cflags: [ + "-DPRESUBMIT_NOT_VTS", + ], } diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp index 9ebc0aac47..88830574da 100644 --- a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp +++ b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp @@ -49,7 +49,17 @@ NeuralnetworksHidlTest::~NeuralnetworksHidlTest() {} void NeuralnetworksHidlTest::SetUp() { ::testing::VtsHalHidlTargetTestBase::SetUp(); device = ::testing::VtsHalHidlTargetTestBase::getService( - NeuralnetworksHidlEnvironment::getInstance()); + NeuralnetworksHidlEnvironment::getInstance()); + +#ifdef PRESUBMIT_NOT_VTS + const std::string name = + NeuralnetworksHidlEnvironment::getInstance()->getServiceName(); + const std::string sampleDriver = "sample-"; + if (device == nullptr && name.substr(0, sampleDriver.size()) == sampleDriver) { + GTEST_SKIP(); + } +#endif // PRESUBMIT_NOT_VTS + ASSERT_NE(nullptr, device.get()); } diff --git a/neuralnetworks/1.1/vts/functional/Android.bp b/neuralnetworks/1.1/vts/functional/Android.bp index 3f0c2561b0..4fbeac978d 100644 --- a/neuralnetworks/1.1/vts/functional/Android.bp +++ b/neuralnetworks/1.1/vts/functional/Android.bp @@ -21,7 +21,6 @@ cc_test { srcs: [ "GeneratedTestsV1_0.cpp", ], - test_suites: ["general-tests"], } // Tests for V1_1 models. @@ -32,5 +31,16 @@ cc_test { "BasicTests.cpp", "GeneratedTests.cpp", ], - test_suites: ["general-tests"], +} + +cc_test { + name: "PresubmitHalNeuralnetworksV1_1TargetTest", + defaults: ["VtsHalNeuralNetworksTargetTestDefaults"], + srcs: [ + "BasicTests.cpp", + "GeneratedTests.cpp", + ], + cflags: [ + "-DPRESUBMIT_NOT_VTS", + ], } diff --git a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp index 4165953df2..224a51d149 100644 --- a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp +++ b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp @@ -49,7 +49,17 @@ NeuralnetworksHidlTest::~NeuralnetworksHidlTest() {} void NeuralnetworksHidlTest::SetUp() { ::testing::VtsHalHidlTargetTestBase::SetUp(); device = ::testing::VtsHalHidlTargetTestBase::getService( - NeuralnetworksHidlEnvironment::getInstance()); + NeuralnetworksHidlEnvironment::getInstance()); + +#ifdef PRESUBMIT_NOT_VTS + const std::string name = + NeuralnetworksHidlEnvironment::getInstance()->getServiceName(); + const std::string sampleDriver = "sample-"; + if (device == nullptr && name.substr(0, sampleDriver.size()) == sampleDriver) { + GTEST_SKIP(); + } +#endif // PRESUBMIT_NOT_VTS + ASSERT_NE(nullptr, device.get()); } diff --git a/neuralnetworks/1.2/vts/functional/Android.bp b/neuralnetworks/1.2/vts/functional/Android.bp index 510a0d5b3c..891b414480 100644 --- a/neuralnetworks/1.2/vts/functional/Android.bp +++ b/neuralnetworks/1.2/vts/functional/Android.bp @@ -24,7 +24,6 @@ cc_test { cflags: [ "-DNN_TEST_DYNAMIC_OUTPUT_SHAPE" ], - test_suites: ["general-tests"], } // Tests for V1_1 models using the V1_2 HAL. @@ -37,7 +36,6 @@ cc_test { cflags: [ "-DNN_TEST_DYNAMIC_OUTPUT_SHAPE" ], - test_suites: ["general-tests"], } // Tests for V1_2 models. @@ -52,5 +50,17 @@ cc_test { cflags: [ "-DNN_TEST_DYNAMIC_OUTPUT_SHAPE" ], - test_suites: ["general-tests"], +} + +cc_test { + name: "PresubmitHalNeuralnetworksV1_2TargetTest", + defaults: ["VtsHalNeuralNetworksTargetTestDefaults"], + srcs: [ + "BasicTests.cpp", + "GeneratedTests.cpp", + ], + cflags: [ + "-DNN_TEST_DYNAMIC_OUTPUT_SHAPE", + "-DPRESUBMIT_NOT_VTS", + ], } diff --git a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp index 34c73ef05d..4728c28e87 100644 --- a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp +++ b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp @@ -49,7 +49,17 @@ NeuralnetworksHidlTest::~NeuralnetworksHidlTest() {} void NeuralnetworksHidlTest::SetUp() { ::testing::VtsHalHidlTargetTestBase::SetUp(); device = ::testing::VtsHalHidlTargetTestBase::getService( - NeuralnetworksHidlEnvironment::getInstance()); + NeuralnetworksHidlEnvironment::getInstance()); + +#ifdef PRESUBMIT_NOT_VTS + const std::string name = + NeuralnetworksHidlEnvironment::getInstance()->getServiceName(); + const std::string sampleDriver = "sample-"; + if (device == nullptr && name.substr(0, sampleDriver.size()) == sampleDriver) { + GTEST_SKIP(); + } +#endif // PRESUBMIT_NOT_VTS + ASSERT_NE(nullptr, device.get()); } diff --git a/neuralnetworks/TEST_MAPPING b/neuralnetworks/TEST_MAPPING new file mode 100644 index 0000000000..50b6c19124 --- /dev/null +++ b/neuralnetworks/TEST_MAPPING @@ -0,0 +1,28 @@ +{ + "presubmit": [ + { + "name": "PresubmitHalNeuralnetworksV1_0TargetTest", + "options": [ + { + "native-test-flag": "--hal_service_instance=android.hardware.neuralnetworks@1.0::IDevice/sample-all" + } + ] + }, + { + "name": "PresubmitHalNeuralnetworksV1_1TargetTest", + "options": [ + { + "native-test-flag": "--hal_service_instance=android.hardware.neuralnetworks@1.1::IDevice/sample-all" + } + ] + }, + { + "name": "PresubmitHalNeuralnetworksV1_2TargetTest", + "options": [ + { + "native-test-flag": "--hal_service_instance=android.hardware.neuralnetworks@1.2::IDevice/sample-all" + } + ] + } + ] +} From bf26a9e3d7cfb904075c2d6ac1d622ab89b5bc11 Mon Sep 17 00:00:00 2001 From: Lev Proleev Date: Wed, 20 Feb 2019 12:49:14 +0000 Subject: [PATCH 488/718] Adds TENSOR_QUANT8_SYMM support to test infrastructure This is needed to be able to test DEQUANTIZE after adding TENSOR_QUANT8_SYMM support. Test: NeuralNetworksTest_static Test: VtsHalNeuralnetworksV1_2TargetTest Change-Id: Iba9b286df70919d7b67cd77c91e625a044bd686c --- neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp index 0724c09ece..7eea7fcedc 100644 --- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp +++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp @@ -72,7 +72,8 @@ void copy_back(MixedTyped* dst, const std::vector& ra, char* sr copy_back_(&dst->bool8Operands, ra, src); copy_back_(&dst->quant8ChannelOperands, ra, src); copy_back_(&dst->quant16AsymmOperands, ra, src); - static_assert(8 == MixedTyped::kNumTypes, + copy_back_(&dst->quant8SymmOperands, ra, src); + static_assert(9 == MixedTyped::kNumTypes, "Number of types in MixedTyped changed, but copy_back function wasn't updated"); } From 84cf5c9fc32839e2defab90a59a604327b35f231 Mon Sep 17 00:00:00 2001 From: Wei Wang Date: Wed, 20 Feb 2019 11:39:14 -0800 Subject: [PATCH 489/718] Improve the comments of Thermal HAL 2.0 API Make sure (un)register API failed with nullptr Test: Build Test: VtsHalThermalV2_0TargetTest Change-Id: I42a87fde85a38f77faa4d07f29ed3a78501a0dca --- current.txt | 2 +- thermal/2.0/IThermal.hal | 22 ++++++++++--------- thermal/2.0/default/Thermal.cpp | 20 +++++++++++++++-- .../VtsHalThermalV2_0TargetTest.cpp | 16 +++++++++++--- 4 files changed, 44 insertions(+), 16 deletions(-) diff --git a/current.txt b/current.txt index a128669e17..be71351ac5 100644 --- a/current.txt +++ b/current.txt @@ -534,7 +534,7 @@ b53ac9d61c24efb16a2d63a861cef20680f6d57adb244a03b9778c675550628b android.hardwar ae5faa38538a9f50eb71eb7f9b998271124d2c64b761cb11c4d820c7732b4ddc android.hardware.sensors@2.0::ISensorsCallback 3a98242a57d0820dacaca0f7db52bec433eae1f21c498763c6f1ece611c3967b android.hardware.sensors@2.0::types ce4b98211959449361146d4b1e5554dc841ceb4d4577154d7b2fb6d1eb504f76 android.hardware.soundtrigger@2.2::ISoundTriggerHw -5cc81d517c5f3fef12e719b0f5683c7c99e3e8895fcb80e6f6653b454f463320 android.hardware.thermal@2.0::IThermal +bd88b48639cae30982021024e22371076c76faa8466e38ca598529452b618eae android.hardware.thermal@2.0::IThermal cc4d2ef36da776c475ad054f0f3416d8a8865def9d9e2129f10074b28e36d203 android.hardware.thermal@2.0::IThermalChangedCallback b47f90302595874dfddb19bd05a054727bf18b3a930bc810ea14957b859ae8bf android.hardware.thermal@2.0::types 61bc302e7c974c59b25898c585c6e9685e8a81021b1bed3eedf5224198f2785a android.hardware.usb@1.2::IUsb diff --git a/thermal/2.0/IThermal.hal b/thermal/2.0/IThermal.hal index f890694d2c..3ea4590991 100644 --- a/thermal/2.0/IThermal.hal +++ b/thermal/2.0/IThermal.hal @@ -56,22 +56,24 @@ interface IThermal extends @1.0::IThermal { * they go offline, if these devices exist on boot. The method * always returns and never removes such temperatures. The thresholds * are returned as static values and must not change across calls. The actual - * throttling state is determined in driver and HAL and must not be simply - * compared with these thresholds. To get accurate throttling status, use - * getCurrentTemperatures or registerThermalChangedCallback and listen. + * throttling state is determined in device thermal mitigation policy/agorithm + * which might not be simple thresholds so these values Thermal HAL provided + * may not be accurate to detemin the throttling status. To get accurate + * throttling status, use getCurrentTemperatures or registerThermalChangedCallback + * and listen to the callback. */ getTemperatureThresholds(bool filterType, TemperatureType type) generates (ThermalStatus status, vec temperatureThresholds); /** * Register an IThermalChangedCallback, used by the Thermal HAL - * to send thermal events when thermal mitigation status changed. + * to receive thermal events when thermal mitigation status changed. * Multiple registrations with different IThermalChangedCallback must be allowed. * Multiple registrations with same IThermalChangedCallback is not allowed, client * should unregister the given IThermalChangedCallback first. * - * @param callback the IThermalChangedCallback to use for sending - * thermal events (cannot be nullptr). + * @param callback the IThermalChangedCallback to use for receiving + * thermal events (nullptr callback will lead to failure with status code FAILURE). * @param filterType if filter for given sensor type. * @param type the type to be filtered. * @@ -84,11 +86,11 @@ interface IThermal extends @1.0::IThermal { generates (ThermalStatus status); /** - * Register an IThermalChangedCallback, used by the Thermal HAL - * to send thermal events when thermal mitigation status changed. + * Unregister an IThermalChangedCallback, used by the Thermal HAL + * to receive thermal events when thermal mitigation status changed. * - * @param callback the IThermalChangedCallback to use for sending - * thermal events, or nullptr to set no callback. + * @param callback the IThermalChangedCallback used for receiving + * thermal events (nullptr callback will lead to failure with status code FAILURE). * * @return status Status of the operation. If status code is FAILURE, * the status.debugMessage must be populated with a human-readable error message. diff --git a/thermal/2.0/default/Thermal.cpp b/thermal/2.0/default/Thermal.cpp index 442af61fa5..0ef4b63324 100644 --- a/thermal/2.0/default/Thermal.cpp +++ b/thermal/2.0/default/Thermal.cpp @@ -155,7 +155,15 @@ Return Thermal::registerThermalChangedCallback(const sp _lock(thermal_callback_mutex_); if (std::any_of(callbacks_.begin(), callbacks_.end(), [&](const CallbackSetting& c) { return interfacesEqual(c.callback, callback); @@ -175,7 +183,15 @@ Return Thermal::registerThermalChangedCallback(const sp Thermal::unregisterThermalChangedCallback( const sp& callback, unregisterThermalChangedCallback_cb _hidl_cb) { ThermalStatus status; - status.code = ThermalStatusCode::SUCCESS; + if (callback == nullptr) { + status.code = ThermalStatusCode::FAILURE; + status.debugMessage = "Invalid nullptr callback"; + LOG(ERROR) << status.debugMessage; + _hidl_cb(status); + return Void(); + } else { + status.code = ThermalStatusCode::SUCCESS; + } bool removed = false; std::lock_guard _lock(thermal_callback_mutex_); callbacks_.erase( diff --git a/thermal/2.0/vts/functional/VtsHalThermalV2_0TargetTest.cpp b/thermal/2.0/vts/functional/VtsHalThermalV2_0TargetTest.cpp index 3893014e20..cc2f3df612 100644 --- a/thermal/2.0/vts/functional/VtsHalThermalV2_0TargetTest.cpp +++ b/thermal/2.0/vts/functional/VtsHalThermalV2_0TargetTest.cpp @@ -132,8 +132,13 @@ TEST_F(ThermalHidlTest, NotifyThrottlingTest) { TEST_F(ThermalHidlTest, RegisterThermalChangedCallbackTest) { // Expect to fail with same callback auto ret = mThermal->registerThermalChangedCallback( - mThermalCallback, false, TemperatureType::SKIN, - [](ThermalStatus status) { EXPECT_NE(ThermalStatusCode::SUCCESS, status.code); }); + mThermalCallback, false, TemperatureType::SKIN, + [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::FAILURE, status.code); }); + ASSERT_TRUE(ret.isOk()); + // Expect to fail with null callback + ret = mThermal->registerThermalChangedCallback( + nullptr, false, TemperatureType::SKIN, + [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::FAILURE, status.code); }); ASSERT_TRUE(ret.isOk()); sp localThermalCallback = new (std::nothrow) ThermalCallback(); // Expect to succeed with different callback @@ -141,11 +146,16 @@ TEST_F(ThermalHidlTest, RegisterThermalChangedCallbackTest) { localThermalCallback, false, TemperatureType::SKIN, [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code); }); ASSERT_TRUE(ret.isOk()); - // Remove the local callback. + // Remove the local callback ret = mThermal->unregisterThermalChangedCallback( localThermalCallback, [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code); }); ASSERT_TRUE(ret.isOk()); + // Expect to fail with null callback + ret = mThermal->unregisterThermalChangedCallback(nullptr, [](ThermalStatus status) { + EXPECT_EQ(ThermalStatusCode::FAILURE, status.code); + }); + ASSERT_TRUE(ret.isOk()); } // Test Thermal->unregisterThermalChangedCallback. From 2f06e17122e5f9c9a8a27043228abd6ff5c811f4 Mon Sep 17 00:00:00 2001 From: Shuzhen Wang Date: Wed, 20 Feb 2019 15:34:15 -0800 Subject: [PATCH 490/718] Camera: Document bufferSize for JPEG_APP_SEGMENTS stream Doc update to clarify that @3.4::Stream::bufferSize is updated by camera framework. Test: Build Bug: 124999074 Change-Id: I818f75eabd613cc5f6d9b7e73b2b1a894b511afe --- camera/device/3.5/types.hal | 4 +++- current.txt | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/camera/device/3.5/types.hal b/camera/device/3.5/types.hal index e3c235018f..f98c60355e 100644 --- a/camera/device/3.5/types.hal +++ b/camera/device/3.5/types.hal @@ -142,7 +142,9 @@ struct BufferRequest { * To capture a JPEG APP segments blob, a stream is created using the pixel format * HAL_PIXEL_FORMAT_BLOB and dataspace HAL_DATASPACE_JPEG_APP_SEGMENTS. The buffer * size for the stream is calculated by the framework, based on the static - * metadata field android.heic.maxAppSegmentsCount. + * metadata field android.heic.maxAppSegmentsCount, and is assigned to both + * @3.2::Stream::width and @3.4::Stream::bufferSize. Camera framework sets + * @3.2::Stream::height to 1. * * Similar to JPEG image, the JPEG APP segment images can be of variable size, * so the HAL needs to include the final size of all APP segments using this diff --git a/current.txt b/current.txt index a128669e17..b47bc34b5d 100644 --- a/current.txt +++ b/current.txt @@ -444,7 +444,7 @@ f7431f3e3e4e3387fc6f27a6cf423eddcd824a395dc4349d302c995ab44a9895 android.hardwar 09ab9b24994429d9bb32a3fb420b6f6be3e47eb655139a2c08c4e80d3f33ff95 android.hardware.camera.device@3.5::ICameraDevice 06237de53c42890029e3f8fe7d1480d078469c0d07608e51c37b4d485d342992 android.hardware.camera.device@3.5::ICameraDeviceCallback 08c68b196e2fc4e5ba67ba0d0917bde828a87cbe2cffec19d04733972da9eb49 android.hardware.camera.device@3.5::ICameraDeviceSession -acaba39216973e58949f50978762bcda1c29f5f7e0bca3e08db21f0767356130 android.hardware.camera.device@3.5::types +a848f7cb3cb3d080cf175bf08412322bfddb535168253796cdf777afdbf05b38 android.hardware.camera.device@3.5::types 74ec7732fdacb22292c907b49f8f933510851ea1b3ed195c4dcdff35a20387f5 android.hardware.camera.metadata@3.4::types 0fb39a7809ad1c52b3efbbed5ef4749b06c2a4f1f19cdc3efa2e3d9b28f1205c android.hardware.camera.provider@2.5::ICameraProvider f5777403d65135a5407723671bc7a864cdca83aea13ee3ce2894b95e6588ca3a android.hardware.camera.provider@2.5::types From 22ab6f2febfc39f26d1b2866a064a5189c69bdb2 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Fri, 22 Feb 2019 10:24:42 -0800 Subject: [PATCH 491/718] Fix audio VTS build Update AudioPrimaryHidlHalTest to reflect changes in AudioPolicyConfig class. Test: make Change-Id: Iab5cb85ff8e79fb5387d5e8ad2f85748342e80fa --- .../core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h index a22cc1cfc5..7f8b6a0646 100644 --- a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h +++ b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h @@ -142,14 +142,13 @@ struct PolicyConfigData { android::DeviceVector availableOutputDevices; android::DeviceVector availableInputDevices; sp defaultOutputDevice; - android::VolumeCurvesCollection volumes; }; class PolicyConfig : private PolicyConfigData, public AudioPolicyConfig { public: PolicyConfig() : AudioPolicyConfig(hwModules, availableOutputDevices, availableInputDevices, - defaultOutputDevice, &volumes) { + defaultOutputDevice) { for (const char* location : kConfigLocations) { std::string path = std::string(location) + '/' + kConfigFileName; if (access(path.c_str(), F_OK) == 0) { From e4c310fdc93df830c21ca4daabaa8684f8e3cabd Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Thu, 21 Feb 2019 15:38:26 -0600 Subject: [PATCH 492/718] Document that video frames rotate We recently changed the behaviour in InputReader to adjust the video frame data based on the current orientation. Update the HAL documentation to reflect that. Also, rearrange the order of width and height, because it is more natural to have the format of num of rows x num of columns. So currently, it is reversed, and not as natural. More information about this is in ag/6414079. Bug: 123241238 Test: none Change-Id: I69f184794bd7684e5c0981a6db66542ab914eff2 --- current.txt | 2 +- input/common/1.0/types.hal | 35 ++++++++++++++++++++++++++--------- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/current.txt b/current.txt index be71351ac5..c288a06b13 100644 --- a/current.txt +++ b/current.txt @@ -487,7 +487,7 @@ c3f831a66d5815baf74f5b82fe79cf099542ddae4dfab3f388e1d41828e794fc android.hardwar dd1ec219f5d2e2b33c6c0bcb92e63bbedb36f7c716413462848f6b6ae74fc864 android.hardware.health.storage@1.0::IStorage 2b4a14661e6a38617b7dd0c6ebb66a56a90e564674ac7697a14cb8a0cab92b2f android.hardware.health.storage@1.0::types 30006fde4cb1f255f2530208728bff692100411b20af5b66fa31a9196d51f00b android.hardware.input.classifier@1.0::IInputClassifier -97d8757bb05eb23d6a218bda374e095dfbb064c47714e2f859963c11f433e822 android.hardware.input.common@1.0::types +0300c7667030da36c3de585f176ce18ff4b0d2615446d4930f331097378c06ef android.hardware.input.common@1.0::types 24ae089981d58bc4cc74d75a6055bf357338ae6744ce1b467c5b4a9c470aba6d android.hardware.media.bufferpool@2.0::IAccessor 897f45ee7db24ef227dea83ca3e4de72d53ff6bb7adc7983c90a650a1a6ff576 android.hardware.media.bufferpool@2.0::IClientManager aee53b2865b4f7939fb3df6fae758d9750c14f93dd454b479fc74aa7978fda4f android.hardware.media.bufferpool@2.0::IConnection diff --git a/input/common/1.0/types.hal b/input/common/1.0/types.hal index 1a07f3b76d..9ad368b3b6 100644 --- a/input/common/1.0/types.hal +++ b/input/common/1.0/types.hal @@ -685,20 +685,20 @@ enum Flag : int32_t { * Touch heatmap. * * The array is a 2-D row-major matrix with dimensions (height, width). - * The heatmap data does not rotate when device orientation changes. + * The heatmap data is rotated when device orientation changes. * * Example: * * If the data in the array is: * data[i] = i for i in 0 .. 59, - * then it can be represented as follows: + * then it can be represented as a 10 x 6 matrix: * - * <-- width -- > + * <-- width --> * 0 1 2 3 4 5 ^ * 6 7 8 9 10 11 | - * 12 12 14 15 16 17 | - * 18 ... 23 | height - * 24 ... 29 | + * 12 13 14 15 16 17 | + * 18 ... 23 | + * 24 ... 29 | height * 30 ... 35 | * 36 ... 41 | * 42 ... 47 | @@ -708,16 +708,33 @@ enum Flag : int32_t { * Looking at the device in standard portrait orientation, * the element "0" is the top left of the screen, * "5" is at the top right, and "59" is the bottom right. - * Here width=6, and height=10. + * Here height=10 and width=6. + * + * If the screen orientation changes to landscape (a 90 degree orientation + * change), the frame's dimensions will become 6 x 10 + * and the data will look as follows: + * 54 48 42 36 30 24 18 12 6 0 ^ + * ... 13 7 1 | + * ... 14 8 2 | height + * ... 15 9 3 | + * ... 16 10 4 | + * 59 53 47 41 35 29 23 17 11 5 v + * <-- width --> + * + * Here the element "0" is at the physical top left of the unrotated screen. + * + * Since the coordinates of a MotionEvent are also adjusted based on the + * orientation, the rotation of the video frame data ensures that + * the axes for MotionEvent and VideoFrame data are consistent. */ struct VideoFrame { /** * Video frame data. - * Size of the data is width * height. + * Size of the data is height * width. */ vec data; - uint32_t width; uint32_t height; + uint32_t width; /** * Time at which the frame was collected, in nanoseconds. * Measured with the same clock that is used to populate MotionEvent times. From fa02144f8d501c55fc85ca37f4cd283f8734b86b Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Fri, 22 Feb 2019 14:28:26 -0800 Subject: [PATCH 493/718] audio: Add support for dumping info from effect HAL modules The implementation uses IBase::debug() method which can write debugging info into the provided file descriptor (same model as used for devices and streams). Bug: 69939533 Test: adb shell dumpsys media.audio_flinger Change-Id: I7876fd43a7066c0f081ea2ca0b3b4b37bbdf8e6c --- .../all-versions/default/AcousticEchoCancelerEffect.cpp | 5 +++++ .../all-versions/default/AcousticEchoCancelerEffect.h | 1 + .../all-versions/default/AutomaticGainControlEffect.cpp | 5 +++++ .../all-versions/default/AutomaticGainControlEffect.h | 1 + audio/effect/all-versions/default/BassBoostEffect.cpp | 4 ++++ audio/effect/all-versions/default/BassBoostEffect.h | 1 + audio/effect/all-versions/default/DownmixEffect.cpp | 4 ++++ audio/effect/all-versions/default/DownmixEffect.h | 1 + audio/effect/all-versions/default/Effect.cpp | 8 ++++++++ audio/effect/all-versions/default/Effect.h | 1 + .../all-versions/default/EnvironmentalReverbEffect.cpp | 5 +++++ .../all-versions/default/EnvironmentalReverbEffect.h | 1 + audio/effect/all-versions/default/EqualizerEffect.cpp | 4 ++++ audio/effect/all-versions/default/EqualizerEffect.h | 1 + .../all-versions/default/LoudnessEnhancerEffect.cpp | 5 +++++ .../effect/all-versions/default/LoudnessEnhancerEffect.h | 1 + .../all-versions/default/NoiseSuppressionEffect.cpp | 5 +++++ .../effect/all-versions/default/NoiseSuppressionEffect.h | 1 + audio/effect/all-versions/default/PresetReverbEffect.cpp | 5 +++++ audio/effect/all-versions/default/PresetReverbEffect.h | 1 + audio/effect/all-versions/default/VirtualizerEffect.cpp | 4 ++++ audio/effect/all-versions/default/VirtualizerEffect.h | 1 + audio/effect/all-versions/default/VisualizerEffect.cpp | 4 ++++ audio/effect/all-versions/default/VisualizerEffect.h | 1 + 24 files changed, 70 insertions(+) diff --git a/audio/effect/all-versions/default/AcousticEchoCancelerEffect.cpp b/audio/effect/all-versions/default/AcousticEchoCancelerEffect.cpp index 0b60622c05..137ea246f6 100644 --- a/audio/effect/all-versions/default/AcousticEchoCancelerEffect.cpp +++ b/audio/effect/all-versions/default/AcousticEchoCancelerEffect.cpp @@ -165,6 +165,11 @@ Return AcousticEchoCancelerEffect::close() { return mEffect->close(); } +Return AcousticEchoCancelerEffect::debug(const hidl_handle& fd, + const hidl_vec& options) { + return mEffect->debug(fd, options); +} + // Methods from ::android::hardware::audio::effect::CPP_VERSION::IAcousticEchoCancelerEffect // follow. Return AcousticEchoCancelerEffect::setEchoDelay(uint32_t echoDelayMs) { diff --git a/audio/effect/all-versions/default/AcousticEchoCancelerEffect.h b/audio/effect/all-versions/default/AcousticEchoCancelerEffect.h index c18f88b276..971f64de80 100644 --- a/audio/effect/all-versions/default/AcousticEchoCancelerEffect.h +++ b/audio/effect/all-versions/default/AcousticEchoCancelerEffect.h @@ -88,6 +88,7 @@ struct AcousticEchoCancelerEffect : public IAcousticEchoCancelerEffect { Return setCurrentConfigForFeature(uint32_t featureId, const hidl_vec& configData) override; Return close() override; + Return debug(const hidl_handle& fd, const hidl_vec& options) override; // Methods from // ::android::hardware::audio::effect::CPP_VERSION::IAcousticEchoCancelerEffect follow. diff --git a/audio/effect/all-versions/default/AutomaticGainControlEffect.cpp b/audio/effect/all-versions/default/AutomaticGainControlEffect.cpp index 651dd1b228..655a4cd0b1 100644 --- a/audio/effect/all-versions/default/AutomaticGainControlEffect.cpp +++ b/audio/effect/all-versions/default/AutomaticGainControlEffect.cpp @@ -178,6 +178,11 @@ Return AutomaticGainControlEffect::close() { return mEffect->close(); } +Return AutomaticGainControlEffect::debug(const hidl_handle& fd, + const hidl_vec& options) { + return mEffect->debug(fd, options); +} + // Methods from ::android::hardware::audio::effect::CPP_VERSION::IAutomaticGainControlEffect // follow. Return AutomaticGainControlEffect::setTargetLevel(int16_t targetLevelMb) { diff --git a/audio/effect/all-versions/default/AutomaticGainControlEffect.h b/audio/effect/all-versions/default/AutomaticGainControlEffect.h index a281b1ddcd..67e260aa20 100644 --- a/audio/effect/all-versions/default/AutomaticGainControlEffect.h +++ b/audio/effect/all-versions/default/AutomaticGainControlEffect.h @@ -90,6 +90,7 @@ struct AutomaticGainControlEffect : public IAutomaticGainControlEffect { Return setCurrentConfigForFeature(uint32_t featureId, const hidl_vec& configData) override; Return close() override; + Return debug(const hidl_handle& fd, const hidl_vec& options) override; // Methods from // ::android::hardware::audio::effect::CPP_VERSION::IAutomaticGainControlEffect follow. diff --git a/audio/effect/all-versions/default/BassBoostEffect.cpp b/audio/effect/all-versions/default/BassBoostEffect.cpp index 6f7763db8e..04fd48615a 100644 --- a/audio/effect/all-versions/default/BassBoostEffect.cpp +++ b/audio/effect/all-versions/default/BassBoostEffect.cpp @@ -161,6 +161,10 @@ Return BassBoostEffect::close() { return mEffect->close(); } +Return BassBoostEffect::debug(const hidl_handle& fd, const hidl_vec& options) { + return mEffect->debug(fd, options); +} + // Methods from ::android::hardware::audio::effect::CPP_VERSION::IBassBoostEffect follow. Return BassBoostEffect::isStrengthSupported(isStrengthSupported_cb _hidl_cb) { return mEffect->getIntegerParam(BASSBOOST_PARAM_STRENGTH_SUPPORTED, _hidl_cb); diff --git a/audio/effect/all-versions/default/BassBoostEffect.h b/audio/effect/all-versions/default/BassBoostEffect.h index a184ac2cc8..b89bb2212f 100644 --- a/audio/effect/all-versions/default/BassBoostEffect.h +++ b/audio/effect/all-versions/default/BassBoostEffect.h @@ -90,6 +90,7 @@ struct BassBoostEffect : public IBassBoostEffect { Return setCurrentConfigForFeature(uint32_t featureId, const hidl_vec& configData) override; Return close() override; + Return debug(const hidl_handle& fd, const hidl_vec& options) override; // Methods from ::android::hardware::audio::effect::CPP_VERSION::IBassBoostEffect follow. Return isStrengthSupported(isStrengthSupported_cb _hidl_cb) override; diff --git a/audio/effect/all-versions/default/DownmixEffect.cpp b/audio/effect/all-versions/default/DownmixEffect.cpp index 94da70e0df..c001a5f4dc 100644 --- a/audio/effect/all-versions/default/DownmixEffect.cpp +++ b/audio/effect/all-versions/default/DownmixEffect.cpp @@ -161,6 +161,10 @@ Return DownmixEffect::close() { return mEffect->close(); } +Return DownmixEffect::debug(const hidl_handle& fd, const hidl_vec& options) { + return mEffect->debug(fd, options); +} + // Methods from ::android::hardware::audio::effect::CPP_VERSION::IDownmixEffect follow. Return DownmixEffect::setType(IDownmixEffect::Type preset) { return mEffect->setParam(DOWNMIX_PARAM_TYPE, static_cast(preset)); diff --git a/audio/effect/all-versions/default/DownmixEffect.h b/audio/effect/all-versions/default/DownmixEffect.h index 6d34c28dd2..40e462ea41 100644 --- a/audio/effect/all-versions/default/DownmixEffect.h +++ b/audio/effect/all-versions/default/DownmixEffect.h @@ -88,6 +88,7 @@ struct DownmixEffect : public IDownmixEffect { Return setCurrentConfigForFeature(uint32_t featureId, const hidl_vec& configData) override; Return close() override; + Return debug(const hidl_handle& fd, const hidl_vec& options) override; // Methods from ::android::hardware::audio::effect::CPP_VERSION::IDownmixEffect follow. Return setType(IDownmixEffect::Type preset) override; diff --git a/audio/effect/all-versions/default/Effect.cpp b/audio/effect/all-versions/default/Effect.cpp index 84608b6065..3c0d8788ab 100644 --- a/audio/effect/all-versions/default/Effect.cpp +++ b/audio/effect/all-versions/default/Effect.cpp @@ -710,6 +710,14 @@ Return Effect::close() { return Result::OK; } +Return Effect::debug(const hidl_handle& fd, const hidl_vec& /* options */) { + if (fd.getNativeHandle() != nullptr && fd->numFds == 1) { + uint32_t cmdData = fd->data[0]; + (void)sendCommand(EFFECT_CMD_DUMP, "DUMP", sizeof(cmdData), &cmdData); + } + return Void(); +} + } // namespace implementation } // namespace CPP_VERSION } // namespace effect diff --git a/audio/effect/all-versions/default/Effect.h b/audio/effect/all-versions/default/Effect.h index 1a2b0393ad..3d99a0e42f 100644 --- a/audio/effect/all-versions/default/Effect.h +++ b/audio/effect/all-versions/default/Effect.h @@ -101,6 +101,7 @@ struct Effect : public IEffect { Return setCurrentConfigForFeature(uint32_t featureId, const hidl_vec& configData) override; Return close() override; + Return debug(const hidl_handle& fd, const hidl_vec& options) override; // Utility methods for extending interfaces. template diff --git a/audio/effect/all-versions/default/EnvironmentalReverbEffect.cpp b/audio/effect/all-versions/default/EnvironmentalReverbEffect.cpp index 1ade7b810b..78122d4b79 100644 --- a/audio/effect/all-versions/default/EnvironmentalReverbEffect.cpp +++ b/audio/effect/all-versions/default/EnvironmentalReverbEffect.cpp @@ -193,6 +193,11 @@ Return EnvironmentalReverbEffect::close() { return mEffect->close(); } +Return EnvironmentalReverbEffect::debug(const hidl_handle& fd, + const hidl_vec& options) { + return mEffect->debug(fd, options); +} + // Methods from ::android::hardware::audio::effect::CPP_VERSION::IEnvironmentalReverbEffect // follow. Return EnvironmentalReverbEffect::setBypass(bool bypass) { diff --git a/audio/effect/all-versions/default/EnvironmentalReverbEffect.h b/audio/effect/all-versions/default/EnvironmentalReverbEffect.h index d06c3fc77b..bb422d46bc 100644 --- a/audio/effect/all-versions/default/EnvironmentalReverbEffect.h +++ b/audio/effect/all-versions/default/EnvironmentalReverbEffect.h @@ -92,6 +92,7 @@ struct EnvironmentalReverbEffect : public IEnvironmentalReverbEffect { Return setCurrentConfigForFeature(uint32_t featureId, const hidl_vec& configData) override; Return close() override; + Return debug(const hidl_handle& fd, const hidl_vec& options) override; // Methods from // ::android::hardware::audio::effect::CPP_VERSION::IEnvironmentalReverbEffect follow. diff --git a/audio/effect/all-versions/default/EqualizerEffect.cpp b/audio/effect/all-versions/default/EqualizerEffect.cpp index f6177b79b4..1b983ec5eb 100644 --- a/audio/effect/all-versions/default/EqualizerEffect.cpp +++ b/audio/effect/all-versions/default/EqualizerEffect.cpp @@ -184,6 +184,10 @@ Return EqualizerEffect::close() { return mEffect->close(); } +Return EqualizerEffect::debug(const hidl_handle& fd, const hidl_vec& options) { + return mEffect->debug(fd, options); +} + // Methods from ::android::hardware::audio::effect::CPP_VERSION::IEqualizerEffect follow. Return EqualizerEffect::getNumBands(getNumBands_cb _hidl_cb) { return mEffect->getIntegerParam(EQ_PARAM_NUM_BANDS, _hidl_cb); diff --git a/audio/effect/all-versions/default/EqualizerEffect.h b/audio/effect/all-versions/default/EqualizerEffect.h index 318c0dbfd0..b1cbefd1f6 100644 --- a/audio/effect/all-versions/default/EqualizerEffect.h +++ b/audio/effect/all-versions/default/EqualizerEffect.h @@ -92,6 +92,7 @@ struct EqualizerEffect : public IEqualizerEffect { Return setCurrentConfigForFeature(uint32_t featureId, const hidl_vec& configData) override; Return close() override; + Return debug(const hidl_handle& fd, const hidl_vec& options) override; // Methods from ::android::hardware::audio::effect::CPP_VERSION::IEqualizerEffect follow. Return getNumBands(getNumBands_cb _hidl_cb) override; diff --git a/audio/effect/all-versions/default/LoudnessEnhancerEffect.cpp b/audio/effect/all-versions/default/LoudnessEnhancerEffect.cpp index 6918bdf533..ebd519766e 100644 --- a/audio/effect/all-versions/default/LoudnessEnhancerEffect.cpp +++ b/audio/effect/all-versions/default/LoudnessEnhancerEffect.cpp @@ -164,6 +164,11 @@ Return LoudnessEnhancerEffect::close() { return mEffect->close(); } +Return LoudnessEnhancerEffect::debug(const hidl_handle& fd, + const hidl_vec& options) { + return mEffect->debug(fd, options); +} + // Methods from ::android::hardware::audio::effect::CPP_VERSION::ILoudnessEnhancerEffect // follow. Return LoudnessEnhancerEffect::setTargetGain(int32_t targetGainMb) { diff --git a/audio/effect/all-versions/default/LoudnessEnhancerEffect.h b/audio/effect/all-versions/default/LoudnessEnhancerEffect.h index 06c521ca82..8baf12839d 100644 --- a/audio/effect/all-versions/default/LoudnessEnhancerEffect.h +++ b/audio/effect/all-versions/default/LoudnessEnhancerEffect.h @@ -88,6 +88,7 @@ struct LoudnessEnhancerEffect : public ILoudnessEnhancerEffect { Return setCurrentConfigForFeature(uint32_t featureId, const hidl_vec& configData) override; Return close() override; + Return debug(const hidl_handle& fd, const hidl_vec& options) override; // Methods from ::android::hardware::audio::effect::CPP_VERSION::ILoudnessEnhancerEffect // follow. diff --git a/audio/effect/all-versions/default/NoiseSuppressionEffect.cpp b/audio/effect/all-versions/default/NoiseSuppressionEffect.cpp index 4756719661..d01bbe5e94 100644 --- a/audio/effect/all-versions/default/NoiseSuppressionEffect.cpp +++ b/audio/effect/all-versions/default/NoiseSuppressionEffect.cpp @@ -173,6 +173,11 @@ Return NoiseSuppressionEffect::close() { return mEffect->close(); } +Return NoiseSuppressionEffect::debug(const hidl_handle& fd, + const hidl_vec& options) { + return mEffect->debug(fd, options); +} + // Methods from ::android::hardware::audio::effect::CPP_VERSION::INoiseSuppressionEffect // follow. Return NoiseSuppressionEffect::setSuppressionLevel(INoiseSuppressionEffect::Level level) { diff --git a/audio/effect/all-versions/default/NoiseSuppressionEffect.h b/audio/effect/all-versions/default/NoiseSuppressionEffect.h index f31ba3b923..c49bf7bd6c 100644 --- a/audio/effect/all-versions/default/NoiseSuppressionEffect.h +++ b/audio/effect/all-versions/default/NoiseSuppressionEffect.h @@ -90,6 +90,7 @@ struct NoiseSuppressionEffect : public INoiseSuppressionEffect { Return setCurrentConfigForFeature(uint32_t featureId, const hidl_vec& configData) override; Return close() override; + Return debug(const hidl_handle& fd, const hidl_vec& options) override; // Methods from ::android::hardware::audio::effect::CPP_VERSION::INoiseSuppressionEffect // follow. diff --git a/audio/effect/all-versions/default/PresetReverbEffect.cpp b/audio/effect/all-versions/default/PresetReverbEffect.cpp index 97723f5fbb..4a2a3a42a9 100644 --- a/audio/effect/all-versions/default/PresetReverbEffect.cpp +++ b/audio/effect/all-versions/default/PresetReverbEffect.cpp @@ -161,6 +161,11 @@ Return PresetReverbEffect::close() { return mEffect->close(); } +Return PresetReverbEffect::debug(const hidl_handle& fd, + const hidl_vec& options) { + return mEffect->debug(fd, options); +} + // Methods from ::android::hardware::audio::effect::CPP_VERSION::IPresetReverbEffect follow. Return PresetReverbEffect::setPreset(IPresetReverbEffect::Preset preset) { return mEffect->setParam(REVERB_PARAM_PRESET, static_cast(preset)); diff --git a/audio/effect/all-versions/default/PresetReverbEffect.h b/audio/effect/all-versions/default/PresetReverbEffect.h index 8971976825..58a6829a83 100644 --- a/audio/effect/all-versions/default/PresetReverbEffect.h +++ b/audio/effect/all-versions/default/PresetReverbEffect.h @@ -88,6 +88,7 @@ struct PresetReverbEffect : public IPresetReverbEffect { Return setCurrentConfigForFeature(uint32_t featureId, const hidl_vec& configData) override; Return close() override; + Return debug(const hidl_handle& fd, const hidl_vec& options) override; // Methods from ::android::hardware::audio::effect::CPP_VERSION::IPresetReverbEffect // follow. diff --git a/audio/effect/all-versions/default/VirtualizerEffect.cpp b/audio/effect/all-versions/default/VirtualizerEffect.cpp index 4d597c76e8..1b69a9033c 100644 --- a/audio/effect/all-versions/default/VirtualizerEffect.cpp +++ b/audio/effect/all-versions/default/VirtualizerEffect.cpp @@ -173,6 +173,10 @@ Return VirtualizerEffect::close() { return mEffect->close(); } +Return VirtualizerEffect::debug(const hidl_handle& fd, const hidl_vec& options) { + return mEffect->debug(fd, options); +} + // Methods from ::android::hardware::audio::effect::CPP_VERSION::IVirtualizerEffect follow. Return VirtualizerEffect::isStrengthSupported() { bool halSupported = false; diff --git a/audio/effect/all-versions/default/VirtualizerEffect.h b/audio/effect/all-versions/default/VirtualizerEffect.h index e7302f9f8b..c630b2e353 100644 --- a/audio/effect/all-versions/default/VirtualizerEffect.h +++ b/audio/effect/all-versions/default/VirtualizerEffect.h @@ -89,6 +89,7 @@ struct VirtualizerEffect : public IVirtualizerEffect { Return setCurrentConfigForFeature(uint32_t featureId, const hidl_vec& configData) override; Return close() override; + Return debug(const hidl_handle& fd, const hidl_vec& options) override; // Methods from ::android::hardware::audio::effect::CPP_VERSION::IVirtualizerEffect // follow. diff --git a/audio/effect/all-versions/default/VisualizerEffect.cpp b/audio/effect/all-versions/default/VisualizerEffect.cpp index 77bf46bcd3..ae533bf946 100644 --- a/audio/effect/all-versions/default/VisualizerEffect.cpp +++ b/audio/effect/all-versions/default/VisualizerEffect.cpp @@ -162,6 +162,10 @@ Return VisualizerEffect::close() { return mEffect->close(); } +Return VisualizerEffect::debug(const hidl_handle& fd, const hidl_vec& options) { + return mEffect->debug(fd, options); +} + // Methods from ::android::hardware::audio::effect::CPP_VERSION::IVisualizerEffect follow. Return VisualizerEffect::setCaptureSize(uint16_t captureSize) { Result retval = mEffect->setParam(VISUALIZER_PARAM_CAPTURE_SIZE, captureSize); diff --git a/audio/effect/all-versions/default/VisualizerEffect.h b/audio/effect/all-versions/default/VisualizerEffect.h index 42c77a2103..315f84452a 100644 --- a/audio/effect/all-versions/default/VisualizerEffect.h +++ b/audio/effect/all-versions/default/VisualizerEffect.h @@ -88,6 +88,7 @@ struct VisualizerEffect : public IVisualizerEffect { Return setCurrentConfigForFeature(uint32_t featureId, const hidl_vec& configData) override; Return close() override; + Return debug(const hidl_handle& fd, const hidl_vec& options) override; // Methods from ::android::hardware::audio::effect::CPP_VERSION::IVisualizerEffect follow. Return setCaptureSize(uint16_t captureSize) override; From 6735fea7125030db314e32e4852f73d5ab9930a2 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Fri, 22 Feb 2019 17:26:09 -0800 Subject: [PATCH 494/718] Revert "Fix audio VTS build" This reverts commit 22ab6f2febfc39f26d1b2866a064a5189c69bdb2. Bug; 125937703 Test: make Change-Id: Iead87b0e1b8078262d7e370b050c2a75dbcda387 --- .../core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h index 7f8b6a0646..a22cc1cfc5 100644 --- a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h +++ b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h @@ -142,13 +142,14 @@ struct PolicyConfigData { android::DeviceVector availableOutputDevices; android::DeviceVector availableInputDevices; sp defaultOutputDevice; + android::VolumeCurvesCollection volumes; }; class PolicyConfig : private PolicyConfigData, public AudioPolicyConfig { public: PolicyConfig() : AudioPolicyConfig(hwModules, availableOutputDevices, availableInputDevices, - defaultOutputDevice) { + defaultOutputDevice, &volumes) { for (const char* location : kConfigLocations) { std::string path = std::string(location) + '/' + kConfigFileName; if (access(path.c_str(), F_OK) == 0) { From bfb49a5cb019ab83ef2da5eb822da11bf9a7a5e6 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Fri, 22 Feb 2019 18:18:55 -0800 Subject: [PATCH 495/718] Revert "Revert "Fix audio VTS build"" This reverts commit 6735fea7125030db314e32e4852f73d5ab9930a2. Test: make. --- .../core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h index a22cc1cfc5..7f8b6a0646 100644 --- a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h +++ b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h @@ -142,14 +142,13 @@ struct PolicyConfigData { android::DeviceVector availableOutputDevices; android::DeviceVector availableInputDevices; sp defaultOutputDevice; - android::VolumeCurvesCollection volumes; }; class PolicyConfig : private PolicyConfigData, public AudioPolicyConfig { public: PolicyConfig() : AudioPolicyConfig(hwModules, availableOutputDevices, availableInputDevices, - defaultOutputDevice, &volumes) { + defaultOutputDevice) { for (const char* location : kConfigLocations) { std::string path = std::string(location) + '/' + kConfigFileName; if (access(path.c_str(), F_OK) == 0) { From 12ac2b5d0f3da834c0a410a4f4fcbadc4f558dc8 Mon Sep 17 00:00:00 2001 From: Pierre Fite-Georgel Date: Thu, 17 Jan 2019 16:56:17 -0800 Subject: [PATCH 496/718] Adding Elapsed Time since boot field to GnssData [HAL]. Test: Added VTS and did a build check. Bug: 121353225 Change-Id: I3cb329c16b0bfbff68c45033bcfdc85d53914f18 --- current.txt | 8 +-- gnss/2.0/Android.bp | 3 + gnss/2.0/IGnss.hal | 13 ++++ gnss/2.0/IGnssCallback.hal | 8 +++ gnss/2.0/IGnssMeasurementCallback.hal | 7 ++ gnss/2.0/default/Gnss.cpp | 70 +++++++++++++------ gnss/2.0/default/Gnss.h | 17 ++--- gnss/2.0/default/GnssMeasurement.cpp | 15 +++- gnss/2.0/types.hal | 55 +++++++++++++++ gnss/2.0/vts/functional/gnss_hal_test.cpp | 25 ++++++- gnss/2.0/vts/functional/gnss_hal_test.h | 20 ++++-- .../vts/functional/gnss_hal_test_cases.cpp | 63 +++++++++++++++++ 12 files changed, 259 insertions(+), 45 deletions(-) diff --git a/current.txt b/current.txt index f37a8e25c1..a76879dbab 100644 --- a/current.txt +++ b/current.txt @@ -464,12 +464,12 @@ f27baaa587bc3dd9b740cb6928ab812b9b7d105b5187663938aee578105f3c39 android.hardwar 7f460e795f5d1ed5e378935f98c6db4d39497de988aef1b4c2a4a07a6c400392 android.hardware.gnss@2.0::IAGnss 2e5ad983734069e84a760004b32da0d09e4170c05380abe27e6eb80e4aa70d5a android.hardware.gnss@2.0::IAGnssCallback 1f4ac068a88a72360280d94a7f6fd7c63813c1eea4891a0eb01394d3e7e775f2 android.hardware.gnss@2.0::IAGnssRil -52e56490d35b4214d68c44f013e22bdf681fd6f8e5947c643dbb8453f9a03dcd android.hardware.gnss@2.0::IGnss -0676e99eda39ff32f6891bcb56ea27df17007c439b9f900aa9a3919776920c23 android.hardware.gnss@2.0::IGnssCallback +6e2f9a44375a0ae0b49ca7d711cb88945189d398535078408269e1e85889061d android.hardware.gnss@2.0::IGnss +54d253b10c7da2a4a708d11acda3118b283df1540bc10323a5a3773c94cc8e71 android.hardware.gnss@2.0::IGnssCallback ecc966c68bddbd95c8dae782b84204cf01c75734675e8769963f3b5106ec128b android.hardware.gnss@2.0::IGnssConfiguration c67759f5d6387d273b66729180d03690e827f0b6b8d4e13ce2ff42d31b224065 android.hardware.gnss@2.0::IGnssMeasurement -08615296d42451856f82c4953b45c4257d0a7b935fd98557c2ee2812c79fe0c3 android.hardware.gnss@2.0::IGnssMeasurementCallback -141269652bcf30a7557edc4cd4311aa3e2ac67a252a7e8d3959b956d35793344 android.hardware.gnss@2.0::types +089338944c45f66f25ba4ee958c161c42fefeb73ec60e4451f3535a1b3fd10c7 android.hardware.gnss@2.0::IGnssMeasurementCallback +9e66234e65bcde75733d75d8b5d5cc094c2a5e14b074a25cd3f9ad141dc56f60 android.hardware.gnss@2.0::types 50623a69a88b1c8a05738e4af7d5f78e905f415ccb0e84c99d0a71ea182e9393 android.hardware.gnss.measurement_corrections@1.0::IMeasurementCorrections 6ef12cd95df73f8f80c25eb035d98ca4594f9cee571fdabea838a0b6016dd908 android.hardware.gnss.measurement_corrections@1.0::types 0d278956d7fc6fdf9ca9c42962ff2d73967bbb1c9f0b3e0b58d71b7095c286bc android.hardware.gnss.visibility_control@1.0::IGnssVisibilityControl diff --git a/gnss/2.0/Android.bp b/gnss/2.0/Android.bp index 9b04be0053..230dd907dd 100644 --- a/gnss/2.0/Android.bp +++ b/gnss/2.0/Android.bp @@ -25,6 +25,9 @@ hidl_interface { "android.hidl.base@1.0", ], types: [ + "ElapsedRealtime", + "ElapsedRealtimeFlags", + "GnssLocation", ], gen_java: true, gen_java_constants: true, diff --git a/gnss/2.0/IGnss.hal b/gnss/2.0/IGnss.hal index 1f1858e940..2c149b7a7b 100644 --- a/gnss/2.0/IGnss.hal +++ b/gnss/2.0/IGnss.hal @@ -20,6 +20,7 @@ import android.hardware.gnss.measurement_corrections@1.0::IMeasurementCorrection import android.hardware.gnss.visibility_control@1.0::IGnssVisibilityControl; import @1.1::IGnss; +import GnssLocation; import IGnssCallback; import IGnssConfiguration; import IGnssMeasurement; @@ -94,4 +95,16 @@ interface IGnss extends @1.1::IGnss { * @return visibilityControlIface Handle to the IGnssVisibilityControl interface. */ getExtensionVisibilityControl() generates (IGnssVisibilityControl visibilityControlIface); + + /** + * Injects current location from the best available location provider. + * + * Unlike injectLocation, this method may inject a recent GNSS location from the HAL + * implementation, if that is the best available location known to the framework. + * + * @param location Location information from the best available location provider. + * + * @return success Returns true if successful. + */ + injectBestLocation_2_0(GnssLocation location) generates (bool success); }; \ No newline at end of file diff --git a/gnss/2.0/IGnssCallback.hal b/gnss/2.0/IGnssCallback.hal index 6baff91a55..e2ac02ac03 100644 --- a/gnss/2.0/IGnssCallback.hal +++ b/gnss/2.0/IGnssCallback.hal @@ -18,6 +18,7 @@ package android.hardware.gnss@2.0; import @1.0::IGnssCallback; import @1.1::IGnssCallback; +import GnssLocation; /** * The interface is required for the HAL to communicate certain information @@ -44,4 +45,11 @@ interface IGnssCallback extends @1.1::IGnssCallback { */ gnssSetCapabilitiesCb_2_0(bitfield capabilities); + /** + * Called when a GNSS location is available. + * + * @param location Location information from HAL. + */ + gnssLocationCb_2_0(GnssLocation location); + }; \ No newline at end of file diff --git a/gnss/2.0/IGnssMeasurementCallback.hal b/gnss/2.0/IGnssMeasurementCallback.hal index fc4446571e..d5dc038b82 100644 --- a/gnss/2.0/IGnssMeasurementCallback.hal +++ b/gnss/2.0/IGnssMeasurementCallback.hal @@ -18,6 +18,7 @@ package android.hardware.gnss@2.0; import @1.0::IGnssMeasurementCallback; import @1.1::IGnssMeasurementCallback; +import ElapsedRealtime; /** The callback interface to report measurements from the HAL. */ interface IGnssMeasurementCallback extends @1.1::IGnssMeasurementCallback { @@ -492,6 +493,12 @@ interface IGnssMeasurementCallback extends @1.1::IGnssMeasurementCallback { /** The GNSS clock time reading. */ GnssClock clock; + + /** + * Timing information of the GNSS data synchronized with SystemClock.elapsedRealtimeNanos() + * clock. + */ + ElapsedRealtime elapsedRealtime; }; /** diff --git a/gnss/2.0/default/Gnss.cpp b/gnss/2.0/default/Gnss.cpp index 1efc9f5b48..599681bf38 100644 --- a/gnss/2.0/default/Gnss.cpp +++ b/gnss/2.0/default/Gnss.cpp @@ -17,7 +17,10 @@ #define LOG_TAG "Gnss" #include "Gnss.h" + #include +#include + #include "AGnss.h" #include "AGnssRil.h" #include "GnssConfiguration.h" @@ -40,6 +43,24 @@ using GnssSvFlags = IGnssCallback::GnssSvFlags; sp Gnss::sGnssCallback_2_0 = nullptr; sp Gnss::sGnssCallback_1_1 = nullptr; +namespace { + +V2_0::GnssLocation getMockLocationV2_0() { + const ElapsedRealtime timestamp = { + .flags = ElapsedRealtimeFlags::HAS_TIMESTAMP_NS | + ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS, + .timestampNs = static_cast(::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 = 1000000}; + + V2_0::GnssLocation location = {.v1_0 = Utils::getMockLocation(), .elapsedRealtime = timestamp}; + return location; +} + +} // namespace + Gnss::Gnss() : mMinIntervalMs(1000) {} Gnss::~Gnss() { @@ -48,7 +69,7 @@ Gnss::~Gnss() { // Methods from V1_0::IGnss follow. Return Gnss::setCallback(const sp&) { - // TODO implement + // TODO(b/124012850): Implement function. return bool{}; } @@ -61,7 +82,7 @@ Return Gnss::start() { mIsActive = true; mThread = std::thread([this]() { while (mIsActive == true) { - const auto location = Utils::getMockLocation(); + const auto location = getMockLocationV2_0(); this->reportLocation(location); std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMs)); @@ -79,44 +100,44 @@ Return Gnss::stop() { } Return Gnss::cleanup() { - // TODO implement + // TODO(b/124012850): Implement function. return Void(); } Return Gnss::injectTime(int64_t, int64_t, int32_t) { - // TODO implement + // TODO(b/124012850): Implement function. return bool{}; } Return Gnss::injectLocation(double, double, float) { - // TODO implement + // TODO(b/124012850): Implement function. return bool{}; } Return Gnss::deleteAidingData(V1_0::IGnss::GnssAidingData) { - // TODO implement + // TODO(b/124012850): Implement function. return Void(); } Return Gnss::setPositionMode(V1_0::IGnss::GnssPositionMode, V1_0::IGnss::GnssPositionRecurrence, uint32_t, uint32_t, uint32_t) { - // TODO implement + // TODO(b/124012850): Implement function. return bool{}; } Return> Gnss::getExtensionAGnssRil() { - // TODO implement + // TODO(b/124012850): Implement function. return sp{}; } Return> Gnss::getExtensionGnssGeofencing() { - // TODO implement + // TODO(b/124012850): Implement function. return sp{}; } Return> Gnss::getExtensionAGnss() { - // TODO implement + // TODO(b/124012850): Implement function. return sp{}; } @@ -131,27 +152,27 @@ Return> Gnss::getExtensionGnssMeasurement() { } Return> Gnss::getExtensionGnssNavigationMessage() { - // TODO implement + // TODO(b/124012850): Implement function. return sp{}; } Return> Gnss::getExtensionXtra() { - // TODO implement + // TODO(b/124012850): Implement function. return sp{}; } Return> Gnss::getExtensionGnssConfiguration() { - // TODO implement + // TODO(b/124012850): Implement function. return sp{}; } Return> Gnss::getExtensionGnssDebug() { - // TODO implement + // TODO(b/124012850): Implement function. return sp{}; } Return> Gnss::getExtensionGnssBatching() { - // TODO implement + // TODO(b/124012850): Implement function. return sp{}; } @@ -194,7 +215,7 @@ Return Gnss::setPositionMode_1_1(V1_0::IGnss::GnssPositionMode, } Return> Gnss::getExtensionGnssConfiguration_1_1() { - // TODO implement + // TODO(b/124012850): Implement function. return sp{}; } @@ -204,7 +225,7 @@ Return> Gnss::getExtensionGnssMeasurement_1_1() { } Return Gnss::injectBestLocation(const V1_0::GnssLocation&) { - // TODO implement + // TODO(b/124012850): Implement function. return bool{}; } @@ -228,7 +249,7 @@ Return> Gnss::getExtensionGnssMeasurement_2_0() { Return> Gnss::getExtensionMeasurementCorrections() { - // TODO implement + // TODO(b/124012850): Implement function. return sp{}; } @@ -268,16 +289,21 @@ Return Gnss::setCallback_2_0(const sp& callback) { return true; } -Return Gnss::reportLocation(const GnssLocation& location) const { +Return Gnss::reportLocation(const V2_0::GnssLocation& location) const { std::unique_lock lock(mMutex); - if (sGnssCallback_1_1 == nullptr) { - ALOGE("%s: sGnssCallback is null.", __func__); + if (sGnssCallback_2_0 == nullptr) { + ALOGE("%s: sGnssCallback 2.0 is null.", __func__); return Void(); } - sGnssCallback_1_1->gnssLocationCb(location); + sGnssCallback_2_0->gnssLocationCb_2_0(location); return Void(); } +Return Gnss::injectBestLocation_2_0(const V2_0::GnssLocation&) { + // TODO(b/124012850): Implement function. + return bool{}; +} + } // namespace implementation } // namespace V2_0 } // namespace gnss diff --git a/gnss/2.0/default/Gnss.h b/gnss/2.0/default/Gnss.h index 7d9e7831cd..f02ab0a21e 100644 --- a/gnss/2.0/default/Gnss.h +++ b/gnss/2.0/default/Gnss.h @@ -91,15 +91,16 @@ struct Gnss : public IGnss { getExtensionMeasurementCorrections() override; Return> getExtensionVisibilityControl() override; + Return injectBestLocation_2_0(const V2_0::GnssLocation& location) override; - private: - Return reportLocation(const GnssLocation&) const; - static sp sGnssCallback_2_0; - static sp sGnssCallback_1_1; - std::atomic mMinIntervalMs; - std::atomic mIsActive; - std::thread mThread; - mutable std::mutex mMutex; + private: + Return reportLocation(const V2_0::GnssLocation&) const; + static sp sGnssCallback_2_0; + static sp sGnssCallback_1_1; + std::atomic mMinIntervalMs; + std::atomic mIsActive; + std::thread mThread; + mutable std::mutex mMutex; }; } // namespace implementation diff --git a/gnss/2.0/default/GnssMeasurement.cpp b/gnss/2.0/default/GnssMeasurement.cpp index 0f707b4d4a..702c9e2362 100644 --- a/gnss/2.0/default/GnssMeasurement.cpp +++ b/gnss/2.0/default/GnssMeasurement.cpp @@ -16,7 +16,9 @@ #define LOG_TAG "GnssMeasurement" #include "GnssMeasurement.h" + #include +#include namespace android { namespace hardware { @@ -129,7 +131,18 @@ GnssData GnssMeasurement::getMockMeasurement() { .driftNsps = -51.757811607455452, .driftUncertaintyNsps = 310.64968328491528, .hwClockDiscontinuityCount = 1}; - GnssData gnssData = {.measurements = measurements, .clock = clock}; + + ElapsedRealtime timestamp = { + .flags = ElapsedRealtimeFlags::HAS_TIMESTAMP_NS | + ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS, + .timestampNs = static_cast(::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 = 1000000}; + + GnssData gnssData = { + .measurements = measurements, .clock = clock, .elapsedRealtime = timestamp}; return gnssData; } diff --git a/gnss/2.0/types.hal b/gnss/2.0/types.hal index 97c178ff32..4abb6048c9 100644 --- a/gnss/2.0/types.hal +++ b/gnss/2.0/types.hal @@ -16,5 +16,60 @@ package android.hardware.gnss@2.0; +import @1.0::GnssLocation; + /** Network handle type. */ typedef uint64_t net_handle_t; + +/** + * Flags indicating the validity of the fields in ElapsedRealtime. + */ +@export(name="", value_prefix="ELAPSED_REALTIME_") +enum ElapsedRealtimeFlags : uint16_t { + /** A valid timestampNs is stored in the data structure. */ + HAS_TIMESTAMP_NS = 1 << 0, + /** A valid timeUncertaintyNs is stored in the data structure. */ + HAS_TIME_UNCERTAINTY_NS = 1 << 1, +}; + +/** + * Represents an estimate of elapsed time since boot of Android for a given event. + * + * This timestamp MUST represent the time the event happened and MUST be synchronized + * with the SystemClock.elapsedRealtimeNanos() clock. + */ +struct ElapsedRealtime { + /** + * A set of flags indicating the validity of each field in this data structure. + * + * Fields may have invalid information in them, if not marked as valid by the + * corresponding bit in flags. + */ + bitfield flags; + + /** + * Estimate of the elapsed time since boot value for the corresponding event in nanoseconds. + */ + uint64_t timestampNs; + + /** + * Estimate of the relative precision of the alignment of this SystemClock + * timestamp, with the reported measurements in nanoseconds (68% confidence). + */ + uint64_t timeUncertaintyNs; +}; + +/** Represents a location. */ +struct GnssLocation { + @1.0::GnssLocation v1_0; + + /** + * Timing information of the GNSS location synchronized with SystemClock.elapsedRealtimeNanos() + * clock. + * + * This clock information can be obtained from SystemClock.elapsedRealtimeNanos(), when the GNSS + * is attached straight to the AP/SOC. When it is attached to a separate module the timestamp + * needs to be estimatedd by syncing the notion of time via PTP or some other mechanism. + */ + ElapsedRealtime elapsedRealtime; +}; \ No newline at end of file diff --git a/gnss/2.0/vts/functional/gnss_hal_test.cpp b/gnss/2.0/vts/functional/gnss_hal_test.cpp index 1580c28841..c564f41a03 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test.cpp +++ b/gnss/2.0/vts/functional/gnss_hal_test.cpp @@ -130,10 +130,10 @@ bool GnssHalTest::StartAndCheckFirstLocation() { return false; } -void GnssHalTest::CheckLocation(const GnssLocation& location, bool check_speed) { +void GnssHalTest::CheckLocation(const GnssLocation_2_0& location, bool check_speed) { const bool check_more_accuracies = (info_called_count_ > 0 && last_info_.yearOfHw >= 2017); - Utils::checkLocation(location, check_speed, check_more_accuracies); + Utils::checkLocation(location.v1_0, check_speed, check_more_accuracies); } void GnssHalTest::StartAndCheckLocations(int count) { @@ -193,6 +193,14 @@ Return GnssHalTest::GnssCallback::gnssSetCapabilitesCb(uint32_t capabiliti return Void(); } +Return GnssHalTest::GnssCallback::gnssSetCapabilitiesCb_2_0(uint32_t capabilities) { + ALOGI("Capabilities (v2.0) received %d", capabilities); + parent_.capabilities_called_count_++; + parent_.last_capabilities_ = capabilities; + parent_.notify(); + return Void(); +} + Return GnssHalTest::GnssCallback::gnssNameCb(const android::hardware::hidl_string& name) { ALOGI("Name received: %s", name.c_str()); parent_.name_called_count_++; @@ -201,8 +209,19 @@ Return GnssHalTest::GnssCallback::gnssNameCb(const android::hardware::hidl return Void(); } -Return GnssHalTest::GnssCallback::gnssLocationCb(const GnssLocation& location) { +Return GnssHalTest::GnssCallback::gnssLocationCb(const GnssLocation_1_0& location) { ALOGI("Location received"); + GnssLocation_2_0 location_v2_0; + location_v2_0.v1_0 = location; + return gnssLocationCbImpl(location_v2_0); +} + +Return GnssHalTest::GnssCallback::gnssLocationCb_2_0(const GnssLocation_2_0& location) { + ALOGI("Location (v2.0) received"); + return gnssLocationCbImpl(location); +} + +Return GnssHalTest::GnssCallback::gnssLocationCbImpl(const GnssLocation_2_0& location) { parent_.location_called_count_++; parent_.last_location_ = location; parent_.notify(); diff --git a/gnss/2.0/vts/functional/gnss_hal_test.h b/gnss/2.0/vts/functional/gnss_hal_test.h index 2c16651d8d..7793eb75cb 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test.h +++ b/gnss/2.0/vts/functional/gnss_hal_test.h @@ -18,7 +18,6 @@ #define GNSS_HAL_TEST_H_ #include - #include #include @@ -29,11 +28,13 @@ using android::hardware::Return; using android::hardware::Void; -using android::hardware::gnss::V1_0::GnssLocation; - using android::hardware::gnss::V1_0::GnssLocationFlags; -using android::hardware::gnss::V1_1::IGnssCallback; using android::hardware::gnss::V2_0::IGnss; +using android::hardware::gnss::V2_0::IGnssCallback; + +using GnssLocation_1_0 = android::hardware::gnss::V1_0::GnssLocation; +using GnssLocation_2_0 = android::hardware::gnss::V2_0::GnssLocation; + using IGnssMeasurementCallback_1_0 = android::hardware::gnss::V1_0::IGnssMeasurementCallback; using IGnssMeasurementCallback_1_1 = android::hardware::gnss::V1_1::IGnssMeasurementCallback; using IGnssMeasurementCallback_2_0 = android::hardware::gnss::V2_0::IGnssMeasurementCallback; @@ -97,10 +98,15 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase { Return gnssRequestTimeCb() override { return Void(); } // Actual (test) callback handlers Return gnssNameCb(const android::hardware::hidl_string& name) override; - Return gnssLocationCb(const GnssLocation& location) override; + Return gnssLocationCb(const GnssLocation_1_0& location) override; + Return gnssLocationCb_2_0(const GnssLocation_2_0& location) override; Return gnssSetCapabilitesCb(uint32_t capabilities) override; + Return gnssSetCapabilitiesCb_2_0(uint32_t capabilities) override; Return gnssSetSystemInfoCb(const IGnssCallback::GnssSystemInfo& info) override; Return gnssSvStatusCb(const IGnssCallback::GnssSvStatus& svStatus) override; + + private: + Return gnssLocationCbImpl(const GnssLocation_2_0& location); }; /* Callback class for GnssMeasurement. */ @@ -147,7 +153,7 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase { * * check_speed: true if speed related fields are also verified. */ - void CheckLocation(const GnssLocation& location, const bool check_speed); + void CheckLocation(const GnssLocation_2_0& location, const bool check_speed); /* * StartAndCheckLocations: @@ -186,7 +192,7 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase { IGnssCallback::GnssSystemInfo last_info_; uint32_t last_capabilities_; - GnssLocation last_location_; + GnssLocation_2_0 last_location_; IGnssMeasurementCallback_2_0::GnssData last_measurement_; android::hardware::hidl_string last_name_; diff --git a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp index 48f2be8802..b135dba2c1 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp +++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp @@ -31,7 +31,9 @@ using IAGnssRil_2_0 = android::hardware::gnss::V2_0::IAGnssRil; using IAGnss_2_0 = android::hardware::gnss::V2_0::IAGnss; using IAGnss_1_0 = android::hardware::gnss::V1_0::IAGnss; using IAGnssCallback_2_0 = android::hardware::gnss::V2_0::IAGnssCallback; + using android::hardware::gnss::V1_0::IGnssNi; +using android::hardware::gnss::V2_0::ElapsedRealtimeFlags; using android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl; /* @@ -269,3 +271,64 @@ TEST_F(GnssHalTest, TestGnssVisibilityControlExtension) { ASSERT_TRUE(result.isOk()); EXPECT_TRUE(result); } + +/* + * TestGnssDataElapsedRealtimeFlags: + * Sets a GnssMeasurementCallback, waits for a GnssData object, and verifies the flags in member + * elapsedRealitme are valid. + */ +TEST_F(GnssHalTest, TestGnssDataElapsedRealtimeFlags) { + const int kFirstGnssMeasurementTimeoutSeconds = 10; + + auto gnssMeasurement = gnss_hal_->getExtensionGnssMeasurement_2_0(); + if (!gnssMeasurement.isOk()) { + return; + } + + sp iGnssMeasurement = gnssMeasurement; + if (iGnssMeasurement == nullptr) { + return; + } + + sp callback = new GnssMeasurementCallback(*this); + + auto result = iGnssMeasurement->setCallback_2_0(callback, /* enableFullTracking= */ true); + ASSERT_TRUE(result.isOk()); + EXPECT_EQ(result, IGnssMeasurement_1_0::GnssMeasurementStatus::SUCCESS); + + wait(kFirstGnssMeasurementTimeoutSeconds); + EXPECT_EQ(measurement_called_count_, 1); + + ASSERT_TRUE((int)last_measurement_.elapsedRealtime.flags >= 0 && + (int)last_measurement_.elapsedRealtime.flags <= + (int)ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS); + + // We expect a non-zero timestamp when set. + if (last_measurement_.elapsedRealtime.flags & ElapsedRealtimeFlags::HAS_TIMESTAMP_NS) { + ASSERT_TRUE(last_measurement_.elapsedRealtime.timestampNs != 0); + } + + iGnssMeasurement->close(); +} + +TEST_F(GnssHalTest, TestGnssLocationElapsedRealtime) { + StartAndCheckFirstLocation(); + + ASSERT_TRUE((int)last_location_.elapsedRealtime.flags >= 0 && + (int)last_location_.elapsedRealtime.flags <= + (int)ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS); + + // We expect a non-zero timestamp when set. + if (last_location_.elapsedRealtime.flags & ElapsedRealtimeFlags::HAS_TIMESTAMP_NS) { + ASSERT_TRUE(last_location_.elapsedRealtime.timestampNs != 0); + } + + StopAndClearLocations(); +} + +// This test only verify that injectBestLocation_2_0 does not crash. +TEST_F(GnssHalTest, TestInjectBestLocation_2_0) { + StartAndCheckFirstLocation(); + gnss_hal_->injectBestLocation_2_0(last_location_); + StopAndClearLocations(); +} From 5d287f709b1c65d9493edf7eec5e18c79fa67859 Mon Sep 17 00:00:00 2001 From: Changyeon Jo Date: Sat, 9 Feb 2019 19:49:23 +0000 Subject: [PATCH 497/718] Updates openDisplay() API description This change corrects the description of openDisplay()'s behavior when new client requests to access a display resource. Bug: 122671398 Test: N/A Change-Id: I0605489506f3a011d2d3ea405d2b87f7cb0bd883 Signed-off-by: Changyeon Jo From b8524954e6c0ac4dae2083c8778426a406cdc1fe Mon Sep 17 00:00:00 2001 From: Emil Jahshan Date: Sun, 27 Jan 2019 11:56:25 +0200 Subject: [PATCH 498/718] VTS tests to work with depth Y16 modified VTS tests functions to work with the Y16 format with the correct dataspace. Y16 changes are in this patch: 847192 Test: ran and tested on intel depth camera D415 and a regular RGB camera Change-Id: Ie40347d58d4f72ed2fc9676bdaab2d1dca5dc5bc Signed-off-by: Emil Jahshan --- .../VtsHalCameraProviderV2_4TargetTest.cpp | 129 +++++++++++++++--- 1 file changed, 109 insertions(+), 20 deletions(-) diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp index 22b738256d..2a464d58fb 100644 --- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp +++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp @@ -671,6 +671,7 @@ public: HalStreamConfiguration *halStreamConfig /*out*/, bool *supportsPartialResults /*out*/, uint32_t *partialResultCount /*out*/); + bool isDepthOnly(camera_metadata_t* staticMeta); static Status getAvailableOutputStreams(camera_metadata_t *staticMeta, std::vector &outputStreams, const AvailableStream *threshold = nullptr); @@ -682,6 +683,10 @@ public: std::unordered_set *physicalIds/*out*/); static Status getSupportedKeys(camera_metadata_t *staticMeta, uint32_t tagId, std::unordered_set *requestIDs/*out*/); + static void fillOutputStreams(camera_metadata_ro_entry_t* entry, + std::vector& outputStreams, + const AvailableStream *threshold = nullptr, + const int32_t availableConfigOutputTag = 0u); static void constructFilteredSettings(const sp& session, const std::unordered_set& availableKeys, RequestTemplate reqTemplate, android::hardware::camera::common::V1_0::helper::CameraMetadata* defaultSettings/*out*/, @@ -2521,14 +2526,24 @@ TEST_F(CameraHidlTest, configureStreamsAvailableOutputs) { int32_t streamId = 0; for (auto& it : outputStreams) { V3_2::Stream stream3_2; - bool isJpeg = static_cast(it.format) == PixelFormat::BLOB; + V3_2::DataspaceFlags dataspaceFlag = 0; + switch (static_cast(it.format)) { + case PixelFormat::BLOB: + dataspaceFlag = static_cast(Dataspace::V0_JFIF); + break; + case PixelFormat::Y16: + dataspaceFlag = static_cast(Dataspace::DEPTH); + break; + default: + dataspaceFlag = static_cast(Dataspace::UNKNOWN); + } stream3_2 = {streamId, StreamType::OUTPUT, static_cast(it.width), static_cast(it.height), static_cast(it.format), GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, - (isJpeg) ? static_cast(Dataspace::V0_JFIF) : 0, + dataspaceFlag, StreamRotation::ROTATION_0}; ::android::hardware::hidl_vec streams3_2 = {stream3_2}; ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4; @@ -2962,6 +2977,14 @@ TEST_F(CameraHidlTest, configureStreamsPreviewStillOutputs) { openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/); castSession(session, deviceVersion, &session3_3, &session3_4); + // Check if camera support depth only + if (isDepthOnly(staticMeta)) { + free_camera_metadata(staticMeta); + ret = session->close(); + ASSERT_TRUE(ret.isOk()); + continue; + } + outputBlobStreams.clear(); ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, outputBlobStreams, @@ -3230,6 +3253,14 @@ TEST_F(CameraHidlTest, configureStreamsVideoStillOutputs) { openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/); castSession(session, deviceVersion, &session3_3, &session3_4); + // Check if camera support depth only + if (isDepthOnly(staticMeta)) { + free_camera_metadata(staticMeta); + ret = session->close(); + ASSERT_TRUE(ret.isOk()); + continue; + } + outputBlobStreams.clear(); ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, outputBlobStreams, @@ -4135,38 +4166,56 @@ TEST_F(CameraHidlTest, flushEmpty) { Status CameraHidlTest::getAvailableOutputStreams(camera_metadata_t *staticMeta, std::vector &outputStreams, const AvailableStream *threshold) { + AvailableStream depthPreviewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight, + static_cast(PixelFormat::Y16)}; if (nullptr == staticMeta) { return Status::ILLEGAL_ARGUMENT; } - camera_metadata_ro_entry entry; - int rc = find_camera_metadata_ro_entry(staticMeta, - ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, &entry); - if ((0 != rc) || (0 != (entry.count % 4))) { + camera_metadata_ro_entry scalarEntry; + camera_metadata_ro_entry depthEntry; + int foundScalar = find_camera_metadata_ro_entry(staticMeta, + ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, &scalarEntry); + int foundDepth = find_camera_metadata_ro_entry(staticMeta, + ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS, &depthEntry); + if ((0 != foundScalar || (0 != (scalarEntry.count % 4))) && + (0 != foundDepth || (0 != (depthEntry.count % 4)))) { return Status::ILLEGAL_ARGUMENT; } - for (size_t i = 0; i < entry.count; i+=4) { - if (ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT == - entry.data.i32[i + 3]) { + if(foundScalar == 0 && (0 == (scalarEntry.count % 4))) { + fillOutputStreams(&scalarEntry, outputStreams, threshold, + ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT); + } + + if(foundDepth == 0 && (0 == (depthEntry.count % 4))) { + fillOutputStreams(&depthEntry, outputStreams, &depthPreviewThreshold, + ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_OUTPUT); + } + + return Status::OK; +} + +void CameraHidlTest::fillOutputStreams(camera_metadata_ro_entry_t* entry, + std::vector& outputStreams, const AvailableStream* threshold, + const int32_t availableConfigOutputTag) { + for (size_t i = 0; i < entry->count; i+=4) { + if (availableConfigOutputTag == entry->data.i32[i + 3]) { if(nullptr == threshold) { - AvailableStream s = {entry.data.i32[i+1], - entry.data.i32[i+2], entry.data.i32[i]}; + AvailableStream s = {entry->data.i32[i+1], + entry->data.i32[i+2], entry->data.i32[i]}; outputStreams.push_back(s); } else { - if ((threshold->format == entry.data.i32[i]) && - (threshold->width >= entry.data.i32[i+1]) && - (threshold->height >= entry.data.i32[i+2])) { - AvailableStream s = {entry.data.i32[i+1], - entry.data.i32[i+2], threshold->format}; + if ((threshold->format == entry->data.i32[i]) && + (threshold->width >= entry->data.i32[i+1]) && + (threshold->height >= entry->data.i32[i+2])) { + AvailableStream s = {entry->data.i32[i+1], + entry->data.i32[i+2], threshold->format}; outputStreams.push_back(s); } } } - } - - return Status::OK; } // Get max jpeg buffer size in android.jpeg.maxSize @@ -4563,6 +4612,37 @@ void CameraHidlTest::configurePreviewStreams3_4(const std::string &name, int32_t ASSERT_TRUE(ret.isOk()); } +bool CameraHidlTest::isDepthOnly(camera_metadata_t* staticMeta) { + camera_metadata_ro_entry scalarEntry; + camera_metadata_ro_entry depthEntry; + + int rc = find_camera_metadata_ro_entry( + staticMeta, ANDROID_REQUEST_AVAILABLE_CAPABILITIES, &scalarEntry); + if (rc == 0) { + for (uint32_t i = 0; i < scalarEntry.count; i++) { + if (scalarEntry.data.u8[i] == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE) { + return false; + } + } + } + + for (uint32_t i = 0; i < scalarEntry.count; i++) { + if (scalarEntry.data.u8[i] == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT) { + + rc = find_camera_metadata_ro_entry( + staticMeta, ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS, &depthEntry); + size_t i = 0; + if (rc == 0 && depthEntry.data.i32[i] == static_cast(PixelFormat::Y16)) { + // only Depth16 format is supported now + return true; + } + break; + } + } + + return false; +} + // Open a device session and configure a preview stream. void CameraHidlTest::configurePreviewStream(const std::string &name, int32_t deviceVersion, sp provider, @@ -4638,11 +4718,20 @@ void CameraHidlTest::configurePreviewStream(const std::string &name, int32_t dev ASSERT_EQ(Status::OK, rc); ASSERT_FALSE(outputPreviewStreams.empty()); + V3_2::DataspaceFlags dataspaceFlag = 0; + switch (static_cast(outputPreviewStreams[0].format)) { + case PixelFormat::Y16: + dataspaceFlag = static_cast(Dataspace::DEPTH); + break; + default: + dataspaceFlag = static_cast(Dataspace::UNKNOWN); + } + V3_2::Stream stream3_2 = {0, StreamType::OUTPUT, static_cast (outputPreviewStreams[0].width), static_cast (outputPreviewStreams[0].height), static_cast (outputPreviewStreams[0].format), - GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, 0, StreamRotation::ROTATION_0}; + GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, dataspaceFlag, StreamRotation::ROTATION_0}; ::android::hardware::hidl_vec streams3_2 = {stream3_2}; ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2; ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4; From e2a5a7597e37ae8b163f42f1e356764e27726f6b Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Mon, 25 Feb 2019 15:31:23 -0800 Subject: [PATCH 499/718] cas@1.1: must be used over cas@1.0 for Q devices Bug: 122472761 Test: N/A Change-Id: Ifb0fe8a83aed1cf6bc57612919d71a7b2e9a0c40 --- compatibility_matrices/compatibility_matrix.current.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml index 2f9fb6eb6c..244d7a0396 100644 --- a/compatibility_matrices/compatibility_matrix.current.xml +++ b/compatibility_matrices/compatibility_matrix.current.xml @@ -121,7 +121,7 @@ android.hardware.cas - 1.0-1 + 1.1 IMediaCasService default From 99dab386d38cf39fe2352c1743a66aa26bf6983d Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Thu, 14 Feb 2019 07:57:10 -0800 Subject: [PATCH 500/718] wifi(implementation): Move set/getMacaddress to a util class This is just a refactor to move the setMacAddress & getFactoryMacAddress methods to a util class within the HAL. This can be then reused in AP iface for mac randomization of SoftAp. This also fixes a bug in the existing setMacAddress() method, the current method always sets wlan0 up/down. STA interface could be wlan1 on some devices. Bug: 78353419 Test: ./hardware/interfaces/wifi/1.3/default/tests/runtests.sh Test: Manually verified STA MAC randomization still works. Change-Id: I0bb8154f7e6dcae37c977454423c8c299762260e --- wifi/1.3/default/Android.mk | 2 + wifi/1.3/default/service.cpp | 2 + .../default/tests/mock_wifi_iface_util.cpp | 37 ++++++++++++ wifi/1.3/default/tests/mock_wifi_iface_util.h | 46 ++++++++++++++ .../default/tests/wifi_chip_unit_tests.cpp | 5 +- wifi/1.3/default/wifi.cpp | 4 +- wifi/1.3/default/wifi.h | 2 + wifi/1.3/default/wifi_ap_iface.cpp | 8 ++- wifi/1.3/default/wifi_ap_iface.h | 6 +- wifi/1.3/default/wifi_chip.cpp | 6 +- wifi/1.3/default/wifi_chip.h | 2 + wifi/1.3/default/wifi_iface_util.cpp | 60 +++++++++++++++++++ wifi/1.3/default/wifi_iface_util.h | 55 +++++++++++++++++ wifi/1.3/default/wifi_sta_iface.cpp | 25 +++----- wifi/1.3/default/wifi_sta_iface.h | 8 +-- 15 files changed, 241 insertions(+), 27 deletions(-) create mode 100644 wifi/1.3/default/tests/mock_wifi_iface_util.cpp create mode 100644 wifi/1.3/default/tests/mock_wifi_iface_util.h create mode 100644 wifi/1.3/default/wifi_iface_util.cpp create mode 100644 wifi/1.3/default/wifi_iface_util.h diff --git a/wifi/1.3/default/Android.mk b/wifi/1.3/default/Android.mk index 01fa934a00..eb07a9af1c 100644 --- a/wifi/1.3/default/Android.mk +++ b/wifi/1.3/default/Android.mk @@ -43,6 +43,7 @@ LOCAL_SRC_FILES := \ wifi_ap_iface.cpp \ wifi_chip.cpp \ wifi_feature_flags.cpp \ + wifi_iface_util.cpp \ wifi_legacy_hal.cpp \ wifi_legacy_hal_stubs.cpp \ wifi_mode_controller.cpp \ @@ -139,6 +140,7 @@ LOCAL_SRC_FILES := \ tests/hidl_struct_util_unit_tests.cpp \ tests/main.cpp \ tests/mock_wifi_feature_flags.cpp \ + tests/mock_wifi_iface_util.cpp \ tests/mock_wifi_legacy_hal.cpp \ tests/mock_wifi_mode_controller.cpp \ tests/ringbuffer_unit_tests.cpp \ diff --git a/wifi/1.3/default/service.cpp b/wifi/1.3/default/service.cpp index 5daf659dfd..73015cf054 100644 --- a/wifi/1.3/default/service.cpp +++ b/wifi/1.3/default/service.cpp @@ -30,6 +30,7 @@ using android::hardware::joinRpcThreadpool; using android::hardware::LazyServiceRegistrar; using android::hardware::wifi::V1_3::implementation::feature_flags:: WifiFeatureFlags; +using android::hardware::wifi::V1_3::implementation::iface_util::WifiIfaceUtil; using android::hardware::wifi::V1_3::implementation::legacy_hal::WifiLegacyHal; using android::hardware::wifi::V1_3::implementation::mode_controller:: WifiModeController; @@ -52,6 +53,7 @@ int main(int /*argc*/, char** argv) { new android::hardware::wifi::V1_3::implementation::Wifi( std::make_shared(), std::make_shared(), + std::make_shared(), std::make_shared()); if (kLazyService) { LazyServiceRegistrar registrar; diff --git a/wifi/1.3/default/tests/mock_wifi_iface_util.cpp b/wifi/1.3/default/tests/mock_wifi_iface_util.cpp new file mode 100644 index 0000000000..706cb6a5ef --- /dev/null +++ b/wifi/1.3/default/tests/mock_wifi_iface_util.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2019 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 +#include +#include + +#undef NAN // This is weird, NAN is defined in bionic/libc/include/math.h:38 +#include "mock_wifi_iface_util.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +namespace iface_util { + +MockWifiIfaceUtil::MockWifiIfaceUtil() : WifiIfaceUtil() {} +} // namespace iface_util +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.3/default/tests/mock_wifi_iface_util.h b/wifi/1.3/default/tests/mock_wifi_iface_util.h new file mode 100644 index 0000000000..6fb8f712d3 --- /dev/null +++ b/wifi/1.3/default/tests/mock_wifi_iface_util.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2019 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 MOCK_WIFI_IFACE_UTIL_H_ +#define MOCK_WIFI_IFACE_UTIL_H_ + +#include + +#include "wifi_iface_util.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +namespace iface_util { + +class MockWifiIfaceUtil : public WifiIfaceUtil { + public: + MockWifiIfaceUtil(); + MOCK_METHOD1(getFactoryMacAddress, + std::array(const std::string&)); + MOCK_METHOD2(setMacAddress, + bool(const std::string&, const std::array&)); +}; +} // namespace iface_util +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // MOCK_WIFI_IFACE_UTIL_H_ diff --git a/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp index 3fcc39eb8f..134563c7ea 100644 --- a/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp +++ b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp @@ -23,6 +23,7 @@ #include "wifi_chip.h" #include "mock_wifi_feature_flags.h" +#include "mock_wifi_iface_util.h" #include "mock_wifi_legacy_hal.h" #include "mock_wifi_mode_controller.h" @@ -263,7 +264,7 @@ class WifiChipTest : public Test { public: void SetUp() override { chip_ = new WifiChip(chip_id_, legacy_hal_, mode_controller_, - feature_flags_); + iface_util_, feature_flags_); EXPECT_CALL(*mode_controller_, changeFirmwareMode(testing::_)) .WillRepeatedly(testing::Return(true)); @@ -278,6 +279,8 @@ class WifiChipTest : public Test { new NiceMock}; std::shared_ptr> mode_controller_{new NiceMock}; + std::shared_ptr> iface_util_{ + new NiceMock}; std::shared_ptr> feature_flags_{new NiceMock}; }; diff --git a/wifi/1.3/default/wifi.cpp b/wifi/1.3/default/wifi.cpp index e3af1eab17..1f640856c2 100644 --- a/wifi/1.3/default/wifi.cpp +++ b/wifi/1.3/default/wifi.cpp @@ -36,9 +36,11 @@ using hidl_return_util::validateAndCallWithLock; Wifi::Wifi( const std::shared_ptr legacy_hal, const std::shared_ptr mode_controller, + const std::shared_ptr iface_util, const std::shared_ptr feature_flags) : legacy_hal_(legacy_hal), mode_controller_(mode_controller), + iface_util_(iface_util), feature_flags_(feature_flags), run_state_(RunState::STOPPED) {} @@ -105,7 +107,7 @@ WifiStatus Wifi::startInternal() { if (wifi_status.code == WifiStatusCode::SUCCESS) { // Create the chip instance once the HAL is started. chip_ = new WifiChip(kChipId, legacy_hal_, mode_controller_, - feature_flags_); + iface_util_, feature_flags_); run_state_ = RunState::STARTED; for (const auto& callback : event_cb_handler_.getCallbacks()) { if (!callback->onStart().isOk()) { diff --git a/wifi/1.3/default/wifi.h b/wifi/1.3/default/wifi.h index e92142492a..c4ab7732bd 100644 --- a/wifi/1.3/default/wifi.h +++ b/wifi/1.3/default/wifi.h @@ -43,6 +43,7 @@ class Wifi : public V1_3::IWifi { Wifi(const std::shared_ptr legacy_hal, const std::shared_ptr mode_controller, + const std::shared_ptr iface_util, const std::shared_ptr feature_flags); bool isValid(); @@ -78,6 +79,7 @@ class Wifi : public V1_3::IWifi { // and shared with all the child HIDL interface objects. std::shared_ptr legacy_hal_; std::shared_ptr mode_controller_; + std::shared_ptr iface_util_; std::shared_ptr feature_flags_; RunState run_state_; sp chip_; diff --git a/wifi/1.3/default/wifi_ap_iface.cpp b/wifi/1.3/default/wifi_ap_iface.cpp index c203e47b5d..025ece3158 100644 --- a/wifi/1.3/default/wifi_ap_iface.cpp +++ b/wifi/1.3/default/wifi_ap_iface.cpp @@ -30,8 +30,12 @@ using hidl_return_util::validateAndCall; WifiApIface::WifiApIface( const std::string& ifname, - const std::weak_ptr legacy_hal) - : ifname_(ifname), legacy_hal_(legacy_hal), is_valid_(true) {} + const std::weak_ptr legacy_hal, + const std::weak_ptr iface_util) + : ifname_(ifname), + legacy_hal_(legacy_hal), + iface_util_(iface_util), + is_valid_(true) {} void WifiApIface::invalidate() { legacy_hal_.reset(); diff --git a/wifi/1.3/default/wifi_ap_iface.h b/wifi/1.3/default/wifi_ap_iface.h index 9f3d870d35..6dbfc18a33 100644 --- a/wifi/1.3/default/wifi_ap_iface.h +++ b/wifi/1.3/default/wifi_ap_iface.h @@ -20,6 +20,8 @@ #include #include +#include "wifi_iface_util.h" + #include "wifi_legacy_hal.h" namespace android { @@ -35,7 +37,8 @@ using namespace android::hardware::wifi::V1_0; class WifiApIface : public V1_0::IWifiApIface { public: WifiApIface(const std::string& ifname, - const std::weak_ptr legacy_hal); + const std::weak_ptr legacy_hal, + const std::weak_ptr iface_util); // Refer to |WifiChip::invalidate()|. void invalidate(); bool isValid(); @@ -59,6 +62,7 @@ class WifiApIface : public V1_0::IWifiApIface { std::string ifname_; std::weak_ptr legacy_hal_; + std::weak_ptr iface_util_; bool is_valid_; DISALLOW_COPY_AND_ASSIGN(WifiApIface); diff --git a/wifi/1.3/default/wifi_chip.cpp b/wifi/1.3/default/wifi_chip.cpp index e7ebc3b1aa..9640a61a85 100644 --- a/wifi/1.3/default/wifi_chip.cpp +++ b/wifi/1.3/default/wifi_chip.cpp @@ -313,10 +313,12 @@ using hidl_return_util::validateAndCallWithLock; WifiChip::WifiChip( ChipId chip_id, const std::weak_ptr legacy_hal, const std::weak_ptr mode_controller, + const std::weak_ptr iface_util, const std::weak_ptr feature_flags) : chip_id_(chip_id), legacy_hal_(legacy_hal), mode_controller_(mode_controller), + iface_util_(iface_util), feature_flags_(feature_flags), is_valid_(true), current_mode_id_(feature_flags::chip_mode_ids::kInvalid), @@ -775,7 +777,7 @@ std::pair> WifiChip::createApIfaceInternal() { return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; } std::string ifname = allocateApOrStaIfaceName(); - sp iface = new WifiApIface(ifname, legacy_hal_); + sp iface = new WifiApIface(ifname, legacy_hal_, iface_util_); ap_ifaces_.push_back(iface); for (const auto& callback : event_cb_handler_.getCallbacks()) { if (!callback->onIfaceAdded(IfaceType::AP, ifname).isOk()) { @@ -914,7 +916,7 @@ std::pair> WifiChip::createStaIfaceInternal() { return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; } std::string ifname = allocateApOrStaIfaceName(); - sp iface = new WifiStaIface(ifname, legacy_hal_); + sp iface = new WifiStaIface(ifname, legacy_hal_, iface_util_); sta_ifaces_.push_back(iface); for (const auto& callback : event_cb_handler_.getCallbacks()) { if (!callback->onIfaceAdded(IfaceType::STA, ifname).isOk()) { diff --git a/wifi/1.3/default/wifi_chip.h b/wifi/1.3/default/wifi_chip.h index d14ced62ce..3eb0aee471 100644 --- a/wifi/1.3/default/wifi_chip.h +++ b/wifi/1.3/default/wifi_chip.h @@ -53,6 +53,7 @@ class WifiChip : public V1_3::IWifiChip { const std::weak_ptr legacy_hal, const std::weak_ptr mode_controller, + const std::weak_ptr iface_util, const std::weak_ptr feature_flags); // HIDL does not provide a built-in mechanism to let the server invalidate // a HIDL interface object after creation. If any client process holds onto @@ -233,6 +234,7 @@ class WifiChip : public V1_3::IWifiChip { ChipId chip_id_; std::weak_ptr legacy_hal_; std::weak_ptr mode_controller_; + std::weak_ptr iface_util_; std::weak_ptr feature_flags_; std::vector> ap_ifaces_; std::vector> nan_ifaces_; diff --git a/wifi/1.3/default/wifi_iface_util.cpp b/wifi/1.3/default/wifi_iface_util.cpp new file mode 100644 index 0000000000..39fa1e8b6d --- /dev/null +++ b/wifi/1.3/default/wifi_iface_util.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2019 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 +#include +#include + +#include "wifi_iface_util.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +namespace iface_util { + +WifiIfaceUtil::WifiIfaceUtil() {} + +std::array WifiIfaceUtil::getFactoryMacAddress( + const std::string& iface_name) { + return iface_tool_.GetFactoryMacAddress(iface_name.c_str()); +} + +bool WifiIfaceUtil::setMacAddress(const std::string& iface_name, + const std::array& mac) { + if (!iface_tool_.SetUpState(iface_name.c_str(), false)) { + LOG(ERROR) << "SetUpState(false) failed."; + return false; + } + if (!iface_tool_.SetMacAddress(iface_name.c_str(), mac)) { + LOG(ERROR) << "SetMacAddress failed."; + return false; + } + if (!iface_tool_.SetUpState(iface_name.c_str(), true)) { + LOG(ERROR) << "SetUpState(true) failed."; + return false; + } + LOG(DEBUG) << "Successfully SetMacAddress."; + return true; +} + +} // namespace iface_util +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.3/default/wifi_iface_util.h b/wifi/1.3/default/wifi_iface_util.h new file mode 100644 index 0000000000..9495322f7d --- /dev/null +++ b/wifi/1.3/default/wifi_iface_util.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2019 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 WIFI_IFACE_UTIL_H_ +#define WIFI_IFACE_UTIL_H_ + +#include + +#include + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +namespace iface_util { + +/** + * Util class for common iface operations. + */ +class WifiIfaceUtil { + public: + WifiIfaceUtil(); + virtual ~WifiIfaceUtil() = default; + + virtual std::array getFactoryMacAddress( + const std::string& iface_name); + virtual bool setMacAddress(const std::string& iface_name, + const std::array& mac); + + private: + wifi_system::InterfaceTool iface_tool_; +}; + +} // namespace iface_util +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_IFACE_UTIL_H_ diff --git a/wifi/1.3/default/wifi_sta_iface.cpp b/wifi/1.3/default/wifi_sta_iface.cpp index f7157a34af..17f3e3d9d8 100644 --- a/wifi/1.3/default/wifi_sta_iface.cpp +++ b/wifi/1.3/default/wifi_sta_iface.cpp @@ -30,8 +30,12 @@ using hidl_return_util::validateAndCall; WifiStaIface::WifiStaIface( const std::string& ifname, - const std::weak_ptr legacy_hal) - : ifname_(ifname), legacy_hal_(legacy_hal), is_valid_(true) { + const std::weak_ptr legacy_hal, + const std::weak_ptr iface_util) + : ifname_(ifname), + legacy_hal_(legacy_hal), + iface_util_(iface_util), + is_valid_(true) { // Turn on DFS channel usage for STA iface. legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->setDfsFlag(ifname_, true); @@ -622,28 +626,17 @@ WifiStaIface::getDebugRxPacketFatesInternal() { WifiStatus WifiStaIface::setMacAddressInternal( const std::array& mac) { - if (!iface_tool_.SetWifiUpState(false)) { - LOG(ERROR) << "SetWifiUpState(false) failed."; + bool status = iface_util_.lock()->setMacAddress(ifname_, mac); + if (!status) { return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); } - - if (!iface_tool_.SetMacAddress(ifname_.c_str(), mac)) { - LOG(ERROR) << "SetMacAddress failed."; - return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); - } - - if (!iface_tool_.SetWifiUpState(true)) { - LOG(ERROR) << "SetWifiUpState(true) failed."; - return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); - } - LOG(DEBUG) << "Successfully SetMacAddress."; return createWifiStatus(WifiStatusCode::SUCCESS); } std::pair> WifiStaIface::getFactoryMacAddressInternal() { std::array mac = - iface_tool_.GetFactoryMacAddress(ifname_.c_str()); + iface_util_.lock()->getFactoryMacAddress(ifname_); return {createWifiStatus(WifiStatusCode::SUCCESS), mac}; } diff --git a/wifi/1.3/default/wifi_sta_iface.h b/wifi/1.3/default/wifi_sta_iface.h index 69cb82a79f..92249394bf 100644 --- a/wifi/1.3/default/wifi_sta_iface.h +++ b/wifi/1.3/default/wifi_sta_iface.h @@ -21,9 +21,8 @@ #include #include -#include - #include "hidl_callback_util.h" +#include "wifi_iface_util.h" #include "wifi_legacy_hal.h" namespace android { @@ -39,7 +38,8 @@ using namespace android::hardware::wifi::V1_0; class WifiStaIface : public V1_3::IWifiStaIface { public: WifiStaIface(const std::string& ifname, - const std::weak_ptr legacy_hal); + const std::weak_ptr legacy_hal, + const std::weak_ptr iface_util); // Refer to |WifiChip::invalidate()|. void invalidate(); bool isValid(); @@ -162,10 +162,10 @@ class WifiStaIface : public V1_3::IWifiStaIface { std::string ifname_; std::weak_ptr legacy_hal_; + std::weak_ptr iface_util_; bool is_valid_; hidl_callback_util::HidlCallbackHandler event_cb_handler_; - wifi_system::InterfaceTool iface_tool_; DISALLOW_COPY_AND_ASSIGN(WifiStaIface); }; From 3b6705fb20afe97c2c53fd8385599dde3cafa9a3 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Thu, 14 Feb 2019 09:43:43 -0800 Subject: [PATCH 501/718] wifi(implementation): Set randomized MAC address for AP Add the plumbing required for setting a random MAC address on AP startup. The random MAC address is created once for the lifetime of the daemon and then reused for any further AP creation. This would ensure that the MAC address is changed on every reboot. The feature is turned on by default, devices will need to set the |WIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION| in their .mk file to disable the feature at compile time. Bug: 78353419 Test: ./hardware/interfaces/wifi/1.3/default/tests/runtests.sh Change-Id: I054d5249c20cc582b76966313135295873cd0b61 --- wifi/1.3/default/Android.mk | 4 + .../default/tests/mock_wifi_feature_flags.h | 1 + wifi/1.3/default/tests/mock_wifi_iface_util.h | 1 + .../tests/wifi_ap_iface_unit_tests.cpp | 76 +++++++++++++++++++ wifi/1.3/default/wifi_ap_iface.cpp | 19 ++++- wifi/1.3/default/wifi_ap_iface.h | 11 ++- wifi/1.3/default/wifi_chip.cpp | 3 +- wifi/1.3/default/wifi_feature_flags.cpp | 10 +++ wifi/1.3/default/wifi_feature_flags.h | 1 + wifi/1.3/default/wifi_iface_util.cpp | 15 +++- wifi/1.3/default/wifi_iface_util.h | 7 ++ 11 files changed, 140 insertions(+), 8 deletions(-) create mode 100644 wifi/1.3/default/tests/wifi_ap_iface_unit_tests.cpp diff --git a/wifi/1.3/default/Android.mk b/wifi/1.3/default/Android.mk index eb07a9af1c..7ebea4f4d1 100644 --- a/wifi/1.3/default/Android.mk +++ b/wifi/1.3/default/Android.mk @@ -33,6 +33,9 @@ endif ifdef WIFI_HIDL_FEATURE_DISABLE_AP LOCAL_CPPFLAGS += -DWIFI_HIDL_FEATURE_DISABLE_AP endif +ifdef WIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION +LOCAL_CPPFLAGS += -DWIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION +endif # Allow implicit fallthroughs in wifi_legacy_hal.cpp until they are fixed. LOCAL_CFLAGS += -Wno-error=implicit-fallthrough LOCAL_SRC_FILES := \ @@ -144,6 +147,7 @@ LOCAL_SRC_FILES := \ tests/mock_wifi_legacy_hal.cpp \ tests/mock_wifi_mode_controller.cpp \ tests/ringbuffer_unit_tests.cpp \ + tests/wifi_ap_iface_unit_tests.cpp \ tests/wifi_chip_unit_tests.cpp LOCAL_STATIC_LIBRARIES := \ libgmock \ diff --git a/wifi/1.3/default/tests/mock_wifi_feature_flags.h b/wifi/1.3/default/tests/mock_wifi_feature_flags.h index 8b0baa41a6..ee12b54c78 100644 --- a/wifi/1.3/default/tests/mock_wifi_feature_flags.h +++ b/wifi/1.3/default/tests/mock_wifi_feature_flags.h @@ -34,6 +34,7 @@ class MockWifiFeatureFlags : public WifiFeatureFlags { MockWifiFeatureFlags(); MOCK_METHOD0(getChipModes, std::vector()); + MOCK_METHOD0(isApMacRandomizationDisabled, bool()); }; } // namespace feature_flags diff --git a/wifi/1.3/default/tests/mock_wifi_iface_util.h b/wifi/1.3/default/tests/mock_wifi_iface_util.h index 6fb8f712d3..87ab5db412 100644 --- a/wifi/1.3/default/tests/mock_wifi_iface_util.h +++ b/wifi/1.3/default/tests/mock_wifi_iface_util.h @@ -35,6 +35,7 @@ class MockWifiIfaceUtil : public WifiIfaceUtil { std::array(const std::string&)); MOCK_METHOD2(setMacAddress, bool(const std::string&, const std::array&)); + MOCK_METHOD0(getOrCreateRandomMacAddress, std::array()); }; } // namespace iface_util } // namespace implementation diff --git a/wifi/1.3/default/tests/wifi_ap_iface_unit_tests.cpp b/wifi/1.3/default/tests/wifi_ap_iface_unit_tests.cpp new file mode 100644 index 0000000000..28e028b675 --- /dev/null +++ b/wifi/1.3/default/tests/wifi_ap_iface_unit_tests.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2019, 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 +#include +#include +#include + +#undef NAN // This is weird, NAN is defined in bionic/libc/include/math.h:38 +#include "wifi_ap_iface.h" + +#include "mock_wifi_feature_flags.h" +#include "mock_wifi_iface_util.h" +#include "mock_wifi_legacy_hal.h" + +using testing::NiceMock; +using testing::Return; +using testing::Test; + +namespace { +constexpr char kIfaceName[] = "mockWlan0"; +} // namespace + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { + +class WifiApIfaceTest : public Test { + protected: + std::shared_ptr> legacy_hal_{ + new NiceMock}; + std::shared_ptr> iface_util_{ + new NiceMock}; + std::shared_ptr> + feature_flags_{new NiceMock}; +}; + +TEST_F(WifiApIfaceTest, SetRandomMacAddressIfFeatureEnabled) { + EXPECT_CALL(*feature_flags_, isApMacRandomizationDisabled()) + .WillOnce(testing::Return(false)); + EXPECT_CALL(*iface_util_, getOrCreateRandomMacAddress()) + .WillOnce(testing::Return(std::array{0, 0, 0, 0, 0, 0})); + EXPECT_CALL(*iface_util_, setMacAddress(testing::_, testing::_)) + .WillOnce(testing::Return(true)); + sp ap_iface = + new WifiApIface(kIfaceName, legacy_hal_, iface_util_, feature_flags_); +} + +TEST_F(WifiApIfaceTest, DontSetRandomMacAddressIfFeatureDisabled) { + EXPECT_CALL(*feature_flags_, isApMacRandomizationDisabled()) + .WillOnce(testing::Return(true)); + EXPECT_CALL(*iface_util_, getOrCreateRandomMacAddress()).Times(0); + EXPECT_CALL(*iface_util_, setMacAddress(testing::_, testing::_)).Times(0); + sp ap_iface = + new WifiApIface(kIfaceName, legacy_hal_, iface_util_, feature_flags_); +} +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.3/default/wifi_ap_iface.cpp b/wifi/1.3/default/wifi_ap_iface.cpp index 025ece3158..9a8681afed 100644 --- a/wifi/1.3/default/wifi_ap_iface.cpp +++ b/wifi/1.3/default/wifi_ap_iface.cpp @@ -31,11 +31,26 @@ using hidl_return_util::validateAndCall; WifiApIface::WifiApIface( const std::string& ifname, const std::weak_ptr legacy_hal, - const std::weak_ptr iface_util) + const std::weak_ptr iface_util, + const std::weak_ptr feature_flags) : ifname_(ifname), legacy_hal_(legacy_hal), iface_util_(iface_util), - is_valid_(true) {} + feature_flags_(feature_flags), + is_valid_(true) { + if (feature_flags_.lock()->isApMacRandomizationDisabled()) { + LOG(INFO) << "AP MAC randomization disabled"; + return; + } + LOG(INFO) << "AP MAC randomization enabled"; + // Set random MAC address + std::array randomized_mac = + iface_util_.lock()->getOrCreateRandomMacAddress(); + bool status = iface_util_.lock()->setMacAddress(ifname_, randomized_mac); + if (!status) { + LOG(ERROR) << "Failed to set random mac address"; + } +} void WifiApIface::invalidate() { legacy_hal_.reset(); diff --git a/wifi/1.3/default/wifi_ap_iface.h b/wifi/1.3/default/wifi_ap_iface.h index 6dbfc18a33..98c5c9c376 100644 --- a/wifi/1.3/default/wifi_ap_iface.h +++ b/wifi/1.3/default/wifi_ap_iface.h @@ -20,8 +20,8 @@ #include #include +#include "wifi_feature_flags.h" #include "wifi_iface_util.h" - #include "wifi_legacy_hal.h" namespace android { @@ -36,9 +36,11 @@ using namespace android::hardware::wifi::V1_0; */ class WifiApIface : public V1_0::IWifiApIface { public: - WifiApIface(const std::string& ifname, - const std::weak_ptr legacy_hal, - const std::weak_ptr iface_util); + WifiApIface( + const std::string& ifname, + const std::weak_ptr legacy_hal, + const std::weak_ptr iface_util, + const std::weak_ptr feature_flags); // Refer to |WifiChip::invalidate()|. void invalidate(); bool isValid(); @@ -63,6 +65,7 @@ class WifiApIface : public V1_0::IWifiApIface { std::string ifname_; std::weak_ptr legacy_hal_; std::weak_ptr iface_util_; + std::weak_ptr feature_flags_; bool is_valid_; DISALLOW_COPY_AND_ASSIGN(WifiApIface); diff --git a/wifi/1.3/default/wifi_chip.cpp b/wifi/1.3/default/wifi_chip.cpp index 9640a61a85..906f14a1c9 100644 --- a/wifi/1.3/default/wifi_chip.cpp +++ b/wifi/1.3/default/wifi_chip.cpp @@ -777,7 +777,8 @@ std::pair> WifiChip::createApIfaceInternal() { return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; } std::string ifname = allocateApOrStaIfaceName(); - sp iface = new WifiApIface(ifname, legacy_hal_, iface_util_); + sp iface = + new WifiApIface(ifname, legacy_hal_, iface_util_, feature_flags_); ap_ifaces_.push_back(iface); for (const auto& callback : event_cb_handler_.getCallbacks()) { if (!callback->onIfaceAdded(IfaceType::AP, ifname).isOk()) { diff --git a/wifi/1.3/default/wifi_feature_flags.cpp b/wifi/1.3/default/wifi_feature_flags.cpp index 17b3bee01c..7212cfac3c 100644 --- a/wifi/1.3/default/wifi_feature_flags.cpp +++ b/wifi/1.3/default/wifi_feature_flags.cpp @@ -144,12 +144,22 @@ static const std::vector kChipModes{ #undef P2P #undef NAN +#ifdef WIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION +static const bool wifiHidlFeatureDisableApMacRandomization = true; +#else +static const bool wifiHidlFeatureDisableApMacRandomization = false; +#endif // WIFI_HIDL_FEATURE_DISABLE_AP + WifiFeatureFlags::WifiFeatureFlags() {} std::vector WifiFeatureFlags::getChipModes() { return kChipModes; } +bool WifiFeatureFlags::isApMacRandomizationDisabled() { + return wifiHidlFeatureDisableApMacRandomization; +} + } // namespace feature_flags } // namespace implementation } // namespace V1_3 diff --git a/wifi/1.3/default/wifi_feature_flags.h b/wifi/1.3/default/wifi_feature_flags.h index b99a4166b5..3ae6920907 100644 --- a/wifi/1.3/default/wifi_feature_flags.h +++ b/wifi/1.3/default/wifi_feature_flags.h @@ -43,6 +43,7 @@ class WifiFeatureFlags { virtual ~WifiFeatureFlags() = default; virtual std::vector getChipModes(); + virtual bool isApMacRandomizationDisabled(); }; } // namespace feature_flags diff --git a/wifi/1.3/default/wifi_iface_util.cpp b/wifi/1.3/default/wifi_iface_util.cpp index 39fa1e8b6d..164aca73a0 100644 --- a/wifi/1.3/default/wifi_iface_util.cpp +++ b/wifi/1.3/default/wifi_iface_util.cpp @@ -27,7 +27,7 @@ namespace V1_3 { namespace implementation { namespace iface_util { -WifiIfaceUtil::WifiIfaceUtil() {} +WifiIfaceUtil::WifiIfaceUtil() : random_mac_address_(nullptr) {} std::array WifiIfaceUtil::getFactoryMacAddress( const std::string& iface_name) { @@ -52,6 +52,19 @@ bool WifiIfaceUtil::setMacAddress(const std::string& iface_name, return true; } +std::array WifiIfaceUtil::getOrCreateRandomMacAddress() { + if (random_mac_address_) { + return *random_mac_address_.get(); + } + random_mac_address_ = + std::make_unique>(createRandomMacAddress()); + return *random_mac_address_.get(); +} + +std::array WifiIfaceUtil::createRandomMacAddress() { + // TODO: Generate random MAC address here. + return {}; +} } // namespace iface_util } // namespace implementation } // namespace V1_3 diff --git a/wifi/1.3/default/wifi_iface_util.h b/wifi/1.3/default/wifi_iface_util.h index 9495322f7d..b2382344ed 100644 --- a/wifi/1.3/default/wifi_iface_util.h +++ b/wifi/1.3/default/wifi_iface_util.h @@ -40,9 +40,16 @@ class WifiIfaceUtil { const std::string& iface_name); virtual bool setMacAddress(const std::string& iface_name, const std::array& mac); + // Get or create a random MAC address. The MAC address returned from + // this method will remain the same throughout the lifetime of the HAL + // daemon. (So, changes on every reboot) + virtual std::array getOrCreateRandomMacAddress(); private: + std::array createRandomMacAddress(); + wifi_system::InterfaceTool iface_tool_; + std::unique_ptr> random_mac_address_; }; } // namespace iface_util From c4446793d189349d3a9920c9e2a47a8de28bebea Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Thu, 14 Feb 2019 13:20:39 -0800 Subject: [PATCH 502/718] wifi(implementation): Generate randomized mac address Generate random MAC address on the first creation of AP iface after reboot. Bug: 78353419 Test: ./hardware/interfaces/wifi/1.3/default/tests/runtests.sh Test: Manually verified that the AP MAC address & BSSID changes on every reboot. Change-Id: Ie9984ec72b2dfec9b7de7a9ef33b9e9ebfaf945c --- wifi/1.3/default/Android.mk | 3 +- .../tests/wifi_iface_util_unit_tests.cpp | 58 +++++++++++++++++++ wifi/1.3/default/wifi_iface_util.cpp | 27 ++++++++- 3 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 wifi/1.3/default/tests/wifi_iface_util_unit_tests.cpp diff --git a/wifi/1.3/default/Android.mk b/wifi/1.3/default/Android.mk index 7ebea4f4d1..199ea3b9f8 100644 --- a/wifi/1.3/default/Android.mk +++ b/wifi/1.3/default/Android.mk @@ -148,7 +148,8 @@ LOCAL_SRC_FILES := \ tests/mock_wifi_mode_controller.cpp \ tests/ringbuffer_unit_tests.cpp \ tests/wifi_ap_iface_unit_tests.cpp \ - tests/wifi_chip_unit_tests.cpp + tests/wifi_chip_unit_tests.cpp \ + tests/wifi_iface_util_unit_tests.cpp LOCAL_STATIC_LIBRARIES := \ libgmock \ libgtest \ diff --git a/wifi/1.3/default/tests/wifi_iface_util_unit_tests.cpp b/wifi/1.3/default/tests/wifi_iface_util_unit_tests.cpp new file mode 100644 index 0000000000..e5758facdb --- /dev/null +++ b/wifi/1.3/default/tests/wifi_iface_util_unit_tests.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2019, 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 +#include +#include + +#undef NAN +#include "wifi_iface_util.h" + +using testing::Test; + +namespace { +constexpr uint8_t kValidUnicastLocallyAssignedMacAddressMask = 0x02; + +bool isValidUnicastLocallyAssignedMacAddress( + const std::array& mac_address) { + uint8_t first_byte = mac_address[0]; + return (first_byte & 0x3) == kValidUnicastLocallyAssignedMacAddressMask; +} +} // namespace + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +class WifiIfaceUtilTest : public Test { + protected: + iface_util::WifiIfaceUtil iface_util_; +}; + +TEST_F(WifiIfaceUtilTest, GetOrCreateRandomMacAddress) { + auto mac_address = iface_util_.getOrCreateRandomMacAddress(); + ASSERT_TRUE(isValidUnicastLocallyAssignedMacAddress(mac_address)); + + // All further calls should return the same MAC address. + ASSERT_EQ(mac_address, iface_util_.getOrCreateRandomMacAddress()); + ASSERT_EQ(mac_address, iface_util_.getOrCreateRandomMacAddress()); +} +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.3/default/wifi_iface_util.cpp b/wifi/1.3/default/wifi_iface_util.cpp index 164aca73a0..5d61271410 100644 --- a/wifi/1.3/default/wifi_iface_util.cpp +++ b/wifi/1.3/default/wifi_iface_util.cpp @@ -14,12 +14,24 @@ * limitations under the License. */ +#include +#include +#include +#include + #include #include #include +#undef NAN #include "wifi_iface_util.h" +namespace { +// Constants to set the local bit & clear the multicast bit. +constexpr uint8_t kMacAddressMulticastMask = 0x01; +constexpr uint8_t kMacAddressLocallyAssignedMask = 0x02; +} // namespace + namespace android { namespace hardware { namespace wifi { @@ -62,8 +74,19 @@ std::array WifiIfaceUtil::getOrCreateRandomMacAddress() { } std::array WifiIfaceUtil::createRandomMacAddress() { - // TODO: Generate random MAC address here. - return {}; + std::array address = {}; + std::random_device rd; + std::default_random_engine engine(rd()); + std::uniform_int_distribution dist( + std::numeric_limits::min(), + std::numeric_limits::max()); + for (size_t i = 0; i < address.size(); i++) { + address[i] = dist(engine); + } + // Set the local bit and clear the multicast bit. + address[0] |= kMacAddressLocallyAssignedMask; + address[0] &= ~kMacAddressMulticastMask; + return address; } } // namespace iface_util } // namespace implementation From 9442dd481b195a3be0e167a5132cad5b5853c9d8 Mon Sep 17 00:00:00 2001 From: Changyeon Jo Date: Tue, 26 Feb 2019 17:52:40 +0000 Subject: [PATCH 503/718] Creates OWNERS for evs interface Creates OWNERS file and adds default reviewers. Bug: 126256874 Test: gerrit uploader Change-Id: I33814c54d79ac5c6356ab3ce9e9ee3e01391e800 Signed-off-by: Changyeon Jo --- automotive/evs/OWNERS | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 automotive/evs/OWNERS diff --git a/automotive/evs/OWNERS b/automotive/evs/OWNERS new file mode 100644 index 0000000000..fec2a3ad33 --- /dev/null +++ b/automotive/evs/OWNERS @@ -0,0 +1,3 @@ +changyeon@google.com +haoxiangl@google.com +swan@google.com From 0d74a22d26cecf39cad66c310073601b9b2bcbbe Mon Sep 17 00:00:00 2001 From: Nazanin Bakhshi Date: Tue, 26 Feb 2019 11:47:54 -0800 Subject: [PATCH 504/718] Fix doc on getModemStackStatus Bug: 123958093 Test: build Change-Id: I29eec2851b08c79463fe55788ffa3bc83c204863 --- current.txt | 2 +- radio/1.3/IRadio.hal | 11 ++++------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/current.txt b/current.txt index 4aa8c1dd87..081e5299a8 100644 --- a/current.txt +++ b/current.txt @@ -513,7 +513,7 @@ cf7a4ba516a638f9b82a249c91fb603042c2d9ca43fd5aad9cf6c0401ed2a5d7 android.hardwar abf98c2ae08bf765db54edc8068e36d52eb558cff6706b6fd7c18c65a1f3fc18 android.hardware.nfc@1.2::types 4cb252dc6372a874aef666b92a6e9529915aa187521a700f0789065c3c702ead android.hardware.power.stats@1.0::IPowerStats 2043037d5baaff604805757d06979aa861013a1e87430db745265339a8681f79 android.hardware.power.stats@1.0::types -11620ce020b6ef8f5b63eb2a39390de4a2fbbccc0a5e558b5b1a0e22e33f63cf android.hardware.radio@1.3::IRadio +d5545a4090e5cf8b7f844121377d580926cb9137d693d8c66772ef99ca23e514 android.hardware.radio@1.3::IRadio e9d0f11a52715f5a29d89e2d8e2e21db1e16a43174af6b9d51a62d705cda1455 android.hardware.radio@1.3::IRadioIndication d233f0da44f55fdef0a95db5229231412787bb67695cd1ea197ce89a3c2908b9 android.hardware.radio@1.3::IRadioResponse 750a363c8cec70baa1aac19e275c15233c5898e93c6bb5155fa2ca7f365490dc android.hardware.radio@1.3::types diff --git a/radio/1.3/IRadio.hal b/radio/1.3/IRadio.hal index cc5b8605bc..95cf6151a5 100644 --- a/radio/1.3/IRadio.hal +++ b/radio/1.3/IRadio.hal @@ -49,10 +49,8 @@ interface IRadio extends @1.2::IRadio { vec specifiers); /** - * Toggle logical modem on and off. It should put the logical modem in low power - * mode without any activity, while the SIM card remains visible. The difference - * with setRadioPower is, setRadioPower affects all logical modem while this controls - * just one. + * Toggle logical modem on and off. The difference with setRadioPower is, + * setRadioPower affects all logical modems while this controls just one. * * @param serial Serial number of request. * @param on True to turn on the logical modem, otherwise turn it off. @@ -62,9 +60,8 @@ interface IRadio extends @1.2::IRadio { oneway enableModem(int32_t serial, bool on); /** - * Request status of logical modem associated with the given serial number. It returns - * isEnabled=true if the logical modem is in low power mode without any activity, while - * the SIM card remains visible. + * Request status of logical modem. It returns isEnabled=true if the logical modem is on. + * This method is the getter method for enableModem. * * @param serial Serial number of request. * From 53cc4ffafce445838a95182ac4167977882fdfdf Mon Sep 17 00:00:00 2001 From: Kai Date: Mon, 7 Jan 2019 14:42:50 -0800 Subject: [PATCH 505/718] Add and update VHAL Properties and permissions Add and update VHAL properties and permissions. Bug: 112435211, 120095752 Test: build and run on HAWK Change-Id: Ia750a472e0185a6f858d23e638c535f67bc86c00 (cherry picked from commit fa638809675178b2f517f02b85bd372b47c08cf2) --- automotive/vehicle/2.0/types.hal | 186 ++++++++++++++++++++++++++++++- 1 file changed, 185 insertions(+), 1 deletion(-) diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal index e874146edf..3efaaec804 100644 --- a/automotive/vehicle/2.0/types.hal +++ b/automotive/vehicle/2.0/types.hal @@ -282,7 +282,6 @@ enum VehicleProperty : int32_t { | VehiclePropertyType:INT32 | VehicleArea:SEAT), - /** * Current odometer value of the vehicle * @@ -1112,6 +1111,91 @@ enum VehicleProperty : int32_t { | VehiclePropertyType:INT32 | VehicleArea:SEAT), + /** + * Distance units for display + * + * Indicates which units the car is using to display distances to the user. Eg. Mile, Meter + * Kilometer. + * + * Distance units are defined in VehicleUnit. + * VehiclePropConfig.configArray is used to indicate the supported distance display units. + * For example: configArray[0] = 0x21 // METER + * configArray[1] = 0x23 // KILOMETER + * configArray[2] = 0x24 // MILE + * @change_mode VehiclePropertyChangeMode:ON_CHANGE + * @access VehiclePropertyAccess:READ_WRITE + * @data_enum VehicleUnit + */ + DISTANCE_DISPLAY_UNITS = ( + 0x0600 + | VehiclePropertyGroup:SYSTEM + | VehiclePropertyType:INT32 + | VehicleArea:GLOBAL), + + /** + * Fuel volume units for display + * + * Indicates which units the car is using to display fuel volume to the user. Eg. Liter or + * Gallon. + * + * Distance units are defined in VehicleUnit. + * VehiclePropConfig.configArray is used to indicate the supported fuel volume display units. + * Volume units are defined in VehicleUnit. + * For example: configArray[0] = 0x41 // LITER + * configArray[1] = 0x42 // GALLON + * @change_mode VehiclePropertyChangeMode:ON_CHANGE + * @access VehiclePropertyAccess:READ_WRITE + * @data_enum VehicleUnit + */ + FUEL_VOLUME_DISPLAY_UNITS = ( + 0x0601 + | VehiclePropertyGroup:SYSTEM + | VehiclePropertyType:INT32 + | VehicleArea:GLOBAL), + + /** + * Tire pressure units for display + * + * Indicates which units the car is using to display tire pressure to the user. Eg. PSI, Bar or + * Kilopascal. + * + * Distance units are defined in VehicleUnit. + * VehiclePropConfig.configArray is used to indicate the supported pressure display units. + * Pressure units are defined in VehicleUnit. + * For example: configArray[0] = 0x70 // KILOPASCAL + * configArray[1] = 0x71 // PSI + * configArray[2] = 0x72 // BAR + * @change_mode VehiclePropertyChangeMode:ON_CHANGE + * @access VehiclePropertyAccess:READ_WRITE + * @data_enum VehicleUnit + */ + TIRE_PRESSURE_DISPLAY_UNITS = ( + 0x0602 + | VehiclePropertyGroup:SYSTEM + | VehiclePropertyType:INT32 + | VehicleArea:GLOBAL), + + /** + * EV battery units for display + * + * Indicates which units the car is using to display EV battery information to the user. Eg. + * watt-hours(Wh), kilowatt-hours(kWh) or ampere-hours(Ah). + * + * Distance units are defined in VehicleUnit. + * VehiclePropConfig.configArray is used to indicate the supported electrical energy units. + * Electrical energy units are defined in VehicleUnit. + * For example: configArray[0] = 0x60 // watt-hours + * configArray[1] = 0x64 // ampere-hours + * configArray[2] = 0x65 // kilowatt-hours + * @change_mode VehiclePropertyChangeMode:ON_CHANGE + * @access VehiclePropertyAccess:READ_WRITE + * @data_enum VehicleUnit + */ + EV_BATTERY_DISPLAY_UNITS = ( + 0x0603 + | VehiclePropertyGroup:SYSTEM + | VehiclePropertyType:INT32 + | VehicleArea:GLOBAL), /** * Outside temperature @@ -1778,6 +1862,22 @@ enum VehicleProperty : int32_t { | VehiclePropertyType:INT32 | VehicleArea:SEAT), + /** + * Seat Occupancy + * + * Indicates whether a particular seat is occupied or not, to the best of the car's ability + * to determine. Valid values are from the VehicleSeatOccupancyState enum. + * + * @change_mode VehiclePropertyChangeMode:ON_CHANGE + * @access VehiclePropertyAccess:READ + * @data_enum VehicleSeatOccupancyState + */ + SEAT_OCCUPANCY = ( + 0x0BB0 + | VehiclePropertyGroup:SYSTEM + | VehiclePropertyType:INT32 + | VehicleArea:SEAT), + /** * Window Position * @@ -2113,6 +2213,83 @@ enum VehicleProperty : int32_t { | VehiclePropertyGroup:SYSTEM | VehiclePropertyType:INT32 | VehicleArea:GLOBAL), + + /** + * Cabin lights + * + * Return current status of cabin lights. + * + * @change_mode VehiclePropertyChangeMode:ON_CHANGE + * @access VehiclePropertyAccess:READ + * @data_enum VehicleLightState + */ + CABIN_LIGHTS_STATE = ( + 0x0F01 + | VehiclePropertyGroup:SYSTEM + | VehiclePropertyType:INT32 + | VehicleArea:GLOBAL), + + /** + * Cabin lights switch + * + * The position of the physical switch which controls the cabin lights. + * This might be different than the CABIN_LIGHTS_STATE if the lights are on because a door + * is open or because of a voice command. + * For example, while the switch is in the "off" or "automatic" position. + * + * @change_mode VehiclePropertyChangeMode:ON_CHANGE + * @access VehiclePropertyAccess:READ_WRITE + * @data_enum VehicleLightSwitch + */ + CABIN_LIGHTS_SWITCH = ( + 0x0F02 + | VehiclePropertyGroup:SYSTEM + | VehiclePropertyType:INT32 + | VehicleArea:GLOBAL), + + /** + * Reading lights + * + * Return current status of reading lights. + * + * @change_mode VehiclePropertyChangeMode:ON_CHANGE + * @access VehiclePropertyAccess:READ + * @data_enum VehicleLightState + */ + READING_LIGHTS_STATE = ( + 0x0F03 + | VehiclePropertyGroup:SYSTEM + | VehiclePropertyType:INT32 + | VehicleArea:SEAT), + + /** + * Reading lights switch + * + * The position of the physical switch which controls the reading lights. + * This might be different than the READING_LIGHTS_STATE if the lights are on because a door + * is open or because of a voice command. + * For example, while the switch is in the "off" or "automatic" position. + * + * @change_mode VehiclePropertyChangeMode:ON_CHANGE + * @access VehiclePropertyAccess:READ_WRITE + * @data_enum VehicleLightSwitch + */ + READING_LIGHTS_SWITCH = ( + 0x0F04 + | VehiclePropertyGroup:SYSTEM + | VehiclePropertyType:INT32 + | VehicleArea:SEAT), + +}; + +/** + * Used by seat occupancy to enumerate the current occupancy state of the seat. + */ +enum VehicleSeatOccupancyState : int32_t { + + UNKNOWN = 0, + VACANT = 1, + OCCUPIED = 2 }; /** @@ -2404,10 +2581,13 @@ enum VehicleUnit : int32_t { MILLIMETER = 0x20, METER = 0x21, KILOMETER = 0x23, + MILE = 0x24, CELSIUS = 0x30, FAHRENHEIT = 0x31, KELVIN = 0x32, MILLILITER = 0x40, + LITER = 0x41, + GALLON = 0x42, NANO_SECS = 0x50, SECS = 0x53, YEAR = 0x59, @@ -2417,8 +2597,12 @@ enum VehicleUnit : int32_t { MILLIAMPERE = 0x61, MILLIVOLT = 0x62, MILLIWATTS = 0x63, + AMPERE_HOURS = 0x64, + KILOWATT_HOUR = 0x65, KILOPASCAL = 0x70, + PSI = 0x71, + BAR = 0x72, DEGREES = 0x80, }; From e64a2288617bbf8ae3b2beb909af7bbfeed0870d Mon Sep 17 00:00:00 2001 From: Sundong Ahn Date: Fri, 22 Feb 2019 11:52:42 +0900 Subject: [PATCH 506/718] Remove configstore 1.2 the configstore functionality was added in Q. But The configstore will be deleted. So additional function is deleted. Bug: 124531214 Test: build & boot Test: adb shell lshal | grep configstore & check configstore 1.2 Change-Id: Idbb00b972bc082bd75bba94dbff9cee19df48b89 --- CleanSpec.mk | 8 + configstore/{1.2 => 1.1}/default/Android.mk | 13 +- .../default/SurfaceFlingerConfigs.cpp | 146 +-------------- .../default/SurfaceFlingerConfigs.h | 19 +- ...droid.hardware.configstore@1.1-service.rc} | 2 +- .../configstore@1.1-arm64.policy} | 0 configstore/{1.2 => 1.1}/default/service.cpp | 10 +- configstore/1.1/default/surfaceflinger.mk | 56 ++++++ configstore/1.2/Android.bp | 27 --- configstore/1.2/ISurfaceFlingerConfigs.hal | 79 -------- configstore/1.2/default/surfaceflinger.mk | 124 ------------- configstore/1.2/types.hal | 28 --- configstore/1.2/vts/functional/Android.bp | 27 --- configstore/1.2/vts/functional/OWNERS | 7 - .../VtsHalConfigstoreV1_2TargetTest.cpp | 174 ------------------ configstore/utils/Android.bp | 2 - current.txt | 2 - 17 files changed, 90 insertions(+), 634 deletions(-) rename configstore/{1.2 => 1.1}/default/Android.mk (70%) rename configstore/{1.2 => 1.1}/default/SurfaceFlingerConfigs.cpp (55%) rename configstore/{1.2 => 1.1}/default/SurfaceFlingerConfigs.h (76%) rename configstore/{1.2/default/android.hardware.configstore@1.2-service.rc => 1.1/default/android.hardware.configstore@1.1-service.rc} (84%) rename configstore/{1.2/default/seccomp_policy/configstore-arm64.policy => 1.1/default/seccomp_policy/configstore@1.1-arm64.policy} (100%) rename configstore/{1.2 => 1.1}/default/service.cpp (80%) create mode 100644 configstore/1.1/default/surfaceflinger.mk delete mode 100644 configstore/1.2/Android.bp delete mode 100644 configstore/1.2/ISurfaceFlingerConfigs.hal delete mode 100644 configstore/1.2/default/surfaceflinger.mk delete mode 100644 configstore/1.2/types.hal delete mode 100644 configstore/1.2/vts/functional/Android.bp delete mode 100644 configstore/1.2/vts/functional/OWNERS delete mode 100644 configstore/1.2/vts/functional/VtsHalConfigstoreV1_2TargetTest.cpp diff --git a/CleanSpec.mk b/CleanSpec.mk index 1af439a97e..edde1cbd33 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -72,3 +72,11 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/init/android.hardware.co $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/bin/hw/android.hardware.cas@1.0*) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/init/android.hardware.cas@1.0*) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/vintf/manifest/android.hardware.cas@1.0*) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/init/android.hardware.configstore@1.2-service.rc) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/bin/hw/android.hardware.configstore@1.2-service) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/seccomp_policy/configstore.policy) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/apex/com.android.media.swcodec/lib64/android.hardware.configstore@1.2.so) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib64/vndk-Q/android.hardware.configstore@1.2.so) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib64/android.hardware.configstore@1.2.so) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/vndk-Q/android.hardware.configstore@1.2.so) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/android.hardware.configstore@1.2.so) diff --git a/configstore/1.2/default/Android.mk b/configstore/1.1/default/Android.mk similarity index 70% rename from configstore/1.2/default/Android.mk rename to configstore/1.1/default/Android.mk index b807357876..104e15eee2 100644 --- a/configstore/1.2/default/Android.mk +++ b/configstore/1.1/default/Android.mk @@ -2,15 +2,15 @@ LOCAL_PATH := $(call my-dir) ################################################################################ include $(CLEAR_VARS) -LOCAL_MODULE := android.hardware.configstore@1.2-service +LOCAL_MODULE := android.hardware.configstore@1.1-service # seccomp is not required for coverage build. ifneq ($(NATIVE_COVERAGE),true) -LOCAL_REQUIRED_MODULES_arm64 := configstore.policy +LOCAL_REQUIRED_MODULES_arm64 := configstore@1.1.policy endif LOCAL_VENDOR_MODULE := true LOCAL_MODULE_CLASS := EXECUTABLES LOCAL_MODULE_RELATIVE_PATH := hw -LOCAL_INIT_RC := android.hardware.configstore@1.2-service.rc +LOCAL_INIT_RC := android.hardware.configstore@1.1-service.rc LOCAL_SRC_FILES:= service.cpp include $(LOCAL_PATH)/surfaceflinger.mk @@ -23,17 +23,16 @@ LOCAL_SHARED_LIBRARIES := \ liblog \ libutils \ android.hardware.configstore@1.0 \ - android.hardware.configstore@1.1 \ - android.hardware.configstore@1.2 + android.hardware.configstore@1.1 include $(BUILD_EXECUTABLE) # seccomp filter for configstore ifeq ($(TARGET_ARCH), $(filter $(TARGET_ARCH), arm64)) include $(CLEAR_VARS) -LOCAL_MODULE := configstore.policy +LOCAL_MODULE := configstore@1.1.policy LOCAL_MODULE_CLASS := ETC LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc/seccomp_policy -LOCAL_SRC_FILES := seccomp_policy/configstore-$(TARGET_ARCH).policy +LOCAL_SRC_FILES := seccomp_policy/configstore@1.1-$(TARGET_ARCH).policy include $(BUILD_PREBUILT) endif diff --git a/configstore/1.2/default/SurfaceFlingerConfigs.cpp b/configstore/1.1/default/SurfaceFlingerConfigs.cpp similarity index 55% rename from configstore/1.2/default/SurfaceFlingerConfigs.cpp rename to configstore/1.1/default/SurfaceFlingerConfigs.cpp index 714442bd22..377e467864 100644 --- a/configstore/1.2/default/SurfaceFlingerConfigs.cpp +++ b/configstore/1.1/default/SurfaceFlingerConfigs.cpp @@ -17,19 +17,14 @@ #include "SurfaceFlingerConfigs.h" #include -#include -#include #include namespace android { namespace hardware { namespace configstore { -namespace V1_2 { +namespace V1_1 { namespace implementation { -using ::android::hardware::graphics::common::V1_2::Dataspace; -using ::android::hardware::graphics::common::V1_2::PixelFormat; - // ::android::hardware::configstore::V1_0::ISurfaceFlingerConfigs implementation. Return SurfaceFlingerConfigs::vsyncEventPhaseOffsetNs(vsyncEventPhaseOffsetNs_cb _hidl_cb) { #ifdef VSYNC_EVENT_PHASE_OFFSET_NS @@ -59,7 +54,7 @@ Return SurfaceFlingerConfigs::useContextPriority(useContextPriority_cb _hi } Return SurfaceFlingerConfigs::maxFrameBufferAcquiredBuffers( - maxFrameBufferAcquiredBuffers_cb _hidl_cb) { + maxFrameBufferAcquiredBuffers_cb _hidl_cb) { #ifdef NUM_FRAMEBUFFER_SURFACE_BUFFERS _hidl_cb({true, NUM_FRAMEBUFFER_SURFACE_BUFFERS}); #else @@ -96,7 +91,7 @@ Return SurfaceFlingerConfigs::hasHDRDisplay(hasHDRDisplay_cb _hidl_cb) { } Return SurfaceFlingerConfigs::presentTimeOffsetFromVSyncNs( - presentTimeOffsetFromVSyncNs_cb _hidl_cb) { + presentTimeOffsetFromVSyncNs_cb _hidl_cb) { #ifdef PRESENT_TIME_OFFSET_FROM_VSYNC_NS _hidl_cb({true, PRESENT_TIME_OFFSET_FROM_VSYNC_NS}); #else @@ -137,7 +132,7 @@ Return SurfaceFlingerConfigs::useVrFlinger(useVrFlinger_cb _hidl_cb) { } Return SurfaceFlingerConfigs::startGraphicsAllocatorService( - startGraphicsAllocatorService_cb _hidl_cb) { + startGraphicsAllocatorService_cb _hidl_cb) { bool value = false; #ifdef START_GRAPHICS_ALLOCATOR_SERVICE value = true; @@ -150,12 +145,12 @@ Return SurfaceFlingerConfigs::startGraphicsAllocatorService( #ifdef PRIMARY_DISPLAY_ORIENTATION static_assert(PRIMARY_DISPLAY_ORIENTATION == 0 || PRIMARY_DISPLAY_ORIENTATION == 90 || - PRIMARY_DISPLAY_ORIENTATION == 180 || PRIMARY_DISPLAY_ORIENTATION == 270, + PRIMARY_DISPLAY_ORIENTATION == 180 || PRIMARY_DISPLAY_ORIENTATION == 270, "Primary display orientation must be 0/90/180/270"); #endif Return SurfaceFlingerConfigs::primaryDisplayOrientation( - primaryDisplayOrientation_cb _hidl_cb) { + primaryDisplayOrientation_cb _hidl_cb) { using ::android::hardware::configstore::V1_1::DisplayOrientation; bool specified = false; @@ -194,135 +189,8 @@ Return SurfaceFlingerConfigs::primaryDisplayOrientation( return Void(); } -// ::android::hardware::configstore::V1_2::ISurfaceFlingerConfigs implementation. -Return SurfaceFlingerConfigs::useColorManagement(useColorManagement_cb _hidl_cb) { -#if defined(USE_COLOR_MANAGEMENT) || defined(HAS_WIDE_COLOR_DISPLAY) || defined(HAS_HDR_DISPLAY) - _hidl_cb({true, true}); -#else - _hidl_cb({true, false}); -#endif - return Void(); -} - -#ifdef DEFAULT_COMPOSITION_DATA_SPACE -static_assert(DEFAULT_COMPOSITION_DATA_SPACE != 0, - "Default composition data space must not be UNKNOWN"); -#endif - -#ifdef WCG_COMPOSITION_DATA_SPACE -static_assert(WCG_COMPOSITION_DATA_SPACE != 0, - "Wide color gamut composition data space must not be UNKNOWN"); -#endif - -Return SurfaceFlingerConfigs::getCompositionPreference(getCompositionPreference_cb _hidl_cb) { - Dataspace defaultDataspace = Dataspace::V0_SRGB; - PixelFormat defaultPixelFormat = PixelFormat::RGBA_8888; - -#ifdef DEFAULT_COMPOSITION_DATA_SPACE - defaultDataspace = static_cast(DEFAULT_COMPOSITION_DATA_SPACE); -#endif - -#ifdef DEFAULT_COMPOSITION_PIXEL_FORMAT - defaultPixelFormat = static_cast(DEFAULT_COMPOSITION_PIXEL_FORMAT); -#endif - - Dataspace wideColorGamutDataspace = Dataspace::V0_SRGB; - PixelFormat wideColorGamutPixelFormat = PixelFormat::RGBA_8888; - -#ifdef WCG_COMPOSITION_DATA_SPACE - wideColorGamutDataspace = static_cast(WCG_COMPOSITION_DATA_SPACE); -#endif - -#ifdef WCG_COMPOSITION_PIXEL_FORMAT - wideColorGamutPixelFormat = static_cast(WCG_COMPOSITION_PIXEL_FORMAT); -#endif - - _hidl_cb(defaultDataspace, defaultPixelFormat, wideColorGamutDataspace, - wideColorGamutPixelFormat); - return Void(); -} - -Return SurfaceFlingerConfigs::getDisplayNativePrimaries(getDisplayNativePrimaries_cb _hidl_cb) { - DisplayPrimaries primaries; - // The default XYZ is sRGB gamut in CIE1931 color space -#ifdef TARGET_DISPLAY_PRIMARY_RED_X - primaries.red.X = TARGET_DISPLAY_PRIMARY_RED_X; -#else - primaries.red.X = 0.4123; -#endif - -#ifdef TARGET_DISPLAY_PRIMARY_RED_Y - primaries.red.Y = TARGET_DISPLAY_PRIMARY_RED_Y; -#else - primaries.red.Y = 0.2126; -#endif - -#ifdef TARGET_DISPLAY_PRIMARY_RED_Z - primaries.red.Z = TARGET_DISPLAY_PRIMARY_RED_Z; -#else - primaries.red.Z = 0.0193; -#endif - -#ifdef TARGET_DISPLAY_PRIMARY_GREEN_X - primaries.green.X = TARGET_DISPLAY_PRIMARY_GREEN_X; -#else - primaries.green.X = 0.3576; -#endif - -#ifdef TARGET_DISPLAY_PRIMARY_GREEN_Y - primaries.green.Y = TARGET_DISPLAY_PRIMARY_GREEN_Y; -#else - primaries.green.Y = 0.7152; -#endif - -#ifdef TARGET_DISPLAY_PRIMARY_GREEN_Z - primaries.green.Z = TARGET_DISPLAY_PRIMARY_GREEN_Z; -#else - primaries.green.Z = 0.1192; -#endif - -#ifdef TARGET_DISPLAY_PRIMARY_BLUE_X - primaries.blue.X = TARGET_DISPLAY_PRIMARY_BLUE_X; -#else - primaries.blue.X = 0.1805; -#endif - -#ifdef TARGET_DISPLAY_PRIMARY_BLUE_Y - primaries.blue.Y = TARGET_DISPLAY_PRIMARY_BLUE_Y; -#else - primaries.blue.Y = 0.0722; -#endif - -#ifdef TARGET_DISPLAY_PRIMARY_BLUE_Z - primaries.blue.Z = TARGET_DISPLAY_PRIMARY_BLUE_Z; -#else - primaries.blue.Z = 0.9506; -#endif - -#ifdef TARGET_DISPLAY_PRIMARY_WHITE_X - primaries.white.X = TARGET_DISPLAY_PRIMARY_WHITE_X; -#else - primaries.white.X = 0.9505; -#endif - -#ifdef TARGET_DISPLAY_PRIMARY_WHITE_Y - primaries.white.Y = TARGET_DISPLAY_PRIMARY_WHITE_Y; -#else - primaries.white.Y = 1.0000; -#endif - -#ifdef TARGET_DISPLAY_PRIMARY_WHITE_Z - primaries.white.Z = TARGET_DISPLAY_PRIMARY_WHITE_Z; -#else - primaries.white.Z = 1.0891; -#endif - - _hidl_cb(primaries); - return Void(); -} - } // namespace implementation -} // namespace V1_2 +} // namespace V1_1 } // namespace configstore } // namespace hardware } // namespace android diff --git a/configstore/1.2/default/SurfaceFlingerConfigs.h b/configstore/1.1/default/SurfaceFlingerConfigs.h similarity index 76% rename from configstore/1.2/default/SurfaceFlingerConfigs.h rename to configstore/1.1/default/SurfaceFlingerConfigs.h index 54a6e6211b..c2f5fef056 100644 --- a/configstore/1.2/default/SurfaceFlingerConfigs.h +++ b/configstore/1.1/default/SurfaceFlingerConfigs.h @@ -14,23 +14,23 @@ * limitations under the License. */ -#ifndef ANDROID_HARDWARE_CONFIGSTORE_V1_2_SURFACEFLINGERCONFIGS_H -#define ANDROID_HARDWARE_CONFIGSTORE_V1_2_SURFACEFLINGERCONFIGS_H +#ifndef ANDROID_HARDWARE_CONFIGSTORE_V1_1_SURFACEFLINGERCONFIGS_H +#define ANDROID_HARDWARE_CONFIGSTORE_V1_1_SURFACEFLINGERCONFIGS_H -#include +#include #include #include namespace android { namespace hardware { namespace configstore { -namespace V1_2 { +namespace V1_1 { namespace implementation { using ::android::sp; using ::android::hardware::Return; using ::android::hardware::Void; -using ::android::hardware::configstore::V1_2::ISurfaceFlingerConfigs; +using ::android::hardware::configstore::V1_1::ISurfaceFlingerConfigs; struct SurfaceFlingerConfigs : public ISurfaceFlingerConfigs { // ::android::hardware::configstore::V1_0::ISurfaceFlingerConfigs implementation. @@ -49,17 +49,12 @@ struct SurfaceFlingerConfigs : public ISurfaceFlingerConfigs { // ::android::hardware::configstore::V1_1::ISurfaceFlingerConfigs follow implementation. Return primaryDisplayOrientation(primaryDisplayOrientation_cb _hidl_cb) override; - - // ::android::hardware::configstore::V1_2::ISurfaceFlingerConfigs follow implementation. - Return useColorManagement(useColorManagement_cb _hidl_cb) override; - Return getCompositionPreference(getCompositionPreference_cb _hidl_cb) override; - Return getDisplayNativePrimaries(getDisplayNativePrimaries_cb _hidl_cb) override; }; } // namespace implementation -} // namespace V1_2 +} // namespace V1_1 } // namespace configstore } // namespace hardware } // namespace android -#endif // ANDROID_HARDWARE_CONFIGSTORE_V1_2_SURFACEFLINGERCONFIGS_H +#endif // ANDROID_HARDWARE_CONFIGSTORE_V1_1_SURFACEFLINGERCONFIGS_H diff --git a/configstore/1.2/default/android.hardware.configstore@1.2-service.rc b/configstore/1.1/default/android.hardware.configstore@1.1-service.rc similarity index 84% rename from configstore/1.2/default/android.hardware.configstore@1.2-service.rc rename to configstore/1.1/default/android.hardware.configstore@1.1-service.rc index d6c5d10a71..105678acb2 100644 --- a/configstore/1.2/default/android.hardware.configstore@1.2-service.rc +++ b/configstore/1.1/default/android.hardware.configstore@1.1-service.rc @@ -1,4 +1,4 @@ -service vendor.configstore-hal /vendor/bin/hw/android.hardware.configstore@1.2-service +service vendor.configstore-hal /vendor/bin/hw/android.hardware.configstore@1.1-service class hal animation user system group system diff --git a/configstore/1.2/default/seccomp_policy/configstore-arm64.policy b/configstore/1.1/default/seccomp_policy/configstore@1.1-arm64.policy similarity index 100% rename from configstore/1.2/default/seccomp_policy/configstore-arm64.policy rename to configstore/1.1/default/seccomp_policy/configstore@1.1-arm64.policy diff --git a/configstore/1.2/default/service.cpp b/configstore/1.1/default/service.cpp similarity index 80% rename from configstore/1.2/default/service.cpp rename to configstore/1.1/default/service.cpp index 65a42f5955..e21de0bdce 100644 --- a/configstore/1.2/default/service.cpp +++ b/configstore/1.1/default/service.cpp @@ -14,9 +14,9 @@ * limitations under the License. */ -#define LOG_TAG "android.hardware.configstore@1.2-service" +#define LOG_TAG "android.hardware.configstore@1.1-service" -#include +#include #include #include @@ -28,13 +28,13 @@ using android::status_t; using android::hardware::configureRpcThreadpool; using android::hardware::joinRpcThreadpool; using android::hardware::SetupMinijail; -using android::hardware::configstore::V1_2::ISurfaceFlingerConfigs; -using android::hardware::configstore::V1_2::implementation::SurfaceFlingerConfigs; +using android::hardware::configstore::V1_1::ISurfaceFlingerConfigs; +using android::hardware::configstore::V1_1::implementation::SurfaceFlingerConfigs; int main() { configureRpcThreadpool(10, true); - SetupMinijail("/vendor/etc/seccomp_policy/configstore.policy"); + SetupMinijail("/vendor/etc/seccomp_policy/configstore@1.1.policy"); sp surfaceFlingerConfigs = new SurfaceFlingerConfigs; status_t status = surfaceFlingerConfigs->registerAsService(); diff --git a/configstore/1.1/default/surfaceflinger.mk b/configstore/1.1/default/surfaceflinger.mk new file mode 100644 index 0000000000..35922ebb09 --- /dev/null +++ b/configstore/1.1/default/surfaceflinger.mk @@ -0,0 +1,56 @@ + +LOCAL_SRC_FILES += SurfaceFlingerConfigs.cpp + +ifneq ($(VSYNC_EVENT_PHASE_OFFSET_NS),) + LOCAL_CFLAGS += -DVSYNC_EVENT_PHASE_OFFSET_NS=$(VSYNC_EVENT_PHASE_OFFSET_NS) +endif + +ifneq ($(SF_VSYNC_EVENT_PHASE_OFFSET_NS),) + LOCAL_CFLAGS += -DSF_VSYNC_EVENT_PHASE_OFFSET_NS=$(SF_VSYNC_EVENT_PHASE_OFFSET_NS) +endif + +ifeq ($(TARGET_USE_CONTEXT_PRIORITY),true) + LOCAL_CFLAGS += -DUSE_CONTEXT_PRIORITY=1 +endif + +ifeq ($(TARGET_HAS_WIDE_COLOR_DISPLAY),true) + LOCAL_CFLAGS += -DHAS_WIDE_COLOR_DISPLAY +endif + +ifeq ($(TARGET_HAS_HDR_DISPLAY),true) + LOCAL_CFLAGS += -DHAS_HDR_DISPLAY +endif + +ifneq ($(PRESENT_TIME_OFFSET_FROM_VSYNC_NS),) + LOCAL_CFLAGS += -DPRESENT_TIME_OFFSET_FROM_VSYNC_NS=$(PRESENT_TIME_OFFSET_FROM_VSYNC_NS) +else + LOCAL_CFLAGS += -DPRESENT_TIME_OFFSET_FROM_VSYNC_NS=0 +endif + +ifeq ($(TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS),true) + LOCAL_CFLAGS += -DFORCE_HWC_COPY_FOR_VIRTUAL_DISPLAYS +endif + +ifneq ($(MAX_VIRTUAL_DISPLAY_DIMENSION),) + LOCAL_CFLAGS += -DMAX_VIRTUAL_DISPLAY_DIMENSION=$(MAX_VIRTUAL_DISPLAY_DIMENSION) +endif + +ifeq ($(TARGET_RUNNING_WITHOUT_SYNC_FRAMEWORK),true) + LOCAL_CFLAGS += -DRUNNING_WITHOUT_SYNC_FRAMEWORK +endif + +ifneq ($(USE_VR_FLINGER),) + LOCAL_CFLAGS += -DUSE_VR_FLINGER +endif + +ifneq ($(NUM_FRAMEBUFFER_SURFACE_BUFFERS),) + LOCAL_CFLAGS += -DNUM_FRAMEBUFFER_SURFACE_BUFFERS=$(NUM_FRAMEBUFFER_SURFACE_BUFFERS) +endif + +ifneq ($(SF_START_GRAPHICS_ALLOCATOR_SERVICE),) + LOCAL_CFLAGS += -DSTART_GRAPHICS_ALLOCATOR_SERVICE +endif + +ifneq ($(SF_PRIMARY_DISPLAY_ORIENTATION),) + LOCAL_CFLAGS += -DPRIMARY_DISPLAY_ORIENTATION=$(SF_PRIMARY_DISPLAY_ORIENTATION) +endif diff --git a/configstore/1.2/Android.bp b/configstore/1.2/Android.bp deleted file mode 100644 index a3976b649f..0000000000 --- a/configstore/1.2/Android.bp +++ /dev/null @@ -1,27 +0,0 @@ -// This file is autogenerated by hidl-gen -Landroidbp. - -hidl_interface { - name: "android.hardware.configstore@1.2", - root: "android.hardware", - vndk: { - enabled: true, - }, - srcs: [ - "types.hal", - "ISurfaceFlingerConfigs.hal", - ], - interfaces: [ - "android.hardware.configstore@1.0", - "android.hardware.configstore@1.1", - "android.hardware.graphics.common@1.0", - "android.hardware.graphics.common@1.1", - "android.hardware.graphics.common@1.2", - "android.hidl.base@1.0", - ], - types: [ - "CieXyz", - "DisplayPrimaries", - ], - gen_java: true, -} - diff --git a/configstore/1.2/ISurfaceFlingerConfigs.hal b/configstore/1.2/ISurfaceFlingerConfigs.hal deleted file mode 100644 index 431b3fc479..0000000000 --- a/configstore/1.2/ISurfaceFlingerConfigs.hal +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.1 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.1 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.hardware.configstore@1.2; - -import android.hardware.graphics.common@1.2::PixelFormat; -import android.hardware.graphics.common@1.2::Dataspace; -import @1.1::ISurfaceFlingerConfigs; -import @1.0::OptionalBool; - -/** - * New revision of ISurfaceFlingerConfigs - */ -interface ISurfaceFlingerConfigs extends @1.1::ISurfaceFlingerConfigs { - /** - * useColorManagement indicates whether SurfaceFlinger should manage color - * by switching to appropriate color mode automatically depending on the - * Dataspace of the surfaces on screen. - * This function must return true when hasWideColorDisplay or hasHDRDisplay - * return true. - */ - useColorManagement() generates (OptionalBool value); - - /** - * Returns the default data space and pixel format that SurfaceFlinger - * expects to receive and output as well as the wide color gamut data space - * and pixel format for wide color gamut surfaces. - * To determine the data space and pixel format, there are a few things - * we recommend to consider: - * - * 1. Hardware composer's capability to composite contents with the chosen - * data space and pixel format efficiently; - * 2. Hardware composer's ability to composite contents when sRGB contents - * and the chosen wide color gamut data space contents coexist; - * 3. For better blending, consider using pixel format where the alpha - * channel has as many bits as the RGB color channel. - * 4. Memory consumption and efficient buffer compression when considering - * more bits in pixel format. - * - * @return dataspace is the default data space that SurfaceFlinger expects. - * The data space must not be Dataspace::UNKNOWN, if unspecified, - * the default data space is Dataspace::V0_SRGB; - * @return pixelFormat is the default pixel format that SurfaceFlinger - * expects. If unspecified, the default pixel format is - * PixelFormat::RGBA_8888. - * @return wcgDataspace is the data space that SurfaceFlinger expects for - * wide color gamut surfaces. - * When hasWideColorDisplay returns true, this API must return a - * valid wide color gamut data space. - * The data space must not be UNKNOWN, if unspecified, the data space - * is V0_SRGB by default, which essentially indicates there's no wide - * color gamut, meaning hasWideColorDisplay returns false. - * @return wcgPixelFormat is the pixel format that SurfaceFlinger expects for - * wide color gamut surfaces. If unspecified, the pixel format is - * PixelFormat::RGBA_8888 by default. - */ - getCompositionPreference() - generates (Dataspace dataspace, PixelFormat pixelFormat, - Dataspace wcgDataspace, PixelFormat wcgPixelFormat); - - /** - * Returns the native panel primary data. The data includes red, green, - * blue and white. The primary format is CIE 1931 XYZ color space. If - * unspecified, the primaries is sRGB gamut by default. - */ - getDisplayNativePrimaries() generates (DisplayPrimaries primaries); -}; diff --git a/configstore/1.2/default/surfaceflinger.mk b/configstore/1.2/default/surfaceflinger.mk deleted file mode 100644 index 9a672564c1..0000000000 --- a/configstore/1.2/default/surfaceflinger.mk +++ /dev/null @@ -1,124 +0,0 @@ - -LOCAL_SRC_FILES += SurfaceFlingerConfigs.cpp - -ifneq ($(VSYNC_EVENT_PHASE_OFFSET_NS),) - LOCAL_CFLAGS += -DVSYNC_EVENT_PHASE_OFFSET_NS=$(VSYNC_EVENT_PHASE_OFFSET_NS) -endif - -ifneq ($(SF_VSYNC_EVENT_PHASE_OFFSET_NS),) - LOCAL_CFLAGS += -DSF_VSYNC_EVENT_PHASE_OFFSET_NS=$(SF_VSYNC_EVENT_PHASE_OFFSET_NS) -endif - -ifeq ($(TARGET_USE_CONTEXT_PRIORITY),true) - LOCAL_CFLAGS += -DUSE_CONTEXT_PRIORITY=1 -endif - -ifeq ($(TARGET_HAS_WIDE_COLOR_DISPLAY),true) - LOCAL_CFLAGS += -DHAS_WIDE_COLOR_DISPLAY -endif - -ifeq ($(TARGET_HAS_HDR_DISPLAY),true) - LOCAL_CFLAGS += -DHAS_HDR_DISPLAY -endif - -ifneq ($(PRESENT_TIME_OFFSET_FROM_VSYNC_NS),) - LOCAL_CFLAGS += -DPRESENT_TIME_OFFSET_FROM_VSYNC_NS=$(PRESENT_TIME_OFFSET_FROM_VSYNC_NS) -else - LOCAL_CFLAGS += -DPRESENT_TIME_OFFSET_FROM_VSYNC_NS=0 -endif - -ifeq ($(TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS),true) - LOCAL_CFLAGS += -DFORCE_HWC_COPY_FOR_VIRTUAL_DISPLAYS -endif - -ifneq ($(MAX_VIRTUAL_DISPLAY_DIMENSION),) - LOCAL_CFLAGS += -DMAX_VIRTUAL_DISPLAY_DIMENSION=$(MAX_VIRTUAL_DISPLAY_DIMENSION) -endif - -ifeq ($(TARGET_RUNNING_WITHOUT_SYNC_FRAMEWORK),true) - LOCAL_CFLAGS += -DRUNNING_WITHOUT_SYNC_FRAMEWORK -endif - -ifneq ($(USE_VR_FLINGER),) - LOCAL_CFLAGS += -DUSE_VR_FLINGER -endif - -ifneq ($(NUM_FRAMEBUFFER_SURFACE_BUFFERS),) - LOCAL_CFLAGS += -DNUM_FRAMEBUFFER_SURFACE_BUFFERS=$(NUM_FRAMEBUFFER_SURFACE_BUFFERS) -endif - -ifneq ($(SF_START_GRAPHICS_ALLOCATOR_SERVICE),) - LOCAL_CFLAGS += -DSTART_GRAPHICS_ALLOCATOR_SERVICE -endif - -ifneq ($(SF_PRIMARY_DISPLAY_ORIENTATION),) - LOCAL_CFLAGS += -DPRIMARY_DISPLAY_ORIENTATION=$(SF_PRIMARY_DISPLAY_ORIENTATION) -endif - -ifeq ($(TARGET_USE_COLOR_MANAGEMENT),true) - LOCAL_CFLAGS += -DUSE_COLOR_MANAGEMENT -endif - -ifneq ($(SF_DEFAULT_COMPOSITION_DATA_SPACE),) - LOCAL_CFLAGS += -DDEFAULT_COMPOSITION_DATA_SPACE=$(SF_DEFAULT_COMPOSITION_DATA_SPACE) -endif - -ifneq ($(SF_DEFAULT_COMPOSITION_PIXEL_FORMAT),) - LOCAL_CFLAGS += -DDEFAULT_COMPOSITION_PIXEL_FORMAT=$(SF_DEFAULT_COMPOSITION_PIXEL_FORMAT) -endif - -ifneq ($(SF_WCG_COMPOSITION_DATA_SPACE),) - LOCAL_CFLAGS += -DWCG_COMPOSITION_DATA_SPACE=$(SF_WCG_COMPOSITION_DATA_SPACE) -endif - -ifneq ($(SF_WCG_COMPOSITION_PIXEL_FORMAT),) - LOCAL_CFLAGS += -DWCG_COMPOSITION_PIXEL_FORMAT=$(SF_WCG_COMPOSITION_PIXEL_FORMAT) -endif - -ifneq ($(TARGET_DISPLAY_PRIMARY_RED_X),) - LOCAL_CFLAGS += -DTARGET_DISPLAY_PRIMARY_RED_X=$(TARGET_DISPLAY_PRIMARY_RED_X) -endif - -ifneq ($(TARGET_DISPLAY_PRIMARY_RED_Y),) - LOCAL_CFLAGS += -DTARGET_DISPLAY_PRIMARY_RED_Y=$(TARGET_DISPLAY_PRIMARY_RED_Y) -endif - -ifneq ($(TARGET_DISPLAY_PRIMARY_RED_Z),) - LOCAL_CFLAGS += -DTARGET_DISPLAY_PRIMARY_RED_Z=$(TARGET_DISPLAY_PRIMARY_RED_Z) -endif - -ifneq ($(TARGET_DISPLAY_PRIMARY_GREEN_X),) - LOCAL_CFLAGS += -DTARGET_DISPLAY_PRIMARY_GREEN_X=$(TARGET_DISPLAY_PRIMARY_GREEN_X) -endif - -ifneq ($(TARGET_DISPLAY_PRIMARY_GREEN_Y),) - LOCAL_CFLAGS += -DTARGET_DISPLAY_PRIMARY_GREEN_Y=$(TARGET_DISPLAY_PRIMARY_GREEN_Y) -endif - -ifneq ($(TARGET_DISPLAY_PRIMARY_GREEN_Z),) - LOCAL_CFLAGS += -DTARGET_DISPLAY_PRIMARY_GREEN_Z=$(TARGET_DISPLAY_PRIMARY_GREEN_Z) -endif - -ifneq ($(TARGET_DISPLAY_PRIMARY_BLUE_X),) - LOCAL_CFLAGS += -DTARGET_DISPLAY_PRIMARY_BLUE_X=$(TARGET_DISPLAY_PRIMARY_BLUE_X) -endif - -ifneq ($(TARGET_DISPLAY_PRIMARY_BLUE_Y),) - LOCAL_CFLAGS += -DTARGET_DISPLAY_PRIMARY_BLUE_Y=$(TARGET_DISPLAY_PRIMARY_BLUE_Y) -endif - -ifneq ($(TARGET_DISPLAY_PRIMARY_BLUE_Z),) - LOCAL_CFLAGS += -DTARGET_DISPLAY_PRIMARY_BLUE_Z=$(TARGET_DISPLAY_PRIMARY_BLUE_Z) -endif - -ifneq ($(TARGET_DISPLAY_PRIMARY_WHITE_X),) - LOCAL_CFLAGS += -DTARGET_DISPLAY_PRIMARY_WHITE_X=$(TARGET_DISPLAY_PRIMARY_WHITE_X) -endif - -ifneq ($(TARGET_DISPLAY_PRIMARY_WHITE_Y),) - LOCAL_CFLAGS += -DTARGET_DISPLAY_PRIMARY_WHITE_Y=$(TARGET_DISPLAY_PRIMARY_WHITE_Y) -endif - -ifneq ($(TARGET_DISPLAY_PRIMARY_WHITE_Z),) - LOCAL_CFLAGS += -DTARGET_DISPLAY_PRIMARY_WHITE_Z=$(TARGET_DISPLAY_PRIMARY_WHITE_Z) -endif diff --git a/configstore/1.2/types.hal b/configstore/1.2/types.hal deleted file mode 100644 index 5b2c9a60b3..0000000000 --- a/configstore/1.2/types.hal +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.hardware.configstore@1.2; - -struct CieXyz { - float X; - float Y; - float Z; -}; -struct DisplayPrimaries { - CieXyz red; - CieXyz green; - CieXyz blue; - CieXyz white; -}; diff --git a/configstore/1.2/vts/functional/Android.bp b/configstore/1.2/vts/functional/Android.bp deleted file mode 100644 index 5f1eca6cdf..0000000000 --- a/configstore/1.2/vts/functional/Android.bp +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright (C) 2018 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -cc_test { - name: "VtsHalConfigstoreV1_2TargetTest", - defaults: ["VtsHalTargetTestDefaults"], - srcs: ["VtsHalConfigstoreV1_2TargetTest.cpp"], - static_libs: [ - "android.hardware.configstore@1.0", - "android.hardware.configstore@1.1", - "android.hardware.configstore@1.2", - ], -} - diff --git a/configstore/1.2/vts/functional/OWNERS b/configstore/1.2/vts/functional/OWNERS deleted file mode 100644 index 2b4fb8c70f..0000000000 --- a/configstore/1.2/vts/functional/OWNERS +++ /dev/null @@ -1,7 +0,0 @@ -# Graphics team -lpy@google.com -olv@google.com -stoza@google.com - -# VTS team -yim@google.com diff --git a/configstore/1.2/vts/functional/VtsHalConfigstoreV1_2TargetTest.cpp b/configstore/1.2/vts/functional/VtsHalConfigstoreV1_2TargetTest.cpp deleted file mode 100644 index d7f4dcf75f..0000000000 --- a/configstore/1.2/vts/functional/VtsHalConfigstoreV1_2TargetTest.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "ConfigstoreHidlHalTest" - -#include -#include -#include -#include -#include -#include -#include - -using ::android::sp; -using ::android::hardware::hidl_vec; -using ::android::hardware::Return; -using ::android::hardware::Void; -using ::android::hardware::configstore::V1_0::OptionalBool; -using ::android::hardware::configstore::V1_0::OptionalInt64; -using ::android::hardware::configstore::V1_0::OptionalUInt64; -using ::android::hardware::configstore::V1_2::DisplayPrimaries; -using ::android::hardware::configstore::V1_2::ISurfaceFlingerConfigs; -using ::android::hardware::graphics::common::V1_2::Dataspace; -using ::android::hardware::graphics::common::V1_2::PixelFormat; - -#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk()) -#define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk()) - -// Test environment for Configstore HIDL HAL. -class ConfigstoreHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { - public: - // get the test environment singleton - static ConfigstoreHidlEnvironment* Instance() { - static ConfigstoreHidlEnvironment* instance = new ConfigstoreHidlEnvironment; - return instance; - } - - virtual void registerTestServices() override { registerTestService(); } -}; - -class ConfigstoreHidlTest : public ::testing::VtsHalHidlTargetTestBase { - public: - sp sfConfigs; - - virtual void SetUp() override { - sfConfigs = ::testing::VtsHalHidlTargetTestBase::getService( - ConfigstoreHidlEnvironment::Instance()->getServiceName()); - ASSERT_NE(sfConfigs, nullptr); - } - - virtual void TearDown() override {} - - bool isSupportedWideColorGamut(Dataspace dataspace) { - Dataspace standard = static_cast(dataspace & Dataspace::STANDARD_MASK); - return standard == Dataspace::STANDARD_DCI_P3 || standard == Dataspace::STANDARD_BT2020; - } -}; - -/** - * Make sure the constrains of hasWideColorDisplay, hasHDRDisplay - * and useColorManagement are enforced. - */ -TEST_F(ConfigstoreHidlTest, TestColorConstrainsWithColorManagement) { - bool hasWideColorDisplay; - bool hasHDRDisplay; - bool useColorManagement; - - Return status = sfConfigs->hasWideColorDisplay( - [&](OptionalBool arg) { hasWideColorDisplay = arg.specified; }); - EXPECT_OK(status); - - status = sfConfigs->hasHDRDisplay([&](OptionalBool arg) { hasHDRDisplay = arg.specified; }); - EXPECT_OK(status); - - status = sfConfigs->useColorManagement( - [&](OptionalBool arg) { useColorManagement = arg.specified; }); - EXPECT_OK(status); - - // When hasHDRDisplay returns true, hasWideColorDisplay must also return true. - if (hasHDRDisplay) { - ASSERT_TRUE(hasWideColorDisplay); - } - - // When hasWideColorDisplay returns true, useColorManagement - // must also return true. - if (hasWideColorDisplay) { - ASSERT_TRUE(useColorManagement); - } -} - -TEST_F(ConfigstoreHidlTest, TestGetCompositionPreference) { - bool hasWideColorDisplay; - - Return status = sfConfigs->hasWideColorDisplay( - [&](OptionalBool arg) { hasWideColorDisplay = arg.specified; }); - EXPECT_OK(status); - - Dataspace defaultDataspace, wcgDataspace; - - status = sfConfigs->getCompositionPreference( - [&](auto tmpDefaultDataspace, PixelFormat, auto tmpWcgDataspace, PixelFormat) { - defaultDataspace = tmpDefaultDataspace; - wcgDataspace = tmpWcgDataspace; - }); - EXPECT_OK(status); - - // Default data space and wide color gamut data space must not be UNKNOWN. - ASSERT_TRUE(defaultDataspace != Dataspace::UNKNOWN && wcgDataspace != Dataspace::UNKNOWN); - - // If hasWideColorDisplay returns true, the wide color gamut data space must be a valid wide - // color gamut. - if (hasWideColorDisplay) { - ASSERT_TRUE(isSupportedWideColorGamut(wcgDataspace)); - } -} - -TEST_F(ConfigstoreHidlTest, TestGetDisplayNativePrimaries) { - DisplayPrimaries primaries; - - Return status = sfConfigs->getDisplayNativePrimaries( - [&](DisplayPrimaries tmpPrimaries) { - primaries.red = tmpPrimaries.red; - primaries.green = tmpPrimaries.green; - primaries.blue = tmpPrimaries.blue; - primaries.white = tmpPrimaries.white; - }); - EXPECT_OK(status); - - // Display primaries should be greater than or equal to zero. - // Or it returns defualt value if there is no definition. - // RED - EXPECT_GE(primaries.red.X, 0.0); - EXPECT_GE(primaries.red.Y, 0.0); - EXPECT_GE(primaries.red.Z, 0.0); - - // GREEN - EXPECT_GE(primaries.green.X, 0.0); - EXPECT_GE(primaries.green.Y, 0.0); - EXPECT_GE(primaries.green.Z, 0.0); - - - // BLUE - EXPECT_GE(primaries.blue.X, 0.0); - EXPECT_GE(primaries.blue.Y, 0.0); - EXPECT_GE(primaries.blue.Z, 0.0); - - - // WHITE - EXPECT_GE(primaries.white.X, 0.0); - EXPECT_GE(primaries.white.Y, 0.0); - EXPECT_GE(primaries.white.Z, 0.0); -} - -int main(int argc, char** argv) { - ::testing::AddGlobalTestEnvironment(ConfigstoreHidlEnvironment::Instance()); - ::testing::InitGoogleTest(&argc, argv); - ConfigstoreHidlEnvironment::Instance()->init(&argc, argv); - int status = RUN_ALL_TESTS(); - LOG(INFO) << "Test result = " << status; - return status; -} diff --git a/configstore/utils/Android.bp b/configstore/utils/Android.bp index e0d4aa8192..178f245fd6 100644 --- a/configstore/utils/Android.bp +++ b/configstore/utils/Android.bp @@ -30,14 +30,12 @@ cc_library_shared { shared_libs: [ "android.hardware.configstore@1.0", "android.hardware.configstore@1.1", - "android.hardware.configstore@1.2", "libbase", "libhidlbase" ], export_shared_lib_headers: [ "android.hardware.configstore@1.0", "android.hardware.configstore@1.1", - "android.hardware.configstore@1.2", "libbase", "libhidlbase" ], diff --git a/current.txt b/current.txt index ce8e05f176..887f53e721 100644 --- a/current.txt +++ b/current.txt @@ -451,8 +451,6 @@ f5777403d65135a5407723671bc7a864cdca83aea13ee3ce2894b95e6588ca3a android.hardwar 44c88954b3c201b26f64fcdb6f278024ab3aae864a9e1ec70e8a74274ae9d6aa android.hardware.cas@1.1::ICas 25012d1778f7396f967bbc0231397d544bde421ba5b98706c9e48ac790612683 android.hardware.cas@1.1::ICasListener dffacdbe0bcf8443013de5bdc56a83479ad979d4919ed15a5585539f46091f07 android.hardware.cas@1.1::IMediaCasService -bc742c6b17c834010f90c06ce2939c845198eecd2706be18da99e14bceb2acc0 android.hardware.configstore@1.2::ISurfaceFlingerConfigs -aadac6b9fcf660384d73cbb97f3732ff9eeb8e8c67001e3fdbf4add108e5b1dc android.hardware.configstore@1.2::types 5b1f4a4fb88c239e07d76026467a1f2ee0d08f4d52c1805bd93bd7c05e3fe69c android.hardware.drm@1.2::ICryptoFactory 4895f98e9ef210e9acb01982f5d07b654538377e1404b8db5e19e7858835e9d8 android.hardware.drm@1.2::ICryptoPlugin 976116b9033b2c222b940109fdf0ffcc29b77cbe631ef6b4fcc2ad5ce8e605f7 android.hardware.drm@1.2::IDrmFactory From f6729eff5dafa345d776eb02804e075c3ed35966 Mon Sep 17 00:00:00 2001 From: Annie Meng Date: Wed, 27 Feb 2019 11:22:21 +0000 Subject: [PATCH 507/718] Revert "Fix doc on getModemStackStatus" This reverts commit 0d74a22d26cecf39cad66c310073601b9b2bcbbe. Reason for revert: Broke presubmit Change-Id: I3052889863c1d750f3e916a575c4e412a5395d49 --- current.txt | 2 +- radio/1.3/IRadio.hal | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/current.txt b/current.txt index 081e5299a8..4aa8c1dd87 100644 --- a/current.txt +++ b/current.txt @@ -513,7 +513,7 @@ cf7a4ba516a638f9b82a249c91fb603042c2d9ca43fd5aad9cf6c0401ed2a5d7 android.hardwar abf98c2ae08bf765db54edc8068e36d52eb558cff6706b6fd7c18c65a1f3fc18 android.hardware.nfc@1.2::types 4cb252dc6372a874aef666b92a6e9529915aa187521a700f0789065c3c702ead android.hardware.power.stats@1.0::IPowerStats 2043037d5baaff604805757d06979aa861013a1e87430db745265339a8681f79 android.hardware.power.stats@1.0::types -d5545a4090e5cf8b7f844121377d580926cb9137d693d8c66772ef99ca23e514 android.hardware.radio@1.3::IRadio +11620ce020b6ef8f5b63eb2a39390de4a2fbbccc0a5e558b5b1a0e22e33f63cf android.hardware.radio@1.3::IRadio e9d0f11a52715f5a29d89e2d8e2e21db1e16a43174af6b9d51a62d705cda1455 android.hardware.radio@1.3::IRadioIndication d233f0da44f55fdef0a95db5229231412787bb67695cd1ea197ce89a3c2908b9 android.hardware.radio@1.3::IRadioResponse 750a363c8cec70baa1aac19e275c15233c5898e93c6bb5155fa2ca7f365490dc android.hardware.radio@1.3::types diff --git a/radio/1.3/IRadio.hal b/radio/1.3/IRadio.hal index 95cf6151a5..cc5b8605bc 100644 --- a/radio/1.3/IRadio.hal +++ b/radio/1.3/IRadio.hal @@ -49,8 +49,10 @@ interface IRadio extends @1.2::IRadio { vec specifiers); /** - * Toggle logical modem on and off. The difference with setRadioPower is, - * setRadioPower affects all logical modems while this controls just one. + * Toggle logical modem on and off. It should put the logical modem in low power + * mode without any activity, while the SIM card remains visible. The difference + * with setRadioPower is, setRadioPower affects all logical modem while this controls + * just one. * * @param serial Serial number of request. * @param on True to turn on the logical modem, otherwise turn it off. @@ -60,8 +62,9 @@ interface IRadio extends @1.2::IRadio { oneway enableModem(int32_t serial, bool on); /** - * Request status of logical modem. It returns isEnabled=true if the logical modem is on. - * This method is the getter method for enableModem. + * Request status of logical modem associated with the given serial number. It returns + * isEnabled=true if the logical modem is in low power mode without any activity, while + * the SIM card remains visible. * * @param serial Serial number of request. * From 68eef0850c6ac64e2c1cd691c1711bdfc685d286 Mon Sep 17 00:00:00 2001 From: Nazanin Bakhshi Date: Wed, 27 Feb 2019 10:10:29 -0800 Subject: [PATCH 508/718] Fix doc on getModemStackStatus Bug: 123958093 Test: build Change-Id: I9ed735df7acd704144f3d399b09f80973e6ff4ab --- current.txt | 2 +- radio/1.3/IRadio.hal | 11 ++++------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/current.txt b/current.txt index ce8e05f176..94b40c2cc8 100644 --- a/current.txt +++ b/current.txt @@ -513,7 +513,7 @@ cf7a4ba516a638f9b82a249c91fb603042c2d9ca43fd5aad9cf6c0401ed2a5d7 android.hardwar abf98c2ae08bf765db54edc8068e36d52eb558cff6706b6fd7c18c65a1f3fc18 android.hardware.nfc@1.2::types 4cb252dc6372a874aef666b92a6e9529915aa187521a700f0789065c3c702ead android.hardware.power.stats@1.0::IPowerStats 2043037d5baaff604805757d06979aa861013a1e87430db745265339a8681f79 android.hardware.power.stats@1.0::types -11620ce020b6ef8f5b63eb2a39390de4a2fbbccc0a5e558b5b1a0e22e33f63cf android.hardware.radio@1.3::IRadio +d5545a4090e5cf8b7f844121377d580926cb9137d693d8c66772ef99ca23e514 android.hardware.radio@1.3::IRadio e9d0f11a52715f5a29d89e2d8e2e21db1e16a43174af6b9d51a62d705cda1455 android.hardware.radio@1.3::IRadioIndication d233f0da44f55fdef0a95db5229231412787bb67695cd1ea197ce89a3c2908b9 android.hardware.radio@1.3::IRadioResponse 750a363c8cec70baa1aac19e275c15233c5898e93c6bb5155fa2ca7f365490dc android.hardware.radio@1.3::types diff --git a/radio/1.3/IRadio.hal b/radio/1.3/IRadio.hal index cc5b8605bc..95cf6151a5 100644 --- a/radio/1.3/IRadio.hal +++ b/radio/1.3/IRadio.hal @@ -49,10 +49,8 @@ interface IRadio extends @1.2::IRadio { vec specifiers); /** - * Toggle logical modem on and off. It should put the logical modem in low power - * mode without any activity, while the SIM card remains visible. The difference - * with setRadioPower is, setRadioPower affects all logical modem while this controls - * just one. + * Toggle logical modem on and off. The difference with setRadioPower is, + * setRadioPower affects all logical modems while this controls just one. * * @param serial Serial number of request. * @param on True to turn on the logical modem, otherwise turn it off. @@ -62,9 +60,8 @@ interface IRadio extends @1.2::IRadio { oneway enableModem(int32_t serial, bool on); /** - * Request status of logical modem associated with the given serial number. It returns - * isEnabled=true if the logical modem is in low power mode without any activity, while - * the SIM card remains visible. + * Request status of logical modem. It returns isEnabled=true if the logical modem is on. + * This method is the getter method for enableModem. * * @param serial Serial number of request. * From 75b35de21d99aafd10d7372ddc8b3ec6d13cc941 Mon Sep 17 00:00:00 2001 From: Yu-Han Yang Date: Wed, 13 Feb 2019 12:04:52 -0800 Subject: [PATCH 509/718] Add isEmergency flag to gnssRequestLocationCb Bug: 124106337 Test: atest VtsHalGnssV2_0TargetTest Change-Id: I1d89b4065e3f40b5a4e0714bacd3e305aa94eaa0 --- current.txt | 2 +- gnss/2.0/IGnssCallback.hal | 23 +++++++++++++++++++++++ gnss/2.0/vts/functional/gnss_hal_test.h | 10 ++++++++-- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/current.txt b/current.txt index ce8e05f176..7370e2928c 100644 --- a/current.txt +++ b/current.txt @@ -465,7 +465,7 @@ f27baaa587bc3dd9b740cb6928ab812b9b7d105b5187663938aee578105f3c39 android.hardwar 2e5ad983734069e84a760004b32da0d09e4170c05380abe27e6eb80e4aa70d5a android.hardware.gnss@2.0::IAGnssCallback 1f4ac068a88a72360280d94a7f6fd7c63813c1eea4891a0eb01394d3e7e775f2 android.hardware.gnss@2.0::IAGnssRil 6e2f9a44375a0ae0b49ca7d711cb88945189d398535078408269e1e85889061d android.hardware.gnss@2.0::IGnss -54d253b10c7da2a4a708d11acda3118b283df1540bc10323a5a3773c94cc8e71 android.hardware.gnss@2.0::IGnssCallback +d815623a6d1ba4abf21248b84eca70a2bfab03058a88b68a29c063ce8aee6b5c android.hardware.gnss@2.0::IGnssCallback ecc966c68bddbd95c8dae782b84204cf01c75734675e8769963f3b5106ec128b android.hardware.gnss@2.0::IGnssConfiguration c67759f5d6387d273b66729180d03690e827f0b6b8d4e13ce2ff42d31b224065 android.hardware.gnss@2.0::IGnssMeasurement 089338944c45f66f25ba4ee958c161c42fefeb73ec60e4451f3535a1b3fd10c7 android.hardware.gnss@2.0::IGnssMeasurementCallback diff --git a/gnss/2.0/IGnssCallback.hal b/gnss/2.0/IGnssCallback.hal index e2ac02ac03..7924b641bc 100644 --- a/gnss/2.0/IGnssCallback.hal +++ b/gnss/2.0/IGnssCallback.hal @@ -52,4 +52,27 @@ interface IGnssCallback extends @1.1::IGnssCallback { */ gnssLocationCb_2_0(GnssLocation location); + /** + * Callback for requesting Location. + * + * HAL implementation must call this when it wants the framework to provide locations to assist + * with GNSS HAL operation, for example, to assist with time to first fix, error recovery, or to + * supplement GNSS location for other clients of the GNSS HAL. + * + * If a request is made with independentFromGnss set to true, the framework must avoid + * providing locations derived from GNSS locations (such as "fused" location), to help improve + * information independence for situations such as error recovery. + * + * In response to this method call, GNSS HAL can expect zero, one, or more calls to + * IGnss::injectLocation or IGnss::injectBestLocation, dependent on availability of location + * from other sources, which may happen at some arbitrary delay. Generally speaking, HAL + * implementations must be able to handle calls to IGnss::injectLocation or + * IGnss::injectBestLocation at any time. + * + * @param independentFromGnss True if requesting a location that is independent from GNSS. + * @param isUserEmergency True if the location request is for delivery of this location to an + * emergency services endpoint, during a user-initiated emergency session (e.g. + * during-call to E911, or up to 5 minutes after end-of-call or text to E911). + */ + gnssRequestLocationCb_2_0(bool independentFromGnss, bool isUserEmergency); }; \ No newline at end of file diff --git a/gnss/2.0/vts/functional/gnss_hal_test.h b/gnss/2.0/vts/functional/gnss_hal_test.h index 7793eb75cb..31750a6641 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test.h +++ b/gnss/2.0/vts/functional/gnss_hal_test.h @@ -99,12 +99,18 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase { // Actual (test) callback handlers Return gnssNameCb(const android::hardware::hidl_string& name) override; Return gnssLocationCb(const GnssLocation_1_0& location) override; - Return gnssLocationCb_2_0(const GnssLocation_2_0& location) override; Return gnssSetCapabilitesCb(uint32_t capabilities) override; - Return gnssSetCapabilitiesCb_2_0(uint32_t capabilities) override; Return gnssSetSystemInfoCb(const IGnssCallback::GnssSystemInfo& info) override; Return gnssSvStatusCb(const IGnssCallback::GnssSvStatus& svStatus) override; + // New in v2.0 + Return gnssLocationCb_2_0(const GnssLocation_2_0& location) override; + Return gnssRequestLocationCb_2_0(bool /* independentFromGnss */, + bool /* isUserEmergency */) override { + return Void(); + } + Return gnssSetCapabilitiesCb_2_0(uint32_t capabilities) override; + private: Return gnssLocationCbImpl(const GnssLocation_2_0& location); }; From ad6bdaac7bcbd632054e22f945276af245064427 Mon Sep 17 00:00:00 2001 From: Malcolm Chen Date: Fri, 22 Feb 2019 18:41:55 -0800 Subject: [PATCH 510/718] Add vts tests on CBRS related HAL APIs Bug: 121345298 Test: vts Change-Id: I011f052fdaa07dcd571d2357865486c7708f797a --- .../1.3/vts/functional/radio_hidl_hal_api.cpp | 33 +++++++ radio/1.3/vts/functional/radio_response.cpp | 3 + .../functional/radio_config_hidl_hal_api.cpp | 86 +++++++++++++++++++ .../functional/radio_config_hidl_hal_utils.h | 1 + .../vts/functional/radio_config_response.cpp | 7 +- 5 files changed, 128 insertions(+), 2 deletions(-) diff --git a/radio/1.3/vts/functional/radio_hidl_hal_api.cpp b/radio/1.3/vts/functional/radio_hidl_hal_api.cpp index 6208c677f5..1bebae7389 100644 --- a/radio/1.3/vts/functional/radio_hidl_hal_api.cpp +++ b/radio/1.3/vts/functional/radio_hidl_hal_api.cpp @@ -75,3 +75,36 @@ TEST_F(RadioHidlTest_v1_3, getModemStackStatus) { radioRsp_v1_3->rspInfo.error, {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::MODEM_ERR})); } + +/* + * Test IRadio.setSystemSelectionChannels() for the response returned. + */ +TEST_F(RadioHidlTest_v1_3, setSystemSelectionChannels) { + serial = GetRandomSerialNumber(); + + RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN, + .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480}, + .channels = {1, 2}}; + + Return res = radio_v1_3->setSystemSelectionChannels(serial, true, {specifier}); + ASSERT_OK(res); + EXPECT_EQ(std::cv_status::no_timeout, wait()); + EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_3->rspInfo.type); + EXPECT_EQ(serial, radioRsp_v1_3->rspInfo.serial); + ALOGI("setSystemSelectionChannels, rspInfo.error = %s\n", + toString(radioRsp_v1_3->rspInfo.error).c_str()); + ASSERT_TRUE(CheckAnyOfErrors( + radioRsp_v1_3->rspInfo.error, + {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::INTERNAL_ERR})); + + if (radioRsp_v1_3->rspInfo.error == RadioError::NONE) { + Return res = radio_v1_3->setSystemSelectionChannels(serial, false, {specifier}); + ASSERT_OK(res); + EXPECT_EQ(std::cv_status::no_timeout, wait()); + EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_3->rspInfo.type); + EXPECT_EQ(serial, radioRsp_v1_3->rspInfo.serial); + ALOGI("setSystemSelectionChannels, rspInfo.error = %s\n", + toString(radioRsp_v1_3->rspInfo.error).c_str()); + EXPECT_EQ(RadioError::NONE, radioRsp_v1_3->rspInfo.error); + } +} \ No newline at end of file diff --git a/radio/1.3/vts/functional/radio_response.cpp b/radio/1.3/vts/functional/radio_response.cpp index 900794ec1b..84a98908b7 100644 --- a/radio/1.3/vts/functional/radio_response.cpp +++ b/radio/1.3/vts/functional/radio_response.cpp @@ -769,12 +769,14 @@ Return RadioResponse_v1_3::getDataRegistrationStateResponse_1_2( /* 1.3 Api */ Return RadioResponse_v1_3::setSystemSelectionChannelsResponse(const RadioResponseInfo& info) { rspInfo = info; + parent_v1_3.notify(info.serial); return Void(); } Return RadioResponse_v1_3::enableModemResponse(const RadioResponseInfo& info) { rspInfo = info; enableModemResponseToggle = !enableModemResponseToggle; + parent_v1_3.notify(info.serial); return Void(); } @@ -782,5 +784,6 @@ Return RadioResponse_v1_3::getModemStackStatusResponse(const RadioResponse const bool enabled) { rspInfo = info; isModemEnabled = enabled; + parent_v1_3.notify(info.serial); return Void(); } diff --git a/radio/config/1.1/vts/functional/radio_config_hidl_hal_api.cpp b/radio/config/1.1/vts/functional/radio_config_hidl_hal_api.cpp index a1639d8bb9..122ce58a3e 100644 --- a/radio/config/1.1/vts/functional/radio_config_hidl_hal_api.cpp +++ b/radio/config/1.1/vts/functional/radio_config_hidl_hal_api.cpp @@ -69,3 +69,89 @@ TEST_F(RadioConfigHidlTest, setModemsConfig_goodRequest) { ASSERT_TRUE(CheckAnyOfErrors(radioConfigRsp->rspInfo.error, {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED})); } + +/* + * Test IRadioConfig.getPhoneCapability() + */ +TEST_F(RadioConfigHidlTest, getPhoneCapability) { + serial = GetRandomSerialNumber(); + Return res = radioConfig->getPhoneCapability(serial); + ASSERT_OK(res); + EXPECT_EQ(std::cv_status::no_timeout, wait()); + EXPECT_EQ(RadioResponseType::SOLICITED, radioConfigRsp->rspInfo.type); + EXPECT_EQ(serial, radioConfigRsp->rspInfo.serial); + ALOGI("getPhoneCapability, rspInfo.error = %s\n", + toString(radioConfigRsp->rspInfo.error).c_str()); + + ASSERT_TRUE(CheckAnyOfErrors( + radioConfigRsp->rspInfo.error, + {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::INTERNAL_ERR})); + + if (radioConfigRsp->rspInfo.error == RadioError ::NONE) { + // maxActiveData should be greater than or equal to maxActiveInternetData. + EXPECT_GE(radioConfigRsp->phoneCap.maxActiveData, + radioConfigRsp->phoneCap.maxActiveInternetData); + // maxActiveData and maxActiveInternetData should be 0 or positive numbers. + EXPECT_GE(radioConfigRsp->phoneCap.maxActiveInternetData, 0); + } +} + +/* + * Test IRadioConfig.getPhoneCapability() + */ +TEST_F(RadioConfigHidlTest, setPreferredDataModem) { + serial = GetRandomSerialNumber(); + Return res = radioConfig->getPhoneCapability(serial); + ASSERT_OK(res); + EXPECT_EQ(std::cv_status::no_timeout, wait()); + EXPECT_EQ(RadioResponseType::SOLICITED, radioConfigRsp->rspInfo.type); + EXPECT_EQ(serial, radioConfigRsp->rspInfo.serial); + ALOGI("getPhoneCapability, rspInfo.error = %s\n", + toString(radioConfigRsp->rspInfo.error).c_str()); + + ASSERT_TRUE(CheckAnyOfErrors( + radioConfigRsp->rspInfo.error, + {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::INTERNAL_ERR})); + + if (radioConfigRsp->rspInfo.error != RadioError ::NONE) { + return; + } + + if (radioConfigRsp->phoneCap.logicalModemList.size() == 0) { + return; + } + + // We get phoneCapability. send setPreferredDataModem command + serial = GetRandomSerialNumber(); + uint8_t modemId = radioConfigRsp->phoneCap.logicalModemList[0].modemId; + res = radioConfig->setPreferredDataModem(serial, modemId); + + ASSERT_OK(res); + EXPECT_EQ(std::cv_status::no_timeout, wait()); + EXPECT_EQ(RadioResponseType::SOLICITED, radioConfigRsp->rspInfo.type); + EXPECT_EQ(serial, radioConfigRsp->rspInfo.serial); + ALOGI("getModemsConfig, rspInfo.error = %s\n", toString(radioConfigRsp->rspInfo.error).c_str()); + + ASSERT_TRUE(CheckAnyOfErrors( + radioConfigRsp->rspInfo.error, + {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::INTERNAL_ERR})); +} + +/* + * Test IRadioConfig.getPhoneCapability() + */ +TEST_F(RadioConfigHidlTest, setPreferredDataModem_invalidArgument) { + serial = GetRandomSerialNumber(); + uint8_t modemId = -1; + Return res = radioConfig->setPreferredDataModem(serial, modemId); + + ASSERT_OK(res); + EXPECT_EQ(std::cv_status::no_timeout, wait()); + EXPECT_EQ(RadioResponseType::SOLICITED, radioConfigRsp->rspInfo.type); + EXPECT_EQ(serial, radioConfigRsp->rspInfo.serial); + ALOGI("getModemsConfig, rspInfo.error = %s\n", toString(radioConfigRsp->rspInfo.error).c_str()); + + ASSERT_TRUE(CheckAnyOfErrors(radioConfigRsp->rspInfo.error, + {RadioError::INVALID_ARGUMENTS, RadioError::RADIO_NOT_AVAILABLE, + RadioError::INTERNAL_ERR})); +} diff --git a/radio/config/1.1/vts/functional/radio_config_hidl_hal_utils.h b/radio/config/1.1/vts/functional/radio_config_hidl_hal_utils.h index 1747ce8f24..c980901014 100644 --- a/radio/config/1.1/vts/functional/radio_config_hidl_hal_utils.h +++ b/radio/config/1.1/vts/functional/radio_config_hidl_hal_utils.h @@ -51,6 +51,7 @@ class RadioConfigResponse : public IRadioConfigResponse { public: RadioResponseInfo rspInfo; + PhoneCapability phoneCap; RadioConfigResponse(RadioConfigHidlTest& parent); virtual ~RadioConfigResponse() = default; diff --git a/radio/config/1.1/vts/functional/radio_config_response.cpp b/radio/config/1.1/vts/functional/radio_config_response.cpp index 8c9e4d75e6..ce3dfdff5d 100644 --- a/radio/config/1.1/vts/functional/radio_config_response.cpp +++ b/radio/config/1.1/vts/functional/radio_config_response.cpp @@ -31,7 +31,10 @@ Return RadioConfigResponse::setSimSlotsMappingResponse(const RadioResponse } Return RadioConfigResponse::getPhoneCapabilityResponse( - const RadioResponseInfo& /* info */, const PhoneCapability& /* phoneCapability */) { + const RadioResponseInfo& info, const PhoneCapability& phoneCapability) { + rspInfo = info; + phoneCap = phoneCapability; + parent.notify(info.serial); return Void(); } @@ -47,4 +50,4 @@ Return RadioConfigResponse::getModemsConfigResponse(const RadioResponseInf Return RadioConfigResponse::setModemsConfigResponse(const RadioResponseInfo& /* info */) { return Void(); -} \ No newline at end of file +} From ce02fb3c51c33f1467f63f563ca3d4a07de63d69 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Thu, 28 Feb 2019 08:12:35 -0800 Subject: [PATCH 511/718] wifi(tests): Fix runtest.sh Bug: 79261060 Test: ./hardware/interfaces/wifi/1.3/default/tests/runtests.sh Change-Id: Idca21bf264640fb2e5eaa1791f3ff29e138bbbb2 --- wifi/1.3/default/tests/runtests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wifi/1.3/default/tests/runtests.sh b/wifi/1.3/default/tests/runtests.sh index eefc697b2e..6bce3ef8c4 100755 --- a/wifi/1.3/default/tests/runtests.sh +++ b/wifi/1.3/default/tests/runtests.sh @@ -23,4 +23,4 @@ set -e $ANDROID_BUILD_TOP/build/soong/soong_ui.bash --make-mode android.hardware.wifi@1.0-service-tests adb root adb sync data -adb shell /data/nativetest64/android.hardware.wifi@1.0-service-tests/android.hardware.wifi@1.0-service-tests +adb shell /data/nativetest64/vendor/android.hardware.wifi@1.0-service-tests/android.hardware.wifi@1.0-service-tests From 0eea29beaa897c2ed0b35eed58b98952f5d09f2d Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Mon, 25 Feb 2019 15:22:42 -0800 Subject: [PATCH 512/718] Remove update scripts for VTS makefiles. These are automatically included as part of hidl_interface and no longer need to be checked in. Bug: 117348839 Test: manual Change-Id: If07460e1b88c5929e23256c30ddb332ee64e9c3d --- update-makefiles.sh | 6 ------ 1 file changed, 6 deletions(-) diff --git a/update-makefiles.sh b/update-makefiles.sh index 14c5b01cac..c58240f0f5 100755 --- a/update-makefiles.sh +++ b/update-makefiles.sh @@ -13,9 +13,3 @@ source $ANDROID_BUILD_TOP/system/tools/hidl/update-makefiles-helper.sh do_makefiles_update \ "android.hardware:hardware/interfaces" \ "android.hidl:system/libhidl/transport" - -echo "Updating files at $ANDROID_BUILD_TOP/test/vts-testcase/hal" -pushd $ANDROID_BUILD_TOP/test/vts-testcase/hal -./script/update_makefiles.py -popd - From 99f88da61b1bc7a01175f8165e6cb2a0b88b0ef5 Mon Sep 17 00:00:00 2001 From: Yu-Han Yang Date: Wed, 27 Feb 2019 12:36:55 -0800 Subject: [PATCH 513/718] Enable GNSS Measurement capability in default implementation Bug: 126573522 Fixes: 126573522 Test: tested on cuttlefish Change-Id: I1cb6d22a7d721c6e8bda37ca8966d1f45c734a16 --- gnss/2.0/default/Gnss.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/gnss/2.0/default/Gnss.cpp b/gnss/2.0/default/Gnss.cpp index 599681bf38..33edbd56eb 100644 --- a/gnss/2.0/default/Gnss.cpp +++ b/gnss/2.0/default/Gnss.cpp @@ -122,8 +122,7 @@ Return Gnss::deleteAidingData(V1_0::IGnss::GnssAidingData) { Return Gnss::setPositionMode(V1_0::IGnss::GnssPositionMode, V1_0::IGnss::GnssPositionRecurrence, uint32_t, uint32_t, uint32_t) { - // TODO(b/124012850): Implement function. - return bool{}; + return true; } Return> Gnss::getExtensionAGnssRil() { @@ -267,7 +266,7 @@ Return Gnss::setCallback_2_0(const sp& callback) { sGnssCallback_2_0 = callback; - uint32_t capabilities = 0x0; + uint32_t capabilities = static_cast(V1_0::IGnssCallback::Capabilities::MEASUREMENTS); auto ret = sGnssCallback_2_0->gnssSetCapabilitesCb(capabilities); if (!ret.isOk()) { ALOGE("%s: Unable to invoke callback", __func__); From 195417f0a4e5557e3b928a5f17e052979ecdcf1a Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Fri, 1 Mar 2019 10:08:19 -0800 Subject: [PATCH 514/718] configstore@1.2: remove requirement - configstore@1.2 no longer exists - configstore@1.1 is being deprecated in favor of properties Bug: 122461092 Bug: 124531214 Test: manual Change-Id: Ia1411ca5db897b3d9f67a4450cf10f878ddc64b9 --- compatibility_matrices/compatibility_matrix.current.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml index 244d7a0396..566bd481d0 100644 --- a/compatibility_matrices/compatibility_matrix.current.xml +++ b/compatibility_matrices/compatibility_matrix.current.xml @@ -127,9 +127,9 @@ default - + android.hardware.configstore - 1.2 + 1.1 ISurfaceFlingerConfigs default From 1a34e407bf9cebd19fdafc96846d4c1e3c4cf41d Mon Sep 17 00:00:00 2001 From: Ilya Matyukhin Date: Tue, 5 Feb 2019 15:12:44 -0800 Subject: [PATCH 515/718] Implemented VTS tests for BiometricsFace.hal Test: manually built and ran the tests Fixes: 110708105 Change-Id: Id2882436b2346032b080cee16a9fc289ee3dbdc2 --- biometrics/face/1.0/vts/functional/Android.bp | 24 + .../VtsHalBiometricsFaceV1_0TargetTest.cpp | 412 ++++++++++++++++++ 2 files changed, 436 insertions(+) create mode 100644 biometrics/face/1.0/vts/functional/Android.bp create mode 100644 biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp diff --git a/biometrics/face/1.0/vts/functional/Android.bp b/biometrics/face/1.0/vts/functional/Android.bp new file mode 100644 index 0000000000..fa68c4e8d7 --- /dev/null +++ b/biometrics/face/1.0/vts/functional/Android.bp @@ -0,0 +1,24 @@ +// +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +cc_test { + name: "VtsHalBiometricsFaceV1_0TargetTest", + defaults: ["VtsHalTargetTestDefaults"], + srcs: ["VtsHalBiometricsFaceV1_0TargetTest.cpp"], + static_libs: ["android.hardware.biometrics.face@1.0"], + test_suites: ["general-tests"], +} + diff --git a/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp b/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp new file mode 100644 index 0000000000..f496bbe642 --- /dev/null +++ b/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp @@ -0,0 +1,412 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "face_hidl_test" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +using android::Condition; +using android::Mutex; +using android::sp; +using android::base::GetUintProperty; +using android::hardware::hidl_vec; +using android::hardware::Return; +using android::hardware::biometrics::face::V1_0::FaceAcquiredInfo; +using android::hardware::biometrics::face::V1_0::FaceError; +using android::hardware::biometrics::face::V1_0::Feature; +using android::hardware::biometrics::face::V1_0::IBiometricsFace; +using android::hardware::biometrics::face::V1_0::IBiometricsFaceClientCallback; +using android::hardware::biometrics::face::V1_0::OptionalUint64; +using android::hardware::biometrics::face::V1_0::Status; + +namespace { + +const uint32_t kTimeout = 3; +const std::chrono::seconds kTimeoutInSeconds = std::chrono::seconds(kTimeout); +const uint32_t kUserId = 99; +const uint32_t kFaceId = 5; +const char kTmpDir[] = "/data/system/users/0/facedata"; +const int kIterations = 1000; + +const auto kAssertCallbackIsSet = [](const OptionalUint64& res) { + ASSERT_EQ(Status::OK, res.status); + // Makes sure the "deviceId" represented by "res.value" is not 0. + // 0 would mean the HIDL is not available. + ASSERT_NE(0UL, res.value); +}; + +// Wait for a callback to occur (signaled by the given future) up to the +// provided timeout. If the future is invalid or the callback does not come +// within the given time, returns false. +template +bool waitForCallback(std::future future, + std::chrono::milliseconds timeout = kTimeoutInSeconds) { + auto expiration = std::chrono::system_clock::now() + timeout; + EXPECT_TRUE(future.valid()); + if (future.valid()) { + std::future_status status = future.wait_until(expiration); + EXPECT_NE(std::future_status::timeout, status) << "Timed out waiting for callback"; + if (status == std::future_status::ready) { + return true; + } + } + return false; +} + +// Base callback implementation that just logs all callbacks by default +class FaceCallbackBase : public IBiometricsFaceClientCallback { + public: + Return onEnrollResult(uint64_t, uint32_t, int32_t, uint32_t) override { + ALOGD("Enroll callback called."); + return Return(); + } + + Return onAuthenticated(uint64_t, uint32_t, int32_t, const hidl_vec&) override { + ALOGD("Authenticated callback called."); + return Return(); + } + + Return onAcquired(uint64_t, int32_t, FaceAcquiredInfo, int32_t) override { + ALOGD("Acquired callback called."); + return Return(); + } + + Return onError(uint64_t, int32_t, FaceError, int32_t) override { + ALOGD("Error callback called."); + EXPECT_TRUE(false); // fail any test that triggers an error + return Return(); + } + + Return onRemoved(uint64_t, uint32_t, int32_t, uint32_t) override { + ALOGD("Removed callback called."); + return Return(); + } + + Return onEnumerate(uint64_t, const hidl_vec&, int32_t /* userId */) override { + ALOGD("Enumerate callback called."); + return Return(); + } + + Return onLockoutChanged(uint64_t) override { + ALOGD("LockoutChanged callback called."); + return Return(); + } +}; + +class EnumerateCallback : public FaceCallbackBase { + public: + Return onEnumerate(uint64_t, const hidl_vec&, int32_t) override { + promise.set_value(); + return Return(); + } + + std::promise promise; +}; + +class ErrorCallback : public FaceCallbackBase { + public: + ErrorCallback(bool filterErrors = false, FaceError errorType = FaceError::HW_UNAVAILABLE) + : filterErrors(filterErrors), errorType(errorType), hasError(false) {} + + Return onError(uint64_t, int32_t, FaceError error, int32_t) override { + if ((filterErrors && errorType == error) || !filterErrors) { + hasError = true; + this->error = error; + promise.set_value(); + } + return Return(); + } + + bool filterErrors; + FaceError errorType; + bool hasError; + FaceError error; + std::promise promise; +}; + +class RemoveCallback : public FaceCallbackBase { + public: + explicit RemoveCallback(int32_t userId) : removeUserId(userId) {} + + Return onRemoved(uint64_t, uint32_t, int32_t userId, uint32_t remaining) override { + EXPECT_EQ(removeUserId, userId); + promise.set_value(); + if (remaining == 0UL) { + promise.set_value(); + } + return Return(); + } + + int32_t removeUserId; + std::promise promise; +}; + +// Test environment for Face HIDL HAL. +class FaceHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { + public: + // get the test environment singleton + static FaceHidlEnvironment* Instance() { + static FaceHidlEnvironment* instance = new FaceHidlEnvironment; + return instance; + } + + void registerTestServices() override { registerTestService(); } +}; + +class FaceHidlTest : public ::testing::VtsHalHidlTargetTestBase { + public: + void SetUp() override { + mService = ::testing::VtsHalHidlTargetTestBase::getService( + FaceHidlEnvironment::Instance()->getServiceName()); + ASSERT_FALSE(mService == nullptr); + Return res = mService->setActiveUser(kUserId, kTmpDir); + ASSERT_EQ(Status::OK, static_cast(res)); + } + + void TearDown() override {} + + sp mService; +}; + +// The service should be reachable. +TEST_F(FaceHidlTest, ConnectTest) { + sp cb = new FaceCallbackBase(); + mService->setCallback(cb, kAssertCallbackIsSet); +} + +// Starting the service with null callback should succeed. +TEST_F(FaceHidlTest, ConnectNullTest) { + mService->setCallback(nullptr, kAssertCallbackIsSet); +} + +// generateChallenge should always return a unique, cryptographically secure, +// non-zero number. +TEST_F(FaceHidlTest, GenerateChallengeTest) { + std::map m; + for (int i = 0; i < kIterations; ++i) { + mService->generateChallenge(kTimeout, [&m](const OptionalUint64& res) { + ASSERT_EQ(Status::OK, res.status); + EXPECT_NE(0UL, res.value); + m[res.value]++; + EXPECT_EQ(1UL, m[res.value]); + }); + } +} + +// enroll with an invalid (all zeroes) HAT should fail. +TEST_F(FaceHidlTest, EnrollZeroHatTest) { + sp cb = new ErrorCallback(); + mService->setCallback(cb, kAssertCallbackIsSet); + + hidl_vec token(69); + for (size_t i = 0; i < 69; i++) { + token[i] = 0; + } + + Return res = mService->enroll(token, kTimeout, {}); + ASSERT_EQ(Status::OK, static_cast(res)); + + // At least one call to onError should occur + ASSERT_TRUE(waitForCallback(cb->promise.get_future())); + ASSERT_TRUE(cb->hasError); +} + +// enroll with an invalid HAT should fail. +TEST_F(FaceHidlTest, EnrollGarbageHatTest) { + sp cb = new ErrorCallback(); + mService->setCallback(cb, kAssertCallbackIsSet); + + // Filling HAT with invalid data + hidl_vec token(69); + for (size_t i = 0; i < 69; ++i) { + token[i] = i; + } + + Return res = mService->enroll(token, kTimeout, {}); + ASSERT_EQ(Status::OK, static_cast(res)); + + // At least one call to onError should occur + ASSERT_TRUE(waitForCallback(cb->promise.get_future())); + ASSERT_TRUE(cb->hasError); +} + +// setFeature with an invalid (all zeros) HAT should fail. +TEST_F(FaceHidlTest, SetFeatureZeroHatTest) { + sp cb = new ErrorCallback(); + mService->setCallback(cb, kAssertCallbackIsSet); + + hidl_vec token(69); + for (size_t i = 0; i < 69; i++) { + token[i] = 0; + } + + Return res = mService->setFeature(Feature::REQUIRE_DIVERSITY, false, token); + ASSERT_EQ(Status::OK, static_cast(res)); + + // At least one call to onError should occur + ASSERT_TRUE(waitForCallback(cb->promise.get_future())); + ASSERT_TRUE(cb->hasError); +} + +// setFeature with an invalid HAT should fail. +TEST_F(FaceHidlTest, SetFeatureGarbageHatTest) { + sp cb = new ErrorCallback(); + mService->setCallback(cb, kAssertCallbackIsSet); + + // Filling HAT with invalid data + hidl_vec token(69); + for (size_t i = 0; i < 69; ++i) { + token[i] = i; + } + + Return res = mService->setFeature(Feature::REQUIRE_DIVERSITY, false, token); + ASSERT_EQ(Status::OK, static_cast(res)); + + // At least one call to onError should occur + ASSERT_TRUE(waitForCallback(cb->promise.get_future())); + ASSERT_TRUE(cb->hasError); +} + +// getFeature by default should return true for REQUIRE_ATTENTION. +TEST_F(FaceHidlTest, GetFeatureRequireAttentionTest) { + Return res = mService->getFeature(Feature::REQUIRE_ATTENTION); + ASSERT_EQ(true, static_cast(res)); +} + +// getFeature by default should return true for REQUIRE_DIVERSITY. +TEST_F(FaceHidlTest, GetFeatureRequireDiversityTest) { + Return res = mService->getFeature(Feature::REQUIRE_DIVERSITY); + ASSERT_EQ(true, static_cast(res)); +} + +// revokeChallenge should always return within the timeout +TEST_F(FaceHidlTest, RevokeChallengeTest) { + sp cb = new FaceCallbackBase(); + mService->setCallback(cb, kAssertCallbackIsSet); + + auto start = std::chrono::system_clock::now(); + mService->revokeChallenge(); + auto elapsed = std::chrono::system_clock::now() - start; + ASSERT_GE(kTimeoutInSeconds, elapsed); +} + +// The call to getAuthenticatorId should succeed. +TEST_F(FaceHidlTest, GetAuthenticatorIdTest) { + mService->getAuthenticatorId( + [](const OptionalUint64& res) { ASSERT_EQ(Status::OK, res.status); }); +} + +// The call to enumerate should succeed. +TEST_F(FaceHidlTest, EnumerateTest) { + sp cb = new EnumerateCallback(); + mService->setCallback(cb, kAssertCallbackIsSet); + Return res = mService->enumerate(); + ASSERT_EQ(Status::OK, static_cast(res)); + ASSERT_TRUE(waitForCallback(cb->promise.get_future())); +} + +// The call to remove should succeed for any faceId +TEST_F(FaceHidlTest, RemoveFaceTest) { + sp cb = new ErrorCallback(); + mService->setCallback(cb, kAssertCallbackIsSet); + + // Remove a face + Return res = mService->remove(kFaceId); + ASSERT_EQ(Status::OK, static_cast(res)); +} + +// Remove should accept 0 to delete all faces +TEST_F(FaceHidlTest, RemoveAllFacesTest) { + sp cb = new ErrorCallback(); + mService->setCallback(cb, kAssertCallbackIsSet); + + // Remove all faces + Return res = mService->remove(0); + ASSERT_EQ(Status::OK, static_cast(res)); +} + +// Active user should successfully set to a writable location. +TEST_F(FaceHidlTest, SetActiveUserTest) { + // Create an active user + Return res = mService->setActiveUser(2, kTmpDir); + ASSERT_EQ(Status::OK, static_cast(res)); + + // Reset active user + res = mService->setActiveUser(kUserId, kTmpDir); + ASSERT_EQ(Status::OK, static_cast(res)); +} + +// Active user should fail to set to an unwritable location. +TEST_F(FaceHidlTest, SetActiveUserUnwritableTest) { + // Create an active user to an unwritable location (device root dir) + Return res = mService->setActiveUser(3, "/"); + ASSERT_NE(Status::OK, static_cast(res)); + + // Reset active user + res = mService->setActiveUser(kUserId, kTmpDir); + ASSERT_EQ(Status::OK, static_cast(res)); +} + +// Active user should fail to set to a null location. +TEST_F(FaceHidlTest, SetActiveUserNullTest) { + // Create an active user to a null location. + Return res = mService->setActiveUser(4, nullptr); + ASSERT_NE(Status::OK, static_cast(res)); + + // Reset active user + res = mService->setActiveUser(kUserId, kTmpDir); + ASSERT_EQ(Status::OK, static_cast(res)); +} + +// Cancel should always return CANCELED from any starting state including +// the IDLE state. +TEST_F(FaceHidlTest, CancelTest) { + sp cb = new ErrorCallback(true, FaceError::CANCELED); + mService->setCallback(cb, kAssertCallbackIsSet); + + Return res = mService->cancel(); + // check that we were able to make an IPC request successfully + ASSERT_EQ(Status::OK, static_cast(res)); + + // make sure callback was invoked within kTimeoutInSeconds + ASSERT_TRUE(waitForCallback(cb->promise.get_future())); + // check error should be CANCELED + ASSERT_EQ(FaceError::CANCELED, cb->error); +} + +} // anonymous namespace + +int main(int argc, char** argv) { + ::testing::AddGlobalTestEnvironment(FaceHidlEnvironment::Instance()); + ::testing::InitGoogleTest(&argc, argv); + FaceHidlEnvironment::Instance()->init(&argc, argv); + int status = RUN_ALL_TESTS(); + LOG(INFO) << "Test result = " << status; + return status; +} From 5b3334648bb1decf51d46cf1a05dc2924b22619e Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Fri, 1 Mar 2019 14:07:22 -0800 Subject: [PATCH 516/718] wifi(implementation): Fix spammy log wifi.interface.0, etc should only be checked if the primary property used on most devices (wifi.interface & wifi.concurrent.interface) does not exist. wifi.interface.0, etc should only defined on Android auto platforms. Bug: 126925255 Test: Manually verified that the spammy log does not exist Change-Id: Ib5e6a87a7da2d4b26cdd35f668385b503e7c8006 --- wifi/1.3/default/wifi_chip.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/wifi/1.3/default/wifi_chip.cpp b/wifi/1.3/default/wifi_chip.cpp index 906f14a1c9..727aac534b 100644 --- a/wifi/1.3/default/wifi_chip.cpp +++ b/wifi/1.3/default/wifi_chip.cpp @@ -86,16 +86,15 @@ std::string getWlanIfaceName(unsigned idx) { } std::array buffer; - std::string propName = "wifi.interface." + std::to_string(idx); - auto res = property_get(propName.c_str(), buffer.data(), nullptr); - if (res > 0) return buffer.data(); - if (idx == 0 || idx == 1) { const char* altPropName = (idx == 0) ? "wifi.interface" : "wifi.concurrent.interface"; - res = property_get(altPropName, buffer.data(), nullptr); + auto res = property_get(altPropName, buffer.data(), nullptr); if (res > 0) return buffer.data(); } + std::string propName = "wifi.interface." + std::to_string(idx); + auto res = property_get(propName.c_str(), buffer.data(), nullptr); + if (res > 0) return buffer.data(); return "wlan" + std::to_string(idx); } From 4822938217da3274428b983264c206edd6f191e5 Mon Sep 17 00:00:00 2001 From: Ahmed ElArabawy Date: Thu, 7 Feb 2019 22:04:53 -0800 Subject: [PATCH 517/718] Add an api call to check if legacy hal is started This commit adds a public api call for legacy hal to check if it is successfully started. This is to be used by callers of legacy hal to make sure not to request functionality while legacy hal (and hence all interfaces) are not started. Bug: 112205428 Test: Manual Change-Id: I5183d01811e35edb3149cfb3784067c68b40e46d --- wifi/1.3/default/wifi_legacy_hal.cpp | 2 ++ wifi/1.3/default/wifi_legacy_hal.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/wifi/1.3/default/wifi_legacy_hal.cpp b/wifi/1.3/default/wifi_legacy_hal.cpp index 2b90f9200c..5aa98c416e 100644 --- a/wifi/1.3/default/wifi_legacy_hal.cpp +++ b/wifi/1.3/default/wifi_legacy_hal.cpp @@ -424,6 +424,8 @@ wifi_error WifiLegacyHal::stop( return WIFI_SUCCESS; } +bool WifiLegacyHal::isStarted() { return is_started_; } + std::pair WifiLegacyHal::getDriverVersion( const std::string& iface_name) { std::array buffer; diff --git a/wifi/1.3/default/wifi_legacy_hal.h b/wifi/1.3/default/wifi_legacy_hal.h index d6f05ae400..70a919f8ce 100644 --- a/wifi/1.3/default/wifi_legacy_hal.h +++ b/wifi/1.3/default/wifi_legacy_hal.h @@ -181,6 +181,8 @@ class WifiLegacyHal { // using a predefined timeout. virtual wifi_error stop(std::unique_lock* lock, const std::function& on_complete_callback); + // Checks if legacy HAL has successfully started + bool isStarted(); // Wrappers for all the functions in the legacy HAL function table. std::pair getDriverVersion( const std::string& iface_name); From b58b311ac79c273f38750a4cb2f7c6c5e60c6b84 Mon Sep 17 00:00:00 2001 From: Pawin Vongmasa Date: Mon, 25 Feb 2019 23:08:14 -0800 Subject: [PATCH 518/718] Add asInputSink() to IComponent By making IComponent present itself as an IInputSink, the wrapper code can be made to execute in the same process as the IComponent instance, hence reducing an IPC hop in the case where an InputSurface comes from a different process. Test: make cts -j123 && cts-tradefed run cts-dev -m \ CtsMediaTestCases --compatibility:module-arg \ CtsMediaTestCases:include-annotation:\ android.platform.test.annotations.RequiresDevice Bug: 126296132 Change-Id: I61409ccfa9a9d6b152e2c9363ff119302ce8ae1a --- current.txt | 2 +- media/c2/1.0/IComponent.hal | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/current.txt b/current.txt index caadefe7aa..8bb4440790 100644 --- a/current.txt +++ b/current.txt @@ -492,7 +492,7 @@ dd1ec219f5d2e2b33c6c0bcb92e63bbedb36f7c716413462848f6b6ae74fc864 android.hardwar aee53b2865b4f7939fb3df6fae758d9750c14f93dd454b479fc74aa7978fda4f android.hardware.media.bufferpool@2.0::IConnection 0bf3758eeeb05767830ea87041214be80968c4679fb73577ac5b3091841ee71f android.hardware.media.bufferpool@2.0::IObserver 82255e252ae215382473ad2e5ac7a2814a439a24f0092551aad7a2f89c6e9546 android.hardware.media.bufferpool@2.0::types -fd4725732511b8ae124b868fd0b2090386663dffc5e67dfd0d0b4a0b49c335db android.hardware.media.c2@1.0::IComponent +277161ea99236a0858e9fcc021c357db03be2de500acf5701d125e73e3e8071a android.hardware.media.c2@1.0::IComponent 389d06e4a4ecf60f828a260045b0c327a5ae883ee0856a3c054556dd22b1f450 android.hardware.media.c2@1.0::IComponentInterface 5ee0c02265c5505ade189796bef46697df4e0563e3544bb0c934855b34694b07 android.hardware.media.c2@1.0::IComponentListener 43d70bcdc63b3d042bac3c3297f5d941dfabbd08f3ceb96b6016cc14f6e34ba3 android.hardware.media.c2@1.0::IComponentStore diff --git a/media/c2/1.0/IComponent.hal b/media/c2/1.0/IComponent.hal index 7fd551fc2b..abd14482bd 100644 --- a/media/c2/1.0/IComponent.hal +++ b/media/c2/1.0/IComponent.hal @@ -22,6 +22,7 @@ import android.hardware.media.omx@1.0::IGraphicBufferSource; import IConfigurable; import IComponentInterface; import IComponentListener; +import IInputSink; import IInputSurface; import IInputSurfaceConnection; @@ -355,11 +356,19 @@ interface IComponent { * Returns the @ref IComponentInterface instance associated to this * component. * - * An @p IConfigurable instance for the component can be obtained by calling + * An @ref IConfigurable instance for the component can be obtained by calling * IComponentInterface::getConfigurable() on the returned @p intf. * * @return intf `IComponentInterface` instance. This must not be null. */ getInterface() generates (IComponentInterface intf); + + /** + * Returns an @ref IInputSink instance that has the component as the + * underlying implementation. + * + * @return sink `IInputSink` instance. + */ + asInputSink() generates (IInputSink sink); }; From b91ac5c6a0c0b76f17c19a1d3983d5faa1857eb6 Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Mon, 4 Mar 2019 12:00:03 -0800 Subject: [PATCH 519/718] Update makefies: no 'types' internal Bug: 123976090 Test: N/A Change-Id: I84b659b163b63d39535b462a3df8a9c19f680976 --- automotive/vehicle/2.0/Android.bp | 55 --------------------- biometrics/face/1.0/Android.bp | 9 ---- camera/device/3.5/Android.bp | 10 ---- camera/metadata/3.4/Android.bp | 13 ----- camera/provider/2.5/Android.bp | 3 -- drm/1.2/Android.bp | 5 -- gnss/2.0/Android.bp | 5 -- gnss/measurement_corrections/1.0/Android.bp | 6 --- graphics/bufferqueue/2.0/Android.bp | 5 -- graphics/common/1.2/Android.bp | 8 --- graphics/mapper/3.0/Android.bp | 4 -- input/common/1.0/Android.bp | 17 ------- media/bufferpool/2.0/Android.bp | 7 --- media/c2/1.0/Android.bp | 22 --------- sensors/2.0/Android.bp | 5 -- thermal/2.0/Android.bp | 8 --- tv/cec/2.0/Android.bp | 26 ---------- usb/1.2/Android.bp | 7 --- wifi/1.3/Android.bp | 5 -- wifi/supplicant/1.2/Android.bp | 6 --- 20 files changed, 226 deletions(-) diff --git a/automotive/vehicle/2.0/Android.bp b/automotive/vehicle/2.0/Android.bp index f64028c9ef..41638795b3 100644 --- a/automotive/vehicle/2.0/Android.bp +++ b/automotive/vehicle/2.0/Android.bp @@ -14,61 +14,6 @@ hidl_interface { interfaces: [ "android.hidl.base@1.0", ], - types: [ - "DiagnosticFloatSensorIndex", - "DiagnosticIntegerSensorIndex", - "EvConnectorType", - "FuelType", - "Obd2CommonIgnitionMonitors", - "Obd2CompressionIgnitionMonitors", - "Obd2FuelSystemStatus", - "Obd2FuelType", - "Obd2IgnitionMonitorKind", - "Obd2SecondaryAirStatus", - "Obd2SparkIgnitionMonitors", - "PortLocationType", - "StatusCode", - "SubscribeFlags", - "SubscribeOptions", - "VehicleApPowerStateConfigFlag", - "VehicleApPowerStateReport", - "VehicleApPowerStateReq", - "VehicleApPowerStateReqIndex", - "VehicleApPowerStateShutdownParam", - "VehicleArea", - "VehicleAreaConfig", - "VehicleAreaDoor", - "VehicleAreaMirror", - "VehicleAreaSeat", - "VehicleAreaWheel", - "VehicleAreaWindow", - "VehicleDisplay", - "VehicleGear", - "VehicleHvacFanDirection", - "VehicleHwKeyInputAction", - "VehicleIgnitionState", - "VehicleLightState", - "VehicleLightSwitch", - "VehicleOilLevel", - "VehiclePropConfig", - "VehiclePropValue", - "VehicleProperty", - "VehiclePropertyAccess", - "VehiclePropertyChangeMode", - "VehiclePropertyGroup", - "VehiclePropertyStatus", - "VehiclePropertyType", - "VehicleTurnSignal", - "VehicleUnit", - "VmsAvailabilityStateIntegerValuesIndex", - "VmsBaseMessageIntegerValuesIndex", - "VmsMessageType", - "VmsMessageWithLayerAndPublisherIdIntegerValuesIndex", - "VmsMessageWithLayerIntegerValuesIndex", - "VmsOfferingMessageIntegerValuesIndex", - "VmsPublisherInformationIntegerValuesIndex", - "VmsSubscriptionsStateIntegerValuesIndex", - ], gen_java: true, } diff --git a/biometrics/face/1.0/Android.bp b/biometrics/face/1.0/Android.bp index 0f8c6e646b..222a09e5e9 100644 --- a/biometrics/face/1.0/Android.bp +++ b/biometrics/face/1.0/Android.bp @@ -14,15 +14,6 @@ hidl_interface { interfaces: [ "android.hidl.base@1.0", ], - types: [ - "FaceAcquiredInfo", - "FaceError", - "Feature", - "OptionalBool", - "OptionalUint64", - "Status", - "UserHandle", - ], gen_java: true, } diff --git a/camera/device/3.5/Android.bp b/camera/device/3.5/Android.bp index 6d1836720d..d51fd0ef87 100644 --- a/camera/device/3.5/Android.bp +++ b/camera/device/3.5/Android.bp @@ -20,16 +20,6 @@ hidl_interface { "android.hardware.graphics.common@1.0", "android.hidl.base@1.0", ], - types: [ - "BufferRequest", - "BufferRequestStatus", - "CameraBlob", - "CameraBlobId", - "StreamBufferRequestError", - "StreamBufferRet", - "StreamBuffersVal", - "StreamConfiguration", - ], gen_java: false, } diff --git a/camera/metadata/3.4/Android.bp b/camera/metadata/3.4/Android.bp index d1cba14d0d..2b75eba51a 100644 --- a/camera/metadata/3.4/Android.bp +++ b/camera/metadata/3.4/Android.bp @@ -13,19 +13,6 @@ hidl_interface { "android.hardware.camera.metadata@3.2", "android.hardware.camera.metadata@3.3", ], - types: [ - "CameraMetadataEnumAndroidDepthAvailableDynamicDepthStreamConfigurations", - "CameraMetadataEnumAndroidHeicAvailableHeicStreamConfigurations", - "CameraMetadataEnumAndroidHeicInfoSupported", - "CameraMetadataEnumAndroidInfoSupportedBufferManagementVersion", - "CameraMetadataEnumAndroidRequestAvailableCapabilities", - "CameraMetadataEnumAndroidScalerAvailableFormats", - "CameraMetadataEnumAndroidScalerAvailableRecommendedStreamConfigurations", - "CameraMetadataEnumAndroidSensorInfoColorFilterArrangement", - "CameraMetadataSection", - "CameraMetadataSectionStart", - "CameraMetadataTag", - ], gen_java: true, } diff --git a/camera/provider/2.5/Android.bp b/camera/provider/2.5/Android.bp index 3de010a11b..a4af07e7c2 100644 --- a/camera/provider/2.5/Android.bp +++ b/camera/provider/2.5/Android.bp @@ -17,9 +17,6 @@ hidl_interface { "android.hardware.camera.provider@2.4", "android.hidl.base@1.0", ], - types: [ - "DeviceState", - ], gen_java: false, } diff --git a/drm/1.2/Android.bp b/drm/1.2/Android.bp index 4e0e8ba6e7..2d54302a58 100644 --- a/drm/1.2/Android.bp +++ b/drm/1.2/Android.bp @@ -19,11 +19,6 @@ hidl_interface { "android.hardware.drm@1.1", "android.hidl.base@1.0", ], - types: [ - "HdcpLevel", - "OfflineLicenseState", - "Status", - ], gen_java: false, } diff --git a/gnss/2.0/Android.bp b/gnss/2.0/Android.bp index 230dd907dd..c01ec55b99 100644 --- a/gnss/2.0/Android.bp +++ b/gnss/2.0/Android.bp @@ -24,11 +24,6 @@ hidl_interface { "android.hardware.gnss@1.1", "android.hidl.base@1.0", ], - types: [ - "ElapsedRealtime", - "ElapsedRealtimeFlags", - "GnssLocation", - ], gen_java: true, gen_java_constants: true, } diff --git a/gnss/measurement_corrections/1.0/Android.bp b/gnss/measurement_corrections/1.0/Android.bp index 237b008bba..4aac7e04c8 100644 --- a/gnss/measurement_corrections/1.0/Android.bp +++ b/gnss/measurement_corrections/1.0/Android.bp @@ -14,12 +14,6 @@ hidl_interface { "android.hardware.gnss@1.0", "android.hidl.base@1.0", ], - types: [ - "GnssSingleSatCorrectionFlags", - "MeasurementCorrections", - "ReflectingPlane", - "SingleSatCorrection", - ], gen_java: true, } diff --git a/graphics/bufferqueue/2.0/Android.bp b/graphics/bufferqueue/2.0/Android.bp index 5385f2806a..97c05faf1e 100644 --- a/graphics/bufferqueue/2.0/Android.bp +++ b/graphics/bufferqueue/2.0/Android.bp @@ -17,11 +17,6 @@ hidl_interface { "android.hardware.graphics.common@1.2", "android.hidl.base@1.0", ], - types: [ - "ConnectionType", - "SlotIndex", - "Status", - ], gen_java: true, } diff --git a/graphics/common/1.2/Android.bp b/graphics/common/1.2/Android.bp index b6cd865dd0..088bc377f6 100644 --- a/graphics/common/1.2/Android.bp +++ b/graphics/common/1.2/Android.bp @@ -14,14 +14,6 @@ hidl_interface { "android.hardware.graphics.common@1.0", "android.hardware.graphics.common@1.1", ], - types: [ - "BufferUsage", - "ColorMode", - "Dataspace", - "HardwareBuffer", - "Hdr", - "PixelFormat", - ], gen_java: true, gen_java_constants: true, } diff --git a/graphics/mapper/3.0/Android.bp b/graphics/mapper/3.0/Android.bp index b2f0aa69b5..e34829652b 100644 --- a/graphics/mapper/3.0/Android.bp +++ b/graphics/mapper/3.0/Android.bp @@ -17,10 +17,6 @@ hidl_interface { "android.hardware.graphics.common@1.2", "android.hidl.base@1.0", ], - types: [ - "Error", - "YCbCrLayout", - ], gen_java: false, } diff --git a/input/common/1.0/Android.bp b/input/common/1.0/Android.bp index 3de18b4961..07b38cf3e5 100644 --- a/input/common/1.0/Android.bp +++ b/input/common/1.0/Android.bp @@ -9,23 +9,6 @@ hidl_interface { srcs: [ "types.hal", ], - types: [ - "Action", - "Axis", - "Button", - "Classification", - "EdgeFlag", - "Flag", - "Meta", - "MotionEvent", - "PointerCoords", - "PointerProperties", - "PolicyFlag", - "Source", - "SourceClass", - "ToolType", - "VideoFrame", - ], gen_java: true, } diff --git a/media/bufferpool/2.0/Android.bp b/media/bufferpool/2.0/Android.bp index 1f8bbdb888..0faa00ef00 100644 --- a/media/bufferpool/2.0/Android.bp +++ b/media/bufferpool/2.0/Android.bp @@ -16,13 +16,6 @@ hidl_interface { interfaces: [ "android.hidl.base@1.0", ], - types: [ - "Buffer", - "BufferInvalidationMessage", - "BufferStatus", - "BufferStatusMessage", - "ResultStatus", - ], gen_java: false, } diff --git a/media/c2/1.0/Android.bp b/media/c2/1.0/Android.bp index 56c78b2e6e..6c836af1a4 100644 --- a/media/c2/1.0/Android.bp +++ b/media/c2/1.0/Android.bp @@ -25,28 +25,6 @@ hidl_interface { "android.hardware.media@1.0", "android.hidl.base@1.0", ], - types: [ - "BaseBlock", - "Block", - "Buffer", - "FieldDescriptor", - "FieldId", - "FieldSupportedValues", - "FieldSupportedValuesQuery", - "FieldSupportedValuesQueryResult", - "FrameData", - "InfoBuffer", - "ParamDescriptor", - "ParamField", - "ParamFieldValues", - "SettingResult", - "Status", - "StructDescriptor", - "Work", - "WorkBundle", - "WorkOrdinal", - "Worklet", - ], gen_java: false, } diff --git a/sensors/2.0/Android.bp b/sensors/2.0/Android.bp index 57d45ff473..eead1d3f28 100644 --- a/sensors/2.0/Android.bp +++ b/sensors/2.0/Android.bp @@ -15,11 +15,6 @@ hidl_interface { "android.hardware.sensors@1.0", "android.hidl.base@1.0", ], - types: [ - "EventQueueFlagBits", - "SensorTimeout", - "WakeLockQueueFlagBits", - ], gen_java: false, } diff --git a/thermal/2.0/Android.bp b/thermal/2.0/Android.bp index c513739e49..af23ee3df0 100644 --- a/thermal/2.0/Android.bp +++ b/thermal/2.0/Android.bp @@ -15,14 +15,6 @@ hidl_interface { "android.hardware.thermal@1.0", "android.hidl.base@1.0", ], - types: [ - "CoolingDevice", - "CoolingType", - "Temperature", - "TemperatureThreshold", - "TemperatureType", - "ThrottlingSeverity", - ], gen_java: true, } diff --git a/tv/cec/2.0/Android.bp b/tv/cec/2.0/Android.bp index 998cb23ecb..5a67fa55f6 100644 --- a/tv/cec/2.0/Android.bp +++ b/tv/cec/2.0/Android.bp @@ -15,32 +15,6 @@ hidl_interface { "android.hidl.base@1.0", "android.hidl.safe_union@1.0", ], - types: [ - "AbortReason", - "CecAllDeviceTypeValue", - "CecDeviceFeature", - "CecDeviceInfo", - "CecDeviceType", - "CecLogicalAddress", - "CecMessage", - "CecMessageType", - "CecPowerState", - "CecRcProfile", - "CecRcProfile1", - "CecRcProfileId", - "CecRcProfileSource", - "CecTopologyEvent", - "CecTopologyEventType", - "CecUICommandCodes", - "CecVersion", - "HdmiPortInfo", - "HdmiPortType", - "HotplugEvent", - "MaxLength", - "OptionKey", - "Result", - "SendMessageResult", - ], gen_java: true, } diff --git a/usb/1.2/Android.bp b/usb/1.2/Android.bp index 55ffad06b1..5206754d98 100644 --- a/usb/1.2/Android.bp +++ b/usb/1.2/Android.bp @@ -16,13 +16,6 @@ hidl_interface { "android.hardware.usb@1.1", "android.hidl.base@1.0", ], - types: [ - "ContaminantDetectionStatus", - "ContaminantProtectionMode", - "ContaminantProtectionStatus", - "PortStatus", - "Status", - ], gen_java: true, gen_java_constants: true, } diff --git a/wifi/1.3/Android.bp b/wifi/1.3/Android.bp index 8af1dc484e..401c7a618c 100644 --- a/wifi/1.3/Android.bp +++ b/wifi/1.3/Android.bp @@ -18,11 +18,6 @@ hidl_interface { "android.hardware.wifi@1.2", "android.hidl.base@1.0", ], - types: [ - "StaLinkLayerRadioStats", - "StaLinkLayerStats", - "WifiChannelStats", - ], gen_java: true, } diff --git a/wifi/supplicant/1.2/Android.bp b/wifi/supplicant/1.2/Android.bp index a0fc2b1b59..c685022b09 100644 --- a/wifi/supplicant/1.2/Android.bp +++ b/wifi/supplicant/1.2/Android.bp @@ -19,12 +19,6 @@ hidl_interface { "android.hardware.wifi.supplicant@1.1", "android.hidl.base@1.0", ], - types: [ - "DppAkm", - "DppFailureCode", - "DppNetRole", - "DppProgressCode", - ], gen_java: true, } From 7054ac55b873d9a4e90e2ef8f6a71f674ead0816 Mon Sep 17 00:00:00 2001 From: Kai Date: Mon, 4 Mar 2019 16:07:39 -0800 Subject: [PATCH 520/718] Add an annotation for property Add enum annotation for HVAC_TEMPERATURE_DISPLAY_UNITS Bug: 126925065 Test: make and flash to HU Change-Id: I083fee4401a3f6e43e69d86ff0e851cbc5ae32e2 --- automotive/vehicle/2.0/types.hal | 1 + 1 file changed, 1 insertion(+) diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal index e874146edf..7f203c4daa 100644 --- a/automotive/vehicle/2.0/types.hal +++ b/automotive/vehicle/2.0/types.hal @@ -990,6 +990,7 @@ enum VehicleProperty : int32_t { * * @change_mode VehiclePropertyChangeMode:ON_CHANGE * @access VehiclePropertyAccess:READ_WRITE + * @data_enum VehicleUnit */ HVAC_TEMPERATURE_DISPLAY_UNITS = ( 0x050E From 7948a04d010541a2060d0011b3433599ed442bc2 Mon Sep 17 00:00:00 2001 From: Jack Yu Date: Mon, 4 Mar 2019 17:31:09 -0800 Subject: [PATCH 521/718] Added VTS tests for setDataProfile and setInitialAttachApn Test: VTS Bug: 121345833 Change-Id: Ia7a260f5bbf9463c96b53656bcbe031af5208cbb --- .../1.4/vts/functional/radio_hidl_hal_api.cpp | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp index 4f347cd53f..8e1dc3e3fb 100644 --- a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp +++ b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp @@ -676,3 +676,85 @@ TEST_F(RadioHidlTest_v1_4, setAllowedCarriers_1_4) { } } } + +TEST_F(RadioHidlTest_v1_4, setDataProfile_1_4) { + serial = GetRandomSerialNumber(); + + // Create a dataProfileInfo + android::hardware::radio::V1_4::DataProfileInfo dataProfileInfo; + memset(&dataProfileInfo, 0, sizeof(dataProfileInfo)); + dataProfileInfo.profileId = DataProfileId::DEFAULT; + dataProfileInfo.apn = hidl_string("internet"); + dataProfileInfo.protocol = PdpProtocolType::IPV4V6; + dataProfileInfo.roamingProtocol = PdpProtocolType::IPV4V6; + dataProfileInfo.authType = ApnAuthType::NO_PAP_NO_CHAP; + dataProfileInfo.user = hidl_string("username"); + dataProfileInfo.password = hidl_string("password"); + dataProfileInfo.type = DataProfileInfoType::THREE_GPP; + dataProfileInfo.maxConnsTime = 300; + dataProfileInfo.maxConns = 20; + dataProfileInfo.waitTime = 0; + dataProfileInfo.enabled = true; + dataProfileInfo.supportedApnTypesBitmap = 320; + dataProfileInfo.bearerBitmap = 161543; + dataProfileInfo.mtu = 0; + dataProfileInfo.preferred = true; + dataProfileInfo.persistent = true; + + // Create a dataProfileInfoList + android::hardware::hidl_vec + dataProfileInfoList = {dataProfileInfo}; + + radio_v1_4->setDataProfile_1_4(serial, dataProfileInfoList); + + EXPECT_EQ(std::cv_status::no_timeout, wait()); + EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_4->rspInfo.type); + EXPECT_EQ(serial, radioRsp_v1_4->rspInfo.serial); + + if (cardStatus.base.base.cardState == CardState::ABSENT) { + ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, + {RadioError::SIM_ABSENT, RadioError::RADIO_NOT_AVAILABLE})); + } else if (cardStatus.base.base.cardState == CardState::PRESENT) { + ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, + {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE})); + } +} + +TEST_F(RadioHidlTest_v1_4, setInitialAttachApn_1_4) { + serial = GetRandomSerialNumber(); + + // Create a dataProfileInfo + android::hardware::radio::V1_4::DataProfileInfo dataProfileInfo; + memset(&dataProfileInfo, 0, sizeof(dataProfileInfo)); + dataProfileInfo.profileId = DataProfileId::DEFAULT; + dataProfileInfo.apn = hidl_string("internet"); + dataProfileInfo.protocol = PdpProtocolType::IPV4V6; + dataProfileInfo.roamingProtocol = PdpProtocolType::IPV4V6; + dataProfileInfo.authType = ApnAuthType::NO_PAP_NO_CHAP; + dataProfileInfo.user = hidl_string("username"); + dataProfileInfo.password = hidl_string("password"); + dataProfileInfo.type = DataProfileInfoType::THREE_GPP; + dataProfileInfo.maxConnsTime = 300; + dataProfileInfo.maxConns = 20; + dataProfileInfo.waitTime = 0; + dataProfileInfo.enabled = true; + dataProfileInfo.supportedApnTypesBitmap = 320; + dataProfileInfo.bearerBitmap = 161543; + dataProfileInfo.mtu = 0; + dataProfileInfo.preferred = true; + dataProfileInfo.persistent = false; + + radio_v1_4->setInitialAttachApn_1_4(serial, dataProfileInfo); + + EXPECT_EQ(std::cv_status::no_timeout, wait()); + EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_4->rspInfo.type); + EXPECT_EQ(serial, radioRsp_v1_4->rspInfo.serial); + + if (cardStatus.base.base.cardState == CardState::ABSENT) { + ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, + {RadioError::SIM_ABSENT, RadioError::RADIO_NOT_AVAILABLE})); + } else if (cardStatus.base.base.cardState == CardState::PRESENT) { + ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, + {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE})); + } +} From 0388c2bc1c7e6b0eb55682a4091c495b5577ba18 Mon Sep 17 00:00:00 2001 From: Yin-Chia Yeh Date: Tue, 26 Feb 2019 14:31:26 -0800 Subject: [PATCH 522/718] Camera: fill in num_output_buffers And also assert fence import should never fail. Test: none Bug: 125472550 Change-Id: Ib9bcc0234108ed0c752d5245d75fca6972e0c8ed --- .../3.5/default/CameraDeviceSession.cpp | 25 +++++++------------ 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/camera/device/3.5/default/CameraDeviceSession.cpp b/camera/device/3.5/default/CameraDeviceSession.cpp index bea1be6d53..e812e50f5f 100644 --- a/camera/device/3.5/default/CameraDeviceSession.cpp +++ b/camera/device/3.5/default/CameraDeviceSession.cpp @@ -273,6 +273,7 @@ camera3_buffer_request_status_t CameraDeviceSession::requestStreamBuffers( int streamId = bufRets[i].streamId; const hidl_vec& hBufs = bufRets[i].val.buffers(); camera3_stream_buffer_t* outBufs = returned_buf_reqs[i].output_buffers; + returned_buf_reqs[i].num_output_buffers = hBufs.size(); for (size_t b = 0; b < hBufs.size(); b++) { const StreamBuffer& hBuf = hBufs[b]; camera3_stream_buffer_t& outBuf = outBufs[b]; @@ -281,27 +282,19 @@ camera3_buffer_request_status_t CameraDeviceSession::requestStreamBuffers( hBuf.bufferId, hBuf.buffer.getNativeHandle(), /*out*/&(outBuf.buffer), /*allowEmptyBuf*/false); - if (s != Status::OK) { - ALOGE("%s: import stream %d bufferId %" PRIu64 " failed!", - __FUNCTION__, streamId, hBuf.bufferId); - cleanupInflightBufferFences(importedFences, importedBuffers); - // Buffer import should never fail - restart HAL since something is very - // wrong. - assert(false); - return CAMERA3_BUF_REQ_FAILED_UNKNOWN; - } + // Buffer import should never fail - restart HAL since something is very wrong. + LOG_ALWAYS_FATAL_IF(s != Status::OK, + "%s: import stream %d bufferId %" PRIu64 " failed!", + __FUNCTION__, streamId, hBuf.bufferId); pushBufferId(*(outBuf.buffer), hBuf.bufferId, streamId); importedBuffers.push_back(std::make_pair(*(outBuf.buffer), streamId)); - if (!sHandleImporter.importFence( - hBuf.acquireFence, - outBuf.acquire_fence)) { - ALOGE("%s: stream %d bufferId %" PRIu64 "acquire fence is invalid", + bool succ = sHandleImporter.importFence(hBuf.acquireFence, outBuf.acquire_fence); + // Fence import should never fail - restart HAL since something is very wrong. + LOG_ALWAYS_FATAL_IF(!succ, + "%s: stream %d bufferId %" PRIu64 "acquire fence is invalid", __FUNCTION__, streamId, hBuf.bufferId); - cleanupInflightBufferFences(importedFences, importedBuffers); - return CAMERA3_BUF_REQ_FAILED_UNKNOWN; - } importedFences.push_back(outBuf.acquire_fence); outBuf.stream = returned_buf_reqs[i].stream; outBuf.status = CAMERA3_BUFFER_STATUS_OK; From 25fe23f55f16f252b44e79229f3f2f1f3fc37aa4 Mon Sep 17 00:00:00 2001 From: Kevin Chyn Date: Mon, 4 Mar 2019 15:35:40 -0800 Subject: [PATCH 523/718] Finalize IBiometricsFace@1.0 Also update VTS tests Fixes: 125936336 Fixes: 124512763 Fixes: 123262389 Test: hidl-gen -L hash -r android.hardware:hardware/interfaces android.hardware.biometrics.face@1.0 add updated hash to current.txt Test: Builds Change-Id: I7949b251064d4578a89f6da834aadbfdf7e9a94f --- biometrics/face/1.0/IBiometricsFace.hal | 93 ++++++++++++------- .../1.0/IBiometricsFaceClientCallback.hal | 2 +- biometrics/face/1.0/types.hal | 18 ++-- .../VtsHalBiometricsFaceV1_0TargetTest.cpp | 63 +++++++++---- current.txt | 6 +- 5 files changed, 118 insertions(+), 64 deletions(-) diff --git a/biometrics/face/1.0/IBiometricsFace.hal b/biometrics/face/1.0/IBiometricsFace.hal index 0499c5d0fd..cd368faddb 100644 --- a/biometrics/face/1.0/IBiometricsFace.hal +++ b/biometrics/face/1.0/IBiometricsFace.hal @@ -53,6 +53,10 @@ interface IBiometricsFace { * returning to the idle state. Calling this method with the same userId * should have no effect on the state machine. * + * Note that onLockoutChanged() MUST be invoked by the implementation in + * response to a user change in order to update the framework with the + * timeout of the new user (or 0 if the user is not locked out). + * * @param userId A non-negative user identifier that must be unique and * persistent for a given user. * @param storePath filesystem path to the template storage directory. @@ -61,19 +65,22 @@ interface IBiometricsFace { setActiveUser(int32_t userId, string storePath) generates (Status status); /** - * Begins a secure transaction request, e.g. enrollment. + * Begins a secure transaction request, e.g. enroll() or resetLockout(). * * Generates a unique and cryptographically secure random token used to * indicate the start of a secure transaction. generateChallenge() and - * revokeChallenge() specify a pin/pattern/password cleared time window where - * the secure transaction is allowed. + * revokeChallenge() specify a window where the resulting HAT that is + * generated in response to checking the user's PIN/pattern/password + * can be used to verify/perform a secure transaction. * - * generateChallenge() generates a challenge which must then be wrapped by the + * generateChallenge() generates a challenge which must then be wrapped by * gatekeeper after verifying a successful strong authentication attempt, * which generates a Hardware Authentication Token. The challenge prevents - * spoofing and replay attacks and ensures that we only update a user’s face - * template if the operation was preceded by some kind of strong credential - * confirmation (e.g. device password). + * spoofing and replay attacks and ensures that only a transaction backed + * by a user authentication (PIN/pattern/password) can proceed. + * + * The implementation should be tolerant of revokeChallenge() being invoked + * after timeout has expired. * * @param challengeTimeoutSec A timeout in seconds, after which the driver * must invalidate the challenge. This is to prevent bugs or crashes in @@ -81,35 +88,35 @@ interface IBiometricsFace { * @return result, with its "value" parameter representing a "challenge": a * unique and cryptographically secure random token. */ - @callflow(next={"enroll", "revokeChallenge", "setFeatureDisabled"}) + @callflow(next={"enroll", "revokeChallenge", "setFeature"}) generateChallenge(uint32_t challengeTimeoutSec) generates (OptionalUint64 result); /** * Enrolls a user's face. * - * Note that this interface permits implementations where multiple faces can - * be enrolled for a single user. However, allowing multiple faces to be - * enrolled can be a severe security vulnerability and hence, most - * implementations must ensure that only a single face be enrolled at a - * given time. Multi-enrollment must only be used where there is a clear - * necessity for a shared use case, e.g. TVs or cars. - * - * Note that the Hardware Authentication Token must still be valid after - * this call, and must be explicitly invalidated by a call to - * revokeChallenge(). This allows clients to immediately reattempt - * enrollment (for example, if a user wasn’t satisfied with their enrollment) - * without having to go through another strong authentication flow. + * Note that the Hardware Authentication Token must be valid for the + * duration of enrollment and thus should be explicitly invalidated by a + * call to revokeChallenge() when enrollment is complete, to reduce the + * window of opportunity to re-use the challenge and HAT. For example, + * Settings calls generateChallenge() once to allow the user to enroll one + * or more faces or toggle secure settings without having to re-enter the + * PIN/pattern/password. Once the user completes the operation, Settings + * invokes revokeChallenge() to close the transaction. If the HAT is expired, + * the implementation must invoke onError with UNABLE_TO_PROCESS. * * This method triggers the IBiometricsFaceClientCallback#onEnrollResult() * method. * * @param hat A valid Hardware Authentication Token, generated as a result * of a generateChallenge() challenge being wrapped by the gatekeeper - * after a sucessful strong authentication request. - * @param timeoutSec A timeout in seconds, after which this enrollment - * attempt is cancelled. Note that the client still needs to - * call revokeChallenge() to terminate the enrollment session. + * after a successful strong authentication request. + * @param timeoutSec A timeout in seconds, after which this enroll + * attempt is cancelled. Note that the framework can continue + * enrollment by calling this again with a valid HAT. This timeout is + * expected to be used to limit power usage if the device becomes idle + * during enrollment. The implementation is expected to send + * ERROR_TIMEOUT if this happens. * @param disabledFeatures A list of features to be disabled during * enrollment. Note that all features are enabled by default. * @return status The status of this method call. @@ -122,8 +129,8 @@ interface IBiometricsFace { * Finishes the secure transaction by invalidating the challenge generated * by generateChallenge(). * - * Clients must call this method once enrollment is complete, and the user's - * face template no longer needs to be updated. + * Clients must call this method once the secure transaction (e.g. enroll + * or setFeature) is completed. See generateChallenge(). * * @return status The status of this method call. */ @@ -131,33 +138,43 @@ interface IBiometricsFace { revokeChallenge() generates (Status status); /** - * Requires all subsequent enroll/authenticate calls to use the feature. - * This method does not affect enroll, which has its own feature list. - * * Changes the state of previous enrollment setting. Because this may * decrease security, the user must enter their password before this method * is invoked (see @param HAT). The driver must verify the HAT before - * changing any feature state. + * changing any feature state. This method must return ILLEGAL_ARGUMENT if + * the HAT or faceId is invalid. This must only be invoked after + * setActiveUser() is called. + * * Note: In some cases it may not be possible to change the state of this * flag without re-enrolling. For example, if the user didn't provide * attention during the original enrollment. This flag reflects the same * persistent state as the one passed to enroll(). * + * Note: This call may block for a short amount of time (few hundred + * milliseconds). Clients are expected to invoke this asynchronously if it + * takes much longer than the above limit. Also note that the result is + * returned solely through Status (and not onError). + * * @param feature The feature to be enabled or disabled. * @param enabled True to enable the feature, false to disable. * @param hat A valid Hardware Authentication Token, generated as a result * of getChallenge(). + * @param faceId the ID of the enrollment returned by enroll() for the + * feature to update. * @return status The status of this method call. */ - setFeature(Feature feature, bool enabled, vec hat) + setFeature(Feature feature, bool enabled, vec hat, uint32_t faceId) generates(Status status); /** - * Retrieves the current state of the feature. + * Retrieves the current state of the feature. If the faceId is invalid, + * the implementation must return ILLEGAL_ARGUMENT. * - * @return enabled True if the feature is enabled, false if disabled. + * @param faceId the ID of the enrollment returned by enroll(). + * @return result with the value set to true if the feature is enabled, + * false if disabled. */ - getFeature(Feature feature) generates (bool enabled); + getFeature(Feature feature, uint32_t faceId) generates (OptionalBool result); /** * Returns an identifier associated with the current face set. @@ -176,7 +193,7 @@ interface IBiometricsFace { getAuthenticatorId() generates (OptionalUint64 result); /** - * Cancels a pending enrollment or authentication request. + * Cancels the current enroll, authenticate, remove, or enumerate operation. * * @return status The status of this method call. */ @@ -241,8 +258,12 @@ interface IBiometricsFace { /** * Reset lockout for the current user. * + * Note: This call may block for a short amount of time (few hundred + * milliseconds). Clients are expected to invoke this asynchronously if it + * takes much longer than the above limit. + * * @param hat A valid Hardware Authentication Token, generated when the - * user authenticates with Pin/Pattern/Pass. When the Hardware + * user authenticates with PIN/pattern/pass. When the Hardware * Authentication Token is verified, lockout must be reset and * onLockoutChanged must be called with duration 0. * @return status The status of this method call. diff --git a/biometrics/face/1.0/IBiometricsFaceClientCallback.hal b/biometrics/face/1.0/IBiometricsFaceClientCallback.hal index c9dd0e2628..969bc68590 100644 --- a/biometrics/face/1.0/IBiometricsFaceClientCallback.hal +++ b/biometrics/face/1.0/IBiometricsFaceClientCallback.hal @@ -39,7 +39,7 @@ interface IBiometricsFaceClientCallback { * A callback invoked when a face has been successfully authenticated. * * @param deviceId A unique id associated with the HAL implementation - * service that processed this autentication attempt. + * service that processed this authentication attempt. * @param faceId The id of the face template that passed the authentication * challenge. * @param userId The active user id for the authenticated face. diff --git a/biometrics/face/1.0/types.hal b/biometrics/face/1.0/types.hal index b5db966b47..8c4a4e9f4e 100644 --- a/biometrics/face/1.0/types.hal +++ b/biometrics/face/1.0/types.hal @@ -82,13 +82,14 @@ enum Feature : uint32_t { enum FaceError : int32_t { /** - * A hardware error has occured that cannot be resolved. Try again later. + * A hardware error has occurred that cannot be resolved. Try again later. */ HW_UNAVAILABLE = 1, /** - * The current enroll or authenticate operation could not be completed; - * the sensor was unable to process the current image. + * The current enroll or authenticate operation could not be completed, + * e.g. the sensor was unable to process the current image or the HAT was + * invalid. */ UNABLE_TO_PROCESS = 2, @@ -97,6 +98,11 @@ enum FaceError : int32_t { * prevent programs from blocking the face HAL indefinitely. The timeout is * framework and sensor-specific, but is generally on the order of 30 * seconds. + + * The timeout is a device-specific time meant to optimize power. For + * example after 30 seconds of searching for a face it can be use to + * indicate that the implementation is no longer looking and the framework + * should restart the operation on the next user interaction. */ TIMEOUT = 3, @@ -108,8 +114,8 @@ enum FaceError : int32_t { /** * The current operation has been cancelled. This may happen if a new - * request (authenticate, remove) is initiated while an on-going operation - * is in progress, or if cancel() was called. + * request (authenticate, remove, enumerate, enroll) is initiated while + * an on-going operation is in progress, or if cancel() was called. */ CANCELED = 5, @@ -357,7 +363,7 @@ struct OptionalUint64 { /** * Result structure with an addition bool field. See documentation in - * getRequireAttention() for usage of the value. + * getFeature() for usage of the value. */ struct OptionalBool { /** diff --git a/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp b/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp index f496bbe642..795a1ae961 100644 --- a/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp +++ b/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp @@ -42,6 +42,7 @@ using android::hardware::biometrics::face::V1_0::FaceError; using android::hardware::biometrics::face::V1_0::Feature; using android::hardware::biometrics::face::V1_0::IBiometricsFace; using android::hardware::biometrics::face::V1_0::IBiometricsFaceClientCallback; +using android::hardware::biometrics::face::V1_0::OptionalBool; using android::hardware::biometrics::face::V1_0::OptionalUint64; using android::hardware::biometrics::face::V1_0::Status; @@ -167,6 +168,19 @@ class RemoveCallback : public FaceCallbackBase { std::promise promise; }; +class LockoutChangedCallback : public FaceCallbackBase { + public: + Return onLockoutChanged(uint64_t duration) override { + this->hasDuration = true; + this->duration = duration; + promise.set_value(); + return Return(); + } + bool hasDuration; + uint64_t duration; + std::promise promise; +}; + // Test environment for Face HIDL HAL. class FaceHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { public: @@ -266,12 +280,8 @@ TEST_F(FaceHidlTest, SetFeatureZeroHatTest) { token[i] = 0; } - Return res = mService->setFeature(Feature::REQUIRE_DIVERSITY, false, token); - ASSERT_EQ(Status::OK, static_cast(res)); - - // At least one call to onError should occur - ASSERT_TRUE(waitForCallback(cb->promise.get_future())); - ASSERT_TRUE(cb->hasError); + Return res = mService->setFeature(Feature::REQUIRE_DIVERSITY, false, token, 0); + ASSERT_EQ(Status::ILLEGAL_ARGUMENT, static_cast(res)); } // setFeature with an invalid HAT should fail. @@ -285,24 +295,27 @@ TEST_F(FaceHidlTest, SetFeatureGarbageHatTest) { token[i] = i; } - Return res = mService->setFeature(Feature::REQUIRE_DIVERSITY, false, token); - ASSERT_EQ(Status::OK, static_cast(res)); - - // At least one call to onError should occur - ASSERT_TRUE(waitForCallback(cb->promise.get_future())); - ASSERT_TRUE(cb->hasError); + Return res = mService->setFeature(Feature::REQUIRE_DIVERSITY, false, token, 0); + ASSERT_EQ(Status::ILLEGAL_ARGUMENT, static_cast(res)); +} + +void assertGetFeatureFails(sp service, int faceId, Feature feature) { + std::promise promise; + + // Features cannot be retrieved for invalid faces. + Return res = service->getFeature(feature, faceId, [&promise](const OptionalBool& result) { + ASSERT_EQ(Status::ILLEGAL_ARGUMENT, result.status); + promise.set_value(); + }); + ASSERT_TRUE(waitForCallback(promise.get_future())); } -// getFeature by default should return true for REQUIRE_ATTENTION. TEST_F(FaceHidlTest, GetFeatureRequireAttentionTest) { - Return res = mService->getFeature(Feature::REQUIRE_ATTENTION); - ASSERT_EQ(true, static_cast(res)); + assertGetFeatureFails(mService, 0 /* faceId */, Feature::REQUIRE_ATTENTION); } -// getFeature by default should return true for REQUIRE_DIVERSITY. TEST_F(FaceHidlTest, GetFeatureRequireDiversityTest) { - Return res = mService->getFeature(Feature::REQUIRE_DIVERSITY); - ASSERT_EQ(true, static_cast(res)); + assertGetFeatureFails(mService, 0 /* faceId */, Feature::REQUIRE_DIVERSITY); } // revokeChallenge should always return within the timeout @@ -400,6 +413,20 @@ TEST_F(FaceHidlTest, CancelTest) { ASSERT_EQ(FaceError::CANCELED, cb->error); } +TEST_F(FaceHidlTest, OnLockoutChangedTest) { + sp cb = new LockoutChangedCallback(); + mService->setCallback(cb, kAssertCallbackIsSet); + + // Update active user and ensure lockout duration 0 is received + mService->setActiveUser(5, kTmpDir); + + // Make sure callback was invoked + ASSERT_TRUE(waitForCallback(cb->promise.get_future())); + + // Check that duration 0 was received + ASSERT_EQ(0, cb->duration); +} + } // anonymous namespace int main(int argc, char** argv) { diff --git a/current.txt b/current.txt index bb9b22f7e2..6a4f9cbba4 100644 --- a/current.txt +++ b/current.txt @@ -435,9 +435,9 @@ ca15a738dedc2f4981925f7d7ff29c22bc3f8a848403dcf0c592c167de09d9af android.hardwar 443659bb9e27221e5da0d16c7a0ecb2dc3a9a03acc8a0b2196b47c50735e2d2e android.hardware.audio.effect@5.0::IVirtualizerEffect 78fed26a781cdca1b3bcb37520bff705d7764ee81db9cfd37014953c7ad2596e android.hardware.audio.effect@5.0::IVisualizerEffect 6385b6accab8a544e2ee54ba7bf5aa55dff6153bcedd80fdaae16fe9e0be7050 android.hardware.audio.effect@5.0::types -2f11e4c10ebe2b600426e0695f3c720d21663501c1c9449537055f13f37600d3 android.hardware.biometrics.face@1.0::IBiometricsFace -dfb0666af59eb306c82a6f576c65a160e6829d3324211a10429fd63768df70df android.hardware.biometrics.face@1.0::IBiometricsFaceClientCallback -cc40d308f38b6a218fcf99f264ebb49544fce670a6abdf294c617357a3d83dad android.hardware.biometrics.face@1.0::types +baf5a0cbf357035394be02d87334890228338fae715f7ab06e2f0e7d05abe656 android.hardware.biometrics.face@1.0::IBiometricsFace +6cbf288d6e6a9f6f0c09d1cde66318aa5b6a8c525778a61ccaedddb090f5e9cb android.hardware.biometrics.face@1.0::IBiometricsFaceClientCallback +ef5d339413d0c94a5b58baafbe3e4bccfd9ed2e7328fbbb5c25471c79923ed2f android.hardware.biometrics.face@1.0::types ecedc58dbcdb13503c19c0ab160ac1dd0530bb1471164149282dd1463c684185 android.hardware.bluetooth.audio@2.0::IBluetoothAudioPort fb9c40e4deab40be5476477078fe3d8a4a4495fd9deef4321878d169d675c633 android.hardware.bluetooth.audio@2.0::IBluetoothAudioProvider f7431f3e3e4e3387fc6f27a6cf423eddcd824a395dc4349d302c995ab44a9895 android.hardware.bluetooth.audio@2.0::IBluetoothAudioProvidersFactory From f09054c17440d952a803aadae2c4e4495e4fba52 Mon Sep 17 00:00:00 2001 From: Shuzhen Wang Date: Thu, 28 Feb 2019 15:27:07 -0800 Subject: [PATCH 524/718] Camera: Make availablePhysicalRequestKeys ndk public Test: camera ndk CTS Bug: 115532726 Change-Id: I6a0e6c8bc14e68bddcd0a5617a706b16520ff871 --- camera/metadata/3.3/types.hal | 2 +- current.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/camera/metadata/3.3/types.hal b/camera/metadata/3.3/types.hal index 27d82b991a..1ed8ed8a0c 100644 --- a/camera/metadata/3.3/types.hal +++ b/camera/metadata/3.3/types.hal @@ -98,7 +98,7 @@ enum CameraMetadataTag : @3.2::CameraMetadataTag { */ ANDROID_REQUEST_AVAILABLE_SESSION_KEYS = android.hardware.camera.metadata@3.2::CameraMetadataTag:ANDROID_REQUEST_END, - /** android.request.availablePhysicalCameraRequestKeys [static, int32[], hidden] + /** android.request.availablePhysicalCameraRequestKeys [static, int32[], ndk_public] * *

A subset of the available request keys that can be overridden for * physical devices backing a logical multi-camera.

diff --git a/current.txt b/current.txt index 8e790f8243..768f7d5a22 100644 --- a/current.txt +++ b/current.txt @@ -390,7 +390,7 @@ cd4330c3196bda1d642a32abfe23a7d64ebfbda721940643af6867af3b3f0aa9 android.hardwar 684702a60deef03a1e8093961dc0a18c555c857ad5a77ba7340b0635ae01eb70 android.hardware.camera.device@3.4::ICameraDeviceSession f8a19622cb0cc890913b1ef3e32b675ffb26089a09e02fef4056ebad324d2b5d android.hardware.camera.device@3.4::types 291638a1b6d4e63283e9e722ab5049d9351717ffa2b66162124f84d1aa7c2835 android.hardware.camera.metadata@3.2::types -8a075cf3a17fe99c6d23415a3e9a65612f1fee73ee052a3a8a0ca5b8877395a4 android.hardware.camera.metadata@3.3::types +a31142da4cc87ad50e4e981d12291d4decbb432fcb00f175f0ca904d0fcdbe5b android.hardware.camera.metadata@3.3::types da33234403ff5d60f3473711917b9948e6484a4260b5247acdafb111193a9de2 android.hardware.configstore@1.0::ISurfaceFlingerConfigs 21165b8e30c4b2d52980e4728f661420adc16e38bbe73476c06b2085be908f4c android.hardware.gnss@1.0::IGnssCallback d702fb01dc2a0733aa820b7eb65435ee3334f75632ef880bafd2fb8803a20a58 android.hardware.gnss@1.0::IGnssMeasurementCallback From 08642f98a4080ade37a2ba643fdc74e31dd5811a Mon Sep 17 00:00:00 2001 From: Yu-Han Yang Date: Sat, 2 Mar 2019 14:22:14 -0800 Subject: [PATCH 525/718] Add VTS test for gnss.measurement_corrections@1.0 - also implemented default implementation Bug: 120529158 Fixes: 120529158 Test: tested on cuttlefish Change-Id: I9e63dc35284effff351eabedade05ed147d1ef17 --- gnss/1.1/vts/functional/Android.bp | 3 + gnss/2.0/default/Android.bp | 1 + gnss/2.0/default/Gnss.cpp | 7 ++- .../default/GnssMeasurementCorrections.cpp | 62 +++++++++++++++++++ gnss/2.0/default/GnssMeasurementCorrections.h | 48 ++++++++++++++ .../vts/functional/gnss_hal_test_cases.cpp | 22 +++++++ gnss/common/utils/vts/Android.bp | 1 + gnss/common/utils/vts/Utils.cpp | 48 ++++++++++++++ gnss/common/utils/vts/include/Utils.h | 3 + 9 files changed, 193 insertions(+), 2 deletions(-) create mode 100644 gnss/2.0/default/GnssMeasurementCorrections.cpp create mode 100644 gnss/2.0/default/GnssMeasurementCorrections.h diff --git a/gnss/1.1/vts/functional/Android.bp b/gnss/1.1/vts/functional/Android.bp index 147a470f8a..cc34290fa8 100644 --- a/gnss/1.1/vts/functional/Android.bp +++ b/gnss/1.1/vts/functional/Android.bp @@ -27,5 +27,8 @@ cc_test { "android.hardware.gnss@1.1", "android.hardware.gnss@common-vts-lib", ], + shared_libs: [ + "android.hardware.gnss.measurement_corrections@1.0", + ], test_suites: ["general-tests"], } diff --git a/gnss/2.0/default/Android.bp b/gnss/2.0/default/Android.bp index f327197f62..64187e24d9 100644 --- a/gnss/2.0/default/Android.bp +++ b/gnss/2.0/default/Android.bp @@ -26,6 +26,7 @@ cc_binary { "AGnssRil.cpp", "Gnss.cpp", "GnssMeasurement.cpp", + "GnssMeasurementCorrections.cpp", "GnssVisibilityControl.cpp", "service.cpp" ], diff --git a/gnss/2.0/default/Gnss.cpp b/gnss/2.0/default/Gnss.cpp index 33edbd56eb..ee6da5374c 100644 --- a/gnss/2.0/default/Gnss.cpp +++ b/gnss/2.0/default/Gnss.cpp @@ -25,11 +25,14 @@ #include "AGnssRil.h" #include "GnssConfiguration.h" #include "GnssMeasurement.h" +#include "GnssMeasurementCorrections.h" #include "GnssVisibilityControl.h" #include "Utils.h" using ::android::hardware::Status; using ::android::hardware::gnss::common::Utils; +using ::android::hardware::gnss::measurement_corrections::V1_0::implementation:: + GnssMeasurementCorrections; using ::android::hardware::gnss::visibility_control::V1_0::implementation::GnssVisibilityControl; namespace android { @@ -248,8 +251,8 @@ Return> Gnss::getExtensionGnssMeasurement_2_0() { Return> Gnss::getExtensionMeasurementCorrections() { - // TODO(b/124012850): Implement function. - return sp{}; + ALOGD("Gnss::getExtensionMeasurementCorrections"); + return new GnssMeasurementCorrections(); } Return> Gnss::getExtensionVisibilityControl() { diff --git a/gnss/2.0/default/GnssMeasurementCorrections.cpp b/gnss/2.0/default/GnssMeasurementCorrections.cpp new file mode 100644 index 0000000000..cbf34ba9c3 --- /dev/null +++ b/gnss/2.0/default/GnssMeasurementCorrections.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "GnssMeasurementCorrections" + +#include "GnssMeasurementCorrections.h" +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace measurement_corrections { +namespace V1_0 { +namespace implementation { + +// Methods from V1_0::IMeasurementCorrections follow. +Return GnssMeasurementCorrections::setCorrections(const MeasurementCorrections& corrections) { + ALOGD("setCorrections"); + ALOGD("corrections = lat: %f, lng: %f, alt: %f, hUnc: %f, vUnc: %f, toa: %llu, " + "satCorrections.size: %d", + corrections.latitudeDegrees, corrections.longitudeDegrees, corrections.altitudeMeters, + corrections.horizontalPositionUncertaintyMeters, + corrections.verticalPositionUncertaintyMeters, + static_cast(corrections.toaGpsNanosecondsOfWeek), + static_cast(corrections.satCorrections.size())); + for (auto singleSatCorrection : corrections.satCorrections) { + ALOGD("singleSatCorrection = flags: %d, constellation: %d, svid: %d, cfHz: %f, probLos: %f," + " epl: %f, eplUnc: %f", + static_cast(singleSatCorrection.singleSatCorrectionFlags), + static_cast(singleSatCorrection.constellation), + static_cast(singleSatCorrection.svid), singleSatCorrection.carrierFrequencyHz, + singleSatCorrection.probSatIsLos, singleSatCorrection.excessPathLengthMeters, + singleSatCorrection.excessPathLengthUncertaintyMeters); + ALOGD("reflecting plane = lat: %f, lng: %f, alt: %f, azm: %f", + singleSatCorrection.reflectingPlane.latitudeDegrees, + singleSatCorrection.reflectingPlane.longitudeDegrees, + singleSatCorrection.reflectingPlane.altitudeMeters, + singleSatCorrection.reflectingPlane.azimuthDegrees); + } + + return true; +} + +} // namespace implementation +} // namespace V1_0 +} // namespace measurement_corrections +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/gnss/2.0/default/GnssMeasurementCorrections.h b/gnss/2.0/default/GnssMeasurementCorrections.h new file mode 100644 index 0000000000..f758bc8a08 --- /dev/null +++ b/gnss/2.0/default/GnssMeasurementCorrections.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2019 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. + */ + +#pragma once + +#include +#include +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace measurement_corrections { +namespace V1_0 { +namespace implementation { + +using ::android::sp; +using ::android::hardware::hidl_array; +using ::android::hardware::hidl_memory; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; + +struct GnssMeasurementCorrections : public IMeasurementCorrections { + // Methods from V1_0::IMeasurementCorrections follow. + Return setCorrections(const MeasurementCorrections& corrections) override; +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace measurement_corrections +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp index b135dba2c1..3703ebaef9 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp +++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp @@ -18,6 +18,7 @@ #include #include +#include "Utils.h" using android::hardware::hidl_string; using android::hardware::hidl_vec; @@ -32,6 +33,9 @@ using IAGnss_2_0 = android::hardware::gnss::V2_0::IAGnss; using IAGnss_1_0 = android::hardware::gnss::V1_0::IAGnss; using IAGnssCallback_2_0 = android::hardware::gnss::V2_0::IAGnssCallback; +using android::hardware::gnss::common::Utils; +using android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections; +using android::hardware::gnss::measurement_corrections::V1_0::MeasurementCorrections; using android::hardware::gnss::V1_0::IGnssNi; using android::hardware::gnss::V2_0::ElapsedRealtimeFlags; using android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl; @@ -272,6 +276,24 @@ TEST_F(GnssHalTest, TestGnssVisibilityControlExtension) { EXPECT_TRUE(result); } +/* + * TestGnssMeasurementCorrections: + * Gets the GnssMeasurementCorrectionsExtension and verifies that it supports the + * gnss.measurement_corrections@1.0::IMeasurementCorrections interface by invoking a method. + */ +TEST_F(GnssHalTest, TestGnssMeasurementCorrections) { + // Verify IMeasurementCorrections is supported. + auto measurementCorrections = gnss_hal_->getExtensionMeasurementCorrections(); + ASSERT_TRUE(measurementCorrections.isOk()); + sp iMeasurementCorrections = measurementCorrections; + ASSERT_NE(iMeasurementCorrections, nullptr); + + // Set a mock MeasurementCorrections. + auto result = iMeasurementCorrections->setCorrections(Utils::getMockMeasurementCorrections()); + ASSERT_TRUE(result.isOk()); + EXPECT_TRUE(result); +} + /* * TestGnssDataElapsedRealtimeFlags: * Sets a GnssMeasurementCallback, waits for a GnssData object, and verifies the flags in member diff --git a/gnss/common/utils/vts/Android.bp b/gnss/common/utils/vts/Android.bp index 99d8cf9185..1988171979 100644 --- a/gnss/common/utils/vts/Android.bp +++ b/gnss/common/utils/vts/Android.bp @@ -29,6 +29,7 @@ cc_library_static { export_include_dirs: ["include"], shared_libs: [ "android.hardware.gnss@1.0", + "android.hardware.gnss.measurement_corrections@1.0", ], static_libs: [ "libgtest", diff --git a/gnss/common/utils/vts/Utils.cpp b/gnss/common/utils/vts/Utils.cpp index 24d68839a8..51d3ea18d5 100644 --- a/gnss/common/utils/vts/Utils.cpp +++ b/gnss/common/utils/vts/Utils.cpp @@ -22,6 +22,7 @@ namespace hardware { namespace gnss { namespace common { +using V1_0::GnssConstellationType; using V1_0::GnssLocationFlags; void Utils::checkLocation(const GnssLocation& location, bool check_speed, @@ -91,6 +92,53 @@ void Utils::checkLocation(const GnssLocation& location, bool check_speed, EXPECT_GT(location.timestamp, 1.48e12); } +const MeasurementCorrections Utils::getMockMeasurementCorrections() { + ReflectingPlane reflectingPlane = { + .latitudeDegrees = 37.4220039, + .longitudeDegrees = -122.0840991, + .altitudeMeters = 250.35, + .azimuthDegrees = 203.0, + }; + + SingleSatCorrection singleSatCorrection1 = { + .singleSatCorrectionFlags = GnssSingleSatCorrectionFlags::HAS_SAT_IS_LOS_PROBABILITY | + GnssSingleSatCorrectionFlags::HAS_EXCESS_PATH_LENGTH | + GnssSingleSatCorrectionFlags::HAS_EXCESS_PATH_LENGTH_UNC | + GnssSingleSatCorrectionFlags::HAS_REFLECTING_PLANE, + .constellation = GnssConstellationType::GPS, + .svid = 12, + .carrierFrequencyHz = 1.59975e+09, + .probSatIsLos = 0.50001, + .excessPathLengthMeters = 137.4802, + .excessPathLengthUncertaintyMeters = 25.5, + .reflectingPlane = reflectingPlane, + }; + SingleSatCorrection singleSatCorrection2 = { + .singleSatCorrectionFlags = GnssSingleSatCorrectionFlags::HAS_SAT_IS_LOS_PROBABILITY | + GnssSingleSatCorrectionFlags::HAS_EXCESS_PATH_LENGTH | + GnssSingleSatCorrectionFlags::HAS_EXCESS_PATH_LENGTH_UNC, + .constellation = GnssConstellationType::GPS, + .svid = 9, + .carrierFrequencyHz = 1.59975e+09, + .probSatIsLos = 0.873, + .excessPathLengthMeters = 26.294, + .excessPathLengthUncertaintyMeters = 10.0, + }; + + hidl_vec singleSatCorrections = {singleSatCorrection1, + singleSatCorrection2}; + MeasurementCorrections mockCorrections = { + .latitudeDegrees = 37.4219999, + .longitudeDegrees = -122.0840575, + .altitudeMeters = 30.60062531, + .horizontalPositionUncertaintyMeters = 9.23542, + .verticalPositionUncertaintyMeters = 15.02341, + .toaGpsNanosecondsOfWeek = 2935633453L, + .satCorrections = singleSatCorrections, + }; + return mockCorrections; +} + } // namespace common } // namespace gnss } // namespace hardware diff --git a/gnss/common/utils/vts/include/Utils.h b/gnss/common/utils/vts/include/Utils.h index f8eeff6864..dce4c7b323 100644 --- a/gnss/common/utils/vts/include/Utils.h +++ b/gnss/common/utils/vts/include/Utils.h @@ -18,8 +18,10 @@ #define android_hardware_gnss_common_vts_Utils_H_ #include +#include using GnssLocation = ::android::hardware::gnss::V1_0::GnssLocation; +using namespace android::hardware::gnss::measurement_corrections::V1_0; namespace android { namespace hardware { @@ -29,6 +31,7 @@ namespace common { struct Utils { static void checkLocation(const GnssLocation& location, bool check_speed, bool check_more_accuracies); + static const MeasurementCorrections getMockMeasurementCorrections(); }; } // namespace common From 0637e1339b93592ca9f01119e01d37192e960254 Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Wed, 6 Mar 2019 12:28:15 -0800 Subject: [PATCH 526/718] audio: Make 'surroundSound' element optional This element makes sense only for TV platforms. The deserializer treats it as optional. Update the schema to match this. Bug: 116356348 Test: xmllint --noout --xinclude --schema \ hardware/interfaces/audio/5.0/config/audio_policy_configuration.xsd \ frameworks/av/services/audiopolicy/config/audio_policy_configuration.xml Change-Id: I822c3ff10a6becc859d3d44fd58ef2ebcd3d40b1 --- audio/5.0/config/audio_policy_configuration.xsd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/audio/5.0/config/audio_policy_configuration.xsd b/audio/5.0/config/audio_policy_configuration.xsd index ee3a437d1d..c580b25dc8 100644 --- a/audio/5.0/config/audio_policy_configuration.xsd +++ b/audio/5.0/config/audio_policy_configuration.xsd @@ -42,7 +42,7 @@ - + From 456f3a6447c86b8f478e2021008e49ec43f3f023 Mon Sep 17 00:00:00 2001 From: Robert Shih Date: Thu, 28 Feb 2019 13:42:28 -0800 Subject: [PATCH 527/718] Add vts tests for new drm@1.2 methods Bug: 118402843 Test: VtsHalDrmV1_2TargetTest Change-Id: If0da1538c33e0284fa6fa6dd48d56a0ce1753f02 --- drm/1.2/vts/functional/Android.bp | 40 ++ .../functional/drm_hal_clearkey_module.cpp | 130 +++++ .../vts/functional/drm_hal_clearkey_module.h | 61 ++ drm/1.2/vts/functional/drm_hal_common.cpp | 483 ++++++++++++++++ drm/1.2/vts/functional/drm_hal_common.h | 198 +++++++ drm/1.2/vts/functional/drm_hal_test.cpp | 542 ++++++++++++++++++ drm/1.2/vts/functional/vendor_modules.cpp | 72 +++ drm/1.2/vts/functional/vendor_modules.h | 73 +++ 8 files changed, 1599 insertions(+) create mode 100644 drm/1.2/vts/functional/Android.bp create mode 100644 drm/1.2/vts/functional/drm_hal_clearkey_module.cpp create mode 100644 drm/1.2/vts/functional/drm_hal_clearkey_module.h create mode 100644 drm/1.2/vts/functional/drm_hal_common.cpp create mode 100644 drm/1.2/vts/functional/drm_hal_common.h create mode 100644 drm/1.2/vts/functional/drm_hal_test.cpp create mode 100644 drm/1.2/vts/functional/vendor_modules.cpp create mode 100644 drm/1.2/vts/functional/vendor_modules.h diff --git a/drm/1.2/vts/functional/Android.bp b/drm/1.2/vts/functional/Android.bp new file mode 100644 index 0000000000..6b4a4c0adf --- /dev/null +++ b/drm/1.2/vts/functional/Android.bp @@ -0,0 +1,40 @@ +// +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +cc_test { + name: "VtsHalDrmV1_2TargetTest", + defaults: ["VtsHalTargetTestDefaults"], + srcs: [ + "drm_hal_clearkey_module.cpp", + "drm_hal_common.cpp", + "drm_hal_test.cpp", + "vendor_modules.cpp", + ], + include_dirs: ["hardware/interfaces/drm/1.0/vts/functional"], + static_libs: [ + "android.hardware.drm@1.0", + "android.hardware.drm@1.1", + "android.hardware.drm@1.2", + "android.hardware.drm@1.0-helper", + "android.hidl.allocator@1.0", + "android.hidl.memory@1.0", + "libhidlmemory", + "libnativehelper", + "libssl", + "libcrypto", + ], + test_suites: ["general-tests"], +} diff --git a/drm/1.2/vts/functional/drm_hal_clearkey_module.cpp b/drm/1.2/vts/functional/drm_hal_clearkey_module.cpp new file mode 100644 index 0000000000..a0dc00155b --- /dev/null +++ b/drm/1.2/vts/functional/drm_hal_clearkey_module.cpp @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "drm_hal_clearkey_module@1.2" + +#include +#include "drm_hal_clearkey_module.h" + +namespace android { +namespace hardware { +namespace drm { +namespace V1_2 { +namespace vts { + +std::vector DrmHalVTSClearkeyModule::handleProvisioningRequest( + const std::vector& /*provisioningRequest*/, + const std::string& /*url*/) { + EXPECT_TRUE(false) << "Clearkey doesn't support provisioning"; + return {}; +} + +std::vector + DrmHalVTSClearkeyModule::getContentConfigurations() const { + DrmHalVTSClearkeyModule::ContentConfiguration conf = { + .name = "DrmHalVTSClearkeyModule", // name + .serverUrl = "", // serverUrl + .initData = { // initData + // BMFF box header (4 bytes size + 'pssh') + 0x00, 0x00, 0x00, 0x34, 0x70, 0x73, 0x73, 0x68, + // full box header (version = 1 flags = 0) + 0x01, 0x00, 0x00, 0x00, + // system id + 0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02, 0xac, 0xe3, 0x3c, + 0x1e, 0x52, 0xe2, 0xfb, 0x4b, + // number of key ids + 0x00, 0x00, 0x00, 0x01, + // key id + 0x60, 0x06, 0x1e, 0x01, 0x7e, 0x47, 0x7e, 0x87, 0x7e, 0x57, 0xd0, + 0x0d, 0x1e, 0xd0, 0x0d, 0x1e, + // size of data, must be zero + 0x00, 0x00, 0x00, 0x00 + }, + .mimeType = "video/mp4", // mimeType + .optionalParameters = {}, // optionalParameters + .policy = { .allowOffline = true }, // allowOffline + .keys = { // keys + { + .isSecure = false, // isSecure + .keyId = { // keyId + 0x60, 0x06, 0x1e, 0x01, 0x7e, 0x47, 0x7e, 0x87, + 0x7e, 0x57, 0xd0, 0x0d, 0x1e, 0xd0, 0x0d, 0x1e + }, + .clearContentKey = { // clearContentKey + 0x1a, 0x8a, 0x20, 0x95, 0xe4, 0xde, 0xb2, 0xd2, + 0x9e, 0xc8, 0x16, 0xac, 0x7b, 0xae, 0x20, 0x82 + } + } + } + }; + return { conf }; +} + +std::vector DrmHalVTSClearkeyModule::handleKeyRequest( + const std::vector& keyRequest, + const std::string& /*serverUrl*/) { + + // {"kids":["YAYeAX5Hfod-V9ANHtANHg"],"type":"temporary"} + std::vector expectedKeyRequest = { + 0x7b, 0x22, 0x6b, 0x69, 0x64, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x59, 0x41, 0x59, 0x65, + 0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2d, 0x56, 0x39, 0x41, 0x4e, 0x48, 0x74, + 0x41, 0x4e, 0x48, 0x67, 0x22, 0x5d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, + 0x22, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x22, 0x7d}; + + // {"kids":["YAYeAX5Hfod-V9ANHtANHg"],"type":"persistent-license"} + std::vector expectedKeyRequestPersistent = { + 0x7b, 0x22, 0x6b, 0x69, 0x64, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x59, 0x41, 0x59, 0x65, + 0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2d, 0x56, 0x39, 0x41, 0x4e, 0x48, 0x74, + 0x41, 0x4e, 0x48, 0x67, 0x22, 0x5d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, + 0x22, 0x70, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x69, + 0x63, 0x65, 0x6e, 0x73, 0x65, 0x22, 0x7d}; + + // {"keys":[{"kty":"oct","kid":"YAYeAX5Hfod-V9ANHtANHg","k":"GoogleTestKeyBase64ggg"}]} + std::vector knownKeyResponse = { + 0x7b, 0x22, 0x6b, 0x65, 0x79, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x6b, 0x74, 0x79, 0x22, + 0x3a, 0x22, 0x6f, 0x63, 0x74, 0x22, 0x2c, 0x22, 0x6b, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x59, + 0x41, 0x59, 0x65, 0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2d, 0x56, 0x39, 0x41, 0x4e, + 0x48, 0x74, 0x41, 0x4e, 0x48, 0x67, 0x22, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x22, 0x47, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x54, 0x65, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x42, 0x61, 0x73, 0x65, + 0x36, 0x34, 0x67, 0x67, 0x67, 0x22, 0x7d, 0x5d, 0x7d}; + + // {"keys":[{"kty":"oct","kid":"YAYeAX5Hfod-V9ANHtANHg","k":"GoogleTestKeyBase64ggg"}],"type":"persistent-license"} + std::vector knownKeyResponsePersistent = { + 0x7b, 0x22, 0x6b, 0x65, 0x79, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x6b, 0x74, 0x79, 0x22, + 0x3a, 0x22, 0x6f, 0x63, 0x74, 0x22, 0x2c, 0x22, 0x6b, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x59, + 0x41, 0x59, 0x65, 0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2d, 0x56, 0x39, 0x41, 0x4e, + 0x48, 0x74, 0x41, 0x4e, 0x48, 0x67, 0x22, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x22, 0x47, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x54, 0x65, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x42, 0x61, 0x73, 0x65, + 0x36, 0x34, 0x67, 0x67, 0x67, 0x22, 0x7d, 0x5d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, + 0x3a, 0x22, 0x70, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x69, + 0x63, 0x65, 0x6e, 0x73, 0x65, 0x22, 0x7d}; + + std::string req(keyRequest.begin(), keyRequest.end()); + if (req.find("persistent-license") != std::string::npos) { + EXPECT_EQ(expectedKeyRequestPersistent, keyRequest); + return knownKeyResponsePersistent; + } else { + EXPECT_EQ(expectedKeyRequest, keyRequest); + return knownKeyResponse; + } + +} + +} // namespace vts +} // namespace V1_2 +} // namespace drm +} // namespace hardware +} // namespace android diff --git a/drm/1.2/vts/functional/drm_hal_clearkey_module.h b/drm/1.2/vts/functional/drm_hal_clearkey_module.h new file mode 100644 index 0000000000..7250cf25dd --- /dev/null +++ b/drm/1.2/vts/functional/drm_hal_clearkey_module.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2019 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 DRM_HAL_CLEARKEY_MODULE_H +#define DRM_HAL_CLEARKEY_MODULE_H + +#include "drm_hal_vendor_module_api.h" + +namespace android { +namespace hardware { +namespace drm { +namespace V1_2 { +namespace vts { + +class DrmHalVTSClearkeyModule : public DrmHalVTSVendorModule_V1 { + public: + DrmHalVTSClearkeyModule() {} + virtual ~DrmHalVTSClearkeyModule() {} + + virtual uint32_t getAPIVersion() const override { return 1; } + + virtual std::string getServiceName() const override { return "clearkey"; } + + virtual std::vector getUUID() const override { + return {0xE2, 0x71, 0x9D, 0x58, 0xA9, 0x85, 0xB3, 0xC9, + 0x78, 0x1A, 0xB0, 0x30, 0xAF, 0x78, 0xD3, 0x0E }; + } + + + virtual std::vector handleProvisioningRequest( + const std::vector& provisioningRequest, + const std::string& url) override; + + virtual std::vector + getContentConfigurations() const override; + + virtual std::vector handleKeyRequest( + const std::vector& keyRequest, + const std::string& serverUrl) override; +}; + +} // namespace vts +} // namespace V1_2 +} // namespace drm +} // namespace hardware +} // namespace android + +#endif // DRM_HAL_CLEARKEY_MODULE_H diff --git a/drm/1.2/vts/functional/drm_hal_common.cpp b/drm/1.2/vts/functional/drm_hal_common.cpp new file mode 100644 index 0000000000..b9a8425fc7 --- /dev/null +++ b/drm/1.2/vts/functional/drm_hal_common.cpp @@ -0,0 +1,483 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "drm_hal_common@1.2" + +#include +#include +#include +#include +#include +#include +#include + +#include "drm_hal_clearkey_module.h" +#include "drm_hal_common.h" + +using ::android::hardware::drm::V1_0::BufferType; +using ::android::hardware::drm::V1_0::DestinationBuffer; +using ICryptoPluginV1_0 = ::android::hardware::drm::V1_0::ICryptoPlugin; +using IDrmPluginV1_0 = ::android::hardware::drm::V1_0::IDrmPlugin; +using ::android::hardware::drm::V1_0::KeyValue; +using ::android::hardware::drm::V1_0::SharedBuffer; +using StatusV1_0 = ::android::hardware::drm::V1_0::Status; + +using ::android::hardware::drm::V1_1::KeyRequestType; + +using ::android::hardware::drm::V1_2::KeySetId; +using ::android::hardware::drm::V1_2::OfflineLicenseState; +using StatusV1_2 = ::android::hardware::drm::V1_2::Status; + +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_memory; + +using ::android::hidl::allocator::V1_0::IAllocator; + +using std::random_device; +using std::mt19937; + +namespace android { +namespace hardware { +namespace drm { +namespace V1_2 { +namespace vts { + +const char *kCallbackLostState = "LostState"; + +drm_vts::VendorModules *DrmHalTest::gVendorModules = nullptr; + +/** + * DrmHalPluginListener + */ + +Return DrmHalPluginListener::sendSessionLostState(const hidl_vec& sessionId) { + NotifyFromCallback(kCallbackLostState, sessionId); + return Void(); +} + +/** + * DrmHalTest + */ + +DrmHalTest::DrmHalTest() + : vendorModule(GetParam() == "clearkey" + ? new DrmHalVTSClearkeyModule() + : static_cast(gVendorModules->getModule(GetParam()))), + contentConfigurations(vendorModule->getContentConfigurations()) { +} + +void DrmHalTest::SetUp() { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + + ALOGD("Running test %s.%s from (vendor) module %s", + test_info->test_case_name(), test_info->name(), + GetParam().c_str()); + + string name = vendorModule->getServiceName(); + drmFactory = VtsHalHidlTargetTestBase::getService(name); + if (drmFactory == nullptr) { + drmFactory = VtsHalHidlTargetTestBase::getService(); + } + if (drmFactory != nullptr) { + drmPlugin = createDrmPlugin(); + } + + cryptoFactory = VtsHalHidlTargetTestBase::getService(name); + if (cryptoFactory == nullptr) { + cryptoFactory = VtsHalHidlTargetTestBase::getService(); + } + if (cryptoFactory != nullptr) { + cryptoPlugin = createCryptoPlugin(); + } + + // If drm scheme not installed skip subsequent tests + if (!drmFactory->isCryptoSchemeSupported(getVendorUUID())) { + vendorModule->setInstalled(false); + return; + } + + ASSERT_NE(nullptr, drmPlugin.get()) << "Can't find " << vendorModule->getServiceName() << " drm@1.2 plugin"; + ASSERT_NE(nullptr, cryptoPlugin.get()) << "Can't find " << vendorModule->getServiceName() << " crypto@1.2 plugin"; + +} + +sp DrmHalTest::createDrmPlugin() { + if (drmFactory == nullptr) { + return nullptr; + } + sp plugin = nullptr; + hidl_string packageName("android.hardware.drm.test"); + auto res = drmFactory->createPlugin( + getVendorUUID(), packageName, + [&](StatusV1_0 status, const sp& pluginV1_0) { + EXPECT_EQ(StatusV1_0::OK, status); + plugin = IDrmPlugin::castFrom(pluginV1_0); + }); + + if (!res.isOk()) { + ALOGE("createDrmPlugin remote call failed"); + } + return plugin; +} + +sp DrmHalTest::createCryptoPlugin() { + if (cryptoFactory == nullptr) { + return nullptr; + } + sp plugin = nullptr; + hidl_vec initVec; + auto res = cryptoFactory->createPlugin( + getVendorUUID(), initVec, + [&](StatusV1_0 status, const sp& pluginV1_0) { + EXPECT_EQ(StatusV1_0::OK, status); + plugin = ICryptoPlugin::castFrom(pluginV1_0); + }); + if (!res.isOk()) { + ALOGE("createCryptoPlugin remote call failed"); + } + return plugin; +} + +hidl_array DrmHalTest::getVendorUUID() { + vector uuid = vendorModule->getUUID(); + return hidl_array(&uuid[0]); +} + +/** + * Helper method to open a session and verify that a non-empty + * session ID is returned + */ +SessionId DrmHalTest::openSession() { + SessionId sessionId; + + auto res = drmPlugin->openSession([&](StatusV1_0 status, const hidl_vec &id) { + EXPECT_EQ(StatusV1_0::OK, status); + EXPECT_NE(id.size(), 0u); + sessionId = id; + }); + EXPECT_OK(res); + return sessionId; +} + +/** + * Helper method to close a session + */ +void DrmHalTest::closeSession(const SessionId& sessionId) { + StatusV1_0 status = drmPlugin->closeSession(sessionId); + EXPECT_EQ(StatusV1_0::OK, status); +} + +hidl_vec DrmHalTest::getKeyRequest( + const SessionId& sessionId, + const DrmHalVTSVendorModule_V1::ContentConfiguration& configuration, + const KeyType& type = KeyType::STREAMING) { + hidl_vec keyRequest; + auto res = drmPlugin->getKeyRequest_1_2( + sessionId, configuration.initData, configuration.mimeType, type, + toHidlKeyedVector(configuration.optionalParameters), + [&](Status status, const hidl_vec& request, + KeyRequestType requestType, const hidl_string&) { + EXPECT_EQ(Status::OK, status) << "Failed to get " + "key request for configuration " + << configuration.name; + if (type == KeyType::RELEASE) { + EXPECT_EQ(KeyRequestType::RELEASE, requestType); + } else { + EXPECT_EQ(KeyRequestType::INITIAL, requestType); + } + EXPECT_NE(request.size(), 0u) << "Expected key request size" + " to have length > 0 bytes"; + keyRequest = request; + }); + EXPECT_OK(res); + return keyRequest; +} + +DrmHalVTSVendorModule_V1::ContentConfiguration DrmHalTest::getContent(const KeyType& type) const { + for (const auto& config : contentConfigurations) { + if (type != KeyType::OFFLINE || config.policy.allowOffline) { + return config; + } + } + EXPECT_TRUE(false) << "no content configurations found"; + return {}; +} + +hidl_vec DrmHalTest::provideKeyResponse( + const SessionId& sessionId, + const hidl_vec& keyResponse) { + hidl_vec keySetId; + auto res = drmPlugin->provideKeyResponse( + sessionId, keyResponse, + [&](StatusV1_0 status, const hidl_vec& myKeySetId) { + EXPECT_EQ(StatusV1_0::OK, status) << "Failure providing " + "key response for configuration "; + keySetId = myKeySetId; + }); + EXPECT_OK(res); + return keySetId; +} + +/** + * Helper method to load keys for subsequent decrypt tests. + * These tests use predetermined key request/response to + * avoid requiring a round trip to a license server. + */ +hidl_vec DrmHalTest::loadKeys( + const SessionId& sessionId, + const DrmHalVTSVendorModule_V1::ContentConfiguration& configuration, + const KeyType& type) { + hidl_vec keyRequest = getKeyRequest(sessionId, configuration, type); + + /** + * Get key response from vendor module + */ + hidl_vec keyResponse = + vendorModule->handleKeyRequest(keyRequest, configuration.serverUrl); + EXPECT_NE(keyResponse.size(), 0u) << "Expected key response size " + "to have length > 0 bytes"; + + return provideKeyResponse(sessionId, keyResponse); +} + +hidl_vec DrmHalTest::loadKeys( + const SessionId& sessionId, + const KeyType& type) { + return loadKeys(sessionId, getContent(type), type); +} + +KeyedVector DrmHalTest::toHidlKeyedVector( + const map& params) { + std::vector stdKeyedVector; + for (auto it = params.begin(); it != params.end(); ++it) { + KeyValue keyValue; + keyValue.key = it->first; + keyValue.value = it->second; + stdKeyedVector.push_back(keyValue); + } + return KeyedVector(stdKeyedVector); +} + +hidl_array DrmHalTest::toHidlArray(const vector& vec) { + EXPECT_EQ(16u, vec.size()); + return hidl_array(&vec[0]); +} + +/** + * getDecryptMemory allocates memory for decryption, then sets it + * as a shared buffer base in the crypto hal. The allocated and + * mapped IMemory is returned. + * + * @param size the size of the memory segment to allocate + * @param the index of the memory segment which will be used + * to refer to it for decryption. + */ +sp DrmHalTest::getDecryptMemory(size_t size, size_t index) { + sp ashmemAllocator = IAllocator::getService("ashmem"); + EXPECT_NE(nullptr, ashmemAllocator.get()); + + hidl_memory hidlMemory; + auto res = ashmemAllocator->allocate( + size, [&](bool success, const hidl_memory& memory) { + EXPECT_EQ(success, true); + EXPECT_EQ(memory.size(), size); + hidlMemory = memory; + }); + + EXPECT_OK(res); + + sp mappedMemory = mapMemory(hidlMemory); + EXPECT_NE(nullptr, mappedMemory.get()); + res = cryptoPlugin->setSharedBufferBase(hidlMemory, index); + EXPECT_OK(res); + return mappedMemory; +} + +void DrmHalTest::fillRandom(const sp& memory) { + random_device rd; + mt19937 rand(rd()); + for (size_t i = 0; i < memory->getSize() / sizeof(uint32_t); i++) { + auto p = static_cast( + static_cast(memory->getPointer())); + p[i] = rand(); + } +} + +uint32_t DrmHalTest::decrypt(Mode mode, bool isSecure, + const hidl_array& keyId, uint8_t* iv, + const hidl_vec& subSamples, const Pattern& pattern, + const vector& key, StatusV1_2 expectedStatus) { + const size_t kSegmentIndex = 0; + + uint8_t localIv[AES_BLOCK_SIZE]; + memcpy(localIv, iv, AES_BLOCK_SIZE); + + size_t totalSize = 0; + for (size_t i = 0; i < subSamples.size(); i++) { + totalSize += subSamples[i].numBytesOfClearData; + totalSize += subSamples[i].numBytesOfEncryptedData; + } + + // The first totalSize bytes of shared memory is the encrypted + // input, the second totalSize bytes (if exists) is the decrypted output. + size_t factor = expectedStatus == StatusV1_2::ERROR_DRM_FRAME_TOO_LARGE ? 1 : 2; + sp sharedMemory = + getDecryptMemory(totalSize * factor, kSegmentIndex); + + const SharedBuffer sourceBuffer = { + .bufferId = kSegmentIndex, .offset = 0, .size = totalSize}; + fillRandom(sharedMemory); + + const DestinationBuffer destBuffer = {.type = BufferType::SHARED_MEMORY, + {.bufferId = kSegmentIndex, + .offset = totalSize, + .size = totalSize}, + .secureMemory = nullptr}; + const uint64_t offset = 0; + uint32_t bytesWritten = 0; + auto res = cryptoPlugin->decrypt_1_2(isSecure, keyId, localIv, mode, pattern, + subSamples, sourceBuffer, offset, destBuffer, + [&](StatusV1_2 status, uint32_t count, string detailedError) { + EXPECT_EQ(expectedStatus, status) << "Unexpected decrypt status " << + detailedError; + bytesWritten = count; + }); + EXPECT_OK(res); + + if (bytesWritten != totalSize) { + return bytesWritten; + } + uint8_t* base = static_cast( + static_cast(sharedMemory->getPointer())); + + // generate reference vector + vector reference(totalSize); + + memcpy(localIv, iv, AES_BLOCK_SIZE); + switch (mode) { + case Mode::UNENCRYPTED: + memcpy(&reference[0], base, totalSize); + break; + case Mode::AES_CTR: + aes_ctr_decrypt(&reference[0], base, localIv, subSamples, key); + break; + case Mode::AES_CBC: + aes_cbc_decrypt(&reference[0], base, localIv, subSamples, key); + break; + case Mode::AES_CBC_CTS: + EXPECT_TRUE(false) << "AES_CBC_CTS mode not supported"; + break; + } + + // compare reference to decrypted data which is at base + total size + EXPECT_EQ(0, memcmp(static_cast(&reference[0]), + static_cast(base + totalSize), totalSize)) + << "decrypt data mismatch"; + return totalSize; +} + +/** + * Decrypt a list of clear+encrypted subsamples using the specified key + * in AES-CTR mode + */ +void DrmHalTest::aes_ctr_decrypt(uint8_t* dest, uint8_t* src, + uint8_t* iv, const hidl_vec& subSamples, + const vector& key) { + AES_KEY decryptionKey; + AES_set_encrypt_key(&key[0], 128, &decryptionKey); + + size_t offset = 0; + unsigned int blockOffset = 0; + uint8_t previousEncryptedCounter[AES_BLOCK_SIZE]; + memset(previousEncryptedCounter, 0, AES_BLOCK_SIZE); + + for (size_t i = 0; i < subSamples.size(); i++) { + const SubSample& subSample = subSamples[i]; + + if (subSample.numBytesOfClearData > 0) { + memcpy(dest + offset, src + offset, subSample.numBytesOfClearData); + offset += subSample.numBytesOfClearData; + } + + if (subSample.numBytesOfEncryptedData > 0) { + AES_ctr128_encrypt(src + offset, dest + offset, + subSample.numBytesOfEncryptedData, &decryptionKey, + iv, previousEncryptedCounter, &blockOffset); + offset += subSample.numBytesOfEncryptedData; + } + } +} + +/** + * Decrypt a list of clear+encrypted subsamples using the specified key + * in AES-CBC mode + */ +void DrmHalTest::aes_cbc_decrypt(uint8_t* dest, uint8_t* src, + uint8_t* iv, const hidl_vec& subSamples, + const vector& key) { + AES_KEY decryptionKey; + AES_set_encrypt_key(&key[0], 128, &decryptionKey); + + size_t offset = 0; + for (size_t i = 0; i < subSamples.size(); i++) { + memcpy(dest + offset, src + offset, subSamples[i].numBytesOfClearData); + offset += subSamples[i].numBytesOfClearData; + + AES_cbc_encrypt(src + offset, dest + offset, subSamples[i].numBytesOfEncryptedData, + &decryptionKey, iv, 0 /* decrypt */); + offset += subSamples[i].numBytesOfEncryptedData; + } +} + +/** + * Helper method to test decryption with invalid keys is returned + */ +void DrmHalClearkeyTest::decryptWithInvalidKeys( + hidl_vec& invalidResponse, + vector& iv, + const Pattern& noPattern, + const vector& subSamples) { + DrmHalVTSVendorModule_V1::ContentConfiguration content = getContent(); + if (content.keys.empty()) { + FAIL() << "no keys"; + } + + const auto& key = content.keys[0]; + auto sessionId = openSession(); + auto res = drmPlugin->provideKeyResponse( + sessionId, invalidResponse, + [&](StatusV1_0 status, const hidl_vec& myKeySetId) { + EXPECT_EQ(StatusV1_0::OK, status); + EXPECT_EQ(0u, myKeySetId.size()); + }); + EXPECT_OK(res); + + EXPECT_TRUE(cryptoPlugin->setMediaDrmSession(sessionId).isOk()); + + uint32_t byteCount = decrypt(Mode::AES_CTR, key.isSecure, + toHidlArray(key.keyId), &iv[0], subSamples, noPattern, + key.clearContentKey, Status::ERROR_DRM_NO_LICENSE); + EXPECT_EQ(0u, byteCount); + + closeSession(sessionId); +} + +} // namespace vts +} // namespace V1_2 +} // namespace drm +} // namespace hardware +} // namespace android diff --git a/drm/1.2/vts/functional/drm_hal_common.h b/drm/1.2/vts/functional/drm_hal_common.h new file mode 100644 index 0000000000..1b95ddeea9 --- /dev/null +++ b/drm/1.2/vts/functional/drm_hal_common.h @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2019 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 DRM_HAL_COMMON_H +#define DRM_HAL_COMMON_H + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "drm_hal_vendor_module_api.h" +#include "vendor_modules.h" +#include "VtsHalHidlTargetCallbackBase.h" +#include "VtsHalHidlTargetTestBase.h" + +using ::android::hardware::drm::V1_0::EventType; +using ::android::hardware::drm::V1_0::KeyedVector; +using ::android::hardware::drm::V1_0::KeyStatus; +using ::android::hardware::drm::V1_0::KeyType; +using ::android::hardware::drm::V1_0::Mode; +using ::android::hardware::drm::V1_0::Pattern; +using ::android::hardware::drm::V1_0::SessionId; +using ::android::hardware::drm::V1_0::SubSample; + +using ::android::hardware::drm::V1_1::ICryptoFactory; + +using ::android::hardware::drm::V1_2::ICryptoPlugin; +using ::android::hardware::drm::V1_2::IDrmFactory; +using ::android::hardware::drm::V1_2::IDrmPlugin; +using ::android::hardware::drm::V1_2::IDrmPluginListener; +using StatusV1_2 = ::android::hardware::drm::V1_2::Status; + +using ::android::hardware::hidl_array; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; + +using ::android::hidl::memory::V1_0::IMemory; +using ::android::sp; + +using ::testing::VtsHalHidlTargetTestBase; + +using std::map; +using std::string; +using std::unique_ptr; +using std::vector; + +#define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk()) + +#define RETURN_IF_SKIPPED \ + if (!vendorModule->isInstalled()) { \ + std::cout << "[ SKIPPED ] This drm scheme not supported." << \ + " library:" << GetParam() << " service-name:" << \ + vendorModule->getServiceName() << std::endl; \ + return; \ + } + +namespace android { +namespace hardware { +namespace drm { +namespace V1_2 { +namespace vts { + +class DrmHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { + public: + // get the test environment singleton + static DrmHidlEnvironment* Instance() { + static DrmHidlEnvironment* instance = new DrmHidlEnvironment; + return instance; + } + + void registerTestServices() override { + registerTestService(); + registerTestService(); + setServiceCombMode(::testing::HalServiceCombMode::NO_COMBINATION); + } + + private: + DrmHidlEnvironment() {} + + GTEST_DISALLOW_COPY_AND_ASSIGN_(DrmHidlEnvironment); +}; + +class DrmHalTest : public ::testing::TestWithParam { + public: + static drm_vts::VendorModules* gVendorModules; + DrmHalTest(); + virtual void SetUp() override; + virtual void TearDown() override {} + + protected: + hidl_array getVendorUUID(); + SessionId openSession(); + void closeSession(const SessionId& sessionId); + hidl_vec loadKeys(const SessionId& sessionId, + const KeyType& type = KeyType::STREAMING); + hidl_vec loadKeys(const SessionId& sessionId, + const DrmHalVTSVendorModule_V1::ContentConfiguration&, + const KeyType& type = KeyType::STREAMING); + hidl_vec getKeyRequest(const SessionId& sessionId, + const DrmHalVTSVendorModule_V1::ContentConfiguration&, + const KeyType& type); + hidl_vec provideKeyResponse(const SessionId& sessionId, + const hidl_vec& keyResponse); + DrmHalVTSVendorModule_V1::ContentConfiguration getContent( + const KeyType& type = KeyType::STREAMING) const; + + KeyedVector toHidlKeyedVector(const map& params); + hidl_array toHidlArray(const vector& vec); + + void fillRandom(const sp& memory); + sp getDecryptMemory(size_t size, size_t index); + uint32_t decrypt(Mode mode, bool isSecure, + const hidl_array& keyId, uint8_t* iv, + const hidl_vec& subSamples, const Pattern& pattern, + const vector& key, StatusV1_2 expectedStatus); + void aes_ctr_decrypt(uint8_t* dest, uint8_t* src, uint8_t* iv, + const hidl_vec& subSamples, const vector& key); + void aes_cbc_decrypt(uint8_t* dest, uint8_t* src, uint8_t* iv, + const hidl_vec& subSamples, const vector& key); + + sp drmFactory; + sp cryptoFactory; + sp drmPlugin; + sp cryptoPlugin; + unique_ptr vendorModule; + const vector contentConfigurations; + + private: + sp createDrmPlugin(); + sp createCryptoPlugin(); + +}; + +class DrmHalClearkeyTest : public DrmHalTest { + public: + virtual void SetUp() override { DrmHalTest::SetUp(); } + virtual void TearDown() override {} + void decryptWithInvalidKeys(hidl_vec& invalidResponse, + vector& iv, const Pattern& noPattern, const vector& subSamples); +}; + +/** + * Event Handling tests + */ +extern const char *kCallbackLostState; + +class DrmHalPluginListener + : public ::testing::VtsHalHidlTargetCallbackBase, + public IDrmPluginListener { +public: + DrmHalPluginListener() { + SetWaitTimeoutDefault(std::chrono::milliseconds(500)); + } + virtual ~DrmHalPluginListener() {} + + virtual Return sendEvent(EventType, const hidl_vec&, + const hidl_vec& ) override { return Void(); } + + virtual Return sendExpirationUpdate(const hidl_vec&, + int64_t) override { return Void(); } + + virtual Return sendKeysChange(const hidl_vec&, + const hidl_vec&, bool) override { return Void(); } + + virtual Return sendSessionLostState(const hidl_vec& sessionId) override; + +}; + +} // namespace vts +} // namespace V1_2 +} // namespace drm +} // namespace hardware +} // namespace android + +#endif // DRM_HAL_COMMON_H diff --git a/drm/1.2/vts/functional/drm_hal_test.cpp b/drm/1.2/vts/functional/drm_hal_test.cpp new file mode 100644 index 0000000000..067b5e474f --- /dev/null +++ b/drm/1.2/vts/functional/drm_hal_test.cpp @@ -0,0 +1,542 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "drm_hal_clearkey_test@1.2" + +#include +#include +#include +#include + +#include "drm_hal_common.h" + +using ::android::hardware::drm::V1_0::Status; +using ::android::hardware::drm::V1_1::KeyRequestType; +using ::android::hardware::drm::V1_1::SecurityLevel; +using ::android::hardware::drm::V1_2::HdcpLevel; +using ::android::hardware::drm::V1_2::KeySetId; +using ::android::hardware::drm::V1_2::OfflineLicenseState; + +using ::android::hardware::drm::V1_2::vts::DrmHalClearkeyTest; +using ::android::hardware::drm::V1_2::vts::DrmHalPluginListener; +using ::android::hardware::drm::V1_2::vts::DrmHalTest; +using ::android::hardware::drm::V1_2::vts::DrmHidlEnvironment; +using ::android::hardware::drm::V1_2::vts::kCallbackLostState; + +using ::android::hardware::hidl_string; + +static const char* const kVideoMp4 = "video/mp4"; +static const char* const kBadMime = "video/unknown"; +static const char* const kDrmErrorTestKey = "drmErrorTest"; +static const char* const kDrmErrorGeneric = ""; +static const char* const kResourceContentionValue = "resourceContention"; +static const SecurityLevel kSwSecureCrypto = SecurityLevel::SW_SECURE_CRYPTO; + +/** + * Ensure drm factory supports module UUID Scheme + */ +TEST_P(DrmHalTest, VendorUuidSupported) { + auto res = drmFactory->isCryptoSchemeSupported_1_2(getVendorUUID(), kVideoMp4, kSwSecureCrypto); + ALOGI("kVideoMp4 = %s res %d", kVideoMp4, (bool)res); + EXPECT_TRUE(res); +} + +/** + * Ensure drm factory doesn't support an invalid scheme UUID + */ +TEST_P(DrmHalTest, InvalidPluginNotSupported) { + const uint8_t kInvalidUUID[16] = { + 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, + 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80}; + EXPECT_FALSE(drmFactory->isCryptoSchemeSupported_1_2(kInvalidUUID, kVideoMp4, kSwSecureCrypto)); +} + +/** + * Ensure drm factory doesn't support an empty UUID + */ +TEST_P(DrmHalTest, EmptyPluginUUIDNotSupported) { + hidl_array emptyUUID; + memset(emptyUUID.data(), 0, 16); + EXPECT_FALSE(drmFactory->isCryptoSchemeSupported_1_2(emptyUUID, kVideoMp4, kSwSecureCrypto)); +} + +/** + * Ensure drm factory doesn't support an invalid mime type + */ +TEST_P(DrmHalTest, BadMimeNotSupported) { + EXPECT_FALSE(drmFactory->isCryptoSchemeSupported_1_2(getVendorUUID(), kBadMime, kSwSecureCrypto)); +} + +/** + * DrmPlugin tests + */ + +/** + * Test that a DRM plugin can handle provisioning. While + * it is not required that a DRM scheme require provisioning, + * it should at least return appropriate status values. If + * a provisioning request is returned, it is passed to the + * vendor module which should provide a provisioning response + * that is delivered back to the HAL. + */ +TEST_P(DrmHalTest, DoProvisioning) { + RETURN_IF_SKIPPED; + hidl_string certificateType; + hidl_string certificateAuthority; + hidl_vec provisionRequest; + hidl_string defaultUrl; + auto res = drmPlugin->getProvisionRequest_1_2( + certificateType, certificateAuthority, + [&](StatusV1_2 status, const hidl_vec& request, + const hidl_string& url) { + if (status == StatusV1_2::OK) { + EXPECT_NE(request.size(), 0u); + provisionRequest = request; + defaultUrl = url; + } else if (status == StatusV1_2::ERROR_DRM_CANNOT_HANDLE) { + EXPECT_EQ(0u, request.size()); + } + }); + EXPECT_OK(res); + + if (provisionRequest.size() > 0) { + vector response = vendorModule->handleProvisioningRequest( + provisionRequest, defaultUrl); + ASSERT_NE(0u, response.size()); + + auto res = drmPlugin->provideProvisionResponse( + response, [&](Status status, const hidl_vec&, + const hidl_vec&) { + EXPECT_EQ(Status::OK, status); + }); + EXPECT_OK(res); + } +} + +/** + * A get key request should fail if no sessionId is provided + */ +TEST_P(DrmHalTest, GetKeyRequestNoSession) { + SessionId invalidSessionId; + hidl_vec initData; + KeyedVector optionalParameters; + auto res = drmPlugin->getKeyRequest_1_2( + invalidSessionId, initData, kVideoMp4, KeyType::STREAMING, + optionalParameters, + [&](StatusV1_2 status, const hidl_vec&, KeyRequestType, + const hidl_string&) { EXPECT_EQ(StatusV1_2::BAD_VALUE, status); }); + EXPECT_OK(res); +} + +/** + * Test that the plugin returns the documented error for the + * case of attempting to generate a key request using an + * invalid mime type + */ +TEST_P(DrmHalTest, GetKeyRequestBadMime) { + auto sessionId = openSession(); + hidl_vec initData; + KeyedVector optionalParameters; + auto res = drmPlugin->getKeyRequest_1_2( + sessionId, initData, kBadMime, KeyType::STREAMING, + optionalParameters, [&](StatusV1_2 status, const hidl_vec&, + KeyRequestType, const hidl_string&) { + EXPECT_NE(StatusV1_2::OK, status); + }); + EXPECT_OK(res); + closeSession(sessionId); +} + +template +void checkKeySetIds(Status status, const hidl_vec& keySetIds) { + EXPECT_EQ(S, status); + if (S == Status::OK) { + EXPECT_EQ(N, keySetIds.size()); + } +} + +template +void checkKeySetIdState(Status status, OfflineLicenseState state) { + if (S == Status::OK) { + EXPECT_TRUE(T == OfflineLicenseState::USABLE || T == OfflineLicenseState::INACTIVE); + } else { + EXPECT_TRUE(T == OfflineLicenseState::UNKNOWN); + } + EXPECT_EQ(S, status); + EXPECT_EQ(T, state); +} + +/** + * Test clearkey plugin offline key support + */ +TEST_P(DrmHalTest, OfflineLicenseTest) { + auto sessionId = openSession(); + hidl_vec keySetId = loadKeys(sessionId, KeyType::OFFLINE); + + auto res = drmPlugin->getOfflineLicenseKeySetIds(checkKeySetIds); + EXPECT_OK(res); + + Status err = drmPlugin->removeOfflineLicense(keySetId); + EXPECT_EQ(Status::OK, err); + + res = drmPlugin->getOfflineLicenseKeySetIds(checkKeySetIds); + EXPECT_OK(res); + + err = drmPlugin->removeOfflineLicense(keySetId); + EXPECT_EQ(Status::BAD_VALUE, err); + + closeSession(sessionId); +} + +/** + * Test clearkey plugin offline key state + */ +TEST_P(DrmHalTest, OfflineLicenseStateTest) { + auto sessionId = openSession(); + DrmHalVTSVendorModule_V1::ContentConfiguration content = getContent(KeyType::OFFLINE); + hidl_vec keySetId = loadKeys(sessionId, content, KeyType::OFFLINE); + drmPlugin->getOfflineLicenseState(keySetId, checkKeySetIdState); + + hidl_vec keyRequest = getKeyRequest(keySetId, content, KeyType::RELEASE); + drmPlugin->getOfflineLicenseState(keySetId, checkKeySetIdState); + + /** + * Get key response from vendor module + */ + hidl_vec keyResponse = + vendorModule->handleKeyRequest(keyRequest, content.serverUrl); + EXPECT_GT(keyResponse.size(), 0u); + + provideKeyResponse(keySetId, keyResponse); + drmPlugin->getOfflineLicenseState(keySetId, checkKeySetIdState); + closeSession(sessionId); +} + +/** + * Negative offline license test. Remove empty keySetId + */ +TEST_P(DrmHalTest, RemoveEmptyKeySetId) { + KeySetId emptyKeySetId; + Status err = drmPlugin->removeOfflineLicense(emptyKeySetId); + EXPECT_EQ(Status::BAD_VALUE, err); +} + +/** + * Negative offline license test. Get empty keySetId state + */ +TEST_P(DrmHalTest, GetEmptyKeySetIdState) { + KeySetId emptyKeySetId; + auto res = drmPlugin->getOfflineLicenseState(emptyKeySetId, checkKeySetIdState); + EXPECT_OK(res); +} + +/** + * Test that the plugin returns valid connected and max HDCP levels + */ +TEST_P(DrmHalTest, GetHdcpLevels) { + auto res = drmPlugin->getHdcpLevels_1_2( + [&](StatusV1_2 status, const HdcpLevel &connectedLevel, + const HdcpLevel &maxLevel) { + EXPECT_EQ(StatusV1_2::OK, status); + EXPECT_GE(connectedLevel, HdcpLevel::HDCP_NONE); + EXPECT_LE(maxLevel, HdcpLevel::HDCP_V2_3); + }); + EXPECT_OK(res); +} + +/** + * CryptoPlugin Decrypt tests + */ + +/** + * Positive decrypt test. "Decrypt" a single clear segment + */ +TEST_P(DrmHalTest, ClearSegmentTest) { + RETURN_IF_SKIPPED; + for (const auto& config : contentConfigurations) { + for (const auto& key : config.keys) { + const size_t kSegmentSize = 1024; + vector iv(AES_BLOCK_SIZE, 0); + const Pattern noPattern = {0, 0}; + const vector subSamples = {{.numBytesOfClearData = kSegmentSize, + .numBytesOfEncryptedData = 0}}; + auto sessionId = openSession(); + loadKeys(sessionId, config); + + Status status = cryptoPlugin->setMediaDrmSession(sessionId); + EXPECT_EQ(Status::OK, status); + + uint32_t byteCount = decrypt(Mode::UNENCRYPTED, key.isSecure, toHidlArray(key.keyId), + &iv[0], subSamples, noPattern, key.clearContentKey, StatusV1_2::OK); + EXPECT_EQ(kSegmentSize, byteCount); + + closeSession(sessionId); + } + } +} + +/** + * Positive decrypt test. Decrypt a single segment using aes_ctr. + * Verify data matches. + */ +TEST_P(DrmHalTest, EncryptedAesCtrSegmentTest) { + RETURN_IF_SKIPPED; + for (const auto& config : contentConfigurations) { + for (const auto& key : config.keys) { + const size_t kSegmentSize = 1024; + vector iv(AES_BLOCK_SIZE, 0); + const Pattern noPattern = {0, 0}; + const vector subSamples = {{.numBytesOfClearData = kSegmentSize, + .numBytesOfEncryptedData = 0}}; + auto sessionId = openSession(); + loadKeys(sessionId, config); + + Status status = cryptoPlugin->setMediaDrmSession(sessionId); + EXPECT_EQ(Status::OK, status); + + uint32_t byteCount = decrypt(Mode::AES_CTR, key.isSecure, toHidlArray(key.keyId), + &iv[0], subSamples, noPattern, key.clearContentKey, StatusV1_2::OK); + EXPECT_EQ(kSegmentSize, byteCount); + + closeSession(sessionId); + } + } +} + +/** + * Negative decrypt test. Decrypted frame too large to fit in output buffer + */ +TEST_P(DrmHalTest, ErrorFrameTooLarge) { + RETURN_IF_SKIPPED; + for (const auto& config : contentConfigurations) { + for (const auto& key : config.keys) { + const size_t kSegmentSize = 1024; + vector iv(AES_BLOCK_SIZE, 0); + const Pattern noPattern = {0, 0}; + const vector subSamples = {{.numBytesOfClearData = kSegmentSize, + .numBytesOfEncryptedData = 0}}; + auto sessionId = openSession(); + loadKeys(sessionId, config); + + Status status = cryptoPlugin->setMediaDrmSession(sessionId); + EXPECT_EQ(Status::OK, status); + + decrypt(Mode::UNENCRYPTED, key.isSecure, toHidlArray(key.keyId), + &iv[0], subSamples, noPattern, key.clearContentKey, StatusV1_2::ERROR_DRM_FRAME_TOO_LARGE); + + closeSession(sessionId); + } + } +} + +/** + * Negative decrypt test. Decrypt without loading keys. + */ +TEST_P(DrmHalTest, EncryptedAesCtrSegmentTestNoKeys) { + RETURN_IF_SKIPPED; + for (const auto& config : contentConfigurations) { + for (const auto& key : config.keys) { + vector iv(AES_BLOCK_SIZE, 0); + const Pattern noPattern = {0, 0}; + const vector subSamples = {{.numBytesOfClearData = 256, + .numBytesOfEncryptedData = 256}}; + auto sessionId = openSession(); + + Status status = cryptoPlugin->setMediaDrmSession(sessionId); + EXPECT_EQ(Status::OK, status); + + uint32_t byteCount = decrypt(Mode::AES_CTR, key.isSecure, + toHidlArray(key.keyId), &iv[0], subSamples, noPattern, + key.clearContentKey, StatusV1_2::ERROR_DRM_NO_LICENSE); + EXPECT_EQ(0u, byteCount); + + closeSession(sessionId); + } + } +} + +/** + * Ensure clearkey drm factory doesn't support security level higher than supported + */ +TEST_P(DrmHalClearkeyTest, BadLevelNotSupported) { + const SecurityLevel kHwSecureAll = SecurityLevel::HW_SECURE_ALL; + EXPECT_FALSE(drmFactory->isCryptoSchemeSupported_1_2(getVendorUUID(), kVideoMp4, kHwSecureAll)); +} + +/** + * Test resource contention during attempt to generate key request + */ +TEST_P(DrmHalClearkeyTest, GetKeyRequestResourceContention) { + Status status = drmPlugin->setPropertyString(kDrmErrorTestKey, kResourceContentionValue); + EXPECT_EQ(Status::OK, status); + auto sessionId = openSession(); + hidl_vec initData; + KeyedVector optionalParameters; + auto res = drmPlugin->getKeyRequest_1_2( + sessionId, initData, kVideoMp4, KeyType::STREAMING, + optionalParameters, [&](StatusV1_2 status, const hidl_vec&, + KeyRequestType, const hidl_string&) { + EXPECT_EQ(StatusV1_2::ERROR_DRM_RESOURCE_CONTENTION, status); + }); + EXPECT_OK(res); + + status = drmPlugin->closeSession(sessionId); + EXPECT_NE(Status::OK, status); +} + +/** + * Test clearkey plugin offline key with mock error + */ +TEST_P(DrmHalClearkeyTest, OfflineLicenseInvalidState) { + auto sessionId = openSession(); + hidl_vec keySetId = loadKeys(sessionId, KeyType::OFFLINE); + Status status = drmPlugin->setPropertyString(kDrmErrorTestKey, kDrmErrorGeneric); + EXPECT_EQ(Status::OK, status); + + // everything should start failing + const Status kInvalidState = Status::ERROR_DRM_INVALID_STATE; + const OfflineLicenseState kUnknownState = OfflineLicenseState::UNKNOWN; + auto res = drmPlugin->getOfflineLicenseKeySetIds(checkKeySetIds); + EXPECT_OK(res); + res = drmPlugin->getOfflineLicenseState(keySetId, checkKeySetIdState); + EXPECT_OK(res); + Status err = drmPlugin->removeOfflineLicense(keySetId); + EXPECT_EQ(kInvalidState, err); + closeSession(sessionId); +} + +/** + * Test SessionLostState is triggered on error + */ +TEST_P(DrmHalClearkeyTest, SessionLostState) { + sp listener = new DrmHalPluginListener(); + auto res = drmPlugin->setListener(listener); + EXPECT_OK(res); + + Status status = drmPlugin->setPropertyString(kDrmErrorTestKey, kDrmErrorGeneric); + EXPECT_EQ(Status::OK, status); + + auto sessionId = openSession(); + drmPlugin->closeSession(sessionId); + + auto result = listener->WaitForCallback(kCallbackLostState); + EXPECT_TRUE(result.no_timeout); + EXPECT_TRUE(result.args); + EXPECT_EQ(sessionId, *(result.args)); +} + +/** + * Negative decrypt test. Decrypt with invalid key. + */ +TEST_P(DrmHalClearkeyTest, DecryptWithEmptyKey) { + vector iv(AES_BLOCK_SIZE, 0); + const Pattern noPattern = {0, 0}; + const uint32_t kClearBytes = 512; + const uint32_t kEncryptedBytes = 512; + const vector subSamples = { + {.numBytesOfClearData = kClearBytes, + .numBytesOfEncryptedData = kEncryptedBytes}}; + + // base 64 encoded JSON response string, must not contain padding character '=' + const hidl_string emptyKeyResponse = + "{\"keys\":[" \ + "{" \ + "\"kty\":\"oct\"" \ + "\"alg\":\"A128KW2\"" \ + "\"k\":\"SGVsbG8gRnJpZW5kIQ\"" \ + "\"kid\":\"Y2xlYXJrZXlrZXlpZDAyAy\"" \ + "}" \ + "{" \ + "\"kty\":\"oct\"," \ + "\"alg\":\"A128KW2\"" \ + "\"kid\":\"Y2xlYXJrZXlrZXlpZDAzAy\"," \ + // empty key follows + "\"k\":\"R\"" \ + "}]" \ + "}"; + const size_t kEmptyKeyResponseSize = emptyKeyResponse.size(); + + hidl_vec invalidResponse; + invalidResponse.resize(kEmptyKeyResponseSize); + memcpy(invalidResponse.data(), emptyKeyResponse.c_str(), kEmptyKeyResponseSize); + decryptWithInvalidKeys(invalidResponse, iv, noPattern, subSamples); +} + +/** + * Negative decrypt test. Decrypt with a key exceeds AES_BLOCK_SIZE. + */ +TEST_P(DrmHalClearkeyTest, DecryptWithKeyTooLong) { + vector iv(AES_BLOCK_SIZE, 0); + const Pattern noPattern = {0, 0}; + const uint32_t kClearBytes = 512; + const uint32_t kEncryptedBytes = 512; + const vector subSamples = { + {.numBytesOfClearData = kClearBytes, + .numBytesOfEncryptedData = kEncryptedBytes}}; + + // base 64 encoded JSON response string, must not contain padding character '=' + const hidl_string keyTooLongResponse = + "{\"keys\":[" \ + "{" \ + "\"kty\":\"oct\"," \ + "\"alg\":\"A128KW2\"" \ + "\"kid\":\"Y2xlYXJrZXlrZXlpZDAzAy\"," \ + // key too long + "\"k\":\"V2lubmllIHRoZSBwb29oIVdpbm5pZSB0aGUgcG9vaCE=\"" \ + "}]" \ + "}"; + const size_t kKeyTooLongResponseSize = keyTooLongResponse.size(); + + hidl_vec invalidResponse; + invalidResponse.resize(kKeyTooLongResponseSize); + memcpy(invalidResponse.data(), keyTooLongResponse.c_str(), kKeyTooLongResponseSize); + decryptWithInvalidKeys(invalidResponse, iv, noPattern, subSamples); +} + +/** + * Instantiate the set of test cases for each vendor module + */ + +INSTANTIATE_TEST_CASE_P( + DrmHalTestClearkey, DrmHalTest, + testing::Values("clearkey")); + +INSTANTIATE_TEST_CASE_P( + DrmHalTestClearkeyExtended, DrmHalClearkeyTest, + testing::Values("clearkey")); + +INSTANTIATE_TEST_CASE_P( + DrmHalTestVendor, DrmHalTest, + testing::ValuesIn(DrmHalTest::gVendorModules->getPathList())); + +int main(int argc, char** argv) { +#if defined(__LP64__) + const char* kModulePath = "/data/local/tmp/64/lib"; +#else + const char* kModulePath = "/data/local/tmp/32/lib"; +#endif + DrmHalTest::gVendorModules = new drm_vts::VendorModules(kModulePath); + if (DrmHalTest::gVendorModules->getPathList().size() == 0) { + std::cerr << "WARNING: No vendor modules found in " << kModulePath << + ", all vendor tests will be skipped" << std::endl; + } + ::testing::AddGlobalTestEnvironment(DrmHidlEnvironment::Instance()); + ::testing::InitGoogleTest(&argc, argv); + DrmHidlEnvironment::Instance()->init(&argc, argv); + int status = RUN_ALL_TESTS(); + ALOGI("Test result = %d", status); + return status; +} diff --git a/drm/1.2/vts/functional/vendor_modules.cpp b/drm/1.2/vts/functional/vendor_modules.cpp new file mode 100644 index 0000000000..efcb90a91a --- /dev/null +++ b/drm/1.2/vts/functional/vendor_modules.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "drm-vts-vendor-modules" + +#include +#include +#include +#include +#include +#include + +#include "vendor_modules.h" + +using std::string; +using std::vector; +using std::unique_ptr; +using ::android::String8; +using ::android::hardware::drm::V1_0::helper::SharedLibrary; + +namespace drm_vts { +void VendorModules::scanModules(const std::string &directory) { + DIR* dir = opendir(directory.c_str()); + if (dir == NULL) { + ALOGE("Unable to open drm VTS vendor directory %s", directory.c_str()); + } else { + struct dirent* entry; + while ((entry = readdir(dir))) { + ALOGD("checking file %s", entry->d_name); + string fullpath = directory + "/" + entry->d_name; + if (endsWith(fullpath, ".so")) { + mPathList.push_back(fullpath); + } + } + closedir(dir); + } +} + +DrmHalVTSVendorModule* VendorModules::getModule(const string& path) { + if (mOpenLibraries.find(path) == mOpenLibraries.end()) { + auto library = std::make_unique(String8(path.c_str())); + if (!library) { + ALOGE("failed to map shared library %s", path.c_str()); + return NULL; + } + mOpenLibraries[path] = std::move(library); + } + const unique_ptr& library = mOpenLibraries[path]; + void* symbol = library->lookup("vendorModuleFactory"); + if (symbol == NULL) { + ALOGE("getVendorModule failed to lookup 'vendorModuleFactory' in %s: " + "%s", path.c_str(), library->lastError()); + return NULL; + } + typedef DrmHalVTSVendorModule* (*ModuleFactory)(); + ModuleFactory moduleFactory = reinterpret_cast(symbol); + return (*moduleFactory)(); +} +}; diff --git a/drm/1.2/vts/functional/vendor_modules.h b/drm/1.2/vts/functional/vendor_modules.h new file mode 100644 index 0000000000..9b730adcd9 --- /dev/null +++ b/drm/1.2/vts/functional/vendor_modules.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2019 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 VENDOR_MODULES_H +#define VENDOR_MODULES_H + +#include +#include +#include + +#include + +using ::android::hardware::drm::V1_0::helper::SharedLibrary; + +class DrmHalVTSVendorModule; + +namespace drm_vts { +class VendorModules { + public: + /** + * Initialize with a file system path where the shared libraries + * are to be found. + */ + explicit VendorModules(const std::string& dir) { + scanModules(dir); + } + ~VendorModules() {} + + /** + * Retrieve a DrmHalVTSVendorModule given its full path. The + * getAPIVersion method can be used to determine the versioned + * subclass type. + */ + DrmHalVTSVendorModule* getModule(const std::string& path); + + /** + * Return the list of paths to available vendor modules. + */ + std::vector getPathList() const {return mPathList;} + + private: + std::vector mPathList; + std::map> mOpenLibraries; + + /** + * Scan the list of paths to available vendor modules. + */ + void scanModules(const std::string& dir); + + inline bool endsWith(const std::string& str, const std::string& suffix) const { + if (suffix.size() > str.size()) return false; + return std::equal(suffix.rbegin(), suffix.rend(), str.rbegin()); + } + + VendorModules(const VendorModules&) = delete; + void operator=(const VendorModules&) = delete; +}; +}; + +#endif // VENDOR_MODULES_H From 0a3c8443986459e0abd56bca4ab9b68e5fd5a7be Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Thu, 7 Mar 2019 14:58:59 -0800 Subject: [PATCH 528/718] Remove obsolete comments. BUG: 127850729 Test: N/A Change-Id: I6d45f30c129749a95050d3c046fbfe91d0a75f3e --- current.txt | 2 +- graphics/composer/2.3/IComposerClient.hal | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/current.txt b/current.txt index 8e790f8243..b94f37ca25 100644 --- a/current.txt +++ b/current.txt @@ -479,7 +479,7 @@ b826892686850a9cf2b60ca5845db7185c2196ea4dd765cd80cd163169678a78 android.hardwar 01c6398c90fc6be0640810e2c5d8a4863b457280132bb3f97dd5682e19632b62 android.hardware.graphics.bufferqueue@2.0::types 7a2d64095252f85781b2d521f4f11d04ce774544feececcec2088c568656e93c android.hardware.graphics.common@1.2::types 3dff04a36b86660b5807414587e530bb0c294ed56fdff06f8915ba0a9b73f974 android.hardware.graphics.composer@2.3::IComposer -ed0cf91532e88dff073cf7f45b9c65ee1c88553ebcb97892f7b7072abb9b822a android.hardware.graphics.composer@2.3::IComposerClient +daa44e83d7709bf1c9e0bd9a6b552feff496fd14574a9461ee93c21980fc5b15 android.hardware.graphics.composer@2.3::IComposerClient 5c8bf8e1af9efe225a4661db8c08ff1b7e13fdc8ed49f35291bd0b6c9436b8f2 android.hardware.graphics.mapper@3.0::IMapper 7183d9d9acfa41a61a64bdfed548e98299265a7bb1821a3ed204173b5c2cfd4a android.hardware.graphics.mapper@3.0::types c3f831a66d5815baf74f5b82fe79cf099542ddae4dfab3f388e1d41828e794fc android.hardware.health.storage@1.0::IGarbageCollectCallback diff --git a/graphics/composer/2.3/IComposerClient.hal b/graphics/composer/2.3/IComposerClient.hal index a3b7792c05..5fcc0e67d6 100644 --- a/graphics/composer/2.3/IComposerClient.hal +++ b/graphics/composer/2.3/IComposerClient.hal @@ -28,7 +28,6 @@ import @2.1::Error; interface IComposerClient extends @2.2::IComposerClient { - // Bug: Move this enum to LLNDK after we decide where to put graphic types. /** * Required capabilities which are supported by the display. The * particular set of supported capabilities for a given display may be @@ -64,7 +63,6 @@ interface IComposerClient extends @2.2::IComposerClient { DOZE = 2, }; - //Bug: Move this enum to LLNDK after we decide where to put graphic types. /** * PerFrameMetadataKey * From 3e83c4558a60af8938d9e2e3955a4b87faeb0c9d Mon Sep 17 00:00:00 2001 From: Dan Gittik Date: Fri, 18 Jan 2019 19:28:52 +0000 Subject: [PATCH 529/718] Moved brightness from Lights to SF. Test: manual. Check that brightness works. Fixes: 111435292 Change-Id: I3d19bc2fc4088bc9a956a5cf38c3b163fe35256f --- current.txt | 2 +- graphics/composer/2.3/IComposerClient.hal | 39 +++++++++++++++++++ .../include/composer-hal/2.3/ComposerClient.h | 14 ++++++- .../include/composer-hal/2.3/ComposerHal.h | 2 + .../include/composer-passthrough/2.3/HwcHal.h | 30 +++++++++++++- .../composer/2.3/utils/vts/ComposerVts.cpp | 13 +++++++ .../include/composer-vts/2.3/ComposerVts.h | 8 +++- .../VtsHalGraphicsComposerV2_3TargetTest.cpp | 30 ++++++++++++++ 8 files changed, 133 insertions(+), 5 deletions(-) diff --git a/current.txt b/current.txt index 7af62c638e..f1b030e522 100644 --- a/current.txt +++ b/current.txt @@ -479,7 +479,7 @@ b826892686850a9cf2b60ca5845db7185c2196ea4dd765cd80cd163169678a78 android.hardwar 01c6398c90fc6be0640810e2c5d8a4863b457280132bb3f97dd5682e19632b62 android.hardware.graphics.bufferqueue@2.0::types 7a2d64095252f85781b2d521f4f11d04ce774544feececcec2088c568656e93c android.hardware.graphics.common@1.2::types 3dff04a36b86660b5807414587e530bb0c294ed56fdff06f8915ba0a9b73f974 android.hardware.graphics.composer@2.3::IComposer -daa44e83d7709bf1c9e0bd9a6b552feff496fd14574a9461ee93c21980fc5b15 android.hardware.graphics.composer@2.3::IComposerClient +54bc1dc874f8bc0781767786075dafd33a0796c1eea7d2317231b8929280e946 android.hardware.graphics.composer@2.3::IComposerClient 5c8bf8e1af9efe225a4661db8c08ff1b7e13fdc8ed49f35291bd0b6c9436b8f2 android.hardware.graphics.mapper@3.0::IMapper 7183d9d9acfa41a61a64bdfed548e98299265a7bb1821a3ed204173b5c2cfd4a android.hardware.graphics.mapper@3.0::types c3f831a66d5815baf74f5b82fe79cf099542ddae4dfab3f388e1d41828e794fc android.hardware.health.storage@1.0::IGarbageCollectCallback diff --git a/graphics/composer/2.3/IComposerClient.hal b/graphics/composer/2.3/IComposerClient.hal index 5fcc0e67d6..1eea306523 100644 --- a/graphics/composer/2.3/IComposerClient.hal +++ b/graphics/composer/2.3/IComposerClient.hal @@ -61,6 +61,11 @@ interface IComposerClient extends @2.2::IComposerClient { * PowerMode::DOZE_SUSPEND. */ DOZE = 2, + + /** + * Indicates that the display supports brightness operations. + */ + BRIGHTNESS = 3, }; /** @@ -495,4 +500,38 @@ interface IComposerClient extends @2.2::IComposerClient { float maxLuminance, float maxAverageLuminance, float minLuminance); + + /** + * Gets whether brightness operations are supported on a display. + * + * @param display + * The display. + * + * @return error is NONE upon success. Otherwise, + * BAD_DISPLAY when the display is invalid, or + * BAD_PARAMETER when the output parameter is invalid. + * @return support + * Whether brightness operations are supported on the display. + */ + getDisplayBrightnessSupport(Display display) generates (Error error, bool support); + + /** + * Sets the brightness of a display. + * + * Ideally, the brightness change should take effect in the next frame post (so that it can be + * aligned with color transforms). + * + * @param display + * The display whose brightness is set. + * @param brightness + * A number between 0.0f (minimum brightness) and 1.0f (maximum brightness), or -1.0 to + * turn the backlight off. + * + * @return error is NONE upon success. Otherwise, + * BAD_DISPLAY when the display is invalid, or + * UNSUPPORTED when brightness operations are not supported, or + * BAD_PARAMETER when the brightness is invalid, or + * NO_RESOURCES when the brightness cannot be applied. + */ + setDisplayBrightness(Display display, float brightness) generates (Error error); }; diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h index a272e72d74..1b4079507a 100644 --- a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h +++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h @@ -172,7 +172,19 @@ class ComposerClientImpl : public V2_2::hal::detail::ComposerClientImpl getDisplayBrightnessSupport( + Display display, IComposerClient::getDisplayBrightnessSupport_cb hidl_cb) override { + bool support = false; + Error error = mHal->getDisplayBrightnessSupport(display, &support); + hidl_cb(error, support); + return Void(); + } + + Return setDisplayBrightness(Display display, float brightness) override { + return mHal->setDisplayBrightness(display, brightness); + } + + protected: std::unique_ptr createCommandEngine() override { return std::make_unique( mHal, static_cast(mResources.get())); diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h index a0812ad9a7..186b004810 100644 --- a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h +++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h @@ -119,6 +119,8 @@ class ComposerHal : public V2_2::hal::ComposerHal { virtual Error setLayerPerFrameMetadataBlobs( Display display, Layer layer, std::vector& blobs) = 0; + virtual Error getDisplayBrightnessSupport(Display display, bool* outSupport) = 0; + virtual Error setDisplayBrightness(Display display, float brightness) = 0; }; } // namespace hal diff --git a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h index 41e333ac5e..070cf80e44 100644 --- a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h +++ b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h @@ -245,7 +245,29 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl { return static_cast(err); } - protected: + Error getDisplayBrightnessSupport(Display display, bool* outSupport) { + if (!mDispatch.getDisplayBrightnessSupport) { + return Error::UNSUPPORTED; + } + bool support = false; + int32_t error = mDispatch.getDisplayBrightnessSupport(mDevice, display, &support); + *outSupport = support; + return static_cast(error); + } + + Error setDisplayBrightness(Display display, float brightness) { + if (std::isnan(brightness) || brightness > 1.0f || + (brightness < 0.0f && brightness != -1.0f)) { + return Error::BAD_PARAMETER; + } + if (!mDispatch.setDisplayBrightness) { + return Error::UNSUPPORTED; + } + int32_t error = mDispatch.setDisplayBrightness(mDevice, display, brightness); + return static_cast(error); + } + + protected: bool initDispatch() override { if (!BaseType2_2::initDispatch()) { return false; @@ -265,6 +287,10 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl { &mDispatch.getDisplayCapabilities); this->initOptionalDispatch(HWC2_FUNCTION_SET_LAYER_PER_FRAME_METADATA_BLOBS, &mDispatch.setLayerPerFrameMetadataBlobs); + this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAY_BRIGHTNESS_SUPPORT, + &mDispatch.getDisplayBrightnessSupport); + this->initOptionalDispatch(HWC2_FUNCTION_SET_DISPLAY_BRIGHTNESS, + &mDispatch.setDisplayBrightness); return true; } @@ -277,6 +303,8 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl { HWC2_PFN_GET_DISPLAYED_CONTENT_SAMPLE getDisplayedContentSample; HWC2_PFN_GET_DISPLAY_CAPABILITIES getDisplayCapabilities; HWC2_PFN_SET_LAYER_PER_FRAME_METADATA_BLOBS setLayerPerFrameMetadataBlobs; + HWC2_PFN_GET_DISPLAY_BRIGHTNESS_SUPPORT getDisplayBrightnessSupport; + HWC2_PFN_SET_DISPLAY_BRIGHTNESS setDisplayBrightness; } mDispatch = {}; using BaseType2_2 = V2_2::passthrough::detail::HwcHalImpl; diff --git a/graphics/composer/2.3/utils/vts/ComposerVts.cpp b/graphics/composer/2.3/utils/vts/ComposerVts.cpp index 0e541ed2e3..4de85d6aa4 100644 --- a/graphics/composer/2.3/utils/vts/ComposerVts.cpp +++ b/graphics/composer/2.3/utils/vts/ComposerVts.cpp @@ -186,6 +186,19 @@ std::vector ComposerClient::getDisplayCapabi return capabilities; } +bool ComposerClient::getDisplayBrightnessSupport(Display display) { + bool support = false; + mClient->getDisplayBrightnessSupport(display, [&](const auto& error, const auto& tmpSupport) { + ASSERT_EQ(Error::NONE, error) << "failed to get brightness support"; + support = tmpSupport; + }); + return support; +} + +Error ComposerClient::setDisplayBrightness(Display display, float brightness) { + return mClient->setDisplayBrightness(display, brightness); +} + } // namespace vts } // namespace V2_3 } // namespace composer diff --git a/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h b/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h index ad4ef0b51e..a0e764d5e6 100644 --- a/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h +++ b/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h @@ -52,7 +52,7 @@ class Composer : public V2_2::vts::Composer { std::unique_ptr createClient(); - protected: + protected: explicit Composer(const sp& composer); private: @@ -99,7 +99,11 @@ class ComposerClient : public V2_2::vts::ComposerClient { std::vector getPerFrameMetadataKeys_2_3(Display display); - private: + bool getDisplayBrightnessSupport(Display display); + + Error setDisplayBrightness(Display display, float brightness); + + private: const sp mClient; }; diff --git a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp index de74e28cc7..b983e42d16 100644 --- a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp +++ b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp @@ -600,6 +600,36 @@ TEST_F(GraphicsComposerHidlTest, SetLayerPerFrameMetadataBlobs) { } } +/* + * Test that getDisplayBrightnessSupport works as expected. + */ +TEST_F(GraphicsComposerHidlTest, getDisplayBrightnessSupport) { + auto capabilities = mComposerClient->getDisplayCapabilities(mPrimaryDisplay); + bool brightnessSupport = + std::find(capabilities.begin(), capabilities.end(), + IComposerClient::DisplayCapability::BRIGHTNESS) != capabilities.end(); + EXPECT_EQ(mComposerClient->getDisplayBrightnessSupport(mPrimaryDisplay), brightnessSupport); +} + +/* + * Test that if brightness operations are supported, setDisplayBrightness works as expected. + */ +TEST_F(GraphicsComposerHidlTest, setDisplayBrightness) { + if (!mComposerClient->getDisplayBrightnessSupport(mPrimaryDisplay)) { + EXPECT_EQ(mComposerClient->getRaw()->setDisplayBrightness(mPrimaryDisplay, 0.5f), + Error::UNSUPPORTED); + GTEST_SUCCEED() << "Brightness operations are not supported"; + } + + EXPECT_EQ(mComposerClient->setDisplayBrightness(mPrimaryDisplay, 0.0f), Error::NONE); + EXPECT_EQ(mComposerClient->setDisplayBrightness(mPrimaryDisplay, 0.5f), Error::NONE); + EXPECT_EQ(mComposerClient->setDisplayBrightness(mPrimaryDisplay, 1.0f), Error::NONE); + EXPECT_EQ(mComposerClient->setDisplayBrightness(mPrimaryDisplay, -1.0f), Error::NONE); + + EXPECT_EQ(mComposerClient->setDisplayBrightness(mPrimaryDisplay, +2.0f), Error::BAD_PARAMETER); + EXPECT_EQ(mComposerClient->setDisplayBrightness(mPrimaryDisplay, -2.0f), Error::BAD_PARAMETER); +} + } // namespace } // namespace vts } // namespace V2_3 From 0d48dc81d08c2f6947537490c258c84d72cd3621 Mon Sep 17 00:00:00 2001 From: Yifan Hong Date: Thu, 7 Mar 2019 13:04:33 -0800 Subject: [PATCH 530/718] health: skip VTS on healthd if vendor HAL is present. If vendor HAL is present, healthd is not used by the framework. VTS should skip testing it when this is the case. Provide a --force option to the test if one wants to test healthd. Fixes: 118852225 Test: on walleye, test healthd with and without --force. Change-Id: I85f792f25406b1c02887a0ac273730e719003e2f Merged-In: I85f792f25406b1c02887a0ac273730e719003e2f (cherry picked from commit e6807ddec17da45161b5f20396776a0ba38b3680) --- health/2.0/vts/functional/Android.bp | 1 + .../vts/functional/VtsHalHealthV2_0TargetTest.cpp | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/health/2.0/vts/functional/Android.bp b/health/2.0/vts/functional/Android.bp index 4ad01b98db..c4f2dc9e3a 100644 --- a/health/2.0/vts/functional/Android.bp +++ b/health/2.0/vts/functional/Android.bp @@ -19,6 +19,7 @@ cc_test { defaults: ["VtsHalTargetTestDefaults"], srcs: ["VtsHalHealthV2_0TargetTest.cpp"], static_libs: [ + "libgflags", "android.hardware.health@1.0", "android.hardware.health@2.0", ], diff --git a/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp b/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp index c5431e45c2..55b48b86ff 100644 --- a/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp +++ b/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp @@ -22,6 +22,7 @@ #include #include #include +#include using ::testing::AssertionFailure; using ::testing::AssertionResult; @@ -29,6 +30,8 @@ using ::testing::AssertionSuccess; using ::testing::VtsHalHidlTargetTestBase; using ::testing::VtsHalHidlTargetTestEnvBase; +DEFINE_bool(force, false, "Force test healthd even when the default instance is present."); + namespace android { namespace hardware { namespace health { @@ -57,6 +60,14 @@ class HealthHidlTest : public ::testing::VtsHalHidlTargetTestBase { public: virtual void SetUp() override { std::string serviceName = HealthHidlEnvironment::Instance()->getServiceName(); + + if (serviceName == "backup" && !FLAGS_force && + ::testing::VtsHalHidlTargetTestBase::getService() != nullptr) { + LOG(INFO) << "Skipping tests on healthd because the default instance is present. " + << "Use --force if you really want to test healthd."; + GTEST_SKIP(); + } + LOG(INFO) << "get service with name:" << serviceName; ASSERT_FALSE(serviceName.empty()); mHealth = ::testing::VtsHalHidlTargetTestBase::getService(serviceName); @@ -269,6 +280,7 @@ int main(int argc, char** argv) { ::testing::AddGlobalTestEnvironment(HealthHidlEnvironment::Instance()); ::testing::InitGoogleTest(&argc, argv); HealthHidlEnvironment::Instance()->init(&argc, argv); + gflags::ParseCommandLineFlags(&argc, &argv, true /* remove flags */); int status = RUN_ALL_TESTS(); LOG(INFO) << "Test result = " << status; return status; From 68c09adf4c387650dadf3419334dc8db9da008ce Mon Sep 17 00:00:00 2001 From: Yifan Hong Date: Fri, 8 Mar 2019 11:37:33 -0800 Subject: [PATCH 531/718] health vts: implement GTEST_SKIP if not defined. gtest in Android P tree does not have GTEST_SKIP. Implement a naive version of it. Bug: 118852225 Test: manually undefine GTEST_SKIP, test with and without --force Change-Id: I8df1154d8a94a67ae28e8024de6022fcfe76384d Merged-In: I8df1154d8a94a67ae28e8024de6022fcfe76384d (cherry picked from commit 03b2a3477b9c39403a8cc641e0d7ef2d092eff66) --- .../functional/VtsHalHealthV2_0TargetTest.cpp | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp b/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp index 55b48b86ff..7bb47fdd1f 100644 --- a/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp +++ b/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp @@ -17,6 +17,8 @@ #define LOG_TAG "health_hidl_hal_test" #include +#include +#include #include #include @@ -32,6 +34,39 @@ using ::testing::VtsHalHidlTargetTestEnvBase; DEFINE_bool(force, false, "Force test healthd even when the default instance is present."); +// If GTEST_SKIP is not implemented, use our own skipping mechanism +#ifndef GTEST_SKIP +static std::mutex gSkippedTestsMutex; +static std::set gSkippedTests; +static std::string GetCurrentTestName() { + const auto& info = ::testing::UnitTest::GetInstance()->current_test_info(); +#ifdef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ + std::string test_suite = info->test_suite_name(); +#else + std::string test_suite = info->test_case_name(); +#endif + return test_suite + "." + info->name(); +} + +#define GTEST_SKIP() \ + do { \ + std::unique_lock lock(gSkippedTestsMutex); \ + gSkippedTests.insert(GetCurrentTestName()); \ + return; \ + } while (0) + +#define SKIP_IF_SKIPPED() \ + do { \ + std::unique_lock lock(gSkippedTestsMutex); \ + if (gSkippedTests.find(GetCurrentTestName()) != gSkippedTests.end()) { \ + std::cerr << "[ SKIPPED ] " << GetCurrentTestName() << std::endl; \ + return; \ + } \ + } while (0) +#else +#define SKIP_IF_SKIPPED() +#endif + namespace android { namespace hardware { namespace health { @@ -122,6 +157,7 @@ AssertionResult isAllOk(const Return& r) { * unregisterCallback, and update. */ TEST_F(HealthHidlTest, Callbacks) { + SKIP_IF_SKIPPED(); using namespace std::chrono_literals; sp firstCallback = new Callback(); sp secondCallback = new Callback(); @@ -158,6 +194,7 @@ TEST_F(HealthHidlTest, Callbacks) { } TEST_F(HealthHidlTest, UnregisterNonExistentCallback) { + SKIP_IF_SKIPPED(); sp callback = new Callback(); auto ret = mHealth->unregisterCallback(callback); ASSERT_OK(ret); @@ -239,6 +276,7 @@ bool verifyHealthInfo(const HealthInfo& health_info) { * interface IHealth. */ TEST_F(HealthHidlTest, Properties) { + SKIP_IF_SKIPPED(); EXPECT_OK(mHealth->getChargeCounter([](auto result, auto value) { EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value > 0); })); From 4add15d0c99a9cebf219e97043b144b586c2a75c Mon Sep 17 00:00:00 2001 From: Robert Shih Date: Fri, 8 Mar 2019 15:15:38 -0800 Subject: [PATCH 532/718] Amend drm@1.2 vts mock errors Bug: 118402843 Test: VtsHalDrmV1_2TargetTest Change-Id: I05cc92d33a50b37ce12d8295cdd129d2653836d1 --- drm/1.2/vts/functional/drm_hal_test.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drm/1.2/vts/functional/drm_hal_test.cpp b/drm/1.2/vts/functional/drm_hal_test.cpp index 067b5e474f..f37adaf310 100644 --- a/drm/1.2/vts/functional/drm_hal_test.cpp +++ b/drm/1.2/vts/functional/drm_hal_test.cpp @@ -41,8 +41,8 @@ using ::android::hardware::hidl_string; static const char* const kVideoMp4 = "video/mp4"; static const char* const kBadMime = "video/unknown"; static const char* const kDrmErrorTestKey = "drmErrorTest"; -static const char* const kDrmErrorGeneric = ""; -static const char* const kResourceContentionValue = "resourceContention"; +static const char* const kDrmErrorInvalidState = "invalidState"; +static const char* const kDrmErrorResourceContention = "resourceContention"; static const SecurityLevel kSwSecureCrypto = SecurityLevel::SW_SECURE_CRYPTO; /** @@ -380,7 +380,7 @@ TEST_P(DrmHalClearkeyTest, BadLevelNotSupported) { * Test resource contention during attempt to generate key request */ TEST_P(DrmHalClearkeyTest, GetKeyRequestResourceContention) { - Status status = drmPlugin->setPropertyString(kDrmErrorTestKey, kResourceContentionValue); + Status status = drmPlugin->setPropertyString(kDrmErrorTestKey, kDrmErrorResourceContention); EXPECT_EQ(Status::OK, status); auto sessionId = openSession(); hidl_vec initData; @@ -403,7 +403,7 @@ TEST_P(DrmHalClearkeyTest, GetKeyRequestResourceContention) { TEST_P(DrmHalClearkeyTest, OfflineLicenseInvalidState) { auto sessionId = openSession(); hidl_vec keySetId = loadKeys(sessionId, KeyType::OFFLINE); - Status status = drmPlugin->setPropertyString(kDrmErrorTestKey, kDrmErrorGeneric); + Status status = drmPlugin->setPropertyString(kDrmErrorTestKey, kDrmErrorInvalidState); EXPECT_EQ(Status::OK, status); // everything should start failing @@ -426,7 +426,7 @@ TEST_P(DrmHalClearkeyTest, SessionLostState) { auto res = drmPlugin->setListener(listener); EXPECT_OK(res); - Status status = drmPlugin->setPropertyString(kDrmErrorTestKey, kDrmErrorGeneric); + Status status = drmPlugin->setPropertyString(kDrmErrorTestKey, kDrmErrorInvalidState); EXPECT_EQ(Status::OK, status); auto sessionId = openSession(); From ce6f1cf448ccd8e901a8ea6dae620b1d7a51fdd5 Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Thu, 21 Feb 2019 07:08:19 +1100 Subject: [PATCH 533/718] audio: Fix and enhance channel mask enums Add AUDIO_CHANNEL_INDEX_MASK_{9..24} Fix channel order for AUDIO_CHANNEL_OUT_3POINT{0,1}POINT2 Bug: 126455009 Test: make Change-Id: I36a89c9903ad1702c5c0bdb0632c3f3234bb75d7 --- audio/common/5.0/types.hal | 22 +++++++++++++++++++--- current.txt | 2 +- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/audio/common/5.0/types.hal b/audio/common/5.0/types.hal index 8f8a888b33..0a8d75bf78 100644 --- a/audio/common/5.0/types.hal +++ b/audio/common/5.0/types.hal @@ -416,9 +416,9 @@ enum AudioChannelMask : uint32_t { OUT_2POINT1POINT2 = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_TOP_SIDE_LEFT | OUT_TOP_SIDE_RIGHT | OUT_LOW_FREQUENCY), - OUT_3POINT0POINT2 = (OUT_FRONT_LEFT | OUT_FRONT_CENTER | OUT_FRONT_RIGHT | + OUT_3POINT0POINT2 = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_FRONT_CENTER | OUT_TOP_SIDE_LEFT | OUT_TOP_SIDE_RIGHT), - OUT_3POINT1POINT2 = (OUT_FRONT_LEFT | OUT_FRONT_CENTER | OUT_FRONT_RIGHT | + OUT_3POINT1POINT2 = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_FRONT_CENTER | OUT_TOP_SIDE_LEFT | OUT_TOP_SIDE_RIGHT | OUT_LOW_FREQUENCY), OUT_QUAD = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT | @@ -517,7 +517,23 @@ enum AudioChannelMask : uint32_t { INDEX_MASK_5 = INDEX_HDR | ((1 << 5) - 1), INDEX_MASK_6 = INDEX_HDR | ((1 << 6) - 1), INDEX_MASK_7 = INDEX_HDR | ((1 << 7) - 1), - INDEX_MASK_8 = INDEX_HDR | ((1 << 8) - 1) + INDEX_MASK_8 = INDEX_HDR | ((1 << 8) - 1), + INDEX_MASK_9 = INDEX_HDR | ((1 << 9) - 1), + INDEX_MASK_10 = INDEX_HDR | ((1 << 10) - 1), + INDEX_MASK_11 = INDEX_HDR | ((1 << 11) - 1), + INDEX_MASK_12 = INDEX_HDR | ((1 << 12) - 1), + INDEX_MASK_13 = INDEX_HDR | ((1 << 13) - 1), + INDEX_MASK_14 = INDEX_HDR | ((1 << 14) - 1), + INDEX_MASK_15 = INDEX_HDR | ((1 << 15) - 1), + INDEX_MASK_16 = INDEX_HDR | ((1 << 16) - 1), + INDEX_MASK_17 = INDEX_HDR | ((1 << 17) - 1), + INDEX_MASK_18 = INDEX_HDR | ((1 << 18) - 1), + INDEX_MASK_19 = INDEX_HDR | ((1 << 19) - 1), + INDEX_MASK_20 = INDEX_HDR | ((1 << 20) - 1), + INDEX_MASK_21 = INDEX_HDR | ((1 << 21) - 1), + INDEX_MASK_22 = INDEX_HDR | ((1 << 22) - 1), + INDEX_MASK_23 = INDEX_HDR | ((1 << 23) - 1), + INDEX_MASK_24 = INDEX_HDR | ((1 << 24) - 1), }; /** diff --git a/current.txt b/current.txt index 8e790f8243..4852f55401 100644 --- a/current.txt +++ b/current.txt @@ -419,7 +419,7 @@ e05e48c583de14c1e5a6fa9d48ea50244e3e0924b76b342374e7471dc8007ba9 android.hardwar 9471b12b1c255bb530695720bc4174bd74987b75b1f820854af8944bc8c215c9 android.hardware.audio@5.0::IStreamOut 1b0500367ed2b32a841667ac3200edf3d3a164e8004aca445ff1b085ac831e93 android.hardware.audio@5.0::IStreamOutCallback 83e365479cc77d8717c155e1787ee668cd2ae4c557b467cf75b8e7cd53697ad8 android.hardware.audio@5.0::types -894af04bebfe7da5b6791eefeb6eb3627da63d5efea735f16876d11d8ca4f61d android.hardware.audio.common@5.0::types +c25ae57a9197fdf83aa6f7b31ab1ac4922dea4f19f92cdb1f9013ad49fa56594 android.hardware.audio.common@5.0::types f269297866765b95ddd1825676cc8a772f0c7c9863286df596fc302781a42ff5 android.hardware.audio.effect@5.0::IAcousticEchoCancelerEffect fa187b602d8939644ef708ed7627f2e3deac97899a4bda1de07f2ff126abe243 android.hardware.audio.effect@5.0::IAutomaticGainControlEffect e1bf864ccb8458c0da1dcc74a2e748b1dca8ac360df590591cf82d98292d7981 android.hardware.audio.effect@5.0::IBassBoostEffect From b936d1d684b87162ce47479523f23ca98e811358 Mon Sep 17 00:00:00 2001 From: Kevin Chyn Date: Mon, 11 Mar 2019 11:21:14 -0700 Subject: [PATCH 534/718] Add SENSOR_DIRTY constant Fixes: 127993599 Test: Test: hidl-gen -L hash -r android.hardware:hardware/interfaces android.hardware.biometrics.face@1.0 add updated hash to current.txt Test: Builds Change-Id: I98a7953f3a99f263709a15f143a3ca5fd062b489 --- biometrics/face/1.0/types.hal | 9 +++++++-- current.txt | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/biometrics/face/1.0/types.hal b/biometrics/face/1.0/types.hal index 8c4a4e9f4e..de6b99ef1d 100644 --- a/biometrics/face/1.0/types.hal +++ b/biometrics/face/1.0/types.hal @@ -339,10 +339,15 @@ enum FaceAcquiredInfo : int32_t { */ START = 20, + /** + * The sensor is dirty. The user should be informed to clean the sensor. + */ + SENSOR_DIRTY = 21, + /** * Used to enable a vendor-specific acquisition message. */ - VENDOR = 21 + VENDOR = 22 }; /** @@ -375,4 +380,4 @@ struct OptionalBool { * This value is only meaningful if status is OK. */ bool value; -}; \ No newline at end of file +}; diff --git a/current.txt b/current.txt index 4ad47e15ff..f22d14f8d1 100644 --- a/current.txt +++ b/current.txt @@ -437,7 +437,7 @@ ca15a738dedc2f4981925f7d7ff29c22bc3f8a848403dcf0c592c167de09d9af android.hardwar 6385b6accab8a544e2ee54ba7bf5aa55dff6153bcedd80fdaae16fe9e0be7050 android.hardware.audio.effect@5.0::types baf5a0cbf357035394be02d87334890228338fae715f7ab06e2f0e7d05abe656 android.hardware.biometrics.face@1.0::IBiometricsFace 6cbf288d6e6a9f6f0c09d1cde66318aa5b6a8c525778a61ccaedddb090f5e9cb android.hardware.biometrics.face@1.0::IBiometricsFaceClientCallback -ef5d339413d0c94a5b58baafbe3e4bccfd9ed2e7328fbbb5c25471c79923ed2f android.hardware.biometrics.face@1.0::types +95aa2f59e29e2f84d8e84320ace9b6682b426a16e897b4bd241375cbee0e07f3 android.hardware.biometrics.face@1.0::types ecedc58dbcdb13503c19c0ab160ac1dd0530bb1471164149282dd1463c684185 android.hardware.bluetooth.audio@2.0::IBluetoothAudioPort fb9c40e4deab40be5476477078fe3d8a4a4495fd9deef4321878d169d675c633 android.hardware.bluetooth.audio@2.0::IBluetoothAudioProvider f7431f3e3e4e3387fc6f27a6cf423eddcd824a395dc4349d302c995ab44a9895 android.hardware.bluetooth.audio@2.0::IBluetoothAudioProvidersFactory From b2aa43ae94961c15f392a06b247c1d2f36a88581 Mon Sep 17 00:00:00 2001 From: sqian Date: Thu, 7 Mar 2019 20:58:17 -0800 Subject: [PATCH 535/718] Sleep one second after connect. Modem side need time for connect to finish. Test: Sanity (encountered by partner) Bug: 122442056 Change-Id: Ib688b968730fcf604ef3807db9b6bd817594cad6 --- radio/1.0/vts/functional/sap_hidl_hal_api.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/radio/1.0/vts/functional/sap_hidl_hal_api.cpp b/radio/1.0/vts/functional/sap_hidl_hal_api.cpp index da78f410d1..1d79ff61a0 100644 --- a/radio/1.0/vts/functional/sap_hidl_hal_api.cpp +++ b/radio/1.0/vts/functional/sap_hidl_hal_api.cpp @@ -26,6 +26,10 @@ TEST_F(SapHidlTest, connectReq) { sap->connectReq(token, maxMsgSize); EXPECT_EQ(std::cv_status::no_timeout, wait()); EXPECT_EQ(sapCb->sapResponseToken, token); + + // Modem side need time for connect to finish. Adding a waiting time to prevent + // disconnect being requested right after connect request. + sleep(1); } /* From 90af5f189891076b5224f14060f4e61c36eae723 Mon Sep 17 00:00:00 2001 From: Robert Shih Date: Fri, 8 Mar 2019 15:06:40 -0800 Subject: [PATCH 536/718] DrmHalTest.OfflineLicenseStateTest: search keySetId Search for key set id instead of simply checking the number of total offline licenses. Fix LOG_TAG & remove clearkey specific comments from generic plugin tests. Bug: 118402843 Test: VtsHalDrmV1_2TargetTest Change-Id: I245007317c813d5a8585d0a4ee29816b8f51ad3c --- drm/1.2/vts/functional/drm_hal_test.cpp | 27 ++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/drm/1.2/vts/functional/drm_hal_test.cpp b/drm/1.2/vts/functional/drm_hal_test.cpp index 067b5e474f..6043391dd9 100644 --- a/drm/1.2/vts/functional/drm_hal_test.cpp +++ b/drm/1.2/vts/functional/drm_hal_test.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#define LOG_TAG "drm_hal_clearkey_test@1.2" +#define LOG_TAG "drm_hal_test@1.2" #include #include @@ -180,19 +180,36 @@ void checkKeySetIdState(Status status, OfflineLicenseState state) { } /** - * Test clearkey plugin offline key support + * Test drm plugin offline key support */ TEST_P(DrmHalTest, OfflineLicenseTest) { auto sessionId = openSession(); hidl_vec keySetId = loadKeys(sessionId, KeyType::OFFLINE); - auto res = drmPlugin->getOfflineLicenseKeySetIds(checkKeySetIds); + auto res = drmPlugin->getOfflineLicenseKeySetIds( + [&](Status status, const hidl_vec& keySetIds) { + bool found = false; + EXPECT_EQ(Status::OK, status); + for (KeySetId keySetId2: keySetIds) { + if (keySetId == keySetId2) { + found = true; + break; + } + } + EXPECT_TRUE(found) << "keySetId not found"; + }); EXPECT_OK(res); Status err = drmPlugin->removeOfflineLicense(keySetId); EXPECT_EQ(Status::OK, err); - res = drmPlugin->getOfflineLicenseKeySetIds(checkKeySetIds); + res = drmPlugin->getOfflineLicenseKeySetIds( + [&](Status status, const hidl_vec& keySetIds) { + EXPECT_EQ(Status::OK, status); + for (KeySetId keySetId2: keySetIds) { + EXPECT_NE(keySetId, keySetId2); + } + }); EXPECT_OK(res); err = drmPlugin->removeOfflineLicense(keySetId); @@ -202,7 +219,7 @@ TEST_P(DrmHalTest, OfflineLicenseTest) { } /** - * Test clearkey plugin offline key state + * Test drm plugin offline key state */ TEST_P(DrmHalTest, OfflineLicenseStateTest) { auto sessionId = openSession(); From 6424d7ea26d4795b04be788f2fd5af9e5cf7463d Mon Sep 17 00:00:00 2001 From: Kevin Chyn Date: Mon, 11 Mar 2019 13:48:39 -0700 Subject: [PATCH 537/718] Address HIDL review comments Fixes: 127852175 Test: builds Test: hidl-gen -L hash -r android.hardware:hardware/interfaces android.hardware.biometrics.face@1.0 hash added to current.txt Test: make -j56 VtsHalBiometricsFaceV1_0TargetTest Change-Id: I4a8b6db5824a686ec742ed826ff26e721ff26dc8 --- biometrics/face/1.0/IBiometricsFace.hal | 8 +++++--- biometrics/face/1.0/IBiometricsFaceClientCallback.hal | 7 ++----- .../vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp | 7 ++----- current.txt | 4 ++-- 4 files changed, 11 insertions(+), 15 deletions(-) diff --git a/biometrics/face/1.0/IBiometricsFace.hal b/biometrics/face/1.0/IBiometricsFace.hal index cd368faddb..180d829116 100644 --- a/biometrics/face/1.0/IBiometricsFace.hal +++ b/biometrics/face/1.0/IBiometricsFace.hal @@ -59,7 +59,9 @@ interface IBiometricsFace { * * @param userId A non-negative user identifier that must be unique and * persistent for a given user. - * @param storePath filesystem path to the template storage directory. + * @param storePath absolute filesystem path to the template storage + * directory. This must be the /data/vendor_de//facedata + * directory specified by the SeLinux policy. */ @callflow(next={"authenticate", "generateChallenge", "enumerate", "remove"}) setActiveUser(int32_t userId, string storePath) generates (Status status); @@ -159,8 +161,8 @@ interface IBiometricsFace { * @param enabled True to enable the feature, false to disable. * @param hat A valid Hardware Authentication Token, generated as a result * of getChallenge(). - * @param faceId the ID of the enrollment returned by enroll() for the - * feature to update. + * @param faceId the ID of the enrollment returned by onEnrollResult() for + * the feature to update. * @return status The status of this method call. */ setFeature(Feature feature, bool enabled, vec hat, uint32_t faceId) diff --git a/biometrics/face/1.0/IBiometricsFaceClientCallback.hal b/biometrics/face/1.0/IBiometricsFaceClientCallback.hal index 969bc68590..d7c317d2f0 100644 --- a/biometrics/face/1.0/IBiometricsFaceClientCallback.hal +++ b/biometrics/face/1.0/IBiometricsFaceClientCallback.hal @@ -95,13 +95,10 @@ interface IBiometricsFaceClientCallback { * * @param deviceId A unique id associated with the HAL implementation * service that processed this removal. - * @param faceId The id of the face template that was removed. + * @param removed A list of ids that were removed. * @param userId The active user id for the removed face template. - * @param remaining The number of face templates remaining after this - * removal, or 0 if there are no more. */ - oneway onRemoved(uint64_t deviceId, uint32_t faceId, int32_t userId, - uint32_t remaining); + oneway onRemoved(uint64_t deviceId, vec removed, int32_t userId); /** * A callback invoked to enumerate all current face templates. diff --git a/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp b/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp index 795a1ae961..40961f79b9 100644 --- a/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp +++ b/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp @@ -104,7 +104,7 @@ class FaceCallbackBase : public IBiometricsFaceClientCallback { return Return(); } - Return onRemoved(uint64_t, uint32_t, int32_t, uint32_t) override { + Return onRemoved(uint64_t, const hidl_vec&, int32_t) override { ALOGD("Removed callback called."); return Return(); } @@ -155,12 +155,9 @@ class RemoveCallback : public FaceCallbackBase { public: explicit RemoveCallback(int32_t userId) : removeUserId(userId) {} - Return onRemoved(uint64_t, uint32_t, int32_t userId, uint32_t remaining) override { + Return onRemoved(uint64_t, const hidl_vec&, int32_t userId) override { EXPECT_EQ(removeUserId, userId); promise.set_value(); - if (remaining == 0UL) { - promise.set_value(); - } return Return(); } diff --git a/current.txt b/current.txt index f22d14f8d1..d7edfdbed5 100644 --- a/current.txt +++ b/current.txt @@ -435,8 +435,8 @@ ca15a738dedc2f4981925f7d7ff29c22bc3f8a848403dcf0c592c167de09d9af android.hardwar 443659bb9e27221e5da0d16c7a0ecb2dc3a9a03acc8a0b2196b47c50735e2d2e android.hardware.audio.effect@5.0::IVirtualizerEffect 78fed26a781cdca1b3bcb37520bff705d7764ee81db9cfd37014953c7ad2596e android.hardware.audio.effect@5.0::IVisualizerEffect 6385b6accab8a544e2ee54ba7bf5aa55dff6153bcedd80fdaae16fe9e0be7050 android.hardware.audio.effect@5.0::types -baf5a0cbf357035394be02d87334890228338fae715f7ab06e2f0e7d05abe656 android.hardware.biometrics.face@1.0::IBiometricsFace -6cbf288d6e6a9f6f0c09d1cde66318aa5b6a8c525778a61ccaedddb090f5e9cb android.hardware.biometrics.face@1.0::IBiometricsFaceClientCallback +e18ff318f3fc43db37f554696dc4e551abb9b119bde53950f73e28ce33a97a40 android.hardware.biometrics.face@1.0::IBiometricsFace +b6e55d7795bbafd011fb95a3b6d3954bf66c349e14cf107f3b72032ce3ceb448 android.hardware.biometrics.face@1.0::IBiometricsFaceClientCallback 95aa2f59e29e2f84d8e84320ace9b6682b426a16e897b4bd241375cbee0e07f3 android.hardware.biometrics.face@1.0::types ecedc58dbcdb13503c19c0ab160ac1dd0530bb1471164149282dd1463c684185 android.hardware.bluetooth.audio@2.0::IBluetoothAudioPort fb9c40e4deab40be5476477078fe3d8a4a4495fd9deef4321878d169d675c633 android.hardware.bluetooth.audio@2.0::IBluetoothAudioProvider From 221a85e014b30c129fc16aa7e642e5d6dd287b2f Mon Sep 17 00:00:00 2001 From: Yu-Han Yang Date: Mon, 11 Mar 2019 19:06:10 -0700 Subject: [PATCH 538/718] Change CodeType from enum to string (HAL) Bug: 127464982 Test: atest VtsHalGnssV2_0TargetTest Change-Id: Ia8635c3c071bcb03b75d17ac1ba36767dc7eda72 --- current.txt | 2 +- gnss/2.0/IGnssMeasurementCallback.hal | 116 ++++++------------ gnss/2.0/default/GnssMeasurement.cpp | 3 +- .../vts/functional/gnss_hal_test_cases.cpp | 12 +- 4 files changed, 41 insertions(+), 92 deletions(-) diff --git a/current.txt b/current.txt index 4ad47e15ff..a1c5fec4d9 100644 --- a/current.txt +++ b/current.txt @@ -467,7 +467,7 @@ f27baaa587bc3dd9b740cb6928ab812b9b7d105b5187663938aee578105f3c39 android.hardwar d815623a6d1ba4abf21248b84eca70a2bfab03058a88b68a29c063ce8aee6b5c android.hardware.gnss@2.0::IGnssCallback ecc966c68bddbd95c8dae782b84204cf01c75734675e8769963f3b5106ec128b android.hardware.gnss@2.0::IGnssConfiguration c67759f5d6387d273b66729180d03690e827f0b6b8d4e13ce2ff42d31b224065 android.hardware.gnss@2.0::IGnssMeasurement -089338944c45f66f25ba4ee958c161c42fefeb73ec60e4451f3535a1b3fd10c7 android.hardware.gnss@2.0::IGnssMeasurementCallback +3dd30a3ca77ef5ab109a55ba603ff816ae5019436886093dccf8fd6a068f85f1 android.hardware.gnss@2.0::IGnssMeasurementCallback 9e66234e65bcde75733d75d8b5d5cc094c2a5e14b074a25cd3f9ad141dc56f60 android.hardware.gnss@2.0::types 50623a69a88b1c8a05738e4af7d5f78e905f415ccb0e84c99d0a71ea182e9393 android.hardware.gnss.measurement_corrections@1.0::IMeasurementCorrections 6ef12cd95df73f8f80c25eb035d98ca4594f9cee571fdabea838a0b6016dd908 android.hardware.gnss.measurement_corrections@1.0::types diff --git a/gnss/2.0/IGnssMeasurementCallback.hal b/gnss/2.0/IGnssMeasurementCallback.hal index d5dc038b82..d9751d35ac 100644 --- a/gnss/2.0/IGnssMeasurementCallback.hal +++ b/gnss/2.0/IGnssMeasurementCallback.hal @@ -22,77 +22,6 @@ import ElapsedRealtime; /** The callback interface to report measurements from the HAL. */ interface IGnssMeasurementCallback extends @1.1::IGnssMeasurementCallback { - /** - * Enumeration of available values for the GNSS Measurement's code type. Similar to the - * Attribute field described in RINEX 3.03, e.g., in Tables 4-10, and Table A2 at the RINEX 3.03 - * Update 1 Document. - */ - enum GnssMeasurementCodeType : uint8_t { - /** GALILEO E1A, GALILEO E6A, IRNSS L5A, IRNSS SA. */ - A = 0, - - /** GALILEO E1B, GALILEO E6B, IRNSS L5B, IRNSS SB. */ - B = 1, - - /** - * GPS L1 C/A, GPS L2 C/A, GLONASS G1 C/A, GLONASS G2 C/A, GALILEO E1C, GALILEO E6C, SBAS - * L1 C/A, QZSS L1 C/A, IRNSS L5C. - */ - C = 2, - - /** - * GPS L5 I, GLONASS G3 I, GALILEO E5a I, GALILEO E5b I, GALILEO E5a+b I, SBAS L5 I, QZSS L5 - * I, BDS B1 I, BDS B2 I, BDS B3 I. - */ - I = 3, - - /** GPS L1C (P), GPS L2C (L), QZSS L1C (P), QZSS L2C (L), LEX(6) L. */ - L = 4, - - /** GPS L1M, GPS L2M. */ - M = 5, - - /** GPS L1P, GPS L2P, GLONASS G1P, GLONASS G2P. */ - P = 6, - - /** - * GPS L5 Q, GLONASS G3 Q, GALILEO E5a Q, GALILEO E5b Q, GALILEO E5a+b Q, SBAS L5 Q, QZSS L5 - * Q, BDS B1 Q, BDS B2 Q, BDS B3 Q. - */ - Q = 7, - - /** GPS L1C (D), GPS L2C (M), QZSS L1C (D), QZSS L2C (M), LEX(6) S. */ - S = 8, - - /** GPS L1 Z-tracking, GPS L2 Z-tracking. */ - W = 9, - - /** - * GPS L1C (D+P), GPS L2C (M+L), GPS L5 (I+Q), GLONASS G3 (I+Q), GALILEO E1 (B+C), GALILEO - * E5a (I+Q), GALILEO E5b (I+Q), GALILEO E5a+b(I+Q), GALILEO E6 (B+C), SBAS L5 (I+Q), QZSS - * L1C (D+P), QZSS L2C (M+L), QZSS L5 (I+Q), LEX(6) (S+L), BDS B1 (I+Q), BDS B2 (I+Q), BDS - * B3 (I+Q), IRNSS L5 (B+C). - */ - X = 10, - - /** GPS L1Y, GPS L2Y. */ - Y = 11, - - /** GALILEO E1 (A+B+C), GALILEO E6 (A+B+C), QZSS L1-SAIF. */ - Z = 12, - - /** GPS L1 codeless, GPS L2 codeless. */ - N = 13, - - /** - * Other code type that does not belong to any of the above code types. - * - * This code type is used in the case that the above code types do not cover all the code - * types introduced in a new version of RINEX standard. When this code type is set, the - * field GnssMeasurement.otherCodeTypeName must specify the new code type. - */ - OTHER = 255 - }; /** * Flags indicating the GNSS measurement state. @@ -458,12 +387,43 @@ interface IGnssMeasurementCallback extends @1.1::IGnssMeasurementCallback { * The type of code that is currently being tracked in the GNSS measurement. * * For high precision applications the type of code being tracked needs to be considered - * in-order to properly apply code specific corrections to the psuedorange measurements. - */ - GnssMeasurementCodeType codeType; - - /** - * The name of the code type when codeType is OTHER. + * in-order to properly apply code specific corrections to the pseudorange measurements. + * + * Value "A" represents GALILEO E1A, GALILEO E6A, IRNSS L5A, IRNSS SA. + * + * Value "B" represents GALILEO E1B, GALILEO E6B, IRNSS L5B, IRNSS SB. + * + * Value "C" represents GPS L1 C/A, GPS L2 C/A, GLONASS G1 C/A, GLONASS G2 C/A, GALILEO E1C, + * GALILEO E6C, SBAS L1 C/A, QZSS L1 C/A, IRNSS L5C. + * + * Value "I" represents GPS L5 I, GLONASS G3 I, GALILEO E5a I, GALILEO E5b I, GALILEO E5a+b I, + * SBAS L5 I, QZSS L5 I, BDS B1 I, BDS B2 I, BDS B3 I. + * + * Value "L" represents GPS L1C (P), GPS L2C (L), QZSS L1C (P), QZSS L2C (L), LEX(6) L. + * + * Value "M" represents GPS L1M, GPS L2M. + * + * Value "N" represents GPS L1 codeless, GPS L2 codeless. + * + * Value "P" represents GPS L1P, GPS L2P, GLONASS G1P, GLONASS G2P. + * + * Value "Q" represents GPS L5 Q, GLONASS G3 Q, GALILEO E5a Q, GALILEO E5b Q, GALILEO E5a+b Q, + * SBAS L5 Q, QZSS L5 Q, BDS B1 Q, BDS B2 Q, BDS B3 Q. + * + * Value "S" represents GPS L1C (D), GPS L2C (M), QZSS L1C (D), QZSS L2C (M), LEX(6) S. + * + * Value "W" represents GPS L1 Z-tracking, GPS L2 Z-tracking. + * + * Value "X" represents GPS L1C (D+P), GPS L2C (M+L), GPS L5 (I+Q), GLONASS G3 (I+Q), + * GALILEO E1 (B+C), GALILEO E5a (I+Q), GALILEO E5b (I+Q), GALILEO E5a+b(I+Q), + * GALILEO E6 (B+C), SBAS L5 (I+Q), QZSS L1C (D+P), QZSS L2C (M+L), QZSS L5 (I+Q), + * LEX(6) (S+L), BDS B1 (I+Q), BDS B2 (I+Q), BDS B3 (I+Q), IRNSS L5 (B+C). + * + * Value "Y" represents GPS L1Y, GPS L2Y. + * + * Value "Z" represents GALILEO E1 (A+B+C), GALILEO E6 (A+B+C), QZSS L1-SAIF. + * + * Value "UNKNOWN" represents the GNSS Measurement's code type is unknown. * * This is used to specify the observation descriptor defined in GNSS Observation Data File * Header Section Description in the RINEX standard (Version 3.XX). In RINEX Version 3.03, @@ -471,7 +431,7 @@ interface IGnssMeasurementCallback extends @1.1::IGnssMeasurementCallback { * "A channel"). In the future, if for instance a code "G" was added in the official RINEX * standard, "G" could be specified here. */ - string otherCodeTypeName; + string codeType; /** * Per satellite sync state. It represents the current sync state for the associated diff --git a/gnss/2.0/default/GnssMeasurement.cpp b/gnss/2.0/default/GnssMeasurement.cpp index 702c9e2362..a62c2dd27e 100644 --- a/gnss/2.0/default/GnssMeasurement.cpp +++ b/gnss/2.0/default/GnssMeasurement.cpp @@ -114,8 +114,7 @@ GnssData GnssMeasurement::getMockMeasurement() { V1_1::IGnssMeasurementCallback::GnssMeasurement measurement_1_1 = {.v1_0 = measurement_1_0}; V2_0::IGnssMeasurementCallback::GnssMeasurement measurement_2_0 = { .v1_1 = measurement_1_1, - .codeType = IGnssMeasurementCallback::GnssMeasurementCodeType::C, - .otherCodeTypeName = "", + .codeType = "C", .state = GnssMeasurementState::STATE_CODE_LOCK | GnssMeasurementState::STATE_BIT_SYNC | GnssMeasurementState::STATE_SUBFRAME_SYNC | GnssMeasurementState::STATE_TOW_DECODED | diff --git a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp index 3703ebaef9..67fda89fc0 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp +++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp @@ -190,17 +190,7 @@ TEST_F(GnssHalTest, TestGnssMeasurementCodeType) { EXPECT_EQ(measurement_called_count_, 1); ASSERT_TRUE(last_measurement_.measurements.size() > 0); for (auto measurement : last_measurement_.measurements) { - ASSERT_TRUE( - ((int)measurement.codeType >= - (int)IGnssMeasurementCallback_2_0::GnssMeasurementCodeType::A && - (int)measurement.codeType <= - (int)IGnssMeasurementCallback_2_0::GnssMeasurementCodeType::N) || - (int)measurement.codeType == - (int)IGnssMeasurementCallback_2_0::GnssMeasurementCodeType::OTHER); - if ((int)measurement.codeType == - (int)IGnssMeasurementCallback_2_0::GnssMeasurementCodeType::OTHER) { - ASSERT_NE(measurement.otherCodeTypeName, ""); - } + ASSERT_NE(measurement.codeType, ""); } iGnssMeasurement->close(); From d293315d93e7e0aaa2b96f99decc0e8a2244efef Mon Sep 17 00:00:00 2001 From: Xusong Wang Date: Tue, 12 Mar 2019 14:40:32 -0700 Subject: [PATCH 539/718] Skip OUTPUT_INSUFFICIENT_SIZE test for zero-sized output. Bug: 126737477 Test: 1.2 VTS with sample driver Change-Id: I04afd962ed45eac16aacfa9664ad80ba0d4f5855 --- .../1.0/vts/functional/GeneratedTestHarness.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp index 7eea7fcedc..f5cb0d7cf5 100644 --- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp +++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp @@ -77,6 +77,13 @@ void copy_back(MixedTyped* dst, const std::vector& ra, char* sr "Number of types in MixedTyped changed, but copy_back function wasn't updated"); } +static bool isZeroSized(const MixedTyped& example, uint32_t index) { + for (auto i : example.operandDimensions.at(index)) { + if (i == 0) return true; + } + return false; +} + // Top level driver for models and examples generated by test_generator.py // Test driver for those generated from ml/nn/runtime/test/spec static Return ExecutePreparedModel(sp& preparedModel, @@ -178,17 +185,18 @@ void EvaluatePreparedModel(sp& preparedModel, std::function(index)) outputs_info.resize(index + 1); if (index == 0) { // On OutputType::INSUFFICIENT, set the output operand with index 0 with // buffer size one byte less than needed. if (outputType == OutputType::INSUFFICIENT) { - if (s > 1) + if (s > 1 && !isZeroSized(golden, index)) { s -= 1; - else + } else { sizeLargerThanOne = false; + } } } RequestArgument arg = { From 7549141c388a39e3cc1a3d2e1ada9d8066ca99a2 Mon Sep 17 00:00:00 2001 From: Emilian Peev Date: Tue, 12 Mar 2019 18:08:23 -0700 Subject: [PATCH 540/718] Camera: Add recommended low latency use case id One extra recommended id must be present for low latency snapshot use cases. Bug: 128450197 Test: vts-tradefed run commandAndExit vts --skip-all-system-status-check --skip-preconditions --module VtsHalCameraProviderV2_4Target -l INFO Change-Id: I259fec5157f1190c485a373dcaa500d02c0389be --- camera/metadata/3.4/types.hal | 5 +++-- current.txt | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/camera/metadata/3.4/types.hal b/camera/metadata/3.4/types.hal index bb630f1922..30c3217ec7 100644 --- a/camera/metadata/3.4/types.hal +++ b/camera/metadata/3.4/types.hal @@ -22,7 +22,6 @@ package android.hardware.camera.metadata@3.4; -/* Include definitions from all prior minor HAL metadata revisions */ import android.hardware.camera.metadata@3.2; import android.hardware.camera.metadata@3.3; @@ -213,8 +212,10 @@ enum CameraMetadataEnumAndroidScalerAvailableRecommendedStreamConfigurations : u = 0x4, ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_RAW = 0x5, - ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_PUBLIC_END + ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_LOW_LATENCY_SNAPSHOT = 0x6, + ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_PUBLIC_END + = 0x7, ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_VENDOR_START = 0x18, }; diff --git a/current.txt b/current.txt index 10b9b18e39..e1c7af4faf 100644 --- a/current.txt +++ b/current.txt @@ -447,7 +447,7 @@ f7431f3e3e4e3387fc6f27a6cf423eddcd824a395dc4349d302c995ab44a9895 android.hardwar 06237de53c42890029e3f8fe7d1480d078469c0d07608e51c37b4d485d342992 android.hardware.camera.device@3.5::ICameraDeviceCallback 08c68b196e2fc4e5ba67ba0d0917bde828a87cbe2cffec19d04733972da9eb49 android.hardware.camera.device@3.5::ICameraDeviceSession a848f7cb3cb3d080cf175bf08412322bfddb535168253796cdf777afdbf05b38 android.hardware.camera.device@3.5::types -74ec7732fdacb22292c907b49f8f933510851ea1b3ed195c4dcdff35a20387f5 android.hardware.camera.metadata@3.4::types +f727d5f350f55a6d3354aad2feb64e43200de77c10d9d642465566bc260bb8ec android.hardware.camera.metadata@3.4::types 0fb39a7809ad1c52b3efbbed5ef4749b06c2a4f1f19cdc3efa2e3d9b28f1205c android.hardware.camera.provider@2.5::ICameraProvider f5777403d65135a5407723671bc7a864cdca83aea13ee3ce2894b95e6588ca3a android.hardware.camera.provider@2.5::types 44c88954b3c201b26f64fcdb6f278024ab3aae864a9e1ec70e8a74274ae9d6aa android.hardware.cas@1.1::ICas From f8230e060c2f91be84a6e68985f426c83edbdfc3 Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Tue, 12 Mar 2019 15:41:56 -0700 Subject: [PATCH 541/718] Remove import comment on camera metadata HAL. No good place in generated docs. Bug: 124382459 Test: ./update-makefiles.sh Change-Id: I7802d12c34b33be192c83fc46ffed5a6a7385a0a --- camera/metadata/3.3/types.hal | 1 - current.txt | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/camera/metadata/3.3/types.hal b/camera/metadata/3.3/types.hal index 1ed8ed8a0c..ca0c9d619b 100644 --- a/camera/metadata/3.3/types.hal +++ b/camera/metadata/3.3/types.hal @@ -22,7 +22,6 @@ package android.hardware.camera.metadata@3.3; -/* Include definitions from all prior minor HAL metadata revisions */ import android.hardware.camera.metadata@3.2; /** diff --git a/current.txt b/current.txt index 10b9b18e39..ffc851b2cb 100644 --- a/current.txt +++ b/current.txt @@ -390,7 +390,7 @@ cd4330c3196bda1d642a32abfe23a7d64ebfbda721940643af6867af3b3f0aa9 android.hardwar 684702a60deef03a1e8093961dc0a18c555c857ad5a77ba7340b0635ae01eb70 android.hardware.camera.device@3.4::ICameraDeviceSession f8a19622cb0cc890913b1ef3e32b675ffb26089a09e02fef4056ebad324d2b5d android.hardware.camera.device@3.4::types 291638a1b6d4e63283e9e722ab5049d9351717ffa2b66162124f84d1aa7c2835 android.hardware.camera.metadata@3.2::types -a31142da4cc87ad50e4e981d12291d4decbb432fcb00f175f0ca904d0fcdbe5b android.hardware.camera.metadata@3.3::types +23780340c686ee86986aa5a9755c2d8566224fed177bbb22a5ebf06be574b60c android.hardware.camera.metadata@3.3::types da33234403ff5d60f3473711917b9948e6484a4260b5247acdafb111193a9de2 android.hardware.configstore@1.0::ISurfaceFlingerConfigs 21165b8e30c4b2d52980e4728f661420adc16e38bbe73476c06b2085be908f4c android.hardware.gnss@1.0::IGnssCallback d702fb01dc2a0733aa820b7eb65435ee3334f75632ef880bafd2fb8803a20a58 android.hardware.gnss@1.0::IGnssMeasurementCallback From d1ce4e664ad87f44193f8c00177ab7cfba94b9ac Mon Sep 17 00:00:00 2001 From: Eino-Ville Talvala Date: Mon, 11 Mar 2019 14:24:47 -0700 Subject: [PATCH 542/718] Camera: Centralize OWNERS Test: Builds Change-Id: I9b8d1675566db44b959c633c25ceaf61a6dc08db --- camera/common/1.0/default/OWNERS | 8 +------- camera/device/1.0/default/OWNERS | 8 +------- camera/device/3.2/default/OWNERS | 8 +------- camera/device/3.3/default/OWNERS | 8 +------- camera/device/3.4/default/OWNERS | 8 +------- camera/device/3.5/default/OWNERS | 8 +------- camera/provider/2.4/default/OWNERS | 8 +------- camera/provider/2.4/vts/OWNERS | 7 +------ camera/provider/2.5/default/OWNERS | 8 +------- 9 files changed, 9 insertions(+), 62 deletions(-) diff --git a/camera/common/1.0/default/OWNERS b/camera/common/1.0/default/OWNERS index 369b2048cb..f112576ef8 100644 --- a/camera/common/1.0/default/OWNERS +++ b/camera/common/1.0/default/OWNERS @@ -1,7 +1 @@ -cychen@google.com -epeev@google.com -etalvala@google.com -jchowdhary@google.com -shuzhenwang@google.com -yinchiayeh@google.com -zhijunhe@google.com +include platform/frameworks/av/camera:/OWNERS diff --git a/camera/device/1.0/default/OWNERS b/camera/device/1.0/default/OWNERS index 369b2048cb..f48a95c5b3 100644 --- a/camera/device/1.0/default/OWNERS +++ b/camera/device/1.0/default/OWNERS @@ -1,7 +1 @@ -cychen@google.com -epeev@google.com -etalvala@google.com -jchowdhary@google.com -shuzhenwang@google.com -yinchiayeh@google.com -zhijunhe@google.com +include platform/frameworks/av:/camera/OWNERS diff --git a/camera/device/3.2/default/OWNERS b/camera/device/3.2/default/OWNERS index 369b2048cb..f48a95c5b3 100644 --- a/camera/device/3.2/default/OWNERS +++ b/camera/device/3.2/default/OWNERS @@ -1,7 +1 @@ -cychen@google.com -epeev@google.com -etalvala@google.com -jchowdhary@google.com -shuzhenwang@google.com -yinchiayeh@google.com -zhijunhe@google.com +include platform/frameworks/av:/camera/OWNERS diff --git a/camera/device/3.3/default/OWNERS b/camera/device/3.3/default/OWNERS index 369b2048cb..f48a95c5b3 100644 --- a/camera/device/3.3/default/OWNERS +++ b/camera/device/3.3/default/OWNERS @@ -1,7 +1 @@ -cychen@google.com -epeev@google.com -etalvala@google.com -jchowdhary@google.com -shuzhenwang@google.com -yinchiayeh@google.com -zhijunhe@google.com +include platform/frameworks/av:/camera/OWNERS diff --git a/camera/device/3.4/default/OWNERS b/camera/device/3.4/default/OWNERS index 369b2048cb..f48a95c5b3 100644 --- a/camera/device/3.4/default/OWNERS +++ b/camera/device/3.4/default/OWNERS @@ -1,7 +1 @@ -cychen@google.com -epeev@google.com -etalvala@google.com -jchowdhary@google.com -shuzhenwang@google.com -yinchiayeh@google.com -zhijunhe@google.com +include platform/frameworks/av:/camera/OWNERS diff --git a/camera/device/3.5/default/OWNERS b/camera/device/3.5/default/OWNERS index 369b2048cb..f48a95c5b3 100644 --- a/camera/device/3.5/default/OWNERS +++ b/camera/device/3.5/default/OWNERS @@ -1,7 +1 @@ -cychen@google.com -epeev@google.com -etalvala@google.com -jchowdhary@google.com -shuzhenwang@google.com -yinchiayeh@google.com -zhijunhe@google.com +include platform/frameworks/av:/camera/OWNERS diff --git a/camera/provider/2.4/default/OWNERS b/camera/provider/2.4/default/OWNERS index 369b2048cb..f48a95c5b3 100644 --- a/camera/provider/2.4/default/OWNERS +++ b/camera/provider/2.4/default/OWNERS @@ -1,7 +1 @@ -cychen@google.com -epeev@google.com -etalvala@google.com -jchowdhary@google.com -shuzhenwang@google.com -yinchiayeh@google.com -zhijunhe@google.com +include platform/frameworks/av:/camera/OWNERS diff --git a/camera/provider/2.4/vts/OWNERS b/camera/provider/2.4/vts/OWNERS index 003fe71fa8..b8f6b048d2 100644 --- a/camera/provider/2.4/vts/OWNERS +++ b/camera/provider/2.4/vts/OWNERS @@ -1,10 +1,5 @@ # Camera team -cychen@google.com -epeev@google.com -etalvala@google.com -shuzhenwang@google.com -yinchiayeh@google.com -zhijunhe@google.com +include platform/frameworks/av:/camera/OWNERS # VTS team yim@google.com diff --git a/camera/provider/2.5/default/OWNERS b/camera/provider/2.5/default/OWNERS index 369b2048cb..f48a95c5b3 100644 --- a/camera/provider/2.5/default/OWNERS +++ b/camera/provider/2.5/default/OWNERS @@ -1,7 +1 @@ -cychen@google.com -epeev@google.com -etalvala@google.com -jchowdhary@google.com -shuzhenwang@google.com -yinchiayeh@google.com -zhijunhe@google.com +include platform/frameworks/av:/camera/OWNERS From 8804423ca13ab48a9c18129e9d1871498a44b8ad Mon Sep 17 00:00:00 2001 From: Xusong Wang Date: Wed, 13 Mar 2019 16:24:34 -0700 Subject: [PATCH 543/718] Fix condition in mutateOperationOperandTypeSkip for conv ops. The filter tensor is not always operand 1 if there are multiple operations in the model. Test: 1.2 VTS tests with sample driver Change-Id: I8925dfd18072ae5579657e8aa13128e7d9f58324 --- neuralnetworks/1.2/vts/functional/ValidateModel.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp index 3b8e3dd4c2..c2330b581e 100644 --- a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp +++ b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp @@ -388,8 +388,9 @@ static bool mutateOperationOperandTypeSkip(size_t operand, OperandType type, con case OperationType::GROUPED_CONV_2D: case OperationType::DEPTHWISE_CONV_2D: case OperationType::CONV_2D: { - if (operand == 1 && (type == OperandType::TENSOR_QUANT8_ASYMM || - type == OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL)) { + if (operand == operation.inputs[1] && + (type == OperandType::TENSOR_QUANT8_ASYMM || + type == OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL)) { return true; } } break; From f5eca2949b5c57f1bf2c5ac12343d16d43273c9c Mon Sep 17 00:00:00 2001 From: chenpaul Date: Thu, 14 Mar 2019 11:08:03 +0800 Subject: [PATCH 544/718] wifi - Add wlan driver/fw version when device boot up Bug: 127715974 Test: Property with wlan driver/fw version when device boot up Change-Id: Idf1215ceb2c34502ed5eac6c8900350e511732fc --- wifi/1.3/default/wifi_chip.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/wifi/1.3/default/wifi_chip.cpp b/wifi/1.3/default/wifi_chip.cpp index d4c032915d..3697d50b5c 100644 --- a/wifi/1.3/default/wifi_chip.cpp +++ b/wifi/1.3/default/wifi_chip.cpp @@ -1152,6 +1152,16 @@ WifiStatus WifiChip::handleChipConfiguration( // This probably is not a critical failure? LOG(ERROR) << "Failed to register radio mode change callback"; } + // Extract and save the version information into property. + std::pair version_info; + version_info = WifiChip::requestChipDebugInfoInternal(); + if (WifiStatusCode::SUCCESS == version_info.first.code) { + property_set("vendor.wlan.firmware.version", + version_info.second.firmwareDescription.c_str()); + property_set("vendor.wlan.driver.version", + version_info.second.driverDescription.c_str()); + } + return createWifiStatus(WifiStatusCode::SUCCESS); } From eed0040e216d58bdaaa2daaa40eab29b0eabeaa8 Mon Sep 17 00:00:00 2001 From: Emil Jahshan Date: Tue, 11 Dec 2018 15:15:17 +0200 Subject: [PATCH 545/718] Y16 format enablement for external provider added Y16 (depth) support for the external provider. refactored initOutputCharsKeys to support both depth and color metadata according to the connected camera. the VTS changes will be pushed to pie-vts-dev Test: tested on intel depth camera D415 manually in addition to the VTS tests. Change-Id: I358686e7c4330bb180dec4a9cce3bc1cf5475260 Signed-off-by: Emil Jahshan --- .../3.4/default/ExternalCameraDevice.cpp | 241 ++++++++++++------ .../default/ExternalCameraDeviceSession.cpp | 77 +++--- .../3.4/default/ExternalCameraUtils.cpp | 72 ++++-- .../ExternalCameraDeviceSession.h | 6 +- .../ExternalCameraDevice_3_4.h | 22 +- .../ExternalCameraUtils.h | 16 +- .../3.5/default/ExternalCameraDevice.cpp | 2 +- .../ExternalCameraDeviceSession.h | 5 +- 8 files changed, 308 insertions(+), 133 deletions(-) diff --git a/camera/device/3.4/default/ExternalCameraDevice.cpp b/camera/device/3.4/default/ExternalCameraDevice.cpp index 0f236570cd..3f047517dd 100644 --- a/camera/device/3.4/default/ExternalCameraDevice.cpp +++ b/camera/device/3.4/default/ExternalCameraDevice.cpp @@ -38,9 +38,8 @@ namespace { // Other formats to consider in the future: // * V4L2_PIX_FMT_YVU420 (== YV12) // * V4L2_PIX_FMT_YVYU (YVYU: can be converted to YV12 or other YUV420_888 formats) -const std::array kSupportedFourCCs {{ - V4L2_PIX_FMT_MJPEG -}}; // double braces required in C++11 +const std::array kSupportedFourCCs{ + {V4L2_PIX_FMT_MJPEG, V4L2_PIX_FMT_Z16}}; // double braces required in C++11 constexpr int MAX_RETRY = 5; // Allow retry v4l2 open failures a few times. constexpr int OPEN_RETRY_SLEEP_US = 100000; // 100ms * MAX_RETRY = 0.5 seconds @@ -231,6 +230,13 @@ status_t ExternalCameraDevice::initCameraCharacteristics() { mCameraCharacteristics.clear(); return ret; } + + ret = initAvailableCapabilities(&mCameraCharacteristics); + if (ret != OK) { + ALOGE("%s: init available capabilities key failed: errorno %d", __FUNCTION__, ret); + mCameraCharacteristics.clear(); + return ret; + } } return OK; } @@ -244,6 +250,39 @@ do { \ } \ } while (0) +status_t ExternalCameraDevice::initAvailableCapabilities( + ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) { + + if (mSupportedFormats.empty()) { + ALOGE("%s: Supported formats list is empty", __FUNCTION__); + return UNKNOWN_ERROR; + } + + bool hasDepth = false; + bool hasColor = false; + for (const auto& fmt : mSupportedFormats) { + switch (fmt.fourcc) { + case V4L2_PIX_FMT_Z16: hasDepth = true; break; + case V4L2_PIX_FMT_MJPEG: hasColor = true; break; + default: ALOGW("%s: Unsupported format found", __FUNCTION__); + } + } + + std::vector availableCapabilities; + if (hasDepth) { + availableCapabilities.push_back(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT); + } + if (hasColor) { + availableCapabilities.push_back(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE); + } + if(!availableCapabilities.empty()) { + UPDATE(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, availableCapabilities.data(), + availableCapabilities.size()); + } + + return OK; +} + status_t ExternalCameraDevice::initDefaultCharsKeys( ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) { const uint8_t hardware_level = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL; @@ -330,12 +369,6 @@ status_t ExternalCameraDevice::initDefaultCharsKeys( &noiseReductionMode, 1); UPDATE(ANDROID_NOISE_REDUCTION_MODE, &noiseReductionMode, 1); - // android.request - const uint8_t availableCapabilities[] = { - ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE}; - UPDATE(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, availableCapabilities, - ARRAY_SIZE(availableCapabilities)); - const int32_t partialResultCount = 1; UPDATE(ANDROID_REQUEST_PARTIAL_RESULT_COUNT, &partialResultCount, 1); @@ -544,9 +577,11 @@ status_t ExternalCameraDevice::initCameraControlsCharsKeys(int, return OK; } -status_t ExternalCameraDevice::initOutputCharsKeys(int fd, - ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) { - initSupportedFormatsLocked(fd); +template +status_t ExternalCameraDevice::initOutputCharskeysByFormat( + ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata, + uint32_t fourcc, const std::array& halFormats, + int streamConfigTag, int streamConfiguration, int minFrameDuration, int stallDuration) { if (mSupportedFormats.empty()) { ALOGE("%s: Init supported format list failed", __FUNCTION__); return UNKNOWN_ERROR; @@ -555,22 +590,17 @@ status_t ExternalCameraDevice::initOutputCharsKeys(int fd, std::vector streamConfigurations; std::vector minFrameDurations; std::vector stallDurations; - int32_t maxFps = std::numeric_limits::min(); - int32_t minFps = std::numeric_limits::max(); - std::set framerates; - - std::array halFormats{{ - HAL_PIXEL_FORMAT_BLOB, - HAL_PIXEL_FORMAT_YCbCr_420_888, - HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED}}; for (const auto& supportedFormat : mSupportedFormats) { + if (supportedFormat.fourcc != fourcc) { + // Skip 4CCs not meant for the halFormats + continue; + } for (const auto& format : halFormats) { streamConfigurations.push_back(format); streamConfigurations.push_back(supportedFormat.width); streamConfigurations.push_back(supportedFormat.height); - streamConfigurations.push_back( - ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT); + streamConfigurations.push_back(streamConfigTag); } int64_t minFrameDuration = std::numeric_limits::max(); @@ -582,14 +612,6 @@ status_t ExternalCameraDevice::initOutputCharsKeys(int fd, if (frameDuration < minFrameDuration) { minFrameDuration = frameDuration; } - int32_t frameRateInt = static_cast(fr.getDouble()); - if (minFps > frameRateInt) { - minFps = frameRateInt; - } - if (maxFps < frameRateInt) { - maxFps = frameRateInt; - } - framerates.insert(frameRateInt); } for (const auto& format : halFormats) { @@ -613,6 +635,30 @@ status_t ExternalCameraDevice::initOutputCharsKeys(int fd, } } + UPDATE(streamConfiguration, streamConfigurations.data(), streamConfigurations.size()); + + UPDATE(minFrameDuration, minFrameDurations.data(), minFrameDurations.size()); + + UPDATE(stallDuration, stallDurations.data(), stallDurations.size()); + + return true; +} + +bool ExternalCameraDevice::calculateMinFps( + ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) { + std::set framerates; + int32_t minFps = std::numeric_limits::max(); + + for (const auto& supportedFormat : mSupportedFormats) { + for (const auto& fr : supportedFormat.frameRates) { + int32_t frameRateInt = static_cast(fr.getDouble()); + if (minFps > frameRateInt) { + minFps = frameRateInt; + } + framerates.insert(frameRateInt); + } + } + std::vector fpsRanges; // FPS ranges for (const auto& framerate : framerates) { @@ -626,17 +672,60 @@ status_t ExternalCameraDevice::initOutputCharsKeys(int fd, UPDATE(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, fpsRanges.data(), fpsRanges.size()); - UPDATE(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, - streamConfigurations.data(), streamConfigurations.size()); - - UPDATE(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS, - minFrameDurations.data(), minFrameDurations.size()); - - UPDATE(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS, stallDurations.data(), - stallDurations.size()); - UPDATE(ANDROID_SENSOR_INFO_MAX_FRAME_DURATION, &maxFrameDuration, 1); + return true; +} + +status_t ExternalCameraDevice::initOutputCharsKeys( + int fd, ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) { + initSupportedFormatsLocked(fd); + if (mSupportedFormats.empty()) { + ALOGE("%s: Init supported format list failed", __FUNCTION__); + return UNKNOWN_ERROR; + } + + bool hasDepth = false; + bool hasColor = false; + + // For V4L2_PIX_FMT_Z16 + std::array halDepthFormats{{HAL_PIXEL_FORMAT_Y16}}; + // For V4L2_PIX_FMT_MJPEG + std::array halFormats{{HAL_PIXEL_FORMAT_BLOB, HAL_PIXEL_FORMAT_YCbCr_420_888, + HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED}}; + + for (const auto& supportedFormat : mSupportedFormats) { + switch (supportedFormat.fourcc) { + case V4L2_PIX_FMT_Z16: + hasDepth = true; + break; + case V4L2_PIX_FMT_MJPEG: + hasColor = true; + break; + default: + ALOGW("%s: format %c%c%c%c is not supported!", __FUNCTION__, + supportedFormat.fourcc & 0xFF, (supportedFormat.fourcc >> 8) & 0xFF, + (supportedFormat.fourcc >> 16) & 0xFF, (supportedFormat.fourcc >> 24) & 0xFF); + } + } + + if (hasDepth) { + initOutputCharskeysByFormat(metadata, V4L2_PIX_FMT_Z16, halDepthFormats, + ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_OUTPUT, + ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS, + ANDROID_DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS, + ANDROID_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS); + } + if (hasColor) { + initOutputCharskeysByFormat(metadata, V4L2_PIX_FMT_MJPEG, halFormats, + ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT, + ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, + ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS, + ANDROID_SCALER_AVAILABLE_STALL_DURATIONS); + } + + calculateMinFps(metadata); + SupportedV4L2Format maximumFormat {.width = 0, .height = 0}; for (const auto& supportedFormat : mSupportedFormats) { if (supportedFormat.width >= maximumFormat.width && @@ -758,11 +847,12 @@ void ExternalCameraDevice::trimSupportedFormats( sortedFmts = out; } -std::vector -ExternalCameraDevice::getCandidateSupportedFormatsLocked( - int fd, CroppingType cropType, - const std::vector& fpsLimits, - const Size& minStreamSize) { +std::vector ExternalCameraDevice::getCandidateSupportedFormatsLocked( + int fd, CroppingType cropType, + const std::vector& fpsLimits, + const std::vector& depthFpsLimits, + const Size& minStreamSize, + bool depthEnabled) { std::vector outFmts; struct v4l2_fmtdesc fmtdesc { .index = 0, @@ -808,28 +898,10 @@ ExternalCameraDevice::getCandidateSupportedFormatsLocked( .fourcc = fmtdesc.pixelformat }; - double fpsUpperBound = -1.0; - for (const auto& limit : fpsLimits) { - if (cropType == VERTICAL) { - if (format.width <= limit.size.width) { - fpsUpperBound = limit.fpsUpperBound; - break; - } - } else { // HORIZONTAL - if (format.height <= limit.size.height) { - fpsUpperBound = limit.fpsUpperBound; - break; - } - } - - } - if (fpsUpperBound < 0.f) { - continue; - } - - getFrameRateList(fd, fpsUpperBound, &format); - if (!format.frameRates.empty()) { - outFmts.push_back(format); + if (format.fourcc == V4L2_PIX_FMT_Z16 && depthEnabled) { + updateFpsBounds(fd, cropType, depthFpsLimits, format, outFmts); + } else { + updateFpsBounds(fd, cropType, fpsLimits, format, outFmts); } } } @@ -841,12 +913,39 @@ ExternalCameraDevice::getCandidateSupportedFormatsLocked( return outFmts; } -void ExternalCameraDevice::initSupportedFormatsLocked(int fd) { +void ExternalCameraDevice::updateFpsBounds( + int fd, CroppingType cropType, + const std::vector& fpsLimits, SupportedV4L2Format format, + std::vector& outFmts) { + double fpsUpperBound = -1.0; + for (const auto& limit : fpsLimits) { + if (cropType == VERTICAL) { + if (format.width <= limit.size.width) { + fpsUpperBound = limit.fpsUpperBound; + break; + } + } else { // HORIZONTAL + if (format.height <= limit.size.height) { + fpsUpperBound = limit.fpsUpperBound; + break; + } + } + } + if (fpsUpperBound < 0.f) { + return; + } - std::vector horizontalFmts = - getCandidateSupportedFormatsLocked(fd, HORIZONTAL, mCfg.fpsLimits, mCfg.minStreamSize); - std::vector verticalFmts = - getCandidateSupportedFormatsLocked(fd, VERTICAL, mCfg.fpsLimits, mCfg.minStreamSize); + getFrameRateList(fd, fpsUpperBound, &format); + if (!format.frameRates.empty()) { + outFmts.push_back(format); + } +} + +void ExternalCameraDevice::initSupportedFormatsLocked(int fd) { + std::vector horizontalFmts = getCandidateSupportedFormatsLocked( + fd, HORIZONTAL, mCfg.fpsLimits, mCfg.depthFpsLimits, mCfg.minStreamSize, mCfg.depthEnabled); + std::vector verticalFmts = getCandidateSupportedFormatsLocked( + fd, VERTICAL, mCfg.fpsLimits, mCfg.depthFpsLimits, mCfg.minStreamSize, mCfg.depthEnabled); size_t horiSize = horizontalFmts.size(); size_t vertSize = verticalFmts.size(); diff --git a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp index 66b17db955..32da9681bf 100644 --- a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp +++ b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp @@ -1819,7 +1819,7 @@ bool ExternalCameraDeviceSession::OutputThread::threadLoop() { return false; }; - if (req->frameIn->mFourcc != V4L2_PIX_FMT_MJPEG) { + if (req->frameIn->mFourcc != V4L2_PIX_FMT_MJPEG && req->frameIn->mFourcc != V4L2_PIX_FMT_Z16) { return onDeviceError("%s: do not support V4L2 format %c%c%c%c", __FUNCTION__, req->frameIn->mFourcc & 0xFF, (req->frameIn->mFourcc >> 8) & 0xFF, @@ -1844,29 +1844,26 @@ bool ExternalCameraDeviceSession::OutputThread::threadLoop() { } // TODO: in some special case maybe we can decode jpg directly to gralloc output? - ATRACE_BEGIN("MJPGtoI420"); - res = libyuv::MJPGToI420( - inData, inDataSize, - static_cast(mYu12FrameLayout.y), - mYu12FrameLayout.yStride, - static_cast(mYu12FrameLayout.cb), - mYu12FrameLayout.cStride, - static_cast(mYu12FrameLayout.cr), - mYu12FrameLayout.cStride, - mYu12Frame->mWidth, mYu12Frame->mHeight, - mYu12Frame->mWidth, mYu12Frame->mHeight); - ATRACE_END(); + if (req->frameIn->mFourcc == V4L2_PIX_FMT_MJPEG) { + ATRACE_BEGIN("MJPGtoI420"); + int res = libyuv::MJPGToI420( + inData, inDataSize, static_cast(mYu12FrameLayout.y), mYu12FrameLayout.yStride, + static_cast(mYu12FrameLayout.cb), mYu12FrameLayout.cStride, + static_cast(mYu12FrameLayout.cr), mYu12FrameLayout.cStride, + mYu12Frame->mWidth, mYu12Frame->mHeight, mYu12Frame->mWidth, mYu12Frame->mHeight); + ATRACE_END(); - if (res != 0) { - // For some webcam, the first few V4L2 frames might be malformed... - ALOGE("%s: Convert V4L2 frame to YU12 failed! res %d", __FUNCTION__, res); - lk.unlock(); - Status st = parent->processCaptureRequestError(req); - if (st != Status::OK) { - return onDeviceError("%s: failed to process capture request error!", __FUNCTION__); + if (res != 0) { + // For some webcam, the first few V4L2 frames might be malformed... + ALOGE("%s: Convert V4L2 frame to YU12 failed! res %d", __FUNCTION__, res); + lk.unlock(); + Status st = parent->processCaptureRequestError(req); + if (st != Status::OK) { + return onDeviceError("%s: failed to process capture request error!", __FUNCTION__); + } + signalRequestDone(); + return true; } - signalRequestDone(); - return true; } ATRACE_BEGIN("Wait for BufferRequest done"); @@ -1910,6 +1907,16 @@ bool ExternalCameraDeviceSession::OutputThread::threadLoop() { __FUNCTION__, ret); } } break; + case PixelFormat::Y16: { + void* outLayout = sHandleImporter.lock(*(halBuf.bufPtr), halBuf.usage, inDataSize); + + std::memcpy(outLayout, inData, inDataSize); + + int relFence = sHandleImporter.unlock(*(halBuf.bufPtr)); + if (relFence >= 0) { + halBuf.acquireFence = relFence; + } + } break; case PixelFormat::YCBCR_420_888: case PixelFormat::YV12: { IMapper::Rect outRect {0, 0, @@ -2164,7 +2171,8 @@ void ExternalCameraDeviceSession::updateBufferCaches(const hidl_vec } bool ExternalCameraDeviceSession::isSupported(const Stream& stream, - const std::vector& supportedFormats) { + const std::vector& supportedFormats, + const ExternalCameraConfig& devCfg) { int32_t ds = static_cast(stream.dataSpace); PixelFormat fmt = stream.format; uint32_t width = stream.width; @@ -2181,11 +2189,6 @@ bool ExternalCameraDeviceSession::isSupported(const Stream& stream, return false; } - if (ds & Dataspace::DEPTH) { - ALOGI("%s: does not support depth output", __FUNCTION__); - return false; - } - switch (fmt) { case PixelFormat::BLOB: if (ds != static_cast(Dataspace::V0_JFIF)) { @@ -2199,6 +2202,16 @@ bool ExternalCameraDeviceSession::isSupported(const Stream& stream, // TODO: check what dataspace we can support here. // intentional no-ops. break; + case PixelFormat::Y16: + if (!devCfg.depthEnabled) { + ALOGI("%s: Depth is not Enabled", __FUNCTION__); + return false; + } + if (!(ds & Dataspace::DEPTH)) { + ALOGI("%s: Y16 supports only dataSpace DEPTH", __FUNCTION__); + return false; + } + break; default: ALOGI("%s: does not support format %x", __FUNCTION__, fmt); return false; @@ -2544,7 +2557,8 @@ void ExternalCameraDeviceSession::enqueueV4l2Frame(const sp& frame) { Status ExternalCameraDeviceSession::isStreamCombinationSupported( const V3_2::StreamConfiguration& config, - const std::vector& supportedFormats) { + const std::vector& supportedFormats, + const ExternalCameraConfig& devCfg) { if (config.operationMode != StreamConfigurationMode::NORMAL_MODE) { ALOGE("%s: unsupported operation mode: %d", __FUNCTION__, config.operationMode); return Status::ILLEGAL_ARGUMENT; @@ -2559,7 +2573,7 @@ Status ExternalCameraDeviceSession::isStreamCombinationSupported( int numStallStream = 0; for (const auto& stream : config.streams) { // Check if the format/width/height combo is supported - if (!isSupported(stream, supportedFormats)) { + if (!isSupported(stream, supportedFormats, devCfg)) { return Status::ILLEGAL_ARGUMENT; } if (stream.format == PixelFormat::BLOB) { @@ -2590,7 +2604,7 @@ Status ExternalCameraDeviceSession::configureStreams( uint32_t blobBufferSize) { ATRACE_CALL(); - Status status = isStreamCombinationSupported(config, mSupportedFormats); + Status status = isStreamCombinationSupported(config, mSupportedFormats, mCfg); if (status != Status::OK) { return status; } @@ -2744,6 +2758,7 @@ Status ExternalCameraDeviceSession::configureStreams( case PixelFormat::BLOB: case PixelFormat::YCBCR_420_888: case PixelFormat::YV12: // Used by SurfaceTexture + case PixelFormat::Y16: // No override out->streams[i].v3_2.overrideFormat = config.streams[i].format; break; diff --git a/camera/device/3.4/default/ExternalCameraUtils.cpp b/camera/device/3.4/default/ExternalCameraUtils.cpp index 0941052c78..e25deff797 100644 --- a/camera/device/3.4/default/ExternalCameraUtils.cpp +++ b/camera/device/3.4/default/ExternalCameraUtils.cpp @@ -21,7 +21,6 @@ #include #include #include "ExternalCameraUtils.h" -#include "tinyxml2.h" // XML parsing namespace android { namespace hardware { @@ -245,28 +244,28 @@ ExternalCameraConfig ExternalCameraConfig::loadFromCfg(const char* cfgPath) { if (fpsList == nullptr) { ALOGI("%s: no fps list specified", __FUNCTION__); } else { - std::vector limits; - XMLElement *row = fpsList->FirstChildElement("Limit"); - while (row != nullptr) { - FpsLimitation prevLimit {{0, 0}, 1000.0}; - FpsLimitation limit; - limit.size = { - row->UnsignedAttribute("width", /*Default*/0), - row->UnsignedAttribute("height", /*Default*/0)}; - limit.fpsUpperBound = row->DoubleAttribute("fpsBound", /*Default*/1000.0); - if (limit.size.width <= prevLimit.size.width || - limit.size.height <= prevLimit.size.height || - limit.fpsUpperBound >= prevLimit.fpsUpperBound) { - ALOGE("%s: FPS limit list must have increasing size and decreasing fps!" - " Prev %dx%d@%f, Current %dx%d@%f", __FUNCTION__, - prevLimit.size.width, prevLimit.size.height, prevLimit.fpsUpperBound, - limit.size.width, limit.size.height, limit.fpsUpperBound); + if (!updateFpsList(fpsList, ret.fpsLimits)) { + return ret; + } + } + + XMLElement *depth = deviceCfg->FirstChildElement("Depth16Supported"); + if (depth == nullptr) { + ret.depthEnabled = false; + ALOGI("%s: depth output is not enabled", __FUNCTION__); + } else { + ret.depthEnabled = depth->BoolAttribute("enabled", false); + } + + if(ret.depthEnabled) { + XMLElement *depthFpsList = deviceCfg->FirstChildElement("DepthFpsList"); + if (depthFpsList == nullptr) { + ALOGW("%s: no depth fps list specified", __FUNCTION__); + } else { + if(!updateFpsList(depthFpsList, ret.depthFpsLimits)) { return ret; } - limits.push_back(limit); - row = row->NextSiblingElement("Limit"); } - ret.fpsLimits = limits; } XMLElement *minStreamSize = deviceCfg->FirstChildElement("MinimumStreamSize"); @@ -293,15 +292,48 @@ ExternalCameraConfig ExternalCameraConfig::loadFromCfg(const char* cfgPath) { ALOGI("%s: fpsLimitList: %dx%d@%f", __FUNCTION__, limit.size.width, limit.size.height, limit.fpsUpperBound); } + for (const auto& limit : ret.depthFpsLimits) { + ALOGI("%s: depthFpsLimitList: %dx%d@%f", __FUNCTION__, limit.size.width, limit.size.height, + limit.fpsUpperBound); + } ALOGI("%s: minStreamSize: %dx%d" , __FUNCTION__, ret.minStreamSize.width, ret.minStreamSize.height); return ret; } +bool ExternalCameraConfig::updateFpsList(tinyxml2::XMLElement* fpsList, + std::vector& fpsLimits) { + using namespace tinyxml2; + std::vector limits; + XMLElement* row = fpsList->FirstChildElement("Limit"); + while (row != nullptr) { + FpsLimitation prevLimit{{0, 0}, 1000.0}; + FpsLimitation limit; + limit.size = {row->UnsignedAttribute("width", /*Default*/ 0), + row->UnsignedAttribute("height", /*Default*/ 0)}; + limit.fpsUpperBound = row->DoubleAttribute("fpsBound", /*Default*/ 1000.0); + if (limit.size.width <= prevLimit.size.width || + limit.size.height <= prevLimit.size.height || + limit.fpsUpperBound >= prevLimit.fpsUpperBound) { + ALOGE( + "%s: FPS limit list must have increasing size and decreasing fps!" + " Prev %dx%d@%f, Current %dx%d@%f", + __FUNCTION__, prevLimit.size.width, prevLimit.size.height, prevLimit.fpsUpperBound, + limit.size.width, limit.size.height, limit.fpsUpperBound); + return false; + } + limits.push_back(limit); + row = row->NextSiblingElement("Limit"); + } + fpsLimits = limits; + return true; +} + ExternalCameraConfig::ExternalCameraConfig() : maxJpegBufSize(kDefaultJpegBufSize), numVideoBuffers(kDefaultNumVideoBuffer), numStillBuffers(kDefaultNumStillBuffer), + depthEnabled(false), orientation(kDefaultOrientation) { fpsLimits.push_back({/*Size*/{ 640, 480}, /*FPS upper bound*/30.0}); fpsLimits.push_back({/*Size*/{1280, 720}, /*FPS upper bound*/7.5}); diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h index 9cc55cbc07..71b7c17dd6 100644 --- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h +++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h @@ -194,7 +194,8 @@ protected: int v4l2StreamOffLocked(); int setV4l2FpsLocked(double fps); static Status isStreamCombinationSupported(const V3_2::StreamConfiguration& config, - const std::vector& supportedFormats); + const std::vector& supportedFormats, + const ExternalCameraConfig& devCfg); // TODO: change to unique_ptr for better tracking sp dequeueV4l2FrameLocked(/*out*/nsecs_t* shutterTs); // Called with mLock hold @@ -202,7 +203,8 @@ protected: // Check if input Stream is one of supported stream setting on this device static bool isSupported(const Stream& stream, - const std::vector& supportedFormats); + const std::vector& supportedFormats, + const ExternalCameraConfig& cfg); // Validate and import request's output buffers and acquire fence virtual Status importRequestLocked( diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h index 719a3ed848..bd7980780b 100644 --- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h +++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h @@ -104,6 +104,9 @@ protected: // Calls into virtual member function. Do not use it in constructor status_t initCameraCharacteristics(); + // Init available capabilities keys + status_t initAvailableCapabilities( + ::android::hardware::camera::common::V1_0::helper::CameraMetadata*); // Init non-device dependent keys virtual status_t initDefaultCharsKeys( ::android::hardware::camera::common::V1_0::helper::CameraMetadata*); @@ -114,13 +117,30 @@ protected: status_t initOutputCharsKeys(int fd, ::android::hardware::camera::common::V1_0::helper::CameraMetadata*); + // Helper function for initOutputCharskeys + template + status_t initOutputCharskeysByFormat( + ::android::hardware::camera::common::V1_0::helper::CameraMetadata*, + uint32_t fourcc, const std::array& formats, + int scaler_stream_config_tag, + int stream_configuration, int min_frame_duration, int stall_duration); + + bool calculateMinFps(::android::hardware::camera::common::V1_0::helper::CameraMetadata*); + static void getFrameRateList(int fd, double fpsUpperBound, SupportedV4L2Format* format); + static void updateFpsBounds(int fd, CroppingType cropType, + const std::vector& fpsLimits, + SupportedV4L2Format format, + std::vector& outFmts); + // Get candidate supported formats list of input cropping type. static std::vector getCandidateSupportedFormatsLocked( int fd, CroppingType cropType, const std::vector& fpsLimits, - const Size& minStreamSize); + const std::vector& depthFpsLimits, + const Size& minStreamSize, + bool depthEnabled); // Trim supported format list by the cropping type. Also sort output formats by width/height static void trimSupportedFormats(CroppingType cropType, /*inout*/std::vector* pFmts); diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h index 3b1ac96934..341c62218d 100644 --- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h +++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h @@ -17,12 +17,13 @@ #ifndef ANDROID_HARDWARE_CAMERA_DEVICE_V3_4_EXTCAMUTIL_H #define ANDROID_HARDWARE_CAMERA_DEVICE_V3_4_EXTCAMUTIL_H -#include -#include "utils/LightRefBase.h" -#include -#include -#include #include +#include +#include +#include +#include +#include "tinyxml2.h" // XML parsing +#include "utils/LightRefBase.h" using android::hardware::graphics::mapper::V2_0::IMapper; using android::hardware::graphics::mapper::V2_0::YCbCrLayout; @@ -71,11 +72,15 @@ struct ExternalCameraConfig { // Size of v4l2 buffer queue when streaming > kMaxVideoSize uint32_t numStillBuffers; + // Indication that the device connected supports depth output + bool depthEnabled; + struct FpsLimitation { Size size; double fpsUpperBound; }; std::vector fpsLimits; + std::vector depthFpsLimits; // Minimum output stream size Size minStreamSize; @@ -85,6 +90,7 @@ struct ExternalCameraConfig { private: ExternalCameraConfig(); + static bool updateFpsList(tinyxml2::XMLElement* fpsList, std::vector& fpsLimits); }; } // common diff --git a/camera/device/3.5/default/ExternalCameraDevice.cpp b/camera/device/3.5/default/ExternalCameraDevice.cpp index 6a0b51e09f..d0de1a40b1 100644 --- a/camera/device/3.5/default/ExternalCameraDevice.cpp +++ b/camera/device/3.5/default/ExternalCameraDevice.cpp @@ -103,7 +103,7 @@ Return ExternalCameraDevice::isStreamCombinationSupported( } V3_2::StreamConfiguration streamConfig = {streamsV3_2, streams.operationMode}; auto status = ExternalCameraDeviceSession::isStreamCombinationSupported(streamConfig, - mSupportedFormats); + mSupportedFormats, mCfg); _hidl_cb(Status::OK, Status::OK == status); return Void(); } diff --git a/camera/device/3.5/default/include/ext_device_v3_5_impl/ExternalCameraDeviceSession.h b/camera/device/3.5/default/include/ext_device_v3_5_impl/ExternalCameraDeviceSession.h index d2b5e8936f..281f93a13b 100644 --- a/camera/device/3.5/default/include/ext_device_v3_5_impl/ExternalCameraDeviceSession.h +++ b/camera/device/3.5/default/include/ext_device_v3_5_impl/ExternalCameraDeviceSession.h @@ -91,9 +91,10 @@ struct ExternalCameraDeviceSession : public V3_4::implementation::ExternalCamera } static Status isStreamCombinationSupported(const V3_2::StreamConfiguration& config, - const std::vector& supportedFormats) { + const std::vector& supportedFormats, + const ExternalCameraConfig& devCfg) { return V3_4::implementation::ExternalCameraDeviceSession::isStreamCombinationSupported( - config, supportedFormats); + config, supportedFormats, devCfg); } protected: From 965d9dd8216d15479172b901202f3152bc22b13d Mon Sep 17 00:00:00 2001 From: Yin-Chia Yeh Date: Thu, 14 Mar 2019 14:21:01 -0700 Subject: [PATCH 546/718] Camera: cleanup external camera HAL fence FD logic Treat all non-negative integers as valid FD. Test: webcam smoke test Bug: N/A Change-Id: I5fd52c0d195d2d4b63d70d66f10bd2a3ea99985c --- .../device/3.4/default/ExternalCameraDeviceSession.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp index 32da9681bf..dc5579ac67 100644 --- a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp +++ b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp @@ -853,7 +853,7 @@ Status ExternalCameraDeviceSession::processCaptureResult(std::shared_ptrbuffers[i].bufferId; if (req->buffers[i].fenceTimeout) { result.outputBuffers[i].status = BufferStatus::ERROR; - if (req->buffers[i].acquireFence > 0) { + if (req->buffers[i].acquireFence >= 0) { native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0); handle->data[0] = req->buffers[i].acquireFence; result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false); @@ -862,7 +862,7 @@ Status ExternalCameraDeviceSession::processCaptureResult(std::shared_ptrbuffers[i].acquireFence > 0) { + if (req->buffers[i].acquireFence >= 0) { native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0); handle->data[0] = req->buffers[i].acquireFence; result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false); @@ -1778,7 +1778,7 @@ int ExternalCameraDeviceSession::OutputThread::createJpegLocked( /* Unlock the HAL jpeg code buffer */ int relFence = sHandleImporter.unlock(*(halBuf.bufPtr)); - if (relFence > 0) { + if (relFence >= 0) { halBuf.acquireFence = relFence; } @@ -1882,7 +1882,7 @@ bool ExternalCameraDeviceSession::OutputThread::threadLoop() { if (*(halBuf.bufPtr) == nullptr) { ALOGW("%s: buffer for stream %d missing", __FUNCTION__, halBuf.streamId); halBuf.fenceTimeout = true; - } else if (halBuf.acquireFence != -1) { + } else if (halBuf.acquireFence >= 0) { int ret = sync_wait(halBuf.acquireFence, kSyncWaitTimeoutMs); if (ret) { halBuf.fenceTimeout = true; @@ -1957,7 +1957,7 @@ bool ExternalCameraDeviceSession::OutputThread::threadLoop() { return onDeviceError("%s: format coversion failed!", __FUNCTION__); } int relFence = sHandleImporter.unlock(*(halBuf.bufPtr)); - if (relFence > 0) { + if (relFence >= 0) { halBuf.acquireFence = relFence; } } break; From f62374d024322a3fe15124a519743667927f16cd Mon Sep 17 00:00:00 2001 From: Allie Date: Tue, 19 Feb 2019 16:21:51 -0800 Subject: [PATCH 547/718] Initial change to add mock DAB stations (hardcoded for now). Test: VtsHalBroadcastradioV2_0TargetTest Change-Id: Ice8923490728402ed945e8cc0891fd8b2c5bf9dd --- broadcastradio/2.0/default/BroadcastRadio.cpp | 1 + broadcastradio/2.0/default/VirtualRadio.cpp | 11 +++++++++++ broadcastradio/2.0/default/VirtualRadio.h | 3 +++ broadcastradio/2.0/default/service.cpp | 10 ++++++++-- broadcastradio/common/utils2x/Utils.cpp | 14 ++++++++++++++ .../include/broadcastradio-utils-2x/Utils.h | 1 + 6 files changed, 38 insertions(+), 2 deletions(-) diff --git a/broadcastradio/2.0/default/BroadcastRadio.cpp b/broadcastradio/2.0/default/BroadcastRadio.cpp index 28a0dd504a..88a726fefb 100644 --- a/broadcastradio/2.0/default/BroadcastRadio.cpp +++ b/broadcastradio/2.0/default/BroadcastRadio.cpp @@ -49,6 +49,7 @@ static Properties initProperties(const VirtualRadio& virtualRadio) { static_cast(IdentifierType::AMFM_FREQUENCY), static_cast(IdentifierType::RDS_PI), static_cast(IdentifierType::HD_STATION_ID_EXT), + static_cast(IdentifierType::DAB_SID_EXT), }); prop.vendorInfo = hidl_vec({ {"com.google.dummy", "dummy"}, diff --git a/broadcastradio/2.0/default/VirtualRadio.cpp b/broadcastradio/2.0/default/VirtualRadio.cpp index 0b65979b76..c59fd8ff4b 100644 --- a/broadcastradio/2.0/default/VirtualRadio.cpp +++ b/broadcastradio/2.0/default/VirtualRadio.cpp @@ -28,6 +28,7 @@ using std::move; using std::mutex; using std::vector; using utils::make_selector_amfm; +using utils::make_selector_dab; VirtualRadio gAmFmRadio( "AM/FM radio mock", @@ -41,6 +42,16 @@ VirtualRadio gAmFmRadio( {make_selector_amfm(106100), "106 KMEL", "Drake", "Marvins Room"}, }); +// clang-format off +VirtualRadio gDabRadio( + "DAB radio mock", + { + {make_selector_dab(12345, 225648), "BBC Radio 1", "Khalid", "Talk"}, // 12B + {make_selector_dab(22345, 222064), "Classic FM", "Jean Sibelius", "Andante Festivo"}, // 11D + {make_selector_dab(32345, 222064), "Absolute Radio", "Coldplay", "Clocks"}, // 11D + }); +// clang-format on + VirtualRadio::VirtualRadio(const std::string& name, const vector& initialList) : mName(name), mPrograms(initialList) {} diff --git a/broadcastradio/2.0/default/VirtualRadio.h b/broadcastradio/2.0/default/VirtualRadio.h index 9c07816b4b..6fa70c5d16 100644 --- a/broadcastradio/2.0/default/VirtualRadio.h +++ b/broadcastradio/2.0/default/VirtualRadio.h @@ -52,6 +52,9 @@ class VirtualRadio { /** AM/FM virtual radio space. */ extern VirtualRadio gAmFmRadio; +/** DAB virtual radio space. */ +extern VirtualRadio gDabRadio; + } // namespace implementation } // namespace V2_0 } // namespace broadcastradio diff --git a/broadcastradio/2.0/default/service.cpp b/broadcastradio/2.0/default/service.cpp index af96dad47f..349aba28e0 100644 --- a/broadcastradio/2.0/default/service.cpp +++ b/broadcastradio/2.0/default/service.cpp @@ -23,6 +23,7 @@ using android::hardware::configureRpcThreadpool; using android::hardware::joinRpcThreadpool; using android::hardware::broadcastradio::V2_0::implementation::BroadcastRadio; using android::hardware::broadcastradio::V2_0::implementation::gAmFmRadio; +using android::hardware::broadcastradio::V2_0::implementation::gDabRadio; int main() { android::base::SetDefaultTag("BcRadioDef"); @@ -30,8 +31,13 @@ int main() { configureRpcThreadpool(4, true); BroadcastRadio broadcastRadio(gAmFmRadio); - auto status = broadcastRadio.registerAsService(); - CHECK_EQ(status, android::OK) << "Failed to register Broadcast Radio HAL implementation"; + auto amFmStatus = broadcastRadio.registerAsService("amfm"); + CHECK_EQ(amFmStatus, android::OK) + << "Failed to register Broadcast Radio AM/FM HAL implementation"; + + BroadcastRadio dabRadio(gDabRadio); + auto dabStatus = dabRadio.registerAsService("dab"); + CHECK_EQ(dabStatus, android::OK) << "Failed to register Broadcast Radio DAB HAL implementation"; joinRpcThreadpool(); return 1; // joinRpcThreadpool shouldn't exit diff --git a/broadcastradio/common/utils2x/Utils.cpp b/broadcastradio/common/utils2x/Utils.cpp index 789265328f..43f272efdb 100644 --- a/broadcastradio/common/utils2x/Utils.cpp +++ b/broadcastradio/common/utils2x/Utils.cpp @@ -299,6 +299,20 @@ ProgramSelector make_selector_amfm(uint32_t frequency) { return sel; } +ProgramSelector make_selector_dab(uint32_t sidExt, uint32_t ensemble) { + ProgramSelector sel = {}; + // TODO(maryabad): Have a helper function to create the sidExt instead of + // passing the whole identifier here. Something like make_dab_sid_ext. + sel.primaryId = make_identifier(IdentifierType::DAB_SID_EXT, sidExt); + hidl_vec secondaryIds = { + make_identifier(IdentifierType::DAB_ENSEMBLE, ensemble), + // TODO(maryabad): Include frequency here when the helper method to + // translate between ensemble and frequency is implemented. + }; + sel.secondaryIds = secondaryIds; + return sel; +} + Metadata make_metadata(MetadataKey key, int64_t value) { Metadata meta = {}; meta.key = static_cast(key); diff --git a/broadcastradio/common/utils2x/include/broadcastradio-utils-2x/Utils.h b/broadcastradio/common/utils2x/include/broadcastradio-utils-2x/Utils.h index c4aecb218f..f4e0732056 100644 --- a/broadcastradio/common/utils2x/include/broadcastradio-utils-2x/Utils.h +++ b/broadcastradio/common/utils2x/include/broadcastradio-utils-2x/Utils.h @@ -126,6 +126,7 @@ bool isValid(const V2_0::ProgramSelector& sel); V2_0::ProgramIdentifier make_identifier(V2_0::IdentifierType type, uint64_t value); V2_0::ProgramSelector make_selector_amfm(uint32_t frequency); +V2_0::ProgramSelector make_selector_dab(uint32_t sidExt, uint32_t ensemble); V2_0::Metadata make_metadata(V2_0::MetadataKey key, int64_t value); V2_0::Metadata make_metadata(V2_0::MetadataKey key, std::string value); From ffbad18ca07482b826d69f6142982cc6a93a2137 Mon Sep 17 00:00:00 2001 From: Ahmed ElArabawy Date: Tue, 5 Mar 2019 17:38:06 -0800 Subject: [PATCH 548/718] Wifi: Add ether_type to sending offloaded packet This commit adds the ether_type as an argument to the legacy hal function to send an offloaded packet. Bug: 122487582 Test: Manual Test: Make sure ether_type is passed all the way to vendor hal function Change-Id: I5918088000cc455e7f83feddc1090803ccc04c06 --- wifi/1.3/default/wifi_legacy_hal.cpp | 8 ++++---- wifi/1.3/default/wifi_legacy_hal.h | 2 +- wifi/1.3/default/wifi_sta_iface.cpp | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/wifi/1.3/default/wifi_legacy_hal.cpp b/wifi/1.3/default/wifi_legacy_hal.cpp index 5aa98c416e..7f9b63575e 100644 --- a/wifi/1.3/default/wifi_legacy_hal.cpp +++ b/wifi/1.3/default/wifi_legacy_hal.cpp @@ -777,7 +777,7 @@ wifi_error WifiLegacyHal::configureNdOffload(const std::string& iface_name, } wifi_error WifiLegacyHal::startSendingOffloadedPacket( - const std::string& iface_name, uint32_t cmd_id, + const std::string& iface_name, uint32_t cmd_id, uint16_t ether_type, const std::vector& ip_packet_data, const std::array& src_address, const std::array& dst_address, uint32_t period_in_ms) { @@ -787,9 +787,9 @@ wifi_error WifiLegacyHal::startSendingOffloadedPacket( std::vector dst_address_internal( dst_address.data(), dst_address.data() + dst_address.size()); return global_func_table_.wifi_start_sending_offloaded_packet( - cmd_id, getIfaceHandle(iface_name), ip_packet_data_internal.data(), - ip_packet_data_internal.size(), src_address_internal.data(), - dst_address_internal.data(), period_in_ms); + cmd_id, getIfaceHandle(iface_name), ether_type, + ip_packet_data_internal.data(), ip_packet_data_internal.size(), + src_address_internal.data(), dst_address_internal.data(), period_in_ms); } wifi_error WifiLegacyHal::stopSendingOffloadedPacket( diff --git a/wifi/1.3/default/wifi_legacy_hal.h b/wifi/1.3/default/wifi_legacy_hal.h index 70a919f8ce..558103c610 100644 --- a/wifi/1.3/default/wifi_legacy_hal.h +++ b/wifi/1.3/default/wifi_legacy_hal.h @@ -246,7 +246,7 @@ class WifiLegacyHal { fw_roaming_state_t state); wifi_error configureNdOffload(const std::string& iface_name, bool enable); wifi_error startSendingOffloadedPacket( - const std::string& iface_name, uint32_t cmd_id, + const std::string& iface_name, uint32_t cmd_id, uint16_t ether_type, const std::vector& ip_packet_data, const std::array& src_address, const std::array& dst_address, uint32_t period_in_ms); diff --git a/wifi/1.3/default/wifi_sta_iface.cpp b/wifi/1.3/default/wifi_sta_iface.cpp index 17f3e3d9d8..a6539e5d90 100644 --- a/wifi/1.3/default/wifi_sta_iface.cpp +++ b/wifi/1.3/default/wifi_sta_iface.cpp @@ -562,12 +562,12 @@ WifiStatus WifiStaIface::enableNdOffloadInternal(bool enable) { WifiStatus WifiStaIface::startSendingKeepAlivePacketsInternal( uint32_t cmd_id, const std::vector& ip_packet_data, - uint16_t /* ether_type */, const std::array& src_address, + uint16_t ether_type, const std::array& src_address, const std::array& dst_address, uint32_t period_in_ms) { legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startSendingOffloadedPacket( - ifname_, cmd_id, ip_packet_data, src_address, dst_address, - period_in_ms); + ifname_, cmd_id, ether_type, ip_packet_data, src_address, + dst_address, period_in_ms); return createWifiStatusFromLegacyError(legacy_status); } From 86450fa579d2d1073b234b8314a0dc4dff7e2fb4 Mon Sep 17 00:00:00 2001 From: Anil Admal Date: Mon, 11 Mar 2019 15:31:05 -0700 Subject: [PATCH 549/718] Add new GNSS capabilities for year of hardware deprecation (HAL) The following capabilities need to be added to the GNSS HAL interface to enforce support through the CTS/VTS tests. -Add low power mode capability. -Add satellite blacklisting capability. -Add measurement corrections capability and move capabilities in IGnssCallback.hal that are specific to measurement correctons to its own sub-HAL measurement_corrections@1.0. Bug: 128028791 Bug: 127434062 Bug: 128309220 Test: Tested on cuttlefish using default implementation and VTS tests Change-Id: I60dbd2ce3cce3cb871aa5f6b690ef881f8dc5705 --- current.txt | 7 +-- gnss/2.0/IGnssCallback.hal | 39 ++++++++++---- gnss/2.0/default/Gnss.cpp | 5 +- .../default/GnssMeasurementCorrections.cpp | 13 +++++ gnss/2.0/default/GnssMeasurementCorrections.h | 1 + gnss/2.0/types.hal | 2 +- gnss/2.0/vts/functional/gnss_hal_test.cpp | 29 +++++++++++ gnss/2.0/vts/functional/gnss_hal_test.h | 16 ++++++ .../vts/functional/gnss_hal_test_cases.cpp | 52 ++++++++++++++----- gnss/measurement_corrections/1.0/Android.bp | 1 + .../1.0/IMeasurementCorrections.hal | 17 ++++-- .../1.0/IMeasurementCorrectionsCallback.hal | 50 ++++++++++++++++++ 12 files changed, 200 insertions(+), 32 deletions(-) create mode 100644 gnss/measurement_corrections/1.0/IMeasurementCorrectionsCallback.hal diff --git a/current.txt b/current.txt index 75b297d2c7..93638a05c1 100644 --- a/current.txt +++ b/current.txt @@ -465,12 +465,13 @@ f27baaa587bc3dd9b740cb6928ab812b9b7d105b5187663938aee578105f3c39 android.hardwar 2e5ad983734069e84a760004b32da0d09e4170c05380abe27e6eb80e4aa70d5a android.hardware.gnss@2.0::IAGnssCallback 1f4ac068a88a72360280d94a7f6fd7c63813c1eea4891a0eb01394d3e7e775f2 android.hardware.gnss@2.0::IAGnssRil 6e2f9a44375a0ae0b49ca7d711cb88945189d398535078408269e1e85889061d android.hardware.gnss@2.0::IGnss -d815623a6d1ba4abf21248b84eca70a2bfab03058a88b68a29c063ce8aee6b5c android.hardware.gnss@2.0::IGnssCallback +782dfc724272f279985de348c824197357941382f73c0083f0344d8ec594d2a8 android.hardware.gnss@2.0::IGnssCallback ecc966c68bddbd95c8dae782b84204cf01c75734675e8769963f3b5106ec128b android.hardware.gnss@2.0::IGnssConfiguration c67759f5d6387d273b66729180d03690e827f0b6b8d4e13ce2ff42d31b224065 android.hardware.gnss@2.0::IGnssMeasurement 3dd30a3ca77ef5ab109a55ba603ff816ae5019436886093dccf8fd6a068f85f1 android.hardware.gnss@2.0::IGnssMeasurementCallback -9e66234e65bcde75733d75d8b5d5cc094c2a5e14b074a25cd3f9ad141dc56f60 android.hardware.gnss@2.0::types -50623a69a88b1c8a05738e4af7d5f78e905f415ccb0e84c99d0a71ea182e9393 android.hardware.gnss.measurement_corrections@1.0::IMeasurementCorrections +4bcd767dd05304b4722c6521c7ed8d4a05faf6022f228f2c088379c647871f7c android.hardware.gnss@2.0::types +d4cc8d91930d5a1a62deb0d97d398510a115ce3ede2d2978738651b9d01b11c3 android.hardware.gnss.measurement_corrections@1.0::IMeasurementCorrections +3eec9763db9b101644f14175b77c9954047445a468e9c743fd402d472d4aa97e android.hardware.gnss.measurement_corrections@1.0::IMeasurementCorrectionsCallback 6ef12cd95df73f8f80c25eb035d98ca4594f9cee571fdabea838a0b6016dd908 android.hardware.gnss.measurement_corrections@1.0::types 0d278956d7fc6fdf9ca9c42962ff2d73967bbb1c9f0b3e0b58d71b7095c286bc android.hardware.gnss.visibility_control@1.0::IGnssVisibilityControl 0d99e34500cfc2d40b684cb4dea7ebd89d4aff9f5315ed36b33442a7a88c138c android.hardware.gnss.visibility_control@1.0::IGnssVisibilityControlCallback diff --git a/gnss/2.0/IGnssCallback.hal b/gnss/2.0/IGnssCallback.hal index 7924b641bc..4c31cf5208 100644 --- a/gnss/2.0/IGnssCallback.hal +++ b/gnss/2.0/IGnssCallback.hal @@ -21,7 +21,7 @@ import @1.1::IGnssCallback; import GnssLocation; /** - * The interface is required for the HAL to communicate certain information + * This interface is required for the HAL to communicate certain information * like status and location info back to the platform, the platform implements * the interfaces and passes a handle to the HAL. */ @@ -29,17 +29,36 @@ interface IGnssCallback extends @1.1::IGnssCallback { /** Flags for the gnssSetCapabilities callback. */ @export(name="", value_prefix="GPS_CAPABILITY_") - enum Capabilities : @1.0::IGnssCallback.Capabilities { - /** GNSS supports line-of-sight satellite identification measurement Corrections */ - MEASUREMENT_CORRECTIONS_LOS_SATS = 1 << 8, - /** GNSS supports per satellite excess-path-length measurement Corrections */ - MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH = 1 << 9, - /** GNSS supports reflecting planes measurement Corrections */ - MEASUREMENT_CORRECTIONS_REFLECTING_PLANE = 1 << 10 + enum Capabilities : uint32_t { + /** + * GNSS HAL schedules fixes for RECURRENCE_PERIODIC mode. + * If this is not set, then the framework will use 1000ms for + * minInterval and must call start() and stop() to schedule the GNSS. + */ + SCHEDULING = 1 << 0, + /** GNSS supports MS-Based AGNSS mode */ + MSB = 1 << 1, + /** GNSS supports MS-Assisted AGNSS mode */ + MSA = 1 << 2, + /** GNSS supports single-shot fixes */ + SINGLE_SHOT = 1 << 3, + /** GNSS supports on demand time injection */ + ON_DEMAND_TIME = 1 << 4, + /** + * Values for the flags removed from IGnssCallback.hal@1.0 Capabilities + * enum are marked as reserved and not reused here to avoid confusion. + */ + RESERVED_1 = 1 << 5, + RESERVED_2 = 1 << 6, + RESERVED_3 = 1 << 7, + /** GNSS supports low power mode */ + LOW_POWER_MODE = 1 << 8, + /** GNSS supports blacklisting satellites */ + SATELLITE_BLACKLIST = 1 << 9 }; /** - * Callback to inform framework of the GNSS engine's capabilities. + * Callback to inform framework of the GNSS HAL implementation's capabilities. * * @param capabilities Capability parameter is a bit field of the Capabilities enum. */ @@ -75,4 +94,4 @@ interface IGnssCallback extends @1.1::IGnssCallback { * during-call to E911, or up to 5 minutes after end-of-call or text to E911). */ gnssRequestLocationCb_2_0(bool independentFromGnss, bool isUserEmergency); -}; \ No newline at end of file +}; diff --git a/gnss/2.0/default/Gnss.cpp b/gnss/2.0/default/Gnss.cpp index ee6da5374c..1dfdadbffb 100644 --- a/gnss/2.0/default/Gnss.cpp +++ b/gnss/2.0/default/Gnss.cpp @@ -269,8 +269,9 @@ Return Gnss::setCallback_2_0(const sp& callback) { sGnssCallback_2_0 = callback; - uint32_t capabilities = static_cast(V1_0::IGnssCallback::Capabilities::MEASUREMENTS); - auto ret = sGnssCallback_2_0->gnssSetCapabilitesCb(capabilities); + using Capabilities = V2_0::IGnssCallback::Capabilities; + const auto capabilities = Capabilities::LOW_POWER_MODE | Capabilities::SATELLITE_BLACKLIST; + auto ret = sGnssCallback_2_0->gnssSetCapabilitiesCb_2_0(capabilities); if (!ret.isOk()) { ALOGE("%s: Unable to invoke callback", __func__); } diff --git a/gnss/2.0/default/GnssMeasurementCorrections.cpp b/gnss/2.0/default/GnssMeasurementCorrections.cpp index cbf34ba9c3..2bf5601820 100644 --- a/gnss/2.0/default/GnssMeasurementCorrections.cpp +++ b/gnss/2.0/default/GnssMeasurementCorrections.cpp @@ -54,6 +54,19 @@ Return GnssMeasurementCorrections::setCorrections(const MeasurementCorrect return true; } +Return GnssMeasurementCorrections::setCallback( + const sp& callback) { + using Capabilities = V1_0::IMeasurementCorrectionsCallback::Capabilities; + auto ret = + callback->setCapabilitiesCb(Capabilities::LOS_SATS | Capabilities::EXCESS_PATH_LENGTH | + Capabilities::REFLECTING_PLANE); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + return false; + } + return true; +} + } // namespace implementation } // namespace V1_0 } // namespace measurement_corrections diff --git a/gnss/2.0/default/GnssMeasurementCorrections.h b/gnss/2.0/default/GnssMeasurementCorrections.h index f758bc8a08..4339bed55d 100644 --- a/gnss/2.0/default/GnssMeasurementCorrections.h +++ b/gnss/2.0/default/GnssMeasurementCorrections.h @@ -38,6 +38,7 @@ using ::android::hardware::Void; struct GnssMeasurementCorrections : public IMeasurementCorrections { // Methods from V1_0::IMeasurementCorrections follow. Return setCorrections(const MeasurementCorrections& corrections) override; + Return setCallback(const sp& callback) override; }; } // namespace implementation diff --git a/gnss/2.0/types.hal b/gnss/2.0/types.hal index 4abb6048c9..21b64f93d7 100644 --- a/gnss/2.0/types.hal +++ b/gnss/2.0/types.hal @@ -69,7 +69,7 @@ struct GnssLocation { * * This clock information can be obtained from SystemClock.elapsedRealtimeNanos(), when the GNSS * is attached straight to the AP/SOC. When it is attached to a separate module the timestamp - * needs to be estimatedd by syncing the notion of time via PTP or some other mechanism. + * needs to be estimated by syncing the notion of time via PTP or some other mechanism. */ ElapsedRealtime elapsedRealtime; }; \ No newline at end of file diff --git a/gnss/2.0/vts/functional/gnss_hal_test.cpp b/gnss/2.0/vts/functional/gnss_hal_test.cpp index c564f41a03..b2b62fcd29 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test.cpp +++ b/gnss/2.0/vts/functional/gnss_hal_test.cpp @@ -77,6 +77,16 @@ void GnssHalTest::SetUpGnssCallback() { EXPECT_EQ(capabilities_called_count_, 1); EXPECT_EQ(info_called_count_, 1); EXPECT_EQ(name_called_count_, 1); + + // Setup measurement corrections callback. + auto measurementCorrections = gnss_hal_->getExtensionMeasurementCorrections(); + ASSERT_TRUE(measurementCorrections.isOk()); + sp iMeasurementCorrections = measurementCorrections; + if (iMeasurementCorrections != nullptr) { + sp iMeasurementCorrectionsCallback = + new GnssMeasurementCorrectionsCallback(*this); + iMeasurementCorrections->setCallback(iMeasurementCorrectionsCallback); + } } void GnssHalTest::StopAndClearLocations() { @@ -176,6 +186,16 @@ std::cv_status GnssHalTest::wait(int timeout_seconds) { return status; } +std::cv_status GnssHalTest::waitForMeasurementCorrectionsCapabilities(int timeout_seconds) { + std::unique_lock lock(mtx_); + auto status = std::cv_status::no_timeout; + while (measurement_corrections_capabilities_called_count_ == 0) { + status = cv_.wait_for(lock, std::chrono::seconds(timeout_seconds)); + if (status == std::cv_status::timeout) return status; + } + return status; +} + Return GnssHalTest::GnssCallback::gnssSetSystemInfoCb( const IGnssCallback::GnssSystemInfo& info) { ALOGI("Info received, year %d", info.yearOfHw); @@ -243,3 +263,12 @@ Return GnssHalTest::GnssMeasurementCallback::gnssMeasurementCb_2_0( parent_.notify(); return Void(); } + +Return GnssHalTest::GnssMeasurementCorrectionsCallback::setCapabilitiesCb( + uint32_t capabilities) { + ALOGI("GnssMeasurementCorrectionsCallback capabilities received %d", capabilities); + parent_.measurement_corrections_capabilities_called_count_++; + parent_.last_measurement_corrections_capabilities_ = capabilities; + parent_.notify(); + return Void(); +} diff --git a/gnss/2.0/vts/functional/gnss_hal_test.h b/gnss/2.0/vts/functional/gnss_hal_test.h index 31750a6641..7354aeae34 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test.h +++ b/gnss/2.0/vts/functional/gnss_hal_test.h @@ -28,6 +28,7 @@ using android::hardware::Return; using android::hardware::Void; +using android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrectionsCallback; using android::hardware::gnss::V1_0::GnssLocationFlags; using android::hardware::gnss::V2_0::IGnss; using android::hardware::gnss::V2_0::IGnssCallback; @@ -73,6 +74,8 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase { /* Test code calls this function to wait for a callback */ std::cv_status wait(int timeout_seconds); + std::cv_status waitForMeasurementCorrectionsCapabilities(int timeout_seconds); + /* Callback class for data & Event. */ class GnssCallback : public IGnssCallback { public: @@ -136,6 +139,17 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase { Return gnssMeasurementCb_2_0(const IGnssMeasurementCallback_2_0::GnssData&) override; }; + /* Callback class for GnssMeasurementCorrections. */ + class GnssMeasurementCorrectionsCallback : public IMeasurementCorrectionsCallback { + public: + GnssHalTest& parent_; + GnssMeasurementCorrectionsCallback(GnssHalTest& parent) : parent_(parent){}; + virtual ~GnssMeasurementCorrectionsCallback() = default; + + // Methods from V1_0::IMeasurementCorrectionsCallback follow. + Return setCapabilitiesCb(uint32_t capabilities) override; + }; + /* * SetUpGnssCallback: * Set GnssCallback and verify the result. @@ -192,12 +206,14 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase { */ int info_called_count_; int capabilities_called_count_; + int measurement_corrections_capabilities_called_count_; int location_called_count_; int measurement_called_count_; int name_called_count_; IGnssCallback::GnssSystemInfo last_info_; uint32_t last_capabilities_; + uint32_t last_measurement_corrections_capabilities_; GnssLocation_2_0 last_location_; IGnssMeasurementCallback_2_0::GnssData last_measurement_; android::hardware::hidl_string last_name_; diff --git a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp index 67fda89fc0..f3559c5788 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp +++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp @@ -38,6 +38,7 @@ using android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrec using android::hardware::gnss::measurement_corrections::V1_0::MeasurementCorrections; using android::hardware::gnss::V1_0::IGnssNi; using android::hardware::gnss::V2_0::ElapsedRealtimeFlags; +using android::hardware::gnss::V2_0::IGnssCallback; using android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl; /* @@ -50,23 +51,21 @@ TEST_F(GnssHalTest, SetupTeardownCreateCleanup) {} /* * TestGnssMeasurementCallback: - * Gets the GnssMeasurementExtension and verify that it returns an actual extension. + * Gets the GnssMeasurementExtension and verifies that it returns an actual extension. */ TEST_F(GnssHalTest, TestGnssMeasurementCallback) { auto gnssMeasurement_2_0 = gnss_hal_->getExtensionGnssMeasurement_2_0(); auto gnssMeasurement_1_1 = gnss_hal_->getExtensionGnssMeasurement_1_1(); auto gnssMeasurement_1_0 = gnss_hal_->getExtensionGnssMeasurement(); - ASSERT_TRUE(gnssMeasurement_2_0.isOk() || gnssMeasurement_1_1.isOk() || + ASSERT_TRUE(gnssMeasurement_2_0.isOk() && gnssMeasurement_1_1.isOk() && gnssMeasurement_1_0.isOk()); - if (last_capabilities_ & IGnssCallback::Capabilities::MEASUREMENTS) { - sp iGnssMeas_2_0 = gnssMeasurement_2_0; - sp iGnssMeas_1_1 = gnssMeasurement_1_1; - sp iGnssMeas_1_0 = gnssMeasurement_1_0; - // At least one interface is non-null. - int numNonNull = (int)(iGnssMeas_2_0 != nullptr) + (int)(iGnssMeas_1_1 != nullptr) + - (int)(iGnssMeas_1_0 != nullptr); - ASSERT_TRUE(numNonNull >= 1); - } + sp iGnssMeas_2_0 = gnssMeasurement_2_0; + sp iGnssMeas_1_1 = gnssMeasurement_1_1; + sp iGnssMeas_1_0 = gnssMeasurement_1_0; + // At least one interface is non-null. + int numNonNull = (int)(iGnssMeas_2_0 != nullptr) + (int)(iGnssMeas_1_1 != nullptr) + + (int)(iGnssMeas_1_0 != nullptr); + ASSERT_TRUE(numNonNull >= 1); } /* @@ -266,9 +265,31 @@ TEST_F(GnssHalTest, TestGnssVisibilityControlExtension) { EXPECT_TRUE(result); } +/* + * TestGnssMeasurementCorrectionsCapabilities: + * If the GnssMeasurementCorrectionsExtension is not null, verifies that the measurement corrections + * capabilities are reported and the mandatory LOS_SATS or the EXCESS_PATH_LENGTH + * capability flag is set. + */ +TEST_F(GnssHalTest, TestGnssMeasurementCorrectionsCapabilities) { + auto measurementCorrections = gnss_hal_->getExtensionMeasurementCorrections(); + ASSERT_TRUE(measurementCorrections.isOk()); + sp iMeasurementCorrections = measurementCorrections; + if (iMeasurementCorrections == nullptr) { + return; + } + + const int kMeasurementCorrectionsCapabilitiesTimeoutSeconds = 5; + waitForMeasurementCorrectionsCapabilities(kMeasurementCorrectionsCapabilitiesTimeoutSeconds); + ASSERT_TRUE(measurement_corrections_capabilities_called_count_ > 0); + using Capabilities = IMeasurementCorrectionsCallback::Capabilities; + ASSERT_TRUE((last_measurement_corrections_capabilities_ & + (Capabilities::LOS_SATS | Capabilities::EXCESS_PATH_LENGTH)) != 0); +} + /* * TestGnssMeasurementCorrections: - * Gets the GnssMeasurementCorrectionsExtension and verifies that it supports the + * If the GnssMeasurementCorrectionsExtension is not null, verifies that it supports the * gnss.measurement_corrections@1.0::IMeasurementCorrections interface by invoking a method. */ TEST_F(GnssHalTest, TestGnssMeasurementCorrections) { @@ -276,8 +297,13 @@ TEST_F(GnssHalTest, TestGnssMeasurementCorrections) { auto measurementCorrections = gnss_hal_->getExtensionMeasurementCorrections(); ASSERT_TRUE(measurementCorrections.isOk()); sp iMeasurementCorrections = measurementCorrections; - ASSERT_NE(iMeasurementCorrections, nullptr); + if (iMeasurementCorrections == nullptr) { + return; + } + const int kMeasurementCorrectionsCapabilitiesTimeoutSeconds = 5; + waitForMeasurementCorrectionsCapabilities(kMeasurementCorrectionsCapabilitiesTimeoutSeconds); + ASSERT_TRUE(measurement_corrections_capabilities_called_count_ > 0); // Set a mock MeasurementCorrections. auto result = iMeasurementCorrections->setCorrections(Utils::getMockMeasurementCorrections()); ASSERT_TRUE(result.isOk()); diff --git a/gnss/measurement_corrections/1.0/Android.bp b/gnss/measurement_corrections/1.0/Android.bp index 4aac7e04c8..456b55c0ef 100644 --- a/gnss/measurement_corrections/1.0/Android.bp +++ b/gnss/measurement_corrections/1.0/Android.bp @@ -9,6 +9,7 @@ hidl_interface { srcs: [ "types.hal", "IMeasurementCorrections.hal", + "IMeasurementCorrectionsCallback.hal", ], interfaces: [ "android.hardware.gnss@1.0", diff --git a/gnss/measurement_corrections/1.0/IMeasurementCorrections.hal b/gnss/measurement_corrections/1.0/IMeasurementCorrections.hal index 934d10f64a..1fa32f4317 100644 --- a/gnss/measurement_corrections/1.0/IMeasurementCorrections.hal +++ b/gnss/measurement_corrections/1.0/IMeasurementCorrections.hal @@ -16,11 +16,12 @@ package android.hardware.gnss.measurement_corrections@1.0; +import IMeasurementCorrectionsCallback; + /** * Interface for measurement corrections support. */ interface IMeasurementCorrections { - /** * Injects measurement corrections to be used by the HAL to improve the GNSS location output. * @@ -35,5 +36,15 @@ interface IMeasurementCorrections { * * @return success Whether the HAL can accept & use these corrections. */ - setCorrections(MeasurementCorrections corrections) generates (bool success); -}; + setCorrections(MeasurementCorrections corrections) generates (bool success); + + /** + * Opens the interface and provides the callback routines to the implementation of this + * interface. + * + * @param callback Callback interface for IMeasurementCorrections. + * + * @return success Returns true on success. + */ + setCallback(IMeasurementCorrectionsCallback callback) generates (bool success); +}; \ No newline at end of file diff --git a/gnss/measurement_corrections/1.0/IMeasurementCorrectionsCallback.hal b/gnss/measurement_corrections/1.0/IMeasurementCorrectionsCallback.hal new file mode 100644 index 0000000000..91d131192b --- /dev/null +++ b/gnss/measurement_corrections/1.0/IMeasurementCorrectionsCallback.hal @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.gnss.measurement_corrections@1.0; + +/** + * GNSS measurement corrections callback interface. + */ +interface IMeasurementCorrectionsCallback { + + /** + * Flags to indicate supported measurement corrections capabilities + * + * Either the LOS_SATS or the EXCESS_PATH_LENGTH capability must be supported. + */ + enum Capabilities : uint32_t { + /** GNSS supports line-of-sight satellite identification measurement corrections */ + LOS_SATS = 1 << 0, + /** GNSS supports per satellite excess-path-length measurement corrections */ + EXCESS_PATH_LENGTH = 1 << 1, + /** GNSS supports reflecting planes measurement corrections */ + REFLECTING_PLANE = 1 << 2 + }; + + /** + * Callback to inform framework the measurement correction specific capabilities of the GNSS + * HAL implementation. + * + * The GNSS HAL must call this method immediately after the framework opens the measurement + * corrections interface. + * + * @param capabilities Supported measurement corrections capabilities. It is mandatory to + * support either LOS_STATS or EXCESS_PATH_LENGTH capability. + * + */ + setCapabilitiesCb(bitfield capabilities); +}; \ No newline at end of file From d80b5bb7dd1377f54b886a435b0e7f6aad74599e Mon Sep 17 00:00:00 2001 From: Pawin Vongmasa Date: Thu, 7 Mar 2019 04:38:57 -0800 Subject: [PATCH 550/718] Accompany HardwareBuffer with generation number attachBuffer() should take a generation number and requestBuffer() should return a generation number because AHardwareBuffer does not carry the generation number. Test: make cts -j123 && cts-tradefed run cts-dev -m \ CtsMediaTestCases --compatibility:module-arg \ CtsMediaTestCases:include-annotation:\ android.platform.test.annotations.RequiresDevice Bug: 127778192 Change-Id: I201f84cf66f0e19b794a05c5ba88066360a37d96 --- current.txt | 2 +- .../2.0/IGraphicBufferProducer.hal | 21 ++++++++++++++----- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/current.txt b/current.txt index 75b297d2c7..3921eb1528 100644 --- a/current.txt +++ b/current.txt @@ -475,7 +475,7 @@ c67759f5d6387d273b66729180d03690e827f0b6b8d4e13ce2ff42d31b224065 android.hardwar 0d278956d7fc6fdf9ca9c42962ff2d73967bbb1c9f0b3e0b58d71b7095c286bc android.hardware.gnss.visibility_control@1.0::IGnssVisibilityControl 0d99e34500cfc2d40b684cb4dea7ebd89d4aff9f5315ed36b33442a7a88c138c android.hardware.gnss.visibility_control@1.0::IGnssVisibilityControlCallback 6b2d8dfa3db505c34a3a19082d8737c86bd859ec00f0e6c5fd19cce3c1ef95d1 android.hardware.graphics.allocator@3.0::IAllocator -2a81d3132df91614a30ca45dfe088d67ddbb30240ab8c25feb6b8110d7ec3800 android.hardware.graphics.bufferqueue@2.0::IGraphicBufferProducer +eb3bcf4e8afacc72fd09821920f277fbbe8b9837513c1f5549fb42588580cbe4 android.hardware.graphics.bufferqueue@2.0::IGraphicBufferProducer b826892686850a9cf2b60ca5845db7185c2196ea4dd765cd80cd163169678a78 android.hardware.graphics.bufferqueue@2.0::IProducerListener 01c6398c90fc6be0640810e2c5d8a4863b457280132bb3f97dd5682e19632b62 android.hardware.graphics.bufferqueue@2.0::types 7a2d64095252f85781b2d521f4f11d04ce774544feececcec2088c568656e93c android.hardware.graphics.common@1.2::types diff --git a/graphics/bufferqueue/2.0/IGraphicBufferProducer.hal b/graphics/bufferqueue/2.0/IGraphicBufferProducer.hal index 734c0b4310..23b360a535 100644 --- a/graphics/bufferqueue/2.0/IGraphicBufferProducer.hal +++ b/graphics/bufferqueue/2.0/IGraphicBufferProducer.hal @@ -75,12 +75,19 @@ interface IGraphicBufferProducer { * @param slot Slot index. * @return status Status of the call. * @return buffer New buffer associated to the given slot index. + * @return generationNumber Generation number of the buffer. If + * requestBuffer() is called immediately after dequeueBuffer() returns + * with `bufferNeedsReallocation` set to `true`, @p generationNumber must + * match the current generation number of the buffer queue previously + * set by setGenerationNumber(). Otherwise, @p generationNumber may not + * match the current generation number of the buffer queue. */ requestBuffer( int32_t slot ) generates ( Status status, - HardwareBuffer buffer + HardwareBuffer buffer, + uint32_t generationNumber ); /** @@ -212,9 +219,9 @@ interface IGraphicBufferProducer { * parameter. * * @param input See #DequeueBufferInput for more information. - * @param status Status of the call. - * @param slot Slot index. - * @param output See #DequeueBufferOutput for more information. + * @return status Status of the call. + * @return slot Slot index. + * @return output See #DequeueBufferOutput for more information. * * @sa queueBuffer(), requestBuffer(). */ @@ -286,6 +293,9 @@ interface IGraphicBufferProducer { * See dequeueBuffer() for conditions that may cause the call to fail. * * @param buffer Buffer to attach to the buffer queue. + * @param generationNumber Generation number of the buffer. If this does not + * match the current generation number of the buffer queue, the call + * must fail with @p status set to `BAD_VALUE`. * @return status Status of the call. * @return slot Slot index assigned to @p buffer. * @return releaseAllBuffers Whether the caller is expected to release all @@ -294,7 +304,8 @@ interface IGraphicBufferProducer { * @sa dequeueBuffer(). */ attachBuffer( - HardwareBuffer buffer + HardwareBuffer buffer, + uint32_t generationNumber ) generates ( Status status, int32_t slot, From d9dcc1752ee2a1f5142c37d3eb0a09358bbefa64 Mon Sep 17 00:00:00 2001 From: Pawin Vongmasa Date: Sat, 2 Mar 2019 02:31:02 -0800 Subject: [PATCH 551/718] Use @2.0::IGraphicBufferProducer in media.c2 Test: make cts -j123 && cts-tradefed run cts-dev -m \ CtsMediaTestCases --compatibility:module-arg \ CtsMediaTestCases:include-annotation:\ android.platform.test.annotations.RequiresDevice Bug: 33350696 Bug: 112362730 Change-Id: I561b96b4a416a92649bd1de174d55c6317d9b40a --- current.txt | 6 +++--- media/c2/1.0/Android.bp | 3 +++ media/c2/1.0/IComponent.hal | 5 +++-- media/c2/1.0/IInputSink.hal | 2 -- media/c2/1.0/IInputSurface.hal | 2 +- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/current.txt b/current.txt index 3921eb1528..11908aa8ba 100644 --- a/current.txt +++ b/current.txt @@ -493,13 +493,13 @@ dd1ec219f5d2e2b33c6c0bcb92e63bbedb36f7c716413462848f6b6ae74fc864 android.hardwar aee53b2865b4f7939fb3df6fae758d9750c14f93dd454b479fc74aa7978fda4f android.hardware.media.bufferpool@2.0::IConnection 0bf3758eeeb05767830ea87041214be80968c4679fb73577ac5b3091841ee71f android.hardware.media.bufferpool@2.0::IObserver 82255e252ae215382473ad2e5ac7a2814a439a24f0092551aad7a2f89c6e9546 android.hardware.media.bufferpool@2.0::types -277161ea99236a0858e9fcc021c357db03be2de500acf5701d125e73e3e8071a android.hardware.media.c2@1.0::IComponent +7faa207e2507c6a2617e5ec2554b83383ebe392b6e627dddf2e3b0eae5715ba8 android.hardware.media.c2@1.0::IComponent 389d06e4a4ecf60f828a260045b0c327a5ae883ee0856a3c054556dd22b1f450 android.hardware.media.c2@1.0::IComponentInterface 5ee0c02265c5505ade189796bef46697df4e0563e3544bb0c934855b34694b07 android.hardware.media.c2@1.0::IComponentListener 43d70bcdc63b3d042bac3c3297f5d941dfabbd08f3ceb96b6016cc14f6e34ba3 android.hardware.media.c2@1.0::IComponentStore d36f747f9c9a8f2f21db2f8323c2d755dd08b34ce813932d7339979f7d490dab android.hardware.media.c2@1.0::IConfigurable -cd2bd9f424515aeb0c2b91f3bb879797defb5b846b8660784b68d225285bcdff android.hardware.media.c2@1.0::IInputSink -c3dfaa1fcd452c6cfc26d8dcbb67b71b08a1fe6dad5f87427e93d11a95372b05 android.hardware.media.c2@1.0::IInputSurface +21aa259585caaa27b6470ebcd8509aabde0ef5d039160aa6425d589cb787488b android.hardware.media.c2@1.0::IInputSink +b9422a9aca84df1ff9623dc12c0562abce97716e28d63a965f2bfb88f9ad9607 android.hardware.media.c2@1.0::IInputSurface 0a786a19e6753f9774a7ca7781c2a2edfe5c0b5fa112355dfa0e50ebedeb08b9 android.hardware.media.c2@1.0::IInputSurfaceConnection 4cb139f729c29d8d6f4ecdab149c4feb571dad8a06e56cd57fcb52e70208bab4 android.hardware.media.c2@1.0::types 4880af120fc1640225abdc2c60bda6d79617d73484d5124913c7278af3b11e2d android.hardware.neuralnetworks@1.2::IBurstCallback diff --git a/media/c2/1.0/Android.bp b/media/c2/1.0/Android.bp index 6c836af1a4..7307a81e00 100644 --- a/media/c2/1.0/Android.bp +++ b/media/c2/1.0/Android.bp @@ -19,7 +19,10 @@ hidl_interface { ], interfaces: [ "android.hardware.graphics.bufferqueue@1.0", + "android.hardware.graphics.bufferqueue@2.0", "android.hardware.graphics.common@1.0", + "android.hardware.graphics.common@1.1", + "android.hardware.graphics.common@1.2", "android.hardware.media.bufferpool@2.0", "android.hardware.media.omx@1.0", "android.hardware.media@1.0", diff --git a/media/c2/1.0/IComponent.hal b/media/c2/1.0/IComponent.hal index abd14482bd..51ef4e1dd3 100644 --- a/media/c2/1.0/IComponent.hal +++ b/media/c2/1.0/IComponent.hal @@ -17,6 +17,7 @@ package android.hardware.media.c2@1.0; import android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer; +import android.hardware.graphics.bufferqueue@2.0::IGraphicBufferProducer; import android.hardware.media.omx@1.0::IGraphicBufferSource; import IConfigurable; @@ -128,7 +129,7 @@ interface IComponent { */ setOutputSurface( uint64_t blockPoolId, - IGraphicBufferProducer surface + @2.0::IGraphicBufferProducer surface ) generates ( Status status ); @@ -184,7 +185,7 @@ interface IComponent { * null. */ connectToOmxInputSurface( - IGraphicBufferProducer producer, + @1.0::IGraphicBufferProducer producer, IGraphicBufferSource source ) generates ( Status status, diff --git a/media/c2/1.0/IInputSink.hal b/media/c2/1.0/IInputSink.hal index 809c27a7aa..767eb7314c 100644 --- a/media/c2/1.0/IInputSink.hal +++ b/media/c2/1.0/IInputSink.hal @@ -16,8 +16,6 @@ package android.hardware.media.c2@1.0; -import android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer; - import IConfigurable; /** diff --git a/media/c2/1.0/IInputSurface.hal b/media/c2/1.0/IInputSurface.hal index d11ce15e0e..3eee7f19a9 100644 --- a/media/c2/1.0/IInputSurface.hal +++ b/media/c2/1.0/IInputSurface.hal @@ -16,7 +16,7 @@ package android.hardware.media.c2@1.0; -import android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer; +import android.hardware.graphics.bufferqueue@2.0::IGraphicBufferProducer; import IConfigurable; import IInputSink; From aa5d4910752f2981bfd7e061fc37ba53d1618840 Mon Sep 17 00:00:00 2001 From: Aniket Kumar Lata Date: Mon, 18 Mar 2019 14:25:20 -0700 Subject: [PATCH 552/718] audio: Add APTX_TWSP audio format Add APTX_TWSP audio format support. Bug: 111812273 Bug: 128825638 Test: make Change-Id: Id8ba35d8aeea3d0c02be6c63ed3d05b039b0bb4f --- audio/5.0/config/api/current.txt | 1 + audio/5.0/config/audio_policy_configuration.xsd | 1 + audio/common/5.0/types.hal | 1 + current.txt | 2 +- 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/audio/5.0/config/api/current.txt b/audio/5.0/config/api/current.txt index 17f38c1647..c66578183a 100644 --- a/audio/5.0/config/api/current.txt +++ b/audio/5.0/config/api/current.txt @@ -114,6 +114,7 @@ package audio.policy.configuration.V5_0 { enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_APTX; enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_APTX_ADAPTIVE; enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_APTX_HD; + enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_APTX_TWSP; enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_CELT; enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_DOLBY_TRUEHD; enum_constant public static final audio.policy.configuration.V5_0.AudioFormat AUDIO_FORMAT_DSD; diff --git a/audio/5.0/config/audio_policy_configuration.xsd b/audio/5.0/config/audio_policy_configuration.xsd index c580b25dc8..2e1a7223cb 100644 --- a/audio/5.0/config/audio_policy_configuration.xsd +++ b/audio/5.0/config/audio_policy_configuration.xsd @@ -374,6 +374,7 @@ + diff --git a/audio/common/5.0/types.hal b/audio/common/5.0/types.hal index 0a8d75bf78..0cbf35ee54 100644 --- a/audio/common/5.0/types.hal +++ b/audio/common/5.0/types.hal @@ -240,6 +240,7 @@ enum AudioFormat : uint32_t { APTX_ADAPTIVE = 0x27000000UL, LHDC = 0x28000000UL, LHDC_LL = 0x29000000UL, + APTX_TWSP = 0x2A000000UL, /** Deprecated */ MAIN_MASK = 0xFF000000UL, diff --git a/current.txt b/current.txt index 4999cbe554..d552ae0cd1 100644 --- a/current.txt +++ b/current.txt @@ -420,7 +420,7 @@ e05e48c583de14c1e5a6fa9d48ea50244e3e0924b76b342374e7471dc8007ba9 android.hardwar 9471b12b1c255bb530695720bc4174bd74987b75b1f820854af8944bc8c215c9 android.hardware.audio@5.0::IStreamOut 1b0500367ed2b32a841667ac3200edf3d3a164e8004aca445ff1b085ac831e93 android.hardware.audio@5.0::IStreamOutCallback 83e365479cc77d8717c155e1787ee668cd2ae4c557b467cf75b8e7cd53697ad8 android.hardware.audio@5.0::types -c25ae57a9197fdf83aa6f7b31ab1ac4922dea4f19f92cdb1f9013ad49fa56594 android.hardware.audio.common@5.0::types +a0df6961e65444e1ca40a206d7f31304d313e8b7e5b122855e3272ab02720cd4 android.hardware.audio.common@5.0::types f269297866765b95ddd1825676cc8a772f0c7c9863286df596fc302781a42ff5 android.hardware.audio.effect@5.0::IAcousticEchoCancelerEffect fa187b602d8939644ef708ed7627f2e3deac97899a4bda1de07f2ff126abe243 android.hardware.audio.effect@5.0::IAutomaticGainControlEffect e1bf864ccb8458c0da1dcc74a2e748b1dca8ac360df590591cf82d98292d7981 android.hardware.audio.effect@5.0::IBassBoostEffect From 8675df05d7a0e0e286a33bebd49d11ff4db5f32b Mon Sep 17 00:00:00 2001 From: Kai Date: Tue, 12 Mar 2019 17:04:24 -0700 Subject: [PATCH 553/718] Add VHAL params for fuel economy and units Add Units: US_GALLON and IMPERIAL_GALLON Add property: FUEL_CONSUMPTION_UNITES_DISTANCE_OVER_VOLUME Bug: 127734378 Test: make and flash Change-Id: Id11501e6dd6ea43fdbda29cccc10ec954e5c3cc4 --- automotive/vehicle/2.0/types.hal | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal index 3efaaec804..90c1242b01 100644 --- a/automotive/vehicle/2.0/types.hal +++ b/automotive/vehicle/2.0/types.hal @@ -1138,7 +1138,6 @@ enum VehicleProperty : int32_t { * Indicates which units the car is using to display fuel volume to the user. Eg. Liter or * Gallon. * - * Distance units are defined in VehicleUnit. * VehiclePropConfig.configArray is used to indicate the supported fuel volume display units. * Volume units are defined in VehicleUnit. * For example: configArray[0] = 0x41 // LITER @@ -1159,7 +1158,6 @@ enum VehicleProperty : int32_t { * Indicates which units the car is using to display tire pressure to the user. Eg. PSI, Bar or * Kilopascal. * - * Distance units are defined in VehicleUnit. * VehiclePropConfig.configArray is used to indicate the supported pressure display units. * Pressure units are defined in VehicleUnit. * For example: configArray[0] = 0x70 // KILOPASCAL @@ -1181,7 +1179,6 @@ enum VehicleProperty : int32_t { * Indicates which units the car is using to display EV battery information to the user. Eg. * watt-hours(Wh), kilowatt-hours(kWh) or ampere-hours(Ah). * - * Distance units are defined in VehicleUnit. * VehiclePropConfig.configArray is used to indicate the supported electrical energy units. * Electrical energy units are defined in VehicleUnit. * For example: configArray[0] = 0x60 // watt-hours @@ -1197,6 +1194,22 @@ enum VehicleProperty : int32_t { | VehiclePropertyType:INT32 | VehicleArea:GLOBAL), + /** + * Fuel consumption units for display + * + * Indicates type of units the car is using to display fuel consumption information to user + * True indicates units are distance over volume such as MPG. + * False indicates units are volume over distance such as L/100KM. + * + * @change_mode VehiclePropertyChangeMode:ON_CHANGE + * @access VehiclePropertyAccess:READ_WRITE + */ + FUEL_CONSUMPTION_UNITS_DISTANCE_OVER_VOLUME = ( + 0x0604 + | VehiclePropertyGroup:SYSTEM + | VehiclePropertyType:BOOLEAN + | VehicleArea:GLOBAL), + /** * Outside temperature * @@ -2587,7 +2600,11 @@ enum VehicleUnit : int32_t { KELVIN = 0x32, MILLILITER = 0x40, LITER = 0x41, + + /** deprecated. Use US_GALLON instead. */ GALLON = 0x42, + US_GALLON = 0x42, + IMPERIAL_GALLON= 0x43, NANO_SECS = 0x50, SECS = 0x53, YEAR = 0x59, From 6999a0f547365c3eaf51a54f061bd2d79debacf1 Mon Sep 17 00:00:00 2001 From: Yu-Han Yang Date: Thu, 14 Mar 2019 11:08:43 -0700 Subject: [PATCH 554/718] Add IRNSS to GnssConstellationType (HAL) Bug: 119270132 Test: atest VtsHalGnssV2_0TestTarget Change-Id: I3a5da40412a1e5dbe9410573ae2bc263643c585c --- current.txt | 9 +-- gnss/2.0/Android.bp | 1 + gnss/2.0/IGnss.hal | 8 +++ gnss/2.0/IGnssCallback.hal | 23 +++++++ gnss/2.0/IGnssDebug.hal | 66 +++++++++++++++++++ gnss/2.0/IGnssMeasurementCallback.hal | 13 +++- gnss/2.0/default/Gnss.cpp | 5 ++ gnss/2.0/default/Gnss.h | 1 + gnss/2.0/default/GnssMeasurement.cpp | 39 ++++++----- gnss/2.0/types.hal | 26 +++++++- gnss/2.0/vts/functional/gnss_hal_test.cpp | 32 +++++---- gnss/2.0/vts/functional/gnss_hal_test.h | 25 ++++--- .../vts/functional/gnss_hal_test_cases.cpp | 43 +++++++++--- 13 files changed, 232 insertions(+), 59 deletions(-) create mode 100644 gnss/2.0/IGnssDebug.hal diff --git a/current.txt b/current.txt index 0a9c0f96b1..9df0406431 100644 --- a/current.txt +++ b/current.txt @@ -464,12 +464,13 @@ f27baaa587bc3dd9b740cb6928ab812b9b7d105b5187663938aee578105f3c39 android.hardwar 7f460e795f5d1ed5e378935f98c6db4d39497de988aef1b4c2a4a07a6c400392 android.hardware.gnss@2.0::IAGnss 2e5ad983734069e84a760004b32da0d09e4170c05380abe27e6eb80e4aa70d5a android.hardware.gnss@2.0::IAGnssCallback 1f4ac068a88a72360280d94a7f6fd7c63813c1eea4891a0eb01394d3e7e775f2 android.hardware.gnss@2.0::IAGnssRil -6e2f9a44375a0ae0b49ca7d711cb88945189d398535078408269e1e85889061d android.hardware.gnss@2.0::IGnss -782dfc724272f279985de348c824197357941382f73c0083f0344d8ec594d2a8 android.hardware.gnss@2.0::IGnssCallback +63216fcb23eaf4d6f12ea0e99b8bfdb8e4e57c02f215d433cd30943d850f61a7 android.hardware.gnss@2.0::IGnss +b11a5e4a1602d3f408716b6fe2c578a79f060d571aad8e828f9a4426d161fbcf android.hardware.gnss@2.0::IGnssCallback ecc966c68bddbd95c8dae782b84204cf01c75734675e8769963f3b5106ec128b android.hardware.gnss@2.0::IGnssConfiguration +b670bae2ab8517336290532e364502b4db9120340d75474ccc8442b1b15d6ab7 android.hardware.gnss@2.0::IGnssDebug c67759f5d6387d273b66729180d03690e827f0b6b8d4e13ce2ff42d31b224065 android.hardware.gnss@2.0::IGnssMeasurement -3dd30a3ca77ef5ab109a55ba603ff816ae5019436886093dccf8fd6a068f85f1 android.hardware.gnss@2.0::IGnssMeasurementCallback -4bcd767dd05304b4722c6521c7ed8d4a05faf6022f228f2c088379c647871f7c android.hardware.gnss@2.0::types +15e09903748857f4beb5f485784606931fa5a6277cd070baa6d584df485b7948 android.hardware.gnss@2.0::IGnssMeasurementCallback +a49c973f21ddf41bc402de55d7c8dffacf4dce06b0bbca4f5ffd3b09a471317e android.hardware.gnss@2.0::types d4cc8d91930d5a1a62deb0d97d398510a115ce3ede2d2978738651b9d01b11c3 android.hardware.gnss.measurement_corrections@1.0::IMeasurementCorrections 3eec9763db9b101644f14175b77c9954047445a468e9c743fd402d472d4aa97e android.hardware.gnss.measurement_corrections@1.0::IMeasurementCorrectionsCallback 6ef12cd95df73f8f80c25eb035d98ca4594f9cee571fdabea838a0b6016dd908 android.hardware.gnss.measurement_corrections@1.0::types diff --git a/gnss/2.0/Android.bp b/gnss/2.0/Android.bp index c01ec55b99..30dc55de57 100644 --- a/gnss/2.0/Android.bp +++ b/gnss/2.0/Android.bp @@ -14,6 +14,7 @@ hidl_interface { "IGnss.hal", "IGnssCallback.hal", "IGnssConfiguration.hal", + "IGnssDebug.hal", "IGnssMeasurement.hal", "IGnssMeasurementCallback.hal", ], diff --git a/gnss/2.0/IGnss.hal b/gnss/2.0/IGnss.hal index 2c149b7a7b..ba757d73d6 100644 --- a/gnss/2.0/IGnss.hal +++ b/gnss/2.0/IGnss.hal @@ -23,6 +23,7 @@ import @1.1::IGnss; import GnssLocation; import IGnssCallback; import IGnssConfiguration; +import IGnssDebug; import IGnssMeasurement; import IAGnss; import IAGnssRil; @@ -54,6 +55,13 @@ interface IGnss extends @1.1::IGnss { */ getExtensionGnssConfiguration_2_0() generates (IGnssConfiguration gnssConfigurationIface); + /** + * This method returns the IGnssDebug interface. + * + * @return gnssDebugIface Handle to the IGnssDebug interface. + */ + getExtensionGnssDebug_2_0() generates (IGnssDebug gnssDebugIface); + /** * This method returns the IAGnss Interface. * diff --git a/gnss/2.0/IGnssCallback.hal b/gnss/2.0/IGnssCallback.hal index 4c31cf5208..a96fd6ce6e 100644 --- a/gnss/2.0/IGnssCallback.hal +++ b/gnss/2.0/IGnssCallback.hal @@ -19,6 +19,7 @@ package android.hardware.gnss@2.0; import @1.0::IGnssCallback; import @1.1::IGnssCallback; import GnssLocation; +import GnssConstellationType; /** * This interface is required for the HAL to communicate certain information @@ -94,4 +95,26 @@ interface IGnssCallback extends @1.1::IGnssCallback { * during-call to E911, or up to 5 minutes after end-of-call or text to E911). */ gnssRequestLocationCb_2_0(bool independentFromGnss, bool isUserEmergency); + + /** Extends a GnssSvInfo, replacing the GnssConstellationType. */ + struct GnssSvInfo { + /** + * GNSS satellite information for a single satellite and frequency. + * + * In this version of the HAL, the field 'constellation' in the v1_0 struct is deprecated, + * and is no longer used by the framework. The constellation type is instead reported in + * @2.0::IGnssCallback.GnssSvInfo.constellation. + */ + @1.0::IGnssCallback.GnssSvInfo v1_0; + + /** Defines the constellation of the given SV. */ + GnssConstellationType constellation; + }; + + /** + * Callback for the HAL to pass a vector of GnssSvInfo back to the client. + * + * @param svInfo SV status information from HAL. + */ + gnssSvStatusCb_2_0(vec svInfoList); }; diff --git a/gnss/2.0/IGnssDebug.hal b/gnss/2.0/IGnssDebug.hal new file mode 100644 index 0000000000..a3138ba6da --- /dev/null +++ b/gnss/2.0/IGnssDebug.hal @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.gnss@2.0; + +import @1.0::IGnssDebug; + +/** Extended interface for DEBUG support. */ +interface IGnssDebug extends @1.0::IGnssDebug { + + /** Extending SatelliteData, replacing the GnssConstellationType. */ + struct SatelliteData { + /** + * GNSS Satellite info. + * + * In this version of the HAL, the field 'constellation' in the v1_0 struct is deprecated, + * and is no longer used by the framework. The constellation type is instead reported in + * @2.0::IGnssDebug.SatelliteData.constellation. + */ + @1.0::IGnssDebug.SatelliteData v1_0; + + /** Defines the constellation type of the given SV. */ + GnssConstellationType constellation; + }; + + /** + * Provides a set of debug information that is filled by the GNSS chipset when the method + * getDebugData() is invoked. + */ + struct DebugData { + /** Current best known position. */ + @1.0::IGnssDebug.PositionDebug position; + + /** Current best know time estimate. */ + @1.0::IGnssDebug.TimeDebug time; + + /** + * Provides a list of the available satellite data, for all + * satellites and constellations the device can track, + * including GnssConstellationType UNKNOWN. + */ + vec satelliteDataArray; + }; + + /** + * This methods requests position, time and satellite ephemeris debug information from the HAL. + * + * @return ret debugData information from GNSS Hal that contains the current best known + * position, best known time estimate and a complete list of constellations that the device can + * track. + */ + getDebugData_2_0() generates (DebugData debugData); +}; diff --git a/gnss/2.0/IGnssMeasurementCallback.hal b/gnss/2.0/IGnssMeasurementCallback.hal index d9751d35ac..e055f7aa45 100644 --- a/gnss/2.0/IGnssMeasurementCallback.hal +++ b/gnss/2.0/IGnssMeasurementCallback.hal @@ -19,6 +19,7 @@ package android.hardware.gnss@2.0; import @1.0::IGnssMeasurementCallback; import @1.1::IGnssMeasurementCallback; import ElapsedRealtime; +import GnssConstellationType; /** The callback interface to report measurements from the HAL. */ interface IGnssMeasurementCallback extends @1.1::IGnssMeasurementCallback { @@ -365,7 +366,8 @@ interface IGnssMeasurementCallback extends @1.1::IGnssMeasurementCallback { }; /** - * Extends a GNSS Measurement, adding a GnssMeasurementCodeType. + * Extends a GNSS Measurement, adding a GnssMeasurementCodeType, a GnssMeasurementState, and + * replacing the GnssConstellationType. */ struct GnssMeasurement { /** @@ -380,6 +382,10 @@ interface IGnssMeasurementCallback extends @1.1::IGnssMeasurementCallback { * In this version of the HAL, the field 'state' in the v1_1.v1_0 struct is deprecated, and * is no longer used by the framework. The satellite sync state is instead reported in * @2.0::IGnssMeasurementCallback.GnssMeasurement.state. + * + * In this version of the HAL, the field 'constellation' in the v1_1.v1_0 struct is + * deprecated, and is no longer used by the framework. The constellation type is instead + * reported in @2.0::IGnssMeasurementCallback.GnssMeasurement.constellation. */ @1.1::IGnssMeasurementCallback.GnssMeasurement v1_1; @@ -442,6 +448,11 @@ interface IGnssMeasurementCallback extends @1.1::IGnssMeasurementCallback { * This value is mandatory. */ bitfield state; + + /** + * The constellation type of the GNSS measurement. + */ + GnssConstellationType constellation; }; /** diff --git a/gnss/2.0/default/Gnss.cpp b/gnss/2.0/default/Gnss.cpp index 1dfdadbffb..bb89b8b423 100644 --- a/gnss/2.0/default/Gnss.cpp +++ b/gnss/2.0/default/Gnss.cpp @@ -236,6 +236,11 @@ Return> Gnss::getExtensionGnssConfiguration_2_0() { return new GnssConfiguration{}; } +Return> Gnss::getExtensionGnssDebug_2_0() { + // TODO(b/124012850): Implement function. + return sp{}; +} + Return> Gnss::getExtensionAGnss_2_0() { return new AGnss{}; } diff --git a/gnss/2.0/default/Gnss.h b/gnss/2.0/default/Gnss.h index f02ab0a21e..a500128670 100644 --- a/gnss/2.0/default/Gnss.h +++ b/gnss/2.0/default/Gnss.h @@ -83,6 +83,7 @@ struct Gnss : public IGnss { // Methods from V2_0::IGnss follow. Return> getExtensionGnssConfiguration_2_0() override; + Return> getExtensionGnssDebug_2_0() override; Return> getExtensionAGnss_2_0() override; Return> getExtensionAGnssRil_2_0() override; Return> getExtensionGnssMeasurement_2_0() override; diff --git a/gnss/2.0/default/GnssMeasurement.cpp b/gnss/2.0/default/GnssMeasurement.cpp index a62c2dd27e..93de89cdfb 100644 --- a/gnss/2.0/default/GnssMeasurement.cpp +++ b/gnss/2.0/default/GnssMeasurement.cpp @@ -26,7 +26,7 @@ namespace gnss { namespace V2_0 { namespace implementation { -using GnssConstellationType = V1_0::GnssConstellationType; +using GnssConstellationType = V2_0::GnssConstellationType; using GnssMeasurementFlags = V1_0::IGnssMeasurementCallback::GnssMeasurementFlags; using GnssMeasurementState = V2_0::IGnssMeasurementCallback::GnssMeasurementState; @@ -46,6 +46,7 @@ Return GnssMeasurement::setCallba } Return GnssMeasurement::close() { + ALOGD("close"); std::unique_lock lock(mMutex); stop(); sCallback = nullptr; @@ -62,6 +63,7 @@ Return GnssMeasurement::setCallba // Methods from V2_0::IGnssMeasurement follow. Return GnssMeasurement::setCallback_2_0( const sp& callback, bool) { + ALOGD("setCallback_2_0"); std::unique_lock lock(mMutex); sCallback = callback; @@ -75,6 +77,7 @@ Return GnssMeasurement::setCallba } void GnssMeasurement::start() { + ALOGD("start"); mIsActive = true; mThread = std::thread([this]() { while (mIsActive == true) { @@ -87,6 +90,7 @@ void GnssMeasurement::start() { } void GnssMeasurement::stop() { + ALOGD("stop"); mIsActive = false; if (mThread.joinable()) { mThread.join(); @@ -95,26 +99,27 @@ void GnssMeasurement::stop() { GnssData GnssMeasurement::getMockMeasurement() { V1_0::IGnssMeasurementCallback::GnssMeasurement measurement_1_0 = { - .flags = (uint32_t)GnssMeasurementFlags::HAS_CARRIER_FREQUENCY, - .svid = (int16_t)6, - .constellation = GnssConstellationType::GLONASS, - .timeOffsetNs = 0.0, - .receivedSvTimeInNs = 8195997131077, - .receivedSvTimeUncertaintyInNs = 15, - .cN0DbHz = 30.0, - .pseudorangeRateMps = -484.13739013671875, - .pseudorangeRateUncertaintyMps = 1.0379999876022339, - .accumulatedDeltaRangeState = (uint32_t) - V1_0::IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_UNKNOWN, - .accumulatedDeltaRangeM = 0.0, - .accumulatedDeltaRangeUncertaintyM = 0.0, - .carrierFrequencyHz = 1.59975e+09, - .multipathIndicator = - V1_0::IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_UNKNOWN}; + .flags = (uint32_t)GnssMeasurementFlags::HAS_CARRIER_FREQUENCY, + .svid = (int16_t)6, + .constellation = V1_0::GnssConstellationType::UNKNOWN, + .timeOffsetNs = 0.0, + .receivedSvTimeInNs = 8195997131077, + .receivedSvTimeUncertaintyInNs = 15, + .cN0DbHz = 30.0, + .pseudorangeRateMps = -484.13739013671875, + .pseudorangeRateUncertaintyMps = 1.0379999876022339, + .accumulatedDeltaRangeState = (uint32_t)V1_0::IGnssMeasurementCallback:: + GnssAccumulatedDeltaRangeState::ADR_STATE_UNKNOWN, + .accumulatedDeltaRangeM = 0.0, + .accumulatedDeltaRangeUncertaintyM = 0.0, + .carrierFrequencyHz = 1.59975e+09, + .multipathIndicator = + V1_0::IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_UNKNOWN}; V1_1::IGnssMeasurementCallback::GnssMeasurement measurement_1_1 = {.v1_0 = measurement_1_0}; V2_0::IGnssMeasurementCallback::GnssMeasurement measurement_2_0 = { .v1_1 = measurement_1_1, .codeType = "C", + .constellation = GnssConstellationType::GLONASS, .state = GnssMeasurementState::STATE_CODE_LOCK | GnssMeasurementState::STATE_BIT_SYNC | GnssMeasurementState::STATE_SUBFRAME_SYNC | GnssMeasurementState::STATE_TOW_DECODED | diff --git a/gnss/2.0/types.hal b/gnss/2.0/types.hal index 21b64f93d7..3865727e41 100644 --- a/gnss/2.0/types.hal +++ b/gnss/2.0/types.hal @@ -72,4 +72,28 @@ struct GnssLocation { * needs to be estimated by syncing the notion of time via PTP or some other mechanism. */ ElapsedRealtime elapsedRealtime; -}; \ No newline at end of file +}; + +/** + * GNSS constellation type + * + * This is to specify the navigation satellite system, for example, as listed in Section 3.5 in + * RINEX Version 3.04. + */ +enum GnssConstellationType : uint8_t { + UNKNOWN = 0, + /** Global Positioning System. */ + GPS = 1, + /** Satellite-Based Augmentation System. */ + SBAS = 2, + /** Global Navigation Satellite System. */ + GLONASS = 3, + /** Quasi-Zenith Satellite System. */ + QZSS = 4, + /** BeiDou Navigation Satellite System. */ + BEIDOU = 5, + /** Galileo Navigation Satellite System. */ + GALILEO = 6, + /** Indian Regional Navigation Satellite System. */ + IRNSS = 7, +}; diff --git a/gnss/2.0/vts/functional/gnss_hal_test.cpp b/gnss/2.0/vts/functional/gnss_hal_test.cpp index b2b62fcd29..b8c343753f 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test.cpp +++ b/gnss/2.0/vts/functional/gnss_hal_test.cpp @@ -33,7 +33,7 @@ GnssHalTest::GnssHalTest() void GnssHalTest::SetUp() { gnss_hal_ = ::testing::VtsHalHidlTargetTestBase::getService( GnssHidlEnvironment::Instance()->getServiceName()); - list_gnss_sv_status_.clear(); + list_vec_gnss_sv_info_.clear(); ASSERT_NE(gnss_hal_, nullptr); SetUpGnssCallback(); @@ -59,7 +59,7 @@ void GnssHalTest::SetUpGnssCallback() { gnss_cb_ = new GnssCallback(*this); ASSERT_NE(gnss_cb_, nullptr); - auto result = gnss_hal_->setCallback_1_1(gnss_cb_); + auto result = gnss_hal_->setCallback_2_0(gnss_cb_); if (!result.isOk()) { ALOGE("result of failed setCallback %s", result.description().c_str()); } @@ -77,16 +77,6 @@ void GnssHalTest::SetUpGnssCallback() { EXPECT_EQ(capabilities_called_count_, 1); EXPECT_EQ(info_called_count_, 1); EXPECT_EQ(name_called_count_, 1); - - // Setup measurement corrections callback. - auto measurementCorrections = gnss_hal_->getExtensionMeasurementCorrections(); - ASSERT_TRUE(measurementCorrections.isOk()); - sp iMeasurementCorrections = measurementCorrections; - if (iMeasurementCorrections != nullptr) { - sp iMeasurementCorrectionsCallback = - new GnssMeasurementCorrectionsCallback(*this); - iMeasurementCorrections->setCallback(iMeasurementCorrectionsCallback); - } } void GnssHalTest::StopAndClearLocations() { @@ -193,11 +183,12 @@ std::cv_status GnssHalTest::waitForMeasurementCorrectionsCapabilities(int timeou status = cv_.wait_for(lock, std::chrono::seconds(timeout_seconds)); if (status == std::cv_status::timeout) return status; } + notify_count_--; return status; } Return GnssHalTest::GnssCallback::gnssSetSystemInfoCb( - const IGnssCallback::GnssSystemInfo& info) { + const IGnssCallback_1_0::GnssSystemInfo& info) { ALOGI("Info received, year %d", info.yearOfHw); parent_.info_called_count_++; parent_.last_info_ = info; @@ -248,10 +239,9 @@ Return GnssHalTest::GnssCallback::gnssLocationCbImpl(const GnssLocation_2_ return Void(); } -Return GnssHalTest::GnssCallback::gnssSvStatusCb( - const IGnssCallback::GnssSvStatus& svStatus) { - ALOGI("GnssSvStatus received"); - parent_.list_gnss_sv_status_.emplace_back(svStatus); +Return GnssHalTest::GnssCallback::gnssSvStatusCb(const IGnssCallback_1_0::GnssSvStatus&) { + ALOGI("gnssSvStatusCb"); + return Void(); } @@ -272,3 +262,11 @@ Return GnssHalTest::GnssMeasurementCorrectionsCallback::setCapabilitiesCb( parent_.notify(); return Void(); } + +Return GnssHalTest::GnssCallback::gnssSvStatusCb_2_0( + const hidl_vec& svInfoList) { + ALOGI("gnssSvStatusCb_2_0. Size = %d", (int)svInfoList.size()); + parent_.list_vec_gnss_sv_info_.emplace_back(svInfoList); + parent_.notify(); + return Void(); +} diff --git a/gnss/2.0/vts/functional/gnss_hal_test.h b/gnss/2.0/vts/functional/gnss_hal_test.h index 7354aeae34..737815f0c3 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test.h +++ b/gnss/2.0/vts/functional/gnss_hal_test.h @@ -25,17 +25,20 @@ #include #include +using android::hardware::hidl_vec; using android::hardware::Return; using android::hardware::Void; using android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrectionsCallback; using android::hardware::gnss::V1_0::GnssLocationFlags; using android::hardware::gnss::V2_0::IGnss; -using android::hardware::gnss::V2_0::IGnssCallback; using GnssLocation_1_0 = android::hardware::gnss::V1_0::GnssLocation; using GnssLocation_2_0 = android::hardware::gnss::V2_0::GnssLocation; +using IGnssCallback_1_0 = android::hardware::gnss::V1_0::IGnssCallback; +using IGnssCallback_2_0 = android::hardware::gnss::V2_0::IGnssCallback; + using IGnssMeasurementCallback_1_0 = android::hardware::gnss::V1_0::IGnssMeasurementCallback; using IGnssMeasurementCallback_1_1 = android::hardware::gnss::V1_1::IGnssMeasurementCallback; using IGnssMeasurementCallback_2_0 = android::hardware::gnss::V2_0::IGnssMeasurementCallback; @@ -77,8 +80,8 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase { std::cv_status waitForMeasurementCorrectionsCapabilities(int timeout_seconds); /* Callback class for data & Event. */ - class GnssCallback : public IGnssCallback { - public: + class GnssCallback : public IGnssCallback_2_0 { + public: GnssHalTest& parent_; GnssCallback(GnssHalTest& parent) : parent_(parent){}; @@ -86,7 +89,7 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase { virtual ~GnssCallback() = default; // Dummy callback handlers - Return gnssStatusCb(const IGnssCallback::GnssStatusValue /* status */) override { + Return gnssStatusCb(const IGnssCallback_1_0::GnssStatusValue /* status */) override { return Void(); } Return gnssNmeaCb(int64_t /* timestamp */, @@ -103,8 +106,8 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase { Return gnssNameCb(const android::hardware::hidl_string& name) override; Return gnssLocationCb(const GnssLocation_1_0& location) override; Return gnssSetCapabilitesCb(uint32_t capabilities) override; - Return gnssSetSystemInfoCb(const IGnssCallback::GnssSystemInfo& info) override; - Return gnssSvStatusCb(const IGnssCallback::GnssSvStatus& svStatus) override; + Return gnssSetSystemInfoCb(const IGnssCallback_1_0::GnssSystemInfo& info) override; + Return gnssSvStatusCb(const IGnssCallback_1_0::GnssSvStatus& svStatus) override; // New in v2.0 Return gnssLocationCb_2_0(const GnssLocation_2_0& location) override; @@ -113,6 +116,8 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase { return Void(); } Return gnssSetCapabilitiesCb_2_0(uint32_t capabilities) override; + Return gnssSvStatusCb_2_0( + const hidl_vec& svInfoList) override; private: Return gnssLocationCbImpl(const GnssLocation_2_0& location); @@ -198,7 +203,7 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase { void SetPositionMode(const int min_interval_msec, const bool low_power_mode); sp gnss_hal_; // GNSS HAL to call into - sp gnss_cb_; // Primary callback interface + sp gnss_cb_; // Primary callback interface // TODO: make these variables thread-safe. /* Count of calls to set the following items, and the latest item (used by @@ -211,16 +216,16 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase { int measurement_called_count_; int name_called_count_; - IGnssCallback::GnssSystemInfo last_info_; + IGnssCallback_1_0::GnssSystemInfo last_info_; uint32_t last_capabilities_; uint32_t last_measurement_corrections_capabilities_; GnssLocation_2_0 last_location_; IGnssMeasurementCallback_2_0::GnssData last_measurement_; android::hardware::hidl_string last_name_; - list list_gnss_sv_status_; + list> list_vec_gnss_sv_info_; - private: + private: std::mutex mtx_; std::condition_variable cv_; int notify_count_; diff --git a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp index f3559c5788..230c9799f1 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp +++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp @@ -38,6 +38,7 @@ using android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrec using android::hardware::gnss::measurement_corrections::V1_0::MeasurementCorrections; using android::hardware::gnss::V1_0::IGnssNi; using android::hardware::gnss::V2_0::ElapsedRealtimeFlags; +using android::hardware::gnss::V2_0::GnssConstellationType; using android::hardware::gnss::V2_0::IGnssCallback; using android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl; @@ -163,10 +164,13 @@ TEST_F(GnssHalTest, TestAGnssRil_UpdateNetworkState_2_0) { } /* - * TestGnssMeasurementCodeType: - * Sets a GnssMeasurementCallback, waits for a measurement, and verifies the codeType is valid. + * TestGnssMeasurementFields: + * Sets a GnssMeasurementCallback, waits for a measurement, and verifies + * 1. codeType is valid, + * 2. constellation is valid. + * 3. state is valid. */ -TEST_F(GnssHalTest, TestGnssMeasurementCodeType) { +TEST_F(GnssHalTest, TestGnssMeasurementFields) { const int kFirstGnssMeasurementTimeoutSeconds = 10; auto gnssMeasurement = gnss_hal_->getExtensionGnssMeasurement_2_0(); @@ -189,7 +193,23 @@ TEST_F(GnssHalTest, TestGnssMeasurementCodeType) { EXPECT_EQ(measurement_called_count_, 1); ASSERT_TRUE(last_measurement_.measurements.size() > 0); for (auto measurement : last_measurement_.measurements) { + // Verify CodeType is valid. ASSERT_NE(measurement.codeType, ""); + + // Verify ConstellationType is valid. + ASSERT_TRUE(static_cast(measurement.constellation) >= + static_cast(GnssConstellationType::UNKNOWN) && + static_cast(measurement.constellation) <= + static_cast(GnssConstellationType::IRNSS)); + + // Verify State is valid. + ASSERT_TRUE( + static_cast(measurement.state) >= + static_cast(IGnssMeasurementCallback_2_0::GnssMeasurementState:: + STATE_UNKNOWN) && + static_cast(measurement.state) <= + static_cast(IGnssMeasurementCallback_2_0::GnssMeasurementState:: + STATE_2ND_CODE_LOCK)); } iGnssMeasurement->close(); @@ -272,6 +292,7 @@ TEST_F(GnssHalTest, TestGnssVisibilityControlExtension) { * capability flag is set. */ TEST_F(GnssHalTest, TestGnssMeasurementCorrectionsCapabilities) { + // Setup measurement corrections callback. auto measurementCorrections = gnss_hal_->getExtensionMeasurementCorrections(); ASSERT_TRUE(measurementCorrections.isOk()); sp iMeasurementCorrections = measurementCorrections; @@ -279,6 +300,10 @@ TEST_F(GnssHalTest, TestGnssMeasurementCorrectionsCapabilities) { return; } + sp iMeasurementCorrectionsCallback = + new GnssMeasurementCorrectionsCallback(*this); + iMeasurementCorrections->setCallback(iMeasurementCorrectionsCallback); + const int kMeasurementCorrectionsCapabilitiesTimeoutSeconds = 5; waitForMeasurementCorrectionsCapabilities(kMeasurementCorrectionsCapabilitiesTimeoutSeconds); ASSERT_TRUE(measurement_corrections_capabilities_called_count_ > 0); @@ -337,9 +362,9 @@ TEST_F(GnssHalTest, TestGnssDataElapsedRealtimeFlags) { wait(kFirstGnssMeasurementTimeoutSeconds); EXPECT_EQ(measurement_called_count_, 1); - ASSERT_TRUE((int)last_measurement_.elapsedRealtime.flags >= 0 && - (int)last_measurement_.elapsedRealtime.flags <= - (int)ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS); + ASSERT_TRUE((int)last_measurement_.elapsedRealtime.flags <= + (int)(ElapsedRealtimeFlags::HAS_TIMESTAMP_NS | + ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS)); // We expect a non-zero timestamp when set. if (last_measurement_.elapsedRealtime.flags & ElapsedRealtimeFlags::HAS_TIMESTAMP_NS) { @@ -352,9 +377,9 @@ TEST_F(GnssHalTest, TestGnssDataElapsedRealtimeFlags) { TEST_F(GnssHalTest, TestGnssLocationElapsedRealtime) { StartAndCheckFirstLocation(); - ASSERT_TRUE((int)last_location_.elapsedRealtime.flags >= 0 && - (int)last_location_.elapsedRealtime.flags <= - (int)ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS); + ASSERT_TRUE((int)last_location_.elapsedRealtime.flags <= + (int)(ElapsedRealtimeFlags::HAS_TIMESTAMP_NS | + ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS)); // We expect a non-zero timestamp when set. if (last_location_.elapsedRealtime.flags & ElapsedRealtimeFlags::HAS_TIMESTAMP_NS) { From c7a8b863cd9684c1221eb7edcf979fd5ed81944d Mon Sep 17 00:00:00 2001 From: Janis Danisevskis Date: Thu, 14 Mar 2019 15:35:48 -0700 Subject: [PATCH 555/718] Keymaster support: Verbose vendor errors Added function for verbosely logging Keymaster vendor errors. Bug: 123562864 Test: atest android.keystore.cts Change-Id: Ida093941d3b76b3d2e953439229081345909c16b --- keymaster/4.0/support/Keymaster.cpp | 13 +++++++++++++ .../4.0/support/include/keymasterV4_0/Keymaster.h | 6 ++++++ 2 files changed, 19 insertions(+) diff --git a/keymaster/4.0/support/Keymaster.cpp b/keymaster/4.0/support/Keymaster.cpp index 9325cc0699..e8db0744e1 100644 --- a/keymaster/4.0/support/Keymaster.cpp +++ b/keymaster/4.0/support/Keymaster.cpp @@ -106,6 +106,19 @@ std::vector> enumerateDevices( return result; } +void Keymaster::logIfKeymasterVendorError(ErrorCode ec) const { + static constexpr int32_t k_keymaster_vendor_error_code_range_max = -10000; + if (static_cast(ec) <= k_keymaster_vendor_error_code_range_max) { + const auto& versionInfo = halVersion(); + LOG(ERROR) << "Keymaster reported error: " << static_cast(ec) << "\n" + << "NOTE: This is an error in the vendor specific error range.\n" + << " Refer to the vendor of the implementation for details.\n" + << " Implementation name: " << versionInfo.keymasterName << "\n" + << " Vendor name: " << versionInfo.authorName << "\n" + << " MajorVersion: " << versionInfo.majorVersion; + } +} + Keymaster::KeymasterSet Keymaster::enumerateAvailableDevices() { auto serviceManager = IServiceManager::getService(); CHECK(serviceManager) << "Could not retrieve ServiceManager"; diff --git a/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h b/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h index 458053a4ea..43a34b055b 100644 --- a/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h +++ b/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h @@ -64,6 +64,12 @@ class Keymaster : public IKeymasterDevice { const hidl_string& descriptor() const { return descriptor_; } const hidl_string& instanceName() const { return instanceName_; } + /** + * If ec is in the vendor error code range (<-10000), logs the fact to logcat. + * There are no side effects otherwise. + */ + void logIfKeymasterVendorError(ErrorCode ec) const; + /** * Returns all available Keymaster3 and Keymaster4 instances, in order of most secure to least * secure (as defined by VersionResult::operator<). From 992cdabf3a4116b56e62f9ea6e7e1aa98131ea0a Mon Sep 17 00:00:00 2001 From: Anil Admal Date: Wed, 13 Mar 2019 17:08:48 -0700 Subject: [PATCH 556/718] Update GNSS Batching to use new GnssLocation with elapsed realtime (HAL) The ElapsedRealTime field was added to the GnssLocation in gnss@2.0 HAL to additionally report elapsed time since boot. The IGnssBatchingCallback.hal@1.0 must be extended to use this new version of GnssLocation so that the location reported in gnssLocationBatchCb() method includes the ElapsedRealTime field. Fixes: 128034260 Test: Tested the new GNSS Batching extension using default implementation, VTS test, and cuttlefish. Change-Id: I326655130782a04fbe168d4582462a123edd9ac2 --- current.txt | 4 +- gnss/2.0/Android.bp | 2 + gnss/2.0/IGnss.hal | 8 +++ gnss/2.0/IGnssBatching.hal | 51 ++++++++++++++ gnss/2.0/IGnssBatchingCallback.hal | 36 ++++++++++ gnss/2.0/default/Android.bp | 1 + gnss/2.0/default/Gnss.cpp | 5 ++ gnss/2.0/default/Gnss.h | 1 + gnss/2.0/default/GnssBatching.cpp | 70 +++++++++++++++++++ gnss/2.0/default/GnssBatching.h | 57 +++++++++++++++ gnss/2.0/default/GnssConfiguration.cpp | 15 ++-- gnss/2.0/vts/functional/gnss_hal_test.cpp | 2 + .../vts/functional/gnss_hal_test_cases.cpp | 23 ++++++ 13 files changed, 264 insertions(+), 11 deletions(-) create mode 100644 gnss/2.0/IGnssBatching.hal create mode 100644 gnss/2.0/IGnssBatchingCallback.hal create mode 100644 gnss/2.0/default/GnssBatching.cpp create mode 100644 gnss/2.0/default/GnssBatching.h diff --git a/current.txt b/current.txt index 0c501400aa..2456032128 100644 --- a/current.txt +++ b/current.txt @@ -464,7 +464,9 @@ f27baaa587bc3dd9b740cb6928ab812b9b7d105b5187663938aee578105f3c39 android.hardwar 7f460e795f5d1ed5e378935f98c6db4d39497de988aef1b4c2a4a07a6c400392 android.hardware.gnss@2.0::IAGnss 2e5ad983734069e84a760004b32da0d09e4170c05380abe27e6eb80e4aa70d5a android.hardware.gnss@2.0::IAGnssCallback 1f4ac068a88a72360280d94a7f6fd7c63813c1eea4891a0eb01394d3e7e775f2 android.hardware.gnss@2.0::IAGnssRil -63216fcb23eaf4d6f12ea0e99b8bfdb8e4e57c02f215d433cd30943d850f61a7 android.hardware.gnss@2.0::IGnss +4deafcdcffa2d002119e7f58810b767a84666e76475aae68e757ec2845d9756d android.hardware.gnss@2.0::IGnss +db6bdf6dfc5edf6c85d2944976db899227abb51079c893874353c322342c50b6 android.hardware.gnss@2.0::IGnssBatching +1f89392f1ebb693d8fa6f50324b1635fc79fab246d31900e63998e1b0e17511c android.hardware.gnss@2.0::IGnssBatchingCallback b11a5e4a1602d3f408716b6fe2c578a79f060d571aad8e828f9a4426d161fbcf android.hardware.gnss@2.0::IGnssCallback ecc966c68bddbd95c8dae782b84204cf01c75734675e8769963f3b5106ec128b android.hardware.gnss@2.0::IGnssConfiguration b670bae2ab8517336290532e364502b4db9120340d75474ccc8442b1b15d6ab7 android.hardware.gnss@2.0::IGnssDebug diff --git a/gnss/2.0/Android.bp b/gnss/2.0/Android.bp index 30dc55de57..6cfd3462f2 100644 --- a/gnss/2.0/Android.bp +++ b/gnss/2.0/Android.bp @@ -12,6 +12,8 @@ hidl_interface { "IAGnssCallback.hal", "IAGnssRil.hal", "IGnss.hal", + "IGnssBatching.hal", + "IGnssBatchingCallback.hal", "IGnssCallback.hal", "IGnssConfiguration.hal", "IGnssDebug.hal", diff --git a/gnss/2.0/IGnss.hal b/gnss/2.0/IGnss.hal index ba757d73d6..f19f8d0566 100644 --- a/gnss/2.0/IGnss.hal +++ b/gnss/2.0/IGnss.hal @@ -27,6 +27,7 @@ import IGnssDebug; import IGnssMeasurement; import IAGnss; import IAGnssRil; +import IGnssBatching; /** * Represents the standard GNSS (Global Navigation Satellite System) interface. @@ -104,6 +105,13 @@ interface IGnss extends @1.1::IGnss { */ getExtensionVisibilityControl() generates (IGnssVisibilityControl visibilityControlIface); + /** + * This method returns the IGnssBatching interface. + * + * @return batchingIface Handle to the IGnssBatching interface. + */ + getExtensionGnssBatching_2_0() generates (IGnssBatching batchingIface); + /** * Injects current location from the best available location provider. * diff --git a/gnss/2.0/IGnssBatching.hal b/gnss/2.0/IGnssBatching.hal new file mode 100644 index 0000000000..961fa69548 --- /dev/null +++ b/gnss/2.0/IGnssBatching.hal @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.gnss@2.0; + +import @1.0::IGnssBatching; +import IGnssBatchingCallback; + +/** + * Extended interface for GNSS Batching support. + * + * If this interface is supported, this batching request must be able to run in + * parallel with, or without, non-batched location requested by the + * IGnss start() & stop() - i.e. both requests must be handled independently, + * and not interfere with each other. + * + * For example, if a 1Hz continuous output is underway on the IGnssCallback, + * due to an IGnss start() operation, + * and then a IGnssBatching start() is called for a location every 10 + * seconds, the newly added batching request must not disrupt the 1Hz + * continuous location output on the IGnssCallback. + * + * As with GNSS Location outputs, source of location must be GNSS satellite + * measurements, optionally using interial and baro sensors to improve + * relative motion filtering. No additional absolute positioning information, + * such as WiFi derived location, may be mixed with the GNSS information. + */ +interface IGnssBatching extends @1.0::IGnssBatching { + /** + * Opens the interface and provides the callback routines + * to the implementation of this interface. + * + * @param callback Callback interface for IGnssBatching. + * + * @return success Returns true on success. + */ + init_2_0(IGnssBatchingCallback callback) generates (bool success); +}; \ No newline at end of file diff --git a/gnss/2.0/IGnssBatchingCallback.hal b/gnss/2.0/IGnssBatchingCallback.hal new file mode 100644 index 0000000000..4f8b4ecbba --- /dev/null +++ b/gnss/2.0/IGnssBatchingCallback.hal @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.gnss@2.0; + +/** The callback interface to report measurements from the HAL. */ +interface IGnssBatchingCallback { + /** + * Called when a batch of locations is output, by various means, including + * a flush request, as well as the buffer becoming full (if appropriate option + * is set.) + * + * All locations returned by this callback must be cleared from the hardware + * buffer, such the sequential calls of this callback do not return any + * redundant locations. (Same lat/lon, at a new time, is acceptable.) + * + * The GnssLocation struct in gnss@2.0 is extended to include elapsed realtime + * information. + * + * @param locations GNSS Location information from HAL. + */ + gnssLocationBatchCb(vec locations); +}; diff --git a/gnss/2.0/default/Android.bp b/gnss/2.0/default/Android.bp index 64187e24d9..0fcd76495c 100644 --- a/gnss/2.0/default/Android.bp +++ b/gnss/2.0/default/Android.bp @@ -25,6 +25,7 @@ cc_binary { "AGnss.cpp", "AGnssRil.cpp", "Gnss.cpp", + "GnssBatching.cpp", "GnssMeasurement.cpp", "GnssMeasurementCorrections.cpp", "GnssVisibilityControl.cpp", diff --git a/gnss/2.0/default/Gnss.cpp b/gnss/2.0/default/Gnss.cpp index bb89b8b423..75c2385169 100644 --- a/gnss/2.0/default/Gnss.cpp +++ b/gnss/2.0/default/Gnss.cpp @@ -23,6 +23,7 @@ #include "AGnss.h" #include "AGnssRil.h" +#include "GnssBatching.h" #include "GnssConfiguration.h" #include "GnssMeasurement.h" #include "GnssMeasurementCorrections.h" @@ -265,6 +266,10 @@ Return> Gnss::getExtensionV return new GnssVisibilityControl(); } +Return> Gnss::getExtensionGnssBatching_2_0() { + return new GnssBatching(); +} + Return Gnss::setCallback_2_0(const sp& callback) { ALOGD("Gnss::setCallback_2_0"); if (callback == nullptr) { diff --git a/gnss/2.0/default/Gnss.h b/gnss/2.0/default/Gnss.h index a500128670..72f77976e5 100644 --- a/gnss/2.0/default/Gnss.h +++ b/gnss/2.0/default/Gnss.h @@ -92,6 +92,7 @@ struct Gnss : public IGnss { getExtensionMeasurementCorrections() override; Return> getExtensionVisibilityControl() override; + Return> getExtensionGnssBatching_2_0() override; Return injectBestLocation_2_0(const V2_0::GnssLocation& location) override; private: diff --git a/gnss/2.0/default/GnssBatching.cpp b/gnss/2.0/default/GnssBatching.cpp new file mode 100644 index 0000000000..d56cdfb33f --- /dev/null +++ b/gnss/2.0/default/GnssBatching.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "GnssBatching" + +#include "GnssBatching.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +sp GnssBatching::sCallback = nullptr; + +// Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow. +Return GnssBatching::init(const sp&) { + // TODO implement + return bool{}; +} + +Return GnssBatching::getBatchSize() { + // TODO implement + return uint16_t{}; +} + +Return GnssBatching::start(const V1_0::IGnssBatching::Options&) { + // TODO implement + return bool{}; +} + +Return GnssBatching::flush() { + // TODO implement + return Void(); +} + +Return GnssBatching::stop() { + // TODO implement + return bool{}; +} + +Return GnssBatching::cleanup() { + // TODO implement + return Void(); +} + +// Methods from V2_0::IGnssBatching follow. +Return GnssBatching::init_2_0(const sp& callback) { + sCallback = callback; + return true; +} + +} // namespace implementation +} // namespace V2_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/gnss/2.0/default/GnssBatching.h b/gnss/2.0/default/GnssBatching.h new file mode 100644 index 0000000000..62ac580897 --- /dev/null +++ b/gnss/2.0/default/GnssBatching.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2019 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. + */ + +#pragma once + +#include +#include +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +using ::android::sp; +using ::android::hardware::hidl_array; +using ::android::hardware::hidl_memory; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; + +struct GnssBatching : public IGnssBatching { + // Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow. + Return init(const sp& callback) override; + Return getBatchSize() override; + Return start(const V1_0::IGnssBatching::Options& options) override; + Return flush() override; + Return stop() override; + Return cleanup() override; + + // Methods from V2_0::IGnssBatching follow. + Return init_2_0(const sp& callback) override; + + private: + static sp sCallback; +}; + +} // namespace implementation +} // namespace V2_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/gnss/2.0/default/GnssConfiguration.cpp b/gnss/2.0/default/GnssConfiguration.cpp index 4389dd28f3..6bf1712aff 100644 --- a/gnss/2.0/default/GnssConfiguration.cpp +++ b/gnss/2.0/default/GnssConfiguration.cpp @@ -33,13 +33,11 @@ Return GnssConfiguration::setSuplEs(bool enable) { } Return GnssConfiguration::setSuplVersion(uint32_t) { - // TODO implement - return bool{}; + return true; } Return GnssConfiguration::setSuplMode(hidl_bitfield) { - // TODO implement - return bool{}; + return true; } Return GnssConfiguration::setGpsLock(hidl_bitfield gpsLock) { @@ -49,18 +47,15 @@ Return GnssConfiguration::setGpsLock(hidl_bitfield gpsLock) { } Return GnssConfiguration::setLppProfile(hidl_bitfield) { - // TODO implement - return bool{}; + return true; } Return GnssConfiguration::setGlonassPositioningProtocol(hidl_bitfield) { - // TODO implement - return bool{}; + return true; } Return GnssConfiguration::setEmergencySuplPdn(bool) { - // TODO implement - return bool{}; + return true; } // Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow. diff --git a/gnss/2.0/vts/functional/gnss_hal_test.cpp b/gnss/2.0/vts/functional/gnss_hal_test.cpp index b8c343753f..da6092bb4b 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test.cpp +++ b/gnss/2.0/vts/functional/gnss_hal_test.cpp @@ -26,6 +26,7 @@ using ::android::hardware::gnss::common::Utils; GnssHalTest::GnssHalTest() : info_called_count_(0), capabilities_called_count_(0), + measurement_corrections_capabilities_called_count_(0), location_called_count_(0), name_called_count_(0), notify_count_(0) {} @@ -43,6 +44,7 @@ void GnssHalTest::TearDown() { // Reset counters info_called_count_ = 0; capabilities_called_count_ = 0; + measurement_corrections_capabilities_called_count_ = 0; location_called_count_ = 0; name_called_count_ = 0; measurement_called_count_ = 0; diff --git a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp index 230c9799f1..0682f84d5f 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp +++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp @@ -32,6 +32,8 @@ using IAGnssRil_2_0 = android::hardware::gnss::V2_0::IAGnssRil; using IAGnss_2_0 = android::hardware::gnss::V2_0::IAGnss; using IAGnss_1_0 = android::hardware::gnss::V1_0::IAGnss; using IAGnssCallback_2_0 = android::hardware::gnss::V2_0::IAGnssCallback; +using IGnssBatching_V1_0 = android::hardware::gnss::V1_0::IGnssBatching; +using IGnssBatching_V2_0 = android::hardware::gnss::V2_0::IGnssBatching; using android::hardware::gnss::common::Utils; using android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections; @@ -326,6 +328,10 @@ TEST_F(GnssHalTest, TestGnssMeasurementCorrections) { return; } + sp iMeasurementCorrectionsCallback = + new GnssMeasurementCorrectionsCallback(*this); + iMeasurementCorrections->setCallback(iMeasurementCorrectionsCallback); + const int kMeasurementCorrectionsCapabilitiesTimeoutSeconds = 5; waitForMeasurementCorrectionsCapabilities(kMeasurementCorrectionsCapabilitiesTimeoutSeconds); ASSERT_TRUE(measurement_corrections_capabilities_called_count_ > 0); @@ -395,3 +401,20 @@ TEST_F(GnssHalTest, TestInjectBestLocation_2_0) { gnss_hal_->injectBestLocation_2_0(last_location_); StopAndClearLocations(); } + +/* + * TestGnssBatchingExtension: + * Gets the GnssBatchingExtension and verifies that it supports either the @1.0::IGnssBatching + * or @2.0::IGnssBatching extension. + */ +TEST_F(GnssHalTest, TestGnssBatchingExtension) { + auto gnssBatching_V2_0 = gnss_hal_->getExtensionGnssBatching_2_0(); + ASSERT_TRUE(gnssBatching_V2_0.isOk()); + + auto gnssBatching_V1_0 = gnss_hal_->getExtensionGnssBatching(); + ASSERT_TRUE(gnssBatching_V1_0.isOk()); + + sp iGnssBatching_V1_0 = gnssBatching_V1_0; + sp iGnssBatching_V2_0 = gnssBatching_V2_0; + ASSERT_TRUE(iGnssBatching_V1_0 != nullptr || iGnssBatching_V2_0 != nullptr); +} From 872ace84c6364318adb3099f4b775d2b6cf909a2 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Tue, 19 Mar 2019 18:21:24 -0700 Subject: [PATCH 557/718] audio HAL: restore HOTWORD audio source HOTWORD audio source was removed from HAL V4.0 by mistake. Bug: 129001649 Test: make Change-Id: I664eb6ca2a6c30bc6f48a752cb7300aac6c4294b --- audio/common/5.0/types.hal | 1 + current.txt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/audio/common/5.0/types.hal b/audio/common/5.0/types.hal index 0cbf35ee54..e1279ee64a 100644 --- a/audio/common/5.0/types.hal +++ b/audio/common/5.0/types.hal @@ -146,6 +146,7 @@ enum AudioSource : int32_t { */ ECHO_REFERENCE = 1997, FM_TUNER = 1998, + HOTWORD = 1999, }; typedef int32_t AudioSession; diff --git a/current.txt b/current.txt index 0c501400aa..1dea8dde05 100644 --- a/current.txt +++ b/current.txt @@ -420,7 +420,7 @@ e05e48c583de14c1e5a6fa9d48ea50244e3e0924b76b342374e7471dc8007ba9 android.hardwar 9471b12b1c255bb530695720bc4174bd74987b75b1f820854af8944bc8c215c9 android.hardware.audio@5.0::IStreamOut 1b0500367ed2b32a841667ac3200edf3d3a164e8004aca445ff1b085ac831e93 android.hardware.audio@5.0::IStreamOutCallback 83e365479cc77d8717c155e1787ee668cd2ae4c557b467cf75b8e7cd53697ad8 android.hardware.audio@5.0::types -a0df6961e65444e1ca40a206d7f31304d313e8b7e5b122855e3272ab02720cd4 android.hardware.audio.common@5.0::types +07d17800b298331e90d4ea5d8ba19a1ae3fe9c1dbff08d9f75fd3ade09496d67 android.hardware.audio.common@5.0::types f269297866765b95ddd1825676cc8a772f0c7c9863286df596fc302781a42ff5 android.hardware.audio.effect@5.0::IAcousticEchoCancelerEffect fa187b602d8939644ef708ed7627f2e3deac97899a4bda1de07f2ff126abe243 android.hardware.audio.effect@5.0::IAutomaticGainControlEffect e1bf864ccb8458c0da1dcc74a2e748b1dca8ac360df590591cf82d98292d7981 android.hardware.audio.effect@5.0::IBassBoostEffect From b3721a68f273c305ea8e151cd3a8c192605370fc Mon Sep 17 00:00:00 2001 From: Donghui Han Date: Thu, 21 Mar 2019 17:42:42 +0000 Subject: [PATCH 558/718] Revert "Update GNSS Batching to use new GnssLocation with elapsed realtime (HAL)" This reverts commit 992cdabf3a4116b56e62f9ea6e7e1aa98131ea0a. Reason for revert: Change-Id: I0215f172f2d37654937ca72522e110a33c2f63c7 --- current.txt | 4 +- gnss/2.0/Android.bp | 2 - gnss/2.0/IGnss.hal | 8 --- gnss/2.0/IGnssBatching.hal | 51 -------------- gnss/2.0/IGnssBatchingCallback.hal | 36 ---------- gnss/2.0/default/Android.bp | 1 - gnss/2.0/default/Gnss.cpp | 5 -- gnss/2.0/default/Gnss.h | 1 - gnss/2.0/default/GnssBatching.cpp | 70 ------------------- gnss/2.0/default/GnssBatching.h | 57 --------------- gnss/2.0/default/GnssConfiguration.cpp | 15 ++-- gnss/2.0/vts/functional/gnss_hal_test.cpp | 2 - .../vts/functional/gnss_hal_test_cases.cpp | 23 ------ 13 files changed, 11 insertions(+), 264 deletions(-) delete mode 100644 gnss/2.0/IGnssBatching.hal delete mode 100644 gnss/2.0/IGnssBatchingCallback.hal delete mode 100644 gnss/2.0/default/GnssBatching.cpp delete mode 100644 gnss/2.0/default/GnssBatching.h diff --git a/current.txt b/current.txt index 2456032128..0c501400aa 100644 --- a/current.txt +++ b/current.txt @@ -464,9 +464,7 @@ f27baaa587bc3dd9b740cb6928ab812b9b7d105b5187663938aee578105f3c39 android.hardwar 7f460e795f5d1ed5e378935f98c6db4d39497de988aef1b4c2a4a07a6c400392 android.hardware.gnss@2.0::IAGnss 2e5ad983734069e84a760004b32da0d09e4170c05380abe27e6eb80e4aa70d5a android.hardware.gnss@2.0::IAGnssCallback 1f4ac068a88a72360280d94a7f6fd7c63813c1eea4891a0eb01394d3e7e775f2 android.hardware.gnss@2.0::IAGnssRil -4deafcdcffa2d002119e7f58810b767a84666e76475aae68e757ec2845d9756d android.hardware.gnss@2.0::IGnss -db6bdf6dfc5edf6c85d2944976db899227abb51079c893874353c322342c50b6 android.hardware.gnss@2.0::IGnssBatching -1f89392f1ebb693d8fa6f50324b1635fc79fab246d31900e63998e1b0e17511c android.hardware.gnss@2.0::IGnssBatchingCallback +63216fcb23eaf4d6f12ea0e99b8bfdb8e4e57c02f215d433cd30943d850f61a7 android.hardware.gnss@2.0::IGnss b11a5e4a1602d3f408716b6fe2c578a79f060d571aad8e828f9a4426d161fbcf android.hardware.gnss@2.0::IGnssCallback ecc966c68bddbd95c8dae782b84204cf01c75734675e8769963f3b5106ec128b android.hardware.gnss@2.0::IGnssConfiguration b670bae2ab8517336290532e364502b4db9120340d75474ccc8442b1b15d6ab7 android.hardware.gnss@2.0::IGnssDebug diff --git a/gnss/2.0/Android.bp b/gnss/2.0/Android.bp index 6cfd3462f2..30dc55de57 100644 --- a/gnss/2.0/Android.bp +++ b/gnss/2.0/Android.bp @@ -12,8 +12,6 @@ hidl_interface { "IAGnssCallback.hal", "IAGnssRil.hal", "IGnss.hal", - "IGnssBatching.hal", - "IGnssBatchingCallback.hal", "IGnssCallback.hal", "IGnssConfiguration.hal", "IGnssDebug.hal", diff --git a/gnss/2.0/IGnss.hal b/gnss/2.0/IGnss.hal index f19f8d0566..ba757d73d6 100644 --- a/gnss/2.0/IGnss.hal +++ b/gnss/2.0/IGnss.hal @@ -27,7 +27,6 @@ import IGnssDebug; import IGnssMeasurement; import IAGnss; import IAGnssRil; -import IGnssBatching; /** * Represents the standard GNSS (Global Navigation Satellite System) interface. @@ -105,13 +104,6 @@ interface IGnss extends @1.1::IGnss { */ getExtensionVisibilityControl() generates (IGnssVisibilityControl visibilityControlIface); - /** - * This method returns the IGnssBatching interface. - * - * @return batchingIface Handle to the IGnssBatching interface. - */ - getExtensionGnssBatching_2_0() generates (IGnssBatching batchingIface); - /** * Injects current location from the best available location provider. * diff --git a/gnss/2.0/IGnssBatching.hal b/gnss/2.0/IGnssBatching.hal deleted file mode 100644 index 961fa69548..0000000000 --- a/gnss/2.0/IGnssBatching.hal +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.hardware.gnss@2.0; - -import @1.0::IGnssBatching; -import IGnssBatchingCallback; - -/** - * Extended interface for GNSS Batching support. - * - * If this interface is supported, this batching request must be able to run in - * parallel with, or without, non-batched location requested by the - * IGnss start() & stop() - i.e. both requests must be handled independently, - * and not interfere with each other. - * - * For example, if a 1Hz continuous output is underway on the IGnssCallback, - * due to an IGnss start() operation, - * and then a IGnssBatching start() is called for a location every 10 - * seconds, the newly added batching request must not disrupt the 1Hz - * continuous location output on the IGnssCallback. - * - * As with GNSS Location outputs, source of location must be GNSS satellite - * measurements, optionally using interial and baro sensors to improve - * relative motion filtering. No additional absolute positioning information, - * such as WiFi derived location, may be mixed with the GNSS information. - */ -interface IGnssBatching extends @1.0::IGnssBatching { - /** - * Opens the interface and provides the callback routines - * to the implementation of this interface. - * - * @param callback Callback interface for IGnssBatching. - * - * @return success Returns true on success. - */ - init_2_0(IGnssBatchingCallback callback) generates (bool success); -}; \ No newline at end of file diff --git a/gnss/2.0/IGnssBatchingCallback.hal b/gnss/2.0/IGnssBatchingCallback.hal deleted file mode 100644 index 4f8b4ecbba..0000000000 --- a/gnss/2.0/IGnssBatchingCallback.hal +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.hardware.gnss@2.0; - -/** The callback interface to report measurements from the HAL. */ -interface IGnssBatchingCallback { - /** - * Called when a batch of locations is output, by various means, including - * a flush request, as well as the buffer becoming full (if appropriate option - * is set.) - * - * All locations returned by this callback must be cleared from the hardware - * buffer, such the sequential calls of this callback do not return any - * redundant locations. (Same lat/lon, at a new time, is acceptable.) - * - * The GnssLocation struct in gnss@2.0 is extended to include elapsed realtime - * information. - * - * @param locations GNSS Location information from HAL. - */ - gnssLocationBatchCb(vec locations); -}; diff --git a/gnss/2.0/default/Android.bp b/gnss/2.0/default/Android.bp index 0fcd76495c..64187e24d9 100644 --- a/gnss/2.0/default/Android.bp +++ b/gnss/2.0/default/Android.bp @@ -25,7 +25,6 @@ cc_binary { "AGnss.cpp", "AGnssRil.cpp", "Gnss.cpp", - "GnssBatching.cpp", "GnssMeasurement.cpp", "GnssMeasurementCorrections.cpp", "GnssVisibilityControl.cpp", diff --git a/gnss/2.0/default/Gnss.cpp b/gnss/2.0/default/Gnss.cpp index 75c2385169..bb89b8b423 100644 --- a/gnss/2.0/default/Gnss.cpp +++ b/gnss/2.0/default/Gnss.cpp @@ -23,7 +23,6 @@ #include "AGnss.h" #include "AGnssRil.h" -#include "GnssBatching.h" #include "GnssConfiguration.h" #include "GnssMeasurement.h" #include "GnssMeasurementCorrections.h" @@ -266,10 +265,6 @@ Return> Gnss::getExtensionV return new GnssVisibilityControl(); } -Return> Gnss::getExtensionGnssBatching_2_0() { - return new GnssBatching(); -} - Return Gnss::setCallback_2_0(const sp& callback) { ALOGD("Gnss::setCallback_2_0"); if (callback == nullptr) { diff --git a/gnss/2.0/default/Gnss.h b/gnss/2.0/default/Gnss.h index 72f77976e5..a500128670 100644 --- a/gnss/2.0/default/Gnss.h +++ b/gnss/2.0/default/Gnss.h @@ -92,7 +92,6 @@ struct Gnss : public IGnss { getExtensionMeasurementCorrections() override; Return> getExtensionVisibilityControl() override; - Return> getExtensionGnssBatching_2_0() override; Return injectBestLocation_2_0(const V2_0::GnssLocation& location) override; private: diff --git a/gnss/2.0/default/GnssBatching.cpp b/gnss/2.0/default/GnssBatching.cpp deleted file mode 100644 index d56cdfb33f..0000000000 --- a/gnss/2.0/default/GnssBatching.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "GnssBatching" - -#include "GnssBatching.h" - -namespace android { -namespace hardware { -namespace gnss { -namespace V2_0 { -namespace implementation { - -sp GnssBatching::sCallback = nullptr; - -// Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow. -Return GnssBatching::init(const sp&) { - // TODO implement - return bool{}; -} - -Return GnssBatching::getBatchSize() { - // TODO implement - return uint16_t{}; -} - -Return GnssBatching::start(const V1_0::IGnssBatching::Options&) { - // TODO implement - return bool{}; -} - -Return GnssBatching::flush() { - // TODO implement - return Void(); -} - -Return GnssBatching::stop() { - // TODO implement - return bool{}; -} - -Return GnssBatching::cleanup() { - // TODO implement - return Void(); -} - -// Methods from V2_0::IGnssBatching follow. -Return GnssBatching::init_2_0(const sp& callback) { - sCallback = callback; - return true; -} - -} // namespace implementation -} // namespace V2_0 -} // namespace gnss -} // namespace hardware -} // namespace android diff --git a/gnss/2.0/default/GnssBatching.h b/gnss/2.0/default/GnssBatching.h deleted file mode 100644 index 62ac580897..0000000000 --- a/gnss/2.0/default/GnssBatching.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2019 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. - */ - -#pragma once - -#include -#include -#include - -namespace android { -namespace hardware { -namespace gnss { -namespace V2_0 { -namespace implementation { - -using ::android::sp; -using ::android::hardware::hidl_array; -using ::android::hardware::hidl_memory; -using ::android::hardware::hidl_string; -using ::android::hardware::hidl_vec; -using ::android::hardware::Return; -using ::android::hardware::Void; - -struct GnssBatching : public IGnssBatching { - // Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow. - Return init(const sp& callback) override; - Return getBatchSize() override; - Return start(const V1_0::IGnssBatching::Options& options) override; - Return flush() override; - Return stop() override; - Return cleanup() override; - - // Methods from V2_0::IGnssBatching follow. - Return init_2_0(const sp& callback) override; - - private: - static sp sCallback; -}; - -} // namespace implementation -} // namespace V2_0 -} // namespace gnss -} // namespace hardware -} // namespace android diff --git a/gnss/2.0/default/GnssConfiguration.cpp b/gnss/2.0/default/GnssConfiguration.cpp index 6bf1712aff..4389dd28f3 100644 --- a/gnss/2.0/default/GnssConfiguration.cpp +++ b/gnss/2.0/default/GnssConfiguration.cpp @@ -33,11 +33,13 @@ Return GnssConfiguration::setSuplEs(bool enable) { } Return GnssConfiguration::setSuplVersion(uint32_t) { - return true; + // TODO implement + return bool{}; } Return GnssConfiguration::setSuplMode(hidl_bitfield) { - return true; + // TODO implement + return bool{}; } Return GnssConfiguration::setGpsLock(hidl_bitfield gpsLock) { @@ -47,15 +49,18 @@ Return GnssConfiguration::setGpsLock(hidl_bitfield gpsLock) { } Return GnssConfiguration::setLppProfile(hidl_bitfield) { - return true; + // TODO implement + return bool{}; } Return GnssConfiguration::setGlonassPositioningProtocol(hidl_bitfield) { - return true; + // TODO implement + return bool{}; } Return GnssConfiguration::setEmergencySuplPdn(bool) { - return true; + // TODO implement + return bool{}; } // Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow. diff --git a/gnss/2.0/vts/functional/gnss_hal_test.cpp b/gnss/2.0/vts/functional/gnss_hal_test.cpp index da6092bb4b..b8c343753f 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test.cpp +++ b/gnss/2.0/vts/functional/gnss_hal_test.cpp @@ -26,7 +26,6 @@ using ::android::hardware::gnss::common::Utils; GnssHalTest::GnssHalTest() : info_called_count_(0), capabilities_called_count_(0), - measurement_corrections_capabilities_called_count_(0), location_called_count_(0), name_called_count_(0), notify_count_(0) {} @@ -44,7 +43,6 @@ void GnssHalTest::TearDown() { // Reset counters info_called_count_ = 0; capabilities_called_count_ = 0; - measurement_corrections_capabilities_called_count_ = 0; location_called_count_ = 0; name_called_count_ = 0; measurement_called_count_ = 0; diff --git a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp index 0682f84d5f..230c9799f1 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp +++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp @@ -32,8 +32,6 @@ using IAGnssRil_2_0 = android::hardware::gnss::V2_0::IAGnssRil; using IAGnss_2_0 = android::hardware::gnss::V2_0::IAGnss; using IAGnss_1_0 = android::hardware::gnss::V1_0::IAGnss; using IAGnssCallback_2_0 = android::hardware::gnss::V2_0::IAGnssCallback; -using IGnssBatching_V1_0 = android::hardware::gnss::V1_0::IGnssBatching; -using IGnssBatching_V2_0 = android::hardware::gnss::V2_0::IGnssBatching; using android::hardware::gnss::common::Utils; using android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections; @@ -328,10 +326,6 @@ TEST_F(GnssHalTest, TestGnssMeasurementCorrections) { return; } - sp iMeasurementCorrectionsCallback = - new GnssMeasurementCorrectionsCallback(*this); - iMeasurementCorrections->setCallback(iMeasurementCorrectionsCallback); - const int kMeasurementCorrectionsCapabilitiesTimeoutSeconds = 5; waitForMeasurementCorrectionsCapabilities(kMeasurementCorrectionsCapabilitiesTimeoutSeconds); ASSERT_TRUE(measurement_corrections_capabilities_called_count_ > 0); @@ -401,20 +395,3 @@ TEST_F(GnssHalTest, TestInjectBestLocation_2_0) { gnss_hal_->injectBestLocation_2_0(last_location_); StopAndClearLocations(); } - -/* - * TestGnssBatchingExtension: - * Gets the GnssBatchingExtension and verifies that it supports either the @1.0::IGnssBatching - * or @2.0::IGnssBatching extension. - */ -TEST_F(GnssHalTest, TestGnssBatchingExtension) { - auto gnssBatching_V2_0 = gnss_hal_->getExtensionGnssBatching_2_0(); - ASSERT_TRUE(gnssBatching_V2_0.isOk()); - - auto gnssBatching_V1_0 = gnss_hal_->getExtensionGnssBatching(); - ASSERT_TRUE(gnssBatching_V1_0.isOk()); - - sp iGnssBatching_V1_0 = gnssBatching_V1_0; - sp iGnssBatching_V2_0 = gnssBatching_V2_0; - ASSERT_TRUE(iGnssBatching_V1_0 != nullptr || iGnssBatching_V2_0 != nullptr); -} From f404a1e8944e8b45de59f849223340a1e575db23 Mon Sep 17 00:00:00 2001 From: Viet Dang Date: Wed, 20 Mar 2019 10:35:21 +0000 Subject: [PATCH 559/718] BidirectionalSequenceLSTM op: Adds layer norm support. Also updates documentation for this op and UnidirectionalSequenceLSTM op. Bug: 123644584 Test: in ag/6758764 Change-Id: I72d029fef6d890eb1771c21814b028b09af280c7 --- current.txt | 2 +- neuralnetworks/1.2/types.hal | 160 +++++++++++++++++++++-------------- 2 files changed, 96 insertions(+), 66 deletions(-) diff --git a/current.txt b/current.txt index 9baa8ed9fd..f49727c41c 100644 --- a/current.txt +++ b/current.txt @@ -510,7 +510,7 @@ b9422a9aca84df1ff9623dc12c0562abce97716e28d63a965f2bfb88f9ad9607 android.hardwar 92714960d1a53fc2ec557302b41c7cc93d2636d8364a44bd0f85be0c92927ff8 android.hardware.neuralnetworks@1.2::IExecutionCallback 83885d366f22ada42c00d8854f0b7e7ba4cf73ddf80bb0d8e168ce132cec57ea android.hardware.neuralnetworks@1.2::IPreparedModel e1c734d1545e1a4ae749ff1dd9704a8e594c59aea7c8363159dc258e93e0df3b android.hardware.neuralnetworks@1.2::IPreparedModelCallback -730c74ee5a3dd61a73f150cf07653e4b928e413b0f228eb004541bfcc22ed245 android.hardware.neuralnetworks@1.2::types +2ef1bab554ea484523b396e48033117dbbefc2f90269f9e7e3eb5a58ba50bfb9 android.hardware.neuralnetworks@1.2::types cf7a4ba516a638f9b82a249c91fb603042c2d9ca43fd5aad9cf6c0401ed2a5d7 android.hardware.nfc@1.2::INfc abf98c2ae08bf765db54edc8068e36d52eb558cff6706b6fd7c18c65a1f3fc18 android.hardware.nfc@1.2::types 4cb252dc6372a874aef666b92a6e9529915aa187521a700f0789065c3c702ead android.hardware.power.stats@1.0::IPowerStats diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal index 918048bd3f..b27dc86088 100644 --- a/neuralnetworks/1.2/types.hal +++ b/neuralnetworks/1.2/types.hal @@ -2270,113 +2270,113 @@ enum OperationType : int32_t { * Inputs: * * 0: The input. * A 3-D tensor of shape: - * If time-major: [max_time, batch_size, output_size] - * If batch-major: [batch_size, max_time, output_size] + * If time-major: [max_time, batch_size, input_size] + * If batch-major: [batch_size, max_time, input_size] * where "max_time" is the number of timesteps (sequence length), * "batch_size" corresponds to the batching dimension, and * "input_size" is the size of the input. * * 1: The forward input-to-input weights. Optional. - * A 2-D tensor of shape [num_units, input_size], where “num_units” - * corresponds to the number of cell units. + * A 2-D tensor of shape [fw_num_units, input_size], where “fw_num_units” + * corresponds to the number of forward cell units. * * 2: The forward input-to-forget weights. - * A 2-D tensor of shape [num_units, input_size]. + * A 2-D tensor of shape [fw_num_units, input_size]. * * 3: The forward input-to-cell weights. - * A 2-D tensor of shape [num_units, input_size]. + * A 2-D tensor of shape [fw_num_units, input_size]. * * 4: The forward input-to-output weights. - * A 2-D tensor of shape [num_units, input_size]. + * A 2-D tensor of shape [fw_num_units, input_size]. * * 5: The forward recurrent-to-input weights. Optional. - * A 2-D tensor of shape [num_units, output_size], where “output_size” - * corresponds to either the number of cell units (i.e., “num_units”), - * or the second dimension of the “projection_weights”, if defined. + * A 2-D tensor of shape [fw_num_units, fw_output_size], where “fw_output_size” + * corresponds to either the number of cell units (i.e., fw_num_units), + * or the second dimension of the “fw_projection_weights”, if defined. * * 6: The forward recurrent-to-forget weights. - * A 2-D tensor of shape [num_units, output_size]. + * A 2-D tensor of shape [fw_num_units, fw_output_size]. * * 7: The forward recurrent-to-cell weights. - * A 2-D tensor of shape [num_units, output_size]. + * A 2-D tensor of shape [fw_num_units, fw_output_size]. * * 8: The forward recurrent-to-output weights. - * A 2-D tensor of shape [num_units, output_size]. + * A 2-D tensor of shape [fw_num_units, fw_output_size]. * * 9: The forward cell-to-input weights. Optional. - * A 1-D tensor of shape [num_units]. + * A 1-D tensor of shape [fw_num_units]. * * 10: The forward cell-to-forget weights. Optional. - * A 1-D tensor of shape [num_units]. + * A 1-D tensor of shape [fw_num_units]. * * 11: The forward cell-to-output weights. Optional. - * A 1-D tensor of shape [num_units]. + * A 1-D tensor of shape [fw_num_units]. * * 12: The forward input gate bias. Optional. - * A 1-D tensor of shape [num_units]. + * A 1-D tensor of shape [fw_num_units]. * * 13: The forward forget gate bias. - * A 1-D tensor of shape [num_units]. + * A 1-D tensor of shape [fw_num_units]. * * 14: The forward cell gate bias. - * A 1-D tensor of shape [num_units]. + * A 1-D tensor of shape [fw_num_units]. * * 15: The forward output gate bias. - * A 1-D tensor of shape [num_units]. + * A 1-D tensor of shape [fw_num_units]. * * 16: The forward projection weights. Optional. - * A 2-D tensor of shape [output_size, num_units]. + * A 2-D tensor of shape [fw_output_size, fw_num_units]. * * 17: The forward projection bias. Optional. - * A 1-D tensor of shape [output_size]. + * A 1-D tensor of shape [fw_output_size]. * * 18: The backward input-to-input weights. Optional. - * A 2-D tensor of shape [num_units, input_size], where “num_units” - * corresponds to the number of cell units. + * A 2-D tensor of shape [bw_num_units, input_size], where “bw_num_units” + * corresponds to the number of backward cell units. * * 19: The backward input-to-forget weights. - * A 2-D tensor of shape [num_units, input_size]. + * A 2-D tensor of shape [bw_num_units, input_size]. * * 20: The backward input-to-cell weights. - * A 2-D tensor of shape [num_units, input_size]. + * A 2-D tensor of shape [bw_num_units, input_size]. * * 21: The backward input-to-output weights. - * A 2-D tensor of shape [num_units, input_size]. + * A 2-D tensor of shape [bw_num_units, input_size]. * * 22: The backward recurrent-to-input weights. Optional. - * A 2-D tensor of shape [num_units, output_size], where “output_size” - * corresponds to either the number of cell units (i.e., “num_units”), - * or the second dimension of the “projection_weights”, if defined. + * A 2-D tensor of shape [bw_num_units, bw_output_size], where “bw_output_size” + * corresponds to either the number of cell units (i.e., “bw_num_units”), + * or the second dimension of the “bw_projection_weights”, if defined. * * 23: The backward recurrent-to-forget weights. - * A 2-D tensor of shape [num_units, output_size]. + * A 2-D tensor of shape [bw_num_units, bw_output_size]. * * 24: The backward recurrent-to-cell weights. - * A 2-D tensor of shape [num_units, output_size]. + * A 2-D tensor of shape [bw_num_units, bw_output_size]. * * 25: The backward recurrent-to-output weights. - * A 2-D tensor of shape [num_units, output_size]. + * A 2-D tensor of shape [bw_num_units, bw_output_size]. * * 26: The backward cell-to-input weights. Optional. - * A 1-D tensor of shape [num_units]. + * A 1-D tensor of shape [bw_num_units]. * * 27: The backward cell-to-forget weights. Optional. - * A 1-D tensor of shape [num_units]. + * A 1-D tensor of shape [bw_num_units]. * * 28: The backward cell-to-output weights. Optional. - * A 1-D tensor of shape [num_units]. + * A 1-D tensor of shape [bw_num_units]. * * 29: The backward input gate bias. Optional. - * A 1-D tensor of shape [num_units]. + * A 1-D tensor of shape [bw_num_units]. * * 30: The backward forget gate bias. - * A 1-D tensor of shape [num_units]. + * A 1-D tensor of shape [bw_num_units]. * * 31: The backward cell gate bias. - * A 1-D tensor of shape [num_units]. + * A 1-D tensor of shape [bw_num_units]. * * 32: The backward output gate bias. - * A 1-D tensor of shape [num_units]. + * A 1-D tensor of shape [bw_num_units]. * * 33: The backward projection weights. Optional. - * A 2-D tensor of shape [output_size, num_units]. + * A 2-D tensor of shape [bw_output_size, bw_num_units]. * * 34: The backward projection bias. Optional. - * A 1-D tensor of shape [output_size]. + * A 1-D tensor of shape [bw_output_size]. * * 35: The forward input activation state. - * A 2-D tensor of shape [batch_size, output_size]. + * A 2-D tensor of shape [batch_size, bw_output_size]. * * 36: The forward input cell state. - * A 2-D tensor of shape [batch_size, num_units]. + * A 2-D tensor of shape [batch_size, bw_num_units]. * * 37: The backward input activation state. - * A 2-D tensor of shape [batch_size, output_size]. + * A 2-D tensor of shape [batch_size, bw_output_size]. * * 38: The backward input cell state. - * A 2-D tensor of shape [batch_size, num_units]. + * A 2-D tensor of shape [batch_size, bw_num_units]. * * 39: The auxiliary input. Optional. * A 3-D tensor of shape [max_time, batch_size, input_size], where “batch_size” * corresponds to the batching dimension, and “input_size” is the size * of the input. * * 40: The forward auxiliary input-to-input weights. Optional. - * A 2-D tensor of shape [num_units, input_size]. + * A 2-D tensor of shape [fw_num_units, input_size]. * * 41: The forward auxiliary input-to-forget weights. Optional. - * A 2-D tensor of shape [num_units, input_size]. + * A 2-D tensor of shape [fw_num_units, input_size]. * * 42: The forward auxiliary input-to-cell weights. Optional. - * A 2-D tensor of shape [num_units, input_size]. + * A 2-D tensor of shape [fw_num_units, input_size]. * * 43: The forward auxiliary input-to-output weights. Optional. - * A 2-D tensor of shape [num_units, input_size]. + * A 2-D tensor of shape [fw_num_units, input_size]. * * 44: The backward auxiliary input-to-input weights. Optional. - * A 2-D tensor of shape [num_units, input_size]. + * A 2-D tensor of shape [bw_num_units, input_size]. * * 45: The backward auxiliary input-to-forget weights. Optional. - * A 2-D tensor of shape [num_units, input_size]. + * A 2-D tensor of shape [bw_num_units, input_size]. * * 46: The backward auxiliary input-to-cell weights. Optional. - * A 2-D tensor of shape [num_units, input_size]. + * A 2-D tensor of shape [bw_num_units, input_size]. * * 47: The backward auxiliary input-to-output weights. Optional. - * A 2-D tensor of shape [num_units, input_size]. + * A 2-D tensor of shape [bw_num_units, input_size]. * * 48: The activation function. * A value indicating the activation function: *
    @@ -2408,16 +2408,46 @@ enum OperationType : int32_t { * * 52: time_major * An {@link OperandType::BOOL} scalar specifying the shape format * of input and output tensors. + * * 53: The forward input layer normalization weights. Optional. + * A 1-D tensor of shape [fw_num_units]. Used to rescale normalized inputs + * to activation at input gate. + * * 54: The forward forget layer normalization weights. Optional. + * A 1-D tensor of shape [fw_num_units]. Used to rescale normalized inputs + * to activation at forget gate. + * * 55: The forward cell layer normalization weights. Optional. + * A 1-D tensor of shape [fw_num_units]. Used to rescale normalized inputs + * to activation at cell gate. + * * 56: The forward output layer normalization weights. Optional. + * A 1-D tensor of shape [fw_num_units]. Used to rescale normalized inputs + * to activation at output gate. + * * 57: The backward input layer normalization weights. Optional. + * A 1-D tensor of shape [bw_num_units]. Used to rescale normalized inputs + * to activation at input gate. + * * 58: The backward forget layer normalization weights. Optional. + * A 1-D tensor of shape [bw_num_units]. Used to rescale normalized inputs + * to activation at forget gate. + * * 59: The backward cell layer normalization weights. Optional. + * A 1-D tensor of shape [bw_num_units]. Used to rescale normalized inputs + * to activation at cell gate. + * * 60: The backward output layer normalization weights. Optional. + * A 1-D tensor of shape [bw_num_units]. Used to rescale normalized inputs + * to activation at output gate. * * Outputs: * * 0: The forward output. * A 3-D tensor of shape: - * If time-major: [max_time, batch_size, output_size] - * If batch-major: [batch_size, max_time, output_size] + * If time-major and not merge_outputs: + * [max_time, batch_size, fw_output_size] + * If time-major and merge_outputs: + * [max_time, batch_size, fw_output_size + bw_output_size] + * If batch-major and not merge_outputs: + * [batch_size, max_time, fw_output_size] + * If batch-major and merge_outputs: + * [batch_size, max_time, fw_output_size + bw_output_size] * * 1: The backward output. Unused if merge_outputs is true. * A 3-D tensor of shape: - * If time-major: [max_time, batch_size, output_size] - * If batch-major: [batch_size, max_time, output_size] + * If time-major: [max_time, batch_size, bw_output_size] + * If batch-major: [batch_size, max_time, bw_output_size] * * Available since API level 29. */ @@ -4357,9 +4387,9 @@ enum OperationType : int32_t { * Inputs: * * 0: The input (\f$x_t\f$). * A 3-D tensor of shape: - * If time-major: [max_time, batch_size, output_size] - * If batch-major: [batch_size, max_time, output_size] - * where “max_size” is the number of timesteps (sequence length), + * If time-major: [max_time, batch_size, input_size] + * If batch-major: [batch_size, max_time, input_size] + * where “max_time” is the number of timesteps (sequence length), * “batch_size” corresponds to the batching dimension, and * “input_size” is the size of the input. * * 1: The input-to-input weights (\f$W_{xi}\f$). Optional. @@ -4419,16 +4449,16 @@ enum OperationType : int32_t { * projection layer, such that values are bound within * [-proj_clip, proj_clip]. If set to 0.0 then clipping is disabled. * * 23:Time-major if true, batch-major if false. - * * 24:The input layer normalization weights. + * * 24:The input layer normalization weights. Optional. * A 1-D tensor of shape [num_units]. Used to rescale normalized inputs * to activation at input gate. - * * 25:The forget layer normalization weights. + * * 25:The forget layer normalization weights. Optional. * A 1-D tensor of shape [num_units]. Used to rescale normalized inputs * to activation at forget gate. - * * 26:The cell layer normalization weights. + * * 26:The cell layer normalization weights. Optional. * A 1-D tensor of shape [num_units]. Used to rescale normalized inputs * to activation at cell gate. - * * 27:The output layer normalization weights. + * * 27:The output layer normalization weights. Optional. * A 1-D tensor of shape [num_units]. Used to rescale normalized inputs * to activation at output gate. * From 704bc613e0dc772f5d523b4815e55839b5db5d69 Mon Sep 17 00:00:00 2001 From: Anil Admal Date: Thu, 21 Mar 2019 18:45:30 +0000 Subject: [PATCH 560/718] Revert "Revert "Update GNSS Batching to use new GnssLocation with elapsed realtime (HAL)"" This reverts commit b3721a68f273c305ea8e151cd3a8c192605370fc. Reason for revert: It appears that the build includes ag/6721678 but not ag/6762021 even though they both were submitted together. Hence the build errors. Change-Id: I4e58b29239d291ae3621b90e4507de8eb8838298 --- current.txt | 4 +- gnss/2.0/Android.bp | 2 + gnss/2.0/IGnss.hal | 8 +++ gnss/2.0/IGnssBatching.hal | 51 ++++++++++++++ gnss/2.0/IGnssBatchingCallback.hal | 36 ++++++++++ gnss/2.0/default/Android.bp | 1 + gnss/2.0/default/Gnss.cpp | 5 ++ gnss/2.0/default/Gnss.h | 1 + gnss/2.0/default/GnssBatching.cpp | 70 +++++++++++++++++++ gnss/2.0/default/GnssBatching.h | 57 +++++++++++++++ gnss/2.0/default/GnssConfiguration.cpp | 15 ++-- gnss/2.0/vts/functional/gnss_hal_test.cpp | 2 + .../vts/functional/gnss_hal_test_cases.cpp | 23 ++++++ 13 files changed, 264 insertions(+), 11 deletions(-) create mode 100644 gnss/2.0/IGnssBatching.hal create mode 100644 gnss/2.0/IGnssBatchingCallback.hal create mode 100644 gnss/2.0/default/GnssBatching.cpp create mode 100644 gnss/2.0/default/GnssBatching.h diff --git a/current.txt b/current.txt index 0c501400aa..2456032128 100644 --- a/current.txt +++ b/current.txt @@ -464,7 +464,9 @@ f27baaa587bc3dd9b740cb6928ab812b9b7d105b5187663938aee578105f3c39 android.hardwar 7f460e795f5d1ed5e378935f98c6db4d39497de988aef1b4c2a4a07a6c400392 android.hardware.gnss@2.0::IAGnss 2e5ad983734069e84a760004b32da0d09e4170c05380abe27e6eb80e4aa70d5a android.hardware.gnss@2.0::IAGnssCallback 1f4ac068a88a72360280d94a7f6fd7c63813c1eea4891a0eb01394d3e7e775f2 android.hardware.gnss@2.0::IAGnssRil -63216fcb23eaf4d6f12ea0e99b8bfdb8e4e57c02f215d433cd30943d850f61a7 android.hardware.gnss@2.0::IGnss +4deafcdcffa2d002119e7f58810b767a84666e76475aae68e757ec2845d9756d android.hardware.gnss@2.0::IGnss +db6bdf6dfc5edf6c85d2944976db899227abb51079c893874353c322342c50b6 android.hardware.gnss@2.0::IGnssBatching +1f89392f1ebb693d8fa6f50324b1635fc79fab246d31900e63998e1b0e17511c android.hardware.gnss@2.0::IGnssBatchingCallback b11a5e4a1602d3f408716b6fe2c578a79f060d571aad8e828f9a4426d161fbcf android.hardware.gnss@2.0::IGnssCallback ecc966c68bddbd95c8dae782b84204cf01c75734675e8769963f3b5106ec128b android.hardware.gnss@2.0::IGnssConfiguration b670bae2ab8517336290532e364502b4db9120340d75474ccc8442b1b15d6ab7 android.hardware.gnss@2.0::IGnssDebug diff --git a/gnss/2.0/Android.bp b/gnss/2.0/Android.bp index 30dc55de57..6cfd3462f2 100644 --- a/gnss/2.0/Android.bp +++ b/gnss/2.0/Android.bp @@ -12,6 +12,8 @@ hidl_interface { "IAGnssCallback.hal", "IAGnssRil.hal", "IGnss.hal", + "IGnssBatching.hal", + "IGnssBatchingCallback.hal", "IGnssCallback.hal", "IGnssConfiguration.hal", "IGnssDebug.hal", diff --git a/gnss/2.0/IGnss.hal b/gnss/2.0/IGnss.hal index ba757d73d6..f19f8d0566 100644 --- a/gnss/2.0/IGnss.hal +++ b/gnss/2.0/IGnss.hal @@ -27,6 +27,7 @@ import IGnssDebug; import IGnssMeasurement; import IAGnss; import IAGnssRil; +import IGnssBatching; /** * Represents the standard GNSS (Global Navigation Satellite System) interface. @@ -104,6 +105,13 @@ interface IGnss extends @1.1::IGnss { */ getExtensionVisibilityControl() generates (IGnssVisibilityControl visibilityControlIface); + /** + * This method returns the IGnssBatching interface. + * + * @return batchingIface Handle to the IGnssBatching interface. + */ + getExtensionGnssBatching_2_0() generates (IGnssBatching batchingIface); + /** * Injects current location from the best available location provider. * diff --git a/gnss/2.0/IGnssBatching.hal b/gnss/2.0/IGnssBatching.hal new file mode 100644 index 0000000000..961fa69548 --- /dev/null +++ b/gnss/2.0/IGnssBatching.hal @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.gnss@2.0; + +import @1.0::IGnssBatching; +import IGnssBatchingCallback; + +/** + * Extended interface for GNSS Batching support. + * + * If this interface is supported, this batching request must be able to run in + * parallel with, or without, non-batched location requested by the + * IGnss start() & stop() - i.e. both requests must be handled independently, + * and not interfere with each other. + * + * For example, if a 1Hz continuous output is underway on the IGnssCallback, + * due to an IGnss start() operation, + * and then a IGnssBatching start() is called for a location every 10 + * seconds, the newly added batching request must not disrupt the 1Hz + * continuous location output on the IGnssCallback. + * + * As with GNSS Location outputs, source of location must be GNSS satellite + * measurements, optionally using interial and baro sensors to improve + * relative motion filtering. No additional absolute positioning information, + * such as WiFi derived location, may be mixed with the GNSS information. + */ +interface IGnssBatching extends @1.0::IGnssBatching { + /** + * Opens the interface and provides the callback routines + * to the implementation of this interface. + * + * @param callback Callback interface for IGnssBatching. + * + * @return success Returns true on success. + */ + init_2_0(IGnssBatchingCallback callback) generates (bool success); +}; \ No newline at end of file diff --git a/gnss/2.0/IGnssBatchingCallback.hal b/gnss/2.0/IGnssBatchingCallback.hal new file mode 100644 index 0000000000..4f8b4ecbba --- /dev/null +++ b/gnss/2.0/IGnssBatchingCallback.hal @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.gnss@2.0; + +/** The callback interface to report measurements from the HAL. */ +interface IGnssBatchingCallback { + /** + * Called when a batch of locations is output, by various means, including + * a flush request, as well as the buffer becoming full (if appropriate option + * is set.) + * + * All locations returned by this callback must be cleared from the hardware + * buffer, such the sequential calls of this callback do not return any + * redundant locations. (Same lat/lon, at a new time, is acceptable.) + * + * The GnssLocation struct in gnss@2.0 is extended to include elapsed realtime + * information. + * + * @param locations GNSS Location information from HAL. + */ + gnssLocationBatchCb(vec locations); +}; diff --git a/gnss/2.0/default/Android.bp b/gnss/2.0/default/Android.bp index 64187e24d9..0fcd76495c 100644 --- a/gnss/2.0/default/Android.bp +++ b/gnss/2.0/default/Android.bp @@ -25,6 +25,7 @@ cc_binary { "AGnss.cpp", "AGnssRil.cpp", "Gnss.cpp", + "GnssBatching.cpp", "GnssMeasurement.cpp", "GnssMeasurementCorrections.cpp", "GnssVisibilityControl.cpp", diff --git a/gnss/2.0/default/Gnss.cpp b/gnss/2.0/default/Gnss.cpp index bb89b8b423..75c2385169 100644 --- a/gnss/2.0/default/Gnss.cpp +++ b/gnss/2.0/default/Gnss.cpp @@ -23,6 +23,7 @@ #include "AGnss.h" #include "AGnssRil.h" +#include "GnssBatching.h" #include "GnssConfiguration.h" #include "GnssMeasurement.h" #include "GnssMeasurementCorrections.h" @@ -265,6 +266,10 @@ Return> Gnss::getExtensionV return new GnssVisibilityControl(); } +Return> Gnss::getExtensionGnssBatching_2_0() { + return new GnssBatching(); +} + Return Gnss::setCallback_2_0(const sp& callback) { ALOGD("Gnss::setCallback_2_0"); if (callback == nullptr) { diff --git a/gnss/2.0/default/Gnss.h b/gnss/2.0/default/Gnss.h index a500128670..72f77976e5 100644 --- a/gnss/2.0/default/Gnss.h +++ b/gnss/2.0/default/Gnss.h @@ -92,6 +92,7 @@ struct Gnss : public IGnss { getExtensionMeasurementCorrections() override; Return> getExtensionVisibilityControl() override; + Return> getExtensionGnssBatching_2_0() override; Return injectBestLocation_2_0(const V2_0::GnssLocation& location) override; private: diff --git a/gnss/2.0/default/GnssBatching.cpp b/gnss/2.0/default/GnssBatching.cpp new file mode 100644 index 0000000000..d56cdfb33f --- /dev/null +++ b/gnss/2.0/default/GnssBatching.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "GnssBatching" + +#include "GnssBatching.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +sp GnssBatching::sCallback = nullptr; + +// Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow. +Return GnssBatching::init(const sp&) { + // TODO implement + return bool{}; +} + +Return GnssBatching::getBatchSize() { + // TODO implement + return uint16_t{}; +} + +Return GnssBatching::start(const V1_0::IGnssBatching::Options&) { + // TODO implement + return bool{}; +} + +Return GnssBatching::flush() { + // TODO implement + return Void(); +} + +Return GnssBatching::stop() { + // TODO implement + return bool{}; +} + +Return GnssBatching::cleanup() { + // TODO implement + return Void(); +} + +// Methods from V2_0::IGnssBatching follow. +Return GnssBatching::init_2_0(const sp& callback) { + sCallback = callback; + return true; +} + +} // namespace implementation +} // namespace V2_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/gnss/2.0/default/GnssBatching.h b/gnss/2.0/default/GnssBatching.h new file mode 100644 index 0000000000..62ac580897 --- /dev/null +++ b/gnss/2.0/default/GnssBatching.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2019 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. + */ + +#pragma once + +#include +#include +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +using ::android::sp; +using ::android::hardware::hidl_array; +using ::android::hardware::hidl_memory; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; + +struct GnssBatching : public IGnssBatching { + // Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow. + Return init(const sp& callback) override; + Return getBatchSize() override; + Return start(const V1_0::IGnssBatching::Options& options) override; + Return flush() override; + Return stop() override; + Return cleanup() override; + + // Methods from V2_0::IGnssBatching follow. + Return init_2_0(const sp& callback) override; + + private: + static sp sCallback; +}; + +} // namespace implementation +} // namespace V2_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/gnss/2.0/default/GnssConfiguration.cpp b/gnss/2.0/default/GnssConfiguration.cpp index 4389dd28f3..6bf1712aff 100644 --- a/gnss/2.0/default/GnssConfiguration.cpp +++ b/gnss/2.0/default/GnssConfiguration.cpp @@ -33,13 +33,11 @@ Return GnssConfiguration::setSuplEs(bool enable) { } Return GnssConfiguration::setSuplVersion(uint32_t) { - // TODO implement - return bool{}; + return true; } Return GnssConfiguration::setSuplMode(hidl_bitfield) { - // TODO implement - return bool{}; + return true; } Return GnssConfiguration::setGpsLock(hidl_bitfield gpsLock) { @@ -49,18 +47,15 @@ Return GnssConfiguration::setGpsLock(hidl_bitfield gpsLock) { } Return GnssConfiguration::setLppProfile(hidl_bitfield) { - // TODO implement - return bool{}; + return true; } Return GnssConfiguration::setGlonassPositioningProtocol(hidl_bitfield) { - // TODO implement - return bool{}; + return true; } Return GnssConfiguration::setEmergencySuplPdn(bool) { - // TODO implement - return bool{}; + return true; } // Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow. diff --git a/gnss/2.0/vts/functional/gnss_hal_test.cpp b/gnss/2.0/vts/functional/gnss_hal_test.cpp index b8c343753f..da6092bb4b 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test.cpp +++ b/gnss/2.0/vts/functional/gnss_hal_test.cpp @@ -26,6 +26,7 @@ using ::android::hardware::gnss::common::Utils; GnssHalTest::GnssHalTest() : info_called_count_(0), capabilities_called_count_(0), + measurement_corrections_capabilities_called_count_(0), location_called_count_(0), name_called_count_(0), notify_count_(0) {} @@ -43,6 +44,7 @@ void GnssHalTest::TearDown() { // Reset counters info_called_count_ = 0; capabilities_called_count_ = 0; + measurement_corrections_capabilities_called_count_ = 0; location_called_count_ = 0; name_called_count_ = 0; measurement_called_count_ = 0; diff --git a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp index 230c9799f1..0682f84d5f 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp +++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp @@ -32,6 +32,8 @@ using IAGnssRil_2_0 = android::hardware::gnss::V2_0::IAGnssRil; using IAGnss_2_0 = android::hardware::gnss::V2_0::IAGnss; using IAGnss_1_0 = android::hardware::gnss::V1_0::IAGnss; using IAGnssCallback_2_0 = android::hardware::gnss::V2_0::IAGnssCallback; +using IGnssBatching_V1_0 = android::hardware::gnss::V1_0::IGnssBatching; +using IGnssBatching_V2_0 = android::hardware::gnss::V2_0::IGnssBatching; using android::hardware::gnss::common::Utils; using android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections; @@ -326,6 +328,10 @@ TEST_F(GnssHalTest, TestGnssMeasurementCorrections) { return; } + sp iMeasurementCorrectionsCallback = + new GnssMeasurementCorrectionsCallback(*this); + iMeasurementCorrections->setCallback(iMeasurementCorrectionsCallback); + const int kMeasurementCorrectionsCapabilitiesTimeoutSeconds = 5; waitForMeasurementCorrectionsCapabilities(kMeasurementCorrectionsCapabilitiesTimeoutSeconds); ASSERT_TRUE(measurement_corrections_capabilities_called_count_ > 0); @@ -395,3 +401,20 @@ TEST_F(GnssHalTest, TestInjectBestLocation_2_0) { gnss_hal_->injectBestLocation_2_0(last_location_); StopAndClearLocations(); } + +/* + * TestGnssBatchingExtension: + * Gets the GnssBatchingExtension and verifies that it supports either the @1.0::IGnssBatching + * or @2.0::IGnssBatching extension. + */ +TEST_F(GnssHalTest, TestGnssBatchingExtension) { + auto gnssBatching_V2_0 = gnss_hal_->getExtensionGnssBatching_2_0(); + ASSERT_TRUE(gnssBatching_V2_0.isOk()); + + auto gnssBatching_V1_0 = gnss_hal_->getExtensionGnssBatching(); + ASSERT_TRUE(gnssBatching_V1_0.isOk()); + + sp iGnssBatching_V1_0 = gnssBatching_V1_0; + sp iGnssBatching_V2_0 = gnssBatching_V2_0; + ASSERT_TRUE(iGnssBatching_V1_0 != nullptr || iGnssBatching_V2_0 != nullptr); +} From b61ba1ed0ba850db7ef8f3a42c58bbc250488d52 Mon Sep 17 00:00:00 2001 From: Xusong Wang Date: Mon, 25 Feb 2019 16:58:58 -0800 Subject: [PATCH 561/718] Fix caching interface according to vendor feedback. - Instead of isCachingSupport returning a single boolean, switch to getNumberOfCacheFilesNeeded returning the number of cache files. This is to support use cases when driver needs more than one cache file for each type, or when driver does not need data cache. - Instead of a separate saveToCache, pass cache info along with prepareModel_1_2 to save into cache as well as perform compilation. This is to avoid a potential additional copy of cache files. Bug: 123780248 Test: VtsHalNeuralnetworksV1_xTargetTest with 1.2 sample driver Test: VtsHalNeuralnetworksV1_xTargetTest with a test driver that can read and write cache entries Change-Id: I921b7b8ccc3c66af19f6589f7213c6870d6f07bf --- current.txt | 6 +- .../vts/functional/GeneratedTestHarness.cpp | 4 +- neuralnetworks/1.2/IDevice.hal | 153 ++- neuralnetworks/1.2/IPreparedModel.hal | 58 - neuralnetworks/1.2/types.hal | 5 + .../1.2/vts/functional/BasicTests.cpp | 13 +- .../functional/CompilationCachingTests.cpp | 1023 +++++++++++------ .../1.2/vts/functional/ValidateModel.cpp | 4 +- .../1.2/vts/functional/ValidateRequest.cpp | 4 +- 9 files changed, 820 insertions(+), 450 deletions(-) diff --git a/current.txt b/current.txt index f49727c41c..3e980a0ec2 100644 --- a/current.txt +++ b/current.txt @@ -506,11 +506,11 @@ b9422a9aca84df1ff9623dc12c0562abce97716e28d63a965f2bfb88f9ad9607 android.hardwar 4cb139f729c29d8d6f4ecdab149c4feb571dad8a06e56cd57fcb52e70208bab4 android.hardware.media.c2@1.0::types 4880af120fc1640225abdc2c60bda6d79617d73484d5124913c7278af3b11e2d android.hardware.neuralnetworks@1.2::IBurstCallback 19877e466ad8c6ed42b38050b77bd010cf7800ff365fdc8574f45bbfda03a758 android.hardware.neuralnetworks@1.2::IBurstContext -96249c852dabeefa3a9496ecdfc44681a071c665bfbf88527bf775c88bf1ab1b android.hardware.neuralnetworks@1.2::IDevice +363821d1b71147b896a08e2a570946db9b9d46f90d9f91b085bd8d3013a2b4d5 android.hardware.neuralnetworks@1.2::IDevice 92714960d1a53fc2ec557302b41c7cc93d2636d8364a44bd0f85be0c92927ff8 android.hardware.neuralnetworks@1.2::IExecutionCallback -83885d366f22ada42c00d8854f0b7e7ba4cf73ddf80bb0d8e168ce132cec57ea android.hardware.neuralnetworks@1.2::IPreparedModel +36e1064c869965dee533c537cefbe87e54db8bd8cd45be7e0e93e00e8a43863a android.hardware.neuralnetworks@1.2::IPreparedModel e1c734d1545e1a4ae749ff1dd9704a8e594c59aea7c8363159dc258e93e0df3b android.hardware.neuralnetworks@1.2::IPreparedModelCallback -2ef1bab554ea484523b396e48033117dbbefc2f90269f9e7e3eb5a58ba50bfb9 android.hardware.neuralnetworks@1.2::types +39a6d7cf9bc7290bd90739e971ccad5f35f5cc0faea4a417b59f22c9ca9f1f2a android.hardware.neuralnetworks@1.2::types cf7a4ba516a638f9b82a249c91fb603042c2d9ca43fd5aad9cf6c0401ed2a5d7 android.hardware.nfc@1.2::INfc abf98c2ae08bf765db54edc8068e36d52eb558cff6706b6fd7c18c65a1f3fc18 android.hardware.nfc@1.2::types 4cb252dc6372a874aef666b92a6e9529915aa187521a700f0789065c3c702ead android.hardware.power.stats@1.0::IPowerStats diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp index f5cb0d7cf5..106f33279d 100644 --- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp +++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp @@ -52,6 +52,7 @@ using ::test_helper::for_each; using ::test_helper::MixedTyped; using ::test_helper::MixedTypedExample; using ::test_helper::resize_accordingly; +using HidlToken = hidl_array(Constant::BYTE_SIZE_OF_CACHE_TOKEN)>; template void copy_back_(std::map>* dst, const std::vector& ra, @@ -540,7 +541,8 @@ void PrepareModel(const sp& device, const V1_2::Model& model, sp preparedModelCallback = new PreparedModelCallback(); ASSERT_NE(nullptr, preparedModelCallback.get()); Return prepareLaunchStatus = device->prepareModel_1_2( - model, ExecutionPreference::FAST_SINGLE_ANSWER, preparedModelCallback); + model, ExecutionPreference::FAST_SINGLE_ANSWER, hidl_vec(), + hidl_vec(), HidlToken(), preparedModelCallback); ASSERT_TRUE(prepareLaunchStatus.isOk()); ASSERT_EQ(ErrorStatus::NONE, static_cast(prepareLaunchStatus)); diff --git a/neuralnetworks/1.2/IDevice.hal b/neuralnetworks/1.2/IDevice.hal index b9fa38870e..da9a966ba1 100644 --- a/neuralnetworks/1.2/IDevice.hal +++ b/neuralnetworks/1.2/IDevice.hal @@ -113,44 +113,83 @@ interface IDevice extends @1.1::IDevice { generates (ErrorStatus status, vec supportedOperations); /** - * Gets whether the driver supports compilation caching. + * Gets the caching requirements of the driver implementation. * - * isCachingSupported indicates whether the driver supports compilation caching. - * Even if so, the driver may still choose not to cache certain compiled models. + * There are two types of cache file descriptors provided to the driver: model cache + * and data cache. * - * If the device reports the caching is not supported, the user may avoid calling - * IDevice::prepareModelFromCache and IPreparedModel::saveToCache. + * The data cache is for caching constant data, possibly including preprocessed + * and transformed tensor buffers. Any modification to the data cache should + * have no worse effect than generating bad output values at execution time. + * + * The model cache is for caching security-sensitive data such as compiled + * executable machine code in the device's native binary format. A modification + * to the model cache may affect the driver's execution behavior, and a malicious + * client could make use of this to execute beyond the granted permission. Thus, + * the driver must always check whether the model cache is corrupted before + * preparing the model from cache. + * + * getNumberOfCacheFilesNeeded returns how many of each type of cache files the driver + * implementation needs to cache a single prepared model. Returning 0 for both types + * indicates compilation caching is not supported by this driver. The driver may + * still choose not to cache certain compiled models even if it reports that caching + * is supported. + * + * If the device reports that caching is not supported, the user may avoid calling + * IDevice::prepareModelFromCache or providing cache file descriptors to + * IDevice::prepareModel_1_2. * * @return status Error status of the call, must be: * - NONE if successful * - DEVICE_UNAVAILABLE if driver is offline or busy * - GENERAL_FAILURE if there is an unspecified error - * @return supported A boolean indicating whether the driver supports compilation - * caching. Even on returning true, the driver may still choose - * not to cache certain compiled models. + * @return numModelCache An unsigned integer indicating how many files for model cache + * the driver needs to cache a single prepared model. It must + * be less than or equal to Constant::MAX_NUMBER_OF_CACHE_FILES. + * @return numDataCache An unsigned integer indicating how many files for data cache + * the driver needs to cache a single prepared model. It must + * be less than or equal to Constant::MAX_NUMBER_OF_CACHE_FILES. */ - isCachingSupported() generates (ErrorStatus status, bool supported); + getNumberOfCacheFilesNeeded() + generates (ErrorStatus status, uint32_t numModelCache, uint32_t numDataCache); /** - * Creates a prepared model for execution. + * Asynchronously creates a prepared model for execution and optionally saves it + * into cache files. * - * prepareModel is used to make any necessary transformations or alternative + * prepareModel is used to make any necessary transformations to or alternative * representations to a model for execution, possibly including * transformations on the constant data, optimization on the model's graph, * or compilation into the device's native binary format. The model itself * is not changed. * + * Optionally, caching information may be provided for the driver to save + * the prepared model to cache files for faster model compilation time + * when the same model preparation is requested in the future. There are + * two types of cache file handles provided to the driver: model cache + * and data cache. For more information on the two types of cache handles, + * refer to getNumberOfCacheFilesNeeded. + * + * The file descriptors must be opened with read and write permission. A file may + * have any size, and the corresponding file descriptor may have any offset. The + * driver must truncate a file to zero size before writing to that file. The file + * descriptors may be closed by the client once the asynchronous preparation has + * finished. The driver must dup a file descriptor if it wants to get access to + * the cache file later. + * * The model is prepared asynchronously with respect to the caller. The - * prepareModel function must verify the inputs to the prepareModel function - * are correct. If there is an error, prepareModel must immediately invoke + * prepareModel function must verify the inputs to the preparedModel function + * related to preparing the model (as opposed to saving the prepared model to + * cache) are correct. If there is an error, prepareModel must immediately invoke * the callback with the appropriate ErrorStatus value and nullptr for the - * IPreparedModel, then return with the same ErrorStatus. If the inputs to - * the prepareModel function are valid and there is no error, prepareModel - * must launch an asynchronous task to prepare the model in the background, - * and immediately return from prepareModel with ErrorStatus::NONE. If the - * asynchronous task fails to launch, prepareModel must immediately invoke - * the callback with ErrorStatus::GENERAL_FAILURE and nullptr for the - * IPreparedModel, then return with ErrorStatus::GENERAL_FAILURE. + * IPreparedModel, then return with the same ErrorStatus. If the inputs to the + * prepareModel function that are related to preparing the model are valid and + * there is no error, prepareModel must launch an asynchronous task + * to prepare the model in the background, and immediately return from + * prepareModel with ErrorStatus::NONE. If the asynchronous task fails to launch, + * prepareModel must immediately invoke the callback with + * ErrorStatus::GENERAL_FAILURE and nullptr for the IPreparedModel, then return + * with ErrorStatus::GENERAL_FAILURE. * * When the asynchronous task has finished preparing the model, it must * immediately invoke the callback function provided as an input to @@ -160,6 +199,14 @@ interface IDevice extends @1.1::IDevice { * the callback object must be invoked with the appropriate ErrorStatus * value and nullptr for the IPreparedModel. * + * Optionally, the driver may save the prepared model to cache during the + * asynchronous preparation. Any error that occurs when saving to cache must + * not affect the status of preparing the model. Even if the input arguments + * related to the cache may be invalid, or the driver may fail to save to cache, + * the prepareModel function must finish preparing the model. The driver + * may choose not to save to cache even if the caching information is + * provided and valid. + * * The only information that may be unknown to the model at this stage is * the shape of the tensors, which may only be known at execution time. As * such, some driver services may return partially prepared models, where @@ -173,6 +220,26 @@ interface IDevice extends @1.1::IDevice { * @param model The model to be prepared for execution. * @param preference Indicates the intended execution behavior of a prepared * model. + * @param modelCache A vector of handles with each entry holding exactly one + * cache file descriptor for the security-sensitive cache. The length of + * the vector must either be 0 indicating that caching information is not provided, + * or match the numModelCache returned from getNumberOfCacheFilesNeeded. The cache + * handles will be provided in the same order when retrieving the + * preparedModel from cache files with prepareModelFromCache. + * @param dataCache A vector of handles with each entry holding exactly one + * cache file descriptor for the constants' cache. The length of + * the vector must either be 0 indicating that caching information is not provided, + * or match the numDataCache returned from getNumberOfCacheFilesNeeded. The cache + * handles will be provided in the same order when retrieving the + * preparedModel from cache files with prepareModelFromCache. + * @param token A caching token of length Constant::BYTE_SIZE_OF_CACHE_TOKEN + * identifying the prepared model. The same token will be provided when retrieving + * the prepared model from the cache files with prepareModelFromCache. + * Tokens should be chosen to have a low rate of collision for a particular + * application. The driver cannot detect a collision; a collision will result + * in a failed execution or in a successful execution that produces incorrect + * output values. If both modelCache and dataCache are empty indicating that + * caching information is not provided, this token must be ignored. * @param callback A callback object used to return the error status of * preparing the model for execution and the prepared model if * successful, nullptr otherwise. The callback object's notify function @@ -182,9 +249,12 @@ interface IDevice extends @1.1::IDevice { * - NONE if preparation task is successfully launched * - DEVICE_UNAVAILABLE if driver is offline or busy * - GENERAL_FAILURE if there is an unspecified error - * - INVALID_ARGUMENT if one of the input arguments is invalid + * - INVALID_ARGUMENT if one of the input arguments related to preparing the + * model is invalid */ prepareModel_1_2(Model model, ExecutionPreference preference, + vec modelCache, vec dataCache, + uint8_t[Constant:BYTE_SIZE_OF_CACHE_TOKEN] token, IPreparedModelCallback callback) generates (ErrorStatus status); @@ -192,22 +262,17 @@ interface IDevice extends @1.1::IDevice { * Creates a prepared model from cache files for execution. * * prepareModelFromCache is used to retrieve a prepared model directly from - * cache files to avoid slow model compilation time. There are exactly two - * cache file descriptors provided to the driver: modelCache and dataCache. + * cache files to avoid slow model compilation time. There are + * two types of cache file handles provided to the driver: model cache + * and data cache. For more information on the two types of cache handles, + * refer to getNumberOfCacheFilesNeeded. * - * The dataCache is for caching constant data, possibly including preprocessed - * and transformed tensor buffers. Any modification to the dataCache should - * have no worse effect than generating bad output values at execution time. - * - * The modelCache is for caching security-sensitive data such as compiled - * executable machine code in the device's native binary format. A modification - * to the modelCache may affect the driver's execution behavior, and a malicious - * client could make use of this to execute beyond the granted permission. Thus, - * the driver must always check whether the modelCache is corrupted before preparing - * the model from cache. - * - * The two file descriptors may be closed by the client once the asynchronous - * preparation has finished. The driver has to copy all the data it needs. + * The file descriptors must be opened with read and write permission. A file may + * have any size, and the corresponding file descriptor may have any offset. The + * driver must truncate a file to zero size before writing to that file. The file + * descriptors may be closed by the client once the asynchronous preparation has + * finished. The driver must dup a file descriptor if it wants to get access to + * the cache file later. * * The model is prepared asynchronously with respect to the caller. The * prepareModelFromCache function must verify the inputs to the @@ -241,13 +306,17 @@ interface IDevice extends @1.1::IDevice { * used with different shapes of inputs on different (possibly concurrent) * executions. * - * @param modelCache A handle holding exactly one cache file descriptor for the - * security-sensitive cache. - * @param dataCache A handle holding exactly one cache file descriptor for the - * constants' cache. + * @param modelCache A vector of handles with each entry holding exactly one + * cache file descriptor for the security-sensitive cache. The length of + * the vector must match the numModelCache returned from getNumberOfCacheFilesNeeded. + * The cache handles will be provided in the same order as with prepareModel_1_2. + * @param dataCache A vector of handles with each entry holding exactly one + * cache file descriptor for the constants' cache. The length of the vector + * must match the numDataCache returned from getNumberOfCacheFilesNeeded. + * The cache handles will be provided in the same order as with prepareModel_1_2. * @param token A caching token of length Constant::BYTE_SIZE_OF_CACHE_TOKEN * identifying the prepared model. It is the same token provided when saving - * the cache files with IPreparedModel::saveToCache. Tokens should be chosen + * the cache files with prepareModel_1_2. Tokens should be chosen * to have a low rate of collision for a particular application. The driver * cannot detect a collision; a collision will result in a failed execution * or in a successful execution that produces incorrect output values. @@ -263,7 +332,7 @@ interface IDevice extends @1.1::IDevice { * unspecified error * - INVALID_ARGUMENT if one of the input arguments is invalid */ - prepareModelFromCache(handle modelCache, handle dataCache, + prepareModelFromCache(vec modelCache, vec dataCache, uint8_t[Constant:BYTE_SIZE_OF_CACHE_TOKEN] token, IPreparedModelCallback callback) generates (ErrorStatus status); diff --git a/neuralnetworks/1.2/IPreparedModel.hal b/neuralnetworks/1.2/IPreparedModel.hal index 757d5f1467..5d2d80ff71 100644 --- a/neuralnetworks/1.2/IPreparedModel.hal +++ b/neuralnetworks/1.2/IPreparedModel.hal @@ -157,62 +157,4 @@ interface IPreparedModel extends @1.0::IPreparedModel { fmq_sync requestChannel, fmq_sync resultChannel) generates (ErrorStatus status, IBurstContext context); - - /* - * Saves the prepared model to cache files. - * - * saveToCache is used to save a prepared model to cache files for faster - * model compilation time when the same model preparation is requested in - * the future. There are exactly two cache file descriptors provided to the - * driver: modelCache and dataCache. - * - * The dataCache is for caching constant data, possibly including preprocessed - * and transformed tensor buffers. Any modification to the dataCache should - * have no worse effect than generating bad output values at execution time. - * - * The modelCache is for caching security-sensitive data such as compiled - * executable machine code in the device's native binary format. A modification - * to the modelCache may affect the driver's execution behavior, and a malicious - * client could make use of this to execute beyond the granted permission. Thus, - * the driver must always check whether the modelCache is corrupted before preparing - * the model from cache. - * - * The two file descriptors must point to two zero-length files with offset - * positioned at the beginning of the file. The file descriptors may be closed - * by the client once the method has returned. - * - * If the driver decides not to save the prepared model without looking at the - * input arguments to the saveToCache function, saveToCache must return with - * ErrorStatus::GENERAL_FAILURE. Otherwise, the saveToCache function must verify - * the input arguments to the saveToCache function are valid, and return with - * ErrorStatus::INVALID_ARGUMENT if not. If the inputs are valid but the driver - * could not save the prepared model, saveToCache must return with the appropriate - * ErrorStatus. Otherwise, it must write the cache files and return - * ErrorStatus::NONE. Unless saveToCache returns ErrorStatus::NONE, the contents - * of the cache files are undefined. - * - * @param modelCache A handle holding exactly one cache file descriptor for the - * security-sensitive cache. - * @param dataCache A handle holding exactly one cache file descriptor for the - * constants' cache. - * @param token A caching token of length Constant::BYTE_SIZE_OF_CACHE_TOKEN - * identifying the prepared model. The same token will be provided - * when retrieving the prepared model from cache files with - * IDevice::prepareModelFromCache. Tokens should be chosen to have - * a low rate of collision for a particular application. The driver - * cannot detect a collision; a collision will result in a failed - * execution or in a successful execution that produces incorrect - * output values. - * @return status Error status of saveToCache, must be: - * - NONE if saveToCache is performed successfully - * - DEVICE_UNAVAILABLE if driver is offline or busy - * - GENERAL_FAILURE if the driver could not save the - * prepared model or if there is an unspecified error - * - INVALID_ARGUMENT if one of the input arguments is invalid, - * unless the driver decides not to save the prepared model - * without looking at the input arguments - */ - saveToCache(handle modelCache, handle dataCache, - uint8_t[Constant:BYTE_SIZE_OF_CACHE_TOKEN] token) - generates (ErrorStatus status); }; diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal index b27dc86088..28d01192da 100644 --- a/neuralnetworks/1.2/types.hal +++ b/neuralnetworks/1.2/types.hal @@ -30,6 +30,11 @@ enum Constant : uint32_t { * The byte size of the cache token. */ BYTE_SIZE_OF_CACHE_TOKEN = 32, + + /** + * The maximum number of files for each type of cache in compilation caching. + */ + MAX_NUMBER_OF_CACHE_FILES = 32, }; enum OperandType : @1.0::OperandType { diff --git a/neuralnetworks/1.2/vts/functional/BasicTests.cpp b/neuralnetworks/1.2/vts/functional/BasicTests.cpp index 365a750fdb..6fb16c2033 100644 --- a/neuralnetworks/1.2/vts/functional/BasicTests.cpp +++ b/neuralnetworks/1.2/vts/functional/BasicTests.cpp @@ -77,10 +77,15 @@ TEST_F(NeuralnetworksHidlTest, GetDeviceSupportedExtensionsTest) { EXPECT_TRUE(ret.isOk()); } -// isCachingSupported test -TEST_F(NeuralnetworksHidlTest, IsCachingSupported) { - Return ret = device->isCachingSupported( - [](ErrorStatus status, bool) { EXPECT_EQ(ErrorStatus::NONE, status); }); +// getNumberOfCacheFilesNeeded test +TEST_F(NeuralnetworksHidlTest, getNumberOfCacheFilesNeeded) { + Return ret = device->getNumberOfCacheFilesNeeded( + [](ErrorStatus status, uint32_t numModelCache, uint32_t numDataCache) { + EXPECT_EQ(ErrorStatus::NONE, status); + EXPECT_LE(numModelCache, + static_cast(Constant::MAX_NUMBER_OF_CACHE_FILES)); + EXPECT_LE(numDataCache, static_cast(Constant::MAX_NUMBER_OF_CACHE_FILES)); + }); EXPECT_TRUE(ret.isOk()); } } // namespace functional diff --git a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp index 00989e5bdc..167fc096ce 100644 --- a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp +++ b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp @@ -54,29 +54,39 @@ namespace { [[maybe_unused]] auto dummy_createTestModel = createTestModel_dynamic_output_shape; [[maybe_unused]] auto dummy_get_examples = get_examples_dynamic_output_shape; -enum class AccessMode { READ_ONLY, WRITE_ONLY }; +enum class AccessMode { READ_WRITE, READ_ONLY, WRITE_ONLY }; -void createCacheHandle(const std::vector& files, AccessMode mode, - hidl_handle* handle) { - std::vector fds; - for (const auto& file : files) { - int fd; - if (mode == AccessMode::READ_ONLY) { - fd = open(file.c_str(), O_RDONLY); - } else if (mode == AccessMode::WRITE_ONLY) { - fd = open(file.c_str(), O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR); - } else { - FAIL(); +// Creates cache handles based on provided file groups. +// The outer vector corresponds to handles and the inner vector is for fds held by each handle. +void createCacheHandles(const std::vector>& fileGroups, + const std::vector& mode, hidl_vec* handles) { + handles->resize(fileGroups.size()); + for (uint32_t i = 0; i < fileGroups.size(); i++) { + std::vector fds; + for (const auto& file : fileGroups[i]) { + int fd; + if (mode[i] == AccessMode::READ_ONLY) { + fd = open(file.c_str(), O_RDONLY); + } else if (mode[i] == AccessMode::WRITE_ONLY) { + fd = open(file.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); + } else if (mode[i] == AccessMode::READ_WRITE) { + fd = open(file.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + } else { + FAIL(); + } + ASSERT_GE(fd, 0); + fds.push_back(fd); } - ASSERT_GE(fd, 0); - fds.push_back(fd); + native_handle_t* cacheNativeHandle = native_handle_create(fds.size(), 0); + ASSERT_NE(cacheNativeHandle, nullptr); + std::copy(fds.begin(), fds.end(), &cacheNativeHandle->data[0]); + (*handles)[i].setTo(cacheNativeHandle, /*shouldOwn=*/true); } - native_handle_t* cacheNativeHandle = native_handle_create(fds.size(), 0); - ASSERT_NE(cacheNativeHandle, nullptr); - for (uint32_t i = 0; i < fds.size(); i++) { - cacheNativeHandle->data[i] = fds[i]; - } - handle->setTo(cacheNativeHandle, /*shouldOwn=*/true); +} + +void createCacheHandles(const std::vector>& fileGroups, AccessMode mode, + hidl_vec* handles) { + createCacheHandles(fileGroups, std::vector(fileGroups.size(), mode), handles); } } // namespace @@ -88,38 +98,43 @@ class CompilationCachingTest : public NeuralnetworksHidlTest { NeuralnetworksHidlTest::SetUp(); ASSERT_NE(device.get(), nullptr); - // Create cache directory. The cache directory and cache files are always created to test - // the behavior of prepareModelFromCache, even when caching is not supported. + // Create cache directory. The cache directory and a temporary cache file is always created + // to test the behavior of prepareModelFromCache, even when caching is not supported. char cacheDirTemp[] = "/data/local/tmp/TestCompilationCachingXXXXXX"; char* cacheDir = mkdtemp(cacheDirTemp); ASSERT_NE(cacheDir, nullptr); mCacheDir = cacheDir; + mCacheDir.push_back('/'); - // Create empty cache files. - mCache1 = mCacheDir + "/cache1"; - mCache2 = mCacheDir + "/cache2"; - mCache3 = mCacheDir + "/cache3"; - // A dummy handle, use AccessMode::WRITE_ONLY for createCacheHandle to create files. - hidl_handle handle; - createCacheHandle({mCache1, mCache2, mCache3}, AccessMode::WRITE_ONLY, &handle); - - // Check if caching is supported. - bool isCachingSupported; - Return ret = device->isCachingSupported( - [&isCachingSupported](ErrorStatus status, bool supported) { + Return ret = device->getNumberOfCacheFilesNeeded( + [this](ErrorStatus status, uint32_t numModelCache, uint32_t numDataCache) { EXPECT_EQ(ErrorStatus::NONE, status); - isCachingSupported = supported; + mNumModelCache = numModelCache; + mNumDataCache = numDataCache; }); EXPECT_TRUE(ret.isOk()); - if (isCachingSupported) { - mIsCachingSupported = true; - } else { + mIsCachingSupported = mNumModelCache > 0 || mNumDataCache > 0; + + // Create empty cache files. + mTmpCache = mCacheDir + "tmp"; + for (uint32_t i = 0; i < mNumModelCache; i++) { + mModelCache.push_back({mCacheDir + "model" + std::to_string(i)}); + } + for (uint32_t i = 0; i < mNumDataCache; i++) { + mDataCache.push_back({mCacheDir + "data" + std::to_string(i)}); + } + // Dummy handles, use AccessMode::WRITE_ONLY for createCacheHandles to create files. + hidl_vec modelHandle, dataHandle, tmpHandle; + createCacheHandles(mModelCache, AccessMode::WRITE_ONLY, &modelHandle); + createCacheHandles(mDataCache, AccessMode::WRITE_ONLY, &dataHandle); + createCacheHandles({{mTmpCache}}, AccessMode::WRITE_ONLY, &tmpHandle); + + if (!mIsCachingSupported) { LOG(INFO) << "NN VTS: Early termination of test because vendor service does not " "support compilation caching."; std::cout << "[ ] Early termination of test because vendor service does not " "support compilation caching." << std::endl; - mIsCachingSupported = false; } } @@ -127,22 +142,49 @@ class CompilationCachingTest : public NeuralnetworksHidlTest { // The tmp directory is only removed when the driver reports caching not supported, // otherwise it is kept for debugging purpose. if (!mIsCachingSupported) { - remove(mCache1.c_str()); - remove(mCache2.c_str()); - remove(mCache3.c_str()); + remove(mTmpCache.c_str()); rmdir(mCacheDir.c_str()); } NeuralnetworksHidlTest::TearDown(); } - void saveModelToCache(sp preparedModel, const hidl_handle& cache1, - const hidl_handle& cache2, ErrorStatus* status) { - // Save IPreparedModel to cache. + void saveModelToCache(const V1_2::Model& model, const hidl_vec& modelCache, + const hidl_vec& dataCache, bool* supported, + sp* preparedModel = nullptr) { + if (preparedModel != nullptr) *preparedModel = nullptr; + + // See if service can handle model. + bool fullySupportsModel = false; + Return supportedCall = device->getSupportedOperations_1_2( + model, + [&fullySupportsModel, &model](ErrorStatus status, const hidl_vec& supported) { + ASSERT_EQ(ErrorStatus::NONE, status); + ASSERT_EQ(supported.size(), model.operations.size()); + fullySupportsModel = std::all_of(supported.begin(), supported.end(), + [](bool valid) { return valid; }); + }); + ASSERT_TRUE(supportedCall.isOk()); + *supported = fullySupportsModel; + if (!fullySupportsModel) return; + + // Launch prepare model. + sp preparedModelCallback = new PreparedModelCallback(); + ASSERT_NE(nullptr, preparedModelCallback.get()); hidl_array cacheToken(mToken); - Return saveToCacheStatus = - preparedModel->saveToCache(cache1, cache2, cacheToken); - ASSERT_TRUE(saveToCacheStatus.isOk()); - *status = static_cast(saveToCacheStatus); + Return prepareLaunchStatus = + device->prepareModel_1_2(model, ExecutionPreference::FAST_SINGLE_ANSWER, modelCache, + dataCache, cacheToken, preparedModelCallback); + ASSERT_TRUE(prepareLaunchStatus.isOk()); + ASSERT_EQ(static_cast(prepareLaunchStatus), ErrorStatus::NONE); + + // Retrieve prepared model. + preparedModelCallback->wait(); + ASSERT_EQ(preparedModelCallback->getStatus(), ErrorStatus::NONE); + if (preparedModel != nullptr) { + *preparedModel = + V1_2::IPreparedModel::castFrom(preparedModelCallback->getPreparedModel()) + .withDefault(nullptr); + } } bool checkEarlyTermination(ErrorStatus status) { @@ -157,14 +199,27 @@ class CompilationCachingTest : public NeuralnetworksHidlTest { return false; } - void prepareModelFromCache(const hidl_handle& cache1, const hidl_handle& cache2, + bool checkEarlyTermination(bool supported) { + if (!supported) { + LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot " + "prepare model that it does not support."; + std::cout << "[ ] Early termination of test because vendor service cannot " + "prepare model that it does not support." + << std::endl; + return true; + } + return false; + } + + void prepareModelFromCache(const hidl_vec& modelCache, + const hidl_vec& dataCache, sp* preparedModel, ErrorStatus* status) { // Launch prepare model from cache. sp preparedModelCallback = new PreparedModelCallback(); ASSERT_NE(nullptr, preparedModelCallback.get()); hidl_array cacheToken(mToken); - Return prepareLaunchStatus = - device->prepareModelFromCache(cache1, cache2, cacheToken, preparedModelCallback); + Return prepareLaunchStatus = device->prepareModelFromCache( + modelCache, dataCache, cacheToken, preparedModelCallback); ASSERT_TRUE(prepareLaunchStatus.isOk()); if (static_cast(prepareLaunchStatus) != ErrorStatus::NONE) { *preparedModel = nullptr; @@ -179,49 +234,54 @@ class CompilationCachingTest : public NeuralnetworksHidlTest { .withDefault(nullptr); } + // Absolute path to the temporary cache directory. std::string mCacheDir; - std::string mCache1; - std::string mCache2; - std::string mCache3; + + // Groups of file paths for model and data cache in the tmp cache directory, initialized with + // outer_size = mNum{Model|Data}Cache, inner_size = 1. The outer vector corresponds to handles + // and the inner vector is for fds held by each handle. + std::vector> mModelCache; + std::vector> mDataCache; + + // A separate temporary file path in the tmp cache directory. + std::string mTmpCache; + uint8_t mToken[static_cast(Constant::BYTE_SIZE_OF_CACHE_TOKEN)] = {}; - bool mIsCachingSupported; + uint32_t mNumModelCache; + uint32_t mNumDataCache; + uint32_t mIsCachingSupported; }; TEST_F(CompilationCachingTest, CacheSavingAndRetrieval) { // Create test HIDL model and compile. Model testModel = createTestModel(); sp preparedModel = nullptr; - generated_tests::PrepareModel(device, testModel, &preparedModel); - // Terminate early if the driver cannot prepare the model. - if (preparedModel == nullptr) return; // Save the compilation to cache. { - ErrorStatus status; - hidl_handle cache1, cache2; - createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1); - createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2); - saveModelToCache(preparedModel, cache1, cache2, &status); - if (!mIsCachingSupported) { - EXPECT_EQ(status, ErrorStatus::GENERAL_FAILURE); - } else { - if (checkEarlyTermination(status)) return; - ASSERT_EQ(status, ErrorStatus::NONE); - } + bool supported; + hidl_vec modelCache, dataCache; + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + saveModelToCache(testModel, modelCache, dataCache, &supported); + if (checkEarlyTermination(supported)) return; } // Retrieve preparedModel from cache. { preparedModel = nullptr; ErrorStatus status; - hidl_handle cache1, cache2; - createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1); - createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2); - prepareModelFromCache(cache1, cache2, &preparedModel, &status); + hidl_vec modelCache, dataCache; + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + prepareModelFromCache(modelCache, dataCache, &preparedModel, &status); if (!mIsCachingSupported) { ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); ASSERT_EQ(preparedModel, nullptr); return; + } else if (checkEarlyTermination(status)) { + ASSERT_EQ(preparedModel, nullptr); + return; } else { ASSERT_EQ(status, ErrorStatus::NONE); ASSERT_NE(preparedModel, nullptr); @@ -238,41 +298,54 @@ TEST_F(CompilationCachingTest, CacheSavingAndRetrievalNonZeroOffset) { // Create test HIDL model and compile. Model testModel = createTestModel(); sp preparedModel = nullptr; - generated_tests::PrepareModel(device, testModel, &preparedModel); - // Terminate early if the driver cannot prepare the model. - if (preparedModel == nullptr) return; // Save the compilation to cache. { - ErrorStatus status; - hidl_handle cache1, cache2; - createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1); - createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2); - saveModelToCache(preparedModel, cache1, cache2, &status); - if (!mIsCachingSupported) { - EXPECT_EQ(status, ErrorStatus::GENERAL_FAILURE); - } else { - if (checkEarlyTermination(status)) return; - ASSERT_EQ(status, ErrorStatus::NONE); + bool supported; + hidl_vec modelCache, dataCache; + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + uint8_t dummyBytes[] = {0, 0}; + // Write a dummy integer to the cache. + // The driver should be able to handle non-empty cache and non-zero fd offset. + for (uint32_t i = 0; i < modelCache.size(); i++) { + ASSERT_EQ(write(modelCache[i].getNativeHandle()->data[0], &dummyBytes, + sizeof(dummyBytes)), + sizeof(dummyBytes)); } + for (uint32_t i = 0; i < dataCache.size(); i++) { + ASSERT_EQ( + write(dataCache[i].getNativeHandle()->data[0], &dummyBytes, sizeof(dummyBytes)), + sizeof(dummyBytes)); + } + saveModelToCache(testModel, modelCache, dataCache, &supported); + if (checkEarlyTermination(supported)) return; } // Retrieve preparedModel from cache. { preparedModel = nullptr; ErrorStatus status; - hidl_handle cache1, cache2; - createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1); - createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2); + hidl_vec modelCache, dataCache; + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); uint8_t dummyByte = 0; - // Advance offset by one byte. - ASSERT_GE(read(cache1.getNativeHandle()->data[0], &dummyByte, 1), 0); - ASSERT_GE(read(cache2.getNativeHandle()->data[0], &dummyByte, 1), 0); - prepareModelFromCache(cache1, cache2, &preparedModel, &status); + // Advance the offset of each handle by one byte. + // The driver should be able to handle non-zero fd offset. + for (uint32_t i = 0; i < modelCache.size(); i++) { + ASSERT_GE(read(modelCache[i].getNativeHandle()->data[0], &dummyByte, 1), 0); + } + for (uint32_t i = 0; i < dataCache.size(); i++) { + ASSERT_GE(read(dataCache[i].getNativeHandle()->data[0], &dummyByte, 1), 0); + } + prepareModelFromCache(modelCache, dataCache, &preparedModel, &status); if (!mIsCachingSupported) { ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); ASSERT_EQ(preparedModel, nullptr); return; + } else if (checkEarlyTermination(status)) { + ASSERT_EQ(preparedModel, nullptr); + return; } else { ASSERT_EQ(status, ErrorStatus::NONE); ASSERT_NE(preparedModel, nullptr); @@ -285,234 +358,512 @@ TEST_F(CompilationCachingTest, CacheSavingAndRetrievalNonZeroOffset) { /*testDynamicOutputShape=*/false); } +TEST_F(CompilationCachingTest, SaveToCacheInvalidNumCache) { + // Create test HIDL model and compile. + Model testModel = createTestModel(); + + // Test with number of model cache files greater than mNumModelCache. + { + bool supported; + hidl_vec modelCache, dataCache; + // Pass an additional cache file for model cache. + mModelCache.push_back({mTmpCache}); + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + mModelCache.pop_back(); + sp preparedModel = nullptr; + saveModelToCache(testModel, modelCache, dataCache, &supported, &preparedModel); + if (checkEarlyTermination(supported)) return; + ASSERT_NE(preparedModel, nullptr); + // Execute and verify results. + generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; }, + get_examples(), + testModel.relaxComputationFloat32toFloat16, + /*testDynamicOutputShape=*/false); + // Check if prepareModelFromCache fails. + preparedModel = nullptr; + ErrorStatus status; + prepareModelFromCache(modelCache, dataCache, &preparedModel, &status); + if (status != ErrorStatus::INVALID_ARGUMENT) { + ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); + } + ASSERT_EQ(preparedModel, nullptr); + } + + // Test with number of model cache files smaller than mNumModelCache. + if (mModelCache.size() > 0) { + bool supported; + hidl_vec modelCache, dataCache; + // Pop out the last cache file. + auto tmp = mModelCache.back(); + mModelCache.pop_back(); + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + mModelCache.push_back(tmp); + sp preparedModel = nullptr; + saveModelToCache(testModel, modelCache, dataCache, &supported, &preparedModel); + if (checkEarlyTermination(supported)) return; + ASSERT_NE(preparedModel, nullptr); + // Execute and verify results. + generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; }, + get_examples(), + testModel.relaxComputationFloat32toFloat16, + /*testDynamicOutputShape=*/false); + // Check if prepareModelFromCache fails. + preparedModel = nullptr; + ErrorStatus status; + prepareModelFromCache(modelCache, dataCache, &preparedModel, &status); + if (status != ErrorStatus::INVALID_ARGUMENT) { + ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); + } + ASSERT_EQ(preparedModel, nullptr); + } + + // Test with number of data cache files greater than mNumDataCache. + { + bool supported; + hidl_vec modelCache, dataCache; + // Pass an additional cache file for data cache. + mDataCache.push_back({mTmpCache}); + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + mDataCache.pop_back(); + sp preparedModel = nullptr; + saveModelToCache(testModel, modelCache, dataCache, &supported, &preparedModel); + if (checkEarlyTermination(supported)) return; + ASSERT_NE(preparedModel, nullptr); + // Execute and verify results. + generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; }, + get_examples(), + testModel.relaxComputationFloat32toFloat16, + /*testDynamicOutputShape=*/false); + // Check if prepareModelFromCache fails. + preparedModel = nullptr; + ErrorStatus status; + prepareModelFromCache(modelCache, dataCache, &preparedModel, &status); + if (status != ErrorStatus::INVALID_ARGUMENT) { + ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); + } + ASSERT_EQ(preparedModel, nullptr); + } + + // Test with number of data cache files smaller than mNumDataCache. + if (mDataCache.size() > 0) { + bool supported; + hidl_vec modelCache, dataCache; + // Pop out the last cache file. + auto tmp = mDataCache.back(); + mDataCache.pop_back(); + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + mDataCache.push_back(tmp); + sp preparedModel = nullptr; + saveModelToCache(testModel, modelCache, dataCache, &supported, &preparedModel); + if (checkEarlyTermination(supported)) return; + ASSERT_NE(preparedModel, nullptr); + // Execute and verify results. + generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; }, + get_examples(), + testModel.relaxComputationFloat32toFloat16, + /*testDynamicOutputShape=*/false); + // Check if prepareModelFromCache fails. + preparedModel = nullptr; + ErrorStatus status; + prepareModelFromCache(modelCache, dataCache, &preparedModel, &status); + if (status != ErrorStatus::INVALID_ARGUMENT) { + ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); + } + ASSERT_EQ(preparedModel, nullptr); + } +} + +TEST_F(CompilationCachingTest, PrepareModelFromCacheInvalidNumCache) { + // Create test HIDL model and compile. + Model testModel = createTestModel(); + + // Save the compilation to cache. + { + bool supported; + hidl_vec modelCache, dataCache; + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + saveModelToCache(testModel, modelCache, dataCache, &supported); + if (checkEarlyTermination(supported)) return; + } + + // Test with number of model cache files greater than mNumModelCache. + { + sp preparedModel = nullptr; + ErrorStatus status; + hidl_vec modelCache, dataCache; + mModelCache.push_back({mTmpCache}); + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + mModelCache.pop_back(); + prepareModelFromCache(modelCache, dataCache, &preparedModel, &status); + if (status != ErrorStatus::GENERAL_FAILURE) { + ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT); + } + ASSERT_EQ(preparedModel, nullptr); + } + + // Test with number of model cache files smaller than mNumModelCache. + if (mModelCache.size() > 0) { + sp preparedModel = nullptr; + ErrorStatus status; + hidl_vec modelCache, dataCache; + auto tmp = mModelCache.back(); + mModelCache.pop_back(); + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + mModelCache.push_back(tmp); + prepareModelFromCache(modelCache, dataCache, &preparedModel, &status); + if (status != ErrorStatus::GENERAL_FAILURE) { + ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT); + } + ASSERT_EQ(preparedModel, nullptr); + } + + // Test with number of data cache files greater than mNumDataCache. + { + sp preparedModel = nullptr; + ErrorStatus status; + hidl_vec modelCache, dataCache; + mDataCache.push_back({mTmpCache}); + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + mDataCache.pop_back(); + prepareModelFromCache(modelCache, dataCache, &preparedModel, &status); + if (status != ErrorStatus::GENERAL_FAILURE) { + ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT); + } + ASSERT_EQ(preparedModel, nullptr); + } + + // Test with number of data cache files smaller than mNumDataCache. + if (mDataCache.size() > 0) { + sp preparedModel = nullptr; + ErrorStatus status; + hidl_vec modelCache, dataCache; + auto tmp = mDataCache.back(); + mDataCache.pop_back(); + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + mDataCache.push_back(tmp); + prepareModelFromCache(modelCache, dataCache, &preparedModel, &status); + if (status != ErrorStatus::GENERAL_FAILURE) { + ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT); + } + ASSERT_EQ(preparedModel, nullptr); + } +} + TEST_F(CompilationCachingTest, SaveToCacheInvalidNumFd) { // Create test HIDL model and compile. Model testModel = createTestModel(); - sp preparedModel = nullptr; - generated_tests::PrepareModel(device, testModel, &preparedModel); - // Terminate early if the driver cannot prepare the model. - if (preparedModel == nullptr) return; - // cache1 with invalid NumFd. - { + // Go through each handle in model cache, test with NumFd greater than 1. + for (uint32_t i = 0; i < mNumModelCache; i++) { + bool supported; + hidl_vec modelCache, dataCache; + // Pass an invalid number of fds for handle i. + mModelCache[i].push_back(mTmpCache); + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + mModelCache[i].pop_back(); + sp preparedModel = nullptr; + saveModelToCache(testModel, modelCache, dataCache, &supported, &preparedModel); + if (checkEarlyTermination(supported)) return; + ASSERT_NE(preparedModel, nullptr); + // Execute and verify results. + generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; }, + get_examples(), + testModel.relaxComputationFloat32toFloat16, + /*testDynamicOutputShape=*/false); + // Check if prepareModelFromCache fails. + preparedModel = nullptr; ErrorStatus status; - hidl_handle cache1, cache2; - createCacheHandle({mCache1, mCache3}, AccessMode::WRITE_ONLY, &cache1); - createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2); - saveModelToCache(preparedModel, cache1, cache2, &status); - if (status != ErrorStatus::GENERAL_FAILURE) { - ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT); + prepareModelFromCache(modelCache, dataCache, &preparedModel, &status); + if (status != ErrorStatus::INVALID_ARGUMENT) { + ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); } + ASSERT_EQ(preparedModel, nullptr); } - // cache2 with invalid NumFd. - { + // Go through each handle in model cache, test with NumFd equal to 0. + for (uint32_t i = 0; i < mNumModelCache; i++) { + bool supported; + hidl_vec modelCache, dataCache; + // Pass an invalid number of fds for handle i. + auto tmp = mModelCache[i].back(); + mModelCache[i].pop_back(); + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + mModelCache[i].push_back(tmp); + sp preparedModel = nullptr; + saveModelToCache(testModel, modelCache, dataCache, &supported, &preparedModel); + if (checkEarlyTermination(supported)) return; + ASSERT_NE(preparedModel, nullptr); + // Execute and verify results. + generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; }, + get_examples(), + testModel.relaxComputationFloat32toFloat16, + /*testDynamicOutputShape=*/false); + // Check if prepareModelFromCache fails. + preparedModel = nullptr; ErrorStatus status; - hidl_handle cache1, cache2; - createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1); - createCacheHandle({mCache2, mCache3}, AccessMode::WRITE_ONLY, &cache2); - saveModelToCache(preparedModel, cache1, cache2, &status); - if (status != ErrorStatus::GENERAL_FAILURE) { - ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT); + prepareModelFromCache(modelCache, dataCache, &preparedModel, &status); + if (status != ErrorStatus::INVALID_ARGUMENT) { + ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); } + ASSERT_EQ(preparedModel, nullptr); + } + + // Go through each handle in data cache, test with NumFd greater than 1. + for (uint32_t i = 0; i < mNumDataCache; i++) { + bool supported; + hidl_vec modelCache, dataCache; + // Pass an invalid number of fds for handle i. + mDataCache[i].push_back(mTmpCache); + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + mDataCache[i].pop_back(); + sp preparedModel = nullptr; + saveModelToCache(testModel, modelCache, dataCache, &supported, &preparedModel); + if (checkEarlyTermination(supported)) return; + ASSERT_NE(preparedModel, nullptr); + // Execute and verify results. + generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; }, + get_examples(), + testModel.relaxComputationFloat32toFloat16, + /*testDynamicOutputShape=*/false); + // Check if prepareModelFromCache fails. + preparedModel = nullptr; + ErrorStatus status; + prepareModelFromCache(modelCache, dataCache, &preparedModel, &status); + if (status != ErrorStatus::INVALID_ARGUMENT) { + ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); + } + ASSERT_EQ(preparedModel, nullptr); + } + + // Go through each handle in data cache, test with NumFd equal to 0. + for (uint32_t i = 0; i < mNumDataCache; i++) { + bool supported; + hidl_vec modelCache, dataCache; + // Pass an invalid number of fds for handle i. + auto tmp = mDataCache[i].back(); + mDataCache[i].pop_back(); + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + mDataCache[i].push_back(tmp); + sp preparedModel = nullptr; + saveModelToCache(testModel, modelCache, dataCache, &supported, &preparedModel); + if (checkEarlyTermination(supported)) return; + ASSERT_NE(preparedModel, nullptr); + // Execute and verify results. + generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; }, + get_examples(), + testModel.relaxComputationFloat32toFloat16, + /*testDynamicOutputShape=*/false); + // Check if prepareModelFromCache fails. + preparedModel = nullptr; + ErrorStatus status; + prepareModelFromCache(modelCache, dataCache, &preparedModel, &status); + if (status != ErrorStatus::INVALID_ARGUMENT) { + ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); + } + ASSERT_EQ(preparedModel, nullptr); } } TEST_F(CompilationCachingTest, PrepareModelFromCacheInvalidNumFd) { // Create test HIDL model and compile. Model testModel = createTestModel(); - sp preparedModel = nullptr; - generated_tests::PrepareModel(device, testModel, &preparedModel); - // Terminate early if the driver cannot prepare the model. - if (preparedModel == nullptr) return; // Save the compilation to cache. { - ErrorStatus status; - hidl_handle cache1, cache2; - createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1); - createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2); - saveModelToCache(preparedModel, cache1, cache2, &status); - if (status != ErrorStatus::GENERAL_FAILURE) { - ASSERT_EQ(status, ErrorStatus::NONE); - } + bool supported; + hidl_vec modelCache, dataCache; + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + saveModelToCache(testModel, modelCache, dataCache, &supported); + if (checkEarlyTermination(supported)) return; } - // cache1 with invalid NumFd. - { - preparedModel = nullptr; + // Go through each handle in model cache, test with NumFd greater than 1. + for (uint32_t i = 0; i < mNumModelCache; i++) { + sp preparedModel = nullptr; ErrorStatus status; - hidl_handle cache1, cache2; - createCacheHandle({mCache1, mCache3}, AccessMode::READ_ONLY, &cache1); - createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2); - prepareModelFromCache(cache1, cache2, &preparedModel, &status); + hidl_vec modelCache, dataCache; + mModelCache[i].push_back(mTmpCache); + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + mModelCache[i].pop_back(); + prepareModelFromCache(modelCache, dataCache, &preparedModel, &status); if (status != ErrorStatus::GENERAL_FAILURE) { ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT); - ASSERT_EQ(preparedModel, nullptr); } + ASSERT_EQ(preparedModel, nullptr); } - // cache2 with invalid NumFd. - { - preparedModel = nullptr; + // Go through each handle in model cache, test with NumFd equal to 0. + for (uint32_t i = 0; i < mNumModelCache; i++) { + sp preparedModel = nullptr; ErrorStatus status; - hidl_handle cache1, cache2; - createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1); - createCacheHandle({mCache2, mCache3}, AccessMode::READ_ONLY, &cache2); - prepareModelFromCache(cache1, cache2, &preparedModel, &status); + hidl_vec modelCache, dataCache; + auto tmp = mModelCache[i].back(); + mModelCache[i].pop_back(); + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + mModelCache[i].push_back(tmp); + prepareModelFromCache(modelCache, dataCache, &preparedModel, &status); if (status != ErrorStatus::GENERAL_FAILURE) { ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT); - ASSERT_EQ(preparedModel, nullptr); } + ASSERT_EQ(preparedModel, nullptr); + } + + // Go through each handle in data cache, test with NumFd greater than 1. + for (uint32_t i = 0; i < mNumDataCache; i++) { + sp preparedModel = nullptr; + ErrorStatus status; + hidl_vec modelCache, dataCache; + mDataCache[i].push_back(mTmpCache); + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + mDataCache[i].pop_back(); + prepareModelFromCache(modelCache, dataCache, &preparedModel, &status); + if (status != ErrorStatus::GENERAL_FAILURE) { + ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT); + } + ASSERT_EQ(preparedModel, nullptr); + } + + // Go through each handle in data cache, test with NumFd equal to 0. + for (uint32_t i = 0; i < mNumDataCache; i++) { + sp preparedModel = nullptr; + ErrorStatus status; + hidl_vec modelCache, dataCache; + auto tmp = mDataCache[i].back(); + mDataCache[i].pop_back(); + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + mDataCache[i].push_back(tmp); + prepareModelFromCache(modelCache, dataCache, &preparedModel, &status); + if (status != ErrorStatus::GENERAL_FAILURE) { + ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT); + } + ASSERT_EQ(preparedModel, nullptr); } } TEST_F(CompilationCachingTest, SaveToCacheInvalidAccessMode) { // Create test HIDL model and compile. Model testModel = createTestModel(); - sp preparedModel = nullptr; - generated_tests::PrepareModel(device, testModel, &preparedModel); - // Terminate early if the driver cannot prepare the model. - if (preparedModel == nullptr) return; + std::vector modelCacheMode(mNumModelCache, AccessMode::READ_WRITE); + std::vector dataCacheMode(mNumDataCache, AccessMode::READ_WRITE); - // cache1 with invalid access mode. - { + // Go through each handle in model cache, test with invalid access mode. + for (uint32_t i = 0; i < mNumModelCache; i++) { + bool supported; + hidl_vec modelCache, dataCache; + modelCacheMode[i] = AccessMode::READ_ONLY; + createCacheHandles(mModelCache, modelCacheMode, &modelCache); + createCacheHandles(mDataCache, dataCacheMode, &dataCache); + modelCacheMode[i] = AccessMode::READ_WRITE; + sp preparedModel = nullptr; + saveModelToCache(testModel, modelCache, dataCache, &supported, &preparedModel); + if (checkEarlyTermination(supported)) return; + ASSERT_NE(preparedModel, nullptr); + // Execute and verify results. + generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; }, + get_examples(), + testModel.relaxComputationFloat32toFloat16, + /*testDynamicOutputShape=*/false); + // Check if prepareModelFromCache fails. + preparedModel = nullptr; ErrorStatus status; - hidl_handle cache1, cache2; - createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1); - createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2); - saveModelToCache(preparedModel, cache1, cache2, &status); - ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); + prepareModelFromCache(modelCache, dataCache, &preparedModel, &status); + if (status != ErrorStatus::INVALID_ARGUMENT) { + ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); + } + ASSERT_EQ(preparedModel, nullptr); } - // cache2 with invalid access mode. - { + // Go through each handle in data cache, test with invalid access mode. + for (uint32_t i = 0; i < mNumDataCache; i++) { + bool supported; + hidl_vec modelCache, dataCache; + dataCacheMode[i] = AccessMode::READ_ONLY; + createCacheHandles(mModelCache, modelCacheMode, &modelCache); + createCacheHandles(mDataCache, dataCacheMode, &dataCache); + dataCacheMode[i] = AccessMode::READ_WRITE; + sp preparedModel = nullptr; + saveModelToCache(testModel, modelCache, dataCache, &supported, &preparedModel); + if (checkEarlyTermination(supported)) return; + ASSERT_NE(preparedModel, nullptr); + // Execute and verify results. + generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; }, + get_examples(), + testModel.relaxComputationFloat32toFloat16, + /*testDynamicOutputShape=*/false); + // Check if prepareModelFromCache fails. + preparedModel = nullptr; ErrorStatus status; - hidl_handle cache1, cache2; - createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1); - createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2); - saveModelToCache(preparedModel, cache1, cache2, &status); - ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); + prepareModelFromCache(modelCache, dataCache, &preparedModel, &status); + if (status != ErrorStatus::INVALID_ARGUMENT) { + ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); + } + ASSERT_EQ(preparedModel, nullptr); } } TEST_F(CompilationCachingTest, PrepareModelFromCacheInvalidAccessMode) { // Create test HIDL model and compile. Model testModel = createTestModel(); - sp preparedModel = nullptr; - generated_tests::PrepareModel(device, testModel, &preparedModel); - // Terminate early if the driver cannot prepare the model. - if (preparedModel == nullptr) return; + std::vector modelCacheMode(mNumModelCache, AccessMode::READ_WRITE); + std::vector dataCacheMode(mNumDataCache, AccessMode::READ_WRITE); // Save the compilation to cache. { - ErrorStatus status; - hidl_handle cache1, cache2; - createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1); - createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2); - saveModelToCache(preparedModel, cache1, cache2, &status); - if (status != ErrorStatus::GENERAL_FAILURE) { - ASSERT_EQ(status, ErrorStatus::NONE); - } + bool supported; + hidl_vec modelCache, dataCache; + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + saveModelToCache(testModel, modelCache, dataCache, &supported); + if (checkEarlyTermination(supported)) return; } - // cache1 with invalid access mode. - { - preparedModel = nullptr; + // Go through each handle in model cache, test with invalid access mode. + for (uint32_t i = 0; i < mNumModelCache; i++) { + sp preparedModel = nullptr; ErrorStatus status; - hidl_handle cache1, cache2; - createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1); - createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2); - prepareModelFromCache(cache1, cache2, &preparedModel, &status); + hidl_vec modelCache, dataCache; + modelCacheMode[i] = AccessMode::WRITE_ONLY; + createCacheHandles(mModelCache, modelCacheMode, &modelCache); + createCacheHandles(mDataCache, dataCacheMode, &dataCache); + modelCacheMode[i] = AccessMode::READ_WRITE; + prepareModelFromCache(modelCache, dataCache, &preparedModel, &status); ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); ASSERT_EQ(preparedModel, nullptr); } - // cache2 with invalid access mode. - { - preparedModel = nullptr; + // Go through each handle in data cache, test with invalid access mode. + for (uint32_t i = 0; i < mNumDataCache; i++) { + sp preparedModel = nullptr; ErrorStatus status; - hidl_handle cache1, cache2; - createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1); - createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2); - prepareModelFromCache(cache1, cache2, &preparedModel, &status); + hidl_vec modelCache, dataCache; + dataCacheMode[i] = AccessMode::WRITE_ONLY; + createCacheHandles(mModelCache, modelCacheMode, &modelCache); + createCacheHandles(mDataCache, dataCacheMode, &dataCache); + dataCacheMode[i] = AccessMode::READ_WRITE; + prepareModelFromCache(modelCache, dataCache, &preparedModel, &status); ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); ASSERT_EQ(preparedModel, nullptr); } } -TEST_F(CompilationCachingTest, SaveToCacheInvalidOffset) { - // Create test HIDL model and compile. - Model testModel = createTestModel(); - sp preparedModel = nullptr; - generated_tests::PrepareModel(device, testModel, &preparedModel); - // Terminate early if the driver cannot prepare the model. - if (preparedModel == nullptr) return; - - // cache1 with invalid file descriptor offset. - { - ErrorStatus status; - hidl_handle cache1, cache2; - createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1); - createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2); - uint8_t dummyByte = 0; - // Advance offset by one byte. - ASSERT_EQ(write(cache1.getNativeHandle()->data[0], &dummyByte, 1), 1); - saveModelToCache(preparedModel, cache1, cache2, &status); - ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); - } - - // cache2 with invalid file descriptor offset. - { - ErrorStatus status; - hidl_handle cache1, cache2; - createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1); - createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2); - uint8_t dummyByte = 0; - // Advance offset by one byte. - ASSERT_EQ(write(cache2.getNativeHandle()->data[0], &dummyByte, 1), 1); - saveModelToCache(preparedModel, cache1, cache2, &status); - ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); - } -} - -TEST_F(CompilationCachingTest, SaveToCacheInvalidFileSize) { - // Create test HIDL model and compile. - Model testModel = createTestModel(); - sp preparedModel = nullptr; - generated_tests::PrepareModel(device, testModel, &preparedModel); - // Terminate early if the driver cannot prepare the model. - if (preparedModel == nullptr) return; - - // cache1 with invalid file size. - { - ErrorStatus status; - hidl_handle cache1, cache2; - createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1); - createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2); - uint8_t dummyByte = 0; - // Write one byte and seek back to the beginning. - ASSERT_EQ(write(cache1.getNativeHandle()->data[0], &dummyByte, 1), 1); - ASSERT_EQ(lseek(cache1.getNativeHandle()->data[0], 0, SEEK_SET), 0); - saveModelToCache(preparedModel, cache1, cache2, &status); - ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); - } - - // cache2 with invalid file size. - { - ErrorStatus status; - hidl_handle cache1, cache2; - createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1); - createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2); - uint8_t dummyByte = 0; - // Write one byte and seek back to the beginning. - ASSERT_EQ(write(cache2.getNativeHandle()->data[0], &dummyByte, 1), 1); - ASSERT_EQ(lseek(cache2.getNativeHandle()->data[0], 0, SEEK_SET), 0); - saveModelToCache(preparedModel, cache1, cache2, &status); - ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); - } -} - class CompilationCachingSecurityTest : public CompilationCachingTest, public ::testing::WithParamInterface { protected: @@ -537,44 +888,44 @@ TEST_P(CompilationCachingSecurityTest, CorruptedSecuritySensitiveCache) { // Create test HIDL model and compile. Model testModel = createTestModel(); - sp preparedModel = nullptr; - generated_tests::PrepareModel(device, testModel, &preparedModel); - // Terminate early if the driver cannot prepare the model. - if (preparedModel == nullptr) return; - // Save the compilation to cache. - { - ErrorStatus status; - hidl_handle cache1, cache2; - createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1); - createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2); - saveModelToCache(preparedModel, cache1, cache2, &status); - if (checkEarlyTermination(status)) return; - ASSERT_EQ(status, ErrorStatus::NONE); - } + for (uint32_t i = 0; i < mNumModelCache; i++) { + // Save the compilation to cache. + { + bool supported; + hidl_vec modelCache, dataCache; + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + saveModelToCache(testModel, modelCache, dataCache, &supported); + if (checkEarlyTermination(supported)) return; + } - // Randomly flip one single bit of the cache entry. - FILE* pFile = fopen(mCache1.c_str(), "r+"); - ASSERT_EQ(fseek(pFile, 0, SEEK_END), 0); - long int fileSize = ftell(pFile); - ASSERT_GT(fileSize, 0); - ASSERT_EQ(fseek(pFile, getRandomInt(0l, fileSize - 1), SEEK_SET), 0); - int readByte = fgetc(pFile); - ASSERT_NE(readByte, EOF); - ASSERT_EQ(fseek(pFile, -1, SEEK_CUR), 0); - ASSERT_NE(fputc(static_cast(readByte) ^ (1U << getRandomInt(0, 7)), pFile), EOF); - fclose(pFile); + // Randomly flip one single bit of the cache entry. + FILE* pFile = fopen(mModelCache[i][0].c_str(), "r+"); + ASSERT_EQ(fseek(pFile, 0, SEEK_END), 0); + long int fileSize = ftell(pFile); + if (fileSize == 0) { + fclose(pFile); + continue; + } + ASSERT_EQ(fseek(pFile, getRandomInt(0l, fileSize - 1), SEEK_SET), 0); + int readByte = fgetc(pFile); + ASSERT_NE(readByte, EOF); + ASSERT_EQ(fseek(pFile, -1, SEEK_CUR), 0); + ASSERT_NE(fputc(static_cast(readByte) ^ (1U << getRandomInt(0, 7)), pFile), EOF); + fclose(pFile); - // Retrieve preparedModel from cache, expect failure. - { - preparedModel = nullptr; - ErrorStatus status; - hidl_handle cache1, cache2; - createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1); - createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2); - prepareModelFromCache(cache1, cache2, &preparedModel, &status); - ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); - ASSERT_EQ(preparedModel, nullptr); + // Retrieve preparedModel from cache, expect failure. + { + sp preparedModel = nullptr; + ErrorStatus status; + hidl_vec modelCache, dataCache; + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + prepareModelFromCache(modelCache, dataCache, &preparedModel, &status); + ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); + ASSERT_EQ(preparedModel, nullptr); + } } } @@ -583,40 +934,37 @@ TEST_P(CompilationCachingSecurityTest, WrongLengthSecuritySensitiveCache) { // Create test HIDL model and compile. Model testModel = createTestModel(); - sp preparedModel = nullptr; - generated_tests::PrepareModel(device, testModel, &preparedModel); - // Terminate early if the driver cannot prepare the model. - if (preparedModel == nullptr) return; - // Save the compilation to cache. - { - ErrorStatus status; - hidl_handle cache1, cache2; - createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1); - createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2); - saveModelToCache(preparedModel, cache1, cache2, &status); - if (checkEarlyTermination(status)) return; - ASSERT_EQ(status, ErrorStatus::NONE); - } + for (uint32_t i = 0; i < mNumModelCache; i++) { + // Save the compilation to cache. + { + bool supported; + hidl_vec modelCache, dataCache; + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + saveModelToCache(testModel, modelCache, dataCache, &supported); + if (checkEarlyTermination(supported)) return; + } - // Randomly append bytes to the cache entry. - FILE* pFile = fopen(mCache1.c_str(), "a"); - uint32_t appendLength = getRandomInt(1, 256); - for (uint32_t i = 0; i < appendLength; i++) { - ASSERT_NE(fputc(getRandomInt(0, 255), pFile), EOF); - } - fclose(pFile); + // Randomly append bytes to the cache entry. + FILE* pFile = fopen(mModelCache[i][0].c_str(), "a"); + uint32_t appendLength = getRandomInt(1, 256); + for (uint32_t i = 0; i < appendLength; i++) { + ASSERT_NE(fputc(getRandomInt(0, 255), pFile), EOF); + } + fclose(pFile); - // Retrieve preparedModel from cache, expect failure. - { - preparedModel = nullptr; - ErrorStatus status; - hidl_handle cache1, cache2; - createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1); - createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2); - prepareModelFromCache(cache1, cache2, &preparedModel, &status); - ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); - ASSERT_EQ(preparedModel, nullptr); + // Retrieve preparedModel from cache, expect failure. + { + sp preparedModel = nullptr; + ErrorStatus status; + hidl_vec modelCache, dataCache; + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + prepareModelFromCache(modelCache, dataCache, &preparedModel, &status); + ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); + ASSERT_EQ(preparedModel, nullptr); + } } } @@ -625,20 +973,15 @@ TEST_P(CompilationCachingSecurityTest, WrongToken) { // Create test HIDL model and compile. Model testModel = createTestModel(); - sp preparedModel = nullptr; - generated_tests::PrepareModel(device, testModel, &preparedModel); - // Terminate early if the driver cannot prepare the model. - if (preparedModel == nullptr) return; // Save the compilation to cache. { - ErrorStatus status; - hidl_handle cache1, cache2; - createCacheHandle({mCache1}, AccessMode::WRITE_ONLY, &cache1); - createCacheHandle({mCache2}, AccessMode::WRITE_ONLY, &cache2); - saveModelToCache(preparedModel, cache1, cache2, &status); - if (checkEarlyTermination(status)) return; - ASSERT_EQ(status, ErrorStatus::NONE); + bool supported; + hidl_vec modelCache, dataCache; + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + saveModelToCache(testModel, modelCache, dataCache, &supported); + if (checkEarlyTermination(supported)) return; } // Randomly flip one single bit in mToken. @@ -647,12 +990,12 @@ TEST_P(CompilationCachingSecurityTest, WrongToken) { // Retrieve the preparedModel from cache, expect failure. { - preparedModel = nullptr; + sp preparedModel = nullptr; ErrorStatus status; - hidl_handle cache1, cache2; - createCacheHandle({mCache1}, AccessMode::READ_ONLY, &cache1); - createCacheHandle({mCache2}, AccessMode::READ_ONLY, &cache2); - prepareModelFromCache(cache1, cache2, &preparedModel, &status); + hidl_vec modelCache, dataCache; + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + prepareModelFromCache(modelCache, dataCache, &preparedModel, &status); ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); ASSERT_EQ(preparedModel, nullptr); } diff --git a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp index c2330b581e..2988211e5a 100644 --- a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp +++ b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp @@ -33,6 +33,7 @@ namespace functional { using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback; using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback; +using HidlToken = hidl_array(Constant::BYTE_SIZE_OF_CACHE_TOKEN)>; ///////////////////////// UTILITY FUNCTIONS ///////////////////////// @@ -54,7 +55,8 @@ static void validatePrepareModel(const sp& device, const std::string& m sp preparedModelCallback = new PreparedModelCallback(); ASSERT_NE(nullptr, preparedModelCallback.get()); Return prepareLaunchStatus = - device->prepareModel_1_2(model, preference, preparedModelCallback); + device->prepareModel_1_2(model, preference, hidl_vec(), + hidl_vec(), HidlToken(), preparedModelCallback); ASSERT_TRUE(prepareLaunchStatus.isOk()); ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast(prepareLaunchStatus)); diff --git a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp index d411da4819..b15f657348 100644 --- a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp +++ b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp @@ -37,6 +37,7 @@ namespace functional { using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback; using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback; using ::android::hidl::memory::V1_0::IMemory; +using HidlToken = hidl_array(Constant::BYTE_SIZE_OF_CACHE_TOKEN)>; using test_helper::for_all; using test_helper::MixedTyped; using test_helper::MixedTypedExample; @@ -66,7 +67,8 @@ static void createPreparedModel(const sp& device, const Model& model, sp preparedModelCallback = new PreparedModelCallback(); ASSERT_NE(nullptr, preparedModelCallback.get()); Return prepareLaunchStatus = device->prepareModel_1_2( - model, ExecutionPreference::FAST_SINGLE_ANSWER, preparedModelCallback); + model, ExecutionPreference::FAST_SINGLE_ANSWER, hidl_vec(), + hidl_vec(), HidlToken(), preparedModelCallback); ASSERT_TRUE(prepareLaunchStatus.isOk()); ASSERT_EQ(ErrorStatus::NONE, static_cast(prepareLaunchStatus)); From aae73cd2589f8b6d16dd030938b623dd32122cb8 Mon Sep 17 00:00:00 2001 From: Wei Wang Date: Thu, 21 Mar 2019 14:54:45 -0700 Subject: [PATCH 562/718] Adjust mock thermal HAL 2.0 mock data Bug: 127269185 Test: Build Change-Id: I7a8b83a893a51dcc1028f3f62c54877a446e1b71 --- thermal/2.0/default/Thermal.cpp | 51 +++++++++++++++++---------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/thermal/2.0/default/Thermal.cpp b/thermal/2.0/default/Thermal.cpp index 0ef4b63324..bbbecb8583 100644 --- a/thermal/2.0/default/Thermal.cpp +++ b/thermal/2.0/default/Thermal.cpp @@ -38,46 +38,47 @@ using ::android::hardware::thermal::V1_0::ThermalStatusCode; std::set> gCallbacks; static const Temperature_1_0 kTemp_1_0 = { - .type = static_cast<::android::hardware::thermal::V1_0::TemperatureType>(TemperatureType::CPU), - .name = "test temperature sensor", - .currentValue = 98.6, - .throttlingThreshold = 58, - .shutdownThreshold = 60.0, - .vrThrottlingThreshold = 59.0, + .type = static_cast<::android::hardware::thermal::V1_0::TemperatureType>( + TemperatureType::SKIN), + .name = "test temperature sensor", + .currentValue = 30.8, + .throttlingThreshold = 48.0, + .shutdownThreshold = 60.0, + .vrThrottlingThreshold = 49.0, }; static const Temperature_2_0 kTemp_2_0 = { - .type = TemperatureType::SKIN, - .name = "test temperature sensor", - .value = 98.6, - .throttlingStatus = ThrottlingSeverity::CRITICAL, + .type = TemperatureType::SKIN, + .name = "test temperature sensor", + .value = 30.8, + .throttlingStatus = ThrottlingSeverity::NONE, }; static const TemperatureThreshold kTempThreshold = { - .type = TemperatureType::SKIN, - .name = "test temperature sensor", - .hotThrottlingThresholds = {{NAN, NAN, NAN, NAN, NAN, NAN, NAN}}, - .coldThrottlingThresholds = {{NAN, NAN, NAN, NAN, NAN, NAN, NAN}}, - .vrThrottlingThreshold = NAN, + .type = TemperatureType::SKIN, + .name = "test temperature sensor", + .hotThrottlingThresholds = {{NAN, NAN, NAN, 48.0, NAN, NAN, 60.0}}, + .coldThrottlingThresholds = {{NAN, NAN, NAN, NAN, NAN, NAN, NAN}}, + .vrThrottlingThreshold = 49.0, }; static const CoolingDevice_1_0 kCooling_1_0 = { - .type = ::android::hardware::thermal::V1_0::CoolingType::FAN_RPM, - .name = "test cooling device", - .currentValue = 100.0, + .type = ::android::hardware::thermal::V1_0::CoolingType::FAN_RPM, + .name = "test cooling device", + .currentValue = 100.0, }; static const CoolingDevice_2_0 kCooling_2_0 = { - .type = CoolingType::CPU, - .name = "test cooling device", - .value = 1, + .type = CoolingType::FAN, + .name = "test cooling device", + .value = 100, }; static const CpuUsage kCpuUsage = { - .name = "cpu_name", - .active = 0, - .total = 0, - .isOnline = true, + .name = "cpu_name", + .active = 0, + .total = 0, + .isOnline = true, }; // Methods from ::android::hardware::thermal::V1_0::IThermal follow. From 7788df304ec0f6b102b86e4f74ac588fafc8e35d Mon Sep 17 00:00:00 2001 From: Shuzhen Wang Date: Thu, 21 Mar 2019 14:28:36 -0700 Subject: [PATCH 563/718] Camera: Update VTS test for revised multi-camera requirement Test to make sure logical multi-camera device support isStreamCombinationSupported() for 3.5 and above devices. Test: VtsHalCameraProviderV2_4TargetTest Bug: 119325664 Change-Id: I734278799f10ed215ceb5dd108ac7f722f7f7925 --- .../VtsHalCameraProviderV2_4TargetTest.cpp | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp index d77bb0e445..5dfc783efa 100644 --- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp +++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp @@ -767,7 +767,7 @@ public: const ::android::hardware::camera::common::V1_0::helper::CameraMetadata& metadata); void verifyStreamCombination(sp cameraDevice3_5, const ::android::hardware::camera::device::V3_4::StreamConfiguration &config3_4, - bool expectedStatus); + bool expectedStatus, bool expectStreamCombQuery); void verifyLogicalCameraResult(const camera_metadata_t* staticMetadata, const ::android::hardware::camera::common::V1_0::helper::CameraMetadata& resultMetadata); @@ -2877,8 +2877,9 @@ TEST_F(CameraHidlTest, configureStreamsAvailableOutputs) { createStreamConfiguration(streams3_2, StreamConfigurationMode::NORMAL_MODE, &config3_2, &config3_4, &config3_5, jpegBufferSize); if (session3_5 != nullptr) { + bool expectStreamCombQuery = (isLogicalMultiCamera(staticMeta) == Status::OK); verifyStreamCombination(cameraDevice3_5, config3_4, - /*expectedStatus*/ true); + /*expectedStatus*/ true, expectStreamCombQuery); config3_5.streamConfigCounter = streamConfigCounter++; ret = session3_5->configureStreams_3_5(config3_5, [streamId](Status s, device::V3_4::HalStreamConfiguration halConfig) { @@ -2971,7 +2972,8 @@ TEST_F(CameraHidlTest, configureStreamsInvalidOutputs) { createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config3_2, &config3_4, &config3_5, jpegBufferSize); if (session3_5 != nullptr) { - verifyStreamCombination(cameraDevice3_5, config3_4, /*expectedStatus*/ false); + verifyStreamCombination(cameraDevice3_5, config3_4, /*expectedStatus*/ false, + /*expectStreamCombQuery*/false); config3_5.streamConfigCounter = streamConfigCounter++; ret = session3_5->configureStreams_3_5(config3_5, [](Status s, device::V3_4::HalStreamConfiguration) { @@ -3232,7 +3234,7 @@ TEST_F(CameraHidlTest, configureStreamsZSLInputOutputs) { &config3_2, &config3_4, &config3_5, jpegBufferSize); if (session3_5 != nullptr) { verifyStreamCombination(cameraDevice3_5, config3_4, - /*expectedStatus*/ true); + /*expectedStatus*/ true, /*expectStreamCombQuery*/ false); config3_5.streamConfigCounter = streamConfigCounter++; ret = session3_5->configureStreams_3_5(config3_5, [](Status s, device::V3_4::HalStreamConfiguration halConfig) { @@ -3483,7 +3485,7 @@ TEST_F(CameraHidlTest, configureStreamsPreviewStillOutputs) { &config3_2, &config3_4, &config3_5, jpegBufferSize); if (session3_5 != nullptr) { verifyStreamCombination(cameraDevice3_5, config3_4, - /*expectedStatus*/ true); + /*expectedStatus*/ true, /*expectStreamCombQuery*/ false); config3_5.streamConfigCounter = streamConfigCounter++; ret = session3_5->configureStreams_3_5(config3_5, [](Status s, device::V3_4::HalStreamConfiguration halConfig) { @@ -3578,7 +3580,7 @@ TEST_F(CameraHidlTest, configureStreamsConstrainedOutputs) { &config3_2, &config3_4, &config3_5); if (session3_5 != nullptr) { verifyStreamCombination(cameraDevice3_5, config3_4, - /*expectedStatus*/ true); + /*expectedStatus*/ true, /*expectStreamCombQuery*/ false); config3_5.streamConfigCounter = streamConfigCounter++; ret = session3_5->configureStreams_3_5(config3_5, [streamId](Status s, device::V3_4::HalStreamConfiguration halConfig) { @@ -3811,7 +3813,7 @@ TEST_F(CameraHidlTest, configureStreamsVideoStillOutputs) { &config3_2, &config3_4, &config3_5, jpegBufferSize); if (session3_5 != nullptr) { verifyStreamCombination(cameraDevice3_5, config3_4, - /*expectedStatus*/ true); + /*expectedStatus*/ true, /*expectStreamCombQuery*/ false); config3_5.streamConfigCounter = streamConfigCounter++; ret = session3_5->configureStreams_3_5(config3_5, [](Status s, device::V3_4::HalStreamConfiguration halConfig) { @@ -5535,11 +5537,12 @@ void CameraHidlTest::castSession(const sp &session, int32_ void CameraHidlTest::verifyStreamCombination(sp cameraDevice3_5, const ::android::hardware::camera::device::V3_4::StreamConfiguration &config3_4, - bool expectedStatus) { + bool expectedStatus, bool expectMethodSupported) { if (cameraDevice3_5.get() != nullptr) { auto ret = cameraDevice3_5->isStreamCombinationSupported(config3_4, - [expectedStatus] (Status s, bool combStatus) { - ASSERT_TRUE((Status::OK == s) || (Status::METHOD_NOT_SUPPORTED == s)); + [expectedStatus, expectMethodSupported] (Status s, bool combStatus) { + ASSERT_TRUE((Status::OK == s) || + (!expectMethodSupported && Status::METHOD_NOT_SUPPORTED == s)); if (Status::OK == s) { ASSERT_TRUE(combStatus == expectedStatus); } From a4c94fd1287bc00c853b83d09313274b0658c8fb Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Thu, 21 Mar 2019 20:48:34 +0000 Subject: [PATCH 564/718] Add new TEXTURE_TICK constant. Unlike TICK, this is specifically meant to be called repeatedly in reaction to small movements in order to replicate a specific texture. Bug: 111461797 Test: VTS Change-Id: If21687b5fed5f578a638017abc9ce479a122612d --- current.txt | 3 +- vibrator/1.3/Android.bp | 1 + vibrator/1.3/IVibrator.hal | 15 ++++ vibrator/1.3/example/Vibrator.cpp | 38 ++++++---- vibrator/1.3/example/Vibrator.h | 5 +- vibrator/1.3/types.hal | 30 ++++++++ .../VtsHalVibratorV1_3TargetTest.cpp | 75 +++++++++++++++++++ 7 files changed, 148 insertions(+), 19 deletions(-) create mode 100644 vibrator/1.3/types.hal diff --git a/current.txt b/current.txt index 88d2e1132a..b91f3f9e54 100644 --- a/current.txt +++ b/current.txt @@ -544,7 +544,8 @@ b47f90302595874dfddb19bd05a054727bf18b3a930bc810ea14957b859ae8bf android.hardwar 61bc302e7c974c59b25898c585c6e9685e8a81021b1bed3eedf5224198f2785a android.hardware.usb@1.2::IUsb 46996cd2a1c66261a75a1f6ecada77eeb5861eb264fa39b996548fe0a7f22dd3 android.hardware.usb@1.2::IUsbCallback 3bbaa8cbc5d6b1da21f5509b2b641e05fc7eeca1354751eb1bb3cf37f89aa32f android.hardware.usb@1.2::types -92c1a726c80970d623b891f7c2f9a989a40a15ee1244092b49f4eb6adcdce4e9 android.hardware.vibrator@1.3::IVibrator +0f7ff73793548d5154014059b7e0fe9ef6355d32218ace157954d02055f5248b android.hardware.vibrator@1.3::IVibrator +2e313dc27a1327a29862ab3e085917f75c9e996f7c8df5a0ce37b9a0ed076b80 android.hardware.vibrator@1.3::types f19832856a3f53ced5ef91d3cc630a57fb7f4d4ce15f364dbed09099b89f6830 android.hardware.wifi@1.3::IWifi 7c6799c19bfdb3dec016b751556fe246cf7d37191ee7bb82a0091ab9fbf6f2fb android.hardware.wifi@1.3::IWifiChip 3bef30e8b61ab050c0f6fd26572712be5ebb7707d624c9aa6c74bbb9d6a5b4a9 android.hardware.wifi@1.3::IWifiStaIface diff --git a/vibrator/1.3/Android.bp b/vibrator/1.3/Android.bp index 28370d6e4d..a2ff784a6c 100644 --- a/vibrator/1.3/Android.bp +++ b/vibrator/1.3/Android.bp @@ -8,6 +8,7 @@ hidl_interface { }, srcs: [ "IVibrator.hal", + "types.hal", ], interfaces: [ "android.hardware.vibrator@1.0", diff --git a/vibrator/1.3/IVibrator.hal b/vibrator/1.3/IVibrator.hal index 01c2801720..1c870ee4cd 100644 --- a/vibrator/1.3/IVibrator.hal +++ b/vibrator/1.3/IVibrator.hal @@ -16,6 +16,7 @@ package android.hardware.vibrator@1.3; +import @1.0::EffectStrength; import @1.0::Status; import @1.2::IVibrator; @@ -41,4 +42,18 @@ interface IVibrator extends @1.2::IVibrator { * not supported by the device. */ setExternalControl(bool enabled) generates (Status status); + + /** + * Fire off a predefined haptic event. + * + * @param event The type of haptic event to trigger. + * @return status Whether the effect was successfully performed or not. Must + * return Status::UNSUPPORTED_OPERATION if the effect is not supported. + * @return lengthMs The length of time the event is expected to take in + * milliseconds. This doesn't need to be perfectly accurate, but should be a reasonable + * approximation. Should be a positive, non-zero value if the returned status is Status::OK, + * and set to 0 otherwise. + */ + perform_1_3(Effect effect, EffectStrength strength) + generates (Status status, uint32_t lengthMs); }; diff --git a/vibrator/1.3/example/Vibrator.cpp b/vibrator/1.3/example/Vibrator.cpp index bb9a057697..eb50187fe9 100644 --- a/vibrator/1.3/example/Vibrator.cpp +++ b/vibrator/1.3/example/Vibrator.cpp @@ -74,22 +74,9 @@ Return Vibrator::perform_1_1(V1_1::Effect_1_1 effect, EffectStrength stren // Methods from ::android::hardware::vibrator::V1_2::IVibrator follow. -Return Vibrator::perform_1_2(Effect effect, EffectStrength strength, perform_cb _hidl_cb) { - uint8_t amplitude; - uint32_t ms; - Status status; - - ALOGI("Perform: Effect %s\n", effectToName(effect)); - - amplitude = strengthToAmplitude(strength); - setAmplitude(amplitude); - - ms = effectToMs(effect); - status = activate(ms); - - _hidl_cb(status, ms); - - return Void(); +Return Vibrator::perform_1_2(V1_2::Effect effect, EffectStrength strength, + perform_cb _hidl_cb) { + return perform_1_3(static_cast(effect), strength, _hidl_cb); } // Methods from ::android::hardware::vibrator::V1_3::IVibrator follow. @@ -110,6 +97,24 @@ Return Vibrator::setExternalControl(bool enabled) { } } +Return Vibrator::perform_1_3(Effect effect, EffectStrength strength, perform_cb _hidl_cb) { + uint8_t amplitude; + uint32_t ms; + Status status; + + ALOGI("Perform: Effect %s\n", effectToName(effect)); + + amplitude = strengthToAmplitude(strength); + setAmplitude(amplitude); + + ms = effectToMs(effect); + status = activate(ms); + + _hidl_cb(status, ms); + + return Void(); +} + // Private methods follow. Status Vibrator::enable(bool enabled) { @@ -184,6 +189,7 @@ uint32_t Vibrator::effectToMs(Effect effect) { case Effect::DOUBLE_CLICK: return 15; case Effect::TICK: + case Effect::TEXTURE_TICK: return 5; case Effect::THUD: return 5; diff --git a/vibrator/1.3/example/Vibrator.h b/vibrator/1.3/example/Vibrator.h index a931b63b09..8cf0b1eb05 100644 --- a/vibrator/1.3/example/Vibrator.h +++ b/vibrator/1.3/example/Vibrator.h @@ -27,7 +27,6 @@ namespace implementation { using android::hardware::vibrator::V1_0::EffectStrength; using android::hardware::vibrator::V1_0::Status; -using android::hardware::vibrator::V1_2::Effect; class Vibrator : public IVibrator { public: @@ -46,11 +45,13 @@ class Vibrator : public IVibrator { perform_cb _hidl_cb) override; // Methods from ::android::hardware::vibrator::V1_2::IVibrator follow. - Return perform_1_2(Effect effect, EffectStrength strength, perform_cb _hidl_cb) override; + Return perform_1_2(V1_2::Effect effect, EffectStrength strength, + perform_cb _hidl_cb) override; // Methods from ::android::hardware::vibrator::V1_3::IVibrator follow. Return supportsExternalControl() override; Return setExternalControl(bool enabled) override; + Return perform_1_3(Effect effect, EffectStrength strength, perform_cb _hidl_cb) override; private: Status enable(bool enabled); diff --git a/vibrator/1.3/types.hal b/vibrator/1.3/types.hal new file mode 100644 index 0000000000..ceb62a5f66 --- /dev/null +++ b/vibrator/1.3/types.hal @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.vibrator@1.3; + +import @1.2::Effect; + +enum Effect : @1.2::Effect { + /** + * A soft tick effect meant to be played as a texture. + * + * A soft, short sensation like the tick of a clock. Unlike regular effects, texture effects + * are expected to be played multiple times in quick succession, replicating a specific + * texture to the user as a form of haptic feedback. + */ + TEXTURE_TICK +}; diff --git a/vibrator/1.3/vts/functional/VtsHalVibratorV1_3TargetTest.cpp b/vibrator/1.3/vts/functional/VtsHalVibratorV1_3TargetTest.cpp index a67d1dc8c7..818f9c7ab4 100644 --- a/vibrator/1.3/vts/functional/VtsHalVibratorV1_3TargetTest.cpp +++ b/vibrator/1.3/vts/functional/VtsHalVibratorV1_3TargetTest.cpp @@ -24,9 +24,16 @@ #include using ::android::sp; +using ::android::hardware::hidl_enum_range; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::vibrator::V1_0::EffectStrength; using ::android::hardware::vibrator::V1_0::Status; +using ::android::hardware::vibrator::V1_3::Effect; using ::android::hardware::vibrator::V1_3::IVibrator; +#define EXPECT_OK(ret) ASSERT_TRUE((ret).isOk()) + // Test environment for Vibrator HIDL HAL. class VibratorHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { public: @@ -71,6 +78,74 @@ TEST_F(VibratorHidlTest_1_3, SetExternalControlReturnUnsupportedOperationIfNotSu } } +static void validatePerformEffectUnsupportedOperation(Status status, uint32_t lengthMs) { + ASSERT_EQ(Status::UNSUPPORTED_OPERATION, status); + ASSERT_EQ(static_cast(0), lengthMs) + << "Effects that return UNSUPPORTED_OPERATION must have a duration of zero"; +} + +static void validatePerformEffect(Status status, uint32_t lengthMs) { + ASSERT_TRUE(status == Status::OK || status == Status::UNSUPPORTED_OPERATION); + if (status == Status::OK) { + ASSERT_LT(static_cast(0), lengthMs) + << "Effects that return OK must return a positive duration"; + } else { + validatePerformEffectUnsupportedOperation(status, lengthMs); + } +} + +/* + * Test to make sure effects within the valid range return are either supported and return OK with + * a valid duration, or are unsupported and return UNSUPPORTED_OPERATION with a duration of 0. + */ +TEST_F(VibratorHidlTest_1_3, PerformEffect_1_3) { + for (const auto& effect : hidl_enum_range()) { + for (const auto& strength : hidl_enum_range()) { + EXPECT_OK(vibrator->perform_1_3(effect, strength, validatePerformEffect)); + } + } +} + +/* + * Test to make sure effect values above the valid range are rejected. + */ +TEST_F(VibratorHidlTest_1_3, PerformEffect_1_3_BadEffects_AboveValidRange) { + Effect effect = *std::prev(hidl_enum_range().end()); + Effect badEffect = static_cast(static_cast(effect) + 1); + EXPECT_OK(vibrator->perform_1_3(badEffect, EffectStrength::LIGHT, + validatePerformEffectUnsupportedOperation)); +} + +/* + * Test to make sure effect values below the valid range are rejected. + */ +TEST_F(VibratorHidlTest_1_3, PerformEffect_1_3_BadEffects_BelowValidRange) { + Effect effect = *hidl_enum_range().begin(); + Effect badEffect = static_cast(static_cast(effect) - 1); + EXPECT_OK(vibrator->perform_1_3(badEffect, EffectStrength::LIGHT, + validatePerformEffectUnsupportedOperation)); +} + +/* + * Test to make sure strength values above the valid range are rejected. + */ +TEST_F(VibratorHidlTest_1_3, PerformEffect_1_3_BadStrength_AboveValidRange) { + EffectStrength strength = *std::prev(hidl_enum_range().end()); + EffectStrength badStrength = static_cast(static_cast(strength) + 1); + EXPECT_OK(vibrator->perform_1_3(Effect::THUD, badStrength, + validatePerformEffectUnsupportedOperation)); +} + +/* + * Test to make sure strength values below the valid range are rejected. + */ +TEST_F(VibratorHidlTest_1_3, PerformEffect_1_3_BadStrength_BelowValidRange) { + EffectStrength strength = *hidl_enum_range().begin(); + EffectStrength badStrength = static_cast(static_cast(strength) - 1); + EXPECT_OK(vibrator->perform_1_3(Effect::THUD, badStrength, + validatePerformEffectUnsupportedOperation)); +} + int main(int argc, char** argv) { ::testing::AddGlobalTestEnvironment(VibratorHidlEnvironment::Instance()); ::testing::InitGoogleTest(&argc, argv); From 58d1b2a036aed20aad035671d2d0d234f06ff7c6 Mon Sep 17 00:00:00 2001 From: Ahmed ElArabawy Date: Thu, 21 Mar 2019 17:04:23 -0700 Subject: [PATCH 565/718] Wifi: Update the Latency mode API documentation This commit updates the documentation for the HAL API setLatencyMode(). It also updates the current.txt with the IWifiChip new hash. Bug: 124459516 Test: None Change-Id: I018e0237807aab70f7587d5fd7517d64352140f7 --- current.txt | 2 +- wifi/1.3/IWifiChip.hal | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/current.txt b/current.txt index 88d2e1132a..2ec77c9112 100644 --- a/current.txt +++ b/current.txt @@ -546,7 +546,7 @@ b47f90302595874dfddb19bd05a054727bf18b3a930bc810ea14957b859ae8bf android.hardwar 3bbaa8cbc5d6b1da21f5509b2b641e05fc7eeca1354751eb1bb3cf37f89aa32f android.hardware.usb@1.2::types 92c1a726c80970d623b891f7c2f9a989a40a15ee1244092b49f4eb6adcdce4e9 android.hardware.vibrator@1.3::IVibrator f19832856a3f53ced5ef91d3cc630a57fb7f4d4ce15f364dbed09099b89f6830 android.hardware.wifi@1.3::IWifi -7c6799c19bfdb3dec016b751556fe246cf7d37191ee7bb82a0091ab9fbf6f2fb android.hardware.wifi@1.3::IWifiChip +64be084b6e1ef330b75fa916593dc0b94b0ec7a16d5cfaa5a31e6c9143c8288d android.hardware.wifi@1.3::IWifiChip 3bef30e8b61ab050c0f6fd26572712be5ebb7707d624c9aa6c74bbb9d6a5b4a9 android.hardware.wifi@1.3::IWifiStaIface f3dbd8dd0d6333c005610288a4785d0ef79a72a7bbe6d0a46d46fa89fc886f1e android.hardware.wifi@1.3::types 2fae61e962f68091335f7ff4581fcfe2e28ce7f6132d7a712fa13d7965543e4d android.hardware.wifi.hostapd@1.1::IHostapd diff --git a/wifi/1.3/IWifiChip.hal b/wifi/1.3/IWifiChip.hal index fc6dbac40e..72cee899b0 100644 --- a/wifi/1.3/IWifiChip.hal +++ b/wifi/1.3/IWifiChip.hal @@ -65,10 +65,14 @@ interface IWifiChip extends @1.2::IWifiChip { /** * API to set the wifi latency mode * - * Latency mode determines whether or not to optimize for reducing wifi - * latency as a tradeoff with other wifi functionality such as scanning, - * roaming, etc. This optimization is suitable for some applications such - * as gaming and virtual reality applications. + * The latency mode is a hint to the HAL to enable or disable Wi-Fi latency + * optimization. The optimization should be enabled if the mode is set to |LOW| + * and should be disabled if the mode is set to |NORMAL|. + * Wi-Fi latency optimization may trade-off latency against other Wi-Fi + * functionality such as scanning, roaming, etc. but it should not result in + * completely halting this functionality. + * + * The low latency mode targets applications such as gaming and virtual reality. */ setLatencyMode(LatencyMode mode) generates (WifiStatus status); From 632b4bd9b0ba0b26a40c3f81fad724f8c07179fe Mon Sep 17 00:00:00 2001 From: David Gross Date: Fri, 15 Mar 2019 17:26:32 -0700 Subject: [PATCH 566/718] Add @V1_2::Capabilities to support all non extension operand types. Performance information in Capabilities is used by the runtime when it selects the appropriate processor to distribute work to. Prior to this CL, Capabilities can only distinguish between float and non-float data types -- so, for example, float16 and float32 performance is considered to be the same, and performance for all non-float data types is considered to be the same. Bug: 124041010 Test: NeuralNetworksTest_static Test: VtsHalNeuralnetworksV1_2TargetTest --hal_service_instance=android.hardware.neuralnetworks@1.2::IDevice/sample-all Change-Id: I83fb5920c1c75afbd7750d793a0b8f3e72a0552c --- current.txt | 4 +-- neuralnetworks/1.2/IDevice.hal | 11 +++++++ neuralnetworks/1.2/types.hal | 33 +++++++++++++++++++ .../1.2/vts/functional/BasicTests.cpp | 27 ++++++++++++++- 4 files changed, 72 insertions(+), 3 deletions(-) diff --git a/current.txt b/current.txt index 23b019e8a5..d68bde5fd0 100644 --- a/current.txt +++ b/current.txt @@ -508,11 +508,11 @@ b9422a9aca84df1ff9623dc12c0562abce97716e28d63a965f2bfb88f9ad9607 android.hardwar 4cb139f729c29d8d6f4ecdab149c4feb571dad8a06e56cd57fcb52e70208bab4 android.hardware.media.c2@1.0::types 4880af120fc1640225abdc2c60bda6d79617d73484d5124913c7278af3b11e2d android.hardware.neuralnetworks@1.2::IBurstCallback 19877e466ad8c6ed42b38050b77bd010cf7800ff365fdc8574f45bbfda03a758 android.hardware.neuralnetworks@1.2::IBurstContext -363821d1b71147b896a08e2a570946db9b9d46f90d9f91b085bd8d3013a2b4d5 android.hardware.neuralnetworks@1.2::IDevice +b83317b66721241887d2770b5ae95fd5af1e77c5daa7530ecb08fae8892f2b43 android.hardware.neuralnetworks@1.2::IDevice 92714960d1a53fc2ec557302b41c7cc93d2636d8364a44bd0f85be0c92927ff8 android.hardware.neuralnetworks@1.2::IExecutionCallback 36e1064c869965dee533c537cefbe87e54db8bd8cd45be7e0e93e00e8a43863a android.hardware.neuralnetworks@1.2::IPreparedModel e1c734d1545e1a4ae749ff1dd9704a8e594c59aea7c8363159dc258e93e0df3b android.hardware.neuralnetworks@1.2::IPreparedModelCallback -39a6d7cf9bc7290bd90739e971ccad5f35f5cc0faea4a417b59f22c9ca9f1f2a android.hardware.neuralnetworks@1.2::types +d734c2441b602da240fa0e9afe3b612cdc9f3ae9c1db13216f957861d0673c5e android.hardware.neuralnetworks@1.2::types cf7a4ba516a638f9b82a249c91fb603042c2d9ca43fd5aad9cf6c0401ed2a5d7 android.hardware.nfc@1.2::INfc abf98c2ae08bf765db54edc8068e36d52eb558cff6706b6fd7c18c65a1f3fc18 android.hardware.nfc@1.2::types 4cb252dc6372a874aef666b92a6e9529915aa187521a700f0789065c3c702ead android.hardware.power.stats@1.0::IPowerStats diff --git a/neuralnetworks/1.2/IDevice.hal b/neuralnetworks/1.2/IDevice.hal index da9a966ba1..d83f9e6758 100644 --- a/neuralnetworks/1.2/IDevice.hal +++ b/neuralnetworks/1.2/IDevice.hal @@ -75,6 +75,17 @@ interface IDevice extends @1.1::IDevice { */ getType() generates (ErrorStatus status, DeviceType type); + /** + * Gets the capabilities of a driver. + * + * @return status Error status of the call, must be: + * - NONE if successful + * - DEVICE_UNAVAILABLE if driver is offline or busy + * - GENERAL_FAILURE if there is an unspecified error + * @return capabilities Capabilities of the driver. + */ + getCapabilities_1_2() generates (ErrorStatus status, Capabilities capabilities); + /** * Gets information about extensions supported by the driver implementation. * diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal index 28d01192da..7691642f75 100644 --- a/neuralnetworks/1.2/types.hal +++ b/neuralnetworks/1.2/types.hal @@ -4617,6 +4617,39 @@ enum DeviceType : int32_t { ACCELERATOR = 4, }; +/** + * The capabilities of a driver. + * + * Performance of an operation comes from the type of its first operand. + * This represents performance for non extension operand types. + */ +struct Capabilities { + /** + * Driver performance when operating on float32 data but performing + * calculations with range and/or precision as low as that of the IEEE + * 754 16-bit floating-point format. + */ + PerformanceInfo relaxedFloat32toFloat16PerformanceScalar; + PerformanceInfo relaxedFloat32toFloat16PerformanceTensor; + + /** + * Driver performance when operating on a particular data type. + * In the case of float32 data, this is used when the calculations + * are not relaxed. + */ + struct OperandPerformance { + OperandType type; + PerformanceInfo info; + }; + + /** + * Performance by operand type. Must be sorted by OperandType. + * If a particular OperandType is not present in operandPerformance, + * its performance is treated as { .execTime = FLT_MAX, .powerUsage = FLT_MAX }. + */ + vec operandPerformance; +}; + /** * Describes one operation of the model's graph. */ diff --git a/neuralnetworks/1.2/vts/functional/BasicTests.cpp b/neuralnetworks/1.2/vts/functional/BasicTests.cpp index 6fb16c2033..5c269df275 100644 --- a/neuralnetworks/1.2/vts/functional/BasicTests.cpp +++ b/neuralnetworks/1.2/vts/functional/BasicTests.cpp @@ -25,7 +25,7 @@ namespace V1_2 { namespace vts { namespace functional { -using V1_1::Capabilities; +using V1_0::PerformanceInfo; // create device test TEST_F(NeuralnetworksHidlTest, CreateDevice) {} @@ -37,6 +37,31 @@ TEST_F(NeuralnetworksHidlTest, StatusTest) { EXPECT_EQ(DeviceStatus::AVAILABLE, static_cast(status)); } +// initialization +TEST_F(NeuralnetworksHidlTest, GetCapabilitiesTest) { + using OperandPerformance = Capabilities::OperandPerformance; + Return ret = device->getCapabilities_1_2([](ErrorStatus status, + const Capabilities& capabilities) { + EXPECT_EQ(ErrorStatus::NONE, status); + + auto isPositive = [](const PerformanceInfo& perf) { + return perf.execTime > 0.0f && perf.powerUsage > 0.0f; + }; + + EXPECT_TRUE(isPositive(capabilities.relaxedFloat32toFloat16PerformanceScalar)); + EXPECT_TRUE(isPositive(capabilities.relaxedFloat32toFloat16PerformanceTensor)); + const auto& opPerf = capabilities.operandPerformance; + EXPECT_TRUE(std::all_of( + opPerf.begin(), opPerf.end(), + [isPositive](const OperandPerformance& a) { return isPositive(a.info); })); + EXPECT_TRUE(std::is_sorted(opPerf.begin(), opPerf.end(), + [](const OperandPerformance& a, const OperandPerformance& b) { + return a.type < b.type; + })); + }); + EXPECT_TRUE(ret.isOk()); +} + // device version test TEST_F(NeuralnetworksHidlTest, GetDeviceVersionStringTest) { Return ret = device->getVersionString([](ErrorStatus status, const hidl_string& version) { From 4b5dce8bb57179809c558b8b090d8001a89b8d05 Mon Sep 17 00:00:00 2001 From: Pawin Vongmasa Date: Fri, 22 Mar 2019 07:45:36 -0700 Subject: [PATCH 567/718] Use safe_union in FieldSupportedValues Test: make cts -j123 && cts-tradefed run cts-dev -m \ CtsMediaTestCases --compatibility:module-arg \ CtsMediaTestCases:include-annotation:\ android.platform.test.annotations.RequiresDevice Bug: 129084824 Change-Id: I9ae77a6a6697dcc508415090640a21841caba345 --- current.txt | 2 +- media/c2/1.0/Android.bp | 1 + media/c2/1.0/types.hal | 134 +++++++++++++++++----------------------- 3 files changed, 59 insertions(+), 78 deletions(-) diff --git a/current.txt b/current.txt index 99100f16cb..b818922d65 100644 --- a/current.txt +++ b/current.txt @@ -502,7 +502,7 @@ d36f747f9c9a8f2f21db2f8323c2d755dd08b34ce813932d7339979f7d490dab android.hardwar 21aa259585caaa27b6470ebcd8509aabde0ef5d039160aa6425d589cb787488b android.hardware.media.c2@1.0::IInputSink b9422a9aca84df1ff9623dc12c0562abce97716e28d63a965f2bfb88f9ad9607 android.hardware.media.c2@1.0::IInputSurface 0a786a19e6753f9774a7ca7781c2a2edfe5c0b5fa112355dfa0e50ebedeb08b9 android.hardware.media.c2@1.0::IInputSurfaceConnection -4cb139f729c29d8d6f4ecdab149c4feb571dad8a06e56cd57fcb52e70208bab4 android.hardware.media.c2@1.0::types +7d3c292ca75ec3e22a8fd4ae72d2edb0659d280257e763786e766f3429954dd1 android.hardware.media.c2@1.0::types 4880af120fc1640225abdc2c60bda6d79617d73484d5124913c7278af3b11e2d android.hardware.neuralnetworks@1.2::IBurstCallback 19877e466ad8c6ed42b38050b77bd010cf7800ff365fdc8574f45bbfda03a758 android.hardware.neuralnetworks@1.2::IBurstContext 96249c852dabeefa3a9496ecdfc44681a071c665bfbf88527bf775c88bf1ab1b android.hardware.neuralnetworks@1.2::IDevice diff --git a/media/c2/1.0/Android.bp b/media/c2/1.0/Android.bp index 7307a81e00..895e9dbbf8 100644 --- a/media/c2/1.0/Android.bp +++ b/media/c2/1.0/Android.bp @@ -27,6 +27,7 @@ hidl_interface { "android.hardware.media.omx@1.0", "android.hardware.media@1.0", "android.hidl.base@1.0", + "android.hidl.safe_union@1.0", ], gen_java: false, } diff --git a/media/c2/1.0/types.hal b/media/c2/1.0/types.hal index ec422b1f40..f4f6f2f402 100644 --- a/media/c2/1.0/types.hal +++ b/media/c2/1.0/types.hal @@ -17,6 +17,7 @@ package android.hardware.media.c2@1.0; import android.hardware.media.bufferpool@2.0::BufferStatusMessage; +import android.hidl.safe_union@1.0::Monostate; /** * Common return values for Codec2 operations. @@ -190,89 +191,68 @@ struct ParamDescriptor { */ typedef uint64_t PrimitiveValue; +/** + * Description of a set of values. + * + * If the `step` member is 0, and `num` and `denom` are both 1, the `Range` + * structure represents a closed interval bounded by `min` and `max`. + * + * Otherwise, the #ValueRange structure represents a finite sequence of numbers + * produced from the following recurrence relation: + * + * @code + * v[0] = min + * v[i] = v[i - 1] * num / denom + step ; i >= 1 + * @endcode + * + * Both the ratio `num / denom` and the value `step` must be positive. The + * last number in the sequence described by this #Range structure is the + * largest number in the sequence that is smaller than or equal to `max`. + * + * @note + * The division in the formula may truncate the result if the data type of + * these values is an integral type. + */ +struct ValueRange { + /** + * Lower end of the range (inclusive). + */ + PrimitiveValue min; + /** + * Upper end of the range (inclusive). + */ + PrimitiveValue max; + /** + * The non-homogeneous term in the recurrence relation. + */ + PrimitiveValue step; + /** + * The numerator of the scale coefficient in the recurrence relation. + */ + PrimitiveValue num; + /** + * The denominator of the scale coefficient in the recurrence relation. + */ + PrimitiveValue denom; +}; + /* * Description of supported values for a field. * * This can be a continuous range or a discrete set of values. + * + * The intended type of values must be made clear in the context where + * `FieldSupportedValues` is used. */ -struct FieldSupportedValues { - /** - * Used if #type is `RANGE`. - * - * If the `step` member is 0, and `num` and `denom` are both 1, the `Range` - * structure represents a closed interval bounded by `min` and `max`. - * - * Otherwise, the #Range structure represents a finite sequence of numbers - * produced from the following recurrence relation: - * - * @code - * v[0] = min - * v[i] = v[i - 1] * num / denom + step ; i >= 1 - * @endcode - * - * Both the ratio `num / denom` and the value `step` must be positive. The - * last number in the sequence described by this #Range structure is the - * largest number in the sequence that is smaller than or equal to `max`. - * - * @note - * The division in the formula may truncate the result if the data type of - * these values is an integral type. - */ - struct Range { - /** - * Lower end of the range (inclusive). - */ - PrimitiveValue min; - /** - * Upper end of the range (inclusive). - */ - PrimitiveValue max; - /** - * The non-homogeneous term in the recurrence relation. - */ - PrimitiveValue step; - /** - * The numerator of the scale coefficient in the recurrence relation. - */ - PrimitiveValue num; - /** - * The denominator of the scale coefficient in the recurrence relation. - */ - PrimitiveValue denom; - }; - - enum Type : int32_t { - /** No supported values */ - EMPTY = 0, - /** Numeric range, described in a #Range structure */ - RANGE, - /** List of values */ - VALUES, - /** List of flags that can be OR-ed */ - FLAGS, - }; - /** - * Type of the supported values. - */ - Type type; - - /** - * When #type is #Type.RANGE, #range shall specify the range of possible - * values. - * - * The intended type of members of #range shall be clear in the context - * where `FieldSupportedValues` is used. - */ - Range range; - - /** - * When #type is #Type.VALUES or #Type.FLAGS, #value shall list supported - * values/flags. - * - * The intended type of components of #value shall be clear in the context - * where `FieldSupportedValues` is used. - */ +safe_union FieldSupportedValues { + /** No supported values */ + Monostate empty; + /** Numeric range, described in a #ValueRange structure */ + ValueRange range; + /** List of values */ vec values; + /** List of flags that can be OR-ed */ + vec flags; }; /** From 8c394f0fb1646f7b532da194e76f897b29fd051b Mon Sep 17 00:00:00 2001 From: Paul McLean Date: Fri, 22 Mar 2019 10:40:16 -0600 Subject: [PATCH 568/718] API changes in MicrophoneDirection Bug: 128523813 Test: build, flash, testbed app. Change-Id: I1bcc9bb667224cebb401d9506853d5c650e7d68d --- audio/5.0/IStreamIn.hal | 8 ++++++++ current.txt | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/audio/5.0/IStreamIn.hal b/audio/5.0/IStreamIn.hal index b042960b17..e15b0347f5 100644 --- a/audio/5.0/IStreamIn.hal +++ b/audio/5.0/IStreamIn.hal @@ -169,6 +169,10 @@ interface IStreamIn extends IStream { /** * Specifies the logical microphone (for processing). * + * If the feature is not supported an error should be returned + * If multiple microphones are present, this should be treated as a preference + * for their combined direction. + * * Optional method * * @param Direction constant @@ -180,6 +184,10 @@ interface IStreamIn extends IStream { /** * Specifies the zoom factor for the selected microphone (for processing). * + * If the feature is not supported an error should be returned + * If multiple microphones are present, this should be treated as a preference + * for their combined field dimension. + * * Optional method * * @param the desired field dimension of microphone capture. Range is from -1 (wide angle), diff --git a/current.txt b/current.txt index 3801d0baa8..e0923d6533 100644 --- a/current.txt +++ b/current.txt @@ -416,7 +416,7 @@ dfdb4d04b65dc363e5621c85bfdf3023c277b75c31d821d8e71b3f44f198e214 android.hardwar 0a911297821854985cfcdb17b63d7948af0f0f51ce8c68cc86367c185bbc772e android.hardware.audio@5.0::IDevicesFactory ce2e8c6c8559fd42bd69e0dee27b4d9c93cd9b2eff487b4e6b6395b6a1a993d6 android.hardware.audio@5.0::IPrimaryDevice 4a4e5e5d9357004a1256bde8d36010ee00c51cea811a1c1e0dd969a9fc0bf862 android.hardware.audio@5.0::IStream -e05e48c583de14c1e5a6fa9d48ea50244e3e0924b76b342374e7471dc8007ba9 android.hardware.audio@5.0::IStreamIn +b9d41ff4031266de1ecef394a8a64de7d857634dd08dc6be855fca2fe3075975 android.hardware.audio@5.0::IStreamIn 9471b12b1c255bb530695720bc4174bd74987b75b1f820854af8944bc8c215c9 android.hardware.audio@5.0::IStreamOut 1b0500367ed2b32a841667ac3200edf3d3a164e8004aca445ff1b085ac831e93 android.hardware.audio@5.0::IStreamOutCallback 83e365479cc77d8717c155e1787ee668cd2ae4c557b467cf75b8e7cd53697ad8 android.hardware.audio@5.0::types From a244321f7271283272f54678e648cf091b0e7e77 Mon Sep 17 00:00:00 2001 From: "Harpreet \"Eli\" Sangha" Date: Mon, 25 Mar 2019 14:08:59 +0900 Subject: [PATCH 569/718] vibrator: example: Fix out-of-scope memory access. Bug: 129091875 Test: VTS Change-Id: I64685e6e8982db1a33c8322e1df7d266fa367eaf Signed-off-by: Harpreet "Eli" Sangha --- vibrator/1.3/example/Vibrator.cpp | 6 +++--- vibrator/1.3/example/Vibrator.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/vibrator/1.3/example/Vibrator.cpp b/vibrator/1.3/example/Vibrator.cpp index eb50187fe9..2137789ce9 100644 --- a/vibrator/1.3/example/Vibrator.cpp +++ b/vibrator/1.3/example/Vibrator.cpp @@ -102,7 +102,7 @@ Return Vibrator::perform_1_3(Effect effect, EffectStrength strength, perfo uint32_t ms; Status status; - ALOGI("Perform: Effect %s\n", effectToName(effect)); + ALOGI("Perform: Effect %s\n", effectToName(effect).c_str()); amplitude = strengthToAmplitude(strength); setAmplitude(amplitude); @@ -178,8 +178,8 @@ void Vibrator::timerCallback(union sigval sigval) { static_cast(sigval.sival_ptr)->timeout(); } -const char* Vibrator::effectToName(Effect effect) { - return toString(effect).c_str(); +const std::string Vibrator::effectToName(Effect effect) { + return toString(effect); } uint32_t Vibrator::effectToMs(Effect effect) { diff --git a/vibrator/1.3/example/Vibrator.h b/vibrator/1.3/example/Vibrator.h index 8cf0b1eb05..c11806158f 100644 --- a/vibrator/1.3/example/Vibrator.h +++ b/vibrator/1.3/example/Vibrator.h @@ -59,7 +59,7 @@ class Vibrator : public IVibrator { void timeout(); static void timerCallback(union sigval sigval); - static const char* effectToName(Effect effect); + static const std::string effectToName(Effect effect); static uint32_t effectToMs(Effect effect); static uint8_t strengthToAmplitude(EffectStrength strength); From 79755bc57077d60d3d612849bed677463c5d3c46 Mon Sep 17 00:00:00 2001 From: "Harpreet \"Eli\" Sangha" Date: Mon, 25 Mar 2019 16:42:28 +0900 Subject: [PATCH 570/718] vibrator: example: Fix New Test Failures Bug: 129091875 Test: VTS Change-Id: Ib57457095c8ff30aff45a5909f2408d144980976 Signed-off-by: Harpreet "Eli" Sangha --- vibrator/1.3/example/Vibrator.cpp | 22 +++++++++++++++++----- vibrator/1.3/example/Vibrator.h | 4 ++-- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/vibrator/1.3/example/Vibrator.cpp b/vibrator/1.3/example/Vibrator.cpp index 2137789ce9..0cb37e6a36 100644 --- a/vibrator/1.3/example/Vibrator.cpp +++ b/vibrator/1.3/example/Vibrator.cpp @@ -100,14 +100,22 @@ Return Vibrator::setExternalControl(bool enabled) { Return Vibrator::perform_1_3(Effect effect, EffectStrength strength, perform_cb _hidl_cb) { uint8_t amplitude; uint32_t ms; - Status status; + Status status = Status::OK; ALOGI("Perform: Effect %s\n", effectToName(effect).c_str()); - amplitude = strengthToAmplitude(strength); + amplitude = strengthToAmplitude(strength, &status); + if (status != Status::OK) { + _hidl_cb(status, 0); + return Void(); + } setAmplitude(amplitude); - ms = effectToMs(effect); + ms = effectToMs(effect, &status); + if (status != Status::OK) { + _hidl_cb(status, 0); + return Void(); + } status = activate(ms); _hidl_cb(status, ms); @@ -182,7 +190,7 @@ const std::string Vibrator::effectToName(Effect effect) { return toString(effect); } -uint32_t Vibrator::effectToMs(Effect effect) { +uint32_t Vibrator::effectToMs(Effect effect, Status* status) { switch (effect) { case Effect::CLICK: return 10; @@ -228,9 +236,11 @@ uint32_t Vibrator::effectToMs(Effect effect) { case Effect::RINGTONE_15: return 30000; } + *status = Status::UNSUPPORTED_OPERATION; + return 0; } -uint8_t Vibrator::strengthToAmplitude(EffectStrength strength) { +uint8_t Vibrator::strengthToAmplitude(EffectStrength strength, Status* status) { switch (strength) { case EffectStrength::LIGHT: return 128; @@ -239,6 +249,8 @@ uint8_t Vibrator::strengthToAmplitude(EffectStrength strength) { case EffectStrength::STRONG: return 255; } + *status = Status::UNSUPPORTED_OPERATION; + return 0; } } // namespace implementation diff --git a/vibrator/1.3/example/Vibrator.h b/vibrator/1.3/example/Vibrator.h index c11806158f..64e8e1b76d 100644 --- a/vibrator/1.3/example/Vibrator.h +++ b/vibrator/1.3/example/Vibrator.h @@ -60,8 +60,8 @@ class Vibrator : public IVibrator { static void timerCallback(union sigval sigval); static const std::string effectToName(Effect effect); - static uint32_t effectToMs(Effect effect); - static uint8_t strengthToAmplitude(EffectStrength strength); + static uint32_t effectToMs(Effect effect, Status* status); + static uint8_t strengthToAmplitude(EffectStrength strength, Status* status); private: bool mEnabled{false}; From 1cd82a8cf28a5c0c8e9e0fcd2769e91fb50274b3 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Mon, 25 Mar 2019 13:51:28 -0700 Subject: [PATCH 571/718] wifi(implementation): Fix unit test failures ag/6722341 caused some unit test failures. Fixing them. Bug: 127715974 Test: ./data/android.hardware.wifi@1.0-service-tests Change-Id: Ib504cf55b9990dba081eb1b07bc32508e09ad0a6 --- wifi/1.3/default/tests/mock_wifi_legacy_hal.h | 4 ++++ wifi/1.3/default/wifi_legacy_hal.h | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/wifi/1.3/default/tests/mock_wifi_legacy_hal.h b/wifi/1.3/default/tests/mock_wifi_legacy_hal.h index deb3a5ae4b..65fd115781 100644 --- a/wifi/1.3/default/tests/mock_wifi_legacy_hal.h +++ b/wifi/1.3/default/tests/mock_wifi_legacy_hal.h @@ -39,6 +39,10 @@ class MockWifiLegacyHal : public WifiLegacyHal { MOCK_METHOD2(registerRadioModeChangeCallbackHandler, wifi_error(const std::string&, const on_radio_mode_change_callback&)); + MOCK_METHOD1(getFirmwareVersion, std::pair( + const std::string& iface_name)); + MOCK_METHOD1(getDriverVersion, std::pair( + const std::string& iface_name)); MOCK_METHOD2(nanRegisterCallbackHandlers, wifi_error(const std::string&, const NanCallbackHandlers&)); MOCK_METHOD2(nanDisableRequest, diff --git a/wifi/1.3/default/wifi_legacy_hal.h b/wifi/1.3/default/wifi_legacy_hal.h index 70a919f8ce..4d6beb3da1 100644 --- a/wifi/1.3/default/wifi_legacy_hal.h +++ b/wifi/1.3/default/wifi_legacy_hal.h @@ -184,9 +184,9 @@ class WifiLegacyHal { // Checks if legacy HAL has successfully started bool isStarted(); // Wrappers for all the functions in the legacy HAL function table. - std::pair getDriverVersion( + virtual std::pair getDriverVersion( const std::string& iface_name); - std::pair getFirmwareVersion( + virtual std::pair getFirmwareVersion( const std::string& iface_name); std::pair> requestDriverMemoryDump( const std::string& iface_name); From 1f3a3a995b8d0a2a1630fe7d66a99e43a5820295 Mon Sep 17 00:00:00 2001 From: "Harpreet \"Eli\" Sangha" Date: Tue, 26 Mar 2019 13:45:23 +0900 Subject: [PATCH 572/718] vibrator: example: Initial OWNERS Test: N/A Change-Id: I2db5a52493af92a7f134e736c68cfd748ef0e721 Signed-off-by: Harpreet "Eli" Sangha --- vibrator/1.3/example/OWNERS | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 vibrator/1.3/example/OWNERS diff --git a/vibrator/1.3/example/OWNERS b/vibrator/1.3/example/OWNERS new file mode 100644 index 0000000000..4b34968b9f --- /dev/null +++ b/vibrator/1.3/example/OWNERS @@ -0,0 +1,2 @@ +eliptus@google.com +michaelwr@google.com From 68289f76f2f6d474849b5e5efef38390bc28cc5e Mon Sep 17 00:00:00 2001 From: Eran Messeri Date: Thu, 7 Mar 2019 16:16:24 +0000 Subject: [PATCH 573/718] Test importing EC P-256 keys with multiple encodings Test importing of an Elliptic Curve P-256 key, encoded using the RFC5915 specification (which requires the curve OID in key in addition to the wrapper) and the same key encoded using SEC1 (which allows omitting the OID if it's known from the wrapper). Test: atest VtsHalKeymasterV4_0TargetTest ImportKeyTest Bug: 124437839 Bug: 127799174 Change-Id: I5f5df86e55a758ed739403d830baa5c7308813a3 --- .../functional/keymaster_hidl_hal_test.cpp | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp index a9c6f6ca93..5c07532c9f 100644 --- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp +++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp @@ -172,6 +172,20 @@ string ec_521_key = hex2str( "E78E70BEFE930DB34818EE4D5C26259F5C6B8E28A652950F9F88D7B4B2C9" "D9"); +string ec_256_key_rfc5915 = + hex2str("308193020100301306072a8648ce3d020106082a8648ce3d030107047930" + "770201010420782370a8c8ce5537baadd04dcff079c8158cfa9c67b818b3" + "8e8d21c9fa750c1da00a06082a8648ce3d030107a14403420004e2cc561e" + "e701da0ad0ef0d176bb0c919d42e79c393fdc1bd6c4010d85cf2cf8e68c9" + "05464666f98dad4f01573ba81078b3428570a439ba3229fbc026c550682f"); + +string ec_256_key_sec1 = + hex2str("308187020100301306072a8648ce3d020106082a8648ce3d030107046d30" + "6b0201010420782370a8c8ce5537baadd04dcff079c8158cfa9c67b818b3" + "8e8d21c9fa750c1da14403420004e2cc561ee701da0ad0ef0d176bb0c919" + "d42e79c393fdc1bd6c4010d85cf2cf8e68c905464666f98dad4f01573ba8" + "1078b3428570a439ba3229fbc026c550682f"); + struct RSA_Delete { void operator()(RSA* p) { RSA_free(p); } }; @@ -1777,6 +1791,56 @@ TEST_F(ImportKeyTest, EcdsaSuccess) { VerifyMessage(message, signature, params); } +/* + * ImportKeyTest.EcdsaP256RFC5915Success + * + * Verifies that importing and using an ECDSA P-256 key pair encoded using RFC5915 works correctly. + */ +TEST_F(ImportKeyTest, EcdsaP256RFC5915Success) { + ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder() + .Authorization(TAG_NO_AUTH_REQUIRED) + .EcdsaSigningKey(256) + .Digest(Digest::SHA_2_256), + KeyFormat::PKCS8, ec_256_key_rfc5915)); + + CheckCryptoParam(TAG_ALGORITHM, Algorithm::EC); + CheckCryptoParam(TAG_KEY_SIZE, 256U); + CheckCryptoParam(TAG_DIGEST, Digest::SHA_2_256); + CheckCryptoParam(TAG_EC_CURVE, EcCurve::P_256); + + CheckOrigin(); + + string message(32, 'a'); + auto params = AuthorizationSetBuilder().Digest(Digest::SHA_2_256); + string signature = SignMessage(message, params); + VerifyMessage(message, signature, params); +} + +/* + * ImportKeyTest.EcdsaP256SEC1Success + * + * Verifies that importing and using an ECDSA P-256 key pair encoded using SEC1 works correctly. + */ +TEST_F(ImportKeyTest, EcdsaP256SEC1Success) { + ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder() + .Authorization(TAG_NO_AUTH_REQUIRED) + .EcdsaSigningKey(256) + .Digest(Digest::SHA_2_256), + KeyFormat::PKCS8, ec_256_key_sec1)); + + CheckCryptoParam(TAG_ALGORITHM, Algorithm::EC); + CheckCryptoParam(TAG_KEY_SIZE, 256U); + CheckCryptoParam(TAG_DIGEST, Digest::SHA_2_256); + CheckCryptoParam(TAG_EC_CURVE, EcCurve::P_256); + + CheckOrigin(); + + string message(32, 'a'); + auto params = AuthorizationSetBuilder().Digest(Digest::SHA_2_256); + string signature = SignMessage(message, params); + VerifyMessage(message, signature, params); +} + /* * ImportKeyTest.Ecdsa521Success * From f638d0a43a42a30ed59b512d115eb2dc7c93b038 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Tue, 21 Aug 2018 14:05:21 -0700 Subject: [PATCH 574/718] wifi(vts): Don't enforce interface combination in VTS tests Devices are allowed to expose multiple AP or STA interfaces, fix the VTS tests to allow this. Bug: 112123615 Test: Compiles Change-Id: I6cf60b3cb0429ca78fe5a54d9e42ba144d7609e9 --- .../vts/functional/wifi_chip_hidl_test.cpp | 24 +++++++------------ 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp index d16f1e7777..14d592707f 100644 --- a/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp +++ b/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp @@ -348,8 +348,8 @@ TEST_F(WifiChipHidlTest, GetDebugHostWakeReasonStats) { /* * CreateApIface - * Configures the chip in AP mode and ensures that only 1 iface creation - * succeeds. The 2nd iface creation should be rejected. + * Configures the chip in AP mode and ensures that at least 1 iface creation + * succeeds. */ TEST_F(WifiChipHidlTest, CreateApIface) { configureChipForIfaceType(IfaceType::AP, true); @@ -357,8 +357,6 @@ TEST_F(WifiChipHidlTest, CreateApIface) { sp iface; EXPECT_EQ(WifiStatusCode::SUCCESS, createApIface(&iface)); EXPECT_NE(nullptr, iface.get()); - - EXPECT_EQ(WifiStatusCode::ERROR_NOT_AVAILABLE, createApIface(&iface)); } /* @@ -443,8 +441,8 @@ TEST_F(WifiChipHidlTest, RemoveApIface) { /* * CreateNanIface - * Configures the chip in NAN mode and ensures that only 1 iface creation - * succeeds. The 2nd iface creation should be rejected. + * Configures the chip in NAN mode and ensures that at least 1 iface creation + * succeeds. */ TEST_F(WifiChipHidlTest, CreateNanIface) { if (!gEnv->isNanOn) return; @@ -453,8 +451,6 @@ TEST_F(WifiChipHidlTest, CreateNanIface) { sp iface; ASSERT_EQ(WifiStatusCode::SUCCESS, createNanIface(&iface)); EXPECT_NE(nullptr, iface.get()); - - EXPECT_EQ(WifiStatusCode::ERROR_NOT_AVAILABLE, createNanIface(&iface)); } /* @@ -543,8 +539,8 @@ TEST_F(WifiChipHidlTest, RemoveNanIface) { /* * CreateP2pIface - * Configures the chip in P2P mode and ensures that only 1 iface creation - * succeeds. The 2nd iface creation should be rejected. + * Configures the chip in P2P mode and ensures that at least 1 iface creation + * succeeds. */ TEST_F(WifiChipHidlTest, CreateP2pIface) { configureChipForIfaceType(IfaceType::P2P, true); @@ -552,8 +548,6 @@ TEST_F(WifiChipHidlTest, CreateP2pIface) { sp iface; EXPECT_EQ(WifiStatusCode::SUCCESS, createP2pIface(&iface)); EXPECT_NE(nullptr, iface.get()); - - EXPECT_EQ(WifiStatusCode::ERROR_NOT_AVAILABLE, createP2pIface(&iface)); } /* @@ -638,8 +632,8 @@ TEST_F(WifiChipHidlTest, RemoveP2pIface) { /* * CreateStaIface - * Configures the chip in STA mode and ensures that only 1 iface creation - * succeeds. The 2nd iface creation should be rejected. + * Configures the chip in STA mode and ensures that at least 1 iface creation + * succeeds. */ TEST_F(WifiChipHidlTest, CreateStaIface) { configureChipForIfaceType(IfaceType::STA, true); @@ -647,8 +641,6 @@ TEST_F(WifiChipHidlTest, CreateStaIface) { sp iface; EXPECT_EQ(WifiStatusCode::SUCCESS, createStaIface(&iface)); EXPECT_NE(nullptr, iface.get()); - - EXPECT_EQ(WifiStatusCode::ERROR_NOT_AVAILABLE, createStaIface(&iface)); } /* From ef77263b2f3b6040a0e04fed2434f673f99448fb Mon Sep 17 00:00:00 2001 From: Valerie Hau Date: Wed, 27 Mar 2019 10:06:12 -0700 Subject: [PATCH 575/718] Adding negative slot index check in ComposerResources Bug: N/A Test: build, boot Change-Id: I8ab18ed8f7c322ee995abc534309b51e796276fe --- .../utils/hal/include/composer-hal/2.1/ComposerResources.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h index 3a73f845e4..1df496c065 100644 --- a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h +++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h @@ -170,7 +170,7 @@ class ComposerHandleCache { } Error lookupCache(uint32_t slot, const native_handle_t** outHandle) { - if (slot < mHandles.size()) { + if (slot >= 0 && slot < mHandles.size()) { *outHandle = mHandles[slot]; return Error::NONE; } else { @@ -180,7 +180,7 @@ class ComposerHandleCache { Error updateCache(uint32_t slot, const native_handle_t* handle, const native_handle** outReplacedHandle) { - if (slot < mHandles.size()) { + if (slot >= 0 && slot < mHandles.size()) { auto& cachedHandle = mHandles[slot]; *outReplacedHandle = cachedHandle; cachedHandle = handle; From a3e5b7fce7206ac2e84a74516ed8baeeae6f8451 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Mon, 25 Mar 2019 13:52:45 -0700 Subject: [PATCH 576/718] wifi(implementation): Pin primary STA iface to wlan0 The primary STA iface will always be pinned to wlan0. The primary AP iface will be pinned to wlan0 for devices not supporting STA + AP concurrency & wlan1 for devices supporting STA + AP concurrency. All secondary STA or AP ifaces will be allocated on a first come first service basis (the current logic). Also, refactored/renamed some of the iface combo selection logic methods to help check whether concurrency is allowed in the current mode. Bug: 128946563 Test: ./data/android.hardware.wifi@1.0-service-tests Test: Will send for full regression tests. Test: On crosshatch, ensured that STA always comes up on wlan0 & AP comes up on wlan1 regardless of the sequence of toggle followed. Change-Id: Idca8de42ce819240bf0fac2a9039d15ed4bcaf90 --- .../default/tests/wifi_chip_unit_tests.cpp | 47 +++++-- wifi/1.3/default/wifi_chip.cpp | 117 +++++++++++++++--- wifi/1.3/default/wifi_chip.h | 19 ++- 3 files changed, 149 insertions(+), 34 deletions(-) diff --git a/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp index 134563c7ea..7df9705314 100644 --- a/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp +++ b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp @@ -122,7 +122,7 @@ class WifiChipTest : public Test { void setup_MultiIfaceCombination() { // clang-format off const hidl_vec combinations = { - {{{{IfaceType::STA}, 3}}} + {{{{IfaceType::STA}, 3}, {{IfaceType::AP}, 1}}} }; const std::vector modes = { {feature_flags::chip_mode_ids::kV3, combinations} @@ -272,6 +272,13 @@ class WifiChipTest : public Test { .WillRepeatedly(testing::Return(legacy_hal::WIFI_SUCCESS)); } + void TearDown() override { + // Restore default system iface names (This should ideally be using a + // mock). + property_set("wifi.interface", "wlan0"); + property_set("wifi.concurrent.interface", "wlan1"); + } + private: sp chip_; ChipId chip_id_ = kFakeChipId; @@ -300,7 +307,7 @@ class WifiChipV1IfaceCombinationTest : public WifiChipTest { TEST_F(WifiChipV1IfaceCombinationTest, StaMode_CreateSta_ShouldSucceed) { findModeAndConfigureForIfaceType(IfaceType::STA); - ASSERT_FALSE(createIface(IfaceType::STA).empty()); + ASSERT_EQ(createIface(IfaceType::STA), "wlan0"); } TEST_F(WifiChipV1IfaceCombinationTest, StaMode_CreateP2p_ShouldSucceed) { @@ -326,7 +333,7 @@ TEST_F(WifiChipV1IfaceCombinationTest, StaMode_CreateStaP2p_ShouldSucceed) { TEST_F(WifiChipV1IfaceCombinationTest, ApMode_CreateAp_ShouldSucceed) { findModeAndConfigureForIfaceType(IfaceType::AP); - ASSERT_FALSE(createIface(IfaceType::AP).empty()); + ASSERT_EQ(createIface(IfaceType::AP), "wlan0"); } TEST_F(WifiChipV1IfaceCombinationTest, ApMode_CreateSta_ShouldFail) { @@ -359,7 +366,7 @@ class WifiChipV1_AwareIfaceCombinationTest : public WifiChipTest { TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateSta_ShouldSucceed) { findModeAndConfigureForIfaceType(IfaceType::STA); - ASSERT_FALSE(createIface(IfaceType::STA).empty()); + ASSERT_EQ(createIface(IfaceType::STA), "wlan0"); } TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateP2p_ShouldSucceed) { @@ -427,7 +434,7 @@ TEST_F(WifiChipV1_AwareIfaceCombinationTest, TEST_F(WifiChipV1_AwareIfaceCombinationTest, ApMode_CreateAp_ShouldSucceed) { findModeAndConfigureForIfaceType(IfaceType::AP); - ASSERT_FALSE(createIface(IfaceType::AP).empty()); + ASSERT_EQ(createIface(IfaceType::AP), "wlan0"); } TEST_F(WifiChipV1_AwareIfaceCombinationTest, ApMode_CreateSta_ShouldFail) { @@ -483,7 +490,7 @@ class WifiChipV2_AwareIfaceCombinationTest : public WifiChipTest { TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateSta_ShouldSucceed) { findModeAndConfigureForIfaceType(IfaceType::STA); - ASSERT_FALSE(createIface(IfaceType::STA).empty()); + ASSERT_EQ(createIface(IfaceType::STA), "wlan0"); } TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateP2p_ShouldSucceed) { @@ -498,19 +505,25 @@ TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateNan_ShouldSucceed) { TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateAp_ShouldSucceed) { findModeAndConfigureForIfaceType(IfaceType::STA); - ASSERT_FALSE(createIface(IfaceType::AP).empty()); + ASSERT_EQ(createIface(IfaceType::AP), "wlan1"); } TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaSta_ShouldFail) { findModeAndConfigureForIfaceType(IfaceType::AP); - ASSERT_FALSE(createIface(IfaceType::STA).empty()); + ASSERT_EQ(createIface(IfaceType::STA), "wlan0"); ASSERT_TRUE(createIface(IfaceType::STA).empty()); } TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaAp_ShouldSucceed) { findModeAndConfigureForIfaceType(IfaceType::AP); - ASSERT_FALSE(createIface(IfaceType::AP).empty()); - ASSERT_FALSE(createIface(IfaceType::STA).empty()); + ASSERT_EQ(createIface(IfaceType::STA), "wlan0"); + ASSERT_EQ(createIface(IfaceType::AP), "wlan1"); +} + +TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateApSta_ShouldSucceed) { + findModeAndConfigureForIfaceType(IfaceType::AP); + ASSERT_EQ(createIface(IfaceType::AP), "wlan1"); + ASSERT_EQ(createIface(IfaceType::STA), "wlan0"); } TEST_F(WifiChipV2_AwareIfaceCombinationTest, @@ -707,8 +720,8 @@ TEST_F(WifiChip_MultiIfaceTest, CreateStaWithCustomNames) { property_set("wifi.interface", "bad0"); property_set("wifi.concurrent.interface", "bad1"); findModeAndConfigureForIfaceType(IfaceType::STA); - ASSERT_EQ(createIface(IfaceType::STA), "test0"); - ASSERT_EQ(createIface(IfaceType::STA), "test1"); + ASSERT_EQ(createIface(IfaceType::STA), "bad0"); + ASSERT_EQ(createIface(IfaceType::STA), "bad1"); ASSERT_EQ(createIface(IfaceType::STA), "test2"); } @@ -724,6 +737,16 @@ TEST_F(WifiChip_MultiIfaceTest, CreateStaWithCustomAltNames) { ASSERT_EQ(createIface(IfaceType::STA), "wlan2"); } +TEST_F(WifiChip_MultiIfaceTest, CreateApStartsWithIdx1) { + findModeAndConfigureForIfaceType(IfaceType::STA); + // First AP will be slotted to wlan1. + ASSERT_EQ(createIface(IfaceType::AP), "wlan1"); + // First STA will be slotted to wlan0. + ASSERT_EQ(createIface(IfaceType::STA), "wlan0"); + // All further STA will be slotted to the remaining free indices. + ASSERT_EQ(createIface(IfaceType::STA), "wlan2"); + ASSERT_EQ(createIface(IfaceType::STA), "wlan3"); +} } // namespace implementation } // namespace V1_3 } // namespace wifi diff --git a/wifi/1.3/default/wifi_chip.cpp b/wifi/1.3/default/wifi_chip.cpp index 3697d50b5c..ce5df174a2 100644 --- a/wifi/1.3/default/wifi_chip.cpp +++ b/wifi/1.3/default/wifi_chip.cpp @@ -766,10 +766,10 @@ WifiChip::requestFirmwareDebugDumpInternal() { } std::pair> WifiChip::createApIfaceInternal() { - if (!canCurrentModeSupportIfaceOfType(IfaceType::AP)) { + if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::AP)) { return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; } - std::string ifname = allocateApOrStaIfaceName(); + std::string ifname = allocateApIfaceName(); sp iface = new WifiApIface(ifname, legacy_hal_, iface_util_, feature_flags_); ap_ifaces_.push_back(iface); @@ -813,7 +813,7 @@ WifiStatus WifiChip::removeApIfaceInternal(const std::string& ifname) { } std::pair> WifiChip::createNanIfaceInternal() { - if (!canCurrentModeSupportIfaceOfType(IfaceType::NAN)) { + if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::NAN)) { return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; } // These are still assumed to be based on wlan0. @@ -860,7 +860,7 @@ WifiStatus WifiChip::removeNanIfaceInternal(const std::string& ifname) { } std::pair> WifiChip::createP2pIfaceInternal() { - if (!canCurrentModeSupportIfaceOfType(IfaceType::P2P)) { + if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::P2P)) { return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; } std::string ifname = getP2pIfaceName(); @@ -906,10 +906,10 @@ WifiStatus WifiChip::removeP2pIfaceInternal(const std::string& ifname) { } std::pair> WifiChip::createStaIfaceInternal() { - if (!canCurrentModeSupportIfaceOfType(IfaceType::STA)) { + if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::STA)) { return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; } - std::string ifname = allocateApOrStaIfaceName(); + std::string ifname = allocateStaIfaceName(); sp iface = new WifiStaIface(ifname, legacy_hal_, iface_util_); sta_ifaces_.push_back(iface); for (const auto& callback : event_cb_handler_.getCallbacks()) { @@ -1298,8 +1298,9 @@ std::vector> WifiChip::expandIfaceCombinations( return expanded_combos; } -bool WifiChip::canExpandedIfaceCombinationSupportIfaceOfType( - const std::map& combo, IfaceType requested_type) { +bool WifiChip::canExpandedIfaceComboSupportIfaceOfTypeWithCurrentIfaces( + const std::map& expanded_combo, + IfaceType requested_type) { const auto current_combo = getCurrentIfaceCombination(); // Check if we have space for 1 more iface of |type| in this combo @@ -1309,7 +1310,7 @@ bool WifiChip::canExpandedIfaceCombinationSupportIfaceOfType( if (type == requested_type) { num_ifaces_needed++; } - size_t num_ifaces_allowed = combo.at(type); + size_t num_ifaces_allowed = expanded_combo.at(type); if (num_ifaces_needed > num_ifaces_allowed) { return false; } @@ -1320,8 +1321,10 @@ bool WifiChip::canExpandedIfaceCombinationSupportIfaceOfType( // This method does the following: // a) Enumerate all possible iface combos by expanding the current // ChipIfaceCombination. -// b) Check if the requested iface type can be added to the current mode. -bool WifiChip::canCurrentModeSupportIfaceOfType(IfaceType type) { +// b) Check if the requested iface type can be added to the current mode +// with the iface combination that is already active. +bool WifiChip::canCurrentModeSupportIfaceOfTypeWithCurrentIfaces( + IfaceType requested_type) { if (!isValidModeId(current_mode_id_)) { LOG(ERROR) << "Chip not configured in a mode yet"; return false; @@ -1330,8 +1333,8 @@ bool WifiChip::canCurrentModeSupportIfaceOfType(IfaceType type) { for (const auto& combination : combinations) { const auto expanded_combos = expandIfaceCombinations(combination); for (const auto& expanded_combo : expanded_combos) { - if (canExpandedIfaceCombinationSupportIfaceOfType(expanded_combo, - type)) { + if (canExpandedIfaceComboSupportIfaceOfTypeWithCurrentIfaces( + expanded_combo, requested_type)) { return true; } } @@ -1339,6 +1342,62 @@ bool WifiChip::canCurrentModeSupportIfaceOfType(IfaceType type) { return false; } +// Note: This does not consider ifaces already active. It only checks if the +// provided expanded iface combination can support the requested combo. +bool WifiChip::canExpandedIfaceComboSupportIfaceCombo( + const std::map& expanded_combo, + const std::map& req_combo) { + // Check if we have space for 1 more iface of |type| in this combo + for (const auto type : + {IfaceType::AP, IfaceType::NAN, IfaceType::P2P, IfaceType::STA}) { + if (req_combo.count(type) == 0) { + // Iface of "type" not in the req_combo. + continue; + } + size_t num_ifaces_needed = req_combo.at(type); + size_t num_ifaces_allowed = expanded_combo.at(type); + if (num_ifaces_needed > num_ifaces_allowed) { + return false; + } + } + return true; +} +// This method does the following: +// a) Enumerate all possible iface combos by expanding the current +// ChipIfaceCombination. +// b) Check if the requested iface combo can be added to the current mode. +// Note: This does not consider ifaces already active. It only checks if the +// current mode can support the requested combo. +bool WifiChip::canCurrentModeSupportIfaceCombo( + const std::map& req_combo) { + if (!isValidModeId(current_mode_id_)) { + LOG(ERROR) << "Chip not configured in a mode yet"; + return false; + } + const auto combinations = getCurrentModeIfaceCombinations(); + for (const auto& combination : combinations) { + const auto expanded_combos = expandIfaceCombinations(combination); + for (const auto& expanded_combo : expanded_combos) { + if (canExpandedIfaceComboSupportIfaceCombo(expanded_combo, + req_combo)) { + return true; + } + } + } + return false; +} + +// This method does the following: +// a) Enumerate all possible iface combos by expanding the current +// ChipIfaceCombination. +// b) Check if the requested iface type can be added to the current mode. +bool WifiChip::canCurrentModeSupportIfaceOfType(IfaceType requested_type) { + // Check if we can support atleast 1 iface of type. + std::map req_iface_combo; + req_iface_combo[requested_type] = 1; + return canCurrentModeSupportIfaceCombo(req_iface_combo); +} + bool WifiChip::isValidModeId(ChipModeId mode_id) { for (const auto& mode : modes_) { if (mode.id == mode_id) { @@ -1348,11 +1407,20 @@ bool WifiChip::isValidModeId(ChipModeId mode_id) { return false; } -// Return the first wlan (wlan0, wlan1 etc.) not already in use. -// This doesn't check the actual presence of these interfaces. -std::string WifiChip::allocateApOrStaIfaceName() { - for (unsigned i = 0; i < kMaxWlanIfaces; i++) { - const auto ifname = getWlanIfaceName(i); +bool WifiChip::isStaApConcurrencyAllowedInCurrentMode() { + // Check if we can support atleast 1 STA & 1 AP concurrently. + std::map req_iface_combo; + req_iface_combo[IfaceType::AP] = 1; + req_iface_combo[IfaceType::STA] = 1; + return canCurrentModeSupportIfaceCombo(req_iface_combo); +} + +// Return the first wlan (wlan0, wlan1 etc.) starting from |start_idx| +// not already in use. +// Note: This doesn't check the actual presence of these interfaces. +std::string WifiChip::allocateApOrStaIfaceName(uint32_t start_idx) { + for (unsigned idx = start_idx; idx < kMaxWlanIfaces; idx++) { + const auto ifname = getWlanIfaceName(idx); if (findUsingName(ap_ifaces_, ifname)) continue; if (findUsingName(sta_ifaces_, ifname)) continue; return ifname; @@ -1362,6 +1430,19 @@ std::string WifiChip::allocateApOrStaIfaceName() { return {}; } +// AP iface names start with idx 1 for modes supporting +// concurrent STA, else start with idx 0. +std::string WifiChip::allocateApIfaceName() { + return allocateApOrStaIfaceName( + isStaApConcurrencyAllowedInCurrentMode() ? 1 : 0); +} + +// STA iface names start with idx 0. +// Primary STA iface will always be 0. +std::string WifiChip::allocateStaIfaceName() { + return allocateApOrStaIfaceName(0); +} + bool WifiChip::writeRingbufferFilesInternal() { if (!removeOldFilesInternal()) { LOG(ERROR) << "Error occurred while deleting old tombstone files"; diff --git a/wifi/1.3/default/wifi_chip.h b/wifi/1.3/default/wifi_chip.h index 3eb0aee471..27db9a487b 100644 --- a/wifi/1.3/default/wifi_chip.h +++ b/wifi/1.3/default/wifi_chip.h @@ -224,11 +224,22 @@ class WifiChip : public V1_3::IWifiChip { std::map getCurrentIfaceCombination(); std::vector> expandIfaceCombinations( const IWifiChip::ChipIfaceCombination& combination); - bool canExpandedIfaceCombinationSupportIfaceOfType( - const std::map& combo, IfaceType type); - bool canCurrentModeSupportIfaceOfType(IfaceType type); + bool canExpandedIfaceComboSupportIfaceOfTypeWithCurrentIfaces( + const std::map& expanded_combo, + IfaceType requested_type); + bool canCurrentModeSupportIfaceOfTypeWithCurrentIfaces( + IfaceType requested_type); + bool canExpandedIfaceComboSupportIfaceCombo( + const std::map& expanded_combo, + const std::map& req_combo); + bool canCurrentModeSupportIfaceCombo( + const std::map& req_combo); + bool canCurrentModeSupportIfaceOfType(IfaceType requested_type); bool isValidModeId(ChipModeId mode_id); - std::string allocateApOrStaIfaceName(); + bool isStaApConcurrencyAllowedInCurrentMode(); + std::string allocateApOrStaIfaceName(uint32_t start_idx); + std::string allocateApIfaceName(); + std::string allocateStaIfaceName(); bool writeRingbufferFilesInternal(); ChipId chip_id_; From 6036c02d839d1027374fe2bee72924fdd76eeed7 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Wed, 27 Mar 2019 10:41:58 -0700 Subject: [PATCH 577/718] wifi(implementation): Use the active iface for chip operation For the chip level operations, the actual interface itself does not matter. So, instead of hard-coding these operations to wlan0 interface, find the first active interface to use. This will still return wlan0 if it's active, but if only AP is up (& pinned to wlan1), then it will use wlan1 instead. Bug: 129358937 Test: ./data/android.hardware.wifi@1.0-service-tests Test: Verified manually that SAR commands are now correctly sent down. Change-Id: I5a6175579027cbb45c09d32633ed81b9f72224dd --- wifi/1.3/default/tests/mock_wifi_legacy_hal.h | 6 ++ .../default/tests/wifi_chip_unit_tests.cpp | 77 +++++++++++++++---- wifi/1.3/default/wifi_chip.cpp | 55 ++++++++----- wifi/1.3/default/wifi_chip.h | 1 + wifi/1.3/default/wifi_legacy_hal.h | 6 +- 5 files changed, 107 insertions(+), 38 deletions(-) diff --git a/wifi/1.3/default/tests/mock_wifi_legacy_hal.h b/wifi/1.3/default/tests/mock_wifi_legacy_hal.h index 65fd115781..53fa8d6f4c 100644 --- a/wifi/1.3/default/tests/mock_wifi_legacy_hal.h +++ b/wifi/1.3/default/tests/mock_wifi_legacy_hal.h @@ -43,6 +43,12 @@ class MockWifiLegacyHal : public WifiLegacyHal { const std::string& iface_name)); MOCK_METHOD1(getDriverVersion, std::pair( const std::string& iface_name)); + + MOCK_METHOD2(selectTxPowerScenario, + wifi_error(const std::string& iface_name, + wifi_power_scenario scenario)); + MOCK_METHOD1(resetTxPowerScenario, + wifi_error(const std::string& iface_name)); MOCK_METHOD2(nanRegisterCallbackHandlers, wifi_error(const std::string&, const NanCallbackHandlers&)); MOCK_METHOD2(nanDisableRequest, diff --git a/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp index 7df9705314..7928328489 100644 --- a/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp +++ b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp @@ -261,6 +261,17 @@ class WifiChipTest : public Test { return success; } + sp chip_; + ChipId chip_id_ = kFakeChipId; + std::shared_ptr> legacy_hal_{ + new NiceMock}; + std::shared_ptr> + mode_controller_{new NiceMock}; + std::shared_ptr> iface_util_{ + new NiceMock}; + std::shared_ptr> + feature_flags_{new NiceMock}; + public: void SetUp() override { chip_ = new WifiChip(chip_id_, legacy_hal_, mode_controller_, @@ -278,18 +289,6 @@ class WifiChipTest : public Test { property_set("wifi.interface", "wlan0"); property_set("wifi.concurrent.interface", "wlan1"); } - - private: - sp chip_; - ChipId chip_id_ = kFakeChipId; - std::shared_ptr> legacy_hal_{ - new NiceMock}; - std::shared_ptr> - mode_controller_{new NiceMock}; - std::shared_ptr> iface_util_{ - new NiceMock}; - std::shared_ptr> - feature_flags_{new NiceMock}; }; ////////// V1 Iface Combinations //////////// @@ -452,18 +451,18 @@ TEST_F(WifiChipV1_AwareIfaceCombinationTest, ApMode_CreateNan_ShouldFail) { ASSERT_TRUE(createIface(IfaceType::NAN).empty()); } -TEST_F(WifiChipV1IfaceCombinationTest, RttControllerFlowStaModeNoSta) { +TEST_F(WifiChipV1_AwareIfaceCombinationTest, RttControllerFlowStaModeNoSta) { findModeAndConfigureForIfaceType(IfaceType::STA); ASSERT_TRUE(createRttController()); } -TEST_F(WifiChipV1IfaceCombinationTest, RttControllerFlowStaModeWithSta) { +TEST_F(WifiChipV1_AwareIfaceCombinationTest, RttControllerFlowStaModeWithSta) { findModeAndConfigureForIfaceType(IfaceType::STA); ASSERT_FALSE(createIface(IfaceType::STA).empty()); ASSERT_TRUE(createRttController()); } -TEST_F(WifiChipV1IfaceCombinationTest, RttControllerFlowApToSta) { +TEST_F(WifiChipV1_AwareIfaceCombinationTest, RttControllerFlowApToSta) { findModeAndConfigureForIfaceType(IfaceType::AP); const auto ap_iface_name = createIface(IfaceType::AP); ASSERT_FALSE(ap_iface_name.empty()); @@ -475,6 +474,30 @@ TEST_F(WifiChipV1IfaceCombinationTest, RttControllerFlowApToSta) { ASSERT_TRUE(createRttController()); } +TEST_F(WifiChipV1_AwareIfaceCombinationTest, SelectTxScenarioWithOnlySta) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_EQ(createIface(IfaceType::STA), "wlan0"); + EXPECT_CALL(*legacy_hal_, selectTxPowerScenario("wlan0", testing::_)) + .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS)); + chip_->selectTxPowerScenario_1_2( + V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF, + [](const WifiStatus& status) { + ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); + }); +} + +TEST_F(WifiChipV1_AwareIfaceCombinationTest, SelectTxScenarioWithOnlyAp) { + findModeAndConfigureForIfaceType(IfaceType::AP); + ASSERT_EQ(createIface(IfaceType::AP), "wlan0"); + EXPECT_CALL(*legacy_hal_, selectTxPowerScenario("wlan0", testing::_)) + .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS)); + chip_->selectTxPowerScenario_1_2( + V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF, + [](const WifiStatus& status) { + ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); + }); +} + ////////// V2 + Aware Iface Combinations //////////// // Mode 1 - STA + STA/AP // - STA + P2P/NAN @@ -653,6 +676,30 @@ TEST_F(WifiChipV2_AwareIfaceCombinationTest, RttControllerFlow) { ASSERT_TRUE(createRttController()); } +TEST_F(WifiChipV2_AwareIfaceCombinationTest, SelectTxScenarioWithOnlySta) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_EQ(createIface(IfaceType::STA), "wlan0"); + EXPECT_CALL(*legacy_hal_, selectTxPowerScenario("wlan0", testing::_)) + .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS)); + chip_->selectTxPowerScenario_1_2( + V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF, + [](const WifiStatus& status) { + ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); + }); +} + +TEST_F(WifiChipV2_AwareIfaceCombinationTest, SelectTxScenarioWithOnlyAp) { + findModeAndConfigureForIfaceType(IfaceType::AP); + ASSERT_EQ(createIface(IfaceType::AP), "wlan1"); + EXPECT_CALL(*legacy_hal_, selectTxPowerScenario("wlan1", testing::_)) + .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS)); + chip_->selectTxPowerScenario_1_2( + V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF, + [](const WifiStatus& status) { + ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); + }); +} + ////////// V1 Iface Combinations when AP creation is disabled ////////// class WifiChipV1_AwareDisabledApIfaceCombinationTest : public WifiChipTest { public: diff --git a/wifi/1.3/default/wifi_chip.cpp b/wifi/1.3/default/wifi_chip.cpp index ce5df174a2..957b22b4a7 100644 --- a/wifi/1.3/default/wifi_chip.cpp +++ b/wifi/1.3/default/wifi_chip.cpp @@ -641,7 +641,7 @@ std::pair WifiChip::getCapabilitiesInternal_1_3() { legacy_hal::wifi_error legacy_status; uint32_t legacy_feature_set; uint32_t legacy_logger_feature_set; - const auto ifname = getWlanIfaceName(0); + const auto ifname = getFirstActiveWlanIfaceName(); std::tie(legacy_status, legacy_feature_set) = legacy_hal_.lock()->getSupportedFeatureSet(ifname); if (legacy_status != legacy_hal::WIFI_SUCCESS) { @@ -709,7 +709,7 @@ WifiChip::requestChipDebugInfoInternal() { IWifiChip::ChipDebugInfo result; legacy_hal::wifi_error legacy_status; std::string driver_desc; - const auto ifname = getWlanIfaceName(0); + const auto ifname = getFirstActiveWlanIfaceName(); std::tie(legacy_status, driver_desc) = legacy_hal_.lock()->getDriverVersion(ifname); if (legacy_status != legacy_hal::WIFI_SUCCESS) { @@ -741,7 +741,8 @@ WifiChip::requestDriverDebugDumpInternal() { legacy_hal::wifi_error legacy_status; std::vector driver_dump; std::tie(legacy_status, driver_dump) = - legacy_hal_.lock()->requestDriverMemoryDump(getWlanIfaceName(0)); + legacy_hal_.lock()->requestDriverMemoryDump( + getFirstActiveWlanIfaceName()); if (legacy_status != legacy_hal::WIFI_SUCCESS) { LOG(ERROR) << "Failed to get driver debug dump: " << legacyErrorToString(legacy_status); @@ -756,7 +757,8 @@ WifiChip::requestFirmwareDebugDumpInternal() { legacy_hal::wifi_error legacy_status; std::vector firmware_dump; std::tie(legacy_status, firmware_dump) = - legacy_hal_.lock()->requestFirmwareMemoryDump(getWlanIfaceName(0)); + legacy_hal_.lock()->requestFirmwareMemoryDump( + getFirstActiveWlanIfaceName()); if (legacy_status != legacy_hal::WIFI_SUCCESS) { LOG(ERROR) << "Failed to get firmware debug dump: " << legacyErrorToString(legacy_status); @@ -817,7 +819,7 @@ std::pair> WifiChip::createNanIfaceInternal() { return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; } // These are still assumed to be based on wlan0. - std::string ifname = getWlanIfaceName(0); + std::string ifname = getFirstActiveWlanIfaceName(); sp iface = new WifiNanIface(ifname, legacy_hal_); nan_ifaces_.push_back(iface); for (const auto& callback : event_cb_handler_.getCallbacks()) { @@ -959,8 +961,8 @@ WifiChip::createRttControllerInternal(const sp& bound_iface) { "(and RTT by extension)"; return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; } - sp rtt = - new WifiRttController(getWlanIfaceName(0), bound_iface, legacy_hal_); + sp rtt = new WifiRttController( + getFirstActiveWlanIfaceName(), bound_iface, legacy_hal_); rtt_controllers_.emplace_back(rtt); return {createWifiStatus(WifiStatusCode::SUCCESS), rtt}; } @@ -971,7 +973,7 @@ WifiChip::getDebugRingBuffersStatusInternal() { std::vector legacy_ring_buffer_status_vec; std::tie(legacy_status, legacy_ring_buffer_status_vec) = - legacy_hal_.lock()->getRingBuffersStatus(getWlanIfaceName(0)); + legacy_hal_.lock()->getRingBuffersStatus(getFirstActiveWlanIfaceName()); if (legacy_status != legacy_hal::WIFI_SUCCESS) { return {createWifiStatusFromLegacyError(legacy_status), {}}; } @@ -993,7 +995,7 @@ WifiStatus WifiChip::startLoggingToDebugRingBufferInternal( } legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startRingBufferLogging( - getWlanIfaceName(0), ring_name, + getFirstActiveWlanIfaceName(), ring_name, static_cast< std::underlying_type::type>( verbose_level), @@ -1010,7 +1012,8 @@ WifiStatus WifiChip::forceDumpToDebugRingBufferInternal( return status; } legacy_hal::wifi_error legacy_status = - legacy_hal_.lock()->getRingBufferData(getWlanIfaceName(0), ring_name); + legacy_hal_.lock()->getRingBufferData(getFirstActiveWlanIfaceName(), + ring_name); return createWifiStatusFromLegacyError(legacy_status); } @@ -1026,7 +1029,7 @@ WifiStatus WifiChip::flushRingBufferToFileInternal() { WifiStatus WifiChip::stopLoggingToDebugRingBufferInternal() { legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->deregisterRingBufferCallbackHandler( - getWlanIfaceName(0)); + getFirstActiveWlanIfaceName()); return createWifiStatusFromLegacyError(legacy_status); } @@ -1035,7 +1038,7 @@ WifiChip::getDebugHostWakeReasonStatsInternal() { legacy_hal::wifi_error legacy_status; legacy_hal::WakeReasonStats legacy_stats; std::tie(legacy_status, legacy_stats) = - legacy_hal_.lock()->getWakeReasonStats(getWlanIfaceName(0)); + legacy_hal_.lock()->getWakeReasonStats(getFirstActiveWlanIfaceName()); if (legacy_status != legacy_hal::WIFI_SUCCESS) { return {createWifiStatusFromLegacyError(legacy_status), {}}; } @@ -1067,10 +1070,10 @@ WifiStatus WifiChip::enableDebugErrorAlertsInternal(bool enable) { } }; legacy_status = legacy_hal_.lock()->registerErrorAlertCallbackHandler( - getWlanIfaceName(0), on_alert_callback); + getFirstActiveWlanIfaceName(), on_alert_callback); } else { legacy_status = legacy_hal_.lock()->deregisterErrorAlertCallbackHandler( - getWlanIfaceName(0)); + getFirstActiveWlanIfaceName()); } return createWifiStatusFromLegacyError(legacy_status); } @@ -1078,20 +1081,20 @@ WifiStatus WifiChip::enableDebugErrorAlertsInternal(bool enable) { WifiStatus WifiChip::selectTxPowerScenarioInternal( V1_1::IWifiChip::TxPowerScenario scenario) { auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario( - getWlanIfaceName(0), + getFirstActiveWlanIfaceName(), hidl_struct_util::convertHidlTxPowerScenarioToLegacy(scenario)); return createWifiStatusFromLegacyError(legacy_status); } WifiStatus WifiChip::resetTxPowerScenarioInternal() { auto legacy_status = - legacy_hal_.lock()->resetTxPowerScenario(getWlanIfaceName(0)); + legacy_hal_.lock()->resetTxPowerScenario(getFirstActiveWlanIfaceName()); return createWifiStatusFromLegacyError(legacy_status); } WifiStatus WifiChip::setLatencyModeInternal(LatencyMode mode) { auto legacy_status = legacy_hal_.lock()->setLatencyMode( - getWlanIfaceName(0), + getFirstActiveWlanIfaceName(), hidl_struct_util::convertHidlLatencyModeToLegacy(mode)); return createWifiStatusFromLegacyError(legacy_status); } @@ -1107,7 +1110,7 @@ WifiStatus WifiChip::registerEventCallbackInternal_1_2( WifiStatus WifiChip::selectTxPowerScenarioInternal_1_2( TxPowerScenario scenario) { auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario( - getWlanIfaceName(0), + getFirstActiveWlanIfaceName(), hidl_struct_util::convertHidlTxPowerScenarioToLegacy_1_2(scenario)); return createWifiStatusFromLegacyError(legacy_status); } @@ -1197,7 +1200,7 @@ WifiStatus WifiChip::registerDebugRingBufferCallback() { }; legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->registerRingBufferCallbackHandler( - getWlanIfaceName(0), on_ring_buffer_data_callback); + getFirstActiveWlanIfaceName(), on_ring_buffer_data_callback); if (legacy_status == legacy_hal::WIFI_SUCCESS) { debug_ring_buffer_cb_registered_ = true; @@ -1231,7 +1234,7 @@ WifiStatus WifiChip::registerRadioModeChangeCallback() { }; legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->registerRadioModeChangeCallbackHandler( - getWlanIfaceName(0), on_radio_mode_change_callback); + getFirstActiveWlanIfaceName(), on_radio_mode_change_callback); return createWifiStatusFromLegacyError(legacy_status); } @@ -1415,6 +1418,18 @@ bool WifiChip::isStaApConcurrencyAllowedInCurrentMode() { return canCurrentModeSupportIfaceCombo(req_iface_combo); } +std::string WifiChip::getFirstActiveWlanIfaceName() { + for (unsigned idx = 0; idx < kMaxWlanIfaces; idx++) { + const auto ifname = getWlanIfaceName(idx); + if (findUsingName(sta_ifaces_, ifname)) return ifname; + if (findUsingName(ap_ifaces_, ifname)) return ifname; + } + // This could happen if the chip call is made before any STA/AP + // iface is created. Default to wlan0 for such cases. + LOG(WARNING) << "No active wlan interfaces in use!"; + return getWlanIfaceName(0); +} + // Return the first wlan (wlan0, wlan1 etc.) starting from |start_idx| // not already in use. // Note: This doesn't check the actual presence of these interfaces. diff --git a/wifi/1.3/default/wifi_chip.h b/wifi/1.3/default/wifi_chip.h index 27db9a487b..3d12f4c9b7 100644 --- a/wifi/1.3/default/wifi_chip.h +++ b/wifi/1.3/default/wifi_chip.h @@ -237,6 +237,7 @@ class WifiChip : public V1_3::IWifiChip { bool canCurrentModeSupportIfaceOfType(IfaceType requested_type); bool isValidModeId(ChipModeId mode_id); bool isStaApConcurrencyAllowedInCurrentMode(); + std::string getFirstActiveWlanIfaceName(); std::string allocateApOrStaIfaceName(uint32_t start_idx); std::string allocateApIfaceName(); std::string allocateStaIfaceName(); diff --git a/wifi/1.3/default/wifi_legacy_hal.h b/wifi/1.3/default/wifi_legacy_hal.h index 4d6beb3da1..5df948789c 100644 --- a/wifi/1.3/default/wifi_legacy_hal.h +++ b/wifi/1.3/default/wifi_legacy_hal.h @@ -254,9 +254,9 @@ class WifiLegacyHal { uint32_t cmd_id); wifi_error setScanningMacOui(const std::string& iface_name, const std::array& oui); - wifi_error selectTxPowerScenario(const std::string& iface_name, - wifi_power_scenario scenario); - wifi_error resetTxPowerScenario(const std::string& iface_name); + virtual wifi_error selectTxPowerScenario(const std::string& iface_name, + wifi_power_scenario scenario); + virtual wifi_error resetTxPowerScenario(const std::string& iface_name); wifi_error setLatencyMode(const std::string& iface_name, wifi_latency_mode mode); // Logger/debug functions. From 0480af9aa84beba07061cfc5279ad6cc9a75af4c Mon Sep 17 00:00:00 2001 From: Lev Proleev Date: Thu, 28 Mar 2019 15:56:33 +0000 Subject: [PATCH 578/718] LSTM: require input layer norm weights to be omitted in case CIFG is used. In case of CIFG LSTM, input layer norm weights are not used in the computation. Bug: 129126572 Test: mma Change-Id: I57bc578606132a2c44c71ab63dd7645dcc001302 --- current.txt | 2 +- neuralnetworks/1.2/types.hal | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/current.txt b/current.txt index 1108bebb2f..346454533c 100644 --- a/current.txt +++ b/current.txt @@ -512,7 +512,7 @@ b83317b66721241887d2770b5ae95fd5af1e77c5daa7530ecb08fae8892f2b43 android.hardwar 92714960d1a53fc2ec557302b41c7cc93d2636d8364a44bd0f85be0c92927ff8 android.hardware.neuralnetworks@1.2::IExecutionCallback 36e1064c869965dee533c537cefbe87e54db8bd8cd45be7e0e93e00e8a43863a android.hardware.neuralnetworks@1.2::IPreparedModel e1c734d1545e1a4ae749ff1dd9704a8e594c59aea7c8363159dc258e93e0df3b android.hardware.neuralnetworks@1.2::IPreparedModelCallback -209a5ee694b94328afb2af2768f1fe6a69148e2cbb85ec3c340a36eed818c697 android.hardware.neuralnetworks@1.2::types +9b3963253e521cca19fd81aeca83aee6dcfe3bdf2805c07cb2d3f64381709b71 android.hardware.neuralnetworks@1.2::types cf7a4ba516a638f9b82a249c91fb603042c2d9ca43fd5aad9cf6c0401ed2a5d7 android.hardware.nfc@1.2::INfc abf98c2ae08bf765db54edc8068e36d52eb558cff6706b6fd7c18c65a1f3fc18 android.hardware.nfc@1.2::types 4cb252dc6372a874aef666b92a6e9529915aa187521a700f0789065c3c702ead android.hardware.power.stats@1.0::IPowerStats diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal index 8c577961cc..67a61c1ca5 100644 --- a/neuralnetworks/1.2/types.hal +++ b/neuralnetworks/1.2/types.hal @@ -1188,8 +1188,11 @@ enum OperationType : int32_t { * value if the recurrent projection layer exists, and should otherwise * have no value. * * (API level >= 29) The four layer normalization weights either all have - * values or none of them have values. Layer normalization is used when - * values are present. + * values or none of them have values. Additionally, if CIFG is used, + * input layer normalization weights tensor is omitted and the other layer + * normalization weights either all have values or none of them have + * values. Layer normalization is used when the values of all the layer + * normalization weights are present. * * References: * From 22ba924404d8b52ce858ede88e76ef709f8abde9 Mon Sep 17 00:00:00 2001 From: Emilian Peev Date: Thu, 28 Mar 2019 09:13:20 -0700 Subject: [PATCH 579/718] Camera: Update 'ERROR_RESULT' documentation Extend "ERROR_RESULT" documentation and describe how Hal must notify about physical device result failures and logical device result failures. Bug: 128835627 Test: Successful build Change-Id: Iac5642f333634d9cc820eb727f8ff3534a47a583 --- camera/device/3.5/types.hal | 8 ++++++++ current.txt | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/camera/device/3.5/types.hal b/camera/device/3.5/types.hal index f98c60355e..6d861e2e72 100644 --- a/camera/device/3.5/types.hal +++ b/camera/device/3.5/types.hal @@ -20,6 +20,14 @@ import @3.2::StreamBuffer; import @3.4::StreamConfiguration; import @3.2::CameraBlobId; +/** + * If the result metadata cannot be produced for a physical camera device part of a logical + * multi-camera, then HAL must invoke the notification callback and pass a message with ERROR_RESULT + * code and errorStreamId that contains the stream id associated with that physical device. + * The behavior during absent result metadata remains unchanged for a logical or a non-logical + * camera device and the errorStreamId must be set to -1. + */ + /** * StreamConfiguration: * diff --git a/current.txt b/current.txt index 3801d0baa8..d163bebfdf 100644 --- a/current.txt +++ b/current.txt @@ -446,7 +446,7 @@ f7431f3e3e4e3387fc6f27a6cf423eddcd824a395dc4349d302c995ab44a9895 android.hardwar 09ab9b24994429d9bb32a3fb420b6f6be3e47eb655139a2c08c4e80d3f33ff95 android.hardware.camera.device@3.5::ICameraDevice 06237de53c42890029e3f8fe7d1480d078469c0d07608e51c37b4d485d342992 android.hardware.camera.device@3.5::ICameraDeviceCallback 08c68b196e2fc4e5ba67ba0d0917bde828a87cbe2cffec19d04733972da9eb49 android.hardware.camera.device@3.5::ICameraDeviceSession -a848f7cb3cb3d080cf175bf08412322bfddb535168253796cdf777afdbf05b38 android.hardware.camera.device@3.5::types +f9b8b388c0c76669e4b9189e4943efd2982f9bda5c10e276f96cc91bc8e818d6 android.hardware.camera.device@3.5::types f727d5f350f55a6d3354aad2feb64e43200de77c10d9d642465566bc260bb8ec android.hardware.camera.metadata@3.4::types 0fb39a7809ad1c52b3efbbed5ef4749b06c2a4f1f19cdc3efa2e3d9b28f1205c android.hardware.camera.provider@2.5::ICameraProvider f5777403d65135a5407723671bc7a864cdca83aea13ee3ce2894b95e6588ca3a android.hardware.camera.provider@2.5::types From e68668f65bbc85268cfb7e591eed2f062d36f3f5 Mon Sep 17 00:00:00 2001 From: Michael Butler Date: Thu, 28 Mar 2019 13:41:14 -0700 Subject: [PATCH 580/718] NNAPI Burst object cleanup -- VTS update This CL adapts the VTS code to the corresponding changes made in the NN utility library. Bug: 119570067 Test: mma Test: atest VtsHalNeuralnetworksV1_0Target Test: atest VtsHalNeuralnetworksV1_1Target Test: atest VtsHalNeuralnetworksV1_2Target Change-Id: I7cbc1d7025c0352aa1ed29d71dc84c2fcfc20a4f --- neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp | 2 +- neuralnetworks/1.2/vts/functional/ValidateRequest.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp index 106f33279d..9c9779a859 100644 --- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp +++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp @@ -127,7 +127,7 @@ static std::unique_ptr<::android::nn::ExecutionBurstController> CreateBurst( } static std::unique_ptr<::android::nn::ExecutionBurstController> CreateBurst( const sp& preparedModel) { - return ::android::nn::createExecutionBurstController(preparedModel, /*blocking=*/true); + return ::android::nn::ExecutionBurstController::create(preparedModel, /*blocking=*/true); } enum class Executor { ASYNC, SYNC, BURST }; enum class OutputType { FULLY_SPECIFIED, UNSPECIFIED, INSUFFICIENT }; diff --git a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp index b15f657348..09e26cc1ad 100644 --- a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp +++ b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp @@ -156,7 +156,7 @@ static void validate(const sp& preparedModel, const std::string& // create burst std::unique_ptr<::android::nn::ExecutionBurstController> burst = - ::android::nn::createExecutionBurstController(preparedModel, /*blocking=*/true); + ::android::nn::ExecutionBurstController::create(preparedModel, /*blocking=*/true); ASSERT_NE(nullptr, burst.get()); // create memory keys From 7c51e8492e7dd1350683c5847d171e9e84228156 Mon Sep 17 00:00:00 2001 From: Eino-Ville Talvala Date: Tue, 4 Dec 2018 13:35:46 -0800 Subject: [PATCH 581/718] graphics.mapper@2.0: Document previously-implicit accessRegion behavior. Existing Android framework code (and transitively, CTS test) require that an accessRegion of (0,0,0,0) is treated the same as an accessRegion covering the entire buffer, when calling lock() or lockYCbCr(). Document this so that there is no confusion about this going forward, since this requirement pre-dates the HIDL HALs. Bug: 119440345 Test: Builds Change-Id: Id16831d3da4ec3dc74dbdca18447581a50ee1193 --- current.txt | 1 + graphics/mapper/2.0/IMapper.hal | 3 +++ 2 files changed, 4 insertions(+) diff --git a/current.txt b/current.txt index 34b3555426..458e360cef 100644 --- a/current.txt +++ b/current.txt @@ -396,6 +396,7 @@ da33234403ff5d60f3473711917b9948e6484a4260b5247acdafb111193a9de2 android.hardwar d702fb01dc2a0733aa820b7eb65435ee3334f75632ef880bafd2fb8803a20a58 android.hardware.gnss@1.0::IGnssMeasurementCallback 7c7721c0f773fcf422b71a4f558545e9e36acc973e58ca51e5bd53905cf46bc0 android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer d4fea995378bb4f421b4e24ccf68cad2734ab07fe4f874a126ba558b99df5766 android.hardware.graphics.composer@2.1::IComposerClient +f7d7cb747dc01a9fdb2d39a80003b4d8df9be733d65f5842198802eb6209db69 android.hardware.graphics.mapper@2.0::IMapper 65a021fa89085b62fc96b2b6d3bef2f9103cf4d63379c68bc154fd9eef672852 android.hardware.health@1.0::types b7ecf29927055ec422ec44bf776223f07d79ad9f92ccf9becf167e62c2607e7a android.hardware.keymaster@4.0::IKeymasterDevice 574e8f1499436fb4075894dcae0b36682427956ecb114f17f1fe22d116a83c6b android.hardware.neuralnetworks@1.0::IPreparedModel diff --git a/graphics/mapper/2.0/IMapper.hal b/graphics/mapper/2.0/IMapper.hal index 45661357af..0e18f42674 100644 --- a/graphics/mapper/2.0/IMapper.hal +++ b/graphics/mapper/2.0/IMapper.hal @@ -147,6 +147,9 @@ interface IMapper { * outside of accessRegion is undefined, except that it must not cause * process termination. * + * An accessRegion of all-zeros means the entire buffer. That is, it is + * equivalent to '(0,0)-(buffer width, buffer height)'. + * * data will be filled with a pointer to the locked buffer memory. This * address will represent the top-left corner of the entire buffer, even * if accessRegion does not begin at the top-left corner. From 102e0442d89df080da69924b1cae8f04c9665a1a Mon Sep 17 00:00:00 2001 From: Michael Butler Date: Wed, 27 Mar 2019 10:59:25 -0700 Subject: [PATCH 582/718] Propagate ANNMemory_free to IBurstContext::freeMemory -- VTS update This CL adapts the VTS code to the corresponding changes made in the NN utility library. Bug: 128319484 Test: mma Test: atest VtsHalNeuralnetworksV1_0Target Test: atest VtsHalNeuralnetworksV1_1Target Test: atest VtsHalNeuralnetworksV1_2Target Change-Id: I470e8228cde2b75620ad851e4fe408f8e8329e7c --- neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp | 4 ++-- neuralnetworks/1.2/vts/functional/ValidateRequest.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp index 9c9779a859..c819b52b8f 100644 --- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp +++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp @@ -125,7 +125,7 @@ static std::unique_ptr<::android::nn::ExecutionBurstController> CreateBurst( ADD_FAILURE() << "asking for burst execution at V1_0"; return nullptr; } -static std::unique_ptr<::android::nn::ExecutionBurstController> CreateBurst( +static std::shared_ptr<::android::nn::ExecutionBurstController> CreateBurst( const sp& preparedModel) { return ::android::nn::ExecutionBurstController::create(preparedModel, /*blocking=*/true); } @@ -286,7 +286,7 @@ void EvaluatePreparedModel(sp& preparedModel, std::function controller = + const std::shared_ptr<::android::nn::ExecutionBurstController> controller = CreateBurst(preparedModel); ASSERT_NE(nullptr, controller.get()); diff --git a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp index 09e26cc1ad..870d01748a 100644 --- a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp +++ b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp @@ -155,7 +155,7 @@ static void validate(const sp& preparedModel, const std::string& SCOPED_TRACE(message + " [burst]"); // create burst - std::unique_ptr<::android::nn::ExecutionBurstController> burst = + std::shared_ptr<::android::nn::ExecutionBurstController> burst = ::android::nn::ExecutionBurstController::create(preparedModel, /*blocking=*/true); ASSERT_NE(nullptr, burst.get()); From 565cb9d2f018b97d7a9384796a72a6d74bb5b5d5 Mon Sep 17 00:00:00 2001 From: Brian Stack Date: Fri, 29 Mar 2019 15:20:47 -0700 Subject: [PATCH 583/718] Rename init script for Sensors 2.0 Mock Service Bug: 129562840 Test: Builds Change-Id: I4744a8e00657f39010d5e2a39fe38d13813e6439 --- sensors/2.0/default/Android.bp | 2 +- ...-service.rc => android.hardware.sensors@2.0-service-mock.rc} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename sensors/2.0/default/{android.hardware.sensors@2.0-service.rc => android.hardware.sensors@2.0-service-mock.rc} (100%) diff --git a/sensors/2.0/default/Android.bp b/sensors/2.0/default/Android.bp index d05634b77a..05a34bbced 100644 --- a/sensors/2.0/default/Android.bp +++ b/sensors/2.0/default/Android.bp @@ -23,7 +23,7 @@ cc_binary { "Sensor.cpp", "Sensors.cpp", ], - init_rc: ["android.hardware.sensors@2.0-service.rc"], + init_rc: ["android.hardware.sensors@2.0-service-mock.rc"], shared_libs: [ "android.hardware.sensors@1.0", "android.hardware.sensors@2.0", diff --git a/sensors/2.0/default/android.hardware.sensors@2.0-service.rc b/sensors/2.0/default/android.hardware.sensors@2.0-service-mock.rc similarity index 100% rename from sensors/2.0/default/android.hardware.sensors@2.0-service.rc rename to sensors/2.0/default/android.hardware.sensors@2.0-service-mock.rc From 57c15713c9d05852926977f2d910c46a31dd3964 Mon Sep 17 00:00:00 2001 From: Jack Yu Date: Tue, 2 Apr 2019 14:02:05 +0800 Subject: [PATCH 584/718] Update nfc@1.1 to nfc@1.2 Test: Manual Bug: 129732996 Change-Id: Ieaef96a228c8410f8c84aae89a36ac8e494eca68 --- compatibility_matrices/compatibility_matrix.current.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml index 566bd481d0..09cbc200b1 100644 --- a/compatibility_matrices/compatibility_matrix.current.xml +++ b/compatibility_matrices/compatibility_matrix.current.xml @@ -301,7 +301,7 @@ android.hardware.nfc - 1.1 + 1.2 INfc default From 8574e7fd8bea515f23c0f3127016e4b8b687925d Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Mon, 1 Apr 2019 13:30:40 -0700 Subject: [PATCH 585/718] wifi(implementation): Set prop with the first active iface This is updated whenever a new STA or AP iface is created & removed. Also, when the chip is configured. This property can be read by the rest of the system (including vendor specific HAL instances) to retrieve the active iface name. Bug: 129506593 Test: ./data/android.hardware.wifi@1.0-service-tests Test: Manually verified the property name after wifi on/off & softap on/off. Change-Id: Ic1c21fd3a1c6894c797070bf889f705e4cba6dd1 --- wifi/1.3/default/wifi_chip.cpp | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/wifi/1.3/default/wifi_chip.cpp b/wifi/1.3/default/wifi_chip.cpp index 957b22b4a7..25eb289838 100644 --- a/wifi/1.3/default/wifi_chip.cpp +++ b/wifi/1.3/default/wifi_chip.cpp @@ -41,7 +41,9 @@ constexpr size_t kMaxBufferSizeBytes = 1024 * 1024 * 3; constexpr uint32_t kMaxRingBufferFileAgeSeconds = 60 * 60 * 10; constexpr uint32_t kMaxRingBufferFileNum = 20; constexpr char kTombstoneFolderPath[] = "/data/vendor/tombstones/wifi/"; -constexpr unsigned kMaxWlanIfaces = 100; +constexpr char kActiveWlanIfaceNameProperty[] = "wifi.active.interface"; +constexpr char kNoActiveWlanIfaceNamePropertyValue[] = ""; +constexpr unsigned kMaxWlanIfaces = 5; template void invalidateAndClear(std::vector>& ifaces, sp iface) { @@ -105,6 +107,13 @@ std::string getP2pIfaceName() { return buffer.data(); } +void setActiveWlanIfaceNameProperty(const std::string& ifname) { + auto res = property_set(kActiveWlanIfaceNameProperty, ifname.data()); + if (res != 0) { + PLOG(ERROR) << "Failed to set active wlan iface name property"; + } +} + // delete files that meet either conditions: // 1. older than a predefined time in the wifi tombstone dir. // 2. Files in excess to a predefined amount, starting from the oldest ones @@ -316,13 +325,16 @@ WifiChip::WifiChip( is_valid_(true), current_mode_id_(feature_flags::chip_mode_ids::kInvalid), modes_(feature_flags.lock()->getChipModes()), - debug_ring_buffer_cb_registered_(false) {} + debug_ring_buffer_cb_registered_(false) { + setActiveWlanIfaceNameProperty(kNoActiveWlanIfaceNamePropertyValue); +} void WifiChip::invalidate() { if (!writeRingbufferFilesInternal()) { LOG(ERROR) << "Error writing files to flash"; } invalidateAndRemoveAllIfaces(); + setActiveWlanIfaceNameProperty(kNoActiveWlanIfaceNamePropertyValue); legacy_hal_.reset(); event_cb_handler_.invalidate(); is_valid_ = false; @@ -693,6 +705,7 @@ WifiStatus WifiChip::configureChipInternal( } current_mode_id_ = mode_id; LOG(INFO) << "Configured chip in mode " << mode_id; + setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName()); return status; } @@ -780,6 +793,7 @@ std::pair> WifiChip::createApIfaceInternal() { LOG(ERROR) << "Failed to invoke onIfaceAdded callback"; } } + setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName()); return {createWifiStatus(WifiStatusCode::SUCCESS), iface}; } @@ -811,6 +825,7 @@ WifiStatus WifiChip::removeApIfaceInternal(const std::string& ifname) { LOG(ERROR) << "Failed to invoke onIfaceRemoved callback"; } } + setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName()); return createWifiStatus(WifiStatusCode::SUCCESS); } @@ -919,6 +934,7 @@ std::pair> WifiChip::createStaIfaceInternal() { LOG(ERROR) << "Failed to invoke onIfaceAdded callback"; } } + setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName()); return {createWifiStatus(WifiStatusCode::SUCCESS), iface}; } @@ -950,6 +966,7 @@ WifiStatus WifiChip::removeStaIfaceInternal(const std::string& ifname) { LOG(ERROR) << "Failed to invoke onIfaceRemoved callback"; } } + setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName()); return createWifiStatus(WifiStatusCode::SUCCESS); } From cde1aa96177cc896268d61cd591b2e205721ebfd Mon Sep 17 00:00:00 2001 From: Prachi Hande Date: Thu, 28 Mar 2019 12:19:43 -0700 Subject: [PATCH 586/718] Updates to VMS Utils to support HAL Client Publisher 1. Added new API/utility functions to support publishing VMS messages from HAL client. 2. Fixed creation of offering message by adding publisher ID 3. Fixed an existing failing test from VmsHalManager_test.cpp Bug: 129475485 Bug: 129163926 Fixes: 129475485 Fixes: 129163926 Test: Added tests for all the new and updated functions in VmsUtilsTest. Ran the tests on Hawk. Change-Id: Ie561dafb86d137a4fdf3042e033f8cb133b4aca7 --- .../common/include/vhal_v2_0/VmsUtils.h | 66 +++++- .../2.0/default/common/src/VmsUtils.cpp | 127 +++++++++-- .../default/tests/VehicleHalManager_test.cpp | 1 - .../2.0/default/tests/VmsUtils_test.cpp | 197 ++++++++++++++++-- 4 files changed, 355 insertions(+), 36 deletions(-) diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h index 9e32bb5a89..258dbd97a4 100644 --- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h +++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h @@ -19,6 +19,7 @@ #include #include +#include #include @@ -42,6 +43,20 @@ struct VmsLayer { int type; int subtype; int version; + bool operator==(const VmsLayer& layer) const { + return this->type == layer.type && this->subtype == layer.subtype && + this->version == layer.version; + } + + // Class for hash function + class VmsLayerHashFunction { + public: + // Hash of the variables is returned. + size_t operator()(const VmsLayer& layer) const { + return std::hash()(layer.type) ^ std::hash()(layer.type) ^ + std::hash()(layer.type); + } + }; }; struct VmsLayerAndPublisher { @@ -66,6 +81,15 @@ struct VmsLayerOffering { std::vector dependencies; }; +// A VmsOffers refers to a list of layers that can be published by the publisher +// with the specified publisher ID. +struct VmsOffers { + VmsOffers(int publisher_id, std::vector offerings) + : publisher_id(publisher_id), offerings(offerings) {} + int publisher_id; + std::vector offerings; +}; + // A VmsSubscriptionsState is delivered in response to a // VmsMessageType.SUBSCRIPTIONS_REQUEST or on the first SUBSCRIBE or last // UNSUBSCRIBE for a layer. It indicates which layers or associated_layers are @@ -81,6 +105,9 @@ struct VmsAvailabilityState { std::vector associated_layers; }; +// Creates an empty base VMS message with some pre-populated default fields. +std::unique_ptr createBaseVmsMessage(size_t message_size); + // Creates a VehiclePropValue containing a message of type // VmsMessageType.SUBSCRIBE, specifying to the VMS service // which layer to subscribe to. @@ -106,8 +133,7 @@ std::unique_ptr createUnsubscribeToPublisherMessage( // Creates a VehiclePropValue containing a message of type // VmsMessageType.OFFERING, specifying to the VMS service which layers are being // offered and their dependencies, if any. -std::unique_ptr createOfferingMessage( - const std::vector& offering); +std::unique_ptr createOfferingMessage(const VmsOffers& offers); // Creates a VehiclePropValue containing a message of type // VmsMessageType.AVAILABILITY_REQUEST. @@ -143,8 +169,40 @@ VmsMessageType parseMessageType(const VehiclePropValue& value); // function to ParseFromString. std::string parseData(const VehiclePropValue& value); -// TODO(aditin): Need to implement additional parsing functions per message -// type. +// Creates a VehiclePropValue containing a message of type +// VmsMessageType.PUBLISHER_ID_REQUEST with the given publisher information. +// Returns a nullptr if the input is empty. +std::unique_ptr createPublisherIdRequest( + const std::string& vms_provider_description); + +// Returns the publisher ID by parsing the VehiclePropValue containing the ID. +// Returns null if the message is invalid. +int32_t parsePublisherIdResponse(const VehiclePropValue& publisher_id_response); + +// Returns true if the new sequence number is greater than the last seen +// sequence number. +bool isSequenceNumberNewer(const VehiclePropValue& subscription_change, + const int last_seen_sequence_number); + +// Returns sequence number of the message. +int32_t getSequenceNumberForSubscriptionsState(const VehiclePropValue& subscription_change); + +// Takes a subscription change message and returns the layers that have active +// subscriptions of the layers that are offered by your HAL client/publisher. +// +// A publisher can use this function when receiving a subscription change message +// to determine which layers to publish data on. +// The caller of this function can optionally decide to not consume these layers +// if the subscription change has the sequence number less than the last seen +// sequence number. +std::vector getSubscribedLayers(const VehiclePropValue& subscription_change, + const VmsOffers& offers); + +// Takes an availability change message and returns true if the parsed message implies that +// the service has newly started or restarted. +// If the message has a sequence number 0, it means that the service +// has newly started or restarted. +bool hasServiceNewlyStarted(const VehiclePropValue& availability_change); } // namespace vms } // namespace V2_0 diff --git a/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp b/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp index f001a3236c..1863191ed9 100644 --- a/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp +++ b/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp @@ -27,16 +27,23 @@ namespace vms { static constexpr int kMessageIndex = toInt(VmsBaseMessageIntegerValuesIndex::MESSAGE_TYPE); static constexpr int kMessageTypeSize = 1; +static constexpr int kPublisherIdSize = 1; static constexpr int kLayerNumberSize = 1; static constexpr int kLayerSize = 3; static constexpr int kLayerAndPublisherSize = 4; +static constexpr int kPublisherIdIndex = + toInt(VmsPublisherInformationIntegerValuesIndex::PUBLISHER_ID); +static constexpr int kSubscriptionStateSequenceNumberIndex = + toInt(VmsSubscriptionsStateIntegerValuesIndex::SEQUENCE_NUMBER); +static constexpr int kAvailabilitySequenceNumberIndex = + toInt(VmsAvailabilityStateIntegerValuesIndex::SEQUENCE_NUMBER); // TODO(aditin): We should extend the VmsMessageType enum to include a first and // last, which would prevent breakages in this API. However, for all of the // functions in this module, we only need to guarantee that the message type is -// between SUBSCRIBE and DATA. +// between SUBSCRIBE and PUBLISHER_ID_RESPONSE. static constexpr int kFirstMessageType = toInt(VmsMessageType::SUBSCRIBE); -static constexpr int kLastMessageType = toInt(VmsMessageType::DATA); +static constexpr int kLastMessageType = toInt(VmsMessageType::PUBLISHER_ID_RESPONSE); std::unique_ptr createBaseVmsMessage(size_t message_size) { auto result = createVehiclePropValue(VehiclePropertyType::INT32, message_size); @@ -77,17 +84,16 @@ std::unique_ptr createUnsubscribeToPublisherMessage( return result; } -std::unique_ptr createOfferingMessage( - const std::vector& offering) { - int message_size = kMessageTypeSize + kLayerNumberSize; - for (const auto& offer : offering) { - message_size += kLayerNumberSize + (1 + offer.dependencies.size()) * kLayerSize; +std::unique_ptr createOfferingMessage(const VmsOffers& offers) { + int message_size = kMessageTypeSize + kPublisherIdSize + kLayerNumberSize; + for (const auto& offer : offers.offerings) { + message_size += kLayerSize + kLayerNumberSize + (offer.dependencies.size() * kLayerSize); } auto result = createBaseVmsMessage(message_size); - std::vector offers = {toInt(VmsMessageType::OFFERING), - static_cast(offering.size())}; - for (const auto& offer : offering) { + std::vector offerings = {toInt(VmsMessageType::OFFERING), offers.publisher_id, + static_cast(offers.offerings.size())}; + for (const auto& offer : offers.offerings) { std::vector layer_vector = {offer.layer.type, offer.layer.subtype, offer.layer.version, static_cast(offer.dependencies.size())}; @@ -97,9 +103,9 @@ std::unique_ptr createOfferingMessage( layer_vector.insert(layer_vector.end(), dependency_layer.begin(), dependency_layer.end()); } - offers.insert(offers.end(), layer_vector.begin(), layer_vector.end()); + offerings.insert(offerings.end(), layer_vector.begin(), layer_vector.end()); } - result->value.int32Values = offers; + result->value.int32Values = offerings; return result; } @@ -153,6 +159,103 @@ std::string parseData(const VehiclePropValue& value) { } } +std::unique_ptr createPublisherIdRequest( + const std::string& vms_provider_description) { + auto result = createBaseVmsMessage(kMessageTypeSize); + result->value.int32Values = hidl_vec{ + toInt(VmsMessageType::PUBLISHER_ID_REQUEST), + }; + result->value.bytes = + std::vector(vms_provider_description.begin(), vms_provider_description.end()); + return result; +} + +int32_t parsePublisherIdResponse(const VehiclePropValue& publisher_id_response) { + if (isValidVmsMessage(publisher_id_response) && + parseMessageType(publisher_id_response) == VmsMessageType::PUBLISHER_ID_RESPONSE && + publisher_id_response.value.int32Values.size() > kPublisherIdIndex) { + return publisher_id_response.value.int32Values[kPublisherIdIndex]; + } + return -1; +} + +bool isSequenceNumberNewer(const VehiclePropValue& subscription_change, + const int last_seen_sequence_number) { + return (isValidVmsMessage(subscription_change) && + parseMessageType(subscription_change) == VmsMessageType::SUBSCRIPTIONS_CHANGE && + subscription_change.value.int32Values.size() > kSubscriptionStateSequenceNumberIndex && + subscription_change.value.int32Values[kSubscriptionStateSequenceNumberIndex] > + last_seen_sequence_number); +} + +int32_t getSequenceNumberForSubscriptionsState(const VehiclePropValue& subscription_change) { + if (isValidVmsMessage(subscription_change) && + parseMessageType(subscription_change) == VmsMessageType::SUBSCRIPTIONS_CHANGE && + subscription_change.value.int32Values.size() > kSubscriptionStateSequenceNumberIndex) { + return subscription_change.value.int32Values[kSubscriptionStateSequenceNumberIndex]; + } + return -1; +} + +std::vector getSubscribedLayers(const VehiclePropValue& subscription_change, + const VmsOffers& offers) { + if (isValidVmsMessage(subscription_change) && + parseMessageType(subscription_change) == VmsMessageType::SUBSCRIPTIONS_CHANGE && + subscription_change.value.int32Values.size() > kSubscriptionStateSequenceNumberIndex) { + const int32_t num_of_layers = subscription_change.value.int32Values[toInt( + VmsSubscriptionsStateIntegerValuesIndex::NUMBER_OF_LAYERS)]; + const int32_t num_of_associated_layers = subscription_change.value.int32Values[toInt( + VmsSubscriptionsStateIntegerValuesIndex ::NUMBER_OF_ASSOCIATED_LAYERS)]; + + std::unordered_set offered_layers; + for (const auto& offer : offers.offerings) { + offered_layers.insert(offer.layer); + } + std::vector subscribed_layers; + + int current_index = toInt(VmsSubscriptionsStateIntegerValuesIndex::SUBSCRIPTIONS_START); + // Add all subscribed layers which are offered by the current publisher. + for (int i = 0; i < num_of_layers; i++) { + VmsLayer layer = VmsLayer(subscription_change.value.int32Values[current_index], + subscription_change.value.int32Values[current_index + 1], + subscription_change.value.int32Values[current_index + 2]); + if (offered_layers.find(layer) != offered_layers.end()) { + subscribed_layers.push_back(layer); + } + current_index += kLayerSize; + } + // Add all subscribed associated layers which are offered by the current publisher. + // For this, we need to check if the associated layer has a publisher ID which is + // same as that of the current publisher. + for (int i = 0; i < num_of_associated_layers; i++) { + VmsLayer layer = VmsLayer(subscription_change.value.int32Values[current_index], + subscription_change.value.int32Values[current_index + 1], + subscription_change.value.int32Values[current_index + 2]); + current_index += kLayerSize; + if (offered_layers.find(layer) != offered_layers.end()) { + int32_t num_of_publisher_ids = subscription_change.value.int32Values[current_index]; + current_index++; + for (int j = 0; j < num_of_publisher_ids; j++) { + if (subscription_change.value.int32Values[current_index] == + offers.publisher_id) { + subscribed_layers.push_back(layer); + } + current_index++; + } + } + } + return subscribed_layers; + } + return {}; +} + +bool hasServiceNewlyStarted(const VehiclePropValue& availability_change) { + return (isValidVmsMessage(availability_change) && + parseMessageType(availability_change) == VmsMessageType::AVAILABILITY_CHANGE && + availability_change.value.int32Values.size() > kAvailabilitySequenceNumberIndex && + availability_change.value.int32Values[kAvailabilitySequenceNumberIndex] == 0); +} + } // namespace vms } // namespace V2_0 } // namespace vehicle diff --git a/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp b/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp index f64eab55a9..09750718a0 100644 --- a/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp +++ b/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp @@ -278,7 +278,6 @@ TEST_F(VehicleHalManagerTest, subscribe) { cb->reset(); VehiclePropValue actualValue(*subscribedValue.get()); - actualValue.status = VehiclePropertyStatus::AVAILABLE; hal->sendPropEvent(std::move(subscribedValue)); ASSERT_TRUE(cb->waitForExpectedEvents(1)) << "Events received: " diff --git a/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp b/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp index 414c5c2a42..5ea5bd45c5 100644 --- a/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp +++ b/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp @@ -60,52 +60,64 @@ TEST(VmsUtilsTest, unsubscribeMessage) { } TEST(VmsUtilsTest, singleOfferingMessage) { - std::vector offering = {VmsLayerOffering(VmsLayer(1, 0, 2))}; - auto message = createOfferingMessage(offering); + VmsOffers offers = {123, {VmsLayerOffering(VmsLayer(1, 0, 2))}}; + auto message = createOfferingMessage(offers); ASSERT_NE(message, nullptr); EXPECT_TRUE(isValidVmsMessage(*message)); EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE)); - EXPECT_EQ(message->value.int32Values.size(), 0x6ul); + EXPECT_EQ(message->value.int32Values.size(), 0x7ul); EXPECT_EQ(parseMessageType(*message), VmsMessageType::OFFERING); + // Publisher ID + EXPECT_EQ(message->value.int32Values[1], 123); + // Number of layer offerings - EXPECT_EQ(message->value.int32Values[1], 1); + EXPECT_EQ(message->value.int32Values[2], 1); // Layer - EXPECT_EQ(message->value.int32Values[2], 1); - EXPECT_EQ(message->value.int32Values[3], 0); - EXPECT_EQ(message->value.int32Values[4], 2); + EXPECT_EQ(message->value.int32Values[3], 1); + EXPECT_EQ(message->value.int32Values[4], 0); + EXPECT_EQ(message->value.int32Values[5], 2); // Number of dependencies - EXPECT_EQ(message->value.int32Values[5], 0); + EXPECT_EQ(message->value.int32Values[6], 0); } TEST(VmsUtilsTest, offeringWithDependencies) { VmsLayer layer(1, 0, 2); - std::vector dependencies = {VmsLayer(2, 0, 2)}; + std::vector dependencies = {VmsLayer(2, 0, 2), VmsLayer(3, 0, 3)}; std::vector offering = {VmsLayerOffering(layer, dependencies)}; - auto message = createOfferingMessage(offering); + VmsOffers offers = {123, offering}; + auto message = createOfferingMessage(offers); ASSERT_NE(message, nullptr); EXPECT_TRUE(isValidVmsMessage(*message)); EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE)); - EXPECT_EQ(message->value.int32Values.size(), 0x9ul); + EXPECT_EQ(message->value.int32Values.size(), 0xdul); EXPECT_EQ(parseMessageType(*message), VmsMessageType::OFFERING); + // Publisher ID + EXPECT_EQ(message->value.int32Values[1], 123); + // Number of layer offerings - EXPECT_EQ(message->value.int32Values[1], 1); + EXPECT_EQ(message->value.int32Values[2], 1); // Layer - EXPECT_EQ(message->value.int32Values[2], 1); - EXPECT_EQ(message->value.int32Values[3], 0); - EXPECT_EQ(message->value.int32Values[4], 2); + EXPECT_EQ(message->value.int32Values[3], 1); + EXPECT_EQ(message->value.int32Values[4], 0); + EXPECT_EQ(message->value.int32Values[5], 2); // Number of dependencies - EXPECT_EQ(message->value.int32Values[5], 1); + EXPECT_EQ(message->value.int32Values[6], 2); // Dependency 1 - EXPECT_EQ(message->value.int32Values[6], 2); - EXPECT_EQ(message->value.int32Values[7], 0); - EXPECT_EQ(message->value.int32Values[8], 2); + EXPECT_EQ(message->value.int32Values[7], 2); + EXPECT_EQ(message->value.int32Values[8], 0); + EXPECT_EQ(message->value.int32Values[9], 2); + + // Dependency 2 + EXPECT_EQ(message->value.int32Values[10], 3); + EXPECT_EQ(message->value.int32Values[11], 0); + EXPECT_EQ(message->value.int32Values[12], 3); } TEST(VmsUtilsTest, availabilityMessage) { @@ -166,6 +178,153 @@ TEST(VmsUtilsTest, parseInvalidDataMessage) { EXPECT_TRUE(data_str.empty()); } +TEST(VmsUtilsTest, publisherIdRequest) { + std::string bytes = "pub_id"; + auto message = createPublisherIdRequest(bytes); + ASSERT_NE(message, nullptr); + EXPECT_TRUE(isValidVmsMessage(*message)); + EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE)); + EXPECT_EQ(message->value.int32Values.size(), 0x1ul); + EXPECT_EQ(parseMessageType(*message), VmsMessageType::PUBLISHER_ID_REQUEST); + EXPECT_EQ(message->value.bytes.size(), bytes.size()); + EXPECT_EQ(memcmp(message->value.bytes.data(), bytes.data(), bytes.size()), 0); +} + +TEST(VmsUtilsTest, validPublisherIdResponse) { + auto message = createBaseVmsMessage(2); + message->value.int32Values = + hidl_vec{toInt(VmsMessageType::PUBLISHER_ID_RESPONSE), 1234}; + EXPECT_EQ(parsePublisherIdResponse(*message), 1234); +} + +TEST(VmsUtilsTest, invalidPublisherIdResponse) { + auto message = createBaseVmsMessage(1); + EXPECT_EQ(parsePublisherIdResponse(*message), -1); +} + +TEST(VmsUtilsTest, validSequenceNumberForSubscriptionsState) { + auto message = createBaseVmsMessage(2); + message->value.int32Values = + hidl_vec{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE), 1234}; + EXPECT_EQ(getSequenceNumberForSubscriptionsState(*message), 1234); +} + +TEST(VmsUtilsTest, invalidSubscriptionsState) { + auto message = createBaseVmsMessage(1); + EXPECT_EQ(getSequenceNumberForSubscriptionsState(*message), -1); +} + +TEST(VmsUtilsTest, newSequenceNumberForExistingSmallerNumber) { + auto message = createBaseVmsMessage(2); + message->value.int32Values = + hidl_vec{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE), 1234}; + EXPECT_TRUE(isSequenceNumberNewer(*message, 1233)); +} + +TEST(VmsUtilsTest, newSequenceNumberForExistingGreaterNumber) { + auto message = createBaseVmsMessage(2); + message->value.int32Values = + hidl_vec{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE), 1234}; + EXPECT_FALSE(isSequenceNumberNewer(*message, 1235)); +} + +TEST(VmsUtilsTest, newSequenceNumberForSameNumber) { + auto message = createBaseVmsMessage(2); + message->value.int32Values = + hidl_vec{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE), 1234}; + EXPECT_FALSE(isSequenceNumberNewer(*message, 1234)); +} + +TEST(VmsUtilsTest, subscribedLayers) { + VmsOffers offers = {123, + {VmsLayerOffering(VmsLayer(1, 0, 1), {VmsLayer(4, 1, 1)}), + VmsLayerOffering(VmsLayer(2, 0, 1))}}; + auto message = createBaseVmsMessage(2); + message->value.int32Values = hidl_vec{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE), + 1234, // sequence number + 2, // number of layers + 1, // number of associated layers + 1, // layer 1 + 0, + 1, + 4, // layer 2 + 1, + 1, + 2, // associated layer + 0, + 1, + 2, // number of publisher IDs + 111, // publisher IDs + 123}; + EXPECT_TRUE(isValidVmsMessage(*message)); + auto result = getSubscribedLayers(*message, offers); + EXPECT_EQ(static_cast(result.size()), 2); + EXPECT_EQ(result.at(0), VmsLayer(1, 0, 1)); + EXPECT_EQ(result.at(1), VmsLayer(2, 0, 1)); +} + +TEST(VmsUtilsTest, subscribedLayersWithDifferentSubtype) { + VmsOffers offers = {123, {VmsLayerOffering(VmsLayer(1, 0, 1))}}; + auto message = createBaseVmsMessage(2); + message->value.int32Values = hidl_vec{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE), + 1234, // sequence number + 1, // number of layers + 0, // number of associated layers + 1, // layer 1 + 1, // different subtype + 1}; + EXPECT_TRUE(isValidVmsMessage(*message)); + EXPECT_TRUE(getSubscribedLayers(*message, offers).empty()); +} + +TEST(VmsUtilsTest, subscribedLayersWithDifferentVersion) { + VmsOffers offers = {123, {VmsLayerOffering(VmsLayer(1, 0, 1))}}; + auto message = createBaseVmsMessage(2); + message->value.int32Values = hidl_vec{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE), + 1234, // sequence number + 1, // number of layers + 0, // number of associated layers + 1, // layer 1 + 0, + 2}; // different version + EXPECT_TRUE(isValidVmsMessage(*message)); + EXPECT_TRUE(getSubscribedLayers(*message, offers).empty()); +} + +TEST(VmsUtilsTest, subscribedLayersWithDifferentPublisherId) { + VmsOffers offers = {123, {VmsLayerOffering(VmsLayer(1, 0, 1))}}; + auto message = createBaseVmsMessage(2); + message->value.int32Values = hidl_vec{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE), + 1234, // sequence number + 0, // number of layers + 1, // number of associated layers + 1, // associated layer 1 + 0, + 1, + 1, // number of publisher IDs + 234}; // publisher ID 1 + EXPECT_TRUE(isValidVmsMessage(*message)); + EXPECT_TRUE(getSubscribedLayers(*message, offers).empty()); +} + +TEST(VmsUtilsTest, serviceNewlyStarted) { + auto message = createBaseVmsMessage(2); + message->value.int32Values = hidl_vec{toInt(VmsMessageType::AVAILABILITY_CHANGE), 0}; + EXPECT_TRUE(hasServiceNewlyStarted(*message)); +} + +TEST(VmsUtilsTest, serviceNotNewlyStarted) { + auto message = createBaseVmsMessage(2); + message->value.int32Values = + hidl_vec{toInt(VmsMessageType::AVAILABILITY_CHANGE), 1234}; + EXPECT_FALSE(hasServiceNewlyStarted(*message)); +} + +TEST(VmsUtilsTest, invalidAvailabilityChange) { + auto message = createBaseVmsMessage(1); + EXPECT_FALSE(hasServiceNewlyStarted(*message)); +} + } // namespace } // namespace vms From c53ea9f5f8e8d30ad79618d57b965a492962b546 Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Tue, 2 Apr 2019 17:05:39 -0700 Subject: [PATCH 587/718] Mark layers with color transform client composition if not implemented. SET_LAYER_COLOR_TRANSFORM is an optional API, and thus when it's not implemented. we want to make sure we follow the spec to mark those layers as client composition and add them into changed layers list proactively. BUG: 115554640 Test: Verify with setting color transform manually. Change-Id: I53b4039eb63cccd1b174e3c6da3b6336b85e0321 --- .../include/composer-passthrough/2.1/HwcHal.h | 28 ++++- .../include/composer-passthrough/2.3/HwcHal.h | 101 +++++++++++++++++- 2 files changed, 123 insertions(+), 6 deletions(-) diff --git a/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h b/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h index 436e4612bb..5826b126bb 100644 --- a/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h +++ b/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h @@ -162,6 +162,7 @@ class HwcHalImpl : public Hal { Error destroyLayer(Display display, Layer layer) override { int32_t err = mDispatch.destroyLayer(mDevice, display, layer); + onLayerDestroyed(display, layer); return static_cast(err); } @@ -327,6 +328,7 @@ class HwcHalImpl : public Hal { std::vector* outCompositionTypes, uint32_t* outDisplayRequestMask, std::vector* outRequestedLayers, std::vector* outRequestMasks) override { + onBeforeValidateDisplay(display); uint32_t typesCount = 0; uint32_t reqsCount = 0; int32_t err = mDispatch.validateDisplay(mDevice, display, &typesCount, &reqsCount); @@ -335,17 +337,15 @@ class HwcHalImpl : public Hal { return static_cast(err); } - err = mDispatch.getChangedCompositionTypes(mDevice, display, &typesCount, nullptr, nullptr); + err = getChangedCompositionTypes(display, &typesCount, nullptr, nullptr); if (err != HWC2_ERROR_NONE) { return static_cast(err); } std::vector changedLayers(typesCount); std::vector compositionTypes(typesCount); - err = mDispatch.getChangedCompositionTypes( - mDevice, display, &typesCount, changedLayers.data(), - reinterpret_cast::type*>( - compositionTypes.data())); + err = getChangedCompositionTypes(display, &typesCount, changedLayers.data(), + compositionTypes.data()); if (err != HWC2_ERROR_NONE) { return static_cast(err); } @@ -578,6 +578,15 @@ class HwcHalImpl : public Hal { return true; } + virtual int32_t getChangedCompositionTypes(Display display, uint32_t* outTypesCount, + Layer* outChangedLayers, + IComposerClient::Composition* outCompositionTypes) { + return getChangedCompositionTypesInternal(display, outTypesCount, outChangedLayers, + outCompositionTypes); + } + virtual void onLayerDestroyed(Display /* display */, Layer /* layer */) {} + virtual void onBeforeValidateDisplay(Display /* display */) {} + static void hotplugHook(hwc2_callback_data_t callbackData, hwc2_display_t display, int32_t connected) { auto hal = static_cast(callbackData); @@ -596,6 +605,15 @@ class HwcHalImpl : public Hal { hal->mEventCallback->onVsync(display, timestamp); } + int32_t getChangedCompositionTypesInternal(Display display, uint32_t* outTypesCount, + Layer* outChangedLayers, + IComposerClient::Composition* outCompositionTypes) { + return mDispatch.getChangedCompositionTypes( + mDevice, display, outTypesCount, outChangedLayers, + reinterpret_cast::type*>( + outCompositionTypes)); + } + hwc2_device_t* mDevice = nullptr; std::unordered_set mCapabilities; diff --git a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h index 070cf80e44..9d67e0442d 100644 --- a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h +++ b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h @@ -42,6 +42,20 @@ using common::V1_2::PixelFormat; using V2_1::Display; using V2_1::Error; +namespace { + +bool isIdentityMatrix(const float* matrix) { + if (matrix[0] == 1.0 && matrix[1] == 0.0 && matrix[2] == 0.0 && matrix[3] == 0.0 && + matrix[4] == 0.0 && matrix[5] == 1.0 && matrix[6] == 0.0 && matrix[7] == 0.0 && + matrix[8] == 0.0 && matrix[9] == 0.0 && matrix[10] == 1.0 && matrix[11] == 0.0 && + matrix[12] == 0.0 && matrix[13] == 0.0 && matrix[14] == 0.0 && matrix[15] == 1.0) { + return true; + } + return false; +} + +} // namespace + // HwcHalImpl implements V2_*::hal::ComposerHal on top of hwcomposer2 template class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl { @@ -130,6 +144,16 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl { Error setLayerColorTransform(Display display, Layer layer, const float* matrix) override { if (!mDispatch.setLayerColorTransform) { + if (isIdentityMatrix(matrix)) { + // If an identity matrix is set, then we can remove the layer from client + // composition list. + mClientCompositionLayers[display].erase(layer); + return Error::UNSUPPORTED; + } + // if setLayerColorTransform is not implemented, per spec we want to make sure the + // layer marked as client composition, and thus we maintain a list, and mark all these + // layers as client composition later before validate the display. + mClientCompositionLayers[display].insert(layer); return Error::UNSUPPORTED; } int32_t err = mDispatch.setLayerColorTransform(mDevice, display, layer, matrix); @@ -294,7 +318,79 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl { return true; } - private: + int32_t getChangedCompositionTypes(Display display, uint32_t* outTypesCount, + Layer* outChangedLayers, + IComposerClient::Composition* outCompositionTypes) override { + if (outChangedLayers == nullptr && outCompositionTypes == nullptr) { + uint32_t typesCount = 0; + int32_t error = BaseType2_1::getChangedCompositionTypesInternal(display, &typesCount, + nullptr, nullptr); + if (error != HWC2_ERROR_NONE) { + return error; + } + mChangedLayersCache[display].reserve(typesCount); + mCompositionTypesCache[display].reserve(typesCount); + error = BaseType2_1::getChangedCompositionTypesInternal( + display, &typesCount, mChangedLayersCache[display].data(), + mCompositionTypesCache[display].data()); + if (error != HWC2_ERROR_NONE) { + return error; + } + for (Layer layer : mClientCompositionLayers[display]) { + bool exist = false; + for (uint32_t i = 0; i < typesCount; ++i) { + if (mChangedLayersCache[display][i] == layer) { + exist = true; + break; + } + } + if (!exist) { + mChangedLayersCache[display].push_back(layer); + mCompositionTypesCache[display].push_back(IComposerClient::Composition::CLIENT); + } + } + *outTypesCount = mChangedLayersCache[display].size(); + return error; + } + for (uint32_t i = 0; i < *outTypesCount; ++i) { + if (outChangedLayers != nullptr) { + outChangedLayers[i] = mChangedLayersCache[display][i]; + } + if (outCompositionTypes != nullptr) { + outCompositionTypes[i] = mCompositionTypesCache[display][i]; + } + } + return HWC2_ERROR_NONE; + } + + void onLayerDestroyed(Display display, Layer layer) override { + if (mClientCompositionLayers.find(display) == mClientCompositionLayers.end()) { + return; + } + mClientCompositionLayers[display].erase(layer); + } + + void onBeforeValidateDisplay(Display display) override { + if (mClientCompositionLayers.find(display) == mClientCompositionLayers.end()) { + return; + } + + // clear the cache proactively so that we don't hold too much memory over time. + mChangedLayersCache[display].clear(); + mCompositionTypesCache[display].clear(); + + // SET_LAYER_COLOR_TRANSFORM is optional, and thus if it's not implemented, we need to + // follow the spec to make sure those layers marked as client composition before validate + // the display. + if (!mDispatch.setLayerColorTransform) { + for (Layer layer : mClientCompositionLayers[display]) { + BaseType2_1::setLayerCompositionType( + display, layer, static_cast(IComposerClient::Composition::CLIENT)); + } + } + } + + private: struct { HWC2_PFN_GET_DISPLAY_IDENTIFICATION_DATA getDisplayIdentificationData; HWC2_PFN_SET_LAYER_COLOR_TRANSFORM setLayerColorTransform; @@ -318,6 +414,9 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl { using BaseType2_2::getRenderIntents; using BaseType2_2::setColorMode_2_2; using BaseType2_2::setLayerPerFrameMetadata; + std::map> mClientCompositionLayers; + std::map> mChangedLayersCache; + std::map> mCompositionTypesCache; }; } // namespace detail From f45338a356b7593b464fe2fb964f8705461ac28f Mon Sep 17 00:00:00 2001 From: Anil Admal Date: Wed, 3 Apr 2019 14:43:30 -0700 Subject: [PATCH 588/718] Restore gnss@1.1 HAL capability bits removed in gnss@2.0 (hal) In the IGnssCallback.hal@2.0 introduced in Android Q, the capability bits in IGnssCallback.hal@1.1 that represent sub-HAL interfaces have been removed as they are derivable from the existing getExtensionXXX() family of methods in the IGnss.hal interface. These need to be restored back as the synchronous nature of the getExtensionXXX() methods called by the framework has an impact on partner implementations that need to communicate with the modem to get the capabilities. Additionally, the capability bit MEASUREMENT_CORRECTIONS needs to be added for the new optional measurement_corrections@1.0 sub-HAL introduced in gnss@2.0. Fixes: 129870126 Test: Verified through cuttlefish default implementation and VTS tests. Change-Id: Ib4164c9501b8db9f09eb5429a077d477d0a4a7f9 --- current.txt | 2 +- gnss/2.0/IGnssCallback.hal | 29 ++++--------------- gnss/2.0/default/Gnss.cpp | 3 +- .../vts/functional/gnss_hal_test_cases.cpp | 24 ++++++++------- 4 files changed, 22 insertions(+), 36 deletions(-) diff --git a/current.txt b/current.txt index 8518c5e2bd..fcb8447696 100644 --- a/current.txt +++ b/current.txt @@ -469,7 +469,7 @@ f27baaa587bc3dd9b740cb6928ab812b9b7d105b5187663938aee578105f3c39 android.hardwar 4deafcdcffa2d002119e7f58810b767a84666e76475aae68e757ec2845d9756d android.hardware.gnss@2.0::IGnss db6bdf6dfc5edf6c85d2944976db899227abb51079c893874353c322342c50b6 android.hardware.gnss@2.0::IGnssBatching 1f89392f1ebb693d8fa6f50324b1635fc79fab246d31900e63998e1b0e17511c android.hardware.gnss@2.0::IGnssBatchingCallback -b11a5e4a1602d3f408716b6fe2c578a79f060d571aad8e828f9a4426d161fbcf android.hardware.gnss@2.0::IGnssCallback +64232037109a5e5f53ab0377e755ec494ae93fcb5279e6eea71dec2e7ac6fbfc android.hardware.gnss@2.0::IGnssCallback ecc966c68bddbd95c8dae782b84204cf01c75734675e8769963f3b5106ec128b android.hardware.gnss@2.0::IGnssConfiguration b670bae2ab8517336290532e364502b4db9120340d75474ccc8442b1b15d6ab7 android.hardware.gnss@2.0::IGnssDebug c67759f5d6387d273b66729180d03690e827f0b6b8d4e13ce2ff42d31b224065 android.hardware.gnss@2.0::IGnssMeasurement diff --git a/gnss/2.0/IGnssCallback.hal b/gnss/2.0/IGnssCallback.hal index a96fd6ce6e..d6db9cce11 100644 --- a/gnss/2.0/IGnssCallback.hal +++ b/gnss/2.0/IGnssCallback.hal @@ -30,32 +30,13 @@ interface IGnssCallback extends @1.1::IGnssCallback { /** Flags for the gnssSetCapabilities callback. */ @export(name="", value_prefix="GPS_CAPABILITY_") - enum Capabilities : uint32_t { - /** - * GNSS HAL schedules fixes for RECURRENCE_PERIODIC mode. - * If this is not set, then the framework will use 1000ms for - * minInterval and must call start() and stop() to schedule the GNSS. - */ - SCHEDULING = 1 << 0, - /** GNSS supports MS-Based AGNSS mode */ - MSB = 1 << 1, - /** GNSS supports MS-Assisted AGNSS mode */ - MSA = 1 << 2, - /** GNSS supports single-shot fixes */ - SINGLE_SHOT = 1 << 3, - /** GNSS supports on demand time injection */ - ON_DEMAND_TIME = 1 << 4, - /** - * Values for the flags removed from IGnssCallback.hal@1.0 Capabilities - * enum are marked as reserved and not reused here to avoid confusion. - */ - RESERVED_1 = 1 << 5, - RESERVED_2 = 1 << 6, - RESERVED_3 = 1 << 7, + enum Capabilities : @1.0::IGnssCallback.Capabilities { /** GNSS supports low power mode */ - LOW_POWER_MODE = 1 << 8, + LOW_POWER_MODE = 1 << 8, /** GNSS supports blacklisting satellites */ - SATELLITE_BLACKLIST = 1 << 9 + SATELLITE_BLACKLIST = 1 << 9, + /** GNSS supports measurement corrections */ + MEASUREMENT_CORRECTIONS = 1 << 10 }; /** diff --git a/gnss/2.0/default/Gnss.cpp b/gnss/2.0/default/Gnss.cpp index 75c2385169..3d64fc30cc 100644 --- a/gnss/2.0/default/Gnss.cpp +++ b/gnss/2.0/default/Gnss.cpp @@ -280,7 +280,8 @@ Return Gnss::setCallback_2_0(const sp& callback) { sGnssCallback_2_0 = callback; using Capabilities = V2_0::IGnssCallback::Capabilities; - const auto capabilities = Capabilities::LOW_POWER_MODE | Capabilities::SATELLITE_BLACKLIST; + const auto capabilities = Capabilities::MEASUREMENTS | Capabilities::MEASUREMENT_CORRECTIONS | + Capabilities::LOW_POWER_MODE | Capabilities::SATELLITE_BLACKLIST; auto ret = sGnssCallback_2_0->gnssSetCapabilitiesCb_2_0(capabilities); if (!ret.isOk()) { ALOGE("%s: Unable to invoke callback", __func__); diff --git a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp index 0682f84d5f..be182a9c52 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp +++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp @@ -289,19 +289,21 @@ TEST_F(GnssHalTest, TestGnssVisibilityControlExtension) { /* * TestGnssMeasurementCorrectionsCapabilities: - * If the GnssMeasurementCorrectionsExtension is not null, verifies that the measurement corrections + * If measurement corrections capability is supported, verifies that the measurement corrections * capabilities are reported and the mandatory LOS_SATS or the EXCESS_PATH_LENGTH * capability flag is set. */ TEST_F(GnssHalTest, TestGnssMeasurementCorrectionsCapabilities) { - // Setup measurement corrections callback. - auto measurementCorrections = gnss_hal_->getExtensionMeasurementCorrections(); - ASSERT_TRUE(measurementCorrections.isOk()); - sp iMeasurementCorrections = measurementCorrections; - if (iMeasurementCorrections == nullptr) { + if (!(last_capabilities_ & IGnssCallback::Capabilities::MEASUREMENT_CORRECTIONS)) { return; } + auto measurementCorrections = gnss_hal_->getExtensionMeasurementCorrections(); + ASSERT_TRUE(measurementCorrections.isOk()); + sp iMeasurementCorrections = measurementCorrections; + ASSERT_NE(iMeasurementCorrections, nullptr); + + // Setup measurement corrections callback. sp iMeasurementCorrectionsCallback = new GnssMeasurementCorrectionsCallback(*this); iMeasurementCorrections->setCallback(iMeasurementCorrectionsCallback); @@ -316,17 +318,19 @@ TEST_F(GnssHalTest, TestGnssMeasurementCorrectionsCapabilities) { /* * TestGnssMeasurementCorrections: - * If the GnssMeasurementCorrectionsExtension is not null, verifies that it supports the + * If measurement corrections capability is supported, verifies that it supports the * gnss.measurement_corrections@1.0::IMeasurementCorrections interface by invoking a method. */ TEST_F(GnssHalTest, TestGnssMeasurementCorrections) { + if (!(last_capabilities_ & IGnssCallback::Capabilities::MEASUREMENT_CORRECTIONS)) { + return; + } + // Verify IMeasurementCorrections is supported. auto measurementCorrections = gnss_hal_->getExtensionMeasurementCorrections(); ASSERT_TRUE(measurementCorrections.isOk()); sp iMeasurementCorrections = measurementCorrections; - if (iMeasurementCorrections == nullptr) { - return; - } + ASSERT_NE(iMeasurementCorrections, nullptr); sp iMeasurementCorrectionsCallback = new GnssMeasurementCorrectionsCallback(*this); From 6f5a48f7af9de2c7cb69ac14a8a8666617f27d21 Mon Sep 17 00:00:00 2001 From: Andrew Chant Date: Thu, 4 Apr 2019 17:40:21 +0000 Subject: [PATCH 589/718] Revert "Mark layers with color transform client composition if not implemented." This reverts commit c53ea9f5f8e8d30ad79618d57b965a492962b546. Reason for revert: Breaks some display output Bug: 129945273 Bug: 115554640 Merged-In: If70a148ae6ad673b5dd03143b3f1ed73eaa1290f Change-Id: If70a148ae6ad673b5dd03143b3f1ed73eaa1290f --- .../include/composer-passthrough/2.1/HwcHal.h | 28 +---- .../include/composer-passthrough/2.3/HwcHal.h | 101 +----------------- 2 files changed, 6 insertions(+), 123 deletions(-) diff --git a/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h b/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h index 5826b126bb..436e4612bb 100644 --- a/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h +++ b/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h @@ -162,7 +162,6 @@ class HwcHalImpl : public Hal { Error destroyLayer(Display display, Layer layer) override { int32_t err = mDispatch.destroyLayer(mDevice, display, layer); - onLayerDestroyed(display, layer); return static_cast(err); } @@ -328,7 +327,6 @@ class HwcHalImpl : public Hal { std::vector* outCompositionTypes, uint32_t* outDisplayRequestMask, std::vector* outRequestedLayers, std::vector* outRequestMasks) override { - onBeforeValidateDisplay(display); uint32_t typesCount = 0; uint32_t reqsCount = 0; int32_t err = mDispatch.validateDisplay(mDevice, display, &typesCount, &reqsCount); @@ -337,15 +335,17 @@ class HwcHalImpl : public Hal { return static_cast(err); } - err = getChangedCompositionTypes(display, &typesCount, nullptr, nullptr); + err = mDispatch.getChangedCompositionTypes(mDevice, display, &typesCount, nullptr, nullptr); if (err != HWC2_ERROR_NONE) { return static_cast(err); } std::vector changedLayers(typesCount); std::vector compositionTypes(typesCount); - err = getChangedCompositionTypes(display, &typesCount, changedLayers.data(), - compositionTypes.data()); + err = mDispatch.getChangedCompositionTypes( + mDevice, display, &typesCount, changedLayers.data(), + reinterpret_cast::type*>( + compositionTypes.data())); if (err != HWC2_ERROR_NONE) { return static_cast(err); } @@ -578,15 +578,6 @@ class HwcHalImpl : public Hal { return true; } - virtual int32_t getChangedCompositionTypes(Display display, uint32_t* outTypesCount, - Layer* outChangedLayers, - IComposerClient::Composition* outCompositionTypes) { - return getChangedCompositionTypesInternal(display, outTypesCount, outChangedLayers, - outCompositionTypes); - } - virtual void onLayerDestroyed(Display /* display */, Layer /* layer */) {} - virtual void onBeforeValidateDisplay(Display /* display */) {} - static void hotplugHook(hwc2_callback_data_t callbackData, hwc2_display_t display, int32_t connected) { auto hal = static_cast(callbackData); @@ -605,15 +596,6 @@ class HwcHalImpl : public Hal { hal->mEventCallback->onVsync(display, timestamp); } - int32_t getChangedCompositionTypesInternal(Display display, uint32_t* outTypesCount, - Layer* outChangedLayers, - IComposerClient::Composition* outCompositionTypes) { - return mDispatch.getChangedCompositionTypes( - mDevice, display, outTypesCount, outChangedLayers, - reinterpret_cast::type*>( - outCompositionTypes)); - } - hwc2_device_t* mDevice = nullptr; std::unordered_set mCapabilities; diff --git a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h index 9d67e0442d..070cf80e44 100644 --- a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h +++ b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h @@ -42,20 +42,6 @@ using common::V1_2::PixelFormat; using V2_1::Display; using V2_1::Error; -namespace { - -bool isIdentityMatrix(const float* matrix) { - if (matrix[0] == 1.0 && matrix[1] == 0.0 && matrix[2] == 0.0 && matrix[3] == 0.0 && - matrix[4] == 0.0 && matrix[5] == 1.0 && matrix[6] == 0.0 && matrix[7] == 0.0 && - matrix[8] == 0.0 && matrix[9] == 0.0 && matrix[10] == 1.0 && matrix[11] == 0.0 && - matrix[12] == 0.0 && matrix[13] == 0.0 && matrix[14] == 0.0 && matrix[15] == 1.0) { - return true; - } - return false; -} - -} // namespace - // HwcHalImpl implements V2_*::hal::ComposerHal on top of hwcomposer2 template class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl { @@ -144,16 +130,6 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl { Error setLayerColorTransform(Display display, Layer layer, const float* matrix) override { if (!mDispatch.setLayerColorTransform) { - if (isIdentityMatrix(matrix)) { - // If an identity matrix is set, then we can remove the layer from client - // composition list. - mClientCompositionLayers[display].erase(layer); - return Error::UNSUPPORTED; - } - // if setLayerColorTransform is not implemented, per spec we want to make sure the - // layer marked as client composition, and thus we maintain a list, and mark all these - // layers as client composition later before validate the display. - mClientCompositionLayers[display].insert(layer); return Error::UNSUPPORTED; } int32_t err = mDispatch.setLayerColorTransform(mDevice, display, layer, matrix); @@ -318,79 +294,7 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl { return true; } - int32_t getChangedCompositionTypes(Display display, uint32_t* outTypesCount, - Layer* outChangedLayers, - IComposerClient::Composition* outCompositionTypes) override { - if (outChangedLayers == nullptr && outCompositionTypes == nullptr) { - uint32_t typesCount = 0; - int32_t error = BaseType2_1::getChangedCompositionTypesInternal(display, &typesCount, - nullptr, nullptr); - if (error != HWC2_ERROR_NONE) { - return error; - } - mChangedLayersCache[display].reserve(typesCount); - mCompositionTypesCache[display].reserve(typesCount); - error = BaseType2_1::getChangedCompositionTypesInternal( - display, &typesCount, mChangedLayersCache[display].data(), - mCompositionTypesCache[display].data()); - if (error != HWC2_ERROR_NONE) { - return error; - } - for (Layer layer : mClientCompositionLayers[display]) { - bool exist = false; - for (uint32_t i = 0; i < typesCount; ++i) { - if (mChangedLayersCache[display][i] == layer) { - exist = true; - break; - } - } - if (!exist) { - mChangedLayersCache[display].push_back(layer); - mCompositionTypesCache[display].push_back(IComposerClient::Composition::CLIENT); - } - } - *outTypesCount = mChangedLayersCache[display].size(); - return error; - } - for (uint32_t i = 0; i < *outTypesCount; ++i) { - if (outChangedLayers != nullptr) { - outChangedLayers[i] = mChangedLayersCache[display][i]; - } - if (outCompositionTypes != nullptr) { - outCompositionTypes[i] = mCompositionTypesCache[display][i]; - } - } - return HWC2_ERROR_NONE; - } - - void onLayerDestroyed(Display display, Layer layer) override { - if (mClientCompositionLayers.find(display) == mClientCompositionLayers.end()) { - return; - } - mClientCompositionLayers[display].erase(layer); - } - - void onBeforeValidateDisplay(Display display) override { - if (mClientCompositionLayers.find(display) == mClientCompositionLayers.end()) { - return; - } - - // clear the cache proactively so that we don't hold too much memory over time. - mChangedLayersCache[display].clear(); - mCompositionTypesCache[display].clear(); - - // SET_LAYER_COLOR_TRANSFORM is optional, and thus if it's not implemented, we need to - // follow the spec to make sure those layers marked as client composition before validate - // the display. - if (!mDispatch.setLayerColorTransform) { - for (Layer layer : mClientCompositionLayers[display]) { - BaseType2_1::setLayerCompositionType( - display, layer, static_cast(IComposerClient::Composition::CLIENT)); - } - } - } - - private: + private: struct { HWC2_PFN_GET_DISPLAY_IDENTIFICATION_DATA getDisplayIdentificationData; HWC2_PFN_SET_LAYER_COLOR_TRANSFORM setLayerColorTransform; @@ -414,9 +318,6 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl { using BaseType2_2::getRenderIntents; using BaseType2_2::setColorMode_2_2; using BaseType2_2::setLayerPerFrameMetadata; - std::map> mClientCompositionLayers; - std::map> mChangedLayersCache; - std::map> mCompositionTypesCache; }; } // namespace detail From 70eae1d3f0336a14ee60cd003255b58d9311cdc9 Mon Sep 17 00:00:00 2001 From: Emilian Peev Date: Thu, 4 Apr 2019 13:18:52 -0700 Subject: [PATCH 590/718] Camera: Set buffer request stream id Additionally fix a possible issue with the buffer request index and variable shadowing. Bug: 129090247 Test: adb shell /data/nativetest64/VtsHalCameraProviderV2_4TargetTest/VtsHalCameraProviderV2_4TargetTest --hal_service_instance=android.hardware.camera.provider@2.4::ICameraProvider/legacy/0 Change-Id: I34ab0285e59233c1b6d276f9167372ef3b0bbd0b --- .../vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp index 5dfc783efa..814b88b70c 100644 --- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp +++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp @@ -1364,19 +1364,20 @@ Return CameraHidlTest::DeviceCb::requestStreamBuffers( } hidl_vec tmpRetBuffers(bufReq.numBuffersRequested); - for (size_t i = 0; i < bufReq.numBuffersRequested; i++) { + for (size_t j = 0; j < bufReq.numBuffersRequested; j++) { hidl_handle buffer_handle; mParent->allocateGraphicBuffer(stream.width, stream.height, android_convertGralloc1To0Usage( halStream.producerUsage, halStream.consumerUsage), halStream.overrideFormat, &buffer_handle); - tmpRetBuffers[i] = {stream.id, mNextBufferId, buffer_handle, BufferStatus::OK, + tmpRetBuffers[j] = {stream.id, mNextBufferId, buffer_handle, BufferStatus::OK, nullptr, nullptr}; mOutstandingBufferIds[idx].insert(std::make_pair(mNextBufferId++, buffer_handle)); } atLeastOneStreamOk = true; - bufRets[0].val.buffers(std::move(tmpRetBuffers)); + bufRets[i].streamId = stream.id; + bufRets[i].val.buffers(std::move(tmpRetBuffers)); } if (allStreamOk) { From 5874bba486f05516d8413ff3710bf2595c711d3b Mon Sep 17 00:00:00 2001 From: Emilian Peev Date: Thu, 21 Feb 2019 15:06:41 -0800 Subject: [PATCH 591/718] Camera: Avoid using an uninitialized physical camera id 'mStreamMap' entries can be inserted by several versions of HIDL API calls. If the fields are initialized by an older version, then make sure that newer additions are always initialized in the respective API method. Bug: 73885805 Test: adb shell /data/nativetest64/VtsHalCameraProviderV2_4TargetTest/VtsHalCameraProviderV2_4TargetTest --hal_service_instance=android.hardware.camera.provider@2.4::ICameraProvider/legacy/0 Change-Id: Ib5bd8f608da05f628c52d288c518cebbe964182b --- camera/device/3.4/default/CameraDeviceSession.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/camera/device/3.4/default/CameraDeviceSession.cpp b/camera/device/3.4/default/CameraDeviceSession.cpp index e00b3f83d0..03b6050397 100644 --- a/camera/device/3.4/default/CameraDeviceSession.cpp +++ b/camera/device/3.4/default/CameraDeviceSession.cpp @@ -187,7 +187,6 @@ bool CameraDeviceSession::preProcessConfigurationLocked_3_4( mPhysicalCameraIdMap[id] = requestedConfiguration.streams[i].physicalCameraId; mStreamMap[id].data_space = mapToLegacyDataspace( mStreamMap[id].data_space); - mStreamMap[id].physical_camera_id = mPhysicalCameraIdMap[id].c_str(); mCirculatingBuffers.emplace(stream.mId, CirculatingBuffers{}); } else { // width/height/format must not change, but usage/rotation might need to change @@ -206,6 +205,11 @@ bool CameraDeviceSession::preProcessConfigurationLocked_3_4( mStreamMap[id].rotation = (int) requestedConfiguration.streams[i].v3_2.rotation; mStreamMap[id].usage = (uint32_t) requestedConfiguration.streams[i].v3_2.usage; } + // It is possible for the entry in 'mStreamMap' to get initialized by an older + // HIDL API. Make sure that the physical id is always initialized when using + // a more recent API call. + mStreamMap[id].physical_camera_id = mPhysicalCameraIdMap[id].c_str(); + (*streams)[i] = &mStreamMap[id]; } From 661f4410f4b4d13dde6fb758fd56848e329edfab Mon Sep 17 00:00:00 2001 From: Jayant Chowdhary Date: Mon, 1 Apr 2019 10:29:53 -0700 Subject: [PATCH 592/718] Allow android.hardware.camera.common@1.0-helper to access vendor tags This allows vendor camera clients to access provider specific vendor tags. No expected behavior changes to camera HAL process(es). Also fixes OWNERS file. Bug: 129688550 Test: AImageReaderTest modified to set a vendor tag in CaptureRequest Test: Take still pictures / record video (sanity) Test: camera CTS tests Change-Id: I18b678e7e0db7f1b29c3de0b762cb65e25842fa8 Signed-off-by: Jayant Chowdhary --- camera/common/1.0/default/CameraMetadata.cpp | 31 +++++++++----------- camera/common/1.0/default/OWNERS | 2 +- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/camera/common/1.0/default/CameraMetadata.cpp b/camera/common/1.0/default/CameraMetadata.cpp index 4c54931a11..eb1bd1c149 100644 --- a/camera/common/1.0/default/CameraMetadata.cpp +++ b/camera/common/1.0/default/CameraMetadata.cpp @@ -171,17 +171,16 @@ status_t CameraMetadata::sort() { } status_t CameraMetadata::checkType(uint32_t tag, uint8_t expectedType) { - int tagType = get_camera_metadata_tag_type(tag); + int tagType = get_local_camera_metadata_tag_type(tag, mBuffer); if ( CC_UNLIKELY(tagType == -1)) { ALOGE("Update metadata entry: Unknown tag %d", tag); return INVALID_OPERATION; } if ( CC_UNLIKELY(tagType != expectedType) ) { ALOGE("Mismatched tag type when updating entry %s (%d) of type %s; " - "got type %s data instead ", - get_camera_metadata_tag_name(tag), tag, - camera_metadata_type_names[tagType], - camera_metadata_type_names[expectedType]); + "got type %s data instead ", + get_local_camera_metadata_tag_name(tag, mBuffer), tag, + camera_metadata_type_names[tagType], camera_metadata_type_names[expectedType]); return INVALID_OPERATION; } return OK; @@ -298,7 +297,7 @@ status_t CameraMetadata::updateImpl(uint32_t tag, const void *data, ALOGE("%s: CameraMetadata is locked", __FUNCTION__); return INVALID_OPERATION; } - int type = get_camera_metadata_tag_type(tag); + int type = get_local_camera_metadata_tag_type(tag, mBuffer); if (type == -1) { ALOGE("%s: Tag %d not found", __FUNCTION__, tag); return BAD_VALUE; @@ -332,9 +331,9 @@ status_t CameraMetadata::updateImpl(uint32_t tag, const void *data, } if (res != OK) { - ALOGE("%s: Unable to update metadata entry %s.%s (%x): %s (%d)", - __FUNCTION__, get_camera_metadata_section_name(tag), - get_camera_metadata_tag_name(tag), tag, strerror(-res), res); + ALOGE("%s: Unable to update metadata entry %s.%s (%x): %s (%d)", __FUNCTION__, + get_local_camera_metadata_section_name(tag, mBuffer), + get_local_camera_metadata_tag_name(tag, mBuffer), tag, strerror(-res), res); } IF_ALOGV() { @@ -391,18 +390,16 @@ status_t CameraMetadata::erase(uint32_t tag) { if (res == NAME_NOT_FOUND) { return OK; } else if (res != OK) { - ALOGE("%s: Error looking for entry %s.%s (%x): %s %d", - __FUNCTION__, - get_camera_metadata_section_name(tag), - get_camera_metadata_tag_name(tag), tag, strerror(-res), res); + ALOGE("%s: Error looking for entry %s.%s (%x): %s %d", __FUNCTION__, + get_local_camera_metadata_section_name(tag, mBuffer), + get_local_camera_metadata_tag_name(tag, mBuffer), tag, strerror(-res), res); return res; } res = delete_camera_metadata_entry(mBuffer, entry.index); if (res != OK) { - ALOGE("%s: Error deleting entry %s.%s (%x): %s %d", - __FUNCTION__, - get_camera_metadata_section_name(tag), - get_camera_metadata_tag_name(tag), tag, strerror(-res), res); + ALOGE("%s: Error deleting entry %s.%s (%x): %s %d", __FUNCTION__, + get_local_camera_metadata_section_name(tag, mBuffer), + get_local_camera_metadata_tag_name(tag, mBuffer), tag, strerror(-res), res); } return res; } diff --git a/camera/common/1.0/default/OWNERS b/camera/common/1.0/default/OWNERS index f112576ef8..70128c7f21 100644 --- a/camera/common/1.0/default/OWNERS +++ b/camera/common/1.0/default/OWNERS @@ -1 +1 @@ -include platform/frameworks/av/camera:/OWNERS +include platform/frameworks/av:camera/OWNERS From 2dcd353f7f0c73c954c0340059ded6dc4db4f2c9 Mon Sep 17 00:00:00 2001 From: Pawin Vongmasa Date: Wed, 20 Mar 2019 16:11:33 -0700 Subject: [PATCH 593/718] Add Codec2 entry; make Codec2 and Omx optional Test: make cts -j123 && cts-tradefed run cts-dev -m \ CtsMediaTestCases --compatibility:module-arg \ CtsMediaTestCases:include-annotation:\ android.platform.test.annotations.RequiresDevice Bug: 112362730 Bug: 121132171 Bug: 128320274 Change-Id: I4ee174bb434935bdf923a30bab40ed3024f45cbe --- .../compatibility_matrix.current.xml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml index 09cbc200b1..e48cc7937f 100644 --- a/compatibility_matrices/compatibility_matrix.current.xml +++ b/compatibility_matrices/compatibility_matrix.current.xml @@ -271,7 +271,16 @@ default - + + android.hardware.media.c2 + 1.0 + + IComponentStore + default[0-9]* + vendor[0-9]*_software + + + android.hardware.media.omx 1.0 From 4de153cd21367497d69824d9904261ddf414ea27 Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Thu, 4 Apr 2019 12:32:09 -0700 Subject: [PATCH 594/718] IMapper: change an error message Change the error message that prints when IMapper 3.0 isn't present. The old warning was causing unnecessary concerns. Bug: 128013727 Test: compile Change-Id: I197cd953d08a8e9f3bdee92cede973bf1b97dfe2 (cherry picked from commit ccbd24f6336bf7141b9a6e463b89aa027b289bfe) --- .../2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h index 1df496c065..18d184ecb4 100644 --- a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h +++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h @@ -44,7 +44,7 @@ class ComposerHandleImporter { if (mMapper3) { return true; } - ALOGW_IF(!mMapper3, "failed to get mapper 3.0 service"); + ALOGD_IF(!mMapper3, "failed to get mapper 3.0 service, falling back to mapper 2.0"); mMapper2 = mapper::V2_0::IMapper::getService(); ALOGE_IF(!mMapper2, "failed to get mapper 2.0 service"); From 7ae8af54b32a7eb827dbf9f2aedb647c9525a3d9 Mon Sep 17 00:00:00 2001 From: Valerie Hau Date: Thu, 4 Apr 2019 21:46:41 +0000 Subject: [PATCH 595/718] Revert "Revert "Mark layers with color transform client composition if not implemented."" This reverts commit 6f5a48f7af9de2c7cb69ac14a8a8666617f27d21. Reason for revert: Reinstating with fix Below is the original commit message: SET_LAYER_COLOR_TRANSFORM is an optional API, and thus when it's not implemented. we want to make sure we follow the spec to mark those layers as client composition and add them into changed layers list proactively. BUG: 115554640 Test: Verify with setting color transform manually. Change-Id: Ia2e8634b01ee1b5c99893e86ef451f90337ef90f --- .../include/composer-passthrough/2.1/HwcHal.h | 28 ++++- .../include/composer-passthrough/2.3/HwcHal.h | 101 +++++++++++++++++- 2 files changed, 123 insertions(+), 6 deletions(-) diff --git a/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h b/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h index 436e4612bb..5826b126bb 100644 --- a/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h +++ b/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h @@ -162,6 +162,7 @@ class HwcHalImpl : public Hal { Error destroyLayer(Display display, Layer layer) override { int32_t err = mDispatch.destroyLayer(mDevice, display, layer); + onLayerDestroyed(display, layer); return static_cast(err); } @@ -327,6 +328,7 @@ class HwcHalImpl : public Hal { std::vector* outCompositionTypes, uint32_t* outDisplayRequestMask, std::vector* outRequestedLayers, std::vector* outRequestMasks) override { + onBeforeValidateDisplay(display); uint32_t typesCount = 0; uint32_t reqsCount = 0; int32_t err = mDispatch.validateDisplay(mDevice, display, &typesCount, &reqsCount); @@ -335,17 +337,15 @@ class HwcHalImpl : public Hal { return static_cast(err); } - err = mDispatch.getChangedCompositionTypes(mDevice, display, &typesCount, nullptr, nullptr); + err = getChangedCompositionTypes(display, &typesCount, nullptr, nullptr); if (err != HWC2_ERROR_NONE) { return static_cast(err); } std::vector changedLayers(typesCount); std::vector compositionTypes(typesCount); - err = mDispatch.getChangedCompositionTypes( - mDevice, display, &typesCount, changedLayers.data(), - reinterpret_cast::type*>( - compositionTypes.data())); + err = getChangedCompositionTypes(display, &typesCount, changedLayers.data(), + compositionTypes.data()); if (err != HWC2_ERROR_NONE) { return static_cast(err); } @@ -578,6 +578,15 @@ class HwcHalImpl : public Hal { return true; } + virtual int32_t getChangedCompositionTypes(Display display, uint32_t* outTypesCount, + Layer* outChangedLayers, + IComposerClient::Composition* outCompositionTypes) { + return getChangedCompositionTypesInternal(display, outTypesCount, outChangedLayers, + outCompositionTypes); + } + virtual void onLayerDestroyed(Display /* display */, Layer /* layer */) {} + virtual void onBeforeValidateDisplay(Display /* display */) {} + static void hotplugHook(hwc2_callback_data_t callbackData, hwc2_display_t display, int32_t connected) { auto hal = static_cast(callbackData); @@ -596,6 +605,15 @@ class HwcHalImpl : public Hal { hal->mEventCallback->onVsync(display, timestamp); } + int32_t getChangedCompositionTypesInternal(Display display, uint32_t* outTypesCount, + Layer* outChangedLayers, + IComposerClient::Composition* outCompositionTypes) { + return mDispatch.getChangedCompositionTypes( + mDevice, display, outTypesCount, outChangedLayers, + reinterpret_cast::type*>( + outCompositionTypes)); + } + hwc2_device_t* mDevice = nullptr; std::unordered_set mCapabilities; diff --git a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h index 070cf80e44..e2bed95fae 100644 --- a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h +++ b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h @@ -42,6 +42,20 @@ using common::V1_2::PixelFormat; using V2_1::Display; using V2_1::Error; +namespace { + +bool isIdentityMatrix(const float* matrix) { + if (matrix[0] == 1.0 && matrix[1] == 0.0 && matrix[2] == 0.0 && matrix[3] == 0.0 && + matrix[4] == 0.0 && matrix[5] == 1.0 && matrix[6] == 0.0 && matrix[7] == 0.0 && + matrix[8] == 0.0 && matrix[9] == 0.0 && matrix[10] == 1.0 && matrix[11] == 0.0 && + matrix[12] == 0.0 && matrix[13] == 0.0 && matrix[14] == 0.0 && matrix[15] == 1.0) { + return true; + } + return false; +} + +} // namespace + // HwcHalImpl implements V2_*::hal::ComposerHal on top of hwcomposer2 template class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl { @@ -130,6 +144,16 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl { Error setLayerColorTransform(Display display, Layer layer, const float* matrix) override { if (!mDispatch.setLayerColorTransform) { + if (isIdentityMatrix(matrix)) { + // If an identity matrix is set, then we can remove the layer from client + // composition list. + mClientCompositionLayers[display].erase(layer); + return Error::UNSUPPORTED; + } + // if setLayerColorTransform is not implemented, per spec we want to make sure the + // layer marked as client composition, and thus we maintain a list, and mark all these + // layers as client composition later before validate the display. + mClientCompositionLayers[display].insert(layer); return Error::UNSUPPORTED; } int32_t err = mDispatch.setLayerColorTransform(mDevice, display, layer, matrix); @@ -294,7 +318,79 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl { return true; } - private: + int32_t getChangedCompositionTypes(Display display, uint32_t* outTypesCount, + Layer* outChangedLayers, + IComposerClient::Composition* outCompositionTypes) override { + if (outChangedLayers == nullptr && outCompositionTypes == nullptr) { + uint32_t typesCount = 0; + int32_t error = BaseType2_1::getChangedCompositionTypesInternal(display, &typesCount, + nullptr, nullptr); + if (error != HWC2_ERROR_NONE) { + return error; + } + mChangedLayersCache[display].resize(typesCount); + mCompositionTypesCache[display].resize(typesCount); + error = BaseType2_1::getChangedCompositionTypesInternal( + display, &typesCount, mChangedLayersCache[display].data(), + mCompositionTypesCache[display].data()); + if (error != HWC2_ERROR_NONE) { + return error; + } + for (Layer layer : mClientCompositionLayers[display]) { + bool exist = false; + for (uint32_t i = 0; i < typesCount; ++i) { + if (mChangedLayersCache[display][i] == layer) { + exist = true; + break; + } + } + if (!exist) { + mChangedLayersCache[display].push_back(layer); + mCompositionTypesCache[display].push_back(IComposerClient::Composition::CLIENT); + } + } + *outTypesCount = mChangedLayersCache[display].size(); + return error; + } + for (uint32_t i = 0; i < *outTypesCount; ++i) { + if (outChangedLayers != nullptr) { + outChangedLayers[i] = mChangedLayersCache[display][i]; + } + if (outCompositionTypes != nullptr) { + outCompositionTypes[i] = mCompositionTypesCache[display][i]; + } + } + return HWC2_ERROR_NONE; + } + + void onLayerDestroyed(Display display, Layer layer) override { + if (mClientCompositionLayers.find(display) == mClientCompositionLayers.end()) { + return; + } + mClientCompositionLayers[display].erase(layer); + } + + void onBeforeValidateDisplay(Display display) override { + if (mClientCompositionLayers.find(display) == mClientCompositionLayers.end()) { + return; + } + + // clear the cache proactively so that we don't hold too much memory over time. + mChangedLayersCache[display].clear(); + mCompositionTypesCache[display].clear(); + + // SET_LAYER_COLOR_TRANSFORM is optional, and thus if it's not implemented, we need to + // follow the spec to make sure those layers marked as client composition before validate + // the display. + if (!mDispatch.setLayerColorTransform) { + for (Layer layer : mClientCompositionLayers[display]) { + BaseType2_1::setLayerCompositionType( + display, layer, static_cast(IComposerClient::Composition::CLIENT)); + } + } + } + + private: struct { HWC2_PFN_GET_DISPLAY_IDENTIFICATION_DATA getDisplayIdentificationData; HWC2_PFN_SET_LAYER_COLOR_TRANSFORM setLayerColorTransform; @@ -318,6 +414,9 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl { using BaseType2_2::getRenderIntents; using BaseType2_2::setColorMode_2_2; using BaseType2_2::setLayerPerFrameMetadata; + std::map> mClientCompositionLayers; + std::map> mChangedLayersCache; + std::map> mCompositionTypesCache; }; } // namespace detail From dd62969e33b0fc78c61000cd8bb9857225879af3 Mon Sep 17 00:00:00 2001 From: Wei Wang Date: Fri, 5 Apr 2019 10:54:20 -0700 Subject: [PATCH 596/718] Check temperature and cooling device name not empty Bug: 116540200 Test: atest VtsHalThermalV2_0TargetTest Change-Id: I61bfb32ed6115d711dfcc82c2c3ff6eb29951ef2 --- .../2.0/vts/functional/VtsHalThermalV2_0TargetTest.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/thermal/2.0/vts/functional/VtsHalThermalV2_0TargetTest.cpp b/thermal/2.0/vts/functional/VtsHalThermalV2_0TargetTest.cpp index cc2f3df612..d0f2e84afd 100644 --- a/thermal/2.0/vts/functional/VtsHalThermalV2_0TargetTest.cpp +++ b/thermal/2.0/vts/functional/VtsHalThermalV2_0TargetTest.cpp @@ -192,6 +192,9 @@ TEST_F(ThermalHidlTest, TemperatureTest) { } else { EXPECT_NE(ThermalStatusCode::SUCCESS, status.code); } + for (int i = 0; i < temperatures.size(); ++i) { + EXPECT_LT(0u, temperatures[i].name.size()); + } }); auto types = hidl_enum_range(); for (const auto& type : types) { @@ -204,6 +207,7 @@ TEST_F(ThermalHidlTest, TemperatureTest) { } for (int i = 0; i < temperatures.size(); ++i) { EXPECT_EQ(type, temperatures[i].type); + EXPECT_LT(0u, temperatures[i].name.size()); } }); } @@ -246,6 +250,9 @@ TEST_F(ThermalHidlTest, CoolingDeviceTest) { } else { EXPECT_NE(ThermalStatusCode::SUCCESS, status.code); } + for (int i = 0; i < cooling_devices.size(); ++i) { + EXPECT_LT(0u, cooling_devices[i].name.size()); + } }); for (int i = 0; i <= static_cast(CoolingType::COMPONENT); ++i) { auto type = static_cast(i); @@ -258,6 +265,7 @@ TEST_F(ThermalHidlTest, CoolingDeviceTest) { } for (int i = 0; i < cooling_devices.size(); ++i) { EXPECT_EQ(type, cooling_devices[i].type); + EXPECT_LT(0u, cooling_devices[i].name.size()); } }); } From 7986bd66ad8904a1714b5c250507e49209091ff0 Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Mon, 8 Apr 2019 17:02:28 -0700 Subject: [PATCH 597/718] compatibility_matrix: restore P graphics.composer graphics.composer 2.3 was added in Android Q, so it is in the compatibility matrix for target-level 4. Devices updating from P to Q will automatically have this option applies. However, for sanity, we try to keep the P compatibility matrix between releases. This change should have no functional difference except minimizing the delta in this file between P/Q branches. Bug: 126892442 Test: diff compatibility matrix files Test: these matrices are verified at build time Change-Id: I8514c7b6ce4c2670ce7926fb31b09ed783d17dca --- compatibility_matrices/compatibility_matrix.3.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compatibility_matrices/compatibility_matrix.3.xml b/compatibility_matrices/compatibility_matrix.3.xml index 4cb3776b16..e13d293b75 100644 --- a/compatibility_matrices/compatibility_matrix.3.xml +++ b/compatibility_matrices/compatibility_matrix.3.xml @@ -193,7 +193,7 @@ android.hardware.graphics.composer - 2.1-3 + 2.1-2 IComposer default From a04e949c4f16953e7cbb283b00b959161bf17ec9 Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Mon, 8 Apr 2019 17:17:44 -0700 Subject: [PATCH 598/718] current FCM: broadcastradio@2.0::IBroadcastRadio/* This was added to the PI (3) compatibility matrix but not to the current matrix. Bug: 126892442 Test: diff between 3 and current FCM only reflects intentional changes Change-Id: Ib6d243d2015cb847afad63075387945a74c30f13 --- compatibility_matrices/compatibility_matrix.current.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml index e48cc7937f..6c3215e8fc 100644 --- a/compatibility_matrices/compatibility_matrix.current.xml +++ b/compatibility_matrices/compatibility_matrix.current.xml @@ -111,6 +111,14 @@ default + + android.hardware.broadcastradio + 2.0 + + IBroadcastRadio + .* + + android.hardware.camera.provider 2.4-5 From 901ac77a69661802f3cac1f5f6e53509bdf66e88 Mon Sep 17 00:00:00 2001 From: Slava Shklyaev Date: Mon, 8 Apr 2019 15:35:03 +0100 Subject: [PATCH 599/718] Update documentation for MAXIMUM and MINIMUM Bug: 130029167 Test: mma Change-Id: Ieb0c3327a85331243af5e20a1f29f1be316267ee --- current.txt | 2 +- neuralnetworks/1.2/types.hal | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/current.txt b/current.txt index fcb8447696..a8062d312c 100644 --- a/current.txt +++ b/current.txt @@ -514,7 +514,7 @@ b83317b66721241887d2770b5ae95fd5af1e77c5daa7530ecb08fae8892f2b43 android.hardwar 92714960d1a53fc2ec557302b41c7cc93d2636d8364a44bd0f85be0c92927ff8 android.hardware.neuralnetworks@1.2::IExecutionCallback 36e1064c869965dee533c537cefbe87e54db8bd8cd45be7e0e93e00e8a43863a android.hardware.neuralnetworks@1.2::IPreparedModel e1c734d1545e1a4ae749ff1dd9704a8e594c59aea7c8363159dc258e93e0df3b android.hardware.neuralnetworks@1.2::IPreparedModelCallback -9b3963253e521cca19fd81aeca83aee6dcfe3bdf2805c07cb2d3f64381709b71 android.hardware.neuralnetworks@1.2::types +b75126d572c1788682a679ab53c2dbdf3fcd75f754b1370dbf09aaad0e19d397 android.hardware.neuralnetworks@1.2::types cf7a4ba516a638f9b82a249c91fb603042c2d9ca43fd5aad9cf6c0401ed2a5d7 android.hardware.nfc@1.2::INfc abf98c2ae08bf765db54edc8068e36d52eb558cff6706b6fd7c18c65a1f3fc18 android.hardware.nfc@1.2::types 4cb252dc6372a874aef666b92a6e9529915aa187521a700f0789065c3c702ead android.hardware.power.stats@1.0::IPowerStats diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal index 67a61c1ca5..839114fe7b 100644 --- a/neuralnetworks/1.2/types.hal +++ b/neuralnetworks/1.2/types.hal @@ -3516,7 +3516,7 @@ enum OperationType : int32_t { * with input0. * * Outputs: - * * 0: The sum, a tensor of the same {@link OperandType} as input0. + * * 0: A tensor of the same {@link OperandType} as input0. * * Available since API level 29. */ @@ -3537,7 +3537,7 @@ enum OperationType : int32_t { * with input0. * * Outputs: - * * 0: The sum, a tensor of the same {@link OperandType} as input0. + * * 0: A tensor of the same {@link OperandType} as input0. * * Available since API level 29. */ From a83bb3a6478bdccd466096fe05a98c524c5c624b Mon Sep 17 00:00:00 2001 From: EdenSu Date: Tue, 2 Apr 2019 18:18:38 +0800 Subject: [PATCH 600/718] Revert "Fix the compatibility matrix with range" This reverts commit 373a24038612470fec48ee4661922dc2fe3a41a8. Bug: 123249760 Test: Both of P19 & P20 build pass, basic functions work and HAL 1.4 works. Change-Id: I69f794f25d7c87c65df749c39ed29b1e0f476b03 --- compatibility_matrices/compatibility_matrix.3.xml | 3 ++- compatibility_matrices/compatibility_matrix.current.xml | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compatibility_matrices/compatibility_matrix.3.xml b/compatibility_matrices/compatibility_matrix.3.xml index e13d293b75..9933b337bd 100644 --- a/compatibility_matrices/compatibility_matrix.3.xml +++ b/compatibility_matrices/compatibility_matrix.3.xml @@ -302,7 +302,8 @@ android.hardware.radio - 1.0-2 + + 1.0-3 IRadio slot1 diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml index 6c3215e8fc..999c29c5a4 100644 --- a/compatibility_matrices/compatibility_matrix.current.xml +++ b/compatibility_matrices/compatibility_matrix.current.xml @@ -350,8 +350,7 @@ android.hardware.radio - - 1.3-4 + 1.4 IRadio slot1 From 6952ddf5968cef9d97be01337b009e96eb9bbf5f Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Tue, 9 Apr 2019 12:34:12 -0700 Subject: [PATCH 601/718] mapper: support new usage and format Update IMapper to use usage and format from android.hardware.graphics.common@1.2. This enables support for the usage HW_IMAGE_ENCODER and the format HSV_888 which is already being defined and used. Test: IMapper VTS tests Bug: 79465976 Change-Id: I680beb6e5b1cd246c28d17f855f5c76a5831ce06 --- current.txt | 2 +- graphics/mapper/3.0/IMapper.hal | 4 ++-- .../3.0/vts/functional/VtsHalGraphicsMapperV3_0TargetTest.cpp | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/current.txt b/current.txt index a8062d312c..b3be6102ee 100644 --- a/current.txt +++ b/current.txt @@ -487,7 +487,7 @@ b826892686850a9cf2b60ca5845db7185c2196ea4dd765cd80cd163169678a78 android.hardwar 7a2d64095252f85781b2d521f4f11d04ce774544feececcec2088c568656e93c android.hardware.graphics.common@1.2::types 3dff04a36b86660b5807414587e530bb0c294ed56fdff06f8915ba0a9b73f974 android.hardware.graphics.composer@2.3::IComposer 54bc1dc874f8bc0781767786075dafd33a0796c1eea7d2317231b8929280e946 android.hardware.graphics.composer@2.3::IComposerClient -5c8bf8e1af9efe225a4661db8c08ff1b7e13fdc8ed49f35291bd0b6c9436b8f2 android.hardware.graphics.mapper@3.0::IMapper +033e096cb65e5093ee1d0e473892b9a487911d4611dbb65ebecb5cef18338923 android.hardware.graphics.mapper@3.0::IMapper 7183d9d9acfa41a61a64bdfed548e98299265a7bb1821a3ed204173b5c2cfd4a android.hardware.graphics.mapper@3.0::types c3f831a66d5815baf74f5b82fe79cf099542ddae4dfab3f388e1d41828e794fc android.hardware.health.storage@1.0::IGarbageCollectCallback dd1ec219f5d2e2b33c6c0bcb92e63bbedb36f7c716413462848f6b6ae74fc864 android.hardware.health.storage@1.0::IStorage diff --git a/graphics/mapper/3.0/IMapper.hal b/graphics/mapper/3.0/IMapper.hal index a0e4d7afc7..71b56d98c0 100644 --- a/graphics/mapper/3.0/IMapper.hal +++ b/graphics/mapper/3.0/IMapper.hal @@ -16,8 +16,8 @@ package android.hardware.graphics.mapper@3.0; -import android.hardware.graphics.common@1.1::BufferUsage; -import android.hardware.graphics.common@1.1::PixelFormat; +import android.hardware.graphics.common@1.2::BufferUsage; +import android.hardware.graphics.common@1.2::PixelFormat; import android.hardware.graphics.common@1.2::Rect; interface IMapper { diff --git a/graphics/mapper/3.0/vts/functional/VtsHalGraphicsMapperV3_0TargetTest.cpp b/graphics/mapper/3.0/vts/functional/VtsHalGraphicsMapperV3_0TargetTest.cpp index cfae635658..ff73ecf769 100644 --- a/graphics/mapper/3.0/vts/functional/VtsHalGraphicsMapperV3_0TargetTest.cpp +++ b/graphics/mapper/3.0/vts/functional/VtsHalGraphicsMapperV3_0TargetTest.cpp @@ -32,8 +32,8 @@ namespace V3_0 { namespace vts { namespace { -using android::hardware::graphics::common::V1_0::BufferUsage; -using android::hardware::graphics::common::V1_1::PixelFormat; +using android::hardware::graphics::common::V1_2::BufferUsage; +using android::hardware::graphics::common::V1_2::PixelFormat; // Test environment for graphics.mapper. class GraphicsMapperHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { From 0cd000e5ceb9b0fbef3a67b4d883fabfb0267cda Mon Sep 17 00:00:00 2001 From: Raj Mojumder Date: Wed, 10 Apr 2019 15:01:17 -0700 Subject: [PATCH 602/718] NFC: Update OWNERS for default/ BUG: 0 Test: gerrit upload Change-Id: Idd1f901f3a58b5646f620c676cada0de5af9fc89 Signed-off-by: Raj Mojumder Exempt-From-Owner-Approval: Invalid owners. --- nfc/1.0/default/OWNERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nfc/1.0/default/OWNERS b/nfc/1.0/default/OWNERS index 984e5f998b..5febd1dae5 100644 --- a/nfc/1.0/default/OWNERS +++ b/nfc/1.0/default/OWNERS @@ -1,2 +1,2 @@ -eisenbach@google.com -kandoiruchi@google.com +rmojumder@google.com +zachoverflow@google.com From f13b305530c625f196cd54a1d1e5c7924c6ac65a Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Wed, 10 Apr 2019 16:23:12 -0700 Subject: [PATCH 603/718] Fix composer@2.3 VTS tests. Some required APIs must be implemented, and thus passthrough will always assume the function pointers exist. BUG: 130195295 Test: atest VtsHalGraphicsComposerV2_3Target Change-Id: Ic2790363fcb116e66438697b1a2e64e71ffc8ac6 --- .../include/composer-hal/2.3/ComposerClient.h | 1 - .../include/composer-passthrough/2.3/HwcHal.h | 4 ---- .../composer/2.3/utils/vts/ComposerVts.cpp | 14 +++++++---- .../include/composer-vts/2.3/ComposerVts.h | 4 +++- .../VtsHalGraphicsComposerV2_3TargetTest.cpp | 23 +++++++++++-------- 5 files changed, 26 insertions(+), 20 deletions(-) diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h index 1b4079507a..3792c2e4a0 100644 --- a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h +++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h @@ -22,7 +22,6 @@ #include #include -#include #include #include diff --git a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h index e2bed95fae..4829e24daa 100644 --- a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h +++ b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h @@ -221,10 +221,6 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl { Error getDisplayCapabilities( Display display, hidl_vec* outCapabilities) override { - if (!mDispatch.getDisplayCapabilities) { - return Error::UNSUPPORTED; - } - uint32_t count = 0; int32_t error = mDispatch.getDisplayCapabilities(mDevice, display, &count, nullptr); if (error != HWC2_ERROR_NONE) { diff --git a/graphics/composer/2.3/utils/vts/ComposerVts.cpp b/graphics/composer/2.3/utils/vts/ComposerVts.cpp index 4de85d6aa4..b7632097ab 100644 --- a/graphics/composer/2.3/utils/vts/ComposerVts.cpp +++ b/graphics/composer/2.3/utils/vts/ComposerVts.cpp @@ -177,13 +177,17 @@ Error ComposerClient::getDisplayedContentSample(uint64_t display, uint64_t maxFr return error; } -std::vector ComposerClient::getDisplayCapabilities( - Display display) { +Error ComposerClient::getDisplayCapabilities( + Display display, std::vector* outCapabilities) { std::vector capabilities; - mClient->getDisplayCapabilities( - display, [&](const auto&, const auto& tmpCapabilities) { capabilities = tmpCapabilities; }); + Error error = Error::NONE; + mClient->getDisplayCapabilities(display, + [&](const auto& tmpError, const auto& tmpCapabilities) { + error = tmpError; + *outCapabilities = tmpCapabilities; + }); - return capabilities; + return error; } bool ComposerClient::getDisplayBrightnessSupport(Display display) { diff --git a/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h b/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h index a0e764d5e6..0d4e5b8d5b 100644 --- a/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h +++ b/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h @@ -95,7 +95,9 @@ class ComposerClient : public V2_2::vts::ComposerClient { bool getClientTargetSupport_2_3(Display display, uint32_t width, uint32_t height, PixelFormat format, Dataspace dataspace); - std::vector getDisplayCapabilities(Display display); + Error getDisplayCapabilities( + Display display, + std::vector* outDisplayCapabilities); std::vector getPerFrameMetadataKeys_2_3(Display display); diff --git a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp index b983e42d16..56b2e337ae 100644 --- a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp +++ b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp @@ -565,16 +565,19 @@ TEST_F(GraphicsComposerHidlTest, GetDisplayedContentSample) { * Test some constraints. */ TEST_F(GraphicsComposerHidlTest, getDisplayCapabilitiesBasic) { - auto capabilities = mComposerClient->getDisplayCapabilities(mPrimaryDisplay); - bool hasDozeSupport = std::find(capabilities.begin(), capabilities.end(), - IComposerClient::DisplayCapability::DOZE) != capabilities.end(); + std::vector capabilities; + const auto error = mComposerClient->getDisplayCapabilities(mPrimaryDisplay, &capabilities); + ASSERT_EQ(Error::NONE, error); + const bool hasDozeSupport = + std::find(capabilities.begin(), capabilities.end(), + IComposerClient::DisplayCapability::DOZE) != capabilities.end(); EXPECT_EQ(mComposerClient->getDozeSupport(mPrimaryDisplay), hasDozeSupport); } TEST_F(GraphicsComposerHidlTest, getDisplayCapabilitiesBadDisplay) { - mComposerClient->getRaw()->getDisplayCapabilities( - mInvalidDisplayId, - [&](const auto& tmpError, const auto&) { EXPECT_EQ(Error::BAD_DISPLAY, tmpError); }); + std::vector capabilities; + const auto error = mComposerClient->getDisplayCapabilities(mInvalidDisplayId, &capabilities); + EXPECT_EQ(Error::BAD_DISPLAY, error); } TEST_F(GraphicsComposerHidlTest, SetLayerPerFrameMetadataBlobs) { @@ -604,7 +607,9 @@ TEST_F(GraphicsComposerHidlTest, SetLayerPerFrameMetadataBlobs) { * Test that getDisplayBrightnessSupport works as expected. */ TEST_F(GraphicsComposerHidlTest, getDisplayBrightnessSupport) { - auto capabilities = mComposerClient->getDisplayCapabilities(mPrimaryDisplay); + std::vector capabilities; + const auto error = mComposerClient->getDisplayCapabilities(mPrimaryDisplay, &capabilities); + ASSERT_EQ(Error::NONE, error); bool brightnessSupport = std::find(capabilities.begin(), capabilities.end(), IComposerClient::DisplayCapability::BRIGHTNESS) != capabilities.end(); @@ -616,9 +621,9 @@ TEST_F(GraphicsComposerHidlTest, getDisplayBrightnessSupport) { */ TEST_F(GraphicsComposerHidlTest, setDisplayBrightness) { if (!mComposerClient->getDisplayBrightnessSupport(mPrimaryDisplay)) { - EXPECT_EQ(mComposerClient->getRaw()->setDisplayBrightness(mPrimaryDisplay, 0.5f), - Error::UNSUPPORTED); + EXPECT_EQ(mComposerClient->setDisplayBrightness(mPrimaryDisplay, 0.5f), Error::UNSUPPORTED); GTEST_SUCCEED() << "Brightness operations are not supported"; + return; } EXPECT_EQ(mComposerClient->setDisplayBrightness(mPrimaryDisplay, 0.0f), Error::NONE); From 873d889730a3159aa7749674aa8db745d9aac61d Mon Sep 17 00:00:00 2001 From: Max Bires Date: Fri, 8 Feb 2019 12:29:58 -0800 Subject: [PATCH 604/718] Expanding VTS test coverage Keymaster VTS test coverage on 4.0 was incomplete. This significantly expands the coverage of the spec. The bugs listed are errors found that these tests will cover, but are not indicative of the complete set of things tested. Test: atest VtsHalKeymasterV4_0TargetTest Bug: 79953279 Bug: 119553313 Bug: 119541233 Bug: 119396995 Bug: 119542230 Bug: 119549128 Bug: 119549677 Bug: 122184852 Bug: 122261372 Change-Id: I42d78091b48398597bbebe1d9c91b806494ddf4c (cherry picked from commit 8c0edf6c84253afb4500a386b83c858e94331d32) --- keymaster/4.0/support/attestation_record.cpp | 58 ++++ .../keymasterV4_0/attestation_record.h | 13 + .../4.0/vts/functional/KeymasterHidlTest.cpp | 42 +++ .../4.0/vts/functional/KeymasterHidlTest.h | 5 + .../functional/keymaster_hidl_hal_test.cpp | 291 +++++++++++++++++- 5 files changed, 399 insertions(+), 10 deletions(-) diff --git a/keymaster/4.0/support/attestation_record.cpp b/keymaster/4.0/support/attestation_record.cpp index 6de0c1c629..000d46e7db 100644 --- a/keymaster/4.0/support/attestation_record.cpp +++ b/keymaster/4.0/support/attestation_record.cpp @@ -16,6 +16,7 @@ #include +#include #include #include @@ -26,6 +27,8 @@ #include #include +#define AT __FILE__ ":" << __LINE__ + namespace android { namespace hardware { namespace keymaster { @@ -304,6 +307,61 @@ ErrorCode parse_attestation_record(const uint8_t* asn1_key_desc, size_t asn1_key return extract_auth_list(record->tee_enforced, tee_enforced); } +ErrorCode parse_root_of_trust(const uint8_t* asn1_key_desc, size_t asn1_key_desc_len, + hidl_vec* verified_boot_key, + keymaster_verified_boot_t* verified_boot_state, bool* device_locked, + hidl_vec* verified_boot_hash) { + if (!verified_boot_key || !verified_boot_state || !device_locked || !verified_boot_hash) { + LOG(ERROR) << AT << "null pointer input(s)"; + return ErrorCode::INVALID_ARGUMENT; + } + const uint8_t* p = asn1_key_desc; + KM_KEY_DESCRIPTION_Ptr record(d2i_KM_KEY_DESCRIPTION(nullptr, &p, asn1_key_desc_len)); + if (!record.get()) { + LOG(ERROR) << AT << "Failed record parsing"; + return ErrorCode::UNKNOWN_ERROR; + } + if (!record->tee_enforced) { + LOG(ERROR) << AT << "Failed hardware characteristic parsing"; + return ErrorCode::INVALID_ARGUMENT; + } + if (!record->tee_enforced->root_of_trust) { + LOG(ERROR) << AT << "Failed root of trust parsing"; + return ErrorCode::INVALID_ARGUMENT; + } + if (!record->tee_enforced->root_of_trust->verified_boot_key) { + LOG(ERROR) << AT << "Failed verified boot key parsing"; + return ErrorCode::INVALID_ARGUMENT; + } + KM_ROOT_OF_TRUST* root_of_trust = record->tee_enforced->root_of_trust; + + auto& vb_key = root_of_trust->verified_boot_key; + verified_boot_key->resize(vb_key->length); + memcpy(verified_boot_key->data(), vb_key->data, vb_key->length); + + *verified_boot_state = static_cast( + ASN1_ENUMERATED_get(root_of_trust->verified_boot_state)); + if (!verified_boot_state) { + LOG(ERROR) << AT << "Failed verified boot state parsing"; + return ErrorCode::INVALID_ARGUMENT; + } + + *device_locked = root_of_trust->device_locked; + if (!device_locked) { + LOG(ERROR) << AT << "Failed device locked parsing"; + return ErrorCode::INVALID_ARGUMENT; + } + + auto& vb_hash = root_of_trust->verified_boot_hash; + if (!vb_hash) { + LOG(ERROR) << AT << "Failed verified boot hash parsing"; + return ErrorCode::INVALID_ARGUMENT; + } + verified_boot_hash->resize(vb_hash->length); + memcpy(verified_boot_hash->data(), vb_hash->data, vb_hash->length); + return ErrorCode::OK; // KM_ERROR_OK; +} + } // namespace V4_0 } // namespace keymaster } // namespace hardware diff --git a/keymaster/4.0/support/include/keymasterV4_0/attestation_record.h b/keymaster/4.0/support/include/keymasterV4_0/attestation_record.h index fae403a7c5..eb95ceae13 100644 --- a/keymaster/4.0/support/include/keymasterV4_0/attestation_record.h +++ b/keymaster/4.0/support/include/keymasterV4_0/attestation_record.h @@ -42,6 +42,13 @@ class AuthorizationSet; */ static const char kAttestionRecordOid[] = "1.3.6.1.4.1.11129.2.1.17"; +enum keymaster_verified_boot_t { + KM_VERIFIED_BOOT_VERIFIED = 0, + KM_VERIFIED_BOOT_SELF_SIGNED = 1, + KM_VERIFIED_BOOT_UNVERIFIED = 2, + KM_VERIFIED_BOOT_FAILED = 3, +}; + ErrorCode parse_attestation_record(const uint8_t* asn1_key_desc, size_t asn1_key_desc_len, uint32_t* attestation_version, // SecurityLevel* attestation_security_level, @@ -51,6 +58,12 @@ ErrorCode parse_attestation_record(const uint8_t* asn1_key_desc, size_t asn1_key AuthorizationSet* software_enforced, AuthorizationSet* tee_enforced, // hidl_vec* unique_id); + +ErrorCode parse_root_of_trust(const uint8_t* asn1_key_desc, size_t asn1_key_desc_len, + hidl_vec* verified_boot_key, + keymaster_verified_boot_t* verified_boot_state, bool* device_locked, + hidl_vec* verified_boot_hash); + } // namespace V4_0 } // namespace keymaster } // namespace hardware diff --git a/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp b/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp index 995ae4f45c..a7b6c981f4 100644 --- a/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp +++ b/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp @@ -16,6 +16,7 @@ #include "KeymasterHidlTest.h" +#include #include #include @@ -206,6 +207,47 @@ void KeymasterHidlTest::CheckedDeleteKey() { CheckedDeleteKey(&key_blob_); } +void KeymasterHidlTest::CheckCreationDateTime( + const AuthorizationSet& sw_enforced, + std::chrono::time_point creation) { + for (int i = 0; i < sw_enforced.size(); i++) { + if (sw_enforced[i].tag == TAG_CREATION_DATETIME) { + std::chrono::time_point now = + std::chrono::system_clock::now(); + std::chrono::time_point reported_time{ + std::chrono::milliseconds(sw_enforced[i].f.dateTime)}; + // The test is flaky for EC keys, so a buffer time of 1 second will be added. + EXPECT_LE(creation - 1s, reported_time); + EXPECT_LE(reported_time, now + 1s); + } + } +} + +void KeymasterHidlTest::CheckGetCharacteristics(const HidlBuf& key_blob, const HidlBuf& client_id, + const HidlBuf& app_data, + KeyCharacteristics* key_characteristics) { + HidlBuf empty_buf = {}; + EXPECT_EQ(ErrorCode::OK, + GetCharacteristics(key_blob, client_id, app_data, key_characteristics)); + EXPECT_GT(key_characteristics->hardwareEnforced.size(), 0); + EXPECT_GT(key_characteristics->softwareEnforced.size(), 0); + + EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB, + GetCharacteristics(key_blob, empty_buf, app_data, key_characteristics)); + EXPECT_EQ(key_characteristics->hardwareEnforced.size(), 0); + EXPECT_EQ(key_characteristics->softwareEnforced.size(), 0); + + EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB, + GetCharacteristics(key_blob, client_id, empty_buf, key_characteristics)); + EXPECT_EQ(key_characteristics->hardwareEnforced.size(), 0); + EXPECT_EQ(key_characteristics->softwareEnforced.size(), 0); + + EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB, + GetCharacteristics(key_blob, empty_buf, empty_buf, key_characteristics)); + EXPECT_EQ(key_characteristics->hardwareEnforced.size(), 0); + EXPECT_EQ(key_characteristics->softwareEnforced.size(), 0); +} + ErrorCode KeymasterHidlTest::GetCharacteristics(const HidlBuf& key_blob, const HidlBuf& client_id, const HidlBuf& app_data, KeyCharacteristics* key_characteristics) { diff --git a/keymaster/4.0/vts/functional/KeymasterHidlTest.h b/keymaster/4.0/vts/functional/KeymasterHidlTest.h index 4cd6a5b577..015fc43752 100644 --- a/keymaster/4.0/vts/functional/KeymasterHidlTest.h +++ b/keymaster/4.0/vts/functional/KeymasterHidlTest.h @@ -131,6 +131,11 @@ class KeymasterHidlTest : public ::testing::VtsHalHidlTargetTestBase { void CheckedDeleteKey(HidlBuf* key_blob, bool keep_key_blob = false); void CheckedDeleteKey(); + static void CheckCreationDateTime(const AuthorizationSet& sw_enforced, + std::chrono::time_point creation); + + void CheckGetCharacteristics(const HidlBuf& key_blob, const HidlBuf& client_id, + const HidlBuf& app_data, KeyCharacteristics* key_characteristics); ErrorCode GetCharacteristics(const HidlBuf& key_blob, const HidlBuf& client_id, const HidlBuf& app_data, KeyCharacteristics* key_characteristics); ErrorCode GetCharacteristics(const HidlBuf& key_blob, KeyCharacteristics* key_characteristics); diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp index 5c07532c9f..fc96724225 100644 --- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp +++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp @@ -313,8 +313,9 @@ std::string make_string(const uint8_t (&a)[N]) { bool verify_attestation_record(const string& challenge, const string& app_id, AuthorizationSet expected_sw_enforced, - AuthorizationSet expected_tee_enforced, SecurityLevel security_level, - const hidl_vec& attestation_cert) { + AuthorizationSet expected_hw_enforced, SecurityLevel security_level, + const hidl_vec& attestation_cert, + std::chrono::time_point creation_time) { X509_Ptr cert(parse_cert_blob(attestation_cert)); EXPECT_TRUE(!!cert.get()); if (!cert.get()) return false; @@ -324,7 +325,7 @@ bool verify_attestation_record(const string& challenge, const string& app_id, if (!attest_rec) return false; AuthorizationSet att_sw_enforced; - AuthorizationSet att_tee_enforced; + AuthorizationSet att_hw_enforced; uint32_t att_attestation_version; uint32_t att_keymaster_version; SecurityLevel att_attestation_security_level; @@ -341,7 +342,7 @@ bool verify_attestation_record(const string& challenge, const string& app_id, &att_keymaster_security_level, // &att_challenge, // &att_sw_enforced, // - &att_tee_enforced, // + &att_hw_enforced, // &att_unique_id); EXPECT_EQ(ErrorCode::OK, error); if (error != ErrorCode::OK) return false; @@ -357,13 +358,105 @@ bool verify_attestation_record(const string& challenge, const string& app_id, EXPECT_EQ(challenge.length(), att_challenge.size()); EXPECT_EQ(0, memcmp(challenge.data(), att_challenge.data(), challenge.length())); + char property_value[PROPERTY_VALUE_MAX] = {}; + for (int i = 0; i < att_hw_enforced.size(); i++) { + if (att_hw_enforced[i].tag == TAG_BOOT_PATCHLEVEL || + att_hw_enforced[i].tag == TAG_VENDOR_PATCHLEVEL) { + std::string date = std::to_string(att_hw_enforced[i].f.integer); + // strptime seems to require delimiters, but the tag value will be YYYYMMDD + date.insert(6, "-"); + date.insert(4, "-"); + EXPECT_EQ(date.size(), 10); + struct tm time; + strptime(date.c_str(), "%Y-%m-%d", &time); + + // Day of the month (0-31) + EXPECT_GT(time.tm_mday, 0); + EXPECT_LT(time.tm_mday, 32); + // Months since Jan (0-11) + EXPECT_GE(time.tm_mon, 0); + EXPECT_LT(time.tm_mon, 12); + // Years since 1900 + EXPECT_GT(time.tm_year, 110); + EXPECT_LT(time.tm_year, 200); + } + } + + // Check to make sure boolean values are properly encoded. Presence of a boolean tag indicates + // true. A provided boolean tag that can be pulled back out of the certificate indicates correct + // encoding. No need to check if it's in both lists, since the AuthorizationSet compare below + // will handle mismatches of tags. + EXPECT_TRUE(expected_hw_enforced.Contains(TAG_NO_AUTH_REQUIRED)); + + // Alternatively this checks the opposite - a false boolean tag (one that isn't provided in + // the authorization list during key generation) isn't being attested to in the certificate. + EXPECT_FALSE(expected_hw_enforced.Contains(TAG_TRUSTED_USER_PRESENCE_REQUIRED)); + EXPECT_FALSE(att_hw_enforced.Contains(TAG_TRUSTED_USER_PRESENCE_REQUIRED)); + + KeymasterHidlTest::CheckCreationDateTime(att_sw_enforced, creation_time); + + if (att_hw_enforced.Contains(TAG_ALGORITHM, Algorithm::EC)) { + // For ECDSA keys, either an EC_CURVE or a KEY_SIZE can be specified, but one must be. + EXPECT_TRUE(att_hw_enforced.Contains(TAG_EC_CURVE) || + att_hw_enforced.Contains(TAG_KEY_SIZE)); + } + + // Test root of trust elements + HidlBuf verified_boot_key; + keymaster_verified_boot_t verified_boot_state; + bool device_locked; + HidlBuf verified_boot_hash; + error = parse_root_of_trust(attest_rec->data, attest_rec->length, &verified_boot_key, + &verified_boot_state, &device_locked, &verified_boot_hash); + EXPECT_EQ(ErrorCode::OK, error); + + property_get("ro.boot.vbmeta.digest", property_value, "nogood"); + EXPECT_NE(strcmp(property_value, "nogood"), 0); + string prop_string(property_value); + EXPECT_EQ(prop_string.size(), 64); + EXPECT_EQ(0, memcmp(verified_boot_hash.data(), prop_string.data(), verified_boot_hash.size())); + + property_get("ro.boot.vbmeta.device_state", property_value, "nogood"); + EXPECT_NE(property_value, "nogood"); + if (!strcmp(property_value, "unlocked")) { + EXPECT_FALSE(device_locked); + } else { + EXPECT_TRUE(device_locked); + } + + // Verified boot key should be all 0's if the boot state is not verified or self signed + std::string empty_boot_key(32, '\0'); + std::string verified_boot_key_str((const char*)verified_boot_key.data(), + verified_boot_key.size()); + property_get("ro.boot.verifiedbootstate", property_value, "nogood"); + EXPECT_NE(property_value, "nogood"); + if (!strcmp(property_value, "green")) { + EXPECT_EQ(verified_boot_state, KM_VERIFIED_BOOT_VERIFIED); + EXPECT_NE(0, memcmp(verified_boot_key.data(), empty_boot_key.data(), + verified_boot_key.size())); + } else if (!strcmp(property_value, "yellow")) { + EXPECT_EQ(verified_boot_state, KM_VERIFIED_BOOT_SELF_SIGNED); + EXPECT_NE(0, memcmp(verified_boot_key.data(), empty_boot_key.data(), + verified_boot_key.size())); + } else if (!strcmp(property_value, "orange")) { + EXPECT_EQ(verified_boot_state, KM_VERIFIED_BOOT_UNVERIFIED); + EXPECT_EQ(0, memcmp(verified_boot_key.data(), empty_boot_key.data(), + verified_boot_key.size())); + } else if (!strcmp(property_value, "red")) { + EXPECT_EQ(verified_boot_state, KM_VERIFIED_BOOT_FAILED); + EXPECT_EQ(0, memcmp(verified_boot_key.data(), empty_boot_key.data(), + verified_boot_key.size())); + } else { + EXPECT_TRUE(false); + } + att_sw_enforced.Sort(); expected_sw_enforced.Sort(); EXPECT_EQ(filter_tags(expected_sw_enforced), filter_tags(att_sw_enforced)); - att_tee_enforced.Sort(); - expected_tee_enforced.Sort(); - EXPECT_EQ(filter_tags(expected_tee_enforced), filter_tags(att_tee_enforced)); + att_hw_enforced.Sort(); + expected_hw_enforced.Sort(); + EXPECT_EQ(filter_tags(expected_hw_enforced), filter_tags(att_hw_enforced)); return true; } @@ -445,6 +538,24 @@ TEST_F(NewKeyGenerationTest, Rsa) { } } +/* + * NewKeyGenerationTest.RsaCheckCreationDateTime + * + * Verifies that creation date time is correct. + */ +TEST_F(NewKeyGenerationTest, RsaCheckCreationDateTime) { + KeyCharacteristics key_characteristics; + auto creation_time = std::chrono::system_clock::now(); + ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() + .Authorization(TAG_NO_AUTH_REQUIRED) + .RsaSigningKey(2048, 3) + .Digest(Digest::NONE) + .Padding(PaddingMode::NONE))); + GetCharacteristics(key_blob_, &key_characteristics); + AuthorizationSet sw_enforced = key_characteristics.softwareEnforced; + CheckCreationDateTime(sw_enforced, creation_time); +} + /* * NewKeyGenerationTest.NoInvalidRsaSizes * @@ -508,6 +619,23 @@ TEST_F(NewKeyGenerationTest, Ecdsa) { } } +/* + * NewKeyGenerationTest.EcCheckCreationDateTime + * + * Verifies that creation date time is correct. + */ +TEST_F(NewKeyGenerationTest, EcCheckCreationDateTime) { + KeyCharacteristics key_characteristics; + auto creation_time = std::chrono::system_clock::now(); + ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() + .Authorization(TAG_NO_AUTH_REQUIRED) + .EcdsaSigningKey(256) + .Digest(Digest::NONE))); + GetCharacteristics(key_blob_, &key_characteristics); + AuthorizationSet sw_enforced = key_characteristics.softwareEnforced; + CheckCreationDateTime(sw_enforced, creation_time); +} + /* * NewKeyGenerationTest.EcdsaDefaultSize * @@ -747,6 +875,69 @@ TEST_F(SigningOperationsTest, RsaSuccess) { message, AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE)); } +/* + * SigningOperationsTest.RsaGetKeyCharacteristicsRequiresCorrectAppIdAppData + * + * Verifies that getting RSA key characteristics requires the correct app ID/data. + */ +TEST_F(SigningOperationsTest, RsaGetKeyCharacteristicsRequiresCorrectAppIdAppData) { + HidlBuf key_blob; + KeyCharacteristics key_characteristics; + ASSERT_EQ(ErrorCode::OK, + GenerateKey(AuthorizationSetBuilder() + .Authorization(TAG_NO_AUTH_REQUIRED) + .RsaSigningKey(2048, 65537) + .Digest(Digest::NONE) + .Padding(PaddingMode::NONE) + .Authorization(TAG_APPLICATION_ID, HidlBuf("clientid")) + .Authorization(TAG_APPLICATION_DATA, HidlBuf("appdata")), + &key_blob, &key_characteristics)); + CheckGetCharacteristics(key_blob, HidlBuf("clientid"), HidlBuf("appdata"), + &key_characteristics); +} + +/* + * SigningOperationsTest.RsaUseRequiresCorrectAppIdAppData + * + * Verifies that using an RSA key requires the correct app ID/data. + */ +TEST_F(SigningOperationsTest, RsaUseRequiresCorrectAppIdAppData) { + ASSERT_EQ(ErrorCode::OK, + GenerateKey(AuthorizationSetBuilder() + .Authorization(TAG_NO_AUTH_REQUIRED) + .RsaSigningKey(2048, 65537) + .Digest(Digest::NONE) + .Padding(PaddingMode::NONE) + .Authorization(TAG_APPLICATION_ID, HidlBuf("clientid")) + .Authorization(TAG_APPLICATION_DATA, HidlBuf("appdata")))); + EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB, + Begin(KeyPurpose::SIGN, + AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE))); + AbortIfNeeded(); + EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB, + Begin(KeyPurpose::SIGN, + AuthorizationSetBuilder() + .Digest(Digest::NONE) + .Padding(PaddingMode::NONE) + .Authorization(TAG_APPLICATION_ID, HidlBuf("clientid")))); + AbortIfNeeded(); + EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB, + Begin(KeyPurpose::SIGN, + AuthorizationSetBuilder() + .Digest(Digest::NONE) + .Padding(PaddingMode::NONE) + .Authorization(TAG_APPLICATION_DATA, HidlBuf("appdata")))); + AbortIfNeeded(); + EXPECT_EQ(ErrorCode::OK, + Begin(KeyPurpose::SIGN, + AuthorizationSetBuilder() + .Digest(Digest::NONE) + .Padding(PaddingMode::NONE) + .Authorization(TAG_APPLICATION_DATA, HidlBuf("appdata")) + .Authorization(TAG_APPLICATION_ID, HidlBuf("clientid")))); + AbortIfNeeded(); +} + /* * SigningOperationsTest.RsaPssSha256Success * @@ -1123,6 +1314,63 @@ TEST_F(SigningOperationsTest, EcdsaNoDigestHugeData) { SignMessage(message, AuthorizationSetBuilder().Digest(Digest::NONE)); } +/* + * SigningOperationsTest.EcGetKeyCharacteristicsRequiresCorrectAppIdAppData + * + * Verifies that getting EC key characteristics requires the correct app ID/data. + */ +TEST_F(SigningOperationsTest, EcGetKeyCharacteristicsRequiresCorrectAppIdAppData) { + HidlBuf key_blob; + KeyCharacteristics key_characteristics; + ASSERT_EQ(ErrorCode::OK, + GenerateKey(AuthorizationSetBuilder() + .Authorization(TAG_NO_AUTH_REQUIRED) + .EcdsaSigningKey(256) + .Digest(Digest::NONE) + .Authorization(TAG_APPLICATION_ID, HidlBuf("clientid")) + .Authorization(TAG_APPLICATION_DATA, HidlBuf("appdata")), + &key_blob, &key_characteristics)); + CheckGetCharacteristics(key_blob, HidlBuf("clientid"), HidlBuf("appdata"), + &key_characteristics); +} + +/* + * SigningOperationsTest.EcUseRequiresCorrectAppIdAppData + * + * Verifies that using an EC key requires the correct app ID/data. + */ +TEST_F(SigningOperationsTest, EcUseRequiresCorrectAppIdAppData) { + ASSERT_EQ(ErrorCode::OK, + GenerateKey(AuthorizationSetBuilder() + .Authorization(TAG_NO_AUTH_REQUIRED) + .EcdsaSigningKey(256) + .Digest(Digest::NONE) + .Authorization(TAG_APPLICATION_ID, HidlBuf("clientid")) + .Authorization(TAG_APPLICATION_DATA, HidlBuf("appdata")))); + EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB, + Begin(KeyPurpose::SIGN, AuthorizationSetBuilder().Digest(Digest::NONE))); + AbortIfNeeded(); + EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB, + Begin(KeyPurpose::SIGN, + AuthorizationSetBuilder() + .Digest(Digest::NONE) + .Authorization(TAG_APPLICATION_ID, HidlBuf("clientid")))); + AbortIfNeeded(); + EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB, + Begin(KeyPurpose::SIGN, + AuthorizationSetBuilder() + .Digest(Digest::NONE) + .Authorization(TAG_APPLICATION_DATA, HidlBuf("appdata")))); + AbortIfNeeded(); + EXPECT_EQ(ErrorCode::OK, + Begin(KeyPurpose::SIGN, + AuthorizationSetBuilder() + .Digest(Digest::NONE) + .Authorization(TAG_APPLICATION_DATA, HidlBuf("appdata")) + .Authorization(TAG_APPLICATION_ID, HidlBuf("clientid")))); + AbortIfNeeded(); +} + /* * SigningOperationsTest.AesEcbSign * @@ -3922,6 +4170,7 @@ typedef KeymasterHidlTest AttestationTest; * Verifies that attesting to RSA keys works and generates the expected output. */ TEST_F(AttestationTest, RsaAttestation) { + auto creation_time = std::chrono::system_clock::now(); ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() .Authorization(TAG_NO_AUTH_REQUIRED) .RsaSigningKey(2048, 65537) @@ -3946,7 +4195,7 @@ TEST_F(AttestationTest, RsaAttestation) { EXPECT_TRUE(verify_attestation_record("challenge", "foo", // key_characteristics_.softwareEnforced, // key_characteristics_.hardwareEnforced, // - SecLevel(), cert_chain[0])); + SecLevel(), cert_chain[0], creation_time)); } /* @@ -3969,12 +4218,35 @@ TEST_F(AttestationTest, RsaAttestationRequiresAppId) { &cert_chain)); } +/* + * AttestationTest.RsaAttestationRequiresCorrectAppId + * + * Verifies that attesting to RSA requires the correct app ID. + */ +TEST_F(AttestationTest, RsaAttestationRequiresCorrectAppId) { + ASSERT_EQ(ErrorCode::OK, + GenerateKey(AuthorizationSetBuilder() + .Authorization(TAG_NO_AUTH_REQUIRED) + .RsaSigningKey(2048, 65537) + .Digest(Digest::NONE) + .Padding(PaddingMode::NONE) + .Authorization(TAG_APPLICATION_ID, HidlBuf("lol")))); + + hidl_vec> cert_chain; + EXPECT_EQ(ErrorCode::ATTESTATION_APPLICATION_ID_MISSING, + AttestKey(AuthorizationSetBuilder() + .Authorization(TAG_ATTESTATION_CHALLENGE, HidlBuf("challenge")) + .Authorization(TAG_APPLICATION_ID, HidlBuf("heh")), + &cert_chain)); +} + /* * AttestationTest.EcAttestation * * Verifies that attesting to EC keys works and generates the expected output. */ TEST_F(AttestationTest, EcAttestation) { + auto creation_time = std::chrono::system_clock::now(); ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() .Authorization(TAG_NO_AUTH_REQUIRED) .EcdsaSigningKey(EcCurve::P_256) @@ -3993,11 +4265,10 @@ TEST_F(AttestationTest, EcAttestation) { string signature = SignMessage(message, AuthorizationSetBuilder().Digest(Digest::SHA_2_256)); EXPECT_TRUE(verify_chain(cert_chain, message, signature)); - EXPECT_TRUE(verify_attestation_record("challenge", "foo", // key_characteristics_.softwareEnforced, // key_characteristics_.hardwareEnforced, // - SecLevel(), cert_chain[0])); + SecLevel(), cert_chain[0], creation_time)); } /* From 51ea7c984b7af8bf2dc147f2698dee6972b64615 Mon Sep 17 00:00:00 2001 From: Yin-Chia Yeh Date: Fri, 5 Apr 2019 14:15:29 -0700 Subject: [PATCH 605/718] Camera: require torch API support for Android Q Torch API was mandated on legacy libhardware camera module 2.4. We kept the option of not supporting this API because the first HIDL legacy wrapper needs to also support libhardware camera module 1.0 + HAL1.0. Now that HAL 1.0 is no longer supported, we can reenforce the torch API being supported by camera HAL as this is critical to power usage of flashlight usecase. Test: adb shell VtsHalCameraProviderV2_4TargetTest --hal_service_instance=android.hardware.camera.provider@2.4::ICameraProvider/legacy/0 Bug: 113336515 Change-Id: I0dcf2e7a5cddadcd097caf6913625d8a607065f8 --- camera/provider/2.4/ICameraProvider.hal | 3 ++- .../VtsHalCameraProviderV2_4TargetTest.cpp | 25 +++++++++++++++---- current.txt | 1 + 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/camera/provider/2.4/ICameraProvider.hal b/camera/provider/2.4/ICameraProvider.hal index 8773bc0819..74c3ff1693 100644 --- a/camera/provider/2.4/ICameraProvider.hal +++ b/camera/provider/2.4/ICameraProvider.hal @@ -140,7 +140,8 @@ interface ICameraProvider { * Torch API support cannot be queried. This may be due to * a failure to initialize the camera subsystem, for example. * @return support Whether the camera devices known to this provider - * supports setTorchMode API or not. + * supports setTorchMode API or not. Devices launched with SDK + * level 29 or higher must return true. * */ isSetTorchModeSupported() generates (Status status, bool support); diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp index 5dfc783efa..797a198595 100644 --- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp +++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp @@ -272,6 +272,16 @@ namespace { ALOGW("Unexpected HAL status code %d", s); return Status::OPERATION_NOT_SUPPORTED; } + + void getFirstApiLevel(/*out*/int32_t* outApiLevel) { + int32_t firstApiLevel = property_get_int32("ro.product.first_api_level", /*default*/-1); + if (firstApiLevel < 0) { + firstApiLevel = property_get_int32("ro.build.version.sdk", /*default*/-1); + } + ASSERT_GT(firstApiLevel, 0); // first_api_level must exist + *outApiLevel = firstApiLevel; + return; + } } // Test environment for camera @@ -1483,11 +1493,8 @@ hidl_vec CameraHidlTest::getCameraDeviceNames(sp p // Test devices with first_api_level >= P does not advertise device@1.0 TEST_F(CameraHidlTest, noHal1AfterP) { constexpr int32_t HAL1_PHASE_OUT_API_LEVEL = 28; - int32_t firstApiLevel = property_get_int32("ro.product.first_api_level", /*default*/-1); - if (firstApiLevel < 0) { - firstApiLevel = property_get_int32("ro.build.version.sdk", /*default*/-1); - } - ASSERT_GT(firstApiLevel, 0); // first_api_level must exist + int32_t firstApiLevel = 0; + getFirstApiLevel(&firstApiLevel); // all devices with first API level == 28 and <= 1GB of RAM must set low_ram // and thus be allowed to continue using HAL1 @@ -1508,11 +1515,19 @@ TEST_F(CameraHidlTest, noHal1AfterP) { } // Test if ICameraProvider::isTorchModeSupported returns Status::OK +// Also if first_api_level >= Q torch API must be supported. TEST_F(CameraHidlTest, isTorchModeSupported) { + constexpr int32_t API_LEVEL_Q = 29; + int32_t firstApiLevel = 0; + getFirstApiLevel(&firstApiLevel); + Return ret; ret = mProvider->isSetTorchModeSupported([&](auto status, bool support) { ALOGI("isSetTorchModeSupported returns status:%d supported:%d", (int)status, support); ASSERT_EQ(Status::OK, status); + if (firstApiLevel >= API_LEVEL_Q) { + ASSERT_EQ(true, support); + } }); ASSERT_TRUE(ret.isOk()); } diff --git a/current.txt b/current.txt index 8518c5e2bd..a609f97bcc 100644 --- a/current.txt +++ b/current.txt @@ -391,6 +391,7 @@ cd4330c3196bda1d642a32abfe23a7d64ebfbda721940643af6867af3b3f0aa9 android.hardwar f8a19622cb0cc890913b1ef3e32b675ffb26089a09e02fef4056ebad324d2b5d android.hardware.camera.device@3.4::types 291638a1b6d4e63283e9e722ab5049d9351717ffa2b66162124f84d1aa7c2835 android.hardware.camera.metadata@3.2::types 23780340c686ee86986aa5a9755c2d8566224fed177bbb22a5ebf06be574b60c android.hardware.camera.metadata@3.3::types +05d1ee760d81cdd2dc7a70ce0241af9fa830edae33b4be83d9bf5fffe05ddc6f android.hardware.camera.provider@2.4::ICameraProvider da33234403ff5d60f3473711917b9948e6484a4260b5247acdafb111193a9de2 android.hardware.configstore@1.0::ISurfaceFlingerConfigs 21165b8e30c4b2d52980e4728f661420adc16e38bbe73476c06b2085be908f4c android.hardware.gnss@1.0::IGnssCallback d702fb01dc2a0733aa820b7eb65435ee3334f75632ef880bafd2fb8803a20a58 android.hardware.gnss@1.0::IGnssMeasurementCallback From 15d5202fa7705146eaa373390d247d707e697fce Mon Sep 17 00:00:00 2001 From: "Harpreet \"Eli\" Sangha" Date: Wed, 10 Apr 2019 16:38:12 +0900 Subject: [PATCH 606/718] vibrator: example: Enforce API-Specific Effect Range Bug: 130265348 Test: vts-tradefed run singleCommand vts-hal -m VtsHalVibratorV1_2Target Change-Id: I45cc2ad64295d6a63ef3280d4d5b869e19786ce3 Signed-off-by: Harpreet "Eli" Sangha --- vibrator/1.3/example/Vibrator.cpp | 25 +++++++++++++++++++++---- vibrator/1.3/example/Vibrator.h | 3 +++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/vibrator/1.3/example/Vibrator.cpp b/vibrator/1.3/example/Vibrator.cpp index 0cb37e6a36..b529437108 100644 --- a/vibrator/1.3/example/Vibrator.cpp +++ b/vibrator/1.3/example/Vibrator.cpp @@ -56,27 +56,30 @@ Return Vibrator::supportsAmplitudeControl() { } Return Vibrator::setAmplitude(uint8_t amplitude) { + if (!amplitude) { + return Status::BAD_VALUE; + } ALOGI("Amplitude: %u -> %u\n", mAmplitude, amplitude); mAmplitude = amplitude; return Status::OK; } Return Vibrator::perform(V1_0::Effect effect, EffectStrength strength, perform_cb _hidl_cb) { - return perform_1_1(static_cast(effect), strength, _hidl_cb); + return perform(effect, strength, _hidl_cb); } // Methods from ::android::hardware::vibrator::V1_1::IVibrator follow. Return Vibrator::perform_1_1(V1_1::Effect_1_1 effect, EffectStrength strength, perform_cb _hidl_cb) { - return perform_1_2(static_cast(effect), strength, _hidl_cb); + return perform(effect, strength, _hidl_cb); } // Methods from ::android::hardware::vibrator::V1_2::IVibrator follow. Return Vibrator::perform_1_2(V1_2::Effect effect, EffectStrength strength, perform_cb _hidl_cb) { - return perform_1_3(static_cast(effect), strength, _hidl_cb); + return perform(effect, strength, _hidl_cb); } // Methods from ::android::hardware::vibrator::V1_3::IVibrator follow. @@ -98,6 +101,12 @@ Return Vibrator::setExternalControl(bool enabled) { } Return Vibrator::perform_1_3(Effect effect, EffectStrength strength, perform_cb _hidl_cb) { + return perform(effect, strength, _hidl_cb); +} + +// Private methods follow. + +Return Vibrator::perform(Effect effect, EffectStrength strength, perform_cb _hidl_cb) { uint8_t amplitude; uint32_t ms; Status status = Status::OK; @@ -123,7 +132,15 @@ Return Vibrator::perform_1_3(Effect effect, EffectStrength strength, perfo return Void(); } -// Private methods follow. +template +Return Vibrator::perform(T effect, EffectStrength strength, perform_cb _hidl_cb) { + auto validRange = hidl_enum_range(); + if (effect < *validRange.begin() || effect > *std::prev(validRange.end())) { + _hidl_cb(Status::UNSUPPORTED_OPERATION, 0); + return Void(); + } + return perform(static_cast(effect), strength, _hidl_cb); +} Status Vibrator::enable(bool enabled) { if (mExternalControl) { diff --git a/vibrator/1.3/example/Vibrator.h b/vibrator/1.3/example/Vibrator.h index 64e8e1b76d..5180774552 100644 --- a/vibrator/1.3/example/Vibrator.h +++ b/vibrator/1.3/example/Vibrator.h @@ -54,6 +54,9 @@ class Vibrator : public IVibrator { Return perform_1_3(Effect effect, EffectStrength strength, perform_cb _hidl_cb) override; private: + Return perform(Effect effect, EffectStrength strength, perform_cb _hidl_cb); + template + Return perform(T effect, EffectStrength strength, perform_cb _hidl_cb); Status enable(bool enabled); Status activate(uint32_t ms); void timeout(); From 834def17c91536be55a2481b01ce3be8fee55124 Mon Sep 17 00:00:00 2001 From: "Harpreet \"Eli\" Sangha" Date: Thu, 11 Apr 2019 15:26:16 +0900 Subject: [PATCH 607/718] vibrator: vts: Add Bad Effect/Strength Checks Bug: 130265348 Test: vts-tradefed run singleCommand vts-hal -m VtsHalVibratorV1_0Target vts-tradefed run singleCommand vts-hal -m VtsHalVibratorV1_1Target Signed-off-by: Harpreet "Eli" Sangha Change-Id: Icc8e0d7bc81bef7141be69c23a797140fddb7295 --- .../VtsHalVibratorV1_0TargetTest.cpp | 51 ++++++++++++++++-- .../VtsHalVibratorV1_1TargetTest.cpp | 54 +++++++++++++++++-- 2 files changed, 98 insertions(+), 7 deletions(-) diff --git a/vibrator/1.0/vts/functional/VtsHalVibratorV1_0TargetTest.cpp b/vibrator/1.0/vts/functional/VtsHalVibratorV1_0TargetTest.cpp index a0e927b1a0..6f8aa02892 100644 --- a/vibrator/1.0/vts/functional/VtsHalVibratorV1_0TargetTest.cpp +++ b/vibrator/1.0/vts/functional/VtsHalVibratorV1_0TargetTest.cpp @@ -24,13 +24,16 @@ #include #include +using ::android::sp; +using ::android::hardware::hidl_enum_range; +using ::android::hardware::Return; +using ::android::hardware::Void; using ::android::hardware::vibrator::V1_0::Effect; using ::android::hardware::vibrator::V1_0::EffectStrength; using ::android::hardware::vibrator::V1_0::IVibrator; using ::android::hardware::vibrator::V1_0::Status; -using ::android::hardware::Return; -using ::android::hardware::Void; -using ::android::sp; + +#define EXPECT_OK(ret) EXPECT_TRUE((ret).isOk()) // Test environment for Vibrator HIDL HAL. class VibratorHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { @@ -70,6 +73,12 @@ static void validatePerformEffect(Status status, uint32_t lengthMs) { } } +static void validatePerformEffectBadInput(Status status, uint32_t lengthMs) { + ASSERT_EQ(Status::UNSUPPORTED_OPERATION, status); + ASSERT_EQ(static_cast(0), lengthMs) + << "Effects that return UNSUPPORTED_OPERATION must have a duration of zero"; +} + TEST_F(VibratorHidlTest, OnThenOffBeforeTimeout) { EXPECT_EQ(Status::OK, vibrator->on(2000)); sleep(1); @@ -81,6 +90,42 @@ TEST_F(VibratorHidlTest, PerformEffect) { vibrator->perform(Effect::DOUBLE_CLICK, EffectStrength::LIGHT, validatePerformEffect); } +/* + * Test to make sure effect values above the valid range are rejected. + */ +TEST_F(VibratorHidlTest, PerformEffect_BadEffects_AboveValidRange) { + Effect effect = *std::prev(hidl_enum_range().end()); + Effect badEffect = static_cast(static_cast(effect) + 1); + EXPECT_OK(vibrator->perform(badEffect, EffectStrength::LIGHT, validatePerformEffectBadInput)); +} + +/* + * Test to make sure effect values below the valid range are rejected. + */ +TEST_F(VibratorHidlTest, PerformEffect_BadEffects_BelowValidRange) { + Effect effect = *hidl_enum_range().begin(); + Effect badEffect = static_cast(static_cast(effect) - 1); + EXPECT_OK(vibrator->perform(badEffect, EffectStrength::LIGHT, validatePerformEffectBadInput)); +} + +/* + * Test to make sure strength values above the valid range are rejected. + */ +TEST_F(VibratorHidlTest, PerformEffect_BadStrength_AboveValidRange) { + EffectStrength strength = *std::prev(hidl_enum_range().end()); + EffectStrength badStrength = static_cast(static_cast(strength) + 1); + EXPECT_OK(vibrator->perform(Effect::CLICK, badStrength, validatePerformEffectBadInput)); +} + +/* + * Test to make sure strength values below the valid range are rejected. + */ +TEST_F(VibratorHidlTest, PerformEffect_BadStrength_BelowValidRange) { + EffectStrength strength = *hidl_enum_range().begin(); + EffectStrength badStrength = static_cast(static_cast(strength) - 1); + EXPECT_OK(vibrator->perform(Effect::CLICK, badStrength, validatePerformEffectBadInput)); +} + TEST_F(VibratorHidlTest, ChangeVibrationalAmplitude) { if (vibrator->supportsAmplitudeControl()) { EXPECT_EQ(Status::OK, vibrator->setAmplitude(1)); diff --git a/vibrator/1.1/vts/functional/VtsHalVibratorV1_1TargetTest.cpp b/vibrator/1.1/vts/functional/VtsHalVibratorV1_1TargetTest.cpp index 1a47fe9fcb..3c3ebf2329 100644 --- a/vibrator/1.1/vts/functional/VtsHalVibratorV1_1TargetTest.cpp +++ b/vibrator/1.1/vts/functional/VtsHalVibratorV1_1TargetTest.cpp @@ -23,14 +23,16 @@ #include #include -using ::android::hardware::vibrator::V1_0::Effect; +using ::android::sp; +using ::android::hardware::hidl_enum_range; +using ::android::hardware::Return; +using ::android::hardware::Void; using ::android::hardware::vibrator::V1_0::EffectStrength; using ::android::hardware::vibrator::V1_0::Status; using ::android::hardware::vibrator::V1_1::Effect_1_1; using ::android::hardware::vibrator::V1_1::IVibrator; -using ::android::hardware::Return; -using ::android::hardware::Void; -using ::android::sp; + +#define EXPECT_OK(ret) EXPECT_TRUE((ret).isOk()) // Test environment for Vibrator HIDL HAL. class VibratorHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { @@ -72,11 +74,55 @@ static void validatePerformEffect(Status status, uint32_t lengthMs) { } } +static void validatePerformEffectBadInput(Status status, uint32_t lengthMs) { + ASSERT_EQ(Status::UNSUPPORTED_OPERATION, status); + ASSERT_EQ(static_cast(0), lengthMs) + << "Effects that return UNSUPPORTED_OPERATION must have a duration of zero"; +} + TEST_F(VibratorHidlTest_1_1, PerformEffect_1_1) { vibrator->perform_1_1(Effect_1_1::CLICK, EffectStrength::MEDIUM, validatePerformEffect); vibrator->perform_1_1(Effect_1_1::TICK, EffectStrength::STRONG, validatePerformEffect); } +/* + * Test to make sure effect values above the valid range are rejected. + */ +TEST_F(VibratorHidlTest_1_1, PerformEffect_1_1_BadEffects_AboveValidRange) { + Effect_1_1 effect = *std::prev(hidl_enum_range().end()); + Effect_1_1 badEffect = static_cast(static_cast(effect) + 1); + EXPECT_OK( + vibrator->perform_1_1(badEffect, EffectStrength::LIGHT, validatePerformEffectBadInput)); +} + +/* + * Test to make sure effect values below the valid range are rejected. + */ +TEST_F(VibratorHidlTest_1_1, PerformEffect_1_1_BadEffects_BelowValidRange) { + Effect_1_1 effect = *hidl_enum_range().begin(); + Effect_1_1 badEffect = static_cast(static_cast(effect) - 1); + EXPECT_OK( + vibrator->perform_1_1(badEffect, EffectStrength::LIGHT, validatePerformEffectBadInput)); +} + +/* + * Test to make sure strength values above the valid range are rejected. + */ +TEST_F(VibratorHidlTest_1_1, PerformEffect_1_1_BadStrength_AboveValidRange) { + EffectStrength strength = *std::prev(hidl_enum_range().end()); + EffectStrength badStrength = static_cast(static_cast(strength) + 1); + EXPECT_OK(vibrator->perform_1_1(Effect_1_1::CLICK, badStrength, validatePerformEffectBadInput)); +} + +/* + * Test to make sure strength values below the valid range are rejected. + */ +TEST_F(VibratorHidlTest_1_1, PerformEffect_1_1_BadStrength_BelowValidRange) { + EffectStrength strength = *hidl_enum_range().begin(); + EffectStrength badStrength = static_cast(static_cast(strength) - 1); + EXPECT_OK(vibrator->perform_1_1(Effect_1_1::CLICK, badStrength, validatePerformEffectBadInput)); +} + int main(int argc, char** argv) { ::testing::AddGlobalTestEnvironment(VibratorHidlEnvironment::Instance()); ::testing::InitGoogleTest(&argc, argv); From 5f5d5f9a54d4c3f17731acdb4ae02252e9497df0 Mon Sep 17 00:00:00 2001 From: Slava Shklyaev Date: Thu, 11 Apr 2019 16:25:21 +0100 Subject: [PATCH 608/718] Clarify NNAPI documentation for RESHAPE Bug: 117176461 Test: mma Change-Id: I620873536ed99ac79b7eced286a8f2621524290b --- current.txt | 4 ++-- neuralnetworks/1.0/types.hal | 5 +++++ neuralnetworks/1.2/types.hal | 5 +++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/current.txt b/current.txt index 875be97f28..83a3a10cbb 100644 --- a/current.txt +++ b/current.txt @@ -401,7 +401,7 @@ f7d7cb747dc01a9fdb2d39a80003b4d8df9be733d65f5842198802eb6209db69 android.hardwar 65a021fa89085b62fc96b2b6d3bef2f9103cf4d63379c68bc154fd9eef672852 android.hardware.health@1.0::types b7ecf29927055ec422ec44bf776223f07d79ad9f92ccf9becf167e62c2607e7a android.hardware.keymaster@4.0::IKeymasterDevice 574e8f1499436fb4075894dcae0b36682427956ecb114f17f1fe22d116a83c6b android.hardware.neuralnetworks@1.0::IPreparedModel -417ab60fe1ef786778047e4486f3d868ebce570d91addd8fe4251515213072de android.hardware.neuralnetworks@1.0::types +567de4ebb3a224721eabae40c4484fad2cd1608eb0e66ec9214eb88e9b15d3c9 android.hardware.neuralnetworks@1.0::types ec8aa14fe9b03f2b3fb9845346a4005b6d098ebe2277b2564f73a548a0fd14a7 android.hardware.neuralnetworks@1.1::types 1d4a5776614c08b5d794a5ec5ab04697260cbd4b3441d5935cd53ee71d19da02 android.hardware.radio@1.0::IRadioResponse ed9da80ec0c96991fd03f0a46107815d0e50f764656e49dba4980fa5c31d5bc3 android.hardware.radio@1.0::types @@ -515,7 +515,7 @@ b83317b66721241887d2770b5ae95fd5af1e77c5daa7530ecb08fae8892f2b43 android.hardwar 92714960d1a53fc2ec557302b41c7cc93d2636d8364a44bd0f85be0c92927ff8 android.hardware.neuralnetworks@1.2::IExecutionCallback 36e1064c869965dee533c537cefbe87e54db8bd8cd45be7e0e93e00e8a43863a android.hardware.neuralnetworks@1.2::IPreparedModel e1c734d1545e1a4ae749ff1dd9704a8e594c59aea7c8363159dc258e93e0df3b android.hardware.neuralnetworks@1.2::IPreparedModelCallback -b75126d572c1788682a679ab53c2dbdf3fcd75f754b1370dbf09aaad0e19d397 android.hardware.neuralnetworks@1.2::types +5c0d2f81f764f6c24928b4bc6b950f58b8eb85e99015bea8510d51e39e8fdadd android.hardware.neuralnetworks@1.2::types cf7a4ba516a638f9b82a249c91fb603042c2d9ca43fd5aad9cf6c0401ed2a5d7 android.hardware.nfc@1.2::INfc abf98c2ae08bf765db54edc8068e36d52eb558cff6706b6fd7c18c65a1f3fc18 android.hardware.nfc@1.2::types 4cb252dc6372a874aef666b92a6e9529915aa187521a700f0789065c3c702ead android.hardware.power.stats@1.0::IPowerStats diff --git a/neuralnetworks/1.0/types.hal b/neuralnetworks/1.0/types.hal index 89af35a376..a358946e31 100644 --- a/neuralnetworks/1.0/types.hal +++ b/neuralnetworks/1.0/types.hal @@ -1197,6 +1197,11 @@ enum OperationType : int32_t { * shape of the output tensor. The number of elements implied by shape * must be the same as the number of elements in the input tensor. * + * If one component of shape is the special value -1, the size of that + * dimension is computed so that the total size remains constant. In + * particular, a shape of [-1] flattens into 1-D. At most one component + * of shape can be -1. + * * Outputs: * * 0: The output tensor, of shape specified by the input shape. * diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal index 839114fe7b..f13fcb290b 100644 --- a/neuralnetworks/1.2/types.hal +++ b/neuralnetworks/1.2/types.hal @@ -1548,6 +1548,11 @@ enum OperationType : int32_t { * shape of the output tensor. The number of elements implied by shape * must be the same as the number of elements in the input tensor. * + * If one component of shape is the special value -1, the size of that + * dimension is computed so that the total size remains constant. In + * particular, a shape of [-1] flattens into 1-D. At most one component + * of shape can be -1. + * * Outputs: * * 0: The output tensor, of shape specified by the input shape. * From d6e605985b2ae0f38d10544b5520c6291b7e0bc4 Mon Sep 17 00:00:00 2001 From: Slava Shklyaev Date: Fri, 12 Apr 2019 15:00:48 +0100 Subject: [PATCH 609/718] Clarify NNAPI documentation for MEAN Bug: 113673389 Test: mma Change-Id: Icd1ce2fb9054ab9ac6f660dce84823c73563ddb8 --- current.txt | 4 ++-- neuralnetworks/1.1/types.hal | 13 ++++++++----- neuralnetworks/1.2/types.hal | 13 ++++++++----- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/current.txt b/current.txt index 83a3a10cbb..a9ea1adb80 100644 --- a/current.txt +++ b/current.txt @@ -402,7 +402,7 @@ f7d7cb747dc01a9fdb2d39a80003b4d8df9be733d65f5842198802eb6209db69 android.hardwar b7ecf29927055ec422ec44bf776223f07d79ad9f92ccf9becf167e62c2607e7a android.hardware.keymaster@4.0::IKeymasterDevice 574e8f1499436fb4075894dcae0b36682427956ecb114f17f1fe22d116a83c6b android.hardware.neuralnetworks@1.0::IPreparedModel 567de4ebb3a224721eabae40c4484fad2cd1608eb0e66ec9214eb88e9b15d3c9 android.hardware.neuralnetworks@1.0::types -ec8aa14fe9b03f2b3fb9845346a4005b6d098ebe2277b2564f73a548a0fd14a7 android.hardware.neuralnetworks@1.1::types +d51937a3567a50f239589e40300264c4b57f2c3582c6fc6df082f45eb74d90e3 android.hardware.neuralnetworks@1.1::types 1d4a5776614c08b5d794a5ec5ab04697260cbd4b3441d5935cd53ee71d19da02 android.hardware.radio@1.0::IRadioResponse ed9da80ec0c96991fd03f0a46107815d0e50f764656e49dba4980fa5c31d5bc3 android.hardware.radio@1.0::types 1d19720d4fd38b1095f0f555a4bd92b3b12c9b1d0f560b0e9a474cd6dcc20db6 android.hardware.radio@1.2::IRadio @@ -515,7 +515,7 @@ b83317b66721241887d2770b5ae95fd5af1e77c5daa7530ecb08fae8892f2b43 android.hardwar 92714960d1a53fc2ec557302b41c7cc93d2636d8364a44bd0f85be0c92927ff8 android.hardware.neuralnetworks@1.2::IExecutionCallback 36e1064c869965dee533c537cefbe87e54db8bd8cd45be7e0e93e00e8a43863a android.hardware.neuralnetworks@1.2::IPreparedModel e1c734d1545e1a4ae749ff1dd9704a8e594c59aea7c8363159dc258e93e0df3b android.hardware.neuralnetworks@1.2::IPreparedModelCallback -5c0d2f81f764f6c24928b4bc6b950f58b8eb85e99015bea8510d51e39e8fdadd android.hardware.neuralnetworks@1.2::types +b47700929d91ad9c037fd26077d4008d4a04753f71f4f332aeedbd1de7bb91e1 android.hardware.neuralnetworks@1.2::types cf7a4ba516a638f9b82a249c91fb603042c2d9ca43fd5aad9cf6c0401ed2a5d7 android.hardware.nfc@1.2::INfc abf98c2ae08bf765db54edc8068e36d52eb558cff6706b6fd7c18c65a1f3fc18 android.hardware.nfc@1.2::types 4cb252dc6372a874aef666b92a6e9529915aa187521a700f0789065c3c702ead android.hardware.power.stats@1.0::IPowerStats diff --git a/neuralnetworks/1.1/types.hal b/neuralnetworks/1.1/types.hal index 99f873a5ab..335b80366f 100644 --- a/neuralnetworks/1.1/types.hal +++ b/neuralnetworks/1.1/types.hal @@ -104,9 +104,6 @@ enum OperationType : @1.0::OperationType { * in axis. If keep_dims is true, the reduced dimensions are retained with * length 1. * - * If dimensions to reduce have no entries, all dimensions are reduced, and - * a tensor with a single element is returned. - * * Supported tensor {@link OperandType}: * * {@link OperandType::TENSOR_FLOAT32} * * {@link OperandType::TENSOR_QUANT8_ASYMM} @@ -116,8 +113,14 @@ enum OperationType : @1.0::OperationType { * Inputs: * * 0: A tensor, specifying the input. * * 1: A 1-D Tensor of {@link OperandType::TENSOR_INT32}. The dimensions - * to reduce. If None (the default), reduces all dimensions. Must be in - * the range [-rank(input_tensor), rank(input_tensor)). + * to reduce. Must be in the range + * [-rank(input_tensor), rank(input_tensor)). + * + * NOTE: When the operation was introduced, the documentation + * incorrectly stated that if dimensions were empty, the operation + * would reduce across all dimensions. This behavior was never + * implemented. + * * * 2: An {@link OperandType::INT32} scalar, keep_dims. If positive, * retains reduced dimensions with length 1. * diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal index f13fcb290b..499c817348 100644 --- a/neuralnetworks/1.2/types.hal +++ b/neuralnetworks/1.2/types.hal @@ -1954,9 +1954,6 @@ enum OperationType : int32_t { * in axis. If keep_dims is true, the reduced dimensions are retained with * length 1. * - * If dimensions to reduce have no entries, all dimensions are reduced, and - * a tensor with a single element is returned. - * * Supported tensor {@link OperandType}: * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) * * {@link OperandType::TENSOR_FLOAT32} @@ -1967,8 +1964,14 @@ enum OperationType : int32_t { * Inputs: * * 0: A tensor, specifying the input. * * 1: A 1-D Tensor of {@link OperandType::TENSOR_INT32}. The dimensions - * to reduce. If None (the default), reduces all dimensions. Must be in - * the range [-rank(input_tensor), rank(input_tensor)). + * to reduce. Must be in the range + * [-rank(input_tensor), rank(input_tensor)). + * + * NOTE: When the operation was introduced, the documentation + * incorrectly stated that if dimensions were empty, the operation + * would reduce across all dimensions. This behavior was never + * implemented. + * * * 2: An {@link OperandType::INT32} scalar, keep_dims. If positive, * retains reduced dimensions with length 1. * From 6d13ba258b0fe7c4e89c11b565aff461080c5e04 Mon Sep 17 00:00:00 2001 From: Lev Proleev Date: Fri, 12 Apr 2019 17:29:33 +0100 Subject: [PATCH 610/718] Fix docs: clarify usage of float16 scalars in operations Update the docs for ops: - LOG_SOFTMAX - LOCAL_RESPONSE_NORMALIZATION The docs mentioned possibility to use float16 as an input type but didn't specify that other inputs must be float16 as well in that case. Fix: 123500722 Test: mma Change-Id: I9028c4a109c80f0b8571fab45555818e9e4bc783 --- current.txt | 2 +- neuralnetworks/1.2/types.hal | 29 +++++++++++++++++++++-------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/current.txt b/current.txt index a9ea1adb80..997c38ad52 100644 --- a/current.txt +++ b/current.txt @@ -515,7 +515,7 @@ b83317b66721241887d2770b5ae95fd5af1e77c5daa7530ecb08fae8892f2b43 android.hardwar 92714960d1a53fc2ec557302b41c7cc93d2636d8364a44bd0f85be0c92927ff8 android.hardware.neuralnetworks@1.2::IExecutionCallback 36e1064c869965dee533c537cefbe87e54db8bd8cd45be7e0e93e00e8a43863a android.hardware.neuralnetworks@1.2::IPreparedModel e1c734d1545e1a4ae749ff1dd9704a8e594c59aea7c8363159dc258e93e0df3b android.hardware.neuralnetworks@1.2::IPreparedModelCallback -b47700929d91ad9c037fd26077d4008d4a04753f71f4f332aeedbd1de7bb91e1 android.hardware.neuralnetworks@1.2::types +73e995644b1bb2678ec3ab850feb7a1b4495501953951c22316cefd67b900b3e android.hardware.neuralnetworks@1.2::types cf7a4ba516a638f9b82a249c91fb603042c2d9ca43fd5aad9cf6c0401ed2a5d7 android.hardware.nfc@1.2::INfc abf98c2ae08bf765db54edc8068e36d52eb558cff6706b6fd7c18c65a1f3fc18 android.hardware.nfc@1.2::types 4cb252dc6372a874aef666b92a6e9529915aa187521a700f0789065c3c702ead android.hardware.power.stats@1.0::IPowerStats diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal index 499c817348..087249abf5 100644 --- a/neuralnetworks/1.2/types.hal +++ b/neuralnetworks/1.2/types.hal @@ -1005,12 +1005,21 @@ enum OperationType : int32_t { * the input. * * 1: An {@link OperandType::INT32} scalar, specifying the radius of * the normalization window. - * * 2: An {@link OperandType::FLOAT32} scalar, specifying the bias, must - * not be zero. - * * 3: An {@link OperandType::FLOAT32} scalar, specifying the scale - * factor, alpha. - * * 4: An {@link OperandType::FLOAT32} scalar, specifying the exponent, - * beta. + * * 2: A scalar, specifying the bias, must not be zero. + * For input tensor of {@link OperandType::TENSOR_FLOAT16}, the bias + * value must be of {@link OperandType::FLOAT16}. + * For input tensor of {@link OperandType::TENSOR_FLOAT32}, the bias + * value must be of {@link OperandType::FLOAT32}. + * * 3: A scalar, specifying the scale factor, alpha. + * For input tensor of {@link OperandType::TENSOR_FLOAT16}, the alpha + * value must be of {@link OperandType::FLOAT16}. + * For input tensor of {@link OperandType::TENSOR_FLOAT32}, the alpha + * value must be of {@link OperandType::FLOAT32}. + * * 4: A scalar, specifying the exponent, beta. + * For input tensor of {@link OperandType::TENSOR_FLOAT16}, the beta + * value must be of {@link OperandType::FLOAT16}. + * For input tensor of {@link OperandType::TENSOR_FLOAT32}, the beta + * value must be of {@link OperandType::FLOAT32}. * * 5: An optional {@link OperandType::INT32} scalar, default to -1, * specifying the dimension normalization would be performed on. * Negative index is used to specify axis from the end (e.g. -1 for @@ -3495,8 +3504,12 @@ enum OperationType : int32_t { * * Inputs: * * 0: A tensor specifying the input logits. - * * 1: An {@link OperandType::FLOAT32} scalar, specifying the positive - * scaling factor for the exponent, beta. + * * 1: A scalar, specifying the positive scaling factor for the exponent, + * beta. + * For input tensor of {@link OperandType::TENSOR_FLOAT16}, the beta + * value must be of {@link OperandType::FLOAT16}. + * For input tensor of {@link OperandType::TENSOR_FLOAT32}, the beta + * value must be of {@link OperandType::FLOAT32}. * * 2: An {@link OperandType::INT32} scalar specifying the axis to * reduce across. Negative index is used to specify axis from the * end (e.g. -1 for the last axis). Must be in the range [-n, n). From 86eb7fc62bd138c746e20171124abaf9b975006c Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Tue, 9 Apr 2019 14:08:40 -0700 Subject: [PATCH 611/718] Compatibility_matrix: s/current/4/ To indicate frozen state/development shouldn't occur here. Bug: 126892442 Test: TH (build checks compatibility matrices) Change-Id: I3daf93d750462bf7dcb698a353801bc55a459d45 --- compatibility_matrices/Android.bp | 6 +++--- compatibility_matrices/Android.mk | 2 +- ...bility_matrix.current.xml => compatibility_matrix.4.xml} | 0 3 files changed, 4 insertions(+), 4 deletions(-) rename compatibility_matrices/{compatibility_matrix.current.xml => compatibility_matrix.4.xml} (100%) diff --git a/compatibility_matrices/Android.bp b/compatibility_matrices/Android.bp index 5f56ee94d8..96b05c9282 100644 --- a/compatibility_matrices/Android.bp +++ b/compatibility_matrices/Android.bp @@ -64,10 +64,10 @@ vintf_compatibility_matrix { } vintf_compatibility_matrix { - name: "framework_compatibility_matrix.current.xml", - stem: "compatibility_matrix.current.xml", + name: "framework_compatibility_matrix.4.xml", + stem: "compatibility_matrix.4.xml", srcs: [ - "compatibility_matrix.current.xml", + "compatibility_matrix.4.xml", ], kernel_configs: [ "kernel_config_current_4.9", diff --git a/compatibility_matrices/Android.mk b/compatibility_matrices/Android.mk index 425e376830..b0caa7c367 100644 --- a/compatibility_matrices/Android.mk +++ b/compatibility_matrices/Android.mk @@ -96,7 +96,7 @@ my_system_matrix_deps := \ framework_compatibility_matrix.1.xml \ framework_compatibility_matrix.2.xml \ framework_compatibility_matrix.3.xml \ - framework_compatibility_matrix.current.xml \ + framework_compatibility_matrix.4.xml \ framework_compatibility_matrix.device.xml \ my_framework_matrix_deps += \ diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.4.xml similarity index 100% rename from compatibility_matrices/compatibility_matrix.current.xml rename to compatibility_matrices/compatibility_matrix.4.xml From b1a144041e19765e6e1b1321a87a92dda21cff9c Mon Sep 17 00:00:00 2001 From: Cheney Ni Date: Thu, 11 Apr 2019 18:51:21 +0800 Subject: [PATCH 612/718] Remove bluetooth.a2dp from matrix as deprecated HAL Bug: 129121468 Test: Manually play A2DP with presubmit build Change-Id: Id1ddd780361110f6e944a095ce1f8ae7ae86b9e9 --- compatibility_matrices/compatibility_matrix.4.xml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/compatibility_matrices/compatibility_matrix.4.xml b/compatibility_matrices/compatibility_matrix.4.xml index 999c29c5a4..a4e77cc0c1 100644 --- a/compatibility_matrices/compatibility_matrix.4.xml +++ b/compatibility_matrices/compatibility_matrix.4.xml @@ -79,14 +79,6 @@ default - - android.hardware.bluetooth.a2dp - 1.0 - - IBluetoothAudioOffload - default - - android.hardware.bluetooth.audio 2.0 From c0cbe539f363da909013b7f939eb3ad4171c3a04 Mon Sep 17 00:00:00 2001 From: Yifan Hong Date: Mon, 15 Apr 2019 10:32:24 -0700 Subject: [PATCH 613/718] Rename kernel config modules from current to Q. Test: builds Bug: 130295628 Change-Id: I4f519d9c67a983df15423f556ecc68586c6a100b --- compatibility_matrices/Android.bp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compatibility_matrices/Android.bp b/compatibility_matrices/Android.bp index 5f56ee94d8..38882a214e 100644 --- a/compatibility_matrices/Android.bp +++ b/compatibility_matrices/Android.bp @@ -70,8 +70,8 @@ vintf_compatibility_matrix { "compatibility_matrix.current.xml", ], kernel_configs: [ - "kernel_config_current_4.9", - "kernel_config_current_4.14", - "kernel_config_current_4.19", + "kernel_config_q_4.9", + "kernel_config_q_4.14", + "kernel_config_q_4.19", ] } From 65c7b60c656c5c96d2cca7d82819546bb655f936 Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Thu, 11 Apr 2019 13:50:37 -0700 Subject: [PATCH 614/718] Deprecate getDisplayBrightnessSupport. Brightness is already a per display capability, we don't need this API. BUG: 130313275 Test: build Change-Id: I0a669aca19a2873df41bee82bd0e5e2775af8101 --- current.txt | 2 +- graphics/composer/2.3/IComposerClient.hal | 4 ++++ .../VtsHalGraphicsComposerV2_3TargetTest.cpp | 20 +++++++++---------- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/current.txt b/current.txt index 875be97f28..b6d9540a82 100644 --- a/current.txt +++ b/current.txt @@ -487,7 +487,7 @@ b826892686850a9cf2b60ca5845db7185c2196ea4dd765cd80cd163169678a78 android.hardwar 01c6398c90fc6be0640810e2c5d8a4863b457280132bb3f97dd5682e19632b62 android.hardware.graphics.bufferqueue@2.0::types 7a2d64095252f85781b2d521f4f11d04ce774544feececcec2088c568656e93c android.hardware.graphics.common@1.2::types 3dff04a36b86660b5807414587e530bb0c294ed56fdff06f8915ba0a9b73f974 android.hardware.graphics.composer@2.3::IComposer -54bc1dc874f8bc0781767786075dafd33a0796c1eea7d2317231b8929280e946 android.hardware.graphics.composer@2.3::IComposerClient +b2b0ef3e6f5e9bb4aa6e978bc62e017b3fd64dba95a2152e8b07e3b7c4581d4f android.hardware.graphics.composer@2.3::IComposerClient 033e096cb65e5093ee1d0e473892b9a487911d4611dbb65ebecb5cef18338923 android.hardware.graphics.mapper@3.0::IMapper 7183d9d9acfa41a61a64bdfed548e98299265a7bb1821a3ed204173b5c2cfd4a android.hardware.graphics.mapper@3.0::types c3f831a66d5815baf74f5b82fe79cf099542ddae4dfab3f388e1d41828e794fc android.hardware.health.storage@1.0::IGarbageCollectCallback diff --git a/graphics/composer/2.3/IComposerClient.hal b/graphics/composer/2.3/IComposerClient.hal index 1eea306523..4d6f78f0be 100644 --- a/graphics/composer/2.3/IComposerClient.hal +++ b/graphics/composer/2.3/IComposerClient.hal @@ -502,6 +502,10 @@ interface IComposerClient extends @2.2::IComposerClient { float minLuminance); /** + * Use getDisplayCapabilities instead. If brightness is supported, must return + * DisplayCapability::BRIGHTNESS as one of the display capabilities via getDisplayCapabilities. + * Only use getDisplayCapabilities as the source of truth to query brightness support. + * * Gets whether brightness operations are supported on a display. * * @param display diff --git a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp index 56b2e337ae..d51c30a307 100644 --- a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp +++ b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp @@ -572,6 +572,10 @@ TEST_F(GraphicsComposerHidlTest, getDisplayCapabilitiesBasic) { std::find(capabilities.begin(), capabilities.end(), IComposerClient::DisplayCapability::DOZE) != capabilities.end(); EXPECT_EQ(mComposerClient->getDozeSupport(mPrimaryDisplay), hasDozeSupport); + bool hasBrightnessSupport = + std::find(capabilities.begin(), capabilities.end(), + IComposerClient::DisplayCapability::BRIGHTNESS) != capabilities.end(); + EXPECT_EQ(mComposerClient->getDisplayBrightnessSupport(mPrimaryDisplay), hasBrightnessSupport); } TEST_F(GraphicsComposerHidlTest, getDisplayCapabilitiesBadDisplay) { @@ -604,24 +608,18 @@ TEST_F(GraphicsComposerHidlTest, SetLayerPerFrameMetadataBlobs) { } /* - * Test that getDisplayBrightnessSupport works as expected. + * Test that if brightness operations are supported, setDisplayBrightness works as expected. */ -TEST_F(GraphicsComposerHidlTest, getDisplayBrightnessSupport) { +TEST_F(GraphicsComposerHidlTest, setDisplayBrightness) { std::vector capabilities; const auto error = mComposerClient->getDisplayCapabilities(mPrimaryDisplay, &capabilities); ASSERT_EQ(Error::NONE, error); bool brightnessSupport = std::find(capabilities.begin(), capabilities.end(), IComposerClient::DisplayCapability::BRIGHTNESS) != capabilities.end(); - EXPECT_EQ(mComposerClient->getDisplayBrightnessSupport(mPrimaryDisplay), brightnessSupport); -} - -/* - * Test that if brightness operations are supported, setDisplayBrightness works as expected. - */ -TEST_F(GraphicsComposerHidlTest, setDisplayBrightness) { - if (!mComposerClient->getDisplayBrightnessSupport(mPrimaryDisplay)) { - EXPECT_EQ(mComposerClient->setDisplayBrightness(mPrimaryDisplay, 0.5f), Error::UNSUPPORTED); + if (!brightnessSupport) { + EXPECT_EQ(mComposerClient->getRaw()->setDisplayBrightness(mPrimaryDisplay, 0.5f), + Error::UNSUPPORTED); GTEST_SUCCEED() << "Brightness operations are not supported"; return; } From adb623e10859b96daa0413b3fcf25c7537982fcc Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Tue, 16 Apr 2019 15:39:33 -0700 Subject: [PATCH 615/718] current.txt: empty section for changes in release Bug: 126892442 Bug: 129931913 Test: N/A Change-Id: If873a5ddc653297c968a0ed4cdfa3adc9fbd4f3a --- current.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/current.txt b/current.txt index 875be97f28..1f0efa51b7 100644 --- a/current.txt +++ b/current.txt @@ -561,3 +561,6 @@ f3dbd8dd0d6333c005610288a4785d0ef79a72a7bbe6d0a46d46fa89fc886f1e android.hardwar 09e08b5d12b109562ecdd8882532fd1f2c4639588e07769d5c7396b7c5b9f34f android.hardware.wifi.supplicant@1.2::ISupplicantStaIfaceCallback efbb061c969fa9553d243da6ee23b83fe5d4aa663a7b8896adc52e2b015bc2f3 android.hardware.wifi.supplicant@1.2::ISupplicantStaNetwork cfa81f229b69f9011c58f48264fcb552447430fe68610eac514e811e65bc306a android.hardware.wifi.supplicant@1.2::types + +# ABI preserving changes to HALs during Android R +# none yet From 248eaba9c16caee729318c8138ab8dce651303f0 Mon Sep 17 00:00:00 2001 From: Michael Butler Date: Tue, 16 Apr 2019 15:04:32 -0700 Subject: [PATCH 616/718] Fix IBurstCallback.hal typo Test: mma Bug: 126892442 Change-Id: If753c6618c31a11672c4449f798fb57aa4bb7831 (cherry picked from commit f1ca6754a86549fb2d84bbca43822fb91bc1ada2) --- current.txt | 2 +- neuralnetworks/1.2/IBurstCallback.hal | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/current.txt b/current.txt index 875be97f28..2ecd50a4a8 100644 --- a/current.txt +++ b/current.txt @@ -509,7 +509,7 @@ d36f747f9c9a8f2f21db2f8323c2d755dd08b34ce813932d7339979f7d490dab android.hardwar b9422a9aca84df1ff9623dc12c0562abce97716e28d63a965f2bfb88f9ad9607 android.hardware.media.c2@1.0::IInputSurface 0a786a19e6753f9774a7ca7781c2a2edfe5c0b5fa112355dfa0e50ebedeb08b9 android.hardware.media.c2@1.0::IInputSurfaceConnection 7d3c292ca75ec3e22a8fd4ae72d2edb0659d280257e763786e766f3429954dd1 android.hardware.media.c2@1.0::types -4880af120fc1640225abdc2c60bda6d79617d73484d5124913c7278af3b11e2d android.hardware.neuralnetworks@1.2::IBurstCallback +5f6b6b99ffd0d51a5713174a3030a2a69273bcd476fc1b5ce814491437685857 android.hardware.neuralnetworks@1.2::IBurstCallback 19877e466ad8c6ed42b38050b77bd010cf7800ff365fdc8574f45bbfda03a758 android.hardware.neuralnetworks@1.2::IBurstContext b83317b66721241887d2770b5ae95fd5af1e77c5daa7530ecb08fae8892f2b43 android.hardware.neuralnetworks@1.2::IDevice 92714960d1a53fc2ec557302b41c7cc93d2636d8364a44bd0f85be0c92927ff8 android.hardware.neuralnetworks@1.2::IExecutionCallback diff --git a/neuralnetworks/1.2/IBurstCallback.hal b/neuralnetworks/1.2/IBurstCallback.hal index 3f82e3152b..cc38d7a3a4 100644 --- a/neuralnetworks/1.2/IBurstCallback.hal +++ b/neuralnetworks/1.2/IBurstCallback.hal @@ -24,7 +24,7 @@ import @1.0::ErrorStatus; */ interface IBurstCallback { /** - * Get the memory regions that correspond to slot ids. The slot ids are are + * Get the memory regions that correspond to slot ids. The slot ids are * unique to the burst object. * * @param slots Values uniquely identifying memory regions within a Burst. From 72132c4feb7c2bb0f20d91445856af04dce1e7f7 Mon Sep 17 00:00:00 2001 From: lesl Date: Wed, 17 Apr 2019 16:43:36 +0800 Subject: [PATCH 617/718] p2p: fix vts fail due to 5g go init fail with 00 country code The force 5GHz Go will cause fail when country code is 00 or chip doesn't support 5GHz. Change test parameter to force 0 which means driver decide GO channel. Bug: 130208180 Test: vts-tradefed run commandAndExit vts-hal --skip-all-system-status-check --primary-abi-only --skip-preconditions --module VtsHalWifiSupplicantP2pV1_2Target -l INFO Change-Id: I0d2a8fcba4ece616ddeccbae36146329e9043157 --- .../1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp b/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp index 9249045483..36bde161c1 100644 --- a/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp +++ b/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp @@ -57,7 +57,7 @@ class SupplicantP2pIfaceHidlTest : public ::testing::VtsHalHidlTargetTestBase { TEST_F(SupplicantP2pIfaceHidlTest, AddGroup_1_2_Success) { std::vector ssid(kTestSsid, kTestSsid + sizeof(kTestSsid)); std::string passphrase = kTestPassphrase; - int freq = 5; + int freq = 0; std::array zero_mac_addr; memcpy(zero_mac_addr.data(), kTestZeroMacAddr, zero_mac_addr.size()); bool persistent = false; @@ -76,7 +76,7 @@ TEST_F(SupplicantP2pIfaceHidlTest, AddGroup_1_2_Success) { TEST_F(SupplicantP2pIfaceHidlTest, AddGroup_1_2_FailureInvalidSsid) { std::vector ssid; std::string passphrase = kTestPassphrase; - int freq = 5; + int freq = 0; std::array zero_mac_addr; memcpy(zero_mac_addr.data(), kTestZeroMacAddr, zero_mac_addr.size()); bool persistent = false; @@ -95,7 +95,7 @@ TEST_F(SupplicantP2pIfaceHidlTest, AddGroup_1_2_FailureInvalidSsid) { TEST_F(SupplicantP2pIfaceHidlTest, AddGroup_1_2_FailureInvalidPassphrase) { std::vector ssid(kTestSsid, kTestSsid + sizeof(kTestSsid)); std::string passphrase = "1234"; - int freq = 5; + int freq = 0; std::array zero_mac_addr; memcpy(zero_mac_addr.data(), kTestZeroMacAddr, zero_mac_addr.size()); bool persistent = false; From ea551fd12a77d4fd36888aab19ec47cce30eff3d Mon Sep 17 00:00:00 2001 From: Viet Dang Date: Thu, 28 Mar 2019 17:22:56 +0000 Subject: [PATCH 618/718] BidirectionalSequenceLSTM op: Fixes VTS test for merge_outputs Bug: 123644584 Test: VtsHalNeuralnetworksV1_xTargetTest Change-Id: I8829fd47094ca4af05e5d60da917499ce61acc5e Merged-In: I8829fd47094ca4af05e5d60da917499ce61acc5e (cherry picked from commit a8f33f7dbff1c3ad0cb01b7f9214b8bf49eaa992) --- neuralnetworks/1.2/vts/functional/ValidateModel.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp index 2988211e5a..a0b6d9aeac 100644 --- a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp +++ b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp @@ -508,9 +508,10 @@ static bool removeOperandSkip(size_t operand, const Model& model) { } } } - // BIDIRECTIONAL_SEQUENCE_RNN can have either on or two outputs - // depending on a mergeOutputs parameter - if (operation.type == OperationType::BIDIRECTIONAL_SEQUENCE_RNN) { + // BIDIRECTIONAL_SEQUENCE_LSTM and BIDIRECTIONAL_SEQUENCE_RNN can have either one or two + // outputs depending on their mergeOutputs parameter. + if (operation.type == OperationType::BIDIRECTIONAL_SEQUENCE_LSTM || + operation.type == OperationType::BIDIRECTIONAL_SEQUENCE_RNN) { for (const size_t outOprand : operation.outputs) { if (operand == outOprand) { return true; From eb73bff276e0a3cb92a7cd9ea333709ecc1c7295 Mon Sep 17 00:00:00 2001 From: "hayun.kim" Date: Mon, 1 Apr 2019 18:46:20 +0900 Subject: [PATCH 619/718] Fix VtsHalWifiV1_0Host#WifiStaIfaceHidlTest.SetScanningMacOui fail 1. snip the VtsHalWifiV1_0Host#WifiStaIfaceHidlTest.SetScanningMacOui test if SCAN_RAND capability is not supported on dut device Test: execute VtsHalWifiV1_0TargetTest of VTS test Bug: 129735587 Change-Id: I825e1df11c958b3b2476880c6c6f7b8ee7b292bf Signed-off-by: hayun Kim --- wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp index a3410287eb..3ced328c05 100644 --- a/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp +++ b/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp @@ -249,6 +249,11 @@ TEST_F(WifiStaIfaceHidlTest, EnableNDOffload) { * code. */ TEST_F(WifiStaIfaceHidlTest, SetScanningMacOui) { + if (!isCapabilitySupported( + IWifiStaIface::StaIfaceCapabilityMask::SCAN_RAND)) { + // No-op if SetScanningMacOui is not supported. + return; + } const android::hardware::hidl_array kOui{ std::array{{0x10, 0x22, 0x33}}}; EXPECT_EQ(WifiStatusCode::SUCCESS, From ce4a7cce2c0439b4c231cc06287aecb7f4ed7e1f Mon Sep 17 00:00:00 2001 From: lesl Date: Wed, 17 Apr 2019 18:45:56 +0800 Subject: [PATCH 620/718] hostapd: fix hostapd vts fail If wpa_supplicant is running during hostapd vts and there are some configuration in wpa_supplicant. It will happen both of hostapd and wpa_supplicant are working with wlan0 interface. Stop wpa_supplicant before running hostapd vts. Reproduce step: 1. Connect to Wifi before execute hostapd vts. 2. Run hostapd vts. Bug: 130207248 Test: vts with below commands vts-tradefed run commandAndExit vts-hal --skip-all-system-status-check --primary-abi-only --skip-preconditions --module VtsHalWifiHostapdV1_0Target -l INFO vts-tradefed run commandAndExit vts-hal --skip-all-system-status-check --primary-abi-only --skip-preconditions --module VtsHalWifiHostapdV1_1Target -l INFO Change-Id: Id91463c2eab3c8c348a91bd978d7ea4aa8d42e85 --- .../1.0/vts/functional/hostapd_hidl_test.cpp | 1 + .../functional/hostapd_hidl_test_utils.cpp | 20 +++++++++++++++---- .../vts/functional/hostapd_hidl_test_utils.h | 1 + .../1.1/vts/functional/hostapd_hidl_test.cpp | 1 + 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test.cpp b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test.cpp index fa780f9a5c..6dc9eb4be7 100644 --- a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test.cpp +++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test.cpp @@ -41,6 +41,7 @@ constexpr int kIfaceInvalidChannel = 567; class HostapdHidlTest : public ::testing::VtsHalHidlTargetTestBase { public: virtual void SetUp() override { + stopSupplicantIfNeeded(); startHostapdAndWaitForHidlService(); hostapd_ = getHostapd(); ASSERT_NE(hostapd_.get(), nullptr); diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp index 22dbb528c3..1c499e7465 100644 --- a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp +++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp @@ -23,24 +23,26 @@ #include #include +#include #include "hostapd_hidl_test_utils.h" #include "wifi_hidl_test_utils.h" using ::android::sp; using ::android::hardware::configureRpcThreadpool; -using ::android::hardware::joinRpcThreadpool; using ::android::hardware::hidl_string; using ::android::hardware::hidl_vec; +using ::android::hardware::joinRpcThreadpool; using ::android::hardware::Return; using ::android::hardware::Void; -using ::android::hardware::wifi::V1_0::ChipModeId; -using ::android::hardware::wifi::V1_0::IWifiChip; -using ::android::hardware::wifi::hostapd::V1_0::IHostapd; using ::android::hardware::wifi::hostapd::V1_0::HostapdStatus; using ::android::hardware::wifi::hostapd::V1_0::HostapdStatusCode; +using ::android::hardware::wifi::hostapd::V1_0::IHostapd; +using ::android::hardware::wifi::V1_0::ChipModeId; +using ::android::hardware::wifi::V1_0::IWifiChip; using ::android::hidl::manager::V1_0::IServiceNotification; using ::android::wifi_system::HostapdManager; +using ::android::wifi_system::SupplicantManager; extern WifiHostapdHidlEnvironment* gEnv; @@ -108,6 +110,16 @@ class ServiceNotificationListener : public IServiceNotification { std::condition_variable condition_; }; +void stopSupplicantIfNeeded() { + SupplicantManager supplicant_manager; + if (supplicant_manager.IsSupplicantRunning()) { + LOG(INFO) << "Supplicant is running, stop supplicant first."; + ASSERT_TRUE(supplicant_manager.StopSupplicant()); + deInitilializeDriverAndFirmware(); + ASSERT_FALSE(supplicant_manager.IsSupplicantRunning()); + } +} + void stopHostapd() { HostapdManager hostapd_manager; diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h index 8e2f1a34d1..9b3df4206b 100644 --- a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h +++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h @@ -25,6 +25,7 @@ // Used to stop the android wifi framework before every test. void stopWifiFramework(); void startWifiFramework(); +void stopSupplicantIfNeeded(); void stopHostapd(); // Used to configure the chip, driver and start wpa_hostapd before every // test. diff --git a/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp b/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp index 439a62403d..26a58b2c61 100644 --- a/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp +++ b/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp @@ -45,6 +45,7 @@ constexpr int kIfaceInvalidChannel = 567; class HostapdHidlTest : public ::testing::VtsHalHidlTargetTestBase { public: virtual void SetUp() override { + stopSupplicantIfNeeded(); startHostapdAndWaitForHidlService(); hostapd_ = getHostapd_1_1(); ASSERT_NE(hostapd_.get(), nullptr); From c88c624e2e7f5f683d6381a8d5c96e58b0a85cb7 Mon Sep 17 00:00:00 2001 From: Valerie Hau Date: Wed, 17 Apr 2019 13:15:02 -0700 Subject: [PATCH 621/718] Deprecate Mapper 2.0 from Q launching devices Bug: 130669566, 62535446 Test: build, boot Change-Id: I1bd576d5a8e8b8fef50a81eae1de18898fe895dd --- compatibility_matrices/compatibility_matrix.4.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compatibility_matrices/compatibility_matrix.4.xml b/compatibility_matrices/compatibility_matrix.4.xml index a4e77cc0c1..a34f746d89 100644 --- a/compatibility_matrices/compatibility_matrix.4.xml +++ b/compatibility_matrices/compatibility_matrix.4.xml @@ -207,7 +207,7 @@ android.hardware.graphics.mapper - 2.0-1 + 2.1 3.0 IMapper From 99712c08ccc5d8a525b020a6c44cf1f2d24a2337 Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Thu, 18 Apr 2019 18:13:05 -0700 Subject: [PATCH 622/718] Update hidl makefiles for bpfmt hidl-generated makefiles are now generated such that bpfmt(file) == file. Bug: 67417008 Test: enable bpfmt hook Change-Id: I53e5bf67a0d314e1b10c0ba0c7172a7af358ddcc --- biometrics/face/1.0/Android.bp | 1 - camera/device/3.5/Android.bp | 1 - camera/metadata/3.4/Android.bp | 1 - camera/provider/2.5/Android.bp | 1 - cas/1.1/Android.bp | 1 - drm/1.2/Android.bp | 1 - gnss/2.0/Android.bp | 1 - gnss/measurement_corrections/1.0/Android.bp | 1 - gnss/visibility_control/1.0/Android.bp | 1 - graphics/allocator/3.0/Android.bp | 1 - graphics/bufferqueue/2.0/Android.bp | 1 - graphics/common/1.2/Android.bp | 1 - graphics/composer/2.3/Android.bp | 1 - graphics/mapper/3.0/Android.bp | 1 - input/classifier/1.0/Android.bp | 1 - input/common/1.0/Android.bp | 1 - media/bufferpool/2.0/Android.bp | 1 - media/c2/1.0/Android.bp | 1 - sensors/2.0/Android.bp | 1 - soundtrigger/2.2/Android.bp | 1 - thermal/2.0/Android.bp | 1 - tv/cec/2.0/Android.bp | 1 - usb/1.2/Android.bp | 1 - vibrator/1.3/Android.bp | 3 +-- wifi/1.3/Android.bp | 1 - wifi/hostapd/1.1/Android.bp | 1 - wifi/supplicant/1.2/Android.bp | 1 - 27 files changed, 1 insertion(+), 28 deletions(-) diff --git a/biometrics/face/1.0/Android.bp b/biometrics/face/1.0/Android.bp index 222a09e5e9..ebb8668938 100644 --- a/biometrics/face/1.0/Android.bp +++ b/biometrics/face/1.0/Android.bp @@ -16,4 +16,3 @@ hidl_interface { ], gen_java: true, } - diff --git a/camera/device/3.5/Android.bp b/camera/device/3.5/Android.bp index d51fd0ef87..362a5e6894 100644 --- a/camera/device/3.5/Android.bp +++ b/camera/device/3.5/Android.bp @@ -22,4 +22,3 @@ hidl_interface { ], gen_java: false, } - diff --git a/camera/metadata/3.4/Android.bp b/camera/metadata/3.4/Android.bp index 2b75eba51a..6a924580fd 100644 --- a/camera/metadata/3.4/Android.bp +++ b/camera/metadata/3.4/Android.bp @@ -15,4 +15,3 @@ hidl_interface { ], gen_java: true, } - diff --git a/camera/provider/2.5/Android.bp b/camera/provider/2.5/Android.bp index a4af07e7c2..4ca1efbfc3 100644 --- a/camera/provider/2.5/Android.bp +++ b/camera/provider/2.5/Android.bp @@ -19,4 +19,3 @@ hidl_interface { ], gen_java: false, } - diff --git a/cas/1.1/Android.bp b/cas/1.1/Android.bp index bb0edb970c..13217b6439 100644 --- a/cas/1.1/Android.bp +++ b/cas/1.1/Android.bp @@ -17,4 +17,3 @@ hidl_interface { ], gen_java: true, } - diff --git a/drm/1.2/Android.bp b/drm/1.2/Android.bp index 2d54302a58..9104aa9ce8 100644 --- a/drm/1.2/Android.bp +++ b/drm/1.2/Android.bp @@ -21,4 +21,3 @@ hidl_interface { ], gen_java: false, } - diff --git a/gnss/2.0/Android.bp b/gnss/2.0/Android.bp index 6cfd3462f2..db5075f862 100644 --- a/gnss/2.0/Android.bp +++ b/gnss/2.0/Android.bp @@ -30,4 +30,3 @@ hidl_interface { gen_java: true, gen_java_constants: true, } - diff --git a/gnss/measurement_corrections/1.0/Android.bp b/gnss/measurement_corrections/1.0/Android.bp index 456b55c0ef..837cc7abca 100644 --- a/gnss/measurement_corrections/1.0/Android.bp +++ b/gnss/measurement_corrections/1.0/Android.bp @@ -17,4 +17,3 @@ hidl_interface { ], gen_java: true, } - diff --git a/gnss/visibility_control/1.0/Android.bp b/gnss/visibility_control/1.0/Android.bp index 40a28c90ab..e58e9327cb 100644 --- a/gnss/visibility_control/1.0/Android.bp +++ b/gnss/visibility_control/1.0/Android.bp @@ -15,4 +15,3 @@ hidl_interface { ], gen_java: true, } - diff --git a/graphics/allocator/3.0/Android.bp b/graphics/allocator/3.0/Android.bp index fa3e2cecc7..2cfa1d0ab7 100644 --- a/graphics/allocator/3.0/Android.bp +++ b/graphics/allocator/3.0/Android.bp @@ -18,4 +18,3 @@ hidl_interface { ], gen_java: false, } - diff --git a/graphics/bufferqueue/2.0/Android.bp b/graphics/bufferqueue/2.0/Android.bp index 97c05faf1e..fd080794b8 100644 --- a/graphics/bufferqueue/2.0/Android.bp +++ b/graphics/bufferqueue/2.0/Android.bp @@ -19,4 +19,3 @@ hidl_interface { ], gen_java: true, } - diff --git a/graphics/common/1.2/Android.bp b/graphics/common/1.2/Android.bp index 088bc377f6..2c4d93b734 100644 --- a/graphics/common/1.2/Android.bp +++ b/graphics/common/1.2/Android.bp @@ -17,4 +17,3 @@ hidl_interface { gen_java: true, gen_java_constants: true, } - diff --git a/graphics/composer/2.3/Android.bp b/graphics/composer/2.3/Android.bp index 6d29348269..a777556aee 100644 --- a/graphics/composer/2.3/Android.bp +++ b/graphics/composer/2.3/Android.bp @@ -20,4 +20,3 @@ hidl_interface { ], gen_java: false, } - diff --git a/graphics/mapper/3.0/Android.bp b/graphics/mapper/3.0/Android.bp index e34829652b..a14324310c 100644 --- a/graphics/mapper/3.0/Android.bp +++ b/graphics/mapper/3.0/Android.bp @@ -19,4 +19,3 @@ hidl_interface { ], gen_java: false, } - diff --git a/input/classifier/1.0/Android.bp b/input/classifier/1.0/Android.bp index 6815a513c1..11e0f52dd0 100644 --- a/input/classifier/1.0/Android.bp +++ b/input/classifier/1.0/Android.bp @@ -15,4 +15,3 @@ hidl_interface { ], gen_java: true, } - diff --git a/input/common/1.0/Android.bp b/input/common/1.0/Android.bp index 07b38cf3e5..2c7c517cce 100644 --- a/input/common/1.0/Android.bp +++ b/input/common/1.0/Android.bp @@ -11,4 +11,3 @@ hidl_interface { ], gen_java: true, } - diff --git a/media/bufferpool/2.0/Android.bp b/media/bufferpool/2.0/Android.bp index 0faa00ef00..6a82616b6f 100644 --- a/media/bufferpool/2.0/Android.bp +++ b/media/bufferpool/2.0/Android.bp @@ -18,4 +18,3 @@ hidl_interface { ], gen_java: false, } - diff --git a/media/c2/1.0/Android.bp b/media/c2/1.0/Android.bp index 895e9dbbf8..391e6c4a1f 100644 --- a/media/c2/1.0/Android.bp +++ b/media/c2/1.0/Android.bp @@ -31,4 +31,3 @@ hidl_interface { ], gen_java: false, } - diff --git a/sensors/2.0/Android.bp b/sensors/2.0/Android.bp index eead1d3f28..c8517c8dcb 100644 --- a/sensors/2.0/Android.bp +++ b/sensors/2.0/Android.bp @@ -17,4 +17,3 @@ hidl_interface { ], gen_java: false, } - diff --git a/soundtrigger/2.2/Android.bp b/soundtrigger/2.2/Android.bp index 0a7c2d80ba..43898c76aa 100644 --- a/soundtrigger/2.2/Android.bp +++ b/soundtrigger/2.2/Android.bp @@ -17,4 +17,3 @@ hidl_interface { ], gen_java: false, } - diff --git a/thermal/2.0/Android.bp b/thermal/2.0/Android.bp index af23ee3df0..1b76f37f27 100644 --- a/thermal/2.0/Android.bp +++ b/thermal/2.0/Android.bp @@ -17,4 +17,3 @@ hidl_interface { ], gen_java: true, } - diff --git a/tv/cec/2.0/Android.bp b/tv/cec/2.0/Android.bp index 5a67fa55f6..61450ac4fb 100644 --- a/tv/cec/2.0/Android.bp +++ b/tv/cec/2.0/Android.bp @@ -17,4 +17,3 @@ hidl_interface { ], gen_java: true, } - diff --git a/usb/1.2/Android.bp b/usb/1.2/Android.bp index 5206754d98..b3ba81f1cf 100644 --- a/usb/1.2/Android.bp +++ b/usb/1.2/Android.bp @@ -19,4 +19,3 @@ hidl_interface { gen_java: true, gen_java_constants: true, } - diff --git a/vibrator/1.3/Android.bp b/vibrator/1.3/Android.bp index a2ff784a6c..357ea9a3e1 100644 --- a/vibrator/1.3/Android.bp +++ b/vibrator/1.3/Android.bp @@ -7,8 +7,8 @@ hidl_interface { enabled: true, }, srcs: [ - "IVibrator.hal", "types.hal", + "IVibrator.hal", ], interfaces: [ "android.hardware.vibrator@1.0", @@ -18,4 +18,3 @@ hidl_interface { ], gen_java: true, } - diff --git a/wifi/1.3/Android.bp b/wifi/1.3/Android.bp index 401c7a618c..3719c2b76b 100644 --- a/wifi/1.3/Android.bp +++ b/wifi/1.3/Android.bp @@ -20,4 +20,3 @@ hidl_interface { ], gen_java: true, } - diff --git a/wifi/hostapd/1.1/Android.bp b/wifi/hostapd/1.1/Android.bp index d4170b678a..64fbc93791 100644 --- a/wifi/hostapd/1.1/Android.bp +++ b/wifi/hostapd/1.1/Android.bp @@ -17,4 +17,3 @@ hidl_interface { ], gen_java: true, } - diff --git a/wifi/supplicant/1.2/Android.bp b/wifi/supplicant/1.2/Android.bp index c685022b09..185d2b8df2 100644 --- a/wifi/supplicant/1.2/Android.bp +++ b/wifi/supplicant/1.2/Android.bp @@ -21,4 +21,3 @@ hidl_interface { ], gen_java: true, } - From 444473fbc083355c978ceb0476de56fc3af16f4c Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Fri, 19 Apr 2019 08:41:20 -0700 Subject: [PATCH 623/718] wifi(implementation): Simplify getFirstActiveWlanIfaceName Get rid of the unnecessary looping inside the method which was causing a bunch of unnecessary selinux denial logs. Bug: 130384921 Test: ./data/android.hardware.wifi@1.0-service-tests Test: Manually verified the property name after wifi on/off & softap on/off. Change-Id: Ia9f61749b2017234851d67b027deb685cb8b539e --- wifi/1.3/default/wifi_chip.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/wifi/1.3/default/wifi_chip.cpp b/wifi/1.3/default/wifi_chip.cpp index 25eb289838..b768959f2a 100644 --- a/wifi/1.3/default/wifi_chip.cpp +++ b/wifi/1.3/default/wifi_chip.cpp @@ -1436,14 +1436,11 @@ bool WifiChip::isStaApConcurrencyAllowedInCurrentMode() { } std::string WifiChip::getFirstActiveWlanIfaceName() { - for (unsigned idx = 0; idx < kMaxWlanIfaces; idx++) { - const auto ifname = getWlanIfaceName(idx); - if (findUsingName(sta_ifaces_, ifname)) return ifname; - if (findUsingName(ap_ifaces_, ifname)) return ifname; - } + if (sta_ifaces_.size() > 0) return sta_ifaces_[0]->getName(); + if (ap_ifaces_.size() > 0) return ap_ifaces_[0]->getName(); // This could happen if the chip call is made before any STA/AP // iface is created. Default to wlan0 for such cases. - LOG(WARNING) << "No active wlan interfaces in use!"; + LOG(WARNING) << "No active wlan interfaces in use! Using default"; return getWlanIfaceName(0); } From 8f8d17756ef5d109a7f447ec1dcea5bfcea9af8e Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Mon, 22 Apr 2019 13:49:27 -0700 Subject: [PATCH 624/718] Remove wifi.offload from Q compat matrix. As it turns out, the client side of this HAL was never implemented. Ideally, we could completely remove the HAL from old compatibility matrices and remove the HAL from current.txt. However, this would break some old devices which include an implementation. Bug: 130080335 Bug: 126892442 Test: build only (checks manifest) Change-Id: I7205faa719b9566af1b4e56fda083c540d622dff --- compatibility_matrices/compatibility_matrix.4.xml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/compatibility_matrices/compatibility_matrix.4.xml b/compatibility_matrices/compatibility_matrix.4.xml index a4e77cc0c1..c77f408338 100644 --- a/compatibility_matrices/compatibility_matrix.4.xml +++ b/compatibility_matrices/compatibility_matrix.4.xml @@ -493,14 +493,6 @@ default - - android.hardware.wifi.offload - 1.0 - - IOffload - default - - android.hardware.wifi.supplicant 1.0-2 From 69ee26a3891b8652c8c67fc8f8a262368f6fa7ff Mon Sep 17 00:00:00 2001 From: Valerie Hau Date: Wed, 17 Apr 2019 16:17:52 -0700 Subject: [PATCH 625/718] Call into validateBufferSize and getTransportSize After adding validateBufferSize and getTransportSize, call into these functions if they have been implemented Bug: 130669566 Test: build, boot Change-Id: I445cb6122107a514bc0bf433a9e140dbe3122573 --- .../mapper-passthrough/2.1/Gralloc0Hal.h | 48 ++++++++++++------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/Gralloc0Hal.h b/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/Gralloc0Hal.h index b704fdba4c..18fbb6d035 100644 --- a/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/Gralloc0Hal.h +++ b/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/Gralloc0Hal.h @@ -34,34 +34,48 @@ using V2_0::Error; template class Gralloc0HalImpl : public V2_0::passthrough::detail::Gralloc0HalImpl { public: - Error validateBufferSize(const native_handle_t* /*bufferHandle*/, - const IMapper::BufferDescriptorInfo& /*descriptorInfo*/, - uint32_t /*stride*/) override { - // need a gralloc0 extension to really validate - return Error::NONE; - } + Error validateBufferSize(const native_handle_t* bufferHandle, + const IMapper::BufferDescriptorInfo& descriptorInfo, + uint32_t stride) override { + if (!mModule->validateBufferSize) { + return Error::NONE; + } - Error getTransportSize(const native_handle_t* bufferHandle, uint32_t* outNumFds, - uint32_t* outNumInts) override { - // need a gralloc0 extension to get the transport size - *outNumFds = bufferHandle->numFds; - *outNumInts = bufferHandle->numInts; - return Error::NONE; + int32_t ret = mModule->validateBufferSize( + mModule, bufferHandle, descriptorInfo.width, descriptorInfo.height, + static_cast(descriptorInfo.format), + static_cast(descriptorInfo.usage), stride); + return static_cast(ret); + } + Error getTransportSize(const native_handle_t* bufferHandle, uint32_t* outNumFds, + uint32_t* outNumInts) override { + if (!mModule->getTransportSize) { + *outNumFds = bufferHandle->numFds; + *outNumInts = bufferHandle->numInts; + return Error::NONE; + } + + int32_t ret = mModule->getTransportSize(mModule, bufferHandle, outNumFds, outNumInts); + return static_cast(ret); } Error createDescriptor_2_1(const IMapper::BufferDescriptorInfo& descriptorInfo, BufferDescriptor* outDescriptor) override { return createDescriptor( - V2_0::IMapper::BufferDescriptorInfo{ - descriptorInfo.width, descriptorInfo.height, descriptorInfo.layerCount, - static_cast(descriptorInfo.format), descriptorInfo.usage, - }, - outDescriptor); + V2_0::IMapper::BufferDescriptorInfo{ + descriptorInfo.width, + descriptorInfo.height, + descriptorInfo.layerCount, + static_cast(descriptorInfo.format), + descriptorInfo.usage, + }, + outDescriptor); } private: using BaseType2_0 = V2_0::passthrough::detail::Gralloc0HalImpl; using BaseType2_0::createDescriptor; + using BaseType2_0::mModule; }; } // namespace detail From 7651215285020b9cd8abbdaa0f50927c4236c7ae Mon Sep 17 00:00:00 2001 From: Changyeon Jo Date: Fri, 29 Mar 2019 10:48:36 -0700 Subject: [PATCH 626/718] Add BGRA8888 format support. Bug: 129462449 Test: Build and run VTS on Hawk Change-Id: I9d162b3200b64fbbec802eb1b0a2b6862af6949b Signed-off-by: Changyeon Jo (cherry picked from commit af09bfeed4f2f4bfc1bffeb6974e9010cbcf203e) --- .../evs/1.0/vts/functional/FormatConvert.cpp | 59 +++++++++++++++---- .../evs/1.0/vts/functional/FormatConvert.h | 26 ++++++-- .../evs/1.0/vts/functional/FrameHandler.cpp | 37 ++++++++++-- 3 files changed, 98 insertions(+), 24 deletions(-) diff --git a/automotive/evs/1.0/vts/functional/FormatConvert.cpp b/automotive/evs/1.0/vts/functional/FormatConvert.cpp index 1e8929d6b7..3d82d32cac 100644 --- a/automotive/evs/1.0/vts/functional/FormatConvert.cpp +++ b/automotive/evs/1.0/vts/functional/FormatConvert.cpp @@ -38,7 +38,8 @@ static inline float clamp(float v, float min, float max) { } -static uint32_t yuvToRgbx(const unsigned char Y, const unsigned char Uin, const unsigned char Vin) { +static uint32_t yuvToRgbx(const unsigned char Y, const unsigned char Uin, const unsigned char Vin, + bool bgrxFormat = false) { // Don't use this if you want to see the best performance. :) // Better to do this in a pixel shader if we really have to, but on actual // embedded hardware we expect to be able to texture directly from the YUV data @@ -52,16 +53,24 @@ static uint32_t yuvToRgbx(const unsigned char Y, const unsigned char Uin, const unsigned char G = (unsigned char)clamp(Gf, 0.0f, 255.0f); unsigned char B = (unsigned char)clamp(Bf, 0.0f, 255.0f); - return (R ) | - (G << 8) | - (B << 16) | - 0xFF000000; // Fill the alpha channel with ones + if (!bgrxFormat) { + return (R ) | + (G << 8) | + (B << 16) | + 0xFF000000; // Fill the alpha channel with ones + } else { + return (R << 16) | + (G << 8) | + (B ) | + 0xFF000000; // Fill the alpha channel with ones + } } void copyNV21toRGB32(unsigned width, unsigned height, uint8_t* src, - uint32_t* dst, unsigned dstStridePixels) + uint32_t* dst, unsigned dstStridePixels, + bool bgrxFormat) { // The NV21 format provides a Y array of 8bit values, followed by a 1/2 x 1/2 interleaved // U/V array. It assumes an even width and height for the overall image, and a horizontal @@ -84,7 +93,7 @@ void copyNV21toRGB32(unsigned width, unsigned height, for (unsigned c = 0; c < width; c++) { unsigned uCol = (c & ~1); // uCol is always even and repeats 1:2 with Y values unsigned vCol = uCol | 1; // vCol is always odd - rowDest[c] = yuvToRgbx(rowY[c], rowUV[uCol], rowUV[vCol]); + rowDest[c] = yuvToRgbx(rowY[c], rowUV[uCol], rowUV[vCol], bgrxFormat); } } } @@ -92,7 +101,8 @@ void copyNV21toRGB32(unsigned width, unsigned height, void copyYV12toRGB32(unsigned width, unsigned height, uint8_t* src, - uint32_t* dst, unsigned dstStridePixels) + uint32_t* dst, unsigned dstStridePixels, + bool bgrxFormat) { // The YV12 format provides a Y array of 8bit values, followed by a 1/2 x 1/2 U array, followed // by another 1/2 x 1/2 V array. It assumes an even width and height for the overall image, @@ -118,7 +128,7 @@ void copyYV12toRGB32(unsigned width, unsigned height, uint32_t* rowDest = dst + r*dstStridePixels; for (unsigned c = 0; c < width; c++) { - rowDest[c] = yuvToRgbx(rowY[c], rowU[c], rowV[c]); + rowDest[c] = yuvToRgbx(rowY[c], rowU[c], rowV[c], bgrxFormat); } } } @@ -126,7 +136,8 @@ void copyYV12toRGB32(unsigned width, unsigned height, void copyYUYVtoRGB32(unsigned width, unsigned height, uint8_t* src, unsigned srcStridePixels, - uint32_t* dst, unsigned dstStridePixels) + uint32_t* dst, unsigned dstStridePixels, + bool bgrxFormat) { uint32_t* srcWords = (uint32_t*)src; @@ -144,8 +155,8 @@ void copyYUYVtoRGB32(unsigned width, unsigned height, uint8_t V = (srcPixel >> 24) & 0xFF; // On the RGB output, we're writing one pixel at a time - *(dst+0) = yuvToRgbx(Y1, U, V); - *(dst+1) = yuvToRgbx(Y2, U, V); + *(dst+0) = yuvToRgbx(Y1, U, V, bgrxFormat); + *(dst+1) = yuvToRgbx(Y2, U, V, bgrxFormat); dst += 2; } @@ -156,6 +167,30 @@ void copyYUYVtoRGB32(unsigned width, unsigned height, } +void copyNV21toBGR32(unsigned width, unsigned height, + uint8_t* src, + uint32_t* dst, unsigned dstStridePixels) +{ + return copyNV21toRGB32(width, height, src, dst, dstStridePixels, true); +} + + +void copyYV12toBGR32(unsigned width, unsigned height, + uint8_t* src, + uint32_t* dst, unsigned dstStridePixels) +{ + return copyYV12toRGB32(width, height, src, dst, dstStridePixels, true); +} + + +void copyYUYVtoBGR32(unsigned width, unsigned height, + uint8_t* src, unsigned srcStridePixels, + uint32_t* dst, unsigned dstStridePixels) +{ + return copyYUYVtoRGB32(width, height, src, srcStridePixels, dst, dstStridePixels, true); +} + + void copyMatchedInterleavedFormats(unsigned width, unsigned height, void* src, unsigned srcStridePixels, void* dst, unsigned dstStridePixels, diff --git a/automotive/evs/1.0/vts/functional/FormatConvert.h b/automotive/evs/1.0/vts/functional/FormatConvert.h index 3ff1eec12d..4a94f996d0 100644 --- a/automotive/evs/1.0/vts/functional/FormatConvert.h +++ b/automotive/evs/1.0/vts/functional/FormatConvert.h @@ -21,30 +21,44 @@ #include -// Given an image buffer in NV21 format (HAL_PIXEL_FORMAT_YCRCB_420_SP), output 32bit RGBx values. -// The NV21 format provides a Y array of 8bit values, followed by a 1/2 x 1/2 interleaved +// Given an image buffer in NV21 format (HAL_PIXEL_FORMAT_YCRCB_420_SP), output 32bit RGBx/BGRx +// values. The NV21 format provides a Y array of 8bit values, followed by a 1/2 x 1/2 interleaved // U/V array. It assumes an even width and height for the overall image, and a horizontal // stride that is an even multiple of 16 bytes for both the Y and UV arrays. void copyNV21toRGB32(unsigned width, unsigned height, + uint8_t* src, + uint32_t* dst, unsigned dstStridePixels, + bool bgrxFormat = false); + +void copyNV21toBGR32(unsigned width, unsigned height, uint8_t* src, uint32_t* dst, unsigned dstStridePixels); -// Given an image buffer in YV12 format (HAL_PIXEL_FORMAT_YV12), output 32bit RGBx values. +// Given an image buffer in YV12 format (HAL_PIXEL_FORMAT_YV12), output 32bit RGBx/BGRx values. // The YV12 format provides a Y array of 8bit values, followed by a 1/2 x 1/2 U array, followed // by another 1/2 x 1/2 V array. It assumes an even width and height for the overall image, // and a horizontal stride that is an even multiple of 16 bytes for each of the Y, U, // and V arrays. void copyYV12toRGB32(unsigned width, unsigned height, + uint8_t* src, + uint32_t* dst, unsigned dstStridePixels, + bool bgrxFormat = false); + +void copyYV12toBGR32(unsigned width, unsigned height, uint8_t* src, uint32_t* dst, unsigned dstStridePixels); - -// Given an image buffer in YUYV format (HAL_PIXEL_FORMAT_YCBCR_422_I), output 32bit RGBx values. -// The NV21 format provides a Y array of 8bit values, followed by a 1/2 x 1/2 interleaved +// Given an image buffer in YUYV format (HAL_PIXEL_FORMAT_YCBCR_422_I), output 32bit RGBx/BGRx +// values. The NV21 format provides a Y array of 8bit values, followed by a 1/2 x 1/2 interleaved // U/V array. It assumes an even width and height for the overall image, and a horizontal // stride that is an even multiple of 16 bytes for both the Y and UV arrays. void copyYUYVtoRGB32(unsigned width, unsigned height, + uint8_t* src, unsigned srcStrideBytes, + uint32_t* dst, unsigned dstStrideBytes, + bool bgrxFormat = false); + +void copyYUYVtoBGR32(unsigned width, unsigned height, uint8_t* src, unsigned srcStrideBytes, uint32_t* dst, unsigned dstStrideBytes); diff --git a/automotive/evs/1.0/vts/functional/FrameHandler.cpp b/automotive/evs/1.0/vts/functional/FrameHandler.cpp index a69f72be49..d44ba41c5d 100644 --- a/automotive/evs/1.0/vts/functional/FrameHandler.cpp +++ b/automotive/evs/1.0/vts/functional/FrameHandler.cpp @@ -231,16 +231,12 @@ bool FrameHandler::copyBufferContents(const BufferDesc& tgtBuffer, uint8_t* srcPixels = nullptr; src->lock(GRALLOC_USAGE_SW_READ_OFTEN, (void**)&srcPixels); - // Lock our target buffer for writing (should be RGBA8888 format) + // Lock our target buffer for writing (should be either RGBA8888 or BGRA8888 format) uint32_t* tgtPixels = nullptr; tgt->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)&tgtPixels); if (srcPixels && tgtPixels) { - if (tgtBuffer.format != HAL_PIXEL_FORMAT_RGBA_8888) { - // We always expect 32 bit RGB for the display output for now. Is there a need for 565? - ALOGE("Diplay buffer is always expected to be 32bit RGBA"); - success = false; - } else { + if (tgtBuffer.format == HAL_PIXEL_FORMAT_RGBA_8888) { if (srcBuffer.format == HAL_PIXEL_FORMAT_YCRCB_420_SP) { // 420SP == NV21 copyNV21toRGB32(width, height, srcPixels, @@ -258,7 +254,36 @@ bool FrameHandler::copyBufferContents(const BufferDesc& tgtBuffer, srcPixels, srcBuffer.stride, tgtPixels, tgtBuffer.stride, tgtBuffer.pixelSize); + } else { + ALOGE("Camera buffer format is not supported"); + success = false; } + } else if (tgtBuffer.format == HAL_PIXEL_FORMAT_BGRA_8888) { + if (srcBuffer.format == HAL_PIXEL_FORMAT_YCRCB_420_SP) { // 420SP == NV21 + copyNV21toBGR32(width, height, + srcPixels, + tgtPixels, tgtBuffer.stride); + } else if (srcBuffer.format == HAL_PIXEL_FORMAT_YV12) { // YUV_420P == YV12 + copyYV12toBGR32(width, height, + srcPixels, + tgtPixels, tgtBuffer.stride); + } else if (srcBuffer.format == HAL_PIXEL_FORMAT_YCBCR_422_I) { // YUYV + copyYUYVtoBGR32(width, height, + srcPixels, srcBuffer.stride, + tgtPixels, tgtBuffer.stride); + } else if (srcBuffer.format == tgtBuffer.format) { // 32bit RGBA + copyMatchedInterleavedFormats(width, height, + srcPixels, srcBuffer.stride, + tgtPixels, tgtBuffer.stride, + tgtBuffer.pixelSize); + } else { + ALOGE("Camera buffer format is not supported"); + success = false; + } + } else { + // We always expect 32 bit RGB for the display output for now. Is there a need for 565? + ALOGE("Diplay buffer is always expected to be 32bit RGBA"); + success = false; } } else { ALOGE("Failed to lock buffer contents for contents transfer"); From d620a2984d9197d75aa54bb6f4a7d9b1788e1b70 Mon Sep 17 00:00:00 2001 From: Youming Ye Date: Tue, 23 Apr 2019 11:10:13 -0700 Subject: [PATCH 627/718] Add comment to track setSystemSelectionChannels api test Since the system API for the hal is not implemented in Q, we disable the vts test. Adding corresponding comments on the test. Bug: 130254624 Test: Build Change-Id: I777961aeaf8fb2baa28cee47cf3df4015a6ee0f0 --- radio/1.3/vts/functional/radio_hidl_hal_api.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/radio/1.3/vts/functional/radio_hidl_hal_api.cpp b/radio/1.3/vts/functional/radio_hidl_hal_api.cpp index 1bebae7389..030f489c48 100644 --- a/radio/1.3/vts/functional/radio_hidl_hal_api.cpp +++ b/radio/1.3/vts/functional/radio_hidl_hal_api.cpp @@ -78,6 +78,8 @@ TEST_F(RadioHidlTest_v1_3, getModemStackStatus) { /* * Test IRadio.setSystemSelectionChannels() for the response returned. + * + * This test is excluded from manifest, due to non-implementation in Q. Tracked by b/130254624. */ TEST_F(RadioHidlTest_v1_3, setSystemSelectionChannels) { serial = GetRandomSerialNumber(); From 5e01b1411afdecc94ab7e60b92ad02672eb5f759 Mon Sep 17 00:00:00 2001 From: Valerie Hau Date: Tue, 23 Apr 2019 22:53:06 +0000 Subject: [PATCH 628/718] Revert "Call into validateBufferSize and getTransportSize" This reverts commit 69ee26a3891b8652c8c67fc8f8a262368f6fa7ff. Reason for revert: Break in Elfin Bug: 130669566 Change-Id: Ia44fd087981770676a6887aa390c674c2855f4cb --- .../mapper-passthrough/2.1/Gralloc0Hal.h | 48 +++++++------------ 1 file changed, 17 insertions(+), 31 deletions(-) diff --git a/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/Gralloc0Hal.h b/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/Gralloc0Hal.h index 18fbb6d035..b704fdba4c 100644 --- a/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/Gralloc0Hal.h +++ b/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/Gralloc0Hal.h @@ -34,48 +34,34 @@ using V2_0::Error; template class Gralloc0HalImpl : public V2_0::passthrough::detail::Gralloc0HalImpl { public: - Error validateBufferSize(const native_handle_t* bufferHandle, - const IMapper::BufferDescriptorInfo& descriptorInfo, - uint32_t stride) override { - if (!mModule->validateBufferSize) { - return Error::NONE; - } + Error validateBufferSize(const native_handle_t* /*bufferHandle*/, + const IMapper::BufferDescriptorInfo& /*descriptorInfo*/, + uint32_t /*stride*/) override { + // need a gralloc0 extension to really validate + return Error::NONE; + } - int32_t ret = mModule->validateBufferSize( - mModule, bufferHandle, descriptorInfo.width, descriptorInfo.height, - static_cast(descriptorInfo.format), - static_cast(descriptorInfo.usage), stride); - return static_cast(ret); - } - Error getTransportSize(const native_handle_t* bufferHandle, uint32_t* outNumFds, - uint32_t* outNumInts) override { - if (!mModule->getTransportSize) { - *outNumFds = bufferHandle->numFds; - *outNumInts = bufferHandle->numInts; - return Error::NONE; - } - - int32_t ret = mModule->getTransportSize(mModule, bufferHandle, outNumFds, outNumInts); - return static_cast(ret); + Error getTransportSize(const native_handle_t* bufferHandle, uint32_t* outNumFds, + uint32_t* outNumInts) override { + // need a gralloc0 extension to get the transport size + *outNumFds = bufferHandle->numFds; + *outNumInts = bufferHandle->numInts; + return Error::NONE; } Error createDescriptor_2_1(const IMapper::BufferDescriptorInfo& descriptorInfo, BufferDescriptor* outDescriptor) override { return createDescriptor( - V2_0::IMapper::BufferDescriptorInfo{ - descriptorInfo.width, - descriptorInfo.height, - descriptorInfo.layerCount, - static_cast(descriptorInfo.format), - descriptorInfo.usage, - }, - outDescriptor); + V2_0::IMapper::BufferDescriptorInfo{ + descriptorInfo.width, descriptorInfo.height, descriptorInfo.layerCount, + static_cast(descriptorInfo.format), descriptorInfo.usage, + }, + outDescriptor); } private: using BaseType2_0 = V2_0::passthrough::detail::Gralloc0HalImpl; using BaseType2_0::createDescriptor; - using BaseType2_0::mModule; }; } // namespace detail From ebfdba67d23044ce9f65744425790b4ee107fc46 Mon Sep 17 00:00:00 2001 From: Garret Kelly Date: Wed, 24 Apr 2019 17:38:40 -0400 Subject: [PATCH 629/718] Fix comparison between hex and binary values The verified boot hash in the attestation record is a binary blob, while the property read from the system is a hex-encoded value. Convert the boot hash from the attestation record into hex before comparing. Test: VtsHalKeymasterV4_0TargetTest Bug: 130843899 Change-Id: I6f6e0da71501d741dd8b27d0778e1854af17ace6 --- keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp index fc96724225..cf12e2a4b5 100644 --- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp +++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp @@ -414,7 +414,7 @@ bool verify_attestation_record(const string& challenge, const string& app_id, EXPECT_NE(strcmp(property_value, "nogood"), 0); string prop_string(property_value); EXPECT_EQ(prop_string.size(), 64); - EXPECT_EQ(0, memcmp(verified_boot_hash.data(), prop_string.data(), verified_boot_hash.size())); + EXPECT_EQ(prop_string, bin2hex(verified_boot_hash)); property_get("ro.boot.vbmeta.device_state", property_value, "nogood"); EXPECT_NE(property_value, "nogood"); From 8e3fe149e1f55039015cf26a964a7f10c0b72d34 Mon Sep 17 00:00:00 2001 From: Valerie Hau Date: Wed, 24 Apr 2019 21:39:41 +0000 Subject: [PATCH 630/718] Call into validateBufferSize and getTransportSize After adding validateBufferSize and getTransportSize, call into these functions if they have been implemented This reverts commit 5e01b1411afdecc94ab7e60b92ad02672eb5f759. Reason for revert: Merge once targets w/ gralloc0 dependency have been updated Bug: 130669566 Test: build, boot Change-Id: Ic20a62c5e73f517028a358548442d59c9cf91cdf --- .../mapper-passthrough/2.1/Gralloc0Hal.h | 48 ++++++++++++------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/Gralloc0Hal.h b/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/Gralloc0Hal.h index b704fdba4c..18fbb6d035 100644 --- a/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/Gralloc0Hal.h +++ b/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/Gralloc0Hal.h @@ -34,34 +34,48 @@ using V2_0::Error; template class Gralloc0HalImpl : public V2_0::passthrough::detail::Gralloc0HalImpl { public: - Error validateBufferSize(const native_handle_t* /*bufferHandle*/, - const IMapper::BufferDescriptorInfo& /*descriptorInfo*/, - uint32_t /*stride*/) override { - // need a gralloc0 extension to really validate - return Error::NONE; - } + Error validateBufferSize(const native_handle_t* bufferHandle, + const IMapper::BufferDescriptorInfo& descriptorInfo, + uint32_t stride) override { + if (!mModule->validateBufferSize) { + return Error::NONE; + } - Error getTransportSize(const native_handle_t* bufferHandle, uint32_t* outNumFds, - uint32_t* outNumInts) override { - // need a gralloc0 extension to get the transport size - *outNumFds = bufferHandle->numFds; - *outNumInts = bufferHandle->numInts; - return Error::NONE; + int32_t ret = mModule->validateBufferSize( + mModule, bufferHandle, descriptorInfo.width, descriptorInfo.height, + static_cast(descriptorInfo.format), + static_cast(descriptorInfo.usage), stride); + return static_cast(ret); + } + Error getTransportSize(const native_handle_t* bufferHandle, uint32_t* outNumFds, + uint32_t* outNumInts) override { + if (!mModule->getTransportSize) { + *outNumFds = bufferHandle->numFds; + *outNumInts = bufferHandle->numInts; + return Error::NONE; + } + + int32_t ret = mModule->getTransportSize(mModule, bufferHandle, outNumFds, outNumInts); + return static_cast(ret); } Error createDescriptor_2_1(const IMapper::BufferDescriptorInfo& descriptorInfo, BufferDescriptor* outDescriptor) override { return createDescriptor( - V2_0::IMapper::BufferDescriptorInfo{ - descriptorInfo.width, descriptorInfo.height, descriptorInfo.layerCount, - static_cast(descriptorInfo.format), descriptorInfo.usage, - }, - outDescriptor); + V2_0::IMapper::BufferDescriptorInfo{ + descriptorInfo.width, + descriptorInfo.height, + descriptorInfo.layerCount, + static_cast(descriptorInfo.format), + descriptorInfo.usage, + }, + outDescriptor); } private: using BaseType2_0 = V2_0::passthrough::detail::Gralloc0HalImpl; using BaseType2_0::createDescriptor; + using BaseType2_0::mModule; }; } // namespace detail From 6e155781562a72f565dc85b43380bef46a4f737b Mon Sep 17 00:00:00 2001 From: Slava Shklyaev Date: Thu, 25 Apr 2019 11:34:09 +0100 Subject: [PATCH 631/718] Specify ranks supported by MAXIMUM and MINIMUM Note that this change documents existing behavior. Bug: 131210955 Test: mma Change-Id: I8d877153e1acc8ca2ad5179d7fd7cdc136838ca3 --- current.txt | 2 +- neuralnetworks/1.2/types.hal | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/current.txt b/current.txt index 3a6241c285..d1c52906f0 100644 --- a/current.txt +++ b/current.txt @@ -515,7 +515,7 @@ b83317b66721241887d2770b5ae95fd5af1e77c5daa7530ecb08fae8892f2b43 android.hardwar 92714960d1a53fc2ec557302b41c7cc93d2636d8364a44bd0f85be0c92927ff8 android.hardware.neuralnetworks@1.2::IExecutionCallback 36e1064c869965dee533c537cefbe87e54db8bd8cd45be7e0e93e00e8a43863a android.hardware.neuralnetworks@1.2::IPreparedModel e1c734d1545e1a4ae749ff1dd9704a8e594c59aea7c8363159dc258e93e0df3b android.hardware.neuralnetworks@1.2::IPreparedModelCallback -73e995644b1bb2678ec3ab850feb7a1b4495501953951c22316cefd67b900b3e android.hardware.neuralnetworks@1.2::types +51725cd8541bf459190d8a911f9aae9a0825678256b88fc39fac81d69feb04af android.hardware.neuralnetworks@1.2::types cf7a4ba516a638f9b82a249c91fb603042c2d9ca43fd5aad9cf6c0401ed2a5d7 android.hardware.nfc@1.2::INfc abf98c2ae08bf765db54edc8068e36d52eb558cff6706b6fd7c18c65a1f3fc18 android.hardware.nfc@1.2::types 4cb252dc6372a874aef666b92a6e9529915aa187521a700f0789065c3c702ead android.hardware.power.stats@1.0::IPowerStats diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal index 087249abf5..31576fa461 100644 --- a/neuralnetworks/1.2/types.hal +++ b/neuralnetworks/1.2/types.hal @@ -3531,6 +3531,8 @@ enum OperationType : int32_t { * * {@link OperandType::TENSOR_INT32} * * {@link OperandType::TENSOR_QUANT8_ASYMM} * + * Supported tensor rank: from 1. + * * Inputs: * * 0: A tensor. * * 1: A tensor of the same {@link OperandType} and compatible dimensions @@ -3552,6 +3554,8 @@ enum OperationType : int32_t { * * {@link OperandType::TENSOR_INT32} * * {@link OperandType::TENSOR_QUANT8_ASYMM} * + * Supported tensor rank: from 1. + * * Inputs: * * 0: A tensor. * * 1: A tensor of the same {@link OperandType} and compatible dimensions From 93e4a086dbdcd4acbb66efa19ff6ef6118b7191a Mon Sep 17 00:00:00 2001 From: mike dooley Date: Thu, 11 Apr 2019 15:08:22 +0200 Subject: [PATCH 632/718] Hooking up Hal Soundtrigger V2_2 VTS test Bug: 117309670 Test: vts-tradefed run commandAndExit vts -m VtsHalSoundtriggerV2_2Target Change-Id: Id320d15a39a6a22cbbcdb00b3b4658d690ab1fe0 --- soundtrigger/2.2/vts/functional/Android.bp | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 soundtrigger/2.2/vts/functional/Android.bp diff --git a/soundtrigger/2.2/vts/functional/Android.bp b/soundtrigger/2.2/vts/functional/Android.bp new file mode 100644 index 0000000000..08ccd7b09d --- /dev/null +++ b/soundtrigger/2.2/vts/functional/Android.bp @@ -0,0 +1,27 @@ +// +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +cc_test { + name: "VtsHalSoundtriggerV2_2TargetTest", + defaults: ["VtsHalTargetTestDefaults"], + srcs: ["VtsHalSoundtriggerV2_2TargetTest.cpp"], + static_libs: [ + "android.hardware.soundtrigger@2.0", + "android.hardware.soundtrigger@2.1", + "android.hardware.soundtrigger@2.2", + ], + test_suites: ["general-tests"], +} From 0d540b3e75a93178f97623dc2b146955741d0748 Mon Sep 17 00:00:00 2001 From: Yin-Chia Yeh Date: Thu, 25 Apr 2019 14:55:22 -0700 Subject: [PATCH 633/718] External Camera: support less thumbnail sizes Since larger thumbnail sizes might hit the app1 size limit of 64KB. Test: camera CTS Bug: 119775355 Change-Id: I9d8d21ac0784c53b42c536cfa09a8c40c4f15ea0 --- camera/device/3.4/default/ExternalCameraDevice.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/camera/device/3.4/default/ExternalCameraDevice.cpp b/camera/device/3.4/default/ExternalCameraDevice.cpp index 3f047517dd..9a2fddff88 100644 --- a/camera/device/3.4/default/ExternalCameraDevice.cpp +++ b/camera/device/3.4/default/ExternalCameraDevice.cpp @@ -342,8 +342,7 @@ status_t ExternalCameraDevice::initDefaultCharsKeys( 256, 144, 240, 160, 256, 154, - 240, 240, - 320, 240}; + 240, 180}; UPDATE(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES, jpegAvailableThumbnailSizes, ARRAY_SIZE(jpegAvailableThumbnailSizes)); From 24621daf454b0f8db031e32f1fc054b90931ebc7 Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Fri, 19 Apr 2019 19:51:41 -0700 Subject: [PATCH 634/718] Add dep to ...broadcastradio@common-utils-2x-tests Required now because iterators use the base hidl_vec constructor. It's not expected this type of change would be needed in any places. This test originally came with the introduction of the constructor that created the hidl_vec. Bug: 131356202 Test: build only, links (note b/130918604) Change-Id: Ide3cb13b6afd79489c208af2396e7c02b7da436e Merged-In: Ide3cb13b6afd79489c208af2396e7c02b7da436e --- broadcastradio/common/tests/Android.bp | 1 + 1 file changed, 1 insertion(+) diff --git a/broadcastradio/common/tests/Android.bp b/broadcastradio/common/tests/Android.bp index ef8733c290..0ace941ac1 100644 --- a/broadcastradio/common/tests/Android.bp +++ b/broadcastradio/common/tests/Android.bp @@ -58,6 +58,7 @@ cc_test { "android.hardware.broadcastradio@common-utils-2x-lib", ], shared_libs: [ + "libhidlbase", "android.hardware.broadcastradio@2.0", ], test_suites: ["general-tests"], From e640a420af306581f72e5f6629cea4ed515d8e26 Mon Sep 17 00:00:00 2001 From: Anil Admal Date: Mon, 8 Apr 2019 17:05:04 -0700 Subject: [PATCH 635/718] Enforce launched-in-Q devices support gnss@2.0 HAL package (hal) Bug: 121287858 Test: atest VtsTrebleVendorVintfTest Change-Id: I45d7f3b6c8353141922724df23780d42df870413 --- compatibility_matrices/compatibility_matrix.4.xml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/compatibility_matrices/compatibility_matrix.4.xml b/compatibility_matrices/compatibility_matrix.4.xml index a34f746d89..a5e4c1c033 100644 --- a/compatibility_matrices/compatibility_matrix.4.xml +++ b/compatibility_matrices/compatibility_matrix.4.xml @@ -181,7 +181,12 @@ android.hardware.gnss - 1.0-1 + + 1.1 2.0 IGnss From a44e130a92d1e897a6ac075affa2564021edd22d Mon Sep 17 00:00:00 2001 From: Xusong Wang Date: Tue, 23 Apr 2019 14:28:17 -0700 Subject: [PATCH 636/718] Test TOCTOU in VTS CompilationCachingTests. Two tests are added into VTS: 1. The TOCTOU test, for a fixed number of iterations. We try to attack the driver by replacing the model cache with another cache entry from a similar model while the driver is saving to or preparing from cache, and see if the driver crashes or falsely prepares an unexpected model (by checking the execution result). Either of the following results are acceptable * Fails -> the driver detects this corruption. * Succeeds and produces correct execution result -> the corruption happens before saving to cache or after preparing from cache. Due to the racy nature, this test is probabilistic and we run it several times. 2. Similar to the TOCTOU test but replace the content between compile-to-cache and compile-from-cache (once only). Additionally, remove tmp cache directory if test succeeds. Bug: 123433989 Test: VtsHalNeuralnetworksV1_xTargetTest with 1.2 sample driver Test: VtsHalNeuralnetworksV1_xTargetTest with a test driver that can read and write cache entries Test: Check /data/local/tmp and confirm that * dirs are preserved on failure * dirs are removed on success Change-Id: Ie04fa905f465c3775979f0ca74359d185dcacea9 --- .../functional/CompilationCachingTests.cpp | 353 +++++++++++++++++- 1 file changed, 337 insertions(+), 16 deletions(-) diff --git a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp index 167fc096ce..df95ac61b4 100644 --- a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp +++ b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp @@ -16,21 +16,22 @@ #define LOG_TAG "neuralnetworks_hidl_hal_test" -#include "VtsHalNeuralnetworks.h" +#include +#include +#include +#include +#include +#include + +#include +#include +#include #include "Callbacks.h" #include "GeneratedTestHarness.h" #include "TestHarness.h" #include "Utils.h" - -#include -#include -#include -#include -#include -#include - -#include +#include "VtsHalNeuralnetworks.h" namespace android { namespace hardware { @@ -46,7 +47,7 @@ using ::test_helper::MixedTypedExample; namespace { -// In frameworks/ml/nn/runtime/tests/generated/, creates a hidl model of mobilenet. +// In frameworks/ml/nn/runtime/test/generated/, creates a hidl model of mobilenet. #include "examples/mobilenet_224_gender_basic_fixed.example.cpp" #include "vts_models/mobilenet_224_gender_basic_fixed.model.cpp" @@ -89,6 +90,118 @@ void createCacheHandles(const std::vector>& fileGroups, createCacheHandles(fileGroups, std::vector(fileGroups.size(), mode), handles); } +// Create a chain of broadcast operations. The second operand is always constant tensor [1]. +// For simplicity, activation scalar is shared. The second operand is not shared +// in the model to let driver maintain a non-trivial size of constant data and the corresponding +// data locations in cache. +// +// --------- activation -------- +// ↓ ↓ ↓ ↓ +// E.g. input -> ADD -> ADD -> ADD -> ... -> ADD -> output +// ↑ ↑ ↑ ↑ +// [1] [1] [1] [1] +// +Model createLargeTestModel(OperationType op, uint32_t len) { + // Model operations and operands. + std::vector operations(len); + std::vector operands(len * 2 + 2); + + // The constant buffer pool. This contains the activation scalar, followed by the + // per-operation constant operands. + std::vector operandValues(sizeof(int32_t) + len * sizeof(float)); + + // The activation scalar, value = 0. + operands[0] = { + .type = OperandType::INT32, + .dimensions = {}, + .numberOfConsumers = len, + .scale = 0.0f, + .zeroPoint = 0, + .lifetime = OperandLifeTime::CONSTANT_COPY, + .location = {.poolIndex = 0, .offset = 0, .length = sizeof(int32_t)}, + }; + memset(operandValues.data(), 0, sizeof(int32_t)); + + const float floatBufferValue = 1.0f; + for (uint32_t i = 0; i < len; i++) { + const uint32_t firstInputIndex = i * 2 + 1; + const uint32_t secondInputIndex = firstInputIndex + 1; + const uint32_t outputIndex = secondInputIndex + 1; + + // The first operation input. + operands[firstInputIndex] = { + .type = OperandType::TENSOR_FLOAT32, + .dimensions = {1}, + .numberOfConsumers = 1, + .scale = 0.0f, + .zeroPoint = 0, + .lifetime = (i == 0 ? OperandLifeTime::MODEL_INPUT + : OperandLifeTime::TEMPORARY_VARIABLE), + .location = {}, + }; + + // The second operation input, value = 1. + operands[secondInputIndex] = { + .type = OperandType::TENSOR_FLOAT32, + .dimensions = {1}, + .numberOfConsumers = 1, + .scale = 0.0f, + .zeroPoint = 0, + .lifetime = OperandLifeTime::CONSTANT_COPY, + .location = {.poolIndex = 0, + .offset = static_cast(i * sizeof(float) + sizeof(int32_t)), + .length = sizeof(float)}, + }; + memcpy(operandValues.data() + sizeof(int32_t) + i * sizeof(float), &floatBufferValue, + sizeof(float)); + + // The operation. All operations share the same activation scalar. + // The output operand is created as an input in the next iteration of the loop, in the case + // of all but the last member of the chain; and after the loop as a model output, in the + // case of the last member of the chain. + operations[i] = { + .type = op, + .inputs = {firstInputIndex, secondInputIndex, /*activation scalar*/ 0}, + .outputs = {outputIndex}, + }; + } + + // The model output. + operands.back() = { + .type = OperandType::TENSOR_FLOAT32, + .dimensions = {1}, + .numberOfConsumers = 0, + .scale = 0.0f, + .zeroPoint = 0, + .lifetime = OperandLifeTime::MODEL_OUTPUT, + .location = {}, + }; + + const std::vector inputIndexes = {1}; + const std::vector outputIndexes = {len * 2 + 1}; + const std::vector pools = {}; + + return { + .operands = operands, + .operations = operations, + .inputIndexes = inputIndexes, + .outputIndexes = outputIndexes, + .operandValues = operandValues, + .pools = pools, + }; +} + +// MixedTypedExample is defined in frameworks/ml/nn/tools/test_generator/include/TestHarness.h. +// This function assumes the operation is always ADD. +std::vector getLargeModelExamples(uint32_t len) { + float outputValue = 1.0f + static_cast(len); + return {{.operands = { + // Input + {.operandDimensions = {{0, {1}}}, .float32Operands = {{0, {1.0f}}}}, + // Output + {.operandDimensions = {{0, {1}}}, .float32Operands = {{0, {outputValue}}}}}}}; +}; + } // namespace // Tag for the compilation caching tests. @@ -139,11 +252,13 @@ class CompilationCachingTest : public NeuralnetworksHidlTest { } void TearDown() override { - // The tmp directory is only removed when the driver reports caching not supported, - // otherwise it is kept for debugging purpose. - if (!mIsCachingSupported) { - remove(mTmpCache.c_str()); - rmdir(mCacheDir.c_str()); + // If the test passes, remove the tmp directory. Otherwise, keep it for debugging purposes. + if (!::testing::Test::HasFailure()) { + // Recursively remove the cache directory specified by mCacheDir. + auto callback = [](const char* entry, const struct stat*, int, struct FTW*) { + return remove(entry); + }; + nftw(mCacheDir.c_str(), callback, 128, FTW_DEPTH | FTW_MOUNT | FTW_PHYS); } NeuralnetworksHidlTest::TearDown(); } @@ -864,6 +979,212 @@ TEST_F(CompilationCachingTest, PrepareModelFromCacheInvalidAccessMode) { } } +// Copy file contents between file groups. +// The outer vector corresponds to handles and the inner vector is for fds held by each handle. +// The outer vector sizes must match and the inner vectors must have size = 1. +static void copyCacheFiles(const std::vector>& from, + const std::vector>& to) { + constexpr size_t kBufferSize = 1000000; + uint8_t buffer[kBufferSize]; + + ASSERT_EQ(from.size(), to.size()); + for (uint32_t i = 0; i < from.size(); i++) { + ASSERT_EQ(from[i].size(), 1u); + ASSERT_EQ(to[i].size(), 1u); + int fromFd = open(from[i][0].c_str(), O_RDONLY); + int toFd = open(to[i][0].c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); + ASSERT_GE(fromFd, 0); + ASSERT_GE(toFd, 0); + + ssize_t readBytes; + while ((readBytes = read(fromFd, &buffer, kBufferSize)) > 0) { + ASSERT_EQ(write(toFd, &buffer, readBytes), readBytes); + } + ASSERT_GE(readBytes, 0); + + close(fromFd); + close(toFd); + } +} + +// Number of operations in the large test model. +constexpr uint32_t kLargeModelSize = 100; +constexpr uint32_t kNumIterationsTOCTOU = 100; + +TEST_F(CompilationCachingTest, SaveToCache_TOCTOU) { + if (!mIsCachingSupported) return; + + // Save the testModelMul compilation to cache. + Model testModelMul = createLargeTestModel(OperationType::MUL, kLargeModelSize); + auto modelCacheMul = mModelCache; + for (auto& cache : modelCacheMul) { + cache[0].append("_mul"); + } + { + hidl_vec modelCache, dataCache; + createCacheHandles(modelCacheMul, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + bool supported; + saveModelToCache(testModelMul, modelCache, dataCache, &supported); + if (checkEarlyTermination(supported)) return; + } + + // Use a different token for testModelAdd. + mToken[0]++; + + // This test is probabilistic, so we run it multiple times. + Model testModelAdd = createLargeTestModel(OperationType::ADD, kLargeModelSize); + for (uint32_t i = 0; i < kNumIterationsTOCTOU; i++) { + // Save the testModelAdd compilation to cache. + { + bool supported; + hidl_vec modelCache, dataCache; + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + + // Spawn a thread to copy the cache content concurrently while saving to cache. + std::thread thread(copyCacheFiles, std::cref(modelCacheMul), std::cref(mModelCache)); + saveModelToCache(testModelAdd, modelCache, dataCache, &supported); + thread.join(); + if (checkEarlyTermination(supported)) return; + } + + // Retrieve preparedModel from cache. + { + sp preparedModel = nullptr; + ErrorStatus status; + hidl_vec modelCache, dataCache; + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + prepareModelFromCache(modelCache, dataCache, &preparedModel, &status); + + // The preparation may fail or succeed, but must not crash. If the preparation succeeds, + // the prepared model must be executed with the correct result and not crash. + if (status != ErrorStatus::NONE) { + ASSERT_EQ(preparedModel, nullptr); + } else { + ASSERT_NE(preparedModel, nullptr); + generated_tests::EvaluatePreparedModel( + preparedModel, [](int) { return false; }, + getLargeModelExamples(kLargeModelSize), + testModelAdd.relaxComputationFloat32toFloat16, + /*testDynamicOutputShape=*/false); + } + } + } +} + +TEST_F(CompilationCachingTest, PrepareFromCache_TOCTOU) { + if (!mIsCachingSupported) return; + + // Save the testModelMul compilation to cache. + Model testModelMul = createLargeTestModel(OperationType::MUL, kLargeModelSize); + auto modelCacheMul = mModelCache; + for (auto& cache : modelCacheMul) { + cache[0].append("_mul"); + } + { + hidl_vec modelCache, dataCache; + createCacheHandles(modelCacheMul, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + bool supported; + saveModelToCache(testModelMul, modelCache, dataCache, &supported); + if (checkEarlyTermination(supported)) return; + } + + // Use a different token for testModelAdd. + mToken[0]++; + + // This test is probabilistic, so we run it multiple times. + Model testModelAdd = createLargeTestModel(OperationType::ADD, kLargeModelSize); + for (uint32_t i = 0; i < kNumIterationsTOCTOU; i++) { + // Save the testModelAdd compilation to cache. + { + bool supported; + hidl_vec modelCache, dataCache; + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + saveModelToCache(testModelAdd, modelCache, dataCache, &supported); + if (checkEarlyTermination(supported)) return; + } + + // Retrieve preparedModel from cache. + { + sp preparedModel = nullptr; + ErrorStatus status; + hidl_vec modelCache, dataCache; + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + + // Spawn a thread to copy the cache content concurrently while preparing from cache. + std::thread thread(copyCacheFiles, std::cref(modelCacheMul), std::cref(mModelCache)); + prepareModelFromCache(modelCache, dataCache, &preparedModel, &status); + thread.join(); + + // The preparation may fail or succeed, but must not crash. If the preparation succeeds, + // the prepared model must be executed with the correct result and not crash. + if (status != ErrorStatus::NONE) { + ASSERT_EQ(preparedModel, nullptr); + } else { + ASSERT_NE(preparedModel, nullptr); + generated_tests::EvaluatePreparedModel( + preparedModel, [](int) { return false; }, + getLargeModelExamples(kLargeModelSize), + testModelAdd.relaxComputationFloat32toFloat16, + /*testDynamicOutputShape=*/false); + } + } + } +} + +TEST_F(CompilationCachingTest, ReplaceSecuritySensitiveCache) { + if (!mIsCachingSupported) return; + + // Save the testModelMul compilation to cache. + Model testModelMul = createLargeTestModel(OperationType::MUL, kLargeModelSize); + auto modelCacheMul = mModelCache; + for (auto& cache : modelCacheMul) { + cache[0].append("_mul"); + } + { + hidl_vec modelCache, dataCache; + createCacheHandles(modelCacheMul, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + bool supported; + saveModelToCache(testModelMul, modelCache, dataCache, &supported); + if (checkEarlyTermination(supported)) return; + } + + // Use a different token for testModelAdd. + mToken[0]++; + + // Save the testModelAdd compilation to cache. + Model testModelAdd = createLargeTestModel(OperationType::ADD, kLargeModelSize); + { + bool supported; + hidl_vec modelCache, dataCache; + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + saveModelToCache(testModelAdd, modelCache, dataCache, &supported); + if (checkEarlyTermination(supported)) return; + } + + // Replace the model cache of testModelAdd with testModelMul. + copyCacheFiles(modelCacheMul, mModelCache); + + // Retrieve the preparedModel from cache, expect failure. + { + sp preparedModel = nullptr; + ErrorStatus status; + hidl_vec modelCache, dataCache; + createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); + createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); + prepareModelFromCache(modelCache, dataCache, &preparedModel, &status); + ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); + ASSERT_EQ(preparedModel, nullptr); + } +} + class CompilationCachingSecurityTest : public CompilationCachingTest, public ::testing::WithParamInterface { protected: From 83ab17f224a908db1cd3947a11d39b6ffcf4b694 Mon Sep 17 00:00:00 2001 From: Xusong Wang Date: Tue, 23 Apr 2019 14:51:50 -0700 Subject: [PATCH 637/718] Test corrupted data cache in CompilationCachingTests. We only expect the driver to not crash. Bug: 123433989 Test: VtsHalNeuralnetworksV1_xTargetTest with 1.2 sample driver Test: VtsHalNeuralnetworksV1_xTargetTest with a test driver that can read and write cache entries Change-Id: Ic9bd7ad6e42d77d505955cb9dda597a39e95cdb6 --- .../functional/CompilationCachingTests.cpp | 163 +++++++++--------- 1 file changed, 82 insertions(+), 81 deletions(-) diff --git a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp index df95ac61b4..3b4acdeff3 100644 --- a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp +++ b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp @@ -1200,34 +1200,15 @@ class CompilationCachingSecurityTest : public CompilationCachingTest, return dis(generator); } - const uint32_t kSeed = GetParam(); - std::mt19937 generator; -}; - -TEST_P(CompilationCachingSecurityTest, CorruptedSecuritySensitiveCache) { - if (!mIsCachingSupported) return; - - // Create test HIDL model and compile. - Model testModel = createTestModel(); - - for (uint32_t i = 0; i < mNumModelCache; i++) { - // Save the compilation to cache. - { - bool supported; - hidl_vec modelCache, dataCache; - createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); - createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); - saveModelToCache(testModel, modelCache, dataCache, &supported); - if (checkEarlyTermination(supported)) return; - } - - // Randomly flip one single bit of the cache entry. - FILE* pFile = fopen(mModelCache[i][0].c_str(), "r+"); + // Randomly flip one single bit of the cache entry. + void flipOneBitOfCache(const std::string& filename, bool* skip) { + FILE* pFile = fopen(filename.c_str(), "r+"); ASSERT_EQ(fseek(pFile, 0, SEEK_END), 0); long int fileSize = ftell(pFile); if (fileSize == 0) { fclose(pFile); - continue; + *skip = true; + return; } ASSERT_EQ(fseek(pFile, getRandomInt(0l, fileSize - 1), SEEK_SET), 0); int readByte = fgetc(pFile); @@ -1235,28 +1216,29 @@ TEST_P(CompilationCachingSecurityTest, CorruptedSecuritySensitiveCache) { ASSERT_EQ(fseek(pFile, -1, SEEK_CUR), 0); ASSERT_NE(fputc(static_cast(readByte) ^ (1U << getRandomInt(0, 7)), pFile), EOF); fclose(pFile); - - // Retrieve preparedModel from cache, expect failure. - { - sp preparedModel = nullptr; - ErrorStatus status; - hidl_vec modelCache, dataCache; - createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); - createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); - prepareModelFromCache(modelCache, dataCache, &preparedModel, &status); - ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); - ASSERT_EQ(preparedModel, nullptr); - } + *skip = false; } -} -TEST_P(CompilationCachingSecurityTest, WrongLengthSecuritySensitiveCache) { - if (!mIsCachingSupported) return; + // Randomly append bytes to the cache entry. + void appendBytesToCache(const std::string& filename, bool* skip) { + FILE* pFile = fopen(filename.c_str(), "a"); + uint32_t appendLength = getRandomInt(1, 256); + for (uint32_t i = 0; i < appendLength; i++) { + ASSERT_NE(fputc(getRandomInt(0, 255), pFile), EOF); + } + fclose(pFile); + *skip = false; + } - // Create test HIDL model and compile. - Model testModel = createTestModel(); + enum class ExpectedResult { GENERAL_FAILURE, NOT_CRASH }; + + // Test if the driver behaves as expected when given corrupted cache or token. + // The modifier will be invoked after save to cache but before prepare from cache. + // The modifier accepts one pointer argument "skip" as the returning value, indicating + // whether the test should be skipped or not. + void testCorruptedCache(ExpectedResult expected, std::function modifier) { + Model testModel = createTestModel(); - for (uint32_t i = 0; i < mNumModelCache; i++) { // Save the compilation to cache. { bool supported; @@ -1267,15 +1249,11 @@ TEST_P(CompilationCachingSecurityTest, WrongLengthSecuritySensitiveCache) { if (checkEarlyTermination(supported)) return; } - // Randomly append bytes to the cache entry. - FILE* pFile = fopen(mModelCache[i][0].c_str(), "a"); - uint32_t appendLength = getRandomInt(1, 256); - for (uint32_t i = 0; i < appendLength; i++) { - ASSERT_NE(fputc(getRandomInt(0, 255), pFile), EOF); - } - fclose(pFile); + bool skip = false; + modifier(&skip); + if (skip) return; - // Retrieve preparedModel from cache, expect failure. + // Retrieve preparedModel from cache. { sp preparedModel = nullptr; ErrorStatus status; @@ -1283,43 +1261,66 @@ TEST_P(CompilationCachingSecurityTest, WrongLengthSecuritySensitiveCache) { createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); prepareModelFromCache(modelCache, dataCache, &preparedModel, &status); - ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); - ASSERT_EQ(preparedModel, nullptr); + + switch (expected) { + case ExpectedResult::GENERAL_FAILURE: + ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); + ASSERT_EQ(preparedModel, nullptr); + break; + case ExpectedResult::NOT_CRASH: + ASSERT_EQ(preparedModel == nullptr, status != ErrorStatus::NONE); + break; + default: + FAIL(); + } } } + + const uint32_t kSeed = GetParam(); + std::mt19937 generator; +}; + +TEST_P(CompilationCachingSecurityTest, CorruptedModelCache) { + if (!mIsCachingSupported) return; + for (uint32_t i = 0; i < mNumModelCache; i++) { + testCorruptedCache(ExpectedResult::GENERAL_FAILURE, + [this, i](bool* skip) { flipOneBitOfCache(mModelCache[i][0], skip); }); + } +} + +TEST_P(CompilationCachingSecurityTest, WrongLengthModelCache) { + if (!mIsCachingSupported) return; + for (uint32_t i = 0; i < mNumModelCache; i++) { + testCorruptedCache(ExpectedResult::GENERAL_FAILURE, + [this, i](bool* skip) { appendBytesToCache(mModelCache[i][0], skip); }); + } +} + +TEST_P(CompilationCachingSecurityTest, CorruptedDataCache) { + if (!mIsCachingSupported) return; + for (uint32_t i = 0; i < mNumDataCache; i++) { + testCorruptedCache(ExpectedResult::NOT_CRASH, + [this, i](bool* skip) { flipOneBitOfCache(mDataCache[i][0], skip); }); + } +} + +TEST_P(CompilationCachingSecurityTest, WrongLengthDataCache) { + if (!mIsCachingSupported) return; + for (uint32_t i = 0; i < mNumDataCache; i++) { + testCorruptedCache(ExpectedResult::NOT_CRASH, + [this, i](bool* skip) { appendBytesToCache(mDataCache[i][0], skip); }); + } } TEST_P(CompilationCachingSecurityTest, WrongToken) { if (!mIsCachingSupported) return; - - // Create test HIDL model and compile. - Model testModel = createTestModel(); - - // Save the compilation to cache. - { - bool supported; - hidl_vec modelCache, dataCache; - createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); - createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); - saveModelToCache(testModel, modelCache, dataCache, &supported); - if (checkEarlyTermination(supported)) return; - } - - // Randomly flip one single bit in mToken. - uint32_t ind = getRandomInt(0u, static_cast(Constant::BYTE_SIZE_OF_CACHE_TOKEN) - 1); - mToken[ind] ^= (1U << getRandomInt(0, 7)); - - // Retrieve the preparedModel from cache, expect failure. - { - sp preparedModel = nullptr; - ErrorStatus status; - hidl_vec modelCache, dataCache; - createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); - createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); - prepareModelFromCache(modelCache, dataCache, &preparedModel, &status); - ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE); - ASSERT_EQ(preparedModel, nullptr); - } + testCorruptedCache(ExpectedResult::GENERAL_FAILURE, [this](bool* skip) { + // Randomly flip one single bit in mToken. + uint32_t ind = + getRandomInt(0u, static_cast(Constant::BYTE_SIZE_OF_CACHE_TOKEN) - 1); + mToken[ind] ^= (1U << getRandomInt(0, 7)); + *skip = false; + }); } INSTANTIATE_TEST_CASE_P(TestCompilationCaching, CompilationCachingSecurityTest, From f8c5987bbd8f747a6ecc0c349128eb7d4d57e11d Mon Sep 17 00:00:00 2001 From: Xusong Wang Date: Fri, 26 Apr 2019 15:33:38 -0700 Subject: [PATCH 638/718] Move getSupportedOperations out of saveToCache. Before this change, getSupportedOperations_1_2 was invoked in saveModelToCache prior to prepareModel_1_2, which delayed the model preparation and cache overwriting always ran faster in SaveToCache_TOCTOU test. This change increases the chance that the model is overwritten after it is saved in SaveToCache_TOCTOU test by moving getSupportedOperations_1_2 out of saveToCache. Bug: 123433989 Test: VtsHalNeuralnetworksV1_xTargetTest with 1.2 sample driver Test: VtsHalNeuralnetworksV1_xTargetTest with a test driver that can read and write cache entries Test: TOCTOU tests with a sample driver that is deliberately broken Change-Id: Ieba6a82252623ac429d5fcb6950b99db949f9886 --- .../functional/CompilationCachingTests.cpp | 162 ++++++++---------- 1 file changed, 70 insertions(+), 92 deletions(-) diff --git a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp index 3b4acdeff3..bf915603bc 100644 --- a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp +++ b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp @@ -263,12 +263,8 @@ class CompilationCachingTest : public NeuralnetworksHidlTest { NeuralnetworksHidlTest::TearDown(); } - void saveModelToCache(const V1_2::Model& model, const hidl_vec& modelCache, - const hidl_vec& dataCache, bool* supported, - sp* preparedModel = nullptr) { - if (preparedModel != nullptr) *preparedModel = nullptr; - - // See if service can handle model. + // See if the service can handle the model. + bool isModelFullySupported(const V1_2::Model& model) { bool fullySupportsModel = false; Return supportedCall = device->getSupportedOperations_1_2( model, @@ -278,9 +274,14 @@ class CompilationCachingTest : public NeuralnetworksHidlTest { fullySupportsModel = std::all_of(supported.begin(), supported.end(), [](bool valid) { return valid; }); }); - ASSERT_TRUE(supportedCall.isOk()); - *supported = fullySupportsModel; - if (!fullySupportsModel) return; + EXPECT_TRUE(supportedCall.isOk()); + return fullySupportsModel; + } + + void saveModelToCache(const V1_2::Model& model, const hidl_vec& modelCache, + const hidl_vec& dataCache, + sp* preparedModel = nullptr) { + if (preparedModel != nullptr) *preparedModel = nullptr; // Launch prepare model. sp preparedModelCallback = new PreparedModelCallback(); @@ -314,8 +315,8 @@ class CompilationCachingTest : public NeuralnetworksHidlTest { return false; } - bool checkEarlyTermination(bool supported) { - if (!supported) { + bool checkEarlyTermination(const V1_2::Model& model) { + if (!isModelFullySupported(model)) { LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot " "prepare model that it does not support."; std::cout << "[ ] Early termination of test because vendor service cannot " @@ -369,17 +370,16 @@ class CompilationCachingTest : public NeuralnetworksHidlTest { TEST_F(CompilationCachingTest, CacheSavingAndRetrieval) { // Create test HIDL model and compile. - Model testModel = createTestModel(); + const Model testModel = createTestModel(); + if (checkEarlyTermination(testModel)) return; sp preparedModel = nullptr; // Save the compilation to cache. { - bool supported; hidl_vec modelCache, dataCache; createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); - saveModelToCache(testModel, modelCache, dataCache, &supported); - if (checkEarlyTermination(supported)) return; + saveModelToCache(testModel, modelCache, dataCache); } // Retrieve preparedModel from cache. @@ -411,12 +411,12 @@ TEST_F(CompilationCachingTest, CacheSavingAndRetrieval) { TEST_F(CompilationCachingTest, CacheSavingAndRetrievalNonZeroOffset) { // Create test HIDL model and compile. - Model testModel = createTestModel(); + const Model testModel = createTestModel(); + if (checkEarlyTermination(testModel)) return; sp preparedModel = nullptr; // Save the compilation to cache. { - bool supported; hidl_vec modelCache, dataCache; createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); @@ -433,8 +433,7 @@ TEST_F(CompilationCachingTest, CacheSavingAndRetrievalNonZeroOffset) { write(dataCache[i].getNativeHandle()->data[0], &dummyBytes, sizeof(dummyBytes)), sizeof(dummyBytes)); } - saveModelToCache(testModel, modelCache, dataCache, &supported); - if (checkEarlyTermination(supported)) return; + saveModelToCache(testModel, modelCache, dataCache); } // Retrieve preparedModel from cache. @@ -475,11 +474,11 @@ TEST_F(CompilationCachingTest, CacheSavingAndRetrievalNonZeroOffset) { TEST_F(CompilationCachingTest, SaveToCacheInvalidNumCache) { // Create test HIDL model and compile. - Model testModel = createTestModel(); + const Model testModel = createTestModel(); + if (checkEarlyTermination(testModel)) return; // Test with number of model cache files greater than mNumModelCache. { - bool supported; hidl_vec modelCache, dataCache; // Pass an additional cache file for model cache. mModelCache.push_back({mTmpCache}); @@ -487,8 +486,7 @@ TEST_F(CompilationCachingTest, SaveToCacheInvalidNumCache) { createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); mModelCache.pop_back(); sp preparedModel = nullptr; - saveModelToCache(testModel, modelCache, dataCache, &supported, &preparedModel); - if (checkEarlyTermination(supported)) return; + saveModelToCache(testModel, modelCache, dataCache, &preparedModel); ASSERT_NE(preparedModel, nullptr); // Execute and verify results. generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; }, @@ -507,7 +505,6 @@ TEST_F(CompilationCachingTest, SaveToCacheInvalidNumCache) { // Test with number of model cache files smaller than mNumModelCache. if (mModelCache.size() > 0) { - bool supported; hidl_vec modelCache, dataCache; // Pop out the last cache file. auto tmp = mModelCache.back(); @@ -516,8 +513,7 @@ TEST_F(CompilationCachingTest, SaveToCacheInvalidNumCache) { createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); mModelCache.push_back(tmp); sp preparedModel = nullptr; - saveModelToCache(testModel, modelCache, dataCache, &supported, &preparedModel); - if (checkEarlyTermination(supported)) return; + saveModelToCache(testModel, modelCache, dataCache, &preparedModel); ASSERT_NE(preparedModel, nullptr); // Execute and verify results. generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; }, @@ -536,7 +532,6 @@ TEST_F(CompilationCachingTest, SaveToCacheInvalidNumCache) { // Test with number of data cache files greater than mNumDataCache. { - bool supported; hidl_vec modelCache, dataCache; // Pass an additional cache file for data cache. mDataCache.push_back({mTmpCache}); @@ -544,8 +539,7 @@ TEST_F(CompilationCachingTest, SaveToCacheInvalidNumCache) { createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); mDataCache.pop_back(); sp preparedModel = nullptr; - saveModelToCache(testModel, modelCache, dataCache, &supported, &preparedModel); - if (checkEarlyTermination(supported)) return; + saveModelToCache(testModel, modelCache, dataCache, &preparedModel); ASSERT_NE(preparedModel, nullptr); // Execute and verify results. generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; }, @@ -564,7 +558,6 @@ TEST_F(CompilationCachingTest, SaveToCacheInvalidNumCache) { // Test with number of data cache files smaller than mNumDataCache. if (mDataCache.size() > 0) { - bool supported; hidl_vec modelCache, dataCache; // Pop out the last cache file. auto tmp = mDataCache.back(); @@ -573,8 +566,7 @@ TEST_F(CompilationCachingTest, SaveToCacheInvalidNumCache) { createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); mDataCache.push_back(tmp); sp preparedModel = nullptr; - saveModelToCache(testModel, modelCache, dataCache, &supported, &preparedModel); - if (checkEarlyTermination(supported)) return; + saveModelToCache(testModel, modelCache, dataCache, &preparedModel); ASSERT_NE(preparedModel, nullptr); // Execute and verify results. generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; }, @@ -594,16 +586,15 @@ TEST_F(CompilationCachingTest, SaveToCacheInvalidNumCache) { TEST_F(CompilationCachingTest, PrepareModelFromCacheInvalidNumCache) { // Create test HIDL model and compile. - Model testModel = createTestModel(); + const Model testModel = createTestModel(); + if (checkEarlyTermination(testModel)) return; // Save the compilation to cache. { - bool supported; hidl_vec modelCache, dataCache; createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); - saveModelToCache(testModel, modelCache, dataCache, &supported); - if (checkEarlyTermination(supported)) return; + saveModelToCache(testModel, modelCache, dataCache); } // Test with number of model cache files greater than mNumModelCache. @@ -675,11 +666,11 @@ TEST_F(CompilationCachingTest, PrepareModelFromCacheInvalidNumCache) { TEST_F(CompilationCachingTest, SaveToCacheInvalidNumFd) { // Create test HIDL model and compile. - Model testModel = createTestModel(); + const Model testModel = createTestModel(); + if (checkEarlyTermination(testModel)) return; // Go through each handle in model cache, test with NumFd greater than 1. for (uint32_t i = 0; i < mNumModelCache; i++) { - bool supported; hidl_vec modelCache, dataCache; // Pass an invalid number of fds for handle i. mModelCache[i].push_back(mTmpCache); @@ -687,8 +678,7 @@ TEST_F(CompilationCachingTest, SaveToCacheInvalidNumFd) { createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); mModelCache[i].pop_back(); sp preparedModel = nullptr; - saveModelToCache(testModel, modelCache, dataCache, &supported, &preparedModel); - if (checkEarlyTermination(supported)) return; + saveModelToCache(testModel, modelCache, dataCache, &preparedModel); ASSERT_NE(preparedModel, nullptr); // Execute and verify results. generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; }, @@ -707,7 +697,6 @@ TEST_F(CompilationCachingTest, SaveToCacheInvalidNumFd) { // Go through each handle in model cache, test with NumFd equal to 0. for (uint32_t i = 0; i < mNumModelCache; i++) { - bool supported; hidl_vec modelCache, dataCache; // Pass an invalid number of fds for handle i. auto tmp = mModelCache[i].back(); @@ -716,8 +705,7 @@ TEST_F(CompilationCachingTest, SaveToCacheInvalidNumFd) { createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); mModelCache[i].push_back(tmp); sp preparedModel = nullptr; - saveModelToCache(testModel, modelCache, dataCache, &supported, &preparedModel); - if (checkEarlyTermination(supported)) return; + saveModelToCache(testModel, modelCache, dataCache, &preparedModel); ASSERT_NE(preparedModel, nullptr); // Execute and verify results. generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; }, @@ -736,7 +724,6 @@ TEST_F(CompilationCachingTest, SaveToCacheInvalidNumFd) { // Go through each handle in data cache, test with NumFd greater than 1. for (uint32_t i = 0; i < mNumDataCache; i++) { - bool supported; hidl_vec modelCache, dataCache; // Pass an invalid number of fds for handle i. mDataCache[i].push_back(mTmpCache); @@ -744,8 +731,7 @@ TEST_F(CompilationCachingTest, SaveToCacheInvalidNumFd) { createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); mDataCache[i].pop_back(); sp preparedModel = nullptr; - saveModelToCache(testModel, modelCache, dataCache, &supported, &preparedModel); - if (checkEarlyTermination(supported)) return; + saveModelToCache(testModel, modelCache, dataCache, &preparedModel); ASSERT_NE(preparedModel, nullptr); // Execute and verify results. generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; }, @@ -764,7 +750,6 @@ TEST_F(CompilationCachingTest, SaveToCacheInvalidNumFd) { // Go through each handle in data cache, test with NumFd equal to 0. for (uint32_t i = 0; i < mNumDataCache; i++) { - bool supported; hidl_vec modelCache, dataCache; // Pass an invalid number of fds for handle i. auto tmp = mDataCache[i].back(); @@ -773,8 +758,7 @@ TEST_F(CompilationCachingTest, SaveToCacheInvalidNumFd) { createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); mDataCache[i].push_back(tmp); sp preparedModel = nullptr; - saveModelToCache(testModel, modelCache, dataCache, &supported, &preparedModel); - if (checkEarlyTermination(supported)) return; + saveModelToCache(testModel, modelCache, dataCache, &preparedModel); ASSERT_NE(preparedModel, nullptr); // Execute and verify results. generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; }, @@ -794,16 +778,15 @@ TEST_F(CompilationCachingTest, SaveToCacheInvalidNumFd) { TEST_F(CompilationCachingTest, PrepareModelFromCacheInvalidNumFd) { // Create test HIDL model and compile. - Model testModel = createTestModel(); + const Model testModel = createTestModel(); + if (checkEarlyTermination(testModel)) return; // Save the compilation to cache. { - bool supported; hidl_vec modelCache, dataCache; createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); - saveModelToCache(testModel, modelCache, dataCache, &supported); - if (checkEarlyTermination(supported)) return; + saveModelToCache(testModel, modelCache, dataCache); } // Go through each handle in model cache, test with NumFd greater than 1. @@ -875,21 +858,20 @@ TEST_F(CompilationCachingTest, PrepareModelFromCacheInvalidNumFd) { TEST_F(CompilationCachingTest, SaveToCacheInvalidAccessMode) { // Create test HIDL model and compile. - Model testModel = createTestModel(); + const Model testModel = createTestModel(); + if (checkEarlyTermination(testModel)) return; std::vector modelCacheMode(mNumModelCache, AccessMode::READ_WRITE); std::vector dataCacheMode(mNumDataCache, AccessMode::READ_WRITE); // Go through each handle in model cache, test with invalid access mode. for (uint32_t i = 0; i < mNumModelCache; i++) { - bool supported; hidl_vec modelCache, dataCache; modelCacheMode[i] = AccessMode::READ_ONLY; createCacheHandles(mModelCache, modelCacheMode, &modelCache); createCacheHandles(mDataCache, dataCacheMode, &dataCache); modelCacheMode[i] = AccessMode::READ_WRITE; sp preparedModel = nullptr; - saveModelToCache(testModel, modelCache, dataCache, &supported, &preparedModel); - if (checkEarlyTermination(supported)) return; + saveModelToCache(testModel, modelCache, dataCache, &preparedModel); ASSERT_NE(preparedModel, nullptr); // Execute and verify results. generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; }, @@ -908,15 +890,13 @@ TEST_F(CompilationCachingTest, SaveToCacheInvalidAccessMode) { // Go through each handle in data cache, test with invalid access mode. for (uint32_t i = 0; i < mNumDataCache; i++) { - bool supported; hidl_vec modelCache, dataCache; dataCacheMode[i] = AccessMode::READ_ONLY; createCacheHandles(mModelCache, modelCacheMode, &modelCache); createCacheHandles(mDataCache, dataCacheMode, &dataCache); dataCacheMode[i] = AccessMode::READ_WRITE; sp preparedModel = nullptr; - saveModelToCache(testModel, modelCache, dataCache, &supported, &preparedModel); - if (checkEarlyTermination(supported)) return; + saveModelToCache(testModel, modelCache, dataCache, &preparedModel); ASSERT_NE(preparedModel, nullptr); // Execute and verify results. generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; }, @@ -936,18 +916,17 @@ TEST_F(CompilationCachingTest, SaveToCacheInvalidAccessMode) { TEST_F(CompilationCachingTest, PrepareModelFromCacheInvalidAccessMode) { // Create test HIDL model and compile. - Model testModel = createTestModel(); + const Model testModel = createTestModel(); + if (checkEarlyTermination(testModel)) return; std::vector modelCacheMode(mNumModelCache, AccessMode::READ_WRITE); std::vector dataCacheMode(mNumDataCache, AccessMode::READ_WRITE); // Save the compilation to cache. { - bool supported; hidl_vec modelCache, dataCache; createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); - saveModelToCache(testModel, modelCache, dataCache, &supported); - if (checkEarlyTermination(supported)) return; + saveModelToCache(testModel, modelCache, dataCache); } // Go through each handle in model cache, test with invalid access mode. @@ -1014,8 +993,13 @@ constexpr uint32_t kNumIterationsTOCTOU = 100; TEST_F(CompilationCachingTest, SaveToCache_TOCTOU) { if (!mIsCachingSupported) return; + // Create test models and check if fully supported by the service. + const Model testModelMul = createLargeTestModel(OperationType::MUL, kLargeModelSize); + if (checkEarlyTermination(testModelMul)) return; + const Model testModelAdd = createLargeTestModel(OperationType::ADD, kLargeModelSize); + if (checkEarlyTermination(testModelAdd)) return; + // Save the testModelMul compilation to cache. - Model testModelMul = createLargeTestModel(OperationType::MUL, kLargeModelSize); auto modelCacheMul = mModelCache; for (auto& cache : modelCacheMul) { cache[0].append("_mul"); @@ -1024,29 +1008,24 @@ TEST_F(CompilationCachingTest, SaveToCache_TOCTOU) { hidl_vec modelCache, dataCache; createCacheHandles(modelCacheMul, AccessMode::READ_WRITE, &modelCache); createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); - bool supported; - saveModelToCache(testModelMul, modelCache, dataCache, &supported); - if (checkEarlyTermination(supported)) return; + saveModelToCache(testModelMul, modelCache, dataCache); } // Use a different token for testModelAdd. mToken[0]++; // This test is probabilistic, so we run it multiple times. - Model testModelAdd = createLargeTestModel(OperationType::ADD, kLargeModelSize); for (uint32_t i = 0; i < kNumIterationsTOCTOU; i++) { // Save the testModelAdd compilation to cache. { - bool supported; hidl_vec modelCache, dataCache; createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); // Spawn a thread to copy the cache content concurrently while saving to cache. std::thread thread(copyCacheFiles, std::cref(modelCacheMul), std::cref(mModelCache)); - saveModelToCache(testModelAdd, modelCache, dataCache, &supported); + saveModelToCache(testModelAdd, modelCache, dataCache); thread.join(); - if (checkEarlyTermination(supported)) return; } // Retrieve preparedModel from cache. @@ -1077,8 +1056,13 @@ TEST_F(CompilationCachingTest, SaveToCache_TOCTOU) { TEST_F(CompilationCachingTest, PrepareFromCache_TOCTOU) { if (!mIsCachingSupported) return; + // Create test models and check if fully supported by the service. + const Model testModelMul = createLargeTestModel(OperationType::MUL, kLargeModelSize); + if (checkEarlyTermination(testModelMul)) return; + const Model testModelAdd = createLargeTestModel(OperationType::ADD, kLargeModelSize); + if (checkEarlyTermination(testModelAdd)) return; + // Save the testModelMul compilation to cache. - Model testModelMul = createLargeTestModel(OperationType::MUL, kLargeModelSize); auto modelCacheMul = mModelCache; for (auto& cache : modelCacheMul) { cache[0].append("_mul"); @@ -1087,25 +1071,20 @@ TEST_F(CompilationCachingTest, PrepareFromCache_TOCTOU) { hidl_vec modelCache, dataCache; createCacheHandles(modelCacheMul, AccessMode::READ_WRITE, &modelCache); createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); - bool supported; - saveModelToCache(testModelMul, modelCache, dataCache, &supported); - if (checkEarlyTermination(supported)) return; + saveModelToCache(testModelMul, modelCache, dataCache); } // Use a different token for testModelAdd. mToken[0]++; // This test is probabilistic, so we run it multiple times. - Model testModelAdd = createLargeTestModel(OperationType::ADD, kLargeModelSize); for (uint32_t i = 0; i < kNumIterationsTOCTOU; i++) { // Save the testModelAdd compilation to cache. { - bool supported; hidl_vec modelCache, dataCache; createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); - saveModelToCache(testModelAdd, modelCache, dataCache, &supported); - if (checkEarlyTermination(supported)) return; + saveModelToCache(testModelAdd, modelCache, dataCache); } // Retrieve preparedModel from cache. @@ -1140,8 +1119,13 @@ TEST_F(CompilationCachingTest, PrepareFromCache_TOCTOU) { TEST_F(CompilationCachingTest, ReplaceSecuritySensitiveCache) { if (!mIsCachingSupported) return; + // Create test models and check if fully supported by the service. + const Model testModelMul = createLargeTestModel(OperationType::MUL, kLargeModelSize); + if (checkEarlyTermination(testModelMul)) return; + const Model testModelAdd = createLargeTestModel(OperationType::ADD, kLargeModelSize); + if (checkEarlyTermination(testModelAdd)) return; + // Save the testModelMul compilation to cache. - Model testModelMul = createLargeTestModel(OperationType::MUL, kLargeModelSize); auto modelCacheMul = mModelCache; for (auto& cache : modelCacheMul) { cache[0].append("_mul"); @@ -1150,23 +1134,18 @@ TEST_F(CompilationCachingTest, ReplaceSecuritySensitiveCache) { hidl_vec modelCache, dataCache; createCacheHandles(modelCacheMul, AccessMode::READ_WRITE, &modelCache); createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); - bool supported; - saveModelToCache(testModelMul, modelCache, dataCache, &supported); - if (checkEarlyTermination(supported)) return; + saveModelToCache(testModelMul, modelCache, dataCache); } // Use a different token for testModelAdd. mToken[0]++; // Save the testModelAdd compilation to cache. - Model testModelAdd = createLargeTestModel(OperationType::ADD, kLargeModelSize); { - bool supported; hidl_vec modelCache, dataCache; createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); - saveModelToCache(testModelAdd, modelCache, dataCache, &supported); - if (checkEarlyTermination(supported)) return; + saveModelToCache(testModelAdd, modelCache, dataCache); } // Replace the model cache of testModelAdd with testModelMul. @@ -1237,16 +1216,15 @@ class CompilationCachingSecurityTest : public CompilationCachingTest, // The modifier accepts one pointer argument "skip" as the returning value, indicating // whether the test should be skipped or not. void testCorruptedCache(ExpectedResult expected, std::function modifier) { - Model testModel = createTestModel(); + const Model testModel = createTestModel(); + if (checkEarlyTermination(testModel)) return; // Save the compilation to cache. { - bool supported; hidl_vec modelCache, dataCache; createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache); createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache); - saveModelToCache(testModel, modelCache, dataCache, &supported); - if (checkEarlyTermination(supported)) return; + saveModelToCache(testModel, modelCache, dataCache); } bool skip = false; From 098720bc2cd9925d13a712d23ffcd747bf8cab52 Mon Sep 17 00:00:00 2001 From: Shuzhen Wang Date: Tue, 23 Apr 2019 09:44:54 -0700 Subject: [PATCH 639/718] Camera: Allow out-of-order ZSL shutter notify - Allow shutter notifies of zero-shutter-lag requests with STILL_CAPTURE intent to be out of order compared to other kinds of requests. - Shutter notifies of same kind of requests must be in order. Test: BurstJpegCapture CTS test Bug: 120604717 Change-Id: Ia31f0d17322cb9b850614413feb1134e16d69552 --- camera/device/3.2/ICameraDeviceCallback.hal | 15 +++++++++++++++ current.txt | 1 + 2 files changed, 16 insertions(+) diff --git a/camera/device/3.2/ICameraDeviceCallback.hal b/camera/device/3.2/ICameraDeviceCallback.hal index 69715dec64..dec3bd88c6 100644 --- a/camera/device/3.2/ICameraDeviceCallback.hal +++ b/camera/device/3.2/ICameraDeviceCallback.hal @@ -125,6 +125,21 @@ interface ICameraDeviceCallback { * via a SHUTTER notify() call. It is highly recommended to dispatch this * call as early as possible. * + * The SHUTTER notify calls for requests with android.control.enableZsl + * set to TRUE and ANDROID_CONTROL_CAPTURE_INTENT == STILL_CAPTURE may be + * out-of-order compared to SHUTTER notify for other kinds of requests + * (including regular, reprocess, or zero-shutter-lag requests with + * different capture intents). + * + * As a result, the capture results of zero-shutter-lag requests with + * ANDROID_CONTROL_CAPTURE_INTENT == STILL_CAPTURE may be out-of-order + * compared to capture results for other kinds of requests. + * + * Different SHUTTER notify calls for zero-shutter-lag requests with + * ANDROID_CONTROL_CAPTURE_INTENT == STILL_CAPTURE must be in order between + * them, as is for other kinds of requests. SHUTTER notify calls for + * zero-shutter-lag requests with non STILL_CAPTURE intent must be in order + * with SHUTTER notify calls for regular requests. * ------------------------------------------------------------------------ * Performance requirements: * diff --git a/current.txt b/current.txt index 3a6241c285..cd51ff50ff 100644 --- a/current.txt +++ b/current.txt @@ -386,6 +386,7 @@ cd4330c3196bda1d642a32abfe23a7d64ebfbda721940643af6867af3b3f0aa9 android.hardwar # ABI preserving changes to HALs during Android Q 2a55e224aa9bc62c0387cd85ad3c97e33f0c33a4e1489cbae86b2523e6f9df35 android.hardware.camera.device@3.2::ICameraDevice +17e878cb11ea602c08af04a09182e6265498be16edf26605058383b9a7628261 android.hardware.camera.device@3.2::ICameraDeviceCallback 8caf9104dc6885852c0b117d853dd93f6d4b61a0a365138295eb8bcd41b36423 android.hardware.camera.device@3.2::ICameraDeviceSession 684702a60deef03a1e8093961dc0a18c555c857ad5a77ba7340b0635ae01eb70 android.hardware.camera.device@3.4::ICameraDeviceSession f8a19622cb0cc890913b1ef3e32b675ffb26089a09e02fef4056ebad324d2b5d android.hardware.camera.device@3.4::types From 20f28a24e908d54f4708ad17943154fb61a4c770 Mon Sep 17 00:00:00 2001 From: Michael Butler Date: Fri, 26 Apr 2019 17:46:08 -0700 Subject: [PATCH 640/718] Add validation tests for NNAPI Burst serialized format This CL adds the following two types of validation tests on the NNAPI Burst serialized format: (1) it directly modifies the serialized data (invalidating it) to ensure that vendor driver services properly validates the serialized request (2) it ensures that vendor driver services properly fail when the result channel is not large enough to return the data This CL additionally includes miscellaneous cleanups: (1) having a generic "validateEverything" function (2) moving the "prepareModel" function that's common across validateRequest and validateBurst to a common area Fixes: 129779280 Bug: 129157135 Test: mma Test: VtsHalNeuralnetworksV1_2TargetTest (with sample-all) Change-Id: Ib90fe7f662824de17db5a254a8c501855e45f6bd --- .../vts/functional/VtsHalNeuralnetworks.cpp | 5 + .../1.0/vts/functional/VtsHalNeuralnetworks.h | 7 +- .../vts/functional/VtsHalNeuralnetworks.cpp | 5 + .../1.1/vts/functional/VtsHalNeuralnetworks.h | 7 +- neuralnetworks/1.2/vts/functional/Android.bp | 4 + .../1.2/vts/functional/ValidateBurst.cpp | 333 ++++++++++++++++++ .../1.2/vts/functional/ValidateRequest.cpp | 61 +--- .../vts/functional/VtsHalNeuralnetworks.cpp | 73 ++++ .../1.2/vts/functional/VtsHalNeuralnetworks.h | 10 +- 9 files changed, 440 insertions(+), 65 deletions(-) create mode 100644 neuralnetworks/1.2/vts/functional/ValidateBurst.cpp diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp index 88830574da..31638c425f 100644 --- a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp +++ b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp @@ -68,6 +68,11 @@ void NeuralnetworksHidlTest::TearDown() { ::testing::VtsHalHidlTargetTestBase::TearDown(); } +void ValidationTest::validateEverything(const Model& model, const std::vector& request) { + validateModel(model); + validateRequests(model, request); +} + } // namespace functional } // namespace vts } // namespace V1_0 diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h index d4c114d3a2..559d678ea1 100644 --- a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h +++ b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h @@ -63,8 +63,11 @@ class NeuralnetworksHidlTest : public ::testing::VtsHalHidlTargetTestBase { // Tag for the validation tests class ValidationTest : public NeuralnetworksHidlTest { protected: - void validateModel(const Model& model); - void validateRequests(const Model& model, const std::vector& request); + void validateEverything(const Model& model, const std::vector& request); + + private: + void validateModel(const Model& model); + void validateRequests(const Model& model, const std::vector& request); }; // Tag for the generated tests diff --git a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp index 224a51d149..11fa693ddc 100644 --- a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp +++ b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp @@ -68,6 +68,11 @@ void NeuralnetworksHidlTest::TearDown() { ::testing::VtsHalHidlTargetTestBase::TearDown(); } +void ValidationTest::validateEverything(const Model& model, const std::vector& request) { + validateModel(model); + validateRequests(model, request); +} + } // namespace functional } // namespace vts } // namespace V1_1 diff --git a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h index 1c8c0e18cb..cea2b54c2d 100644 --- a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h +++ b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h @@ -72,8 +72,11 @@ class NeuralnetworksHidlTest : public ::testing::VtsHalHidlTargetTestBase { // Tag for the validation tests class ValidationTest : public NeuralnetworksHidlTest { protected: - void validateModel(const Model& model); - void validateRequests(const Model& model, const std::vector& request); + void validateEverything(const Model& model, const std::vector& request); + + private: + void validateModel(const Model& model); + void validateRequests(const Model& model, const std::vector& request); }; // Tag for the generated tests diff --git a/neuralnetworks/1.2/vts/functional/Android.bp b/neuralnetworks/1.2/vts/functional/Android.bp index 891b414480..6c26820b27 100644 --- a/neuralnetworks/1.2/vts/functional/Android.bp +++ b/neuralnetworks/1.2/vts/functional/Android.bp @@ -20,6 +20,7 @@ cc_test { defaults: ["VtsHalNeuralNetworksTargetTestDefaults"], srcs: [ "GeneratedTestsV1_0.cpp", + "ValidateBurst.cpp", ], cflags: [ "-DNN_TEST_DYNAMIC_OUTPUT_SHAPE" @@ -32,6 +33,7 @@ cc_test { defaults: ["VtsHalNeuralNetworksTargetTestDefaults"], srcs: [ "GeneratedTestsV1_1.cpp", + "ValidateBurst.cpp", ], cflags: [ "-DNN_TEST_DYNAMIC_OUTPUT_SHAPE" @@ -46,6 +48,7 @@ cc_test { "BasicTests.cpp", "CompilationCachingTests.cpp", "GeneratedTests.cpp", + "ValidateBurst.cpp", ], cflags: [ "-DNN_TEST_DYNAMIC_OUTPUT_SHAPE" @@ -58,6 +61,7 @@ cc_test { srcs: [ "BasicTests.cpp", "GeneratedTests.cpp", + "ValidateBurst.cpp", ], cflags: [ "-DNN_TEST_DYNAMIC_OUTPUT_SHAPE", diff --git a/neuralnetworks/1.2/vts/functional/ValidateBurst.cpp b/neuralnetworks/1.2/vts/functional/ValidateBurst.cpp new file mode 100644 index 0000000000..386c141f80 --- /dev/null +++ b/neuralnetworks/1.2/vts/functional/ValidateBurst.cpp @@ -0,0 +1,333 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "neuralnetworks_hidl_hal_test" + +#include "VtsHalNeuralnetworks.h" + +#include "Callbacks.h" +#include "ExecutionBurstController.h" +#include "ExecutionBurstServer.h" +#include "TestHarness.h" +#include "Utils.h" + +#include + +namespace android { +namespace hardware { +namespace neuralnetworks { +namespace V1_2 { +namespace vts { +namespace functional { + +using ::android::nn::ExecutionBurstController; +using ::android::nn::RequestChannelSender; +using ::android::nn::ResultChannelReceiver; +using ExecutionBurstCallback = ::android::nn::ExecutionBurstController::ExecutionBurstCallback; + +constexpr size_t kExecutionBurstChannelLength = 1024; +constexpr size_t kExecutionBurstChannelSmallLength = 8; + +///////////////////////// UTILITY FUNCTIONS ///////////////////////// + +static bool badTiming(Timing timing) { + return timing.timeOnDevice == UINT64_MAX && timing.timeInDriver == UINT64_MAX; +} + +static void createBurst(const sp& preparedModel, const sp& callback, + std::unique_ptr* sender, + std::unique_ptr* receiver, + sp* context) { + ASSERT_NE(nullptr, preparedModel.get()); + ASSERT_NE(nullptr, sender); + ASSERT_NE(nullptr, receiver); + ASSERT_NE(nullptr, context); + + // create FMQ objects + auto [fmqRequestChannel, fmqRequestDescriptor] = + RequestChannelSender::create(kExecutionBurstChannelLength, /*blocking=*/true); + auto [fmqResultChannel, fmqResultDescriptor] = + ResultChannelReceiver::create(kExecutionBurstChannelLength, /*blocking=*/true); + ASSERT_NE(nullptr, fmqRequestChannel.get()); + ASSERT_NE(nullptr, fmqResultChannel.get()); + ASSERT_NE(nullptr, fmqRequestDescriptor); + ASSERT_NE(nullptr, fmqResultDescriptor); + + // configure burst + ErrorStatus errorStatus; + sp burstContext; + const Return ret = preparedModel->configureExecutionBurst( + callback, *fmqRequestDescriptor, *fmqResultDescriptor, + [&errorStatus, &burstContext](ErrorStatus status, const sp& context) { + errorStatus = status; + burstContext = context; + }); + ASSERT_TRUE(ret.isOk()); + ASSERT_EQ(ErrorStatus::NONE, errorStatus); + ASSERT_NE(nullptr, burstContext.get()); + + // return values + *sender = std::move(fmqRequestChannel); + *receiver = std::move(fmqResultChannel); + *context = burstContext; +} + +static void createBurstWithResultChannelLength( + const sp& preparedModel, + std::shared_ptr* controller, size_t resultChannelLength) { + ASSERT_NE(nullptr, preparedModel.get()); + ASSERT_NE(nullptr, controller); + + // create FMQ objects + auto [fmqRequestChannel, fmqRequestDescriptor] = + RequestChannelSender::create(kExecutionBurstChannelLength, /*blocking=*/true); + auto [fmqResultChannel, fmqResultDescriptor] = + ResultChannelReceiver::create(resultChannelLength, /*blocking=*/true); + ASSERT_NE(nullptr, fmqRequestChannel.get()); + ASSERT_NE(nullptr, fmqResultChannel.get()); + ASSERT_NE(nullptr, fmqRequestDescriptor); + ASSERT_NE(nullptr, fmqResultDescriptor); + + // configure burst + sp callback = new ExecutionBurstCallback(); + ErrorStatus errorStatus; + sp burstContext; + const Return ret = preparedModel->configureExecutionBurst( + callback, *fmqRequestDescriptor, *fmqResultDescriptor, + [&errorStatus, &burstContext](ErrorStatus status, const sp& context) { + errorStatus = status; + burstContext = context; + }); + ASSERT_TRUE(ret.isOk()); + ASSERT_EQ(ErrorStatus::NONE, errorStatus); + ASSERT_NE(nullptr, burstContext.get()); + + // return values + *controller = std::make_shared( + std::move(fmqRequestChannel), std::move(fmqResultChannel), burstContext, callback); +} + +// Primary validation function. This function will take a valid serialized +// request, apply a mutation to it to invalidate the serialized request, then +// pass it to interface calls that use the serialized request. Note that the +// serialized request here is passed by value, and any mutation to the +// serialized request does not leave this function. +static void validate(RequestChannelSender* sender, ResultChannelReceiver* receiver, + const std::string& message, std::vector serialized, + const std::function*)>& mutation) { + mutation(&serialized); + + // skip if packet is too large to send + if (serialized.size() > kExecutionBurstChannelLength) { + return; + } + + SCOPED_TRACE(message); + + // send invalid packet + sender->sendPacket(serialized); + + // receive error + auto results = receiver->getBlocking(); + ASSERT_TRUE(results.has_value()); + const auto [status, outputShapes, timing] = std::move(*results); + EXPECT_NE(ErrorStatus::NONE, status); + EXPECT_EQ(0u, outputShapes.size()); + EXPECT_TRUE(badTiming(timing)); +} + +static std::vector createUniqueDatum() { + const FmqRequestDatum::PacketInformation packetInformation = { + /*.packetSize=*/10, /*.numberOfInputOperands=*/10, /*.numberOfOutputOperands=*/10, + /*.numberOfPools=*/10}; + const FmqRequestDatum::OperandInformation operandInformation = { + /*.hasNoValue=*/false, /*.location=*/{}, /*.numberOfDimensions=*/10}; + const int32_t invalidPoolIdentifier = std::numeric_limits::max(); + std::vector unique(7); + unique[0].packetInformation(packetInformation); + unique[1].inputOperandInformation(operandInformation); + unique[2].inputOperandDimensionValue(0); + unique[3].outputOperandInformation(operandInformation); + unique[4].outputOperandDimensionValue(0); + unique[5].poolIdentifier(invalidPoolIdentifier); + unique[6].measureTiming(MeasureTiming::YES); + return unique; +} + +static const std::vector& getUniqueDatum() { + static const std::vector unique = createUniqueDatum(); + return unique; +} + +///////////////////////// REMOVE DATUM //////////////////////////////////// + +static void removeDatumTest(RequestChannelSender* sender, ResultChannelReceiver* receiver, + const std::vector& serialized) { + for (size_t index = 0; index < serialized.size(); ++index) { + const std::string message = "removeDatum: removed datum at index " + std::to_string(index); + validate(sender, receiver, message, serialized, + [index](std::vector* serialized) { + serialized->erase(serialized->begin() + index); + }); + } +} + +///////////////////////// ADD DATUM //////////////////////////////////// + +static void addDatumTest(RequestChannelSender* sender, ResultChannelReceiver* receiver, + const std::vector& serialized) { + const std::vector& extra = getUniqueDatum(); + for (size_t index = 0; index <= serialized.size(); ++index) { + for (size_t type = 0; type < extra.size(); ++type) { + const std::string message = "addDatum: added datum type " + std::to_string(type) + + " at index " + std::to_string(index); + validate(sender, receiver, message, serialized, + [index, type, &extra](std::vector* serialized) { + serialized->insert(serialized->begin() + index, extra[type]); + }); + } + } +} + +///////////////////////// MUTATE DATUM //////////////////////////////////// + +static bool interestingCase(const FmqRequestDatum& lhs, const FmqRequestDatum& rhs) { + using Discriminator = FmqRequestDatum::hidl_discriminator; + + const bool differentValues = (lhs != rhs); + const bool sameSumType = (lhs.getDiscriminator() == rhs.getDiscriminator()); + const auto discriminator = rhs.getDiscriminator(); + const bool isDimensionValue = (discriminator == Discriminator::inputOperandDimensionValue || + discriminator == Discriminator::outputOperandDimensionValue); + + return differentValues && !(sameSumType && isDimensionValue); +} + +static void mutateDatumTest(RequestChannelSender* sender, ResultChannelReceiver* receiver, + const std::vector& serialized) { + const std::vector& change = getUniqueDatum(); + for (size_t index = 0; index < serialized.size(); ++index) { + for (size_t type = 0; type < change.size(); ++type) { + if (interestingCase(serialized[index], change[type])) { + const std::string message = "mutateDatum: changed datum at index " + + std::to_string(index) + " to datum type " + + std::to_string(type); + validate(sender, receiver, message, serialized, + [index, type, &change](std::vector* serialized) { + (*serialized)[index] = change[type]; + }); + } + } + } +} + +///////////////////////// BURST VALIATION TESTS //////////////////////////////////// + +static void validateBurstSerialization(const sp& preparedModel, + const std::vector& requests) { + // create burst + std::unique_ptr sender; + std::unique_ptr receiver; + sp callback = new ExecutionBurstCallback(); + sp context; + ASSERT_NO_FATAL_FAILURE(createBurst(preparedModel, callback, &sender, &receiver, &context)); + ASSERT_NE(nullptr, sender.get()); + ASSERT_NE(nullptr, receiver.get()); + ASSERT_NE(nullptr, context.get()); + + // validate each request + for (const Request& request : requests) { + // load memory into callback slots + std::vector keys(request.pools.size()); + for (size_t i = 0; i < keys.size(); ++i) { + keys[i] = reinterpret_cast(&request.pools[i]); + } + const std::vector slots = callback->getSlots(request.pools, keys); + + // ensure slot std::numeric_limits::max() doesn't exist (for + // subsequent slot validation testing) + const auto maxElement = std::max_element(slots.begin(), slots.end()); + ASSERT_NE(slots.end(), maxElement); + ASSERT_NE(std::numeric_limits::max(), *maxElement); + + // serialize the request + const auto serialized = ::android::nn::serialize(request, MeasureTiming::YES, slots); + + // validations + removeDatumTest(sender.get(), receiver.get(), serialized); + addDatumTest(sender.get(), receiver.get(), serialized); + mutateDatumTest(sender.get(), receiver.get(), serialized); + } +} + +static void validateBurstFmqLength(const sp& preparedModel, + const std::vector& requests) { + // create regular burst + std::shared_ptr controllerRegular; + ASSERT_NO_FATAL_FAILURE(createBurstWithResultChannelLength(preparedModel, &controllerRegular, + kExecutionBurstChannelLength)); + ASSERT_NE(nullptr, controllerRegular.get()); + + // create burst with small output channel + std::shared_ptr controllerSmall; + ASSERT_NO_FATAL_FAILURE(createBurstWithResultChannelLength(preparedModel, &controllerSmall, + kExecutionBurstChannelSmallLength)); + ASSERT_NE(nullptr, controllerSmall.get()); + + // validate each request + for (const Request& request : requests) { + // load memory into callback slots + std::vector keys(request.pools.size()); + for (size_t i = 0; i < keys.size(); ++i) { + keys[i] = reinterpret_cast(&request.pools[i]); + } + + // collect serialized result by running regular burst + const auto [status1, outputShapes1, timing1] = + controllerRegular->compute(request, MeasureTiming::NO, keys); + + // skip test if synchronous output isn't useful + const std::vector serialized = + ::android::nn::serialize(status1, outputShapes1, timing1); + if (status1 != ErrorStatus::NONE || + serialized.size() <= kExecutionBurstChannelSmallLength) { + continue; + } + + // by this point, execution should fail because the result channel isn't + // large enough to return the serialized result + const auto [status2, outputShapes2, timing2] = + controllerSmall->compute(request, MeasureTiming::NO, keys); + EXPECT_NE(ErrorStatus::NONE, status2); + EXPECT_EQ(0u, outputShapes2.size()); + EXPECT_TRUE(badTiming(timing2)); + } +} + +///////////////////////////// ENTRY POINT ////////////////////////////////// + +void ValidationTest::validateBurst(const sp& preparedModel, + const std::vector& requests) { + ASSERT_NO_FATAL_FAILURE(validateBurstSerialization(preparedModel, requests)); + ASSERT_NO_FATAL_FAILURE(validateBurstFmqLength(preparedModel, requests)); +} + +} // namespace functional +} // namespace vts +} // namespace V1_2 +} // namespace neuralnetworks +} // namespace hardware +} // namespace android diff --git a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp index 870d01748a..9703c2d765 100644 --- a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp +++ b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp @@ -35,9 +35,7 @@ namespace vts { namespace functional { using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback; -using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback; using ::android::hidl::memory::V1_0::IMemory; -using HidlToken = hidl_array(Constant::BYTE_SIZE_OF_CACHE_TOKEN)>; using test_helper::for_all; using test_helper::MixedTyped; using test_helper::MixedTypedExample; @@ -48,55 +46,6 @@ static bool badTiming(Timing timing) { return timing.timeOnDevice == UINT64_MAX && timing.timeInDriver == UINT64_MAX; } -static void createPreparedModel(const sp& device, const Model& model, - sp* preparedModel) { - ASSERT_NE(nullptr, preparedModel); - - // see if service can handle model - bool fullySupportsModel = false; - Return supportedOpsLaunchStatus = device->getSupportedOperations_1_2( - model, [&fullySupportsModel](ErrorStatus status, const hidl_vec& supported) { - ASSERT_EQ(ErrorStatus::NONE, status); - ASSERT_NE(0ul, supported.size()); - fullySupportsModel = - std::all_of(supported.begin(), supported.end(), [](bool valid) { return valid; }); - }); - ASSERT_TRUE(supportedOpsLaunchStatus.isOk()); - - // launch prepare model - sp preparedModelCallback = new PreparedModelCallback(); - ASSERT_NE(nullptr, preparedModelCallback.get()); - Return prepareLaunchStatus = device->prepareModel_1_2( - model, ExecutionPreference::FAST_SINGLE_ANSWER, hidl_vec(), - hidl_vec(), HidlToken(), preparedModelCallback); - ASSERT_TRUE(prepareLaunchStatus.isOk()); - ASSERT_EQ(ErrorStatus::NONE, static_cast(prepareLaunchStatus)); - - // retrieve prepared model - preparedModelCallback->wait(); - ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus(); - *preparedModel = getPreparedModel_1_2(preparedModelCallback); - - // The getSupportedOperations_1_2 call returns a list of operations that are - // guaranteed not to fail if prepareModel_1_2 is called, and - // 'fullySupportsModel' is true i.f.f. the entire model is guaranteed. - // If a driver has any doubt that it can prepare an operation, it must - // return false. So here, if a driver isn't sure if it can support an - // operation, but reports that it successfully prepared the model, the test - // can continue. - if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) { - ASSERT_EQ(nullptr, preparedModel->get()); - LOG(INFO) << "NN VTS: Unable to test Request validation because vendor service cannot " - "prepare model that it does not support."; - std::cout << "[ ] Unable to test Request validation because vendor service " - "cannot prepare model that it does not support." - << std::endl; - return; - } - ASSERT_EQ(ErrorStatus::NONE, prepareReturnStatus); - ASSERT_NE(nullptr, preparedModel->get()); -} - // Primary validation function. This function will take a valid request, apply a // mutation to it to invalidate the request, then pass it to interface calls // that use the request. Note that the request here is passed by value, and any @@ -316,14 +265,8 @@ std::vector createRequests(const std::vector& exampl return requests; } -void ValidationTest::validateRequests(const Model& model, const std::vector& requests) { - // create IPreparedModel - sp preparedModel; - ASSERT_NO_FATAL_FAILURE(createPreparedModel(device, model, &preparedModel)); - if (preparedModel == nullptr) { - return; - } - +void ValidationTest::validateRequests(const sp& preparedModel, + const std::vector& requests) { // validate each request for (const Request& request : requests) { removeInputTest(preparedModel, request); diff --git a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp index 4728c28e87..93182f1da2 100644 --- a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp +++ b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp @@ -18,6 +18,10 @@ #include "VtsHalNeuralnetworks.h" +#include + +#include "Callbacks.h" + namespace android { namespace hardware { namespace neuralnetworks { @@ -25,6 +29,61 @@ namespace V1_2 { namespace vts { namespace functional { +using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback; +using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback; +using HidlToken = hidl_array(Constant::BYTE_SIZE_OF_CACHE_TOKEN)>; +using V1_1::ExecutionPreference; + +// internal helper function +static void createPreparedModel(const sp& device, const Model& model, + sp* preparedModel) { + ASSERT_NE(nullptr, preparedModel); + + // see if service can handle model + bool fullySupportsModel = false; + Return supportedOpsLaunchStatus = device->getSupportedOperations_1_2( + model, [&fullySupportsModel](ErrorStatus status, const hidl_vec& supported) { + ASSERT_EQ(ErrorStatus::NONE, status); + ASSERT_NE(0ul, supported.size()); + fullySupportsModel = std::all_of(supported.begin(), supported.end(), + [](bool valid) { return valid; }); + }); + ASSERT_TRUE(supportedOpsLaunchStatus.isOk()); + + // launch prepare model + sp preparedModelCallback = new PreparedModelCallback(); + ASSERT_NE(nullptr, preparedModelCallback.get()); + Return prepareLaunchStatus = device->prepareModel_1_2( + model, ExecutionPreference::FAST_SINGLE_ANSWER, hidl_vec(), + hidl_vec(), HidlToken(), preparedModelCallback); + ASSERT_TRUE(prepareLaunchStatus.isOk()); + ASSERT_EQ(ErrorStatus::NONE, static_cast(prepareLaunchStatus)); + + // retrieve prepared model + preparedModelCallback->wait(); + ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus(); + *preparedModel = getPreparedModel_1_2(preparedModelCallback); + + // The getSupportedOperations_1_2 call returns a list of operations that are + // guaranteed not to fail if prepareModel_1_2 is called, and + // 'fullySupportsModel' is true i.f.f. the entire model is guaranteed. + // If a driver has any doubt that it can prepare an operation, it must + // return false. So here, if a driver isn't sure if it can support an + // operation, but reports that it successfully prepared the model, the test + // can continue. + if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) { + ASSERT_EQ(nullptr, preparedModel->get()); + LOG(INFO) << "NN VTS: Unable to test Request validation because vendor service cannot " + "prepare model that it does not support."; + std::cout << "[ ] Unable to test Request validation because vendor service " + "cannot prepare model that it does not support." + << std::endl; + return; + } + ASSERT_EQ(ErrorStatus::NONE, prepareReturnStatus); + ASSERT_NE(nullptr, preparedModel->get()); +} + // A class for test environment setup NeuralnetworksHidlEnvironment::NeuralnetworksHidlEnvironment() {} @@ -68,6 +127,20 @@ void NeuralnetworksHidlTest::TearDown() { ::testing::VtsHalHidlTargetTestBase::TearDown(); } +void ValidationTest::validateEverything(const Model& model, const std::vector& request) { + validateModel(model); + + // create IPreparedModel + sp preparedModel; + ASSERT_NO_FATAL_FAILURE(createPreparedModel(device, model, &preparedModel)); + if (preparedModel == nullptr) { + return; + } + + validateRequests(preparedModel, request); + validateBurst(preparedModel, request); +} + sp getPreparedModel_1_2( const sp& callback) { sp preparedModelV1_0 = callback->getPreparedModel(); diff --git a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h index 404eec06db..36e73a4fb0 100644 --- a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h +++ b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h @@ -72,8 +72,14 @@ class NeuralnetworksHidlTest : public ::testing::VtsHalHidlTargetTestBase { // Tag for the validation tests class ValidationTest : public NeuralnetworksHidlTest { protected: - void validateModel(const Model& model); - void validateRequests(const Model& model, const std::vector& request); + void validateEverything(const Model& model, const std::vector& request); + + private: + void validateModel(const Model& model); + void validateRequests(const sp& preparedModel, + const std::vector& requests); + void validateBurst(const sp& preparedModel, + const std::vector& requests); }; // Tag for the generated tests From 286339b4c817e1db9ace3fbed911ace4affa6563 Mon Sep 17 00:00:00 2001 From: Miao Wang Date: Mon, 29 Apr 2019 15:30:06 -0700 Subject: [PATCH 641/718] Fix the order of width and height for NNAPI RESIZE_BILINEAR and RESIZE_NEAREST_NEIGHBOR - The CPU implementation always had the order of {width, height}. - In P, the documentation was incorrectly changed to {height, width}. Bug: 131623949 Bug: 130035110 Test: mm Change-Id: I6c79459fa73347fb51fc34a76ad78d5ac207f210 --- current.txt | 4 ++-- neuralnetworks/1.0/types.hal | 4 ++-- neuralnetworks/1.2/types.hal | 24 ++++++++++++------------ 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/current.txt b/current.txt index d1c52906f0..9fdab8d4ef 100644 --- a/current.txt +++ b/current.txt @@ -401,7 +401,7 @@ f7d7cb747dc01a9fdb2d39a80003b4d8df9be733d65f5842198802eb6209db69 android.hardwar 65a021fa89085b62fc96b2b6d3bef2f9103cf4d63379c68bc154fd9eef672852 android.hardware.health@1.0::types b7ecf29927055ec422ec44bf776223f07d79ad9f92ccf9becf167e62c2607e7a android.hardware.keymaster@4.0::IKeymasterDevice 574e8f1499436fb4075894dcae0b36682427956ecb114f17f1fe22d116a83c6b android.hardware.neuralnetworks@1.0::IPreparedModel -567de4ebb3a224721eabae40c4484fad2cd1608eb0e66ec9214eb88e9b15d3c9 android.hardware.neuralnetworks@1.0::types +e75759b40a1c5f97b463b30aab91954012c9ea9e454dde308db853a56796e5a6 android.hardware.neuralnetworks@1.0::types d51937a3567a50f239589e40300264c4b57f2c3582c6fc6df082f45eb74d90e3 android.hardware.neuralnetworks@1.1::types 1d4a5776614c08b5d794a5ec5ab04697260cbd4b3441d5935cd53ee71d19da02 android.hardware.radio@1.0::IRadioResponse ed9da80ec0c96991fd03f0a46107815d0e50f764656e49dba4980fa5c31d5bc3 android.hardware.radio@1.0::types @@ -515,7 +515,7 @@ b83317b66721241887d2770b5ae95fd5af1e77c5daa7530ecb08fae8892f2b43 android.hardwar 92714960d1a53fc2ec557302b41c7cc93d2636d8364a44bd0f85be0c92927ff8 android.hardware.neuralnetworks@1.2::IExecutionCallback 36e1064c869965dee533c537cefbe87e54db8bd8cd45be7e0e93e00e8a43863a android.hardware.neuralnetworks@1.2::IPreparedModel e1c734d1545e1a4ae749ff1dd9704a8e594c59aea7c8363159dc258e93e0df3b android.hardware.neuralnetworks@1.2::IPreparedModelCallback -51725cd8541bf459190d8a911f9aae9a0825678256b88fc39fac81d69feb04af android.hardware.neuralnetworks@1.2::types +30f6da776bf909fc139f2bc4c176b5a74e9db0978240efcd7429d04e221bfaee android.hardware.neuralnetworks@1.2::types cf7a4ba516a638f9b82a249c91fb603042c2d9ca43fd5aad9cf6c0401ed2a5d7 android.hardware.nfc@1.2::INfc abf98c2ae08bf765db54edc8068e36d52eb558cff6706b6fd7c18c65a1f3fc18 android.hardware.nfc@1.2::types 4cb252dc6372a874aef666b92a6e9529915aa187521a700f0789065c3c702ead android.hardware.power.stats@1.0::IPowerStats diff --git a/neuralnetworks/1.0/types.hal b/neuralnetworks/1.0/types.hal index a358946e31..b0a1c1aec2 100644 --- a/neuralnetworks/1.0/types.hal +++ b/neuralnetworks/1.0/types.hal @@ -1225,9 +1225,9 @@ enum OperationType : int32_t { * * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying * the input. * * 1: An {@link OperandType::INT32} scalar, specifying the output - * height of the output tensor. - * * 2: An {@link OperandType::INT32} scalar, specifying the output * width of the output tensor. + * * 2: An {@link OperandType::INT32} scalar, specifying the output + * height of the output tensor. * * Outputs: * * 0: The output 4-D tensor, of shape diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal index 31576fa461..a6abfc30c5 100644 --- a/neuralnetworks/1.2/types.hal +++ b/neuralnetworks/1.2/types.hal @@ -1593,9 +1593,9 @@ enum OperationType : int32_t { * the input. Since API level 29, zero batches is supported for this * tensor. * * 1: An {@link OperandType::INT32} scalar, specifying the output - * height of the output tensor. - * * 2: An {@link OperandType::INT32} scalar, specifying the output * width of the output tensor. + * * 2: An {@link OperandType::INT32} scalar, specifying the output + * height of the output tensor. * * 3: An optional {@link OperandType::BOOL} scalar, default to false. * Set to true to specify NCHW data layout for input0 and output0. * Available since API level 29. @@ -1603,15 +1603,15 @@ enum OperationType : int32_t { * Inputs (resizing by scale, since API level 29): * * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying * the input. Zero batches is supported for this tensor. - * * 1: A scalar, specifying height_scale, the scaling factor of the height + * * 1: A scalar, specifying width_scale, the scaling factor of the width * dimension from the input tensor to the output tensor. The output - * height is calculated as new_height = floor(height * height_scale). + * width is calculated as new_width = floor(width * width_scale). * The scalar must be of {@link OperandType::FLOAT16} if input0 is * of {@link OperandType::TENSOR_FLOAT16} and of * {@link OperandType::FLOAT32} otherwise. - * * 2: A scalar, specifying width_scale, the scaling factor of the width + * * 2: A scalar, specifying height_scale, the scaling factor of the height * dimension from the input tensor to the output tensor. The output - * width is calculated as new_width = floor(width * width_scale). + * height is calculated as new_height = floor(height * height_scale). * The scalar must be of {@link OperandType::FLOAT16} if input0 is * of {@link OperandType::TENSOR_FLOAT16} and of * {@link OperandType::FLOAT32} otherwise. @@ -4663,24 +4663,24 @@ enum OperationType : int32_t { * * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying * the input. Zero batches is supported for this tensor. * * 1: An {@link OperandType::INT32} scalar, specifying the output - * height of the output tensor. - * * 2: An {@link OperandType::INT32} scalar, specifying the output * width of the output tensor. + * * 2: An {@link OperandType::INT32} scalar, specifying the output + * height of the output tensor. * * 3: An {@link OperandType::BOOL} scalar, default to false. * Set to true to specify NCHW data layout for input0 and output0. * * Inputs (resizing by scale): * * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying * the input. Zero batches is supported for this tensor. - * * 1: A scalar, specifying height_scale, the scaling factor of the height + * * 1: A scalar, specifying width_scale, the scaling factor of the width * dimension from the input tensor to the output tensor. The output - * height is calculated as new_height = floor(height * height_scale). + * width is calculated as new_width = floor(width * width_scale). * The scalar must be of {@link OperandType::FLOAT16} if input0 is * of {@link OperandType::TENSOR_FLOAT16} and of * {@link OperandType::FLOAT32} otherwise. - * * 2: A scalar, specifying width_scale, the scaling factor of the width + * * 2: A scalar, specifying height_scale, the scaling factor of the height * dimension from the input tensor to the output tensor. The output - * width is calculated as new_width = floor(width * width_scale). + * height is calculated as new_height = floor(height * height_scale). * The scalar must be of {@link OperandType::FLOAT16} if input0 is * of {@link OperandType::TENSOR_FLOAT16} and of * {@link OperandType::FLOAT32} otherwise. From 8acfc0ce73f4c20414a20ca5240cbe47a8016111 Mon Sep 17 00:00:00 2001 From: Kai Date: Fri, 26 Apr 2019 15:44:51 -0700 Subject: [PATCH 642/718] Add configArray for HVAC_TEMPERATURE_DISPLAY_UNITS Add configArray for HVAC_TEMPERATURE_DISPLAY_UNITS Bug: 80298447 Test: build Change-Id: Ie4fb6ea78f4a4c1337420db8d9b6d545fd9f377c --- automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h | 1 + 1 file changed, 1 insertion(+) 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 08cdffa715..39fe991339 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 @@ -530,6 +530,7 @@ const ConfigDeclaration kVehicleProperties[]{ {.config = {.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_DISPLAY_UNITS), .access = VehiclePropertyAccess::READ_WRITE, .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + .configArray = {(int)VehicleUnit::FAHRENHEIT, (int)VehicleUnit::CELSIUS}, .areaConfigs = {VehicleAreaConfig{.areaId = (0)}}}, .initialValue = {.int32Values = {(int)VehicleUnit::FAHRENHEIT}}}, From b01ce9644e3e46600143953905a9b53c0de37887 Mon Sep 17 00:00:00 2001 From: Slava Shklyaev Date: Tue, 30 Apr 2019 14:32:17 +0100 Subject: [PATCH 643/718] Document that quantized PAD behavior is undefined before NNAPI 1.2 We had no tests for quantized PAD in NNAPI 1.1 and think that vendors might have implemented different behaviors. Bug: 122243484 Test: N/A Change-Id: Ibfc0801ab746fc271dc5f8efc764b818c6d49df4 --- current.txt | 4 ++-- neuralnetworks/1.1/types.hal | 5 ++++- neuralnetworks/1.2/types.hal | 7 ++++++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/current.txt b/current.txt index 9fdab8d4ef..30839471c9 100644 --- a/current.txt +++ b/current.txt @@ -402,7 +402,7 @@ f7d7cb747dc01a9fdb2d39a80003b4d8df9be733d65f5842198802eb6209db69 android.hardwar b7ecf29927055ec422ec44bf776223f07d79ad9f92ccf9becf167e62c2607e7a android.hardware.keymaster@4.0::IKeymasterDevice 574e8f1499436fb4075894dcae0b36682427956ecb114f17f1fe22d116a83c6b android.hardware.neuralnetworks@1.0::IPreparedModel e75759b40a1c5f97b463b30aab91954012c9ea9e454dde308db853a56796e5a6 android.hardware.neuralnetworks@1.0::types -d51937a3567a50f239589e40300264c4b57f2c3582c6fc6df082f45eb74d90e3 android.hardware.neuralnetworks@1.1::types +eb754b58c93e5591613208b4c972811288b0fa16a82430d602f107c91a908b22 android.hardware.neuralnetworks@1.1::types 1d4a5776614c08b5d794a5ec5ab04697260cbd4b3441d5935cd53ee71d19da02 android.hardware.radio@1.0::IRadioResponse ed9da80ec0c96991fd03f0a46107815d0e50f764656e49dba4980fa5c31d5bc3 android.hardware.radio@1.0::types 1d19720d4fd38b1095f0f555a4bd92b3b12c9b1d0f560b0e9a474cd6dcc20db6 android.hardware.radio@1.2::IRadio @@ -515,7 +515,7 @@ b83317b66721241887d2770b5ae95fd5af1e77c5daa7530ecb08fae8892f2b43 android.hardwar 92714960d1a53fc2ec557302b41c7cc93d2636d8364a44bd0f85be0c92927ff8 android.hardware.neuralnetworks@1.2::IExecutionCallback 36e1064c869965dee533c537cefbe87e54db8bd8cd45be7e0e93e00e8a43863a android.hardware.neuralnetworks@1.2::IPreparedModel e1c734d1545e1a4ae749ff1dd9704a8e594c59aea7c8363159dc258e93e0df3b android.hardware.neuralnetworks@1.2::IPreparedModelCallback -30f6da776bf909fc139f2bc4c176b5a74e9db0978240efcd7429d04e221bfaee android.hardware.neuralnetworks@1.2::types +e3b6176e3bf235c4e0e4e451b0166e396c7ee176cfe167c9147c3d46d7b34f0c android.hardware.neuralnetworks@1.2::types cf7a4ba516a638f9b82a249c91fb603042c2d9ca43fd5aad9cf6c0401ed2a5d7 android.hardware.nfc@1.2::INfc abf98c2ae08bf765db54edc8068e36d52eb558cff6706b6fd7c18c65a1f3fc18 android.hardware.nfc@1.2::types 4cb252dc6372a874aef666b92a6e9529915aa187521a700f0789065c3c702ead android.hardware.power.stats@1.0::IPowerStats diff --git a/neuralnetworks/1.1/types.hal b/neuralnetworks/1.1/types.hal index 335b80366f..73705bb56d 100644 --- a/neuralnetworks/1.1/types.hal +++ b/neuralnetworks/1.1/types.hal @@ -138,7 +138,7 @@ enum OperationType : @1.0::OperationType { * * Supported tensor {@link OperandType}: * * {@link OperandType::TENSOR_FLOAT32} - * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} (the pad value is undefined) * * Supported tensor rank: up to 4 * @@ -161,6 +161,9 @@ enum OperationType : @1.0::OperationType { * output0.dimension[i] = * padding[i, 0] + input0.dimension[i] + padding[i, 1] * + * NOTE: The pad value for {@link ANEURALNETWORKS_TENSOR_QUANT8_ASYMM} + * is undefined. + * * Available since API level 28. */ PAD = 32, diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal index a6abfc30c5..c2e8f22052 100644 --- a/neuralnetworks/1.2/types.hal +++ b/neuralnetworks/1.2/types.hal @@ -1999,7 +1999,8 @@ enum OperationType : int32_t { * Supported tensor {@link OperandType}: * * {@link OperandType::TENSOR_FLOAT16} (since API level 29) * * {@link OperandType::TENSOR_FLOAT32} - * * {@link OperandType::TENSOR_QUANT8_ASYMM} + * * {@link OperandType::TENSOR_QUANT8_ASYMM} (full support since API + * level 29, see the output section) * * Supported tensor rank: up to 4 * @@ -2022,6 +2023,10 @@ enum OperationType : int32_t { * output0.dimension[i] = * padding[i, 0] + input0.dimension[i] + padding[i, 1] * + * NOTE: Before API level 29, the pad value for + * {@link ANEURALNETWORKS_TENSOR_QUANT8_ASYMM} is undefined. + * Since API level 29, the pad value is always the logical zero. + * * Available since API level 28. */ PAD = @1.1::OperationType:PAD, From d47288dde54232df0fac57c70c12f75fc1de0c8b Mon Sep 17 00:00:00 2001 From: Garret Kelly Date: Wed, 1 May 2019 15:12:11 -0400 Subject: [PATCH 644/718] Make test expectation match comment The BOOT_PATCHLEVEL value is allowed to have 00 in the days position according to the keymaster specification. This test's comment already suggests that it's allowed, so update the expectation to match. Test: VtsHalKeymasterV4_0TargetTest Bug: 130843899 Change-Id: Ib43da43b2e0398b48fb59710bf4066f2641de2eb --- keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp index cf12e2a4b5..3d37e9fb82 100644 --- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp +++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp @@ -371,7 +371,7 @@ bool verify_attestation_record(const string& challenge, const string& app_id, strptime(date.c_str(), "%Y-%m-%d", &time); // Day of the month (0-31) - EXPECT_GT(time.tm_mday, 0); + EXPECT_GE(time.tm_mday, 0); EXPECT_LT(time.tm_mday, 32); // Months since Jan (0-11) EXPECT_GE(time.tm_mon, 0); From 0686afa15a0c2f3666246977ebd1db37e640ebad Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Mon, 29 Apr 2019 16:04:41 -0700 Subject: [PATCH 645/718] Return display capability if getDisplayBrightnessSupport is not registered. If getDisplayBrightnessSupport is not registered, there are two possibilities, one is it's not supported at all, the other is that the support is returned in getDisplayCapabilities. And thus we need to check getDisplayCapabilities, and we return UNSUPPORTED always in this case. This patch also allows getPerFrameMetadataKeys to return UNSUPPORTED on non-HDR capable devices. BUG: 131595097 Test: Build, boot. Change-Id: Ied302b1ac702dd94e039f1081d5420395c1bfbf4 --- .../VtsHalGraphicsComposerV2_2TargetTest.cpp | 14 +++++++++++++- .../include/composer-hal/2.3/ComposerClient.h | 2 +- .../hal/include/composer-hal/2.3/ComposerHal.h | 2 +- .../include/composer-passthrough/2.3/HwcHal.h | 18 ++++++++++++++++-- 4 files changed, 31 insertions(+), 5 deletions(-) diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp index 7834b9460f..9c80f4da5e 100644 --- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp +++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp @@ -246,7 +246,19 @@ TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_PER_FRAME_METADATA) { * Test IComposerClient::getPerFrameMetadataKeys. */ TEST_F(GraphicsComposerHidlTest, GetPerFrameMetadataKeys) { - mComposerClient->getPerFrameMetadataKeys(mPrimaryDisplay); + std::vector keys; + Error error = Error::NONE; + mComposerClient->getRaw()->getPerFrameMetadataKeys( + mPrimaryDisplay, [&](const auto& tmpError, const auto& tmpKeys) { + error = tmpError; + keys = tmpKeys; + }); + if (error == Error::UNSUPPORTED) { + GTEST_SUCCEED() << "getPerFrameMetadataKeys is not supported"; + return; + } + ASSERT_EQ(Error::NONE, error); + ASSERT_TRUE(keys.size() >= 0); } /** diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h index 3792c2e4a0..b289b6a0f9 100644 --- a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h +++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h @@ -95,7 +95,7 @@ class ComposerClientImpl : public V2_2::hal::detail::ComposerClientImpl getDisplayCapabilities( Display display, IComposerClient::getDisplayCapabilities_cb hidl_cb) override { - hidl_vec capabilities; + std::vector capabilities; Error error = mHal->getDisplayCapabilities(display, &capabilities); hidl_cb(error, capabilities); return Void(); diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h index 186b004810..c3c488746d 100644 --- a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h +++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h @@ -115,7 +115,7 @@ class ComposerHal : public V2_2::hal::ComposerHal { hidl_vec& sampleComponent2, hidl_vec& sampleComponent3) = 0; virtual Error getDisplayCapabilities( - Display display, hidl_vec* outCapabilities) = 0; + Display display, std::vector* outCapabilities) = 0; virtual Error setLayerPerFrameMetadataBlobs( Display display, Layer layer, std::vector& blobs) = 0; diff --git a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h index 4829e24daa..d3b29bb803 100644 --- a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h +++ b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h @@ -220,7 +220,8 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl { } Error getDisplayCapabilities( - Display display, hidl_vec* outCapabilities) override { + Display display, + std::vector* outCapabilities) override { uint32_t count = 0; int32_t error = mDispatch.getDisplayCapabilities(mDevice, display, &count, nullptr); if (error != HWC2_ERROR_NONE) { @@ -232,7 +233,7 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl { reinterpret_cast::type*>( outCapabilities->data())); if (error != HWC2_ERROR_NONE) { - *outCapabilities = hidl_vec(); + *outCapabilities = std::vector(); return static_cast(error); } return Error::NONE; @@ -267,6 +268,19 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl { Error getDisplayBrightnessSupport(Display display, bool* outSupport) { if (!mDispatch.getDisplayBrightnessSupport) { + // Preemptively set to false. + *outSupport = false; + // Try to query from getDisplayCapabilities. + std::vector capabilities; + Error error = getDisplayCapabilities(display, &capabilities); + if (error != Error::NONE) { + // This function is not registered, always return UNSUPPORTED. + return Error::UNSUPPORTED; + } + *outSupport = + std::find(capabilities.begin(), capabilities.end(), + IComposerClient::DisplayCapability::BRIGHTNESS) != capabilities.end(); + // This function is not registered, always return UNSUPPORTED. return Error::UNSUPPORTED; } bool support = false; From 62d2ca76874de7f9fd350cbba4718fd59a118973 Mon Sep 17 00:00:00 2001 From: Anil Admal Date: Wed, 1 May 2019 19:30:31 -0700 Subject: [PATCH 646/718] Update GNSS VTS 2.0 tests to address sub-HAL support requirements - IGnssConfiguration.hal@2.0 must be supported. - If IAGnss.hal is supported, it must be at IAGnss.hal@2.0 - If IAGnssRil.hal is supported, it must be at IAGnssRil.hal@2.0 - gnss.visibility_control sub-HAL is optional - gnss.measurement_corrections sub HAL is optional. - IGnssBatching.hal@2.0 support is optional. Bug: 70978505 Test: atest VtsHalGnssV2_0TargetTest Change-Id: Icf98c13ef32bdea7dafda8f79b685466712b16b6 --- .../vts/functional/gnss_hal_test_cases.cpp | 99 +++++++++---------- 1 file changed, 44 insertions(+), 55 deletions(-) diff --git a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp index be182a9c52..7c253b0645 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp +++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp @@ -29,6 +29,7 @@ using IGnssMeasurement_2_0 = android::hardware::gnss::V2_0::IGnssMeasurement; using IGnssMeasurement_1_1 = android::hardware::gnss::V1_1::IGnssMeasurement; using IGnssMeasurement_1_0 = android::hardware::gnss::V1_0::IGnssMeasurement; using IAGnssRil_2_0 = android::hardware::gnss::V2_0::IAGnssRil; +using IAGnssRil_1_0 = android::hardware::gnss::V1_0::IAGnssRil; using IAGnss_2_0 = android::hardware::gnss::V2_0::IAGnss; using IAGnss_1_0 = android::hardware::gnss::V1_0::IAGnss; using IAGnssCallback_2_0 = android::hardware::gnss::V2_0::IAGnssCallback; @@ -125,16 +126,21 @@ TEST_F(GnssHalTest, TestGnssConfiguration_setGpsLock_Deprecation) { * TestAGnssRilExtension: * Gets the AGnssRilExtension and verifies that it returns an actual extension. * - * The GNSS HAL 2.0 implementation must support @2.0::IAGnssRil interface due to the deprecation - * of framework network API methods needed to support the @1.0::IAGnssRil interface. - * - * TODO (b/121287858): Enforce gnss@2.0 HAL package is supported on devices launched with Q or later + * If IAGnssRil interface is supported, then the GNSS HAL 2.0 implementation must support + * @2.0::IAGnssRil interface due to the deprecation of framework network API methods needed + * to support the @1.0::IAGnssRil interface. */ TEST_F(GnssHalTest, TestAGnssRilExtension) { - auto agnssRil = gnss_hal_->getExtensionAGnssRil_2_0(); - ASSERT_TRUE(agnssRil.isOk()); - sp iAGnssRil = agnssRil; - ASSERT_NE(iAGnssRil, nullptr); + auto agnssRil_2_0 = gnss_hal_->getExtensionAGnssRil_2_0(); + ASSERT_TRUE(agnssRil_2_0.isOk()); + sp iAGnssRil_2_0 = agnssRil_2_0; + if (iAGnssRil_2_0 == nullptr) { + // Verify IAGnssRil 1.0 is not supported. + auto agnssRil_1_0 = gnss_hal_->getExtensionAGnssRil(); + ASSERT_TRUE(agnssRil_1_0.isOk()); + sp iAGnssRil_1_0 = agnssRil_1_0; + ASSERT_EQ(iAGnssRil_1_0, nullptr); + } } /* @@ -146,7 +152,9 @@ TEST_F(GnssHalTest, TestAGnssRil_UpdateNetworkState_2_0) { auto agnssRil = gnss_hal_->getExtensionAGnssRil_2_0(); ASSERT_TRUE(agnssRil.isOk()); sp iAGnssRil = agnssRil; - ASSERT_NE(iAGnssRil, nullptr); + if (iAGnssRil == nullptr) { + return; + } // Update GNSS HAL that a network has connected. IAGnssRil_2_0::NetworkAttributes networkAttributes = { @@ -219,44 +227,35 @@ TEST_F(GnssHalTest, TestGnssMeasurementFields) { /* * TestAGnssExtension: - * Gets the AGnssExtension and verifies that it supports @2.0::IAGnss interface by invoking - * a method. + * Gets the AGnssExtension and verifies that it returns an actual extension. * - * The GNSS HAL 2.0 implementation must support @2.0::IAGnss interface due to the deprecation - * of framework network API methods needed to support the @1.0::IAGnss interface. - * - * TODO (b/121287858): Enforce gnss@2.0 HAL package is supported on devices launched with Q or later + * If IAGnss interface is supported, then the GNSS HAL 2.0 implementation must support + * @2.0::IAGnss interface due to the deprecation of framework network API methods needed + * to support the @1.0::IAGnss interface. */ TEST_F(GnssHalTest, TestAGnssExtension) { - // Verify IAGnss 2.0 is supported. - auto agnss = gnss_hal_->getExtensionAGnss_2_0(); - ASSERT_TRUE(agnss.isOk()); - sp iAGnss = agnss; - ASSERT_NE(iAGnss, nullptr); + auto agnss_2_0 = gnss_hal_->getExtensionAGnss_2_0(); + ASSERT_TRUE(agnss_2_0.isOk()); + sp iAGnss_2_0 = agnss_2_0; + if (iAGnss_2_0 == nullptr) { + // Verify IAGnss 1.0 is not supported. + auto agnss_1_0 = gnss_hal_->getExtensionAGnss(); + ASSERT_TRUE(agnss_1_0.isOk()); + sp iAGnss_1_0 = agnss_1_0; + ASSERT_EQ(iAGnss_1_0, nullptr); + return; + } // Set SUPL server host/port - auto result = iAGnss->setServer(IAGnssCallback_2_0::AGnssType::SUPL, "supl.google.com", 7275); + auto result = + iAGnss_2_0->setServer(IAGnssCallback_2_0::AGnssType::SUPL, "supl.google.com", 7275); ASSERT_TRUE(result.isOk()); EXPECT_TRUE(result); } -/* - * TestAGnssExtension_1_0_Deprecation: - * Gets the @1.0::IAGnss extension and verifies that it is a nullptr. - * - * TODO (b/121287858): Enforce gnss@2.0 HAL package is supported on devices launched with Q or later - */ -TEST_F(GnssHalTest, TestAGnssExtension_1_0_Deprecation) { - // Verify IAGnss 1.0 is not supported. - auto agnss_1_0 = gnss_hal_->getExtensionAGnss(); - ASSERT_TRUE(!agnss_1_0.isOk() || ((sp)agnss_1_0) == nullptr); -} - /* * TestGnssNiExtension_Deprecation: * Gets the @1.0::IGnssNi extension and verifies that it is a nullptr. - * - * TODO (b/121287858): Enforce gnss@2.0 HAL package is supported on devices launched with Q or later */ TEST_F(GnssHalTest, TestGnssNiExtension_Deprecation) { // Verify IGnssNi 1.0 is not supported. @@ -266,22 +265,19 @@ TEST_F(GnssHalTest, TestGnssNiExtension_Deprecation) { /* * TestGnssVisibilityControlExtension: - * Gets the GnssVisibilityControlExtension and verifies that it supports the - * gnss.visibility_control@1.0::IGnssVisibilityControl interface by invoking a method. - * - * The GNSS HAL 2.0 implementation must support gnss.visibility_control@1.0::IGnssVisibilityControl. - * - * TODO (b/121287858): Enforce gnss@2.0 HAL package is supported on devices launched with Q or later + * Gets the GnssVisibilityControlExtension and if it is not null, verifies that it supports + * the gnss.visibility_control@1.0::IGnssVisibilityControl interface by invoking a method. */ TEST_F(GnssHalTest, TestGnssVisibilityControlExtension) { - // Verify IGnssVisibilityControl is supported. auto gnssVisibilityControl = gnss_hal_->getExtensionVisibilityControl(); ASSERT_TRUE(gnssVisibilityControl.isOk()); sp iGnssVisibilityControl = gnssVisibilityControl; - ASSERT_NE(iGnssVisibilityControl, nullptr); + if (iGnssVisibilityControl == nullptr) { + return; + } // Set non-framework proxy apps. - hidl_vec proxyApps{"ims.example.com", "mdt.example.com"}; + hidl_vec proxyApps{"com.example.ims", "com.example.mdt"}; auto result = iGnssVisibilityControl->enableNfwLocationAccess(proxyApps); ASSERT_TRUE(result.isOk()); EXPECT_TRUE(result); @@ -408,17 +404,10 @@ TEST_F(GnssHalTest, TestInjectBestLocation_2_0) { /* * TestGnssBatchingExtension: - * Gets the GnssBatchingExtension and verifies that it supports either the @1.0::IGnssBatching - * or @2.0::IGnssBatching extension. + * Gets the @2.0::IGnssBatching extension and verifies that it doesn't return an error. Support + * for this interface is optional. */ TEST_F(GnssHalTest, TestGnssBatchingExtension) { - auto gnssBatching_V2_0 = gnss_hal_->getExtensionGnssBatching_2_0(); - ASSERT_TRUE(gnssBatching_V2_0.isOk()); - - auto gnssBatching_V1_0 = gnss_hal_->getExtensionGnssBatching(); - ASSERT_TRUE(gnssBatching_V1_0.isOk()); - - sp iGnssBatching_V1_0 = gnssBatching_V1_0; - sp iGnssBatching_V2_0 = gnssBatching_V2_0; - ASSERT_TRUE(iGnssBatching_V1_0 != nullptr || iGnssBatching_V2_0 != nullptr); + auto gnssBatching_2_0 = gnss_hal_->getExtensionGnssBatching_2_0(); + ASSERT_TRUE(gnssBatching_2_0.isOk()); } From 7f9c13e198e63618245d093da1306b5291b6e70d Mon Sep 17 00:00:00 2001 From: Anil Admal Date: Fri, 3 May 2019 15:59:16 -0700 Subject: [PATCH 647/718] Fix wait/notify logic in GNSS VTS 2.0 test cases Fixes: 131869042 Test: atest VtsHalGnssV2_0TargetTest Change-Id: I6fe5713c0f1d329f2738a2d4ba4a7d5aa58efec9 --- gnss/2.0/vts/functional/gnss_hal_test.cpp | 130 ++++++------------ gnss/2.0/vts/functional/gnss_hal_test.h | 100 +++++++++++--- .../vts/functional/gnss_hal_test_cases.cpp | 33 +++-- 3 files changed, 140 insertions(+), 123 deletions(-) diff --git a/gnss/2.0/vts/functional/gnss_hal_test.cpp b/gnss/2.0/vts/functional/gnss_hal_test.cpp index da6092bb4b..febd0f1d13 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test.cpp +++ b/gnss/2.0/vts/functional/gnss_hal_test.cpp @@ -23,38 +23,34 @@ using ::android::hardware::gnss::common::Utils; // Implementations for the main test class for GNSS HAL -GnssHalTest::GnssHalTest() - : info_called_count_(0), - capabilities_called_count_(0), - measurement_corrections_capabilities_called_count_(0), - location_called_count_(0), - name_called_count_(0), - notify_count_(0) {} +GnssHalTest::GnssHalTest() {} void GnssHalTest::SetUp() { gnss_hal_ = ::testing::VtsHalHidlTargetTestBase::getService( GnssHidlEnvironment::Instance()->getServiceName()); - list_vec_gnss_sv_info_.clear(); ASSERT_NE(gnss_hal_, nullptr); SetUpGnssCallback(); } void GnssHalTest::TearDown() { - // Reset counters - info_called_count_ = 0; - capabilities_called_count_ = 0; - measurement_corrections_capabilities_called_count_ = 0; - location_called_count_ = 0; - name_called_count_ = 0; - measurement_called_count_ = 0; - if (gnss_hal_ != nullptr) { gnss_hal_->cleanup(); } - if (notify_count_ > 0) { - ALOGW("%d unprocessed callbacks discarded", notify_count_); + + int unprocessedEventsCount = measurement_cbq_.size() + location_cbq_.size(); + if (unprocessedEventsCount > 0) { + ALOGW("%d unprocessed callbacks discarded", unprocessedEventsCount); } + + // Reset all callback event queues. + info_cbq_.reset(); + name_cbq_.reset(); + top_hal_capabilities_cbq_.reset(); + measurement_corrections_capabilities_cbq_.reset(); + measurement_cbq_.reset(); + location_cbq_.reset(); + sv_info_cbq_.reset(); } void GnssHalTest::SetUpGnssCallback() { @@ -72,13 +68,13 @@ void GnssHalTest::SetUpGnssCallback() { /* * All capabilities, name and systemInfo callbacks should trigger */ - EXPECT_EQ(std::cv_status::no_timeout, wait(TIMEOUT_SEC)); - EXPECT_EQ(std::cv_status::no_timeout, wait(TIMEOUT_SEC)); - EXPECT_EQ(std::cv_status::no_timeout, wait(TIMEOUT_SEC)); + EXPECT_TRUE(top_hal_capabilities_cbq_.retrieve(last_capabilities_, TIMEOUT_SEC)); + EXPECT_TRUE(info_cbq_.retrieve(last_info_, TIMEOUT_SEC)); + EXPECT_TRUE(name_cbq_.retrieve(last_name_, TIMEOUT_SEC)); - EXPECT_EQ(capabilities_called_count_, 1); - EXPECT_EQ(info_called_count_, 1); - EXPECT_EQ(name_called_count_, 1); + EXPECT_EQ(top_hal_capabilities_cbq_.calledCount(), 1); + EXPECT_EQ(info_cbq_.calledCount(), 1); + EXPECT_EQ(name_cbq_.calledCount(), 1); } void GnssHalTest::StopAndClearLocations() { @@ -92,9 +88,8 @@ void GnssHalTest::StopAndClearLocations() { * the last reply for final startup messages to arrive (esp. system * info.) */ - while (wait(TIMEOUT_SEC) == std::cv_status::no_timeout) { - } - location_called_count_ = 0; + location_cbq_.waitUntilEmpty(TIMEOUT_SEC); + location_cbq_.reset(); } void GnssHalTest::SetPositionMode(const int min_interval_msec, const bool low_power_mode) { @@ -121,10 +116,11 @@ bool GnssHalTest::StartAndCheckFirstLocation() { */ const int kFirstGnssLocationTimeoutSeconds = 75; - wait(kFirstGnssLocationTimeoutSeconds); - EXPECT_EQ(location_called_count_, 1); + EXPECT_TRUE(location_cbq_.retrieve(last_location_, kFirstGnssLocationTimeoutSeconds)); + int locationCalledCount = location_cbq_.calledCount(); + EXPECT_EQ(locationCalledCount, 1); - if (location_called_count_ > 0) { + if (locationCalledCount > 0) { // don't require speed on first fix CheckLocation(last_location_, false); return true; @@ -133,7 +129,7 @@ bool GnssHalTest::StartAndCheckFirstLocation() { } void GnssHalTest::CheckLocation(const GnssLocation_2_0& location, bool check_speed) { - const bool check_more_accuracies = (info_called_count_ > 0 && last_info_.yearOfHw >= 2017); + const bool check_more_accuracies = (info_cbq_.calledCount() > 0 && last_info_.yearOfHw >= 2017); Utils::checkLocation(location.v1_0, check_speed, check_more_accuracies); } @@ -148,77 +144,39 @@ void GnssHalTest::StartAndCheckLocations(int count) { EXPECT_TRUE(StartAndCheckFirstLocation()); for (int i = 1; i < count; i++) { - EXPECT_EQ(std::cv_status::no_timeout, wait(kLocationTimeoutSubsequentSec)); - EXPECT_EQ(location_called_count_, i + 1); + EXPECT_TRUE(location_cbq_.retrieve(last_location_, kLocationTimeoutSubsequentSec)); + int locationCalledCount = location_cbq_.calledCount(); + EXPECT_EQ(locationCalledCount, i + 1); // Don't cause confusion by checking details if no location yet - if (location_called_count_ > 0) { + if (locationCalledCount > 0) { // Should be more than 1 location by now, but if not, still don't check first fix speed - CheckLocation(last_location_, location_called_count_ > 1); + CheckLocation(last_location_, locationCalledCount > 1); } } } -void GnssHalTest::notify() { - { - std::unique_lock lock(mtx_); - notify_count_++; - } - cv_.notify_one(); -} - -std::cv_status GnssHalTest::wait(int timeout_seconds) { - std::unique_lock lock(mtx_); - - auto status = std::cv_status::no_timeout; - while (notify_count_ == 0) { - status = cv_.wait_for(lock, std::chrono::seconds(timeout_seconds)); - if (status == std::cv_status::timeout) return status; - } - notify_count_--; - return status; -} - -std::cv_status GnssHalTest::waitForMeasurementCorrectionsCapabilities(int timeout_seconds) { - std::unique_lock lock(mtx_); - auto status = std::cv_status::no_timeout; - while (measurement_corrections_capabilities_called_count_ == 0) { - status = cv_.wait_for(lock, std::chrono::seconds(timeout_seconds)); - if (status == std::cv_status::timeout) return status; - } - notify_count_--; - return status; -} - Return GnssHalTest::GnssCallback::gnssSetSystemInfoCb( const IGnssCallback_1_0::GnssSystemInfo& info) { ALOGI("Info received, year %d", info.yearOfHw); - parent_.info_called_count_++; - parent_.last_info_ = info; - parent_.notify(); + parent_.info_cbq_.store(info); return Void(); } Return GnssHalTest::GnssCallback::gnssSetCapabilitesCb(uint32_t capabilities) { ALOGI("Capabilities received %d", capabilities); - parent_.capabilities_called_count_++; - parent_.last_capabilities_ = capabilities; - parent_.notify(); + parent_.top_hal_capabilities_cbq_.store(capabilities); return Void(); } Return GnssHalTest::GnssCallback::gnssSetCapabilitiesCb_2_0(uint32_t capabilities) { ALOGI("Capabilities (v2.0) received %d", capabilities); - parent_.capabilities_called_count_++; - parent_.last_capabilities_ = capabilities; - parent_.notify(); + parent_.top_hal_capabilities_cbq_.store(capabilities); return Void(); } Return GnssHalTest::GnssCallback::gnssNameCb(const android::hardware::hidl_string& name) { ALOGI("Name received: %s", name.c_str()); - parent_.name_called_count_++; - parent_.last_name_ = name; - parent_.notify(); + parent_.name_cbq_.store(name); return Void(); } @@ -235,40 +193,32 @@ Return GnssHalTest::GnssCallback::gnssLocationCb_2_0(const GnssLocation_2_ } Return GnssHalTest::GnssCallback::gnssLocationCbImpl(const GnssLocation_2_0& location) { - parent_.location_called_count_++; - parent_.last_location_ = location; - parent_.notify(); + parent_.location_cbq_.store(location); return Void(); } Return GnssHalTest::GnssCallback::gnssSvStatusCb(const IGnssCallback_1_0::GnssSvStatus&) { ALOGI("gnssSvStatusCb"); - return Void(); } Return GnssHalTest::GnssMeasurementCallback::gnssMeasurementCb_2_0( const IGnssMeasurementCallback_2_0::GnssData& data) { ALOGD("GnssMeasurement received. Size = %d", (int)data.measurements.size()); - parent_.measurement_called_count_++; - parent_.last_measurement_ = data; - parent_.notify(); + parent_.measurement_cbq_.store(data); return Void(); } Return GnssHalTest::GnssMeasurementCorrectionsCallback::setCapabilitiesCb( uint32_t capabilities) { ALOGI("GnssMeasurementCorrectionsCallback capabilities received %d", capabilities); - parent_.measurement_corrections_capabilities_called_count_++; - parent_.last_measurement_corrections_capabilities_ = capabilities; - parent_.notify(); + parent_.measurement_corrections_capabilities_cbq_.store(capabilities); return Void(); } Return GnssHalTest::GnssCallback::gnssSvStatusCb_2_0( const hidl_vec& svInfoList) { ALOGI("gnssSvStatusCb_2_0. Size = %d", (int)svInfoList.size()); - parent_.list_vec_gnss_sv_info_.emplace_back(svInfoList); - parent_.notify(); + parent_.sv_info_cbq_.store(svInfoList); return Void(); } diff --git a/gnss/2.0/vts/functional/gnss_hal_test.h b/gnss/2.0/vts/functional/gnss_hal_test.h index 737815f0c3..8e440ff956 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test.h +++ b/gnss/2.0/vts/functional/gnss_hal_test.h @@ -22,7 +22,7 @@ #include #include -#include +#include #include using android::hardware::hidl_vec; @@ -125,7 +125,7 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase { /* Callback class for GnssMeasurement. */ class GnssMeasurementCallback : public IGnssMeasurementCallback_2_0 { - public: + public: GnssHalTest& parent_; GnssMeasurementCallback(GnssHalTest& parent) : parent_(parent){}; virtual ~GnssMeasurementCallback() = default; @@ -155,6 +155,77 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase { Return setCapabilitiesCb(uint32_t capabilities) override; }; + /* Producer/consumer queue for storing/retrieving callback events from GNSS HAL */ + template + class CallbackQueue { + public: + CallbackQueue() : called_count_(0){}; + + /* Adds callback event to the end of the queue. */ + void store(const T& event) { + std::unique_lock lock(mtx_); + events_.push_back(event); + ++called_count_; + lock.unlock(); + cv_.notify_all(); + } + + /* + * Removes the callack event at the front of the queue, stores it in event parameter + * and returns true. If the timeout occurs waiting for callback event, returns false. + */ + bool retrieve(T& event, int timeout_seconds) { + std::unique_lock lock(mtx_); + cv_.wait_for(lock, std::chrono::seconds(timeout_seconds), + [&] { return !events_.empty(); }); + if (events_.empty()) { + return false; + } + event = events_.front(); + events_.pop_front(); + return true; + } + + /* Returns the number of events pending to be retrieved from the callback event queue. */ + int size() const { + std::unique_lock lock(mtx_); + return events_.size(); + } + + /* Returns the number of callback events received since last reset(). */ + int calledCount() const { + std::unique_lock lock(mtx_); + return called_count_; + } + + /* Clears the callback event queue and resets the calledCount() to 0. */ + void reset() { + std::unique_lock lock(mtx_); + events_.clear(); + called_count_ = 0; + } + + /* + * Blocks the calling thread until the callback event queue becomes empty or timeout + * occurs. Returns false on timeout. + */ + bool waitUntilEmpty(int timeout_seconds) { + std::unique_lock lock(mtx_); + cv_.wait_for(lock, std::chrono::seconds(timeout_seconds), + [&] { return events_.empty(); }); + return !events_.empty(); + } + + private: + CallbackQueue(const CallbackQueue&) = delete; + CallbackQueue& operator=(const CallbackQueue&) = delete; + + mutable std::recursive_mutex mtx_; + std::condition_variable_any cv_; + std::deque events_; + int called_count_; + }; + /* * SetUpGnssCallback: * Set GnssCallback and verify the result. @@ -205,30 +276,19 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase { sp gnss_hal_; // GNSS HAL to call into sp gnss_cb_; // Primary callback interface - // TODO: make these variables thread-safe. - /* Count of calls to set the following items, and the latest item (used by - * test.) - */ - int info_called_count_; - int capabilities_called_count_; - int measurement_corrections_capabilities_called_count_; - int location_called_count_; - int measurement_called_count_; - int name_called_count_; - IGnssCallback_1_0::GnssSystemInfo last_info_; uint32_t last_capabilities_; uint32_t last_measurement_corrections_capabilities_; GnssLocation_2_0 last_location_; - IGnssMeasurementCallback_2_0::GnssData last_measurement_; android::hardware::hidl_string last_name_; - list> list_vec_gnss_sv_info_; - - private: - std::mutex mtx_; - std::condition_variable cv_; - int notify_count_; + CallbackQueue info_cbq_; + CallbackQueue name_cbq_; + CallbackQueue top_hal_capabilities_cbq_; + CallbackQueue measurement_corrections_capabilities_cbq_; + CallbackQueue measurement_cbq_; + CallbackQueue location_cbq_; + CallbackQueue> sv_info_cbq_; }; #endif // GNSS_HAL_TEST_H_ diff --git a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp index 7c253b0645..009f43d0c3 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp +++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp @@ -199,10 +199,11 @@ TEST_F(GnssHalTest, TestGnssMeasurementFields) { ASSERT_TRUE(result.isOk()); EXPECT_EQ(result, IGnssMeasurement_1_0::GnssMeasurementStatus::SUCCESS); - wait(kFirstGnssMeasurementTimeoutSeconds); - EXPECT_EQ(measurement_called_count_, 1); - ASSERT_TRUE(last_measurement_.measurements.size() > 0); - for (auto measurement : last_measurement_.measurements) { + IGnssMeasurementCallback_2_0::GnssData lastMeasurement; + ASSERT_TRUE(measurement_cbq_.retrieve(lastMeasurement, kFirstGnssMeasurementTimeoutSeconds)); + EXPECT_EQ(measurement_cbq_.calledCount(), 1); + ASSERT_TRUE(lastMeasurement.measurements.size() > 0); + for (auto measurement : lastMeasurement.measurements) { // Verify CodeType is valid. ASSERT_NE(measurement.codeType, ""); @@ -305,8 +306,10 @@ TEST_F(GnssHalTest, TestGnssMeasurementCorrectionsCapabilities) { iMeasurementCorrections->setCallback(iMeasurementCorrectionsCallback); const int kMeasurementCorrectionsCapabilitiesTimeoutSeconds = 5; - waitForMeasurementCorrectionsCapabilities(kMeasurementCorrectionsCapabilitiesTimeoutSeconds); - ASSERT_TRUE(measurement_corrections_capabilities_called_count_ > 0); + measurement_corrections_capabilities_cbq_.retrieve( + last_measurement_corrections_capabilities_, + kMeasurementCorrectionsCapabilitiesTimeoutSeconds); + ASSERT_TRUE(measurement_corrections_capabilities_cbq_.calledCount() > 0); using Capabilities = IMeasurementCorrectionsCallback::Capabilities; ASSERT_TRUE((last_measurement_corrections_capabilities_ & (Capabilities::LOS_SATS | Capabilities::EXCESS_PATH_LENGTH)) != 0); @@ -333,8 +336,11 @@ TEST_F(GnssHalTest, TestGnssMeasurementCorrections) { iMeasurementCorrections->setCallback(iMeasurementCorrectionsCallback); const int kMeasurementCorrectionsCapabilitiesTimeoutSeconds = 5; - waitForMeasurementCorrectionsCapabilities(kMeasurementCorrectionsCapabilitiesTimeoutSeconds); - ASSERT_TRUE(measurement_corrections_capabilities_called_count_ > 0); + measurement_corrections_capabilities_cbq_.retrieve( + last_measurement_corrections_capabilities_, + kMeasurementCorrectionsCapabilitiesTimeoutSeconds); + ASSERT_TRUE(measurement_corrections_capabilities_cbq_.calledCount() > 0); + // Set a mock MeasurementCorrections. auto result = iMeasurementCorrections->setCorrections(Utils::getMockMeasurementCorrections()); ASSERT_TRUE(result.isOk()); @@ -365,16 +371,17 @@ TEST_F(GnssHalTest, TestGnssDataElapsedRealtimeFlags) { ASSERT_TRUE(result.isOk()); EXPECT_EQ(result, IGnssMeasurement_1_0::GnssMeasurementStatus::SUCCESS); - wait(kFirstGnssMeasurementTimeoutSeconds); - EXPECT_EQ(measurement_called_count_, 1); + IGnssMeasurementCallback_2_0::GnssData lastMeasurement; + ASSERT_TRUE(measurement_cbq_.retrieve(lastMeasurement, kFirstGnssMeasurementTimeoutSeconds)); + EXPECT_EQ(measurement_cbq_.calledCount(), 1); - ASSERT_TRUE((int)last_measurement_.elapsedRealtime.flags <= + ASSERT_TRUE((int)lastMeasurement.elapsedRealtime.flags <= (int)(ElapsedRealtimeFlags::HAS_TIMESTAMP_NS | ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS)); // We expect a non-zero timestamp when set. - if (last_measurement_.elapsedRealtime.flags & ElapsedRealtimeFlags::HAS_TIMESTAMP_NS) { - ASSERT_TRUE(last_measurement_.elapsedRealtime.timestampNs != 0); + if (lastMeasurement.elapsedRealtime.flags & ElapsedRealtimeFlags::HAS_TIMESTAMP_NS) { + ASSERT_TRUE(lastMeasurement.elapsedRealtime.timestampNs != 0); } iGnssMeasurement->close(); From 2690a27d8daca31a49b0d643eba5e541bb099ea6 Mon Sep 17 00:00:00 2001 From: Anil Admal Date: Sat, 4 May 2019 22:37:31 -0700 Subject: [PATCH 648/718] Fix wait/notify logic in GNSS VTS 2.0 test cases (part 2) Addresses follow up code review comments after merge of ag/7324643. Fixes: 131869042 Test: atest VtsHalGnssV2_0TargetTest Change-Id: I0177ee60c5edfb6855ce6a1d45b8805166a33cf2 --- gnss/2.0/vts/functional/gnss_hal_test.cpp | 89 ++++---- gnss/2.0/vts/functional/gnss_hal_test.h | 194 +++++++++--------- .../vts/functional/gnss_hal_test_cases.cpp | 58 +++--- 3 files changed, 166 insertions(+), 175 deletions(-) diff --git a/gnss/2.0/vts/functional/gnss_hal_test.cpp b/gnss/2.0/vts/functional/gnss_hal_test.cpp index febd0f1d13..a9f858cc9d 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test.cpp +++ b/gnss/2.0/vts/functional/gnss_hal_test.cpp @@ -23,8 +23,6 @@ using ::android::hardware::gnss::common::Utils; // Implementations for the main test class for GNSS HAL -GnssHalTest::GnssHalTest() {} - void GnssHalTest::SetUp() { gnss_hal_ = ::testing::VtsHalHidlTargetTestBase::getService( GnssHidlEnvironment::Instance()->getServiceName()); @@ -36,25 +34,15 @@ void GnssHalTest::SetUp() { void GnssHalTest::TearDown() { if (gnss_hal_ != nullptr) { gnss_hal_->cleanup(); + gnss_hal_ = nullptr; } - int unprocessedEventsCount = measurement_cbq_.size() + location_cbq_.size(); - if (unprocessedEventsCount > 0) { - ALOGW("%d unprocessed callbacks discarded", unprocessedEventsCount); - } - - // Reset all callback event queues. - info_cbq_.reset(); - name_cbq_.reset(); - top_hal_capabilities_cbq_.reset(); - measurement_corrections_capabilities_cbq_.reset(); - measurement_cbq_.reset(); - location_cbq_.reset(); - sv_info_cbq_.reset(); + // Set to nullptr to destruct the callback event queues and warn of any unprocessed events. + gnss_cb_ = nullptr; } void GnssHalTest::SetUpGnssCallback() { - gnss_cb_ = new GnssCallback(*this); + gnss_cb_ = new GnssCallback(); ASSERT_NE(gnss_cb_, nullptr); auto result = gnss_hal_->setCallback_2_0(gnss_cb_); @@ -68,13 +56,13 @@ void GnssHalTest::SetUpGnssCallback() { /* * All capabilities, name and systemInfo callbacks should trigger */ - EXPECT_TRUE(top_hal_capabilities_cbq_.retrieve(last_capabilities_, TIMEOUT_SEC)); - EXPECT_TRUE(info_cbq_.retrieve(last_info_, TIMEOUT_SEC)); - EXPECT_TRUE(name_cbq_.retrieve(last_name_, TIMEOUT_SEC)); + EXPECT_TRUE(gnss_cb_->capabilities_cbq_.retrieve(gnss_cb_->last_capabilities_, TIMEOUT_SEC)); + EXPECT_TRUE(gnss_cb_->info_cbq_.retrieve(gnss_cb_->last_info_, TIMEOUT_SEC)); + EXPECT_TRUE(gnss_cb_->name_cbq_.retrieve(gnss_cb_->last_name_, TIMEOUT_SEC)); - EXPECT_EQ(top_hal_capabilities_cbq_.calledCount(), 1); - EXPECT_EQ(info_cbq_.calledCount(), 1); - EXPECT_EQ(name_cbq_.calledCount(), 1); + EXPECT_EQ(gnss_cb_->capabilities_cbq_.calledCount(), 1); + EXPECT_EQ(gnss_cb_->info_cbq_.calledCount(), 1); + EXPECT_EQ(gnss_cb_->name_cbq_.calledCount(), 1); } void GnssHalTest::StopAndClearLocations() { @@ -88,8 +76,9 @@ void GnssHalTest::StopAndClearLocations() { * the last reply for final startup messages to arrive (esp. system * info.) */ - location_cbq_.waitUntilEmpty(TIMEOUT_SEC); - location_cbq_.reset(); + while (gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_, TIMEOUT_SEC)) { + } + gnss_cb_->location_cbq_.reset(); } void GnssHalTest::SetPositionMode(const int min_interval_msec, const bool low_power_mode) { @@ -116,20 +105,22 @@ bool GnssHalTest::StartAndCheckFirstLocation() { */ const int kFirstGnssLocationTimeoutSeconds = 75; - EXPECT_TRUE(location_cbq_.retrieve(last_location_, kFirstGnssLocationTimeoutSeconds)); - int locationCalledCount = location_cbq_.calledCount(); + EXPECT_TRUE(gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_, + kFirstGnssLocationTimeoutSeconds)); + int locationCalledCount = gnss_cb_->location_cbq_.calledCount(); EXPECT_EQ(locationCalledCount, 1); if (locationCalledCount > 0) { // don't require speed on first fix - CheckLocation(last_location_, false); + CheckLocation(gnss_cb_->last_location_, false); return true; } return false; } void GnssHalTest::CheckLocation(const GnssLocation_2_0& location, bool check_speed) { - const bool check_more_accuracies = (info_cbq_.calledCount() > 0 && last_info_.yearOfHw >= 2017); + const bool check_more_accuracies = + (gnss_cb_->info_cbq_.calledCount() > 0 && gnss_cb_->last_info_.yearOfHw >= 2017); Utils::checkLocation(location.v1_0, check_speed, check_more_accuracies); } @@ -144,39 +135,47 @@ void GnssHalTest::StartAndCheckLocations(int count) { EXPECT_TRUE(StartAndCheckFirstLocation()); for (int i = 1; i < count; i++) { - EXPECT_TRUE(location_cbq_.retrieve(last_location_, kLocationTimeoutSubsequentSec)); - int locationCalledCount = location_cbq_.calledCount(); + EXPECT_TRUE(gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_, + kLocationTimeoutSubsequentSec)); + int locationCalledCount = gnss_cb_->location_cbq_.calledCount(); EXPECT_EQ(locationCalledCount, i + 1); // Don't cause confusion by checking details if no location yet if (locationCalledCount > 0) { // Should be more than 1 location by now, but if not, still don't check first fix speed - CheckLocation(last_location_, locationCalledCount > 1); + CheckLocation(gnss_cb_->last_location_, locationCalledCount > 1); } } } +GnssHalTest::GnssCallback::GnssCallback() + : info_cbq_("system_info"), + name_cbq_("name"), + capabilities_cbq_("capabilities"), + location_cbq_("location"), + sv_info_cbq_("sv_info") {} + Return GnssHalTest::GnssCallback::gnssSetSystemInfoCb( const IGnssCallback_1_0::GnssSystemInfo& info) { ALOGI("Info received, year %d", info.yearOfHw); - parent_.info_cbq_.store(info); + info_cbq_.store(info); return Void(); } Return GnssHalTest::GnssCallback::gnssSetCapabilitesCb(uint32_t capabilities) { ALOGI("Capabilities received %d", capabilities); - parent_.top_hal_capabilities_cbq_.store(capabilities); + capabilities_cbq_.store(capabilities); return Void(); } Return GnssHalTest::GnssCallback::gnssSetCapabilitiesCb_2_0(uint32_t capabilities) { ALOGI("Capabilities (v2.0) received %d", capabilities); - parent_.top_hal_capabilities_cbq_.store(capabilities); + capabilities_cbq_.store(capabilities); return Void(); } Return GnssHalTest::GnssCallback::gnssNameCb(const android::hardware::hidl_string& name) { ALOGI("Name received: %s", name.c_str()); - parent_.name_cbq_.store(name); + name_cbq_.store(name); return Void(); } @@ -193,7 +192,7 @@ Return GnssHalTest::GnssCallback::gnssLocationCb_2_0(const GnssLocation_2_ } Return GnssHalTest::GnssCallback::gnssLocationCbImpl(const GnssLocation_2_0& location) { - parent_.location_cbq_.store(location); + location_cbq_.store(location); return Void(); } @@ -202,23 +201,23 @@ Return GnssHalTest::GnssCallback::gnssSvStatusCb(const IGnssCallback_1_0:: return Void(); } +Return GnssHalTest::GnssCallback::gnssSvStatusCb_2_0( + const hidl_vec& svInfoList) { + ALOGI("gnssSvStatusCb_2_0. Size = %d", (int)svInfoList.size()); + sv_info_cbq_.store(svInfoList); + return Void(); +} + Return GnssHalTest::GnssMeasurementCallback::gnssMeasurementCb_2_0( const IGnssMeasurementCallback_2_0::GnssData& data) { ALOGD("GnssMeasurement received. Size = %d", (int)data.measurements.size()); - parent_.measurement_cbq_.store(data); + measurement_cbq_.store(data); return Void(); } Return GnssHalTest::GnssMeasurementCorrectionsCallback::setCapabilitiesCb( uint32_t capabilities) { ALOGI("GnssMeasurementCorrectionsCallback capabilities received %d", capabilities); - parent_.measurement_corrections_capabilities_cbq_.store(capabilities); - return Void(); -} - -Return GnssHalTest::GnssCallback::gnssSvStatusCb_2_0( - const hidl_vec& svInfoList) { - ALOGI("gnssSvStatusCb_2_0. Size = %d", (int)svInfoList.size()); - parent_.sv_info_cbq_.store(svInfoList); + capabilities_cbq_.store(capabilities); return Void(); } diff --git a/gnss/2.0/vts/functional/gnss_hal_test.h b/gnss/2.0/vts/functional/gnss_hal_test.h index 8e440ff956..05e37d33f7 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test.h +++ b/gnss/2.0/vts/functional/gnss_hal_test.h @@ -65,27 +65,61 @@ class GnssHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { // The main test class for GNSS HAL. class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase { public: - GnssHalTest(); - virtual void SetUp() override; virtual void TearDown() override; - /* Used as a mechanism to inform the test that a callback has occurred */ - void notify(); + /* Producer/consumer queue for storing/retrieving callback events from GNSS HAL */ + template + class CallbackQueue { + public: + CallbackQueue(const std::string& name) : name_(name), called_count_(0){}; + ~CallbackQueue() { reset(); } - /* Test code calls this function to wait for a callback */ - std::cv_status wait(int timeout_seconds); + /* Adds callback event to the end of the queue. */ + void store(const T& event); - std::cv_status waitForMeasurementCorrectionsCapabilities(int timeout_seconds); + /* + * Removes the callack event at the front of the queue, stores it in event parameter + * and returns true. Returns false on timeout and event is not populated. + */ + bool retrieve(T& event, int timeout_seconds); + + /* Returns the number of events pending to be retrieved from the callback event queue. */ + int size() const; + + /* Returns the number of callback events received since last reset(). */ + int calledCount() const; + + /* Clears the callback event queue and resets the calledCount() to 0. */ + void reset(); + + private: + CallbackQueue(const CallbackQueue&) = delete; + CallbackQueue& operator=(const CallbackQueue&) = delete; + + std::string name_; + int called_count_; + mutable std::recursive_mutex mtx_; + std::condition_variable_any cv_; + std::deque events_; + }; /* Callback class for data & Event. */ class GnssCallback : public IGnssCallback_2_0 { public: - GnssHalTest& parent_; + IGnssCallback_1_0::GnssSystemInfo last_info_; + android::hardware::hidl_string last_name_; + uint32_t last_capabilities_; + GnssLocation_2_0 last_location_; - GnssCallback(GnssHalTest& parent) : parent_(parent){}; + CallbackQueue info_cbq_; + CallbackQueue name_cbq_; + CallbackQueue capabilities_cbq_; + CallbackQueue location_cbq_; + CallbackQueue> sv_info_cbq_; + GnssCallback(); virtual ~GnssCallback() = default; // Dummy callback handlers @@ -126,8 +160,9 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase { /* Callback class for GnssMeasurement. */ class GnssMeasurementCallback : public IGnssMeasurementCallback_2_0 { public: - GnssHalTest& parent_; - GnssMeasurementCallback(GnssHalTest& parent) : parent_(parent){}; + CallbackQueue measurement_cbq_; + + GnssMeasurementCallback() : measurement_cbq_("measurement"){}; virtual ~GnssMeasurementCallback() = default; // Methods from V1_0::IGnssMeasurementCallback follow. @@ -147,85 +182,16 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase { /* Callback class for GnssMeasurementCorrections. */ class GnssMeasurementCorrectionsCallback : public IMeasurementCorrectionsCallback { public: - GnssHalTest& parent_; - GnssMeasurementCorrectionsCallback(GnssHalTest& parent) : parent_(parent){}; + uint32_t last_capabilities_; + CallbackQueue capabilities_cbq_; + + GnssMeasurementCorrectionsCallback() : capabilities_cbq_("capabilities"){}; virtual ~GnssMeasurementCorrectionsCallback() = default; // Methods from V1_0::IMeasurementCorrectionsCallback follow. Return setCapabilitiesCb(uint32_t capabilities) override; }; - /* Producer/consumer queue for storing/retrieving callback events from GNSS HAL */ - template - class CallbackQueue { - public: - CallbackQueue() : called_count_(0){}; - - /* Adds callback event to the end of the queue. */ - void store(const T& event) { - std::unique_lock lock(mtx_); - events_.push_back(event); - ++called_count_; - lock.unlock(); - cv_.notify_all(); - } - - /* - * Removes the callack event at the front of the queue, stores it in event parameter - * and returns true. If the timeout occurs waiting for callback event, returns false. - */ - bool retrieve(T& event, int timeout_seconds) { - std::unique_lock lock(mtx_); - cv_.wait_for(lock, std::chrono::seconds(timeout_seconds), - [&] { return !events_.empty(); }); - if (events_.empty()) { - return false; - } - event = events_.front(); - events_.pop_front(); - return true; - } - - /* Returns the number of events pending to be retrieved from the callback event queue. */ - int size() const { - std::unique_lock lock(mtx_); - return events_.size(); - } - - /* Returns the number of callback events received since last reset(). */ - int calledCount() const { - std::unique_lock lock(mtx_); - return called_count_; - } - - /* Clears the callback event queue and resets the calledCount() to 0. */ - void reset() { - std::unique_lock lock(mtx_); - events_.clear(); - called_count_ = 0; - } - - /* - * Blocks the calling thread until the callback event queue becomes empty or timeout - * occurs. Returns false on timeout. - */ - bool waitUntilEmpty(int timeout_seconds) { - std::unique_lock lock(mtx_); - cv_.wait_for(lock, std::chrono::seconds(timeout_seconds), - [&] { return events_.empty(); }); - return !events_.empty(); - } - - private: - CallbackQueue(const CallbackQueue&) = delete; - CallbackQueue& operator=(const CallbackQueue&) = delete; - - mutable std::recursive_mutex mtx_; - std::condition_variable_any cv_; - std::deque events_; - int called_count_; - }; - /* * SetUpGnssCallback: * Set GnssCallback and verify the result. @@ -274,21 +240,51 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase { void SetPositionMode(const int min_interval_msec, const bool low_power_mode); sp gnss_hal_; // GNSS HAL to call into - sp gnss_cb_; // Primary callback interface - - IGnssCallback_1_0::GnssSystemInfo last_info_; - uint32_t last_capabilities_; - uint32_t last_measurement_corrections_capabilities_; - GnssLocation_2_0 last_location_; - android::hardware::hidl_string last_name_; - - CallbackQueue info_cbq_; - CallbackQueue name_cbq_; - CallbackQueue top_hal_capabilities_cbq_; - CallbackQueue measurement_corrections_capabilities_cbq_; - CallbackQueue measurement_cbq_; - CallbackQueue location_cbq_; - CallbackQueue> sv_info_cbq_; + sp gnss_cb_; // Primary callback interface }; +template +void GnssHalTest::CallbackQueue::store(const T& event) { + std::unique_lock lock(mtx_); + events_.push_back(event); + ++called_count_; + lock.unlock(); + cv_.notify_all(); +} + +template +bool GnssHalTest::CallbackQueue::retrieve(T& event, int timeout_seconds) { + std::unique_lock lock(mtx_); + cv_.wait_for(lock, std::chrono::seconds(timeout_seconds), [&] { return !events_.empty(); }); + if (events_.empty()) { + return false; + } + event = events_.front(); + events_.pop_front(); + return true; +} + +template +int GnssHalTest::CallbackQueue::size() const { + std::unique_lock lock(mtx_); + return events_.size(); +} + +template +int GnssHalTest::CallbackQueue::calledCount() const { + std::unique_lock lock(mtx_); + return called_count_; +} + +template +void GnssHalTest::CallbackQueue::reset() { + std::unique_lock lock(mtx_); + if (!events_.empty()) { + ALOGW("%u unprocessed events discarded in callback queue %s", (unsigned int)events_.size(), + name_.c_str()); + } + events_.clear(); + called_count_ = 0; +} + #endif // GNSS_HAL_TEST_H_ diff --git a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp index 009f43d0c3..155afd614b 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp +++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp @@ -54,10 +54,10 @@ using android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl; TEST_F(GnssHalTest, SetupTeardownCreateCleanup) {} /* - * TestGnssMeasurementCallback: + * TestGnssMeasurementExtension: * Gets the GnssMeasurementExtension and verifies that it returns an actual extension. */ -TEST_F(GnssHalTest, TestGnssMeasurementCallback) { +TEST_F(GnssHalTest, TestGnssMeasurementExtension) { auto gnssMeasurement_2_0 = gnss_hal_->getExtensionGnssMeasurement_2_0(); auto gnssMeasurement_1_1 = gnss_hal_->getExtensionGnssMeasurement_1_1(); auto gnssMeasurement_1_0 = gnss_hal_->getExtensionGnssMeasurement(); @@ -193,15 +193,15 @@ TEST_F(GnssHalTest, TestGnssMeasurementFields) { return; } - sp callback = new GnssMeasurementCallback(*this); - + sp callback = new GnssMeasurementCallback(); auto result = iGnssMeasurement->setCallback_2_0(callback, /* enableFullTracking= */ true); ASSERT_TRUE(result.isOk()); EXPECT_EQ(result, IGnssMeasurement_1_0::GnssMeasurementStatus::SUCCESS); IGnssMeasurementCallback_2_0::GnssData lastMeasurement; - ASSERT_TRUE(measurement_cbq_.retrieve(lastMeasurement, kFirstGnssMeasurementTimeoutSeconds)); - EXPECT_EQ(measurement_cbq_.calledCount(), 1); + ASSERT_TRUE(callback->measurement_cbq_.retrieve(lastMeasurement, + kFirstGnssMeasurementTimeoutSeconds)); + EXPECT_EQ(callback->measurement_cbq_.calledCount(), 1); ASSERT_TRUE(lastMeasurement.measurements.size() > 0); for (auto measurement : lastMeasurement.measurements) { // Verify CodeType is valid. @@ -291,7 +291,7 @@ TEST_F(GnssHalTest, TestGnssVisibilityControlExtension) { * capability flag is set. */ TEST_F(GnssHalTest, TestGnssMeasurementCorrectionsCapabilities) { - if (!(last_capabilities_ & IGnssCallback::Capabilities::MEASUREMENT_CORRECTIONS)) { + if (!(gnss_cb_->last_capabilities_ & IGnssCallback::Capabilities::MEASUREMENT_CORRECTIONS)) { return; } @@ -301,17 +301,15 @@ TEST_F(GnssHalTest, TestGnssMeasurementCorrectionsCapabilities) { ASSERT_NE(iMeasurementCorrections, nullptr); // Setup measurement corrections callback. - sp iMeasurementCorrectionsCallback = - new GnssMeasurementCorrectionsCallback(*this); - iMeasurementCorrections->setCallback(iMeasurementCorrectionsCallback); + sp callback = new GnssMeasurementCorrectionsCallback(); + iMeasurementCorrections->setCallback(callback); const int kMeasurementCorrectionsCapabilitiesTimeoutSeconds = 5; - measurement_corrections_capabilities_cbq_.retrieve( - last_measurement_corrections_capabilities_, - kMeasurementCorrectionsCapabilitiesTimeoutSeconds); - ASSERT_TRUE(measurement_corrections_capabilities_cbq_.calledCount() > 0); + callback->capabilities_cbq_.retrieve(callback->last_capabilities_, + kMeasurementCorrectionsCapabilitiesTimeoutSeconds); + ASSERT_TRUE(callback->capabilities_cbq_.calledCount() > 0); using Capabilities = IMeasurementCorrectionsCallback::Capabilities; - ASSERT_TRUE((last_measurement_corrections_capabilities_ & + ASSERT_TRUE((callback->last_capabilities_ & (Capabilities::LOS_SATS | Capabilities::EXCESS_PATH_LENGTH)) != 0); } @@ -321,7 +319,7 @@ TEST_F(GnssHalTest, TestGnssMeasurementCorrectionsCapabilities) { * gnss.measurement_corrections@1.0::IMeasurementCorrections interface by invoking a method. */ TEST_F(GnssHalTest, TestGnssMeasurementCorrections) { - if (!(last_capabilities_ & IGnssCallback::Capabilities::MEASUREMENT_CORRECTIONS)) { + if (!(gnss_cb_->last_capabilities_ & IGnssCallback::Capabilities::MEASUREMENT_CORRECTIONS)) { return; } @@ -331,15 +329,13 @@ TEST_F(GnssHalTest, TestGnssMeasurementCorrections) { sp iMeasurementCorrections = measurementCorrections; ASSERT_NE(iMeasurementCorrections, nullptr); - sp iMeasurementCorrectionsCallback = - new GnssMeasurementCorrectionsCallback(*this); - iMeasurementCorrections->setCallback(iMeasurementCorrectionsCallback); + sp callback = new GnssMeasurementCorrectionsCallback(); + iMeasurementCorrections->setCallback(callback); const int kMeasurementCorrectionsCapabilitiesTimeoutSeconds = 5; - measurement_corrections_capabilities_cbq_.retrieve( - last_measurement_corrections_capabilities_, - kMeasurementCorrectionsCapabilitiesTimeoutSeconds); - ASSERT_TRUE(measurement_corrections_capabilities_cbq_.calledCount() > 0); + callback->capabilities_cbq_.retrieve(callback->last_capabilities_, + kMeasurementCorrectionsCapabilitiesTimeoutSeconds); + ASSERT_TRUE(callback->capabilities_cbq_.calledCount() > 0); // Set a mock MeasurementCorrections. auto result = iMeasurementCorrections->setCorrections(Utils::getMockMeasurementCorrections()); @@ -365,15 +361,15 @@ TEST_F(GnssHalTest, TestGnssDataElapsedRealtimeFlags) { return; } - sp callback = new GnssMeasurementCallback(*this); - + sp callback = new GnssMeasurementCallback(); auto result = iGnssMeasurement->setCallback_2_0(callback, /* enableFullTracking= */ true); ASSERT_TRUE(result.isOk()); EXPECT_EQ(result, IGnssMeasurement_1_0::GnssMeasurementStatus::SUCCESS); IGnssMeasurementCallback_2_0::GnssData lastMeasurement; - ASSERT_TRUE(measurement_cbq_.retrieve(lastMeasurement, kFirstGnssMeasurementTimeoutSeconds)); - EXPECT_EQ(measurement_cbq_.calledCount(), 1); + ASSERT_TRUE(callback->measurement_cbq_.retrieve(lastMeasurement, + kFirstGnssMeasurementTimeoutSeconds)); + EXPECT_EQ(callback->measurement_cbq_.calledCount(), 1); ASSERT_TRUE((int)lastMeasurement.elapsedRealtime.flags <= (int)(ElapsedRealtimeFlags::HAS_TIMESTAMP_NS | @@ -390,13 +386,13 @@ TEST_F(GnssHalTest, TestGnssDataElapsedRealtimeFlags) { TEST_F(GnssHalTest, TestGnssLocationElapsedRealtime) { StartAndCheckFirstLocation(); - ASSERT_TRUE((int)last_location_.elapsedRealtime.flags <= + ASSERT_TRUE((int)gnss_cb_->last_location_.elapsedRealtime.flags <= (int)(ElapsedRealtimeFlags::HAS_TIMESTAMP_NS | ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS)); // We expect a non-zero timestamp when set. - if (last_location_.elapsedRealtime.flags & ElapsedRealtimeFlags::HAS_TIMESTAMP_NS) { - ASSERT_TRUE(last_location_.elapsedRealtime.timestampNs != 0); + if (gnss_cb_->last_location_.elapsedRealtime.flags & ElapsedRealtimeFlags::HAS_TIMESTAMP_NS) { + ASSERT_TRUE(gnss_cb_->last_location_.elapsedRealtime.timestampNs != 0); } StopAndClearLocations(); @@ -405,7 +401,7 @@ TEST_F(GnssHalTest, TestGnssLocationElapsedRealtime) { // This test only verify that injectBestLocation_2_0 does not crash. TEST_F(GnssHalTest, TestInjectBestLocation_2_0) { StartAndCheckFirstLocation(); - gnss_hal_->injectBestLocation_2_0(last_location_); + gnss_hal_->injectBestLocation_2_0(gnss_cb_->last_location_); StopAndClearLocations(); } From efe7621dac44b99b2f742365e9263dbdaf55093d Mon Sep 17 00:00:00 2001 From: Valerie Hau Date: Tue, 7 May 2019 08:06:05 -0700 Subject: [PATCH 649/718] Fix setLayerCursorPosition Test Bug: 131181758 Test: build, boot, VtsHalGraphicsComposerV2_1TargetTest Change-Id: I70f4f8f64c16ce45eba70c2e47d3fa2913034eba --- .../VtsHalGraphicsComposerV2_1TargetTest.cpp | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp index 4018aeafd6..a4a41c16ce 100644 --- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp +++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp @@ -850,10 +850,37 @@ TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_CURSOR_POSITION) { ASSERT_NO_FATAL_FAILURE(layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); + auto handle = allocate(); + ASSERT_NE(nullptr, handle); + IComposerClient::Rect displayFrame{0, 0, mDisplayWidth, mDisplayHeight}; + mWriter->selectDisplay(mPrimaryDisplay); mWriter->selectLayer(layer); + mWriter->setLayerBuffer(0, handle, -1); + mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE); + mWriter->setLayerDisplayFrame(displayFrame); + mWriter->setLayerPlaneAlpha(1); + mWriter->setLayerSourceCrop({0, 0, (float)mDisplayWidth, (float)mDisplayHeight}); + mWriter->setLayerTransform(static_cast(0)); + mWriter->setLayerVisibleRegion(std::vector(1, displayFrame)); + mWriter->setLayerZOrder(10); + mWriter->setLayerBlendMode(IComposerClient::BlendMode::NONE); + mWriter->setLayerSurfaceDamage(std::vector(1, displayFrame)); + mWriter->setLayerDataspace(Dataspace::UNKNOWN); + mWriter->validateDisplay(); + + execute(); + if (mReader->mCompositionChanges.size() != 0) { + GTEST_SUCCEED() << "Composition change requested, skipping test"; + return; + } + mWriter->presentDisplay(); + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->setLayerCursorPosition(1, 1); mWriter->setLayerCursorPosition(0, 0); + mWriter->validateDisplay(); + mWriter->presentDisplay(); execute(); } From ddb770f0e4eb5cec88a8124a29c318b5e925bffe Mon Sep 17 00:00:00 2001 From: Michael Butler Date: Thu, 2 May 2019 18:16:13 -0700 Subject: [PATCH 650/718] NNAPI: validate that FmqResultDatum padding is 0 -- VTS FmqResultDatum::OperandInformation has padding that may not be initialized by an NN HAL service instance. This CL adds a validation check to ensure that services are not leaking uninitialized data through this padding region. Bug: 131356202 Test: mma Test: atest VtsHalNeuralnetworksV1_2TargetTest (for ValidationTest with sample-all) Test: altered sample-driver to randomly set a padding byte to 1; the new validation test successfully failed the test Change-Id: I6661945392b3fc773493d8f2f306f29b39e09bab --- .../1.2/vts/functional/ValidateBurst.cpp | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/neuralnetworks/1.2/vts/functional/ValidateBurst.cpp b/neuralnetworks/1.2/vts/functional/ValidateBurst.cpp index 386c141f80..8bb4934833 100644 --- a/neuralnetworks/1.2/vts/functional/ValidateBurst.cpp +++ b/neuralnetworks/1.2/vts/functional/ValidateBurst.cpp @@ -25,6 +25,7 @@ #include "Utils.h" #include +#include namespace android { namespace hardware { @@ -317,12 +318,91 @@ static void validateBurstFmqLength(const sp& preparedModel, } } +static bool isSanitized(const FmqResultDatum& datum) { + using Discriminator = FmqResultDatum::hidl_discriminator; + + // check to ensure the padding values in the returned + // FmqResultDatum::OperandInformation are initialized to 0 + if (datum.getDiscriminator() == Discriminator::operandInformation) { + static_assert( + offsetof(FmqResultDatum::OperandInformation, isSufficient) == 0, + "unexpected value for offset of FmqResultDatum::OperandInformation::isSufficient"); + static_assert( + sizeof(FmqResultDatum::OperandInformation::isSufficient) == 1, + "unexpected value for size of FmqResultDatum::OperandInformation::isSufficient"); + static_assert(offsetof(FmqResultDatum::OperandInformation, numberOfDimensions) == 4, + "unexpected value for offset of " + "FmqResultDatum::OperandInformation::numberOfDimensions"); + static_assert(sizeof(FmqResultDatum::OperandInformation::numberOfDimensions) == 4, + "unexpected value for size of " + "FmqResultDatum::OperandInformation::numberOfDimensions"); + static_assert(sizeof(FmqResultDatum::OperandInformation) == 8, + "unexpected value for size of " + "FmqResultDatum::OperandInformation"); + + constexpr size_t paddingOffset = + offsetof(FmqResultDatum::OperandInformation, isSufficient) + + sizeof(FmqResultDatum::OperandInformation::isSufficient); + constexpr size_t paddingSize = + offsetof(FmqResultDatum::OperandInformation, numberOfDimensions) - paddingOffset; + + FmqResultDatum::OperandInformation initialized{}; + std::memset(&initialized, 0, sizeof(initialized)); + + const char* initializedPaddingStart = + reinterpret_cast(&initialized) + paddingOffset; + const char* datumPaddingStart = + reinterpret_cast(&datum.operandInformation()) + paddingOffset; + + return std::memcmp(datumPaddingStart, initializedPaddingStart, paddingSize) == 0; + } + + // there are no other padding initialization checks required, so return true + // for any sum-type that isn't FmqResultDatum::OperandInformation + return true; +} + +static void validateBurstSanitized(const sp& preparedModel, + const std::vector& requests) { + // create burst + std::unique_ptr sender; + std::unique_ptr receiver; + sp callback = new ExecutionBurstCallback(); + sp context; + ASSERT_NO_FATAL_FAILURE(createBurst(preparedModel, callback, &sender, &receiver, &context)); + ASSERT_NE(nullptr, sender.get()); + ASSERT_NE(nullptr, receiver.get()); + ASSERT_NE(nullptr, context.get()); + + // validate each request + for (const Request& request : requests) { + // load memory into callback slots + std::vector keys; + keys.reserve(request.pools.size()); + std::transform(request.pools.begin(), request.pools.end(), std::back_inserter(keys), + [](const auto& pool) { return reinterpret_cast(&pool); }); + const std::vector slots = callback->getSlots(request.pools, keys); + + // send valid request + ASSERT_TRUE(sender->send(request, MeasureTiming::YES, slots)); + + // receive valid result + auto serialized = receiver->getPacketBlocking(); + ASSERT_TRUE(serialized.has_value()); + + // sanitize result + ASSERT_TRUE(std::all_of(serialized->begin(), serialized->end(), isSanitized)) + << "The result serialized data is not properly sanitized"; + } +} + ///////////////////////////// ENTRY POINT ////////////////////////////////// void ValidationTest::validateBurst(const sp& preparedModel, const std::vector& requests) { ASSERT_NO_FATAL_FAILURE(validateBurstSerialization(preparedModel, requests)); ASSERT_NO_FATAL_FAILURE(validateBurstFmqLength(preparedModel, requests)); + ASSERT_NO_FATAL_FAILURE(validateBurstSanitized(preparedModel, requests)); } } // namespace functional From 804857176a54c56c8553b557e8d470ee8aef7005 Mon Sep 17 00:00:00 2001 From: Valerie Hau Date: Tue, 7 May 2019 11:45:06 -0700 Subject: [PATCH 651/718] Fix getDisplayCapabilitiesBasic VTS test Old test checked error code when calling getBrightnessSupport in the getDisplayCapabilitiesBasic test. However, it is possible that the function is not implemented (UNSUPPORTED). We want to return normally and use the returned supported boolean to check this instead. Bug: 132043561, 132056857 Test: VtsHalGraphicsComposerV2_3TargetTest Change-Id: I94f8f39ba9129c4a8d939a5385538db3489c46b9 --- graphics/composer/2.3/utils/vts/ComposerVts.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/graphics/composer/2.3/utils/vts/ComposerVts.cpp b/graphics/composer/2.3/utils/vts/ComposerVts.cpp index b7632097ab..d4f5b3a4de 100644 --- a/graphics/composer/2.3/utils/vts/ComposerVts.cpp +++ b/graphics/composer/2.3/utils/vts/ComposerVts.cpp @@ -192,10 +192,8 @@ Error ComposerClient::getDisplayCapabilities( bool ComposerClient::getDisplayBrightnessSupport(Display display) { bool support = false; - mClient->getDisplayBrightnessSupport(display, [&](const auto& error, const auto& tmpSupport) { - ASSERT_EQ(Error::NONE, error) << "failed to get brightness support"; - support = tmpSupport; - }); + mClient->getDisplayBrightnessSupport( + display, [&](const auto& /*error*/, const auto& tmpSupport) { support = tmpSupport; }); return support; } From 185d7a4b1f23a58d718f7a770957e979e0dda52d Mon Sep 17 00:00:00 2001 From: Valerie Hau Date: Tue, 7 May 2019 12:35:49 -0700 Subject: [PATCH 652/718] Fix setLayerCursorPosition test Set composition type to Cursor Bug: 132057336, 131181758 Test: VtsHalGraphicsComposerV2_1TargetTest Change-Id: I03ae799358abcdbd0a1c39a13d30d76aa7712004 --- .../2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp index a4a41c16ce..3c408b7d7b 100644 --- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp +++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp @@ -857,7 +857,7 @@ TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_CURSOR_POSITION) { mWriter->selectDisplay(mPrimaryDisplay); mWriter->selectLayer(layer); mWriter->setLayerBuffer(0, handle, -1); - mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE); + mWriter->setLayerCompositionType(IComposerClient::Composition::CURSOR); mWriter->setLayerDisplayFrame(displayFrame); mWriter->setLayerPlaneAlpha(1); mWriter->setLayerSourceCrop({0, 0, (float)mDisplayWidth, (float)mDisplayHeight}); From 0a1ad962bb47ba190954d931630de6f0c04a8f11 Mon Sep 17 00:00:00 2001 From: Michael Butler Date: Tue, 30 Apr 2019 13:51:24 -0700 Subject: [PATCH 653/718] Follow up CL to "Add validation tests for NNAPI Burst serialized format" Bug: 129779280 Bug: 129157135 Test: mma Test: atest NeuralNetworksTest_static Test: atest VtsHalNeuralnetworksV1_0TargetTest (with sample-all) Test: atest VtsHalNeuralnetworksV1_1TargetTest (with sample-all) Test: atest VtsHalNeuralnetworksV1_2TargetTest (with sample-all) Change-Id: I6bd088f01c051a76561c0ecf9bbf878bb21c5754 --- .../1.0/vts/functional/ValidateRequest.cpp | 57 +------- .../vts/functional/VtsHalNeuralnetworks.cpp | 65 ++++++++- .../1.0/vts/functional/VtsHalNeuralnetworks.h | 3 +- .../1.1/vts/functional/ValidateRequest.cpp | 58 +------- .../vts/functional/VtsHalNeuralnetworks.cpp | 66 ++++++++- .../1.1/vts/functional/VtsHalNeuralnetworks.h | 3 +- .../1.2/vts/functional/ValidateBurst.cpp | 134 +++++++++--------- .../vts/functional/VtsHalNeuralnetworks.cpp | 7 +- .../1.2/vts/functional/VtsHalNeuralnetworks.h | 2 +- 9 files changed, 206 insertions(+), 189 deletions(-) diff --git a/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp index 72a500783f..f0c93b7b54 100644 --- a/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp +++ b/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp @@ -34,7 +34,6 @@ namespace vts { namespace functional { using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback; -using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback; using ::android::hidl::memory::V1_0::IMemory; using test_helper::for_all; using test_helper::MixedTyped; @@ -42,53 +41,6 @@ using test_helper::MixedTypedExample; ///////////////////////// UTILITY FUNCTIONS ///////////////////////// -static void createPreparedModel(const sp& device, const V1_0::Model& model, - sp* preparedModel) { - ASSERT_NE(nullptr, preparedModel); - - // see if service can handle model - bool fullySupportsModel = false; - Return supportedOpsLaunchStatus = device->getSupportedOperations( - model, [&fullySupportsModel](ErrorStatus status, const hidl_vec& supported) { - ASSERT_EQ(ErrorStatus::NONE, status); - ASSERT_NE(0ul, supported.size()); - fullySupportsModel = - std::all_of(supported.begin(), supported.end(), [](bool valid) { return valid; }); - }); - ASSERT_TRUE(supportedOpsLaunchStatus.isOk()); - - // launch prepare model - sp preparedModelCallback = new PreparedModelCallback(); - ASSERT_NE(nullptr, preparedModelCallback.get()); - Return prepareLaunchStatus = device->prepareModel(model, preparedModelCallback); - ASSERT_TRUE(prepareLaunchStatus.isOk()); - ASSERT_EQ(ErrorStatus::NONE, static_cast(prepareLaunchStatus)); - - // retrieve prepared model - preparedModelCallback->wait(); - ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus(); - *preparedModel = preparedModelCallback->getPreparedModel(); - - // The getSupportedOperations call returns a list of operations that are - // guaranteed not to fail if prepareModel is called, and - // 'fullySupportsModel' is true i.f.f. the entire model is guaranteed. - // If a driver has any doubt that it can prepare an operation, it must - // return false. So here, if a driver isn't sure if it can support an - // operation, but reports that it successfully prepared the model, the test - // can continue. - if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) { - ASSERT_EQ(nullptr, preparedModel->get()); - LOG(INFO) << "NN VTS: Unable to test Request validation because vendor service cannot " - "prepare model that it does not support."; - std::cout << "[ ] Unable to test Request validation because vendor service " - "cannot prepare model that it does not support." - << std::endl; - return; - } - ASSERT_EQ(ErrorStatus::NONE, prepareReturnStatus); - ASSERT_NE(nullptr, preparedModel->get()); -} - // Primary validation function. This function will take a valid request, apply a // mutation to it to invalidate the request, then pass it to interface calls // that use the request. Note that the request here is passed by value, and any @@ -237,15 +189,8 @@ std::vector createRequests(const std::vector& exampl return requests; } -void ValidationTest::validateRequests(const V1_0::Model& model, +void ValidationTest::validateRequests(const sp& preparedModel, const std::vector& requests) { - // create IPreparedModel - sp preparedModel; - ASSERT_NO_FATAL_FAILURE(createPreparedModel(device, model, &preparedModel)); - if (preparedModel == nullptr) { - return; - } - // validate each request for (const Request& request : requests) { removeInputTest(preparedModel, request); diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp index 31638c425f..aee2f8549b 100644 --- a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp +++ b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp @@ -18,6 +18,10 @@ #include "VtsHalNeuralnetworks.h" +#include + +#include "Callbacks.h" + namespace android { namespace hardware { namespace neuralnetworks { @@ -25,6 +29,55 @@ namespace V1_0 { namespace vts { namespace functional { +using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback; + +static void createPreparedModel(const sp& device, const V1_0::Model& model, + sp* preparedModel) { + ASSERT_NE(nullptr, preparedModel); + + // see if service can handle model + bool fullySupportsModel = false; + Return supportedOpsLaunchStatus = device->getSupportedOperations( + model, [&fullySupportsModel](ErrorStatus status, const hidl_vec& supported) { + ASSERT_EQ(ErrorStatus::NONE, status); + ASSERT_NE(0ul, supported.size()); + fullySupportsModel = std::all_of(supported.begin(), supported.end(), + [](bool valid) { return valid; }); + }); + ASSERT_TRUE(supportedOpsLaunchStatus.isOk()); + + // launch prepare model + sp preparedModelCallback = new PreparedModelCallback(); + ASSERT_NE(nullptr, preparedModelCallback.get()); + Return prepareLaunchStatus = device->prepareModel(model, preparedModelCallback); + ASSERT_TRUE(prepareLaunchStatus.isOk()); + ASSERT_EQ(ErrorStatus::NONE, static_cast(prepareLaunchStatus)); + + // retrieve prepared model + preparedModelCallback->wait(); + ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus(); + *preparedModel = preparedModelCallback->getPreparedModel(); + + // The getSupportedOperations call returns a list of operations that are + // guaranteed not to fail if prepareModel is called, and + // 'fullySupportsModel' is true i.f.f. the entire model is guaranteed. + // If a driver has any doubt that it can prepare an operation, it must + // return false. So here, if a driver isn't sure if it can support an + // operation, but reports that it successfully prepared the model, the test + // can continue. + if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) { + ASSERT_EQ(nullptr, preparedModel->get()); + LOG(INFO) << "NN VTS: Unable to test Request validation because vendor service cannot " + "prepare model that it does not support."; + std::cout << "[ ] Unable to test Request validation because vendor service " + "cannot prepare model that it does not support." + << std::endl; + return; + } + ASSERT_EQ(ErrorStatus::NONE, prepareReturnStatus); + ASSERT_NE(nullptr, preparedModel->get()); +} + // A class for test environment setup NeuralnetworksHidlEnvironment::NeuralnetworksHidlEnvironment() {} @@ -68,9 +121,17 @@ void NeuralnetworksHidlTest::TearDown() { ::testing::VtsHalHidlTargetTestBase::TearDown(); } -void ValidationTest::validateEverything(const Model& model, const std::vector& request) { +void ValidationTest::validateEverything(const Model& model, const std::vector& requests) { validateModel(model); - validateRequests(model, request); + + // create IPreparedModel + sp preparedModel; + ASSERT_NO_FATAL_FAILURE(createPreparedModel(device, model, &preparedModel)); + if (preparedModel == nullptr) { + return; + } + + validateRequests(preparedModel, requests); } } // namespace functional diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h index 559d678ea1..22285be38e 100644 --- a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h +++ b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h @@ -67,7 +67,8 @@ class ValidationTest : public NeuralnetworksHidlTest { private: void validateModel(const Model& model); - void validateRequests(const Model& model, const std::vector& request); + void validateRequests(const sp& preparedModel, + const std::vector& requests); }; // Tag for the generated tests diff --git a/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp index 5225bf7581..f4adbabf93 100644 --- a/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp +++ b/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp @@ -34,7 +34,6 @@ namespace vts { namespace functional { using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback; -using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback; using ::android::hidl::memory::V1_0::IMemory; using test_helper::for_all; using test_helper::MixedTyped; @@ -42,54 +41,6 @@ using test_helper::MixedTypedExample; ///////////////////////// UTILITY FUNCTIONS ///////////////////////// -static void createPreparedModel(const sp& device, const V1_1::Model& model, - sp* preparedModel) { - ASSERT_NE(nullptr, preparedModel); - - // see if service can handle model - bool fullySupportsModel = false; - Return supportedOpsLaunchStatus = device->getSupportedOperations_1_1( - model, [&fullySupportsModel](ErrorStatus status, const hidl_vec& supported) { - ASSERT_EQ(ErrorStatus::NONE, status); - ASSERT_NE(0ul, supported.size()); - fullySupportsModel = - std::all_of(supported.begin(), supported.end(), [](bool valid) { return valid; }); - }); - ASSERT_TRUE(supportedOpsLaunchStatus.isOk()); - - // launch prepare model - sp preparedModelCallback = new PreparedModelCallback(); - ASSERT_NE(nullptr, preparedModelCallback.get()); - Return prepareLaunchStatus = device->prepareModel_1_1( - model, ExecutionPreference::FAST_SINGLE_ANSWER, preparedModelCallback); - ASSERT_TRUE(prepareLaunchStatus.isOk()); - ASSERT_EQ(ErrorStatus::NONE, static_cast(prepareLaunchStatus)); - - // retrieve prepared model - preparedModelCallback->wait(); - ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus(); - *preparedModel = preparedModelCallback->getPreparedModel(); - - // The getSupportedOperations_1_1 call returns a list of operations that are - // guaranteed not to fail if prepareModel_1_1 is called, and - // 'fullySupportsModel' is true i.f.f. the entire model is guaranteed. - // If a driver has any doubt that it can prepare an operation, it must - // return false. So here, if a driver isn't sure if it can support an - // operation, but reports that it successfully prepared the model, the test - // can continue. - if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) { - ASSERT_EQ(nullptr, preparedModel->get()); - LOG(INFO) << "NN VTS: Unable to test Request validation because vendor service cannot " - "prepare model that it does not support."; - std::cout << "[ ] Unable to test Request validation because vendor service " - "cannot prepare model that it does not support." - << std::endl; - return; - } - ASSERT_EQ(ErrorStatus::NONE, prepareReturnStatus); - ASSERT_NE(nullptr, preparedModel->get()); -} - // Primary validation function. This function will take a valid request, apply a // mutation to it to invalidate the request, then pass it to interface calls // that use the request. Note that the request here is passed by value, and any @@ -238,15 +189,8 @@ std::vector createRequests(const std::vector& exampl return requests; } -void ValidationTest::validateRequests(const V1_1::Model& model, +void ValidationTest::validateRequests(const sp& preparedModel, const std::vector& requests) { - // create IPreparedModel - sp preparedModel; - ASSERT_NO_FATAL_FAILURE(createPreparedModel(device, model, &preparedModel)); - if (preparedModel == nullptr) { - return; - } - // validate each request for (const Request& request : requests) { removeInputTest(preparedModel, request); diff --git a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp index 11fa693ddc..08069f2e7a 100644 --- a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp +++ b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp @@ -18,6 +18,10 @@ #include "VtsHalNeuralnetworks.h" +#include + +#include "Callbacks.h" + namespace android { namespace hardware { namespace neuralnetworks { @@ -25,6 +29,56 @@ namespace V1_1 { namespace vts { namespace functional { +using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback; + +static void createPreparedModel(const sp& device, const V1_1::Model& model, + sp* preparedModel) { + ASSERT_NE(nullptr, preparedModel); + + // see if service can handle model + bool fullySupportsModel = false; + Return supportedOpsLaunchStatus = device->getSupportedOperations_1_1( + model, [&fullySupportsModel](ErrorStatus status, const hidl_vec& supported) { + ASSERT_EQ(ErrorStatus::NONE, status); + ASSERT_NE(0ul, supported.size()); + fullySupportsModel = std::all_of(supported.begin(), supported.end(), + [](bool valid) { return valid; }); + }); + ASSERT_TRUE(supportedOpsLaunchStatus.isOk()); + + // launch prepare model + sp preparedModelCallback = new PreparedModelCallback(); + ASSERT_NE(nullptr, preparedModelCallback.get()); + Return prepareLaunchStatus = device->prepareModel_1_1( + model, ExecutionPreference::FAST_SINGLE_ANSWER, preparedModelCallback); + ASSERT_TRUE(prepareLaunchStatus.isOk()); + ASSERT_EQ(ErrorStatus::NONE, static_cast(prepareLaunchStatus)); + + // retrieve prepared model + preparedModelCallback->wait(); + ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus(); + *preparedModel = preparedModelCallback->getPreparedModel(); + + // The getSupportedOperations_1_1 call returns a list of operations that are + // guaranteed not to fail if prepareModel_1_1 is called, and + // 'fullySupportsModel' is true i.f.f. the entire model is guaranteed. + // If a driver has any doubt that it can prepare an operation, it must + // return false. So here, if a driver isn't sure if it can support an + // operation, but reports that it successfully prepared the model, the test + // can continue. + if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) { + ASSERT_EQ(nullptr, preparedModel->get()); + LOG(INFO) << "NN VTS: Unable to test Request validation because vendor service cannot " + "prepare model that it does not support."; + std::cout << "[ ] Unable to test Request validation because vendor service " + "cannot prepare model that it does not support." + << std::endl; + return; + } + ASSERT_EQ(ErrorStatus::NONE, prepareReturnStatus); + ASSERT_NE(nullptr, preparedModel->get()); +} + // A class for test environment setup NeuralnetworksHidlEnvironment::NeuralnetworksHidlEnvironment() {} @@ -68,9 +122,17 @@ void NeuralnetworksHidlTest::TearDown() { ::testing::VtsHalHidlTargetTestBase::TearDown(); } -void ValidationTest::validateEverything(const Model& model, const std::vector& request) { +void ValidationTest::validateEverything(const Model& model, const std::vector& requests) { validateModel(model); - validateRequests(model, request); + + // create IPreparedModel + sp preparedModel; + ASSERT_NO_FATAL_FAILURE(createPreparedModel(device, model, &preparedModel)); + if (preparedModel == nullptr) { + return; + } + + validateRequests(preparedModel, requests); } } // namespace functional diff --git a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h index cea2b54c2d..f3f587b866 100644 --- a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h +++ b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h @@ -76,7 +76,8 @@ class ValidationTest : public NeuralnetworksHidlTest { private: void validateModel(const Model& model); - void validateRequests(const Model& model, const std::vector& request); + void validateRequests(const sp& preparedModel, + const std::vector& requests); }; // Tag for the generated tests diff --git a/neuralnetworks/1.2/vts/functional/ValidateBurst.cpp b/neuralnetworks/1.2/vts/functional/ValidateBurst.cpp index 8bb4934833..8c6391e815 100644 --- a/neuralnetworks/1.2/vts/functional/ValidateBurst.cpp +++ b/neuralnetworks/1.2/vts/functional/ValidateBurst.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Android Open Source Project + * Copyright (C) 2019 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. @@ -39,7 +39,13 @@ using ::android::nn::RequestChannelSender; using ::android::nn::ResultChannelReceiver; using ExecutionBurstCallback = ::android::nn::ExecutionBurstController::ExecutionBurstCallback; +// This constant value represents the length of an FMQ that is large enough to +// return a result from a burst execution for all of the generated test cases. constexpr size_t kExecutionBurstChannelLength = 1024; + +// This constant value represents a length of an FMQ that is not large enough +// to return a result from a burst execution for some of the generated test +// cases. constexpr size_t kExecutionBurstChannelSmallLength = 8; ///////////////////////// UTILITY FUNCTIONS ///////////////////////// @@ -51,7 +57,8 @@ static bool badTiming(Timing timing) { static void createBurst(const sp& preparedModel, const sp& callback, std::unique_ptr* sender, std::unique_ptr* receiver, - sp* context) { + sp* context, + size_t resultChannelLength = kExecutionBurstChannelLength) { ASSERT_NE(nullptr, preparedModel.get()); ASSERT_NE(nullptr, sender); ASSERT_NE(nullptr, receiver); @@ -61,7 +68,7 @@ static void createBurst(const sp& preparedModel, const sp& preparedModel, const sp& preparedModel, - std::shared_ptr* controller, size_t resultChannelLength) { + const sp& preparedModel, size_t resultChannelLength, + std::shared_ptr* controller) { ASSERT_NE(nullptr, preparedModel.get()); ASSERT_NE(nullptr, controller); // create FMQ objects - auto [fmqRequestChannel, fmqRequestDescriptor] = - RequestChannelSender::create(kExecutionBurstChannelLength, /*blocking=*/true); - auto [fmqResultChannel, fmqResultDescriptor] = - ResultChannelReceiver::create(resultChannelLength, /*blocking=*/true); - ASSERT_NE(nullptr, fmqRequestChannel.get()); - ASSERT_NE(nullptr, fmqResultChannel.get()); - ASSERT_NE(nullptr, fmqRequestDescriptor); - ASSERT_NE(nullptr, fmqResultDescriptor); - - // configure burst + std::unique_ptr sender; + std::unique_ptr receiver; sp callback = new ExecutionBurstCallback(); - ErrorStatus errorStatus; - sp burstContext; - const Return ret = preparedModel->configureExecutionBurst( - callback, *fmqRequestDescriptor, *fmqResultDescriptor, - [&errorStatus, &burstContext](ErrorStatus status, const sp& context) { - errorStatus = status; - burstContext = context; - }); - ASSERT_TRUE(ret.isOk()); - ASSERT_EQ(ErrorStatus::NONE, errorStatus); - ASSERT_NE(nullptr, burstContext.get()); + sp context; + ASSERT_NO_FATAL_FAILURE(createBurst(preparedModel, callback, &sender, &receiver, &context, + resultChannelLength)); + ASSERT_NE(nullptr, sender.get()); + ASSERT_NE(nullptr, receiver.get()); + ASSERT_NE(nullptr, context.get()); // return values - *controller = std::make_shared( - std::move(fmqRequestChannel), std::move(fmqResultChannel), burstContext, callback); + *controller = std::make_shared(std::move(sender), std::move(receiver), + context, callback); } // Primary validation function. This function will take a valid serialized @@ -139,7 +133,7 @@ static void validate(RequestChannelSender* sender, ResultChannelReceiver* receiv SCOPED_TRACE(message); // send invalid packet - sender->sendPacket(serialized); + ASSERT_TRUE(sender->sendPacket(serialized)); // receive error auto results = receiver->getBlocking(); @@ -150,27 +144,34 @@ static void validate(RequestChannelSender* sender, ResultChannelReceiver* receiv EXPECT_TRUE(badTiming(timing)); } -static std::vector createUniqueDatum() { +// For validation, valid packet entries are mutated to invalid packet entries, +// or invalid packet entries are inserted into valid packets. This function +// creates pre-set invalid packet entries for convenience. +static std::vector createBadRequestPacketEntries() { const FmqRequestDatum::PacketInformation packetInformation = { /*.packetSize=*/10, /*.numberOfInputOperands=*/10, /*.numberOfOutputOperands=*/10, /*.numberOfPools=*/10}; const FmqRequestDatum::OperandInformation operandInformation = { /*.hasNoValue=*/false, /*.location=*/{}, /*.numberOfDimensions=*/10}; const int32_t invalidPoolIdentifier = std::numeric_limits::max(); - std::vector unique(7); - unique[0].packetInformation(packetInformation); - unique[1].inputOperandInformation(operandInformation); - unique[2].inputOperandDimensionValue(0); - unique[3].outputOperandInformation(operandInformation); - unique[4].outputOperandDimensionValue(0); - unique[5].poolIdentifier(invalidPoolIdentifier); - unique[6].measureTiming(MeasureTiming::YES); - return unique; + std::vector bad(7); + bad[0].packetInformation(packetInformation); + bad[1].inputOperandInformation(operandInformation); + bad[2].inputOperandDimensionValue(0); + bad[3].outputOperandInformation(operandInformation); + bad[4].outputOperandDimensionValue(0); + bad[5].poolIdentifier(invalidPoolIdentifier); + bad[6].measureTiming(MeasureTiming::YES); + return bad; } -static const std::vector& getUniqueDatum() { - static const std::vector unique = createUniqueDatum(); - return unique; +// For validation, valid packet entries are mutated to invalid packet entries, +// or invalid packet entries are inserted into valid packets. This function +// retrieves pre-set invalid packet entries for convenience. This function +// caches these data so they can be reused on subsequent validation checks. +static const std::vector& getBadRequestPacketEntries() { + static const std::vector bad = createBadRequestPacketEntries(); + return bad; } ///////////////////////// REMOVE DATUM //////////////////////////////////// @@ -190,7 +191,7 @@ static void removeDatumTest(RequestChannelSender* sender, ResultChannelReceiver* static void addDatumTest(RequestChannelSender* sender, ResultChannelReceiver* receiver, const std::vector& serialized) { - const std::vector& extra = getUniqueDatum(); + const std::vector& extra = getBadRequestPacketEntries(); for (size_t index = 0; index <= serialized.size(); ++index) { for (size_t type = 0; type < extra.size(); ++type) { const std::string message = "addDatum: added datum type " + std::to_string(type) + @@ -209,17 +210,17 @@ static bool interestingCase(const FmqRequestDatum& lhs, const FmqRequestDatum& r using Discriminator = FmqRequestDatum::hidl_discriminator; const bool differentValues = (lhs != rhs); - const bool sameSumType = (lhs.getDiscriminator() == rhs.getDiscriminator()); + const bool sameDiscriminator = (lhs.getDiscriminator() == rhs.getDiscriminator()); const auto discriminator = rhs.getDiscriminator(); const bool isDimensionValue = (discriminator == Discriminator::inputOperandDimensionValue || discriminator == Discriminator::outputOperandDimensionValue); - return differentValues && !(sameSumType && isDimensionValue); + return differentValues && !(sameDiscriminator && isDimensionValue); } static void mutateDatumTest(RequestChannelSender* sender, ResultChannelReceiver* receiver, const std::vector& serialized) { - const std::vector& change = getUniqueDatum(); + const std::vector& change = getBadRequestPacketEntries(); for (size_t index = 0; index < serialized.size(); ++index) { for (size_t type = 0; type < change.size(); ++type) { if (interestingCase(serialized[index], change[type])) { @@ -252,17 +253,17 @@ static void validateBurstSerialization(const sp& preparedModel, // validate each request for (const Request& request : requests) { // load memory into callback slots - std::vector keys(request.pools.size()); - for (size_t i = 0; i < keys.size(); ++i) { - keys[i] = reinterpret_cast(&request.pools[i]); - } + std::vector keys; + keys.reserve(request.pools.size()); + std::transform(request.pools.begin(), request.pools.end(), std::back_inserter(keys), + [](const auto& pool) { return reinterpret_cast(&pool); }); const std::vector slots = callback->getSlots(request.pools, keys); // ensure slot std::numeric_limits::max() doesn't exist (for // subsequent slot validation testing) - const auto maxElement = std::max_element(slots.begin(), slots.end()); - ASSERT_NE(slots.end(), maxElement); - ASSERT_NE(std::numeric_limits::max(), *maxElement); + ASSERT_TRUE(std::all_of(slots.begin(), slots.end(), [](int32_t slot) { + return slot != std::numeric_limits::max(); + })); // serialize the request const auto serialized = ::android::nn::serialize(request, MeasureTiming::YES, slots); @@ -274,18 +275,20 @@ static void validateBurstSerialization(const sp& preparedModel, } } +// This test validates that when the Result message size exceeds length of the +// result FMQ, the service instance gracefully fails and returns an error. static void validateBurstFmqLength(const sp& preparedModel, const std::vector& requests) { // create regular burst std::shared_ptr controllerRegular; - ASSERT_NO_FATAL_FAILURE(createBurstWithResultChannelLength(preparedModel, &controllerRegular, - kExecutionBurstChannelLength)); + ASSERT_NO_FATAL_FAILURE(createBurstWithResultChannelLength( + preparedModel, kExecutionBurstChannelLength, &controllerRegular)); ASSERT_NE(nullptr, controllerRegular.get()); // create burst with small output channel std::shared_ptr controllerSmall; - ASSERT_NO_FATAL_FAILURE(createBurstWithResultChannelLength(preparedModel, &controllerSmall, - kExecutionBurstChannelSmallLength)); + ASSERT_NO_FATAL_FAILURE(createBurstWithResultChannelLength( + preparedModel, kExecutionBurstChannelSmallLength, &controllerSmall)); ASSERT_NE(nullptr, controllerSmall.get()); // validate each request @@ -297,24 +300,25 @@ static void validateBurstFmqLength(const sp& preparedModel, } // collect serialized result by running regular burst - const auto [status1, outputShapes1, timing1] = + const auto [statusRegular, outputShapesRegular, timingRegular] = controllerRegular->compute(request, MeasureTiming::NO, keys); - // skip test if synchronous output isn't useful + // skip test if regular burst output isn't useful for testing a failure + // caused by having too small of a length for the result FMQ const std::vector serialized = - ::android::nn::serialize(status1, outputShapes1, timing1); - if (status1 != ErrorStatus::NONE || + ::android::nn::serialize(statusRegular, outputShapesRegular, timingRegular); + if (statusRegular != ErrorStatus::NONE || serialized.size() <= kExecutionBurstChannelSmallLength) { continue; } // by this point, execution should fail because the result channel isn't // large enough to return the serialized result - const auto [status2, outputShapes2, timing2] = + const auto [statusSmall, outputShapesSmall, timingSmall] = controllerSmall->compute(request, MeasureTiming::NO, keys); - EXPECT_NE(ErrorStatus::NONE, status2); - EXPECT_EQ(0u, outputShapes2.size()); - EXPECT_TRUE(badTiming(timing2)); + EXPECT_NE(ErrorStatus::NONE, statusSmall); + EXPECT_EQ(0u, outputShapesSmall.size()); + EXPECT_TRUE(badTiming(timingSmall)); } } diff --git a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp index 93182f1da2..4ddefe8134 100644 --- a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp +++ b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp @@ -29,7 +29,6 @@ namespace V1_2 { namespace vts { namespace functional { -using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback; using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback; using HidlToken = hidl_array(Constant::BYTE_SIZE_OF_CACHE_TOKEN)>; using V1_1::ExecutionPreference; @@ -127,7 +126,7 @@ void NeuralnetworksHidlTest::TearDown() { ::testing::VtsHalHidlTargetTestBase::TearDown(); } -void ValidationTest::validateEverything(const Model& model, const std::vector& request) { +void ValidationTest::validateEverything(const Model& model, const std::vector& requests) { validateModel(model); // create IPreparedModel @@ -137,8 +136,8 @@ void ValidationTest::validateEverything(const Model& model, const std::vector getPreparedModel_1_2( diff --git a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h index 36e73a4fb0..8d1acbe03e 100644 --- a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h +++ b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h @@ -72,7 +72,7 @@ class NeuralnetworksHidlTest : public ::testing::VtsHalHidlTargetTestBase { // Tag for the validation tests class ValidationTest : public NeuralnetworksHidlTest { protected: - void validateEverything(const Model& model, const std::vector& request); + void validateEverything(const Model& model, const std::vector& requests); private: void validateModel(const Model& model); From 31703179a53f4f36e9ae67b3b28fe936a2995c20 Mon Sep 17 00:00:00 2001 From: Robert Shih Date: Thu, 18 Apr 2019 00:06:54 -0700 Subject: [PATCH 654/718] Add status for license starting in the future Bug:116738851 Test: vts-tradefed run commandAndExit -m VtsHalDrmV1_2Target Change-Id: Id5017e3ffa1fcf5aaad1815b59a425ac63f2e53e --- current.txt | 6 ++-- drm/1.2/IDrmPlugin.hal | 18 ++++++++++++ drm/1.2/IDrmPluginListener.hal | 18 ++++++++++++ drm/1.2/types.hal | 23 +++++++++++++++ drm/1.2/vts/functional/drm_hal_common.cpp | 15 +++++++++- drm/1.2/vts/functional/drm_hal_common.h | 20 ++++++++----- drm/1.2/vts/functional/drm_hal_test.cpp | 34 ++++++++++++++++++++++- 7 files changed, 122 insertions(+), 12 deletions(-) diff --git a/current.txt b/current.txt index 30839471c9..078a9dfde4 100644 --- a/current.txt +++ b/current.txt @@ -459,9 +459,9 @@ dffacdbe0bcf8443013de5bdc56a83479ad979d4919ed15a5585539f46091f07 android.hardwar 5b1f4a4fb88c239e07d76026467a1f2ee0d08f4d52c1805bd93bd7c05e3fe69c android.hardware.drm@1.2::ICryptoFactory 4895f98e9ef210e9acb01982f5d07b654538377e1404b8db5e19e7858835e9d8 android.hardware.drm@1.2::ICryptoPlugin 976116b9033b2c222b940109fdf0ffcc29b77cbe631ef6b4fcc2ad5ce8e605f7 android.hardware.drm@1.2::IDrmFactory -b2efccc6425085f84795a2ca15a09d9a81ffd02f9dc3d30ba21d1a59bdfa253f android.hardware.drm@1.2::IDrmPlugin -39ca9e88404b6c090f7650455a7ed3fdee9cce4e3a356c9d547f8ff02f2e7fc8 android.hardware.drm@1.2::IDrmPluginListener -f27baaa587bc3dd9b740cb6928ab812b9b7d105b5187663938aee578105f3c39 android.hardware.drm@1.2::types +8ef1caf921c3e83a00180f770e3b8e8ff65d8a5c806482e51aa45e6d55f1aec1 android.hardware.drm@1.2::IDrmPlugin +b778fcce93eb6294446a940e1bae0200da7bd97b91b91977be2dcd31ca58374f android.hardware.drm@1.2::IDrmPluginListener +564732cbfe5c0895cfbd2bdf84c3f2b0f760ea20f2237c0d388aaeeaef2dd0a9 android.hardware.drm@1.2::types 44480c912e4ab90b9ed17e56569cd5ca98413a8a2372efb028f4181204b6b73e android.hardware.fastboot@1.0::IFastboot 7b2989744e3c555292d4b5b829acd09a7b40f96ead62ce54174cd959503b64bb android.hardware.fastboot@1.0::types 7f460e795f5d1ed5e378935f98c6db4d39497de988aef1b4c2a4a07a6c400392 android.hardware.gnss@2.0::IAGnss diff --git a/drm/1.2/IDrmPlugin.hal b/drm/1.2/IDrmPlugin.hal index 7d266f4c7a..df09ccf910 100644 --- a/drm/1.2/IDrmPlugin.hal +++ b/drm/1.2/IDrmPlugin.hal @@ -226,4 +226,22 @@ interface IDrmPlugin extends @1.1::IDrmPlugin { * @param sessionId identifies the session the event originated from */ sendSessionLostState(SessionId sessionId); + + /** + * Send a keys change event to the listener. The keys change event + * indicates the status of each key in the session. Keys can be + * indicated as being usable, expired, outputnotallowed or statuspending. + * + * This method only differs from @1.0 version by the addition of new + * KeyStatusType(s) in keyStatusList. + * + * @param sessionId identifies the session the event originated from + * @param keyStatusList indicates the status for each key ID in the + * session. + * @param hasNewUsableKey indicates if the event includes at least one + * key that has become usable. + */ + sendKeysChange_1_2(SessionId sessionId, vec keyStatusList, + bool hasNewUsableKey); + }; diff --git a/drm/1.2/IDrmPluginListener.hal b/drm/1.2/IDrmPluginListener.hal index a6bd6c9ad4..e8cb91a9c7 100644 --- a/drm/1.2/IDrmPluginListener.hal +++ b/drm/1.2/IDrmPluginListener.hal @@ -36,4 +36,22 @@ interface IDrmPluginListener extends @1.0::IDrmPluginListener { * @param sessionId identifies the session that has been invalidated */ oneway sendSessionLostState(SessionId sessionId); + + /** + * Send a keys change event to the listener. The keys change event + * indicates the status of each key in the session. Keys can be + * indicated as being usable, expired, outputnotallowed or statuspending. + * + * This method only differs from @1.0 version by the addition of new + * KeyStatusType(s) in keyStatusList. + * + * @param sessionId identifies the session the event originated from + * @param keyStatusList indicates the status for each key ID in the + * session. + * @param hasNewUsableKey indicates if the event includes at least one + * key that has become usable. + */ + oneway sendKeysChange_1_2(SessionId sessionId, vec keyStatusList, + bool hasNewUsableKey); + }; diff --git a/drm/1.2/types.hal b/drm/1.2/types.hal index 28c8e67b79..87218a4209 100644 --- a/drm/1.2/types.hal +++ b/drm/1.2/types.hal @@ -16,6 +16,7 @@ package android.hardware.drm@1.2; +import @1.0::KeyStatusType; import @1.0::Status; import @1.1::HdcpLevel; @@ -93,3 +94,25 @@ enum HdcpLevel : @1.1::HdcpLevel { * set in methods that take a KeySetId as an input parameter. */ typedef vec KeySetId; + +enum KeyStatusType : @1.0::KeyStatusType { + /** + * The key is not yet usable to decrypt media because the start + * time is in the future. The key must become usable when + * its start time is reached. + */ + USABLEINFUTURE +}; + +/** + * Used by sendKeysChange_1_2 to report the usability status of each key to the + * app. + * + * This struct only differs from @1.0 version by the addition of new + * KeyStatusType(s). + * + */ +struct KeyStatus { + KeySetId keyId; + KeyStatusType type; +}; diff --git a/drm/1.2/vts/functional/drm_hal_common.cpp b/drm/1.2/vts/functional/drm_hal_common.cpp index b9a8425fc7..bfffbe8d22 100644 --- a/drm/1.2/vts/functional/drm_hal_common.cpp +++ b/drm/1.2/vts/functional/drm_hal_common.cpp @@ -56,6 +56,7 @@ namespace V1_2 { namespace vts { const char *kCallbackLostState = "LostState"; +const char *kCallbackKeysChange = "KeysChange"; drm_vts::VendorModules *DrmHalTest::gVendorModules = nullptr; @@ -64,7 +65,19 @@ drm_vts::VendorModules *DrmHalTest::gVendorModules = nullptr; */ Return DrmHalPluginListener::sendSessionLostState(const hidl_vec& sessionId) { - NotifyFromCallback(kCallbackLostState, sessionId); + ListenerEventArgs args; + args.sessionId = sessionId; + NotifyFromCallback(kCallbackLostState, args); + return Void(); +} + +Return DrmHalPluginListener::sendKeysChange_1_2(const hidl_vec& sessionId, + const hidl_vec& keyStatusList, bool hasNewUsableKey) { + ListenerEventArgs args; + args.sessionId = sessionId; + args.keyStatusList = keyStatusList; + args.hasNewUsableKey = hasNewUsableKey; + NotifyFromCallback(kCallbackKeysChange, args); return Void(); } diff --git a/drm/1.2/vts/functional/drm_hal_common.h b/drm/1.2/vts/functional/drm_hal_common.h index 1b95ddeea9..e34866474b 100644 --- a/drm/1.2/vts/functional/drm_hal_common.h +++ b/drm/1.2/vts/functional/drm_hal_common.h @@ -37,7 +37,7 @@ using ::android::hardware::drm::V1_0::EventType; using ::android::hardware::drm::V1_0::KeyedVector; -using ::android::hardware::drm::V1_0::KeyStatus; +using KeyStatusV1_0 = ::android::hardware::drm::V1_0::KeyStatus; using ::android::hardware::drm::V1_0::KeyType; using ::android::hardware::drm::V1_0::Mode; using ::android::hardware::drm::V1_0::Pattern; @@ -46,10 +46,6 @@ using ::android::hardware::drm::V1_0::SubSample; using ::android::hardware::drm::V1_1::ICryptoFactory; -using ::android::hardware::drm::V1_2::ICryptoPlugin; -using ::android::hardware::drm::V1_2::IDrmFactory; -using ::android::hardware::drm::V1_2::IDrmPlugin; -using ::android::hardware::drm::V1_2::IDrmPluginListener; using StatusV1_2 = ::android::hardware::drm::V1_2::Status; using ::android::hardware::hidl_array; @@ -166,9 +162,16 @@ class DrmHalClearkeyTest : public DrmHalTest { * Event Handling tests */ extern const char *kCallbackLostState; +extern const char *kCallbackKeysChange; + +struct ListenerEventArgs { + SessionId sessionId; + hidl_vec keyStatusList; + bool hasNewUsableKey; +}; class DrmHalPluginListener - : public ::testing::VtsHalHidlTargetCallbackBase, + : public ::testing::VtsHalHidlTargetCallbackBase, public IDrmPluginListener { public: DrmHalPluginListener() { @@ -183,10 +186,13 @@ public: int64_t) override { return Void(); } virtual Return sendKeysChange(const hidl_vec&, - const hidl_vec&, bool) override { return Void(); } + const hidl_vec&, bool) override { return Void(); } virtual Return sendSessionLostState(const hidl_vec& sessionId) override; + virtual Return sendKeysChange_1_2(const hidl_vec&, + const hidl_vec&, bool) override; + }; } // namespace vts diff --git a/drm/1.2/vts/functional/drm_hal_test.cpp b/drm/1.2/vts/functional/drm_hal_test.cpp index 252ebb95f5..37ecc25430 100644 --- a/drm/1.2/vts/functional/drm_hal_test.cpp +++ b/drm/1.2/vts/functional/drm_hal_test.cpp @@ -28,6 +28,8 @@ using ::android::hardware::drm::V1_1::KeyRequestType; using ::android::hardware::drm::V1_1::SecurityLevel; using ::android::hardware::drm::V1_2::HdcpLevel; using ::android::hardware::drm::V1_2::KeySetId; +using ::android::hardware::drm::V1_2::KeyStatus; +using ::android::hardware::drm::V1_2::KeyStatusType; using ::android::hardware::drm::V1_2::OfflineLicenseState; using ::android::hardware::drm::V1_2::vts::DrmHalClearkeyTest; @@ -35,6 +37,7 @@ using ::android::hardware::drm::V1_2::vts::DrmHalPluginListener; using ::android::hardware::drm::V1_2::vts::DrmHalTest; using ::android::hardware::drm::V1_2::vts::DrmHidlEnvironment; using ::android::hardware::drm::V1_2::vts::kCallbackLostState; +using ::android::hardware::drm::V1_2::vts::kCallbackKeysChange; using ::android::hardware::hidl_string; @@ -274,6 +277,35 @@ TEST_P(DrmHalTest, GetHdcpLevels) { EXPECT_OK(res); } +/** + * Simulate the plugin sending keys change and make sure + * the listener gets them. + */ +TEST_P(DrmHalTest, ListenerKeysChange) { + RETURN_IF_SKIPPED; + sp listener = new DrmHalPluginListener(); + auto res = drmPlugin->setListener(listener); + EXPECT_OK(res); + + auto sessionId = openSession(); + const hidl_vec keyStatusList = { + {{1}, KeyStatusType::USABLE}, + {{2}, KeyStatusType::EXPIRED}, + {{3}, KeyStatusType::OUTPUTNOTALLOWED}, + {{4}, KeyStatusType::STATUSPENDING}, + {{5}, KeyStatusType::INTERNALERROR}, + {{6}, KeyStatusType::USABLEINFUTURE}, + }; + + drmPlugin->sendKeysChange_1_2(sessionId, keyStatusList, true); + auto result = listener->WaitForCallback(kCallbackKeysChange); + EXPECT_TRUE(result.no_timeout); + EXPECT_TRUE(result.args); + EXPECT_EQ(sessionId, result.args->sessionId); + EXPECT_EQ(keyStatusList, result.args->keyStatusList); + closeSession(sessionId); +} + /** * CryptoPlugin Decrypt tests */ @@ -452,7 +484,7 @@ TEST_P(DrmHalClearkeyTest, SessionLostState) { auto result = listener->WaitForCallback(kCallbackLostState); EXPECT_TRUE(result.no_timeout); EXPECT_TRUE(result.args); - EXPECT_EQ(sessionId, *(result.args)); + EXPECT_EQ(sessionId, result.args->sessionId); } /** From e0537f09fba5b52c40c540341d69ff18e4179323 Mon Sep 17 00:00:00 2001 From: Lev Proleev Date: Wed, 8 May 2019 16:57:56 +0100 Subject: [PATCH 655/718] Fix LSTM documentation The documentation said that cell-to-input weights are required to be present when input-to-input weights, recurrent-to-input weights and input gate bias are present. This was incorrect since this weights can be omitted if peephole connections are not used even if all the other tensors are present. Another bug that is fixed in this change is that for output #0 the docs said "of shape [batch_size, num_units * 4] with CIFG, or [batch_size, num_units * 3] without CIFG" when in fact it is the opposite, i.e. "of shape [batch_size, num_units * 3] with CIFG, or [batch_size, num_units * 4] without CIFG." Existing CTS/VTS tests expect behaviour described in the fixed documentation. Existing CPU implementation is also compliant with the fixed documentation. Fix: 111842951 Test: mma Change-Id: Id011783e33672ae65dc6fe3784cb26feb832acf9 --- current.txt | 4 ++-- neuralnetworks/1.0/types.hal | 25 +++++++++++++------------ neuralnetworks/1.2/types.hal | 21 +++++++++++---------- 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/current.txt b/current.txt index 30839471c9..c51d38f79f 100644 --- a/current.txt +++ b/current.txt @@ -401,7 +401,7 @@ f7d7cb747dc01a9fdb2d39a80003b4d8df9be733d65f5842198802eb6209db69 android.hardwar 65a021fa89085b62fc96b2b6d3bef2f9103cf4d63379c68bc154fd9eef672852 android.hardware.health@1.0::types b7ecf29927055ec422ec44bf776223f07d79ad9f92ccf9becf167e62c2607e7a android.hardware.keymaster@4.0::IKeymasterDevice 574e8f1499436fb4075894dcae0b36682427956ecb114f17f1fe22d116a83c6b android.hardware.neuralnetworks@1.0::IPreparedModel -e75759b40a1c5f97b463b30aab91954012c9ea9e454dde308db853a56796e5a6 android.hardware.neuralnetworks@1.0::types +1e3576c07006d82ba5bc6ddbf87c101414d361c41afe7a82713750844c488725 android.hardware.neuralnetworks@1.0::types eb754b58c93e5591613208b4c972811288b0fa16a82430d602f107c91a908b22 android.hardware.neuralnetworks@1.1::types 1d4a5776614c08b5d794a5ec5ab04697260cbd4b3441d5935cd53ee71d19da02 android.hardware.radio@1.0::IRadioResponse ed9da80ec0c96991fd03f0a46107815d0e50f764656e49dba4980fa5c31d5bc3 android.hardware.radio@1.0::types @@ -515,7 +515,7 @@ b83317b66721241887d2770b5ae95fd5af1e77c5daa7530ecb08fae8892f2b43 android.hardwar 92714960d1a53fc2ec557302b41c7cc93d2636d8364a44bd0f85be0c92927ff8 android.hardware.neuralnetworks@1.2::IExecutionCallback 36e1064c869965dee533c537cefbe87e54db8bd8cd45be7e0e93e00e8a43863a android.hardware.neuralnetworks@1.2::IPreparedModel e1c734d1545e1a4ae749ff1dd9704a8e594c59aea7c8363159dc258e93e0df3b android.hardware.neuralnetworks@1.2::IPreparedModelCallback -e3b6176e3bf235c4e0e4e451b0166e396c7ee176cfe167c9147c3d46d7b34f0c android.hardware.neuralnetworks@1.2::types +d18bba0b6c8d2d1da3cfb52b14f556d2e04eb91551d97ee60a3524cf993a3e0e android.hardware.neuralnetworks@1.2::types cf7a4ba516a638f9b82a249c91fb603042c2d9ca43fd5aad9cf6c0401ed2a5d7 android.hardware.nfc@1.2::INfc abf98c2ae08bf765db54edc8068e36d52eb558cff6706b6fd7c18c65a1f3fc18 android.hardware.nfc@1.2::types 4cb252dc6372a874aef666b92a6e9529915aa187521a700f0789065c3c702ead android.hardware.power.stats@1.0::IPowerStats diff --git a/neuralnetworks/1.0/types.hal b/neuralnetworks/1.0/types.hal index b0a1c1aec2..02db063e18 100644 --- a/neuralnetworks/1.0/types.hal +++ b/neuralnetworks/1.0/types.hal @@ -858,20 +858,21 @@ enum OperationType : int32_t { * elements of the input matrices. * * The operation has the following independently optional inputs: + * * The cell-to-input weights (\f$W_{ci}\f$), cell-to-forget weights + * (\f$W_{cf}\f$) and cell-to-output weights (\f$W_{co}\f$) either all + * have values or neither of them have values (i.e., all set to null). If + * they have values, the peephole optimization is used. * * The input-to-input weights (\f$W_{xi}\f$), recurrent-to-input weights - * (\f$W_{hi}\f$), cell-to-input (\f$W_{ci}\f$) weights, and input gate - * bias (\f$b_i\f$) either all have values, or none of them have values - * (i.e., all set to null). If they have no values, coupling of input and - * forget gates (CIFG) is used, in which case the input gate (\f$i_t\f$) - * is calculated using the following equation instead. + * (\f$W_{hi}\f$) and input gate bias (\f$b_i\f$) either all have values, + * or none of them have values. If they have no values, coupling of input + * and forget gates (CIFG) is used, in which case the input gate + * (\f$i_t\f$) is calculated using the following equation instead. * \f{eqnarray*}{ * i_t = 1 - f_t * \f} - * * The cell-to-forget weights (\f$W_{cf}\f$) and cell-to-output weights - * (\f$W_{co}\f$) either both have values or neither of them have values. - * If they have values, the peephole optimization is used. Additionally, - * if CIFG is not used, cell-to-input weights (\f$W_{ci}\f$) is also - * required to have values for peephole optimization. + * In case peephole optimization is used and CIFG is not used + * cell-to-input (\f$W_{ci}\f$) weights must be present. Otherwise, the + * cell-to-input weights must have no value. * * The projection weights (\f$W_{proj}\f$) is required only for the * recurrent projection layer, and should otherwise have no value. * * The projection bias (\f$b_{proj}\f$) may (but not required to) have a @@ -984,8 +985,8 @@ enum OperationType : int32_t { * Outputs: * * 0: The scratch buffer. * A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape - * [batch_size, num_units * 4] with CIFG, or - * [batch_size, num_units * 3] without CIFG. + * [batch_size, num_units * 3] with CIFG, or + * [batch_size, num_units * 4] without CIFG. * * 1: The output state (out) (\f$h_t\f$). * A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape * [batch_size, output_size]. diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal index c2e8f22052..f368ce2cea 100644 --- a/neuralnetworks/1.2/types.hal +++ b/neuralnetworks/1.2/types.hal @@ -1177,20 +1177,21 @@ enum OperationType : int32_t { * https://arxiv.org/pdf/1607.06450.pdf * * The operation has the following independently optional inputs: + * * The cell-to-input weights (\f$W_{ci}\f$), cell-to-forget weights + * (\f$W_{cf}\f$) and cell-to-output weights (\f$W_{co}\f$) either all + * have values or neither of them have values (i.e., all set to null). If + * they have values, the peephole optimization is used. * * The input-to-input weights (\f$W_{xi}\f$), recurrent-to-input weights - * (\f$W_{hi}\f$), cell-to-input (\f$W_{ci}\f$) weights, and input gate - * bias (\f$b_i\f$) either all have values, or none of them have values - * (i.e., all set to null). If they have no values, coupling of input and - * forget gates (CIFG) is used, in which case the input gate (\f$i_t\f$) - * is calculated using the following equation instead. + * (\f$W_{hi}\f$) and input gate bias (\f$b_i\f$) either all have values, + * or none of them have values. If they have no values, coupling of input + * and forget gates (CIFG) is used, in which case the input gate + * (\f$i_t\f$) is calculated using the following equation instead. * \f{eqnarray*}{ * i_t = 1 - f_t * \f} - * * The cell-to-forget weights (\f$W_{cf}\f$) and cell-to-output weights - * (\f$W_{co}\f$) either both have values or neither of them have values. - * If they have values, the peephole optimization is used. Additionally, - * if CIFG is not used, cell-to-input weights (\f$W_{ci}\f$) is also - * required to have values for peephole optimization. + * In case peephole optimization is used and CIFG is not used + * cell-to-input (\f$W_{ci}\f$) weights must be present. Otherwise, the + * cell-to-input weights must have no value. * * The projection weights (\f$W_{proj}\f$) is required only for the * recurrent projection layer, and should otherwise have no value. * * The projection bias (\f$b_{proj}\f$) may (but not required to) have a From 35e7599eb22d4912756c6e09293cdf20cafebad2 Mon Sep 17 00:00:00 2001 From: Xusong Wang Date: Tue, 7 May 2019 12:57:49 -0700 Subject: [PATCH 656/718] Add quant8 variant of VTS CompilationCachingTest. Prior to this CL, the VTS compilation caching tests are using float32 models. However, there exists several drivers that only support QUANT8 operations, and most of the tests are simply skipped. This CL makes the CompilationCachingTest fixture parameterized that every test will run twice, with the first pass running with float32 models and the second pass running with quant8 models. Bug: 132112463 Test: 1.2 VTS with sample drivers Test: 1.2 VTS with test drivers that can read and write cache entries Change-Id: Iaf28065e46c2d90ab8b347b9848be1e6546cce86 --- .../functional/CompilationCachingTests.cpp | 191 ++++++++++++++---- 1 file changed, 148 insertions(+), 43 deletions(-) diff --git a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp index bf915603bc..4411b90097 100644 --- a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp +++ b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp @@ -45,9 +45,9 @@ using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCa using ::android::nn::allocateSharedMemory; using ::test_helper::MixedTypedExample; -namespace { +namespace float32_model { -// In frameworks/ml/nn/runtime/test/generated/, creates a hidl model of mobilenet. +// In frameworks/ml/nn/runtime/test/generated/, creates a hidl model of float32 mobilenet. #include "examples/mobilenet_224_gender_basic_fixed.example.cpp" #include "vts_models/mobilenet_224_gender_basic_fixed.model.cpp" @@ -55,6 +55,44 @@ namespace { [[maybe_unused]] auto dummy_createTestModel = createTestModel_dynamic_output_shape; [[maybe_unused]] auto dummy_get_examples = get_examples_dynamic_output_shape; +// MixedTypedExample is defined in frameworks/ml/nn/tools/test_generator/include/TestHarness.h. +// This function assumes the operation is always ADD. +std::vector getLargeModelExamples(uint32_t len) { + float outputValue = 1.0f + static_cast(len); + return {{.operands = { + // Input + {.operandDimensions = {{0, {1}}}, .float32Operands = {{0, {1.0f}}}}, + // Output + {.operandDimensions = {{0, {1}}}, .float32Operands = {{0, {outputValue}}}}}}}; +} + +} // namespace float32_model + +namespace quant8_model { + +// In frameworks/ml/nn/runtime/test/generated/, creates a hidl model of quant8 mobilenet. +#include "examples/mobilenet_quantized.example.cpp" +#include "vts_models/mobilenet_quantized.model.cpp" + +// Prevent the compiler from complaining about an otherwise unused function. +[[maybe_unused]] auto dummy_createTestModel = createTestModel_dynamic_output_shape; +[[maybe_unused]] auto dummy_get_examples = get_examples_dynamic_output_shape; + +// MixedTypedExample is defined in frameworks/ml/nn/tools/test_generator/include/TestHarness.h. +// This function assumes the operation is always ADD. +std::vector getLargeModelExamples(uint32_t len) { + uint8_t outputValue = 1 + static_cast(len); + return {{.operands = {// Input + {.operandDimensions = {{0, {1}}}, .quant8AsymmOperands = {{0, {1}}}}, + // Output + {.operandDimensions = {{0, {1}}}, + .quant8AsymmOperands = {{0, {outputValue}}}}}}}; +} + +} // namespace quant8_model + +namespace { + enum class AccessMode { READ_WRITE, READ_ONLY, WRITE_ONLY }; // Creates cache handles based on provided file groups. @@ -101,14 +139,18 @@ void createCacheHandles(const std::vector>& fileGroups, // ↑ ↑ ↑ ↑ // [1] [1] [1] [1] // -Model createLargeTestModel(OperationType op, uint32_t len) { +// This function assumes the operation is either ADD or MUL. +template +Model createLargeTestModelImpl(OperationType op, uint32_t len) { + EXPECT_TRUE(op == OperationType::ADD || op == OperationType::MUL); + // Model operations and operands. std::vector operations(len); std::vector operands(len * 2 + 2); // The constant buffer pool. This contains the activation scalar, followed by the // per-operation constant operands. - std::vector operandValues(sizeof(int32_t) + len * sizeof(float)); + std::vector operandValues(sizeof(int32_t) + len * sizeof(CppType)); // The activation scalar, value = 0. operands[0] = { @@ -122,7 +164,26 @@ Model createLargeTestModel(OperationType op, uint32_t len) { }; memset(operandValues.data(), 0, sizeof(int32_t)); - const float floatBufferValue = 1.0f; + // The buffer value of the constant second operand. The logical value is always 1.0f. + CppType bufferValue; + // The scale of the first and second operand. + float scale1, scale2; + if (operandType == OperandType::TENSOR_FLOAT32) { + bufferValue = 1.0f; + scale1 = 0.0f; + scale2 = 0.0f; + } else if (op == OperationType::ADD) { + bufferValue = 1; + scale1 = 1.0f; + scale2 = 1.0f; + } else { + // To satisfy the constraint on quant8 MUL: input0.scale * input1.scale < output.scale, + // set input1 to have scale = 0.5f and bufferValue = 2, i.e. 1.0f in floating point. + bufferValue = 2; + scale1 = 1.0f; + scale2 = 0.5f; + } + for (uint32_t i = 0; i < len; i++) { const uint32_t firstInputIndex = i * 2 + 1; const uint32_t secondInputIndex = firstInputIndex + 1; @@ -130,10 +191,10 @@ Model createLargeTestModel(OperationType op, uint32_t len) { // The first operation input. operands[firstInputIndex] = { - .type = OperandType::TENSOR_FLOAT32, + .type = operandType, .dimensions = {1}, .numberOfConsumers = 1, - .scale = 0.0f, + .scale = scale1, .zeroPoint = 0, .lifetime = (i == 0 ? OperandLifeTime::MODEL_INPUT : OperandLifeTime::TEMPORARY_VARIABLE), @@ -142,18 +203,18 @@ Model createLargeTestModel(OperationType op, uint32_t len) { // The second operation input, value = 1. operands[secondInputIndex] = { - .type = OperandType::TENSOR_FLOAT32, + .type = operandType, .dimensions = {1}, .numberOfConsumers = 1, - .scale = 0.0f, + .scale = scale2, .zeroPoint = 0, .lifetime = OperandLifeTime::CONSTANT_COPY, .location = {.poolIndex = 0, - .offset = static_cast(i * sizeof(float) + sizeof(int32_t)), - .length = sizeof(float)}, + .offset = static_cast(i * sizeof(CppType) + sizeof(int32_t)), + .length = sizeof(CppType)}, }; - memcpy(operandValues.data() + sizeof(int32_t) + i * sizeof(float), &floatBufferValue, - sizeof(float)); + memcpy(operandValues.data() + sizeof(int32_t) + i * sizeof(CppType), &bufferValue, + sizeof(CppType)); // The operation. All operations share the same activation scalar. // The output operand is created as an input in the next iteration of the loop, in the case @@ -168,10 +229,10 @@ Model createLargeTestModel(OperationType op, uint32_t len) { // The model output. operands.back() = { - .type = OperandType::TENSOR_FLOAT32, + .type = operandType, .dimensions = {1}, .numberOfConsumers = 0, - .scale = 0.0f, + .scale = scale1, .zeroPoint = 0, .lifetime = OperandLifeTime::MODEL_OUTPUT, .location = {}, @@ -191,22 +252,13 @@ Model createLargeTestModel(OperationType op, uint32_t len) { }; } -// MixedTypedExample is defined in frameworks/ml/nn/tools/test_generator/include/TestHarness.h. -// This function assumes the operation is always ADD. -std::vector getLargeModelExamples(uint32_t len) { - float outputValue = 1.0f + static_cast(len); - return {{.operands = { - // Input - {.operandDimensions = {{0, {1}}}, .float32Operands = {{0, {1.0f}}}}, - // Output - {.operandDimensions = {{0, {1}}}, .float32Operands = {{0, {outputValue}}}}}}}; -}; - } // namespace // Tag for the compilation caching tests. -class CompilationCachingTest : public NeuralnetworksHidlTest { +class CompilationCachingTestBase : public NeuralnetworksHidlTest { protected: + CompilationCachingTestBase(OperandType type) : kOperandType(type) {} + void SetUp() override { NeuralnetworksHidlTest::SetUp(); ASSERT_NE(device.get(), nullptr); @@ -263,6 +315,40 @@ class CompilationCachingTest : public NeuralnetworksHidlTest { NeuralnetworksHidlTest::TearDown(); } + // Model and examples creators. According to kOperandType, the following methods will return + // either float32 model/examples or the quant8 variant. + Model createTestModel() { + if (kOperandType == OperandType::TENSOR_FLOAT32) { + return float32_model::createTestModel(); + } else { + return quant8_model::createTestModel(); + } + } + + std::vector get_examples() { + if (kOperandType == OperandType::TENSOR_FLOAT32) { + return float32_model::get_examples(); + } else { + return quant8_model::get_examples(); + } + } + + Model createLargeTestModel(OperationType op, uint32_t len) { + if (kOperandType == OperandType::TENSOR_FLOAT32) { + return createLargeTestModelImpl(op, len); + } else { + return createLargeTestModelImpl(op, len); + } + } + + std::vector getLargeModelExamples(uint32_t len) { + if (kOperandType == OperandType::TENSOR_FLOAT32) { + return float32_model::getLargeModelExamples(len); + } else { + return quant8_model::getLargeModelExamples(len); + } + } + // See if the service can handle the model. bool isModelFullySupported(const V1_2::Model& model) { bool fullySupportsModel = false; @@ -366,9 +452,20 @@ class CompilationCachingTest : public NeuralnetworksHidlTest { uint32_t mNumModelCache; uint32_t mNumDataCache; uint32_t mIsCachingSupported; + + // The primary data type of the testModel. + const OperandType kOperandType; }; -TEST_F(CompilationCachingTest, CacheSavingAndRetrieval) { +// A parameterized fixture of CompilationCachingTestBase. Every test will run twice, with the first +// pass running with float32 models and the second pass running with quant8 models. +class CompilationCachingTest : public CompilationCachingTestBase, + public ::testing::WithParamInterface { + protected: + CompilationCachingTest() : CompilationCachingTestBase(GetParam()) {} +}; + +TEST_P(CompilationCachingTest, CacheSavingAndRetrieval) { // Create test HIDL model and compile. const Model testModel = createTestModel(); if (checkEarlyTermination(testModel)) return; @@ -409,7 +506,7 @@ TEST_F(CompilationCachingTest, CacheSavingAndRetrieval) { /*testDynamicOutputShape=*/false); } -TEST_F(CompilationCachingTest, CacheSavingAndRetrievalNonZeroOffset) { +TEST_P(CompilationCachingTest, CacheSavingAndRetrievalNonZeroOffset) { // Create test HIDL model and compile. const Model testModel = createTestModel(); if (checkEarlyTermination(testModel)) return; @@ -472,7 +569,7 @@ TEST_F(CompilationCachingTest, CacheSavingAndRetrievalNonZeroOffset) { /*testDynamicOutputShape=*/false); } -TEST_F(CompilationCachingTest, SaveToCacheInvalidNumCache) { +TEST_P(CompilationCachingTest, SaveToCacheInvalidNumCache) { // Create test HIDL model and compile. const Model testModel = createTestModel(); if (checkEarlyTermination(testModel)) return; @@ -584,7 +681,7 @@ TEST_F(CompilationCachingTest, SaveToCacheInvalidNumCache) { } } -TEST_F(CompilationCachingTest, PrepareModelFromCacheInvalidNumCache) { +TEST_P(CompilationCachingTest, PrepareModelFromCacheInvalidNumCache) { // Create test HIDL model and compile. const Model testModel = createTestModel(); if (checkEarlyTermination(testModel)) return; @@ -664,7 +761,7 @@ TEST_F(CompilationCachingTest, PrepareModelFromCacheInvalidNumCache) { } } -TEST_F(CompilationCachingTest, SaveToCacheInvalidNumFd) { +TEST_P(CompilationCachingTest, SaveToCacheInvalidNumFd) { // Create test HIDL model and compile. const Model testModel = createTestModel(); if (checkEarlyTermination(testModel)) return; @@ -776,7 +873,7 @@ TEST_F(CompilationCachingTest, SaveToCacheInvalidNumFd) { } } -TEST_F(CompilationCachingTest, PrepareModelFromCacheInvalidNumFd) { +TEST_P(CompilationCachingTest, PrepareModelFromCacheInvalidNumFd) { // Create test HIDL model and compile. const Model testModel = createTestModel(); if (checkEarlyTermination(testModel)) return; @@ -856,7 +953,7 @@ TEST_F(CompilationCachingTest, PrepareModelFromCacheInvalidNumFd) { } } -TEST_F(CompilationCachingTest, SaveToCacheInvalidAccessMode) { +TEST_P(CompilationCachingTest, SaveToCacheInvalidAccessMode) { // Create test HIDL model and compile. const Model testModel = createTestModel(); if (checkEarlyTermination(testModel)) return; @@ -914,7 +1011,7 @@ TEST_F(CompilationCachingTest, SaveToCacheInvalidAccessMode) { } } -TEST_F(CompilationCachingTest, PrepareModelFromCacheInvalidAccessMode) { +TEST_P(CompilationCachingTest, PrepareModelFromCacheInvalidAccessMode) { // Create test HIDL model and compile. const Model testModel = createTestModel(); if (checkEarlyTermination(testModel)) return; @@ -990,7 +1087,7 @@ static void copyCacheFiles(const std::vector>& from, constexpr uint32_t kLargeModelSize = 100; constexpr uint32_t kNumIterationsTOCTOU = 100; -TEST_F(CompilationCachingTest, SaveToCache_TOCTOU) { +TEST_P(CompilationCachingTest, SaveToCache_TOCTOU) { if (!mIsCachingSupported) return; // Create test models and check if fully supported by the service. @@ -1053,7 +1150,7 @@ TEST_F(CompilationCachingTest, SaveToCache_TOCTOU) { } } -TEST_F(CompilationCachingTest, PrepareFromCache_TOCTOU) { +TEST_P(CompilationCachingTest, PrepareFromCache_TOCTOU) { if (!mIsCachingSupported) return; // Create test models and check if fully supported by the service. @@ -1116,7 +1213,7 @@ TEST_F(CompilationCachingTest, PrepareFromCache_TOCTOU) { } } -TEST_F(CompilationCachingTest, ReplaceSecuritySensitiveCache) { +TEST_P(CompilationCachingTest, ReplaceSecuritySensitiveCache) { if (!mIsCachingSupported) return; // Create test models and check if fully supported by the service. @@ -1164,11 +1261,19 @@ TEST_F(CompilationCachingTest, ReplaceSecuritySensitiveCache) { } } -class CompilationCachingSecurityTest : public CompilationCachingTest, - public ::testing::WithParamInterface { +static const auto kOperandTypeChoices = + ::testing::Values(OperandType::TENSOR_FLOAT32, OperandType::TENSOR_QUANT8_ASYMM); + +INSTANTIATE_TEST_CASE_P(TestCompilationCaching, CompilationCachingTest, kOperandTypeChoices); + +class CompilationCachingSecurityTest + : public CompilationCachingTestBase, + public ::testing::WithParamInterface> { protected: + CompilationCachingSecurityTest() : CompilationCachingTestBase(std::get<0>(GetParam())) {} + void SetUp() { - CompilationCachingTest::SetUp(); + CompilationCachingTestBase::SetUp(); generator.seed(kSeed); } @@ -1254,7 +1359,7 @@ class CompilationCachingSecurityTest : public CompilationCachingTest, } } - const uint32_t kSeed = GetParam(); + const uint32_t kSeed = std::get<1>(GetParam()); std::mt19937 generator; }; @@ -1302,7 +1407,7 @@ TEST_P(CompilationCachingSecurityTest, WrongToken) { } INSTANTIATE_TEST_CASE_P(TestCompilationCaching, CompilationCachingSecurityTest, - ::testing::Range(0U, 10U)); + ::testing::Combine(kOperandTypeChoices, ::testing::Range(0U, 10U))); } // namespace functional } // namespace vts From 0862fabdbebb48a0ccc49fa92fc8eeffc1e22502 Mon Sep 17 00:00:00 2001 From: Mark Tabry Date: Wed, 17 Apr 2019 17:16:35 -0700 Subject: [PATCH 657/718] Adds VMS START_SESSION message type and message definition. Bug: 130313799 Test: No tests affected. VmsUtils support will be added in a separate CL. Change-Id: I1c7b713b85f191b057051737ca6bbdd0ae9bc170 --- automotive/vehicle/2.0/types.hal | 36 +++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal index b04d0962c4..661c3d4b3d 100644 --- a/automotive/vehicle/2.0/types.hal +++ b/automotive/vehicle/2.0/types.hal @@ -3248,6 +3248,16 @@ enum DiagnosticFloatSensorIndex : int32_t { * the message is decoded. */ enum VmsMessageType : int32_t { + /** + * A notification indicating that the sender has been reset. + * + * The receiving party must reset its internal state and respond to the + * sender with a START_SESSION message as acknowledgement. + * + * This message type uses enum VmsStartSessionMessageIntegerValuesIndex. + */ + START_SESSION = 17, + /** * A request from the subscribers to the VMS service to subscribe to a layer. * @@ -3364,7 +3374,7 @@ enum VmsMessageType : int32_t { */ PUBLISHER_INFORMATION_RESPONSE = 16, - LAST_VMS_MESSAGE_TYPE = PUBLISHER_INFORMATION_RESPONSE, + LAST_VMS_MESSAGE_TYPE = START_SESSION, }; /** @@ -3377,6 +3387,30 @@ enum VmsBaseMessageIntegerValuesIndex : int32_t { MESSAGE_TYPE = 0, }; +/* + * Handshake data sent as part of a VmsMessageType.START_SESSION message. + * + * A new session is initiated by sending a START_SESSION message with the + * sender's identifier populated and the receiver's identifier set to -1. + * + * Identifier values are independently generated, but must be non-negative, and + * increase monotonically between reboots. + * + * Upon receiving a START_SESSION with a mis-matching identifier, the receiver + * must clear any cached VMS offering or subscription state and acknowledge the + * new session by responding with a START_SESSION message that populates both + * identifier fields. + * + * Any VMS messages received between initiation and completion of the handshake + * must be discarded. + */ +enum VmsStartSessionMessageIntegerValuesIndex : VmsBaseMessageIntegerValuesIndex { + /* Identifier field for the Android system service. */ + SERVICE_ID = 1, + /* Identifier field for the HAL client process. */ + CLIENT_ID = 2, +}; + /* * A VMS message with a layer is sent as part of a VmsMessageType.SUBSCRIBE or * VmsMessageType.UNSUBSCRIBE messages. From a3afa5c65caf4bf48c4b8fc95c3760d0c38b6573 Mon Sep 17 00:00:00 2001 From: Anil Admal Date: Wed, 8 May 2019 18:18:19 -0700 Subject: [PATCH 658/718] Update @2.0::IGnss.hal setCallback() method documentation The IGnss.hal setCallback() and cleanup() methods need to be updated to clarify when the framework calls them so that that the GNSS engine knows when to shut down for power savings. This CL updates the @2.0::IGnss.hal setCallback() method documenation only. The @1.1::IGnss.hal and @1.0::IGnss.hal setCallback() and cleanup() method documentation is updated in another CL. Bug: 124104175 Test: Existing tests pass Change-Id: I6a2dd6f82becc0adef8b4b56fe83e7c004aefd7a --- current.txt | 2 +- gnss/2.0/IGnss.hal | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/current.txt b/current.txt index 30839471c9..01053a0b12 100644 --- a/current.txt +++ b/current.txt @@ -467,7 +467,7 @@ f27baaa587bc3dd9b740cb6928ab812b9b7d105b5187663938aee578105f3c39 android.hardwar 7f460e795f5d1ed5e378935f98c6db4d39497de988aef1b4c2a4a07a6c400392 android.hardware.gnss@2.0::IAGnss 2e5ad983734069e84a760004b32da0d09e4170c05380abe27e6eb80e4aa70d5a android.hardware.gnss@2.0::IAGnssCallback 1f4ac068a88a72360280d94a7f6fd7c63813c1eea4891a0eb01394d3e7e775f2 android.hardware.gnss@2.0::IAGnssRil -4deafcdcffa2d002119e7f58810b767a84666e76475aae68e757ec2845d9756d android.hardware.gnss@2.0::IGnss +f5605f48c2fb9f231615dd932bf730ae9540f4f98b5b7ae2b269975f452f6d73 android.hardware.gnss@2.0::IGnss db6bdf6dfc5edf6c85d2944976db899227abb51079c893874353c322342c50b6 android.hardware.gnss@2.0::IGnssBatching 1f89392f1ebb693d8fa6f50324b1635fc79fab246d31900e63998e1b0e17511c android.hardware.gnss@2.0::IGnssBatchingCallback 64232037109a5e5f53ab0377e755ec494ae93fcb5279e6eea71dec2e7ac6fbfc android.hardware.gnss@2.0::IGnssCallback diff --git a/gnss/2.0/IGnss.hal b/gnss/2.0/IGnss.hal index f19f8d0566..9935bf914d 100644 --- a/gnss/2.0/IGnss.hal +++ b/gnss/2.0/IGnss.hal @@ -36,13 +36,18 @@ import IGnssBatching; * the interface @1.0::IGnssNi.hal and @1.0::IGnssNiCallback.hal are deprecated in this version * and are not supported by the framework. The GNSS HAL implementation of this interface * must return nullptr for the following @1.0::IGnss method. - * getExtensionGnssNi() generates (IGnssNi gnssNiIface); + * getExtensionGnssNi() generates (IGnssNi gnssNiIface); */ interface IGnss extends @1.1::IGnss { /** * Opens the interface and provides the callback routines to the implementation of this * interface. * + * The framework calls this method to instruct the GPS engine to prepare for serving requests + * from the framework. The GNSS HAL implementation must respond to all GNSS requests from the + * framework upon successful return from this method until cleanup() method is called to + * close this interface. + * * @param callback Callback interface for IGnss. * * @return success Returns true on success. @@ -83,8 +88,9 @@ interface IGnss extends @1.1::IGnss { /** * This method returns the IGnssMeasurement interface. * - * Exactly one of getExtensionGnssMeasurement_1_1() and getExtensionGnssMeasurement_2_0() must - * return a non-null handle, and the other method must return nullptr. + * Exactly one of getExtensionGnssMeasurement(), getExtensionGnssMeasurement_1_1(), and + * getExtensionGnssMeasurement_2_0() methods must return a non-null handle, and the other + * methods must return nullptr. * * @return gnssMeasurementIface Handle to the IGnssMeasurement interface. */ From 2f28bb0c1939b94a2c13bcfa6d51fda698a25279 Mon Sep 17 00:00:00 2001 From: Anil Admal Date: Thu, 9 May 2019 09:19:54 -0700 Subject: [PATCH 659/718] Clarify when IGnss.hal cleanup() and setCallback() methods are called Update IGnss.hal cleanup() and setCallback() method documentation to clarify when the framework calls these methods so that the GNSS engine knows when to shut down for power savings. This CL updates @1.1::IGnss.hal and @1.0::IGnss.hal interfaces only. @2.0::IGnss.hal is updated in another CL. Bug: 124104175 Test: Existing tests pass Change-Id: I8181251677dab78ce0619fa1e2a667b36e115f25 --- current.txt | 2 ++ gnss/1.0/IGnss.hal | 23 ++++++++++++++++++++--- gnss/1.1/IGnss.hal | 7 ++++++- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/current.txt b/current.txt index 1f322638ca..cb2882659b 100644 --- a/current.txt +++ b/current.txt @@ -393,8 +393,10 @@ f8a19622cb0cc890913b1ef3e32b675ffb26089a09e02fef4056ebad324d2b5d android.hardwar 23780340c686ee86986aa5a9755c2d8566224fed177bbb22a5ebf06be574b60c android.hardware.camera.metadata@3.3::types 05d1ee760d81cdd2dc7a70ce0241af9fa830edae33b4be83d9bf5fffe05ddc6f android.hardware.camera.provider@2.4::ICameraProvider da33234403ff5d60f3473711917b9948e6484a4260b5247acdafb111193a9de2 android.hardware.configstore@1.0::ISurfaceFlingerConfigs +ede69710c3a95c2cbe818e6c8bb72c7816823face5fc21c17731b26f41d94d65 android.hardware.gnss@1.0::IGnss 21165b8e30c4b2d52980e4728f661420adc16e38bbe73476c06b2085be908f4c android.hardware.gnss@1.0::IGnssCallback d702fb01dc2a0733aa820b7eb65435ee3334f75632ef880bafd2fb8803a20a58 android.hardware.gnss@1.0::IGnssMeasurementCallback +b5f1f4c1bd6de71a8e71d70f57cdab904ac024a12f3dee3e2173770a4583bcc2 android.hardware.gnss@1.1::IGnss 7c7721c0f773fcf422b71a4f558545e9e36acc973e58ca51e5bd53905cf46bc0 android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer d4fea995378bb4f421b4e24ccf68cad2734ab07fe4f874a126ba558b99df5766 android.hardware.graphics.composer@2.1::IComposerClient f7d7cb747dc01a9fdb2d39a80003b4d8df9be733d65f5842198802eb6209db69 android.hardware.graphics.mapper@2.0::IMapper diff --git a/gnss/1.0/IGnss.hal b/gnss/1.0/IGnss.hal index 602c615af9..d32bc63940 100644 --- a/gnss/1.0/IGnss.hal +++ b/gnss/1.0/IGnss.hal @@ -75,8 +75,13 @@ interface IGnss { }; /** - * Opens the interface and provides the callback routines - * to the implementation of this interface. + * Opens the interface and provides the callback routines to the implementation of this + * interface. + * + * The framework calls this method to instruct the GPS engine to prepare for serving requests + * from the framework. The GNSS HAL implementation must respond to all GNSS requests from the + * framework upon successful return from this method until cleanup() method is called to + * close this interface. * * @param callback Callback interface for IGnss. * @@ -105,6 +110,18 @@ interface IGnss { /** * Closes the interface. + * + * The cleanup() method is called by the framework to tell the GNSS HAL implementation to + * not expect any GNSS requests in the immediate future - e.g. this may be called when + * location is disabled by a user setting or low battery conditions. The GNSS HAL + * implementation must immediately stop responding to any existing requests until the + * setCallback() method is called again and the requests are re-initiated by the framework. + * + * After this method is called, the GNSS HAL implementation may choose to modify GNSS hardware + * states to save power. It is expected that when setCallback() method is called again to + * reopen this interface, to serve requests, there may be some minor delays in GNSS response + * requests as hardware readiness states are restored, not to exceed those that occur on normal + * device boot up. */ cleanup(); @@ -153,7 +170,7 @@ interface IGnss { * @param mode Parameter must be one of MS_BASED or STANDALONE. * It is allowed by the platform (and it is recommended) to fallback to * MS_BASED if MS_ASSISTED is passed in, and MS_BASED is supported. - * @recurrence GNSS postion recurrence value, either periodic or single. + * @recurrence GNSS position recurrence value, either periodic or single. * @param minIntervalMs Represents the time between fixes in milliseconds. * @param preferredAccuracyMeters Represents the requested fix accuracy in meters. * @param preferredTimeMs Represents the requested time to first fix in milliseconds. diff --git a/gnss/1.1/IGnss.hal b/gnss/1.1/IGnss.hal index 672f74236d..3400807d23 100644 --- a/gnss/1.1/IGnss.hal +++ b/gnss/1.1/IGnss.hal @@ -29,6 +29,11 @@ interface IGnss extends @1.0::IGnss { * Opens the interface and provides the callback routines to the implementation of this * interface. * + * The framework calls this method to instruct the GPS engine to prepare for serving requests + * from the framework. The GNSS HAL implementation must respond to all GNSS requests from the + * framework upon successful return from this method until cleanup() method is called to + * close this interface. + * * @param callback Callback interface for IGnss. * * @return success Returns true on success. @@ -42,7 +47,7 @@ interface IGnss extends @1.0::IGnss { * @param mode Parameter must be one of MS_BASED or STANDALONE. It is allowed by the platform * (and it is recommended) to fallback to MS_BASED if MS_ASSISTED is passed in, and MS_BASED * is supported. - * @param recurrence GNSS postion recurrence value, either periodic or single. + * @param recurrence GNSS position recurrence value, either periodic or single. * @param minIntervalMs Represents the time between fixes in milliseconds. * @param preferredAccuracyMeters Represents the requested fix accuracy in meters. * @param preferredTimeMs Represents the requested time to first fix in milliseconds. From 5ec377b43038a9b705704c2b48e03c9f9587dde4 Mon Sep 17 00:00:00 2001 From: Emilian Peev Date: Wed, 1 May 2019 10:51:23 -0700 Subject: [PATCH 660/718] Camera: Add fall back properties for FMQ size override All system properties in the vendor partition must start with either "vendor" or "ro.vendor". Older devices should not be affected but newer implementations may not be able to override the FMQ size if needed. Keep this functionality and provide fall back properties using "ro.vendor.camera". Bug: 77865891 Test: Manual using application and modified device configuration. Change-Id: I23d0ba7a10eaafe98a708277c26579e8a0fec614 --- .../3.2/default/CameraDeviceSession.cpp | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/camera/device/3.2/default/CameraDeviceSession.cpp b/camera/device/3.2/default/CameraDeviceSession.cpp index f2d7a47e83..99cdccbcdb 100644 --- a/camera/device/3.2/default/CameraDeviceSession.cpp +++ b/camera/device/3.2/default/CameraDeviceSession.cpp @@ -99,11 +99,20 @@ bool CameraDeviceSession::initialize() { return true; } - int32_t reqFMQSize = property_get_int32("ro.camera.req.fmq.size", /*default*/-1); + // "ro.camera" properties are no longer supported on vendor side. + // Support a fall back for the fmq size override that uses "ro.vendor.camera" + // properties. + int32_t reqFMQSize = property_get_int32("ro.vendor.camera.req.fmq.size", /*default*/-1); if (reqFMQSize < 0) { - reqFMQSize = CAMERA_REQUEST_METADATA_QUEUE_SIZE; + reqFMQSize = property_get_int32("ro.camera.req.fmq.size", /*default*/-1); + if (reqFMQSize < 0) { + reqFMQSize = CAMERA_REQUEST_METADATA_QUEUE_SIZE; + } else { + ALOGV("%s: request FMQ size overridden to %d", __FUNCTION__, reqFMQSize); + } } else { - ALOGV("%s: request FMQ size overridden to %d", __FUNCTION__, reqFMQSize); + ALOGV("%s: request FMQ size overridden to %d via fallback property", __FUNCTION__, + reqFMQSize); } mRequestMetadataQueue = std::make_unique( @@ -114,12 +123,22 @@ bool CameraDeviceSession::initialize() { return true; } - int32_t resFMQSize = property_get_int32("ro.camera.res.fmq.size", /*default*/-1); + // "ro.camera" properties are no longer supported on vendor side. + // Support a fall back for the fmq size override that uses "ro.vendor.camera" + // properties. + int32_t resFMQSize = property_get_int32("ro.vendor.camera.res.fmq.size", /*default*/-1); if (resFMQSize < 0) { - resFMQSize = CAMERA_RESULT_METADATA_QUEUE_SIZE; + resFMQSize = property_get_int32("ro.camera.res.fmq.size", /*default*/-1); + if (resFMQSize < 0) { + resFMQSize = CAMERA_RESULT_METADATA_QUEUE_SIZE; + } else { + ALOGV("%s: result FMQ size overridden to %d", __FUNCTION__, resFMQSize); + } } else { - ALOGV("%s: result FMQ size overridden to %d", __FUNCTION__, resFMQSize); + ALOGV("%s: result FMQ size overridden to %d via fallback property", __FUNCTION__, + resFMQSize); } + mResultMetadataQueue = std::make_shared( static_cast(resFMQSize), false /* non blocking */); From 8b6484bce6ff4a995c6df28d2780731f84eb3788 Mon Sep 17 00:00:00 2001 From: Kai Date: Wed, 8 May 2019 13:29:03 -0700 Subject: [PATCH 661/718] Add property for vehicle speed Add proerty and units for vehicle speed. Bug: 131715430 Test: build and flash Change-Id: I4b34808b75d76385d0b1b76530889f69bd945c84 --- automotive/vehicle/2.0/types.hal | 104 +++++++++++++++++++------------ 1 file changed, 63 insertions(+), 41 deletions(-) diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal index b04d0962c4..c1828432a5 100644 --- a/automotive/vehicle/2.0/types.hal +++ b/automotive/vehicle/2.0/types.hal @@ -1120,9 +1120,9 @@ enum VehicleProperty : int32_t { * * Distance units are defined in VehicleUnit. * VehiclePropConfig.configArray is used to indicate the supported distance display units. - * For example: configArray[0] = 0x21 // METER - * configArray[1] = 0x23 // KILOMETER - * configArray[2] = 0x24 // MILE + * For example: configArray[0] = METER + * configArray[1] = KILOMETER + * configArray[2] = MILE * @change_mode VehiclePropertyChangeMode:ON_CHANGE * @access VehiclePropertyAccess:READ_WRITE * @data_enum VehicleUnit @@ -1141,8 +1141,8 @@ enum VehicleProperty : int32_t { * * VehiclePropConfig.configArray is used to indicate the supported fuel volume display units. * Volume units are defined in VehicleUnit. - * For example: configArray[0] = 0x41 // LITER - * configArray[1] = 0x42 // GALLON + * For example: configArray[0] = LITER + * configArray[1] = GALLON * @change_mode VehiclePropertyChangeMode:ON_CHANGE * @access VehiclePropertyAccess:READ_WRITE * @data_enum VehicleUnit @@ -1161,9 +1161,9 @@ enum VehicleProperty : int32_t { * * VehiclePropConfig.configArray is used to indicate the supported pressure display units. * Pressure units are defined in VehicleUnit. - * For example: configArray[0] = 0x70 // KILOPASCAL - * configArray[1] = 0x71 // PSI - * configArray[2] = 0x72 // BAR + * For example: configArray[0] = KILOPASCAL + * configArray[1] = PSI + * configArray[2] = BAR * @change_mode VehiclePropertyChangeMode:ON_CHANGE * @access VehiclePropertyAccess:READ_WRITE * @data_enum VehicleUnit @@ -1182,9 +1182,9 @@ enum VehicleProperty : int32_t { * * VehiclePropConfig.configArray is used to indicate the supported electrical energy units. * Electrical energy units are defined in VehicleUnit. - * For example: configArray[0] = 0x60 // watt-hours - * configArray[1] = 0x64 // ampere-hours - * configArray[2] = 0x65 // kilowatt-hours + * For example: configArray[0] = WATT_HOUR + * configArray[1] = AMPERE_HOURS + * configArray[2] = KILOWATT_HOUR * @change_mode VehiclePropertyChangeMode:ON_CHANGE * @access VehiclePropertyAccess:READ_WRITE * @data_enum VehicleUnit @@ -1211,6 +1211,25 @@ enum VehicleProperty : int32_t { | VehiclePropertyType:BOOLEAN | VehicleArea:GLOBAL), + /** + * Speed units for display + * + * Indicates type of units the car is using to display speed to user. Eg. m/s, km/h, or mph. + * + * VehiclePropConfig.configArray is used to indicate the supported speed display units. + * Pressure units are defined in VehicleUnit. + * For example: configArray[0] = METER_PER_SEC + * configArray[1] = MILES_PER_HOUR + * configArray[2] = KILOMETERS_PER_HOUR + * @change_mode VehiclePropertyChangeMode:ON_CHANGE + * @access VehiclePropertyAccess:READ_WRITE + */ + VEHICLE_SPEED_DISPLAY_UNITS = ( + 0x0605 + | VehiclePropertyGroup:SYSTEM + | VehiclePropertyType:INT32 + | VehicleArea:GLOBAL), + /** * Outside temperature * @@ -2586,42 +2605,45 @@ enum VehicleDisplay : int32_t { * Units used for int or float type with no attached enum types. */ enum VehicleUnit : int32_t { - SHOULD_NOT_USE = 0x000, + SHOULD_NOT_USE = 0x000, - METER_PER_SEC = 0x01, - RPM = 0x02, - HERTZ = 0x03, - PERCENTILE = 0x10, - MILLIMETER = 0x20, - METER = 0x21, - KILOMETER = 0x23, - MILE = 0x24, - CELSIUS = 0x30, - FAHRENHEIT = 0x31, - KELVIN = 0x32, - MILLILITER = 0x40, - LITER = 0x41, + METER_PER_SEC = 0x01, + RPM = 0x02, + HERTZ = 0x03, + PERCENTILE = 0x10, + MILLIMETER = 0x20, + METER = 0x21, + KILOMETER = 0x23, + MILE = 0x24, + CELSIUS = 0x30, + FAHRENHEIT = 0x31, + KELVIN = 0x32, + MILLILITER = 0x40, + LITER = 0x41, /** deprecated. Use US_GALLON instead. */ - GALLON = 0x42, - US_GALLON = 0x42, - IMPERIAL_GALLON= 0x43, - NANO_SECS = 0x50, - SECS = 0x53, - YEAR = 0x59, + GALLON = 0x42, + US_GALLON = 0x42, + IMPERIAL_GALLON = 0x43, + NANO_SECS = 0x50, + SECS = 0x53, + YEAR = 0x59, // Electrical Units - WATT_HOUR = 0x60, - MILLIAMPERE = 0x61, - MILLIVOLT = 0x62, - MILLIWATTS = 0x63, - AMPERE_HOURS = 0x64, - KILOWATT_HOUR = 0x65, + WATT_HOUR = 0x60, + MILLIAMPERE = 0x61, + MILLIVOLT = 0x62, + MILLIWATTS = 0x63, + AMPERE_HOURS = 0x64, + KILOWATT_HOUR = 0x65, - KILOPASCAL = 0x70, - PSI = 0x71, - BAR = 0x72, - DEGREES = 0x80, + KILOPASCAL = 0x70, + PSI = 0x71, + BAR = 0x72, + DEGREES = 0x80, + + MILES_PER_HOUR = 0x90, + KILOMETERS_PER_HOUR = 0x91, }; /** From a2019c16d5740b387f85a7853dc385e195c6eae3 Mon Sep 17 00:00:00 2001 From: Wally Yau Date: Fri, 10 May 2019 14:25:39 -0700 Subject: [PATCH 662/718] Detach pollThread only if it is joinable sensor HAL is not required for Android TV. Hence, ISensors returned from getService() was null and pollThread was not associated with any thread of execution. Bug: 120910004 Test: run vts -m VtsHalSensorsV1_0Target Change-Id: If16af7313ff7bb22e5ca16c03a0fee0b8d733335 --- sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp index c18eedd176..098a24ff5b 100644 --- a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp +++ b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp @@ -105,7 +105,9 @@ void SensorsHidlEnvironment::HidlTearDown() { if (stopThread) { *stopThread = true; } - pollThread.detach(); + if (pollThread.joinable()) { + pollThread.detach(); + } } void SensorsHidlEnvironment::resetHal() { From 0d2925263161509462917a3dae67a937fd79bf75 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Thu, 9 May 2019 18:42:37 -0700 Subject: [PATCH 663/718] Use Widely Supported GSM Channels for NetworkScan Change the network scan tests to use the P900 and 850 GSM bands, which are commonly (nearly universally) supported bands. Bug: 132076611 Test: atest RadioHidlTest_v1_2 Change-Id: Ia682f022d35c481876c49c9c8802d7c39722be0e (cherry picked from commit 2ea2a64bc78cff5a0c0cc1211adbdfd59caf379c) --- .../1.2/vts/functional/radio_hidl_hal_api.cpp | 164 +++++++----------- 1 file changed, 65 insertions(+), 99 deletions(-) diff --git a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp index 35101637df..feee37d4b2 100644 --- a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp +++ b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp @@ -19,19 +19,25 @@ #define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk()) +namespace { +const RadioAccessSpecifier GERAN_SPECIFIER_P900 = {.radioAccessNetwork = RadioAccessNetworks::GERAN, + .geranBands = {GeranBands::BAND_P900}, + .channels = {1, 2}}; +const RadioAccessSpecifier GERAN_SPECIFIER_850 = {.radioAccessNetwork = RadioAccessNetworks::GERAN, + .geranBands = {GeranBands::BAND_850}, + .channels = {128, 129}}; +} // namespace + /* * Test IRadio.startNetworkScan() for the response returned. */ TEST_F(RadioHidlTest_v1_2, startNetworkScan) { serial = GetRandomSerialNumber(); - RadioAccessSpecifier specifier = { - .radioAccessNetwork = RadioAccessNetworks::GERAN, - .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480}, - .channels = {1,2}}; - ::android::hardware::radio::V1_2::NetworkScanRequest request = { - .type = ScanType::ONE_SHOT, .interval = 60, .specifiers = {specifier}}; + .type = ScanType::ONE_SHOT, + .interval = 60, + .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850}}; Return res = radio_v1_2->startNetworkScan_1_2(serial, request); ASSERT_OK(res); @@ -89,18 +95,13 @@ TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidArgument) { TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidInterval1) { serial = GetRandomSerialNumber(); - RadioAccessSpecifier specifier = { - .radioAccessNetwork = RadioAccessNetworks::GERAN, - .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480}, - .channels = {1,2}}; - ::android::hardware::radio::V1_2::NetworkScanRequest request = { - .type = ScanType::ONE_SHOT, - .interval = 4, - .specifiers = {specifier}, - .maxSearchTime = 60, - .incrementalResults = false, - .incrementalResultsPeriodicity = 1}; + .type = ScanType::ONE_SHOT, + .interval = 4, + .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850}, + .maxSearchTime = 60, + .incrementalResults = false, + .incrementalResultsPeriodicity = 1}; Return res = radio_v1_2->startNetworkScan_1_2(serial, request); ASSERT_OK(res); @@ -126,18 +127,13 @@ TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidInterval1) { TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidInterval2) { serial = GetRandomSerialNumber(); - RadioAccessSpecifier specifier = { - .radioAccessNetwork = RadioAccessNetworks::GERAN, - .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480}, - .channels = {1,2}}; - ::android::hardware::radio::V1_2::NetworkScanRequest request = { - .type = ScanType::ONE_SHOT, - .interval = 301, - .specifiers = {specifier}, - .maxSearchTime = 60, - .incrementalResults = false, - .incrementalResultsPeriodicity = 1}; + .type = ScanType::ONE_SHOT, + .interval = 301, + .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850}, + .maxSearchTime = 60, + .incrementalResults = false, + .incrementalResultsPeriodicity = 1}; Return res = radio_v1_2->startNetworkScan_1_2(serial, request); ASSERT_OK(res); @@ -163,18 +159,13 @@ TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidInterval2) { TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidMaxSearchTime1) { serial = GetRandomSerialNumber(); - RadioAccessSpecifier specifier = { - .radioAccessNetwork = RadioAccessNetworks::GERAN, - .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480}, - .channels = {1,2}}; - ::android::hardware::radio::V1_2::NetworkScanRequest request = { - .type = ScanType::ONE_SHOT, - .interval = 60, - .specifiers = {specifier}, - .maxSearchTime = 59, - .incrementalResults = false, - .incrementalResultsPeriodicity = 1}; + .type = ScanType::ONE_SHOT, + .interval = 60, + .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850}, + .maxSearchTime = 59, + .incrementalResults = false, + .incrementalResultsPeriodicity = 1}; Return res = radio_v1_2->startNetworkScan_1_2(serial, request); ASSERT_OK(res); @@ -200,18 +191,13 @@ TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidMaxSearchTime1) { TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidMaxSearchTime2) { serial = GetRandomSerialNumber(); - RadioAccessSpecifier specifier = { - .radioAccessNetwork = RadioAccessNetworks::GERAN, - .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480}, - .channels = {1,2}}; - ::android::hardware::radio::V1_2::NetworkScanRequest request = { - .type = ScanType::ONE_SHOT, - .interval = 60, - .specifiers = {specifier}, - .maxSearchTime = 3601, - .incrementalResults = false, - .incrementalResultsPeriodicity = 1}; + .type = ScanType::ONE_SHOT, + .interval = 60, + .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850}, + .maxSearchTime = 3601, + .incrementalResults = false, + .incrementalResultsPeriodicity = 1}; Return res = radio_v1_2->startNetworkScan_1_2(serial, request); ASSERT_OK(res); @@ -237,18 +223,13 @@ TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidMaxSearchTime2) { TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidPeriodicity1) { serial = GetRandomSerialNumber(); - RadioAccessSpecifier specifier = { - .radioAccessNetwork = RadioAccessNetworks::GERAN, - .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480}, - .channels = {1,2}}; - ::android::hardware::radio::V1_2::NetworkScanRequest request = { - .type = ScanType::ONE_SHOT, - .interval = 60, - .specifiers = {specifier}, - .maxSearchTime = 600, - .incrementalResults = false, - .incrementalResultsPeriodicity = 0}; + .type = ScanType::ONE_SHOT, + .interval = 60, + .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850}, + .maxSearchTime = 600, + .incrementalResults = false, + .incrementalResultsPeriodicity = 0}; Return res = radio_v1_2->startNetworkScan_1_2(serial, request); ASSERT_OK(res); @@ -274,18 +255,13 @@ TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidPeriodicity1) { TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidPeriodicity2) { serial = GetRandomSerialNumber(); - RadioAccessSpecifier specifier = { - .radioAccessNetwork = RadioAccessNetworks::GERAN, - .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480}, - .channels = {1,2}}; - ::android::hardware::radio::V1_2::NetworkScanRequest request = { - .type = ScanType::ONE_SHOT, - .interval = 60, - .specifiers = {specifier}, - .maxSearchTime = 600, - .incrementalResults = false, - .incrementalResultsPeriodicity = 11}; + .type = ScanType::ONE_SHOT, + .interval = 60, + .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850}, + .maxSearchTime = 600, + .incrementalResults = false, + .incrementalResultsPeriodicity = 11}; Return res = radio_v1_2->startNetworkScan_1_2(serial, request); ASSERT_OK(res); @@ -311,20 +287,15 @@ TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidPeriodicity2) { TEST_F(RadioHidlTest_v1_2, startNetworkScan_GoodRequest1) { serial = GetRandomSerialNumber(); - RadioAccessSpecifier specifier = { - .radioAccessNetwork = RadioAccessNetworks::GERAN, - .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480}, - .channels = {1,2}}; - ::android::hardware::radio::V1_2::NetworkScanRequest request = { - .type = ScanType::ONE_SHOT, - .interval = 60, - .specifiers = {specifier}, - // Some vendor may not support max search time of 360s. - // This issue is tracked in b/112205669. - .maxSearchTime = 300, - .incrementalResults = false, - .incrementalResultsPeriodicity = 10}; + .type = ScanType::ONE_SHOT, + .interval = 60, + .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850}, + // Some vendor may not support max search time of 360s. + // This issue is tracked in b/112205669. + .maxSearchTime = 300, + .incrementalResults = false, + .incrementalResultsPeriodicity = 10}; Return res = radio_v1_2->startNetworkScan_1_2(serial, request); ASSERT_OK(res); @@ -350,21 +321,16 @@ TEST_F(RadioHidlTest_v1_2, startNetworkScan_GoodRequest1) { TEST_F(RadioHidlTest_v1_2, startNetworkScan_GoodRequest2) { serial = GetRandomSerialNumber(); - RadioAccessSpecifier specifier = { - .radioAccessNetwork = RadioAccessNetworks::GERAN, - .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480}, - .channels = {1,2}}; - ::android::hardware::radio::V1_2::NetworkScanRequest request = { - .type = ScanType::ONE_SHOT, - .interval = 60, - .specifiers = {specifier}, - // Some vendor may not support max search time of 360s. - // This issue is tracked in b/112205669. - .maxSearchTime = 300, - .incrementalResults = false, - .incrementalResultsPeriodicity = 10, - .mccMncs = {"310410"}}; + .type = ScanType::ONE_SHOT, + .interval = 60, + .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850}, + // Some vendor may not support max search time of 360s. + // This issue is tracked in b/112205669. + .maxSearchTime = 300, + .incrementalResults = false, + .incrementalResultsPeriodicity = 10, + .mccMncs = {"310410"}}; Return res = radio_v1_2->startNetworkScan_1_2(serial, request); ASSERT_OK(res); From 3b3ffacd25b5d52ce30214936e61a021dffbe61e Mon Sep 17 00:00:00 2001 From: Nazanin Bakhshi Date: Fri, 10 May 2019 16:20:16 -0700 Subject: [PATCH 664/718] VTS: add NOT_SUPPORTED to enableModem Bug: 130190479 Test: VTS Change-Id: Ie5851929287f461f20ee6a7b979f15133755b2b3 --- radio/1.3/vts/functional/radio_hidl_hal_api.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/radio/1.3/vts/functional/radio_hidl_hal_api.cpp b/radio/1.3/vts/functional/radio_hidl_hal_api.cpp index 030f489c48..5b7a06de87 100644 --- a/radio/1.3/vts/functional/radio_hidl_hal_api.cpp +++ b/radio/1.3/vts/functional/radio_hidl_hal_api.cpp @@ -33,9 +33,9 @@ TEST_F(RadioHidlTest_v1_3, enableModem) { EXPECT_EQ(serial, radioRsp_v1_3->rspInfo.serial); ALOGI("getModemStackStatus, rspInfo.error = %s\n", toString(radioRsp_v1_3->rspInfo.error).c_str()); - ASSERT_TRUE(CheckAnyOfErrors( - radioRsp_v1_3->rspInfo.error, - {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::MODEM_ERR})); + ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_3->rspInfo.error, + {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, + RadioError::MODEM_ERR, RadioError::REQUEST_NOT_SUPPORTED})); // checking if getModemStackStatus returns true, as modem was enabled above if (RadioError::NONE == radioRsp_v1_3->rspInfo.error) { @@ -50,9 +50,9 @@ TEST_F(RadioHidlTest_v1_3, enableModem) { EXPECT_EQ(serial, radioRsp_v1_3->rspInfo.serial); ALOGI("getModemStackStatus, rspInfo.error = %s\n", toString(radioRsp_v1_3->rspInfo.error).c_str()); - ASSERT_TRUE(CheckAnyOfErrors( - radioRsp_v1_3->rspInfo.error, - {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::MODEM_ERR})); + ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_3->rspInfo.error, + {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, + RadioError::MODEM_ERR, RadioError::REQUEST_NOT_SUPPORTED})); // verify that enableModem did set isEnabled correctly EXPECT_EQ(true, radioRsp_v1_3->isModemEnabled); } From a83af2b6fd15dcef622407c7931c894dfe428b88 Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Mon, 13 May 2019 09:34:10 -0700 Subject: [PATCH 665/718] Put composer 2.3 in the right cpuset. the composer HAL should be in the system-background cpuset, but hwc 2.3 is not in any cpuset. This patch restricts it to system-background. BUG: 132559090 Test: Build, flash and boot. Change-Id: I1739a6c049e195f6cc79b81fcba7a6fcb55b546a --- .../default/android.hardware.graphics.composer@2.3-service.rc | 1 + 1 file changed, 1 insertion(+) diff --git a/graphics/composer/2.3/default/android.hardware.graphics.composer@2.3-service.rc b/graphics/composer/2.3/default/android.hardware.graphics.composer@2.3-service.rc index 08e32d8f13..81ce89059c 100644 --- a/graphics/composer/2.3/default/android.hardware.graphics.composer@2.3-service.rc +++ b/graphics/composer/2.3/default/android.hardware.graphics.composer@2.3-service.rc @@ -4,3 +4,4 @@ service vendor.hwcomposer-2-3 /vendor/bin/hw/android.hardware.graphics.composer@ group graphics drmrpc capabilities SYS_NICE onrestart restart surfaceflinger + writepid /dev/cpuset/system-background/tasks From 1ff574dc635ee0c6812e37c936456a5697c2bf02 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Thu, 9 May 2019 18:42:37 -0700 Subject: [PATCH 666/718] Use Widely Supported GSM Channels for NetworkScan Change the network scan tests to use the P900 and 850 GSM bands, which are commonly (nearly universally) supported bands. Bug: 132076611 Test: atest RadioHidlTest_v1_2 Merged-In: Ia682f022d35c481876c49c9c8802d7c39722be0e Change-Id: Ia682f022d35c481876c49c9c8802d7c39722be0e (cherry picked from commit 2ea2a64bc78cff5a0c0cc1211adbdfd59caf379c) --- .../1.2/vts/functional/radio_hidl_hal_api.cpp | 164 +++++++----------- 1 file changed, 65 insertions(+), 99 deletions(-) diff --git a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp index 730d9696aa..c14720c453 100644 --- a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp +++ b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp @@ -19,19 +19,25 @@ #define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk()) +namespace { +const RadioAccessSpecifier GERAN_SPECIFIER_P900 = {.radioAccessNetwork = RadioAccessNetworks::GERAN, + .geranBands = {GeranBands::BAND_P900}, + .channels = {1, 2}}; +const RadioAccessSpecifier GERAN_SPECIFIER_850 = {.radioAccessNetwork = RadioAccessNetworks::GERAN, + .geranBands = {GeranBands::BAND_850}, + .channels = {128, 129}}; +} // namespace + /* * Test IRadio.startNetworkScan() for the response returned. */ TEST_F(RadioHidlTest_v1_2, startNetworkScan) { serial = GetRandomSerialNumber(); - RadioAccessSpecifier specifier = { - .radioAccessNetwork = RadioAccessNetworks::GERAN, - .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480}, - .channels = {1,2}}; - ::android::hardware::radio::V1_2::NetworkScanRequest request = { - .type = ScanType::ONE_SHOT, .interval = 60, .specifiers = {specifier}}; + .type = ScanType::ONE_SHOT, + .interval = 60, + .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850}}; Return res = radio_v1_2->startNetworkScan_1_2(serial, request); ASSERT_OK(res); @@ -89,18 +95,13 @@ TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidArgument) { TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidInterval1) { serial = GetRandomSerialNumber(); - RadioAccessSpecifier specifier = { - .radioAccessNetwork = RadioAccessNetworks::GERAN, - .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480}, - .channels = {1,2}}; - ::android::hardware::radio::V1_2::NetworkScanRequest request = { - .type = ScanType::ONE_SHOT, - .interval = 4, - .specifiers = {specifier}, - .maxSearchTime = 60, - .incrementalResults = false, - .incrementalResultsPeriodicity = 1}; + .type = ScanType::ONE_SHOT, + .interval = 4, + .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850}, + .maxSearchTime = 60, + .incrementalResults = false, + .incrementalResultsPeriodicity = 1}; Return res = radio_v1_2->startNetworkScan_1_2(serial, request); ASSERT_OK(res); @@ -126,18 +127,13 @@ TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidInterval1) { TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidInterval2) { serial = GetRandomSerialNumber(); - RadioAccessSpecifier specifier = { - .radioAccessNetwork = RadioAccessNetworks::GERAN, - .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480}, - .channels = {1,2}}; - ::android::hardware::radio::V1_2::NetworkScanRequest request = { - .type = ScanType::ONE_SHOT, - .interval = 301, - .specifiers = {specifier}, - .maxSearchTime = 60, - .incrementalResults = false, - .incrementalResultsPeriodicity = 1}; + .type = ScanType::ONE_SHOT, + .interval = 301, + .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850}, + .maxSearchTime = 60, + .incrementalResults = false, + .incrementalResultsPeriodicity = 1}; Return res = radio_v1_2->startNetworkScan_1_2(serial, request); ASSERT_OK(res); @@ -163,18 +159,13 @@ TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidInterval2) { TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidMaxSearchTime1) { serial = GetRandomSerialNumber(); - RadioAccessSpecifier specifier = { - .radioAccessNetwork = RadioAccessNetworks::GERAN, - .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480}, - .channels = {1,2}}; - ::android::hardware::radio::V1_2::NetworkScanRequest request = { - .type = ScanType::ONE_SHOT, - .interval = 60, - .specifiers = {specifier}, - .maxSearchTime = 59, - .incrementalResults = false, - .incrementalResultsPeriodicity = 1}; + .type = ScanType::ONE_SHOT, + .interval = 60, + .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850}, + .maxSearchTime = 59, + .incrementalResults = false, + .incrementalResultsPeriodicity = 1}; Return res = radio_v1_2->startNetworkScan_1_2(serial, request); ASSERT_OK(res); @@ -200,18 +191,13 @@ TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidMaxSearchTime1) { TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidMaxSearchTime2) { serial = GetRandomSerialNumber(); - RadioAccessSpecifier specifier = { - .radioAccessNetwork = RadioAccessNetworks::GERAN, - .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480}, - .channels = {1,2}}; - ::android::hardware::radio::V1_2::NetworkScanRequest request = { - .type = ScanType::ONE_SHOT, - .interval = 60, - .specifiers = {specifier}, - .maxSearchTime = 3601, - .incrementalResults = false, - .incrementalResultsPeriodicity = 1}; + .type = ScanType::ONE_SHOT, + .interval = 60, + .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850}, + .maxSearchTime = 3601, + .incrementalResults = false, + .incrementalResultsPeriodicity = 1}; Return res = radio_v1_2->startNetworkScan_1_2(serial, request); ASSERT_OK(res); @@ -237,18 +223,13 @@ TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidMaxSearchTime2) { TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidPeriodicity1) { serial = GetRandomSerialNumber(); - RadioAccessSpecifier specifier = { - .radioAccessNetwork = RadioAccessNetworks::GERAN, - .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480}, - .channels = {1,2}}; - ::android::hardware::radio::V1_2::NetworkScanRequest request = { - .type = ScanType::ONE_SHOT, - .interval = 60, - .specifiers = {specifier}, - .maxSearchTime = 600, - .incrementalResults = false, - .incrementalResultsPeriodicity = 0}; + .type = ScanType::ONE_SHOT, + .interval = 60, + .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850}, + .maxSearchTime = 600, + .incrementalResults = false, + .incrementalResultsPeriodicity = 0}; Return res = radio_v1_2->startNetworkScan_1_2(serial, request); ASSERT_OK(res); @@ -274,18 +255,13 @@ TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidPeriodicity1) { TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidPeriodicity2) { serial = GetRandomSerialNumber(); - RadioAccessSpecifier specifier = { - .radioAccessNetwork = RadioAccessNetworks::GERAN, - .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480}, - .channels = {1,2}}; - ::android::hardware::radio::V1_2::NetworkScanRequest request = { - .type = ScanType::ONE_SHOT, - .interval = 60, - .specifiers = {specifier}, - .maxSearchTime = 600, - .incrementalResults = false, - .incrementalResultsPeriodicity = 11}; + .type = ScanType::ONE_SHOT, + .interval = 60, + .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850}, + .maxSearchTime = 600, + .incrementalResults = false, + .incrementalResultsPeriodicity = 11}; Return res = radio_v1_2->startNetworkScan_1_2(serial, request); ASSERT_OK(res); @@ -311,20 +287,15 @@ TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidPeriodicity2) { TEST_F(RadioHidlTest_v1_2, startNetworkScan_GoodRequest1) { serial = GetRandomSerialNumber(); - RadioAccessSpecifier specifier = { - .radioAccessNetwork = RadioAccessNetworks::GERAN, - .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480}, - .channels = {1,2}}; - ::android::hardware::radio::V1_2::NetworkScanRequest request = { - .type = ScanType::ONE_SHOT, - .interval = 60, - .specifiers = {specifier}, - // Some vendor may not support max search time of 360s. - // This issue is tracked in b/112205669. - .maxSearchTime = 300, - .incrementalResults = false, - .incrementalResultsPeriodicity = 10}; + .type = ScanType::ONE_SHOT, + .interval = 60, + .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850}, + // Some vendor may not support max search time of 360s. + // This issue is tracked in b/112205669. + .maxSearchTime = 300, + .incrementalResults = false, + .incrementalResultsPeriodicity = 10}; Return res = radio_v1_2->startNetworkScan_1_2(serial, request); ASSERT_OK(res); @@ -350,21 +321,16 @@ TEST_F(RadioHidlTest_v1_2, startNetworkScan_GoodRequest1) { TEST_F(RadioHidlTest_v1_2, startNetworkScan_GoodRequest2) { serial = GetRandomSerialNumber(); - RadioAccessSpecifier specifier = { - .radioAccessNetwork = RadioAccessNetworks::GERAN, - .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480}, - .channels = {1,2}}; - ::android::hardware::radio::V1_2::NetworkScanRequest request = { - .type = ScanType::ONE_SHOT, - .interval = 60, - .specifiers = {specifier}, - // Some vendor may not support max search time of 360s. - // This issue is tracked in b/112205669. - .maxSearchTime = 300, - .incrementalResults = false, - .incrementalResultsPeriodicity = 10, - .mccMncs = {"310410"}}; + .type = ScanType::ONE_SHOT, + .interval = 60, + .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850}, + // Some vendor may not support max search time of 360s. + // This issue is tracked in b/112205669. + .maxSearchTime = 300, + .incrementalResults = false, + .incrementalResultsPeriodicity = 10, + .mccMncs = {"310410"}}; Return res = radio_v1_2->startNetworkScan_1_2(serial, request); ASSERT_OK(res); From 915115e381ff4c90c01ff8a11b4951624a4e1276 Mon Sep 17 00:00:00 2001 From: Shuzhen Wang Date: Fri, 10 May 2019 12:07:14 -0700 Subject: [PATCH 667/718] Camera: Add support for IMapper 3.0 Use IMapper 3.0 if available. Otherwise, fall back to IMapper 2.0. Test: Update camera VTS test passes Bug: 128013727 Change-Id: I9bb54bbc290f1b90ef593dee9796b22b0dd49671 --- camera/common/1.0/default/Android.bp | 1 + camera/common/1.0/default/HandleImporter.cpp | 244 +++++++++++------- .../1.0/default/include/HandleImporter.h | 13 +- camera/device/1.0/default/Android.bp | 1 + camera/device/3.2/default/Android.bp | 1 + camera/device/3.3/default/Android.bp | 1 + camera/device/3.4/default/Android.bp | 2 + camera/device/3.5/default/Android.bp | 2 + camera/provider/2.4/default/Android.bp | 2 + camera/provider/2.4/vts/functional/Android.bp | 2 + .../VtsHalCameraProviderV2_4TargetTest.cpp | 82 ++++-- 11 files changed, 237 insertions(+), 114 deletions(-) diff --git a/camera/common/1.0/default/Android.bp b/camera/common/1.0/default/Android.bp index 21f81f5acc..3e5c6d7812 100644 --- a/camera/common/1.0/default/Android.bp +++ b/camera/common/1.0/default/Android.bp @@ -20,6 +20,7 @@ cc_library_static { "libhardware", "libcamera_metadata", "android.hardware.graphics.mapper@2.0", + "android.hardware.graphics.mapper@3.0", "libexif", ], include_dirs: ["system/media/private/camera/include"], diff --git a/camera/common/1.0/default/HandleImporter.cpp b/camera/common/1.0/default/HandleImporter.cpp index 21706a84a3..b8c40e95b8 100644 --- a/camera/common/1.0/default/HandleImporter.cpp +++ b/camera/common/1.0/default/HandleImporter.cpp @@ -25,7 +25,9 @@ namespace common { namespace V1_0 { namespace helper { -using MapperError = android::hardware::graphics::mapper::V2_0::Error; +using MapperErrorV2 = android::hardware::graphics::mapper::V2_0::Error; +using MapperErrorV3 = android::hardware::graphics::mapper::V3_0::Error; +using IMapperV3 = android::hardware::graphics::mapper::V3_0::IMapper; HandleImporter::HandleImporter() : mInitialized(false) {} @@ -34,8 +36,14 @@ void HandleImporter::initializeLocked() { return; } - mMapper = IMapper::getService(); - if (mMapper == nullptr) { + mMapperV3 = IMapperV3::getService(); + if (mMapperV3 != nullptr) { + mInitialized = true; + return; + } + + mMapperV2 = IMapper::getService(); + if (mMapperV2 == nullptr) { ALOGE("%s: cannnot acccess graphics mapper HAL!", __FUNCTION__); return; } @@ -45,10 +53,90 @@ void HandleImporter::initializeLocked() { } void HandleImporter::cleanup() { - mMapper.clear(); + mMapperV3.clear(); + mMapperV2.clear(); mInitialized = false; } +template +bool HandleImporter::importBufferInternal(const sp mapper, buffer_handle_t& handle) { + E error; + buffer_handle_t importedHandle; + auto ret = mapper->importBuffer( + hidl_handle(handle), + [&](const auto& tmpError, const auto& tmpBufferHandle) { + error = tmpError; + importedHandle = static_cast(tmpBufferHandle); + }); + + if (!ret.isOk()) { + ALOGE("%s: mapper importBuffer failed: %s", + __FUNCTION__, ret.description().c_str()); + return false; + } + + if (error != E::NONE) { + return false; + } + + handle = importedHandle; + return true; +} + +template +YCbCrLayout HandleImporter::lockYCbCrInternal(const sp mapper, buffer_handle_t& buf, + uint64_t cpuUsage, const IMapper::Rect& accessRegion) { + hidl_handle acquireFenceHandle; + auto buffer = const_cast(buf); + YCbCrLayout layout = {}; + + typename M::Rect accessRegionCopy = {accessRegion.left, accessRegion.top, + accessRegion.width, accessRegion.height}; + mapper->lockYCbCr(buffer, cpuUsage, accessRegionCopy, acquireFenceHandle, + [&](const auto& tmpError, const auto& tmpLayout) { + if (tmpError == E::NONE) { + // Member by member copy from different versions of YCbCrLayout. + layout.y = tmpLayout.y; + layout.cb = tmpLayout.cb; + layout.cr = tmpLayout.cr; + layout.yStride = tmpLayout.yStride; + layout.cStride = tmpLayout.cStride; + layout.chromaStep = tmpLayout.chromaStep; + } else { + ALOGE("%s: failed to lockYCbCr error %d!", __FUNCTION__, tmpError); + } + }); + return layout; +} + +template +int HandleImporter::unlockInternal(const sp mapper, buffer_handle_t& buf) { + int releaseFence = -1; + auto buffer = const_cast(buf); + + mapper->unlock( + buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) { + if (tmpError == E::NONE) { + auto fenceHandle = tmpReleaseFence.getNativeHandle(); + if (fenceHandle) { + if (fenceHandle->numInts != 0 || fenceHandle->numFds != 1) { + ALOGE("%s: bad release fence numInts %d numFds %d", + __FUNCTION__, fenceHandle->numInts, fenceHandle->numFds); + return; + } + releaseFence = dup(fenceHandle->data[0]); + if (releaseFence < 0) { + ALOGE("%s: bad release fence FD %d", + __FUNCTION__, releaseFence); + } + } + } else { + ALOGE("%s: failed to unlock error %d!", __FUNCTION__, tmpError); + } + }); + return releaseFence; +} + // In IComposer, any buffer_handle_t is owned by the caller and we need to // make a clone for hwcomposer2. We also need to translate empty handle // to nullptr. This function does that, in-place. @@ -63,33 +151,16 @@ bool HandleImporter::importBuffer(buffer_handle_t& handle) { initializeLocked(); } - if (mMapper == nullptr) { - ALOGE("%s: mMapper is null!", __FUNCTION__); - return false; + if (mMapperV3 != nullptr) { + return importBufferInternal(mMapperV3, handle); } - MapperError error; - buffer_handle_t importedHandle; - auto ret = mMapper->importBuffer( - hidl_handle(handle), - [&](const auto& tmpError, const auto& tmpBufferHandle) { - error = tmpError; - importedHandle = static_cast(tmpBufferHandle); - }); - - if (!ret.isOk()) { - ALOGE("%s: mapper importBuffer failed: %s", - __FUNCTION__, ret.description().c_str()); - return false; + if (mMapperV2 != nullptr) { + return importBufferInternal(mMapperV2, handle); } - if (error != MapperError::NONE) { - return false; - } - - handle = importedHandle; - - return true; + ALOGE("%s: mMapperV3 and mMapperV2 are both null!", __FUNCTION__); + return false; } void HandleImporter::freeBuffer(buffer_handle_t handle) { @@ -98,15 +169,23 @@ void HandleImporter::freeBuffer(buffer_handle_t handle) { } Mutex::Autolock lock(mLock); - if (mMapper == nullptr) { - ALOGE("%s: mMapper is null!", __FUNCTION__); + if (mMapperV3 == nullptr && mMapperV2 == nullptr) { + ALOGE("%s: mMapperV3 and mMapperV2 are both null!", __FUNCTION__); return; } - auto ret = mMapper->freeBuffer(const_cast(handle)); - if (!ret.isOk()) { - ALOGE("%s: mapper freeBuffer failed: %s", - __FUNCTION__, ret.description().c_str()); + if (mMapperV3 != nullptr) { + auto ret = mMapperV3->freeBuffer(const_cast(handle)); + if (!ret.isOk()) { + ALOGE("%s: mapper freeBuffer failed: %s", + __FUNCTION__, ret.description().c_str()); + } + } else { + auto ret = mMapperV2->freeBuffer(const_cast(handle)); + if (!ret.isOk()) { + ALOGE("%s: mapper freeBuffer failed: %s", + __FUNCTION__, ret.description().c_str()); + } } } @@ -138,91 +217,82 @@ void* HandleImporter::lock( buffer_handle_t& buf, uint64_t cpuUsage, size_t size) { Mutex::Autolock lock(mLock); void *ret = 0; - IMapper::Rect accessRegion { 0, 0, static_cast(size), 1 }; if (!mInitialized) { initializeLocked(); } - if (mMapper == nullptr) { - ALOGE("%s: mMapper is null!", __FUNCTION__); + if (mMapperV3 == nullptr && mMapperV2 == nullptr) { + ALOGE("%s: mMapperV3 and mMapperV2 are both null!", __FUNCTION__); return ret; } hidl_handle acquireFenceHandle; auto buffer = const_cast(buf); - mMapper->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle, - [&](const auto& tmpError, const auto& tmpPtr) { - if (tmpError == MapperError::NONE) { - ret = tmpPtr; - } else { - ALOGE("%s: failed to lock error %d!", - __FUNCTION__, tmpError); - } - }); + if (mMapperV3 != nullptr) { + IMapperV3::Rect accessRegion { 0, 0, static_cast(size), 1 }; + // No need to use bytesPerPixel and bytesPerStride because we are using + // an 1-D buffer and accressRegion. + mMapperV3->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle, + [&](const auto& tmpError, const auto& tmpPtr, const auto& /*bytesPerPixel*/, + const auto& /*bytesPerStride*/) { + if (tmpError == MapperErrorV3::NONE) { + ret = tmpPtr; + } else { + ALOGE("%s: failed to lock error %d!", + __FUNCTION__, tmpError); + } + }); + } else { + IMapper::Rect accessRegion { 0, 0, static_cast(size), 1 }; + mMapperV2->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle, + [&](const auto& tmpError, const auto& tmpPtr) { + if (tmpError == MapperErrorV2::NONE) { + ret = tmpPtr; + } else { + ALOGE("%s: failed to lock error %d!", + __FUNCTION__, tmpError); + } + }); + } ALOGV("%s: ptr %p size: %zu", __FUNCTION__, ret, size); return ret; } - YCbCrLayout HandleImporter::lockYCbCr( buffer_handle_t& buf, uint64_t cpuUsage, const IMapper::Rect& accessRegion) { Mutex::Autolock lock(mLock); - YCbCrLayout layout = {}; if (!mInitialized) { initializeLocked(); } - if (mMapper == nullptr) { - ALOGE("%s: mMapper is null!", __FUNCTION__); - return layout; + if (mMapperV3 != nullptr) { + return lockYCbCrInternal( + mMapperV3, buf, cpuUsage, accessRegion); } - hidl_handle acquireFenceHandle; - auto buffer = const_cast(buf); - mMapper->lockYCbCr(buffer, cpuUsage, accessRegion, acquireFenceHandle, - [&](const auto& tmpError, const auto& tmpLayout) { - if (tmpError == MapperError::NONE) { - layout = tmpLayout; - } else { - ALOGE("%s: failed to lockYCbCr error %d!", __FUNCTION__, tmpError); - } - }); + if (mMapperV2 != nullptr) { + return lockYCbCrInternal( + mMapperV2, buf, cpuUsage, accessRegion); + } - ALOGV("%s: layout y %p cb %p cr %p y_str %d c_str %d c_step %d", - __FUNCTION__, layout.y, layout.cb, layout.cr, - layout.yStride, layout.cStride, layout.chromaStep); - return layout; + ALOGE("%s: mMapperV3 and mMapperV2 are both null!", __FUNCTION__); + return {}; } int HandleImporter::unlock(buffer_handle_t& buf) { - int releaseFence = -1; - auto buffer = const_cast(buf); - mMapper->unlock( - buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) { - if (tmpError == MapperError::NONE) { - auto fenceHandle = tmpReleaseFence.getNativeHandle(); - if (fenceHandle) { - if (fenceHandle->numInts != 0 || fenceHandle->numFds != 1) { - ALOGE("%s: bad release fence numInts %d numFds %d", - __FUNCTION__, fenceHandle->numInts, fenceHandle->numFds); - return; - } - releaseFence = dup(fenceHandle->data[0]); - if (releaseFence <= 0) { - ALOGE("%s: bad release fence FD %d", - __FUNCTION__, releaseFence); - } - } - } else { - ALOGE("%s: failed to unlock error %d!", __FUNCTION__, tmpError); - } - }); + if (mMapperV3 != nullptr) { + return unlockInternal(mMapperV3, buf); + } + if (mMapperV2 != nullptr) { + return unlockInternal(mMapperV2, buf); + } - return releaseFence; + ALOGE("%s: mMapperV3 and mMapperV2 are both null!", __FUNCTION__); + return -1; } } // namespace helper diff --git a/camera/common/1.0/default/include/HandleImporter.h b/camera/common/1.0/default/include/HandleImporter.h index f9cd9fb604..a93d4554ad 100644 --- a/camera/common/1.0/default/include/HandleImporter.h +++ b/camera/common/1.0/default/include/HandleImporter.h @@ -19,6 +19,7 @@ #include #include +#include #include using android::hardware::graphics::mapper::V2_0::IMapper; @@ -57,10 +58,18 @@ private: void initializeLocked(); void cleanup(); + template + bool importBufferInternal(const sp mapper, buffer_handle_t& handle); + template + YCbCrLayout lockYCbCrInternal(const sp mapper, buffer_handle_t& buf, uint64_t cpuUsage, + const IMapper::Rect& accessRegion); + template + int unlockInternal(const sp mapper, buffer_handle_t& buf); + Mutex mLock; bool mInitialized; - sp mMapper; - + sp mMapperV2; + sp mMapperV3; }; } // namespace helper diff --git a/camera/device/1.0/default/Android.bp b/camera/device/1.0/default/Android.bp index 4a7fc9c1e0..aa3b941c2e 100644 --- a/camera/device/1.0/default/Android.bp +++ b/camera/device/1.0/default/Android.bp @@ -15,6 +15,7 @@ cc_library_shared { "android.hardware.camera.common@1.0", "android.hardware.graphics.allocator@2.0", "android.hardware.graphics.mapper@2.0", + "android.hardware.graphics.mapper@3.0", "android.hardware.graphics.common@1.0", "android.hidl.allocator@1.0", "android.hidl.memory@1.0", diff --git a/camera/device/3.2/default/Android.bp b/camera/device/3.2/default/Android.bp index 325c0085a4..edb008ed62 100644 --- a/camera/device/3.2/default/Android.bp +++ b/camera/device/3.2/default/Android.bp @@ -13,6 +13,7 @@ cc_library_shared { "android.hardware.camera.device@3.2", "android.hardware.camera.provider@2.4", "android.hardware.graphics.mapper@2.0", + "android.hardware.graphics.mapper@3.0", "liblog", "libhardware", "libcamera_metadata", diff --git a/camera/device/3.3/default/Android.bp b/camera/device/3.3/default/Android.bp index b1e9b46d8f..39d379d049 100644 --- a/camera/device/3.3/default/Android.bp +++ b/camera/device/3.3/default/Android.bp @@ -15,6 +15,7 @@ cc_library_shared { "android.hardware.camera.device@3.3", "android.hardware.camera.provider@2.4", "android.hardware.graphics.mapper@2.0", + "android.hardware.graphics.mapper@3.0", "liblog", "libhardware", "libcamera_metadata", diff --git a/camera/device/3.4/default/Android.bp b/camera/device/3.4/default/Android.bp index 272bf42baa..c22b13c2c4 100644 --- a/camera/device/3.4/default/Android.bp +++ b/camera/device/3.4/default/Android.bp @@ -48,6 +48,7 @@ cc_library_shared { "android.hardware.camera.device@3.4", "android.hardware.camera.provider@2.4", "android.hardware.graphics.mapper@2.0", + "android.hardware.graphics.mapper@3.0", "liblog", "libhardware", "libcamera_metadata", @@ -84,6 +85,7 @@ cc_library_shared { "android.hardware.camera.device@3.4", "android.hardware.camera.provider@2.4", "android.hardware.graphics.mapper@2.0", + "android.hardware.graphics.mapper@3.0", "liblog", "libhardware", "libcamera_metadata", diff --git a/camera/device/3.5/default/Android.bp b/camera/device/3.5/default/Android.bp index 7a48865a3b..26b3b6734b 100644 --- a/camera/device/3.5/default/Android.bp +++ b/camera/device/3.5/default/Android.bp @@ -49,6 +49,7 @@ cc_library_shared { "android.hardware.camera.device@3.5", "android.hardware.camera.provider@2.4", "android.hardware.graphics.mapper@2.0", + "android.hardware.graphics.mapper@3.0", "liblog", "libhardware", "libcamera_metadata", @@ -82,6 +83,7 @@ cc_library_shared { "android.hardware.camera.device@3.5", "android.hardware.camera.provider@2.4", "android.hardware.graphics.mapper@2.0", + "android.hardware.graphics.mapper@3.0", "liblog", "libhardware", "libcamera_metadata", diff --git a/camera/provider/2.4/default/Android.bp b/camera/provider/2.4/default/Android.bp index 9d73934de0..cb78fcb859 100644 --- a/camera/provider/2.4/default/Android.bp +++ b/camera/provider/2.4/default/Android.bp @@ -12,6 +12,7 @@ cc_library_shared { "android.hardware.camera.device@3.5", "android.hardware.camera.provider@2.4", "android.hardware.graphics.mapper@2.0", + "android.hardware.graphics.mapper@3.0", "android.hidl.allocator@1.0", "android.hidl.memory@1.0", "camera.device@1.0-impl", @@ -50,6 +51,7 @@ cc_library_shared { "android.hardware.camera.device@3.5", "android.hardware.camera.provider@2.4", "android.hardware.graphics.mapper@2.0", + "android.hardware.graphics.mapper@3.0", "android.hidl.allocator@1.0", "android.hidl.memory@1.0", "camera.device@3.3-impl", diff --git a/camera/provider/2.4/vts/functional/Android.bp b/camera/provider/2.4/vts/functional/Android.bp index 5fb1fd852d..2c3ed37a6a 100644 --- a/camera/provider/2.4/vts/functional/Android.bp +++ b/camera/provider/2.4/vts/functional/Android.bp @@ -42,8 +42,10 @@ cc_test { "android.hardware.camera.provider@2.4", "android.hardware.camera.provider@2.5", "android.hardware.graphics.allocator@2.0", + "android.hardware.graphics.allocator@3.0", "android.hardware.graphics.common@1.0", "android.hardware.graphics.mapper@2.0", + "android.hardware.graphics.mapper@3.0", "android.hidl.allocator@1.0", "libgrallocusage", "libhidlmemory", diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp index 33d23a0030..200dd3f199 100644 --- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp +++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp @@ -54,8 +54,10 @@ #include #include +#include #include #include +#include #include #include #include @@ -6104,36 +6106,66 @@ void CameraHidlTest::allocateGraphicBuffer(uint32_t width, uint32_t height, uint sp allocator = android::hardware::graphics::allocator::V2_0::IAllocator::getService(); - ASSERT_NE(nullptr, allocator.get()); + sp allocatorV3 = + android::hardware::graphics::allocator::V3_0::IAllocator::getService(); + sp mapperV3 = + android::hardware::graphics::mapper::V3_0::IMapper::getService(); sp mapper = android::hardware::graphics::mapper::V2_0::IMapper::getService(); - ASSERT_NE(mapper.get(), nullptr); - - android::hardware::graphics::mapper::V2_0::IMapper::BufferDescriptorInfo descriptorInfo {}; - descriptorInfo.width = width; - descriptorInfo.height = height; - descriptorInfo.layerCount = 1; - descriptorInfo.format = format; - descriptorInfo.usage = usage; - ::android::hardware::hidl_vec descriptor; - auto ret = mapper->createDescriptor( - descriptorInfo, [&descriptor](android::hardware::graphics::mapper::V2_0::Error err, - ::android::hardware::hidl_vec desc) { - ASSERT_EQ(err, android::hardware::graphics::mapper::V2_0::Error::NONE); - descriptor = desc; - }); - ASSERT_TRUE(ret.isOk()); + if (mapperV3 != nullptr && allocatorV3 != nullptr) { + android::hardware::graphics::mapper::V3_0::IMapper::BufferDescriptorInfo descriptorInfo {}; + descriptorInfo.width = width; + descriptorInfo.height = height; + descriptorInfo.layerCount = 1; + descriptorInfo.format = + static_cast(format); + descriptorInfo.usage = usage; - ret = allocator->allocate(descriptor, 1u, - [&](android::hardware::graphics::mapper::V2_0::Error err, uint32_t /*stride*/, - const ::android::hardware::hidl_vec<::android::hardware::hidl_handle>& buffers) { - ASSERT_EQ(android::hardware::graphics::mapper::V2_0::Error::NONE, err); - ASSERT_EQ(buffers.size(), 1u); - *buffer_handle = buffers[0]; - }); - ASSERT_TRUE(ret.isOk()); + auto ret = mapperV3->createDescriptor( + descriptorInfo, [&descriptor](android::hardware::graphics::mapper::V3_0::Error err, + ::android::hardware::hidl_vec desc) { + ASSERT_EQ(err, android::hardware::graphics::mapper::V3_0::Error::NONE); + descriptor = desc; + }); + ASSERT_TRUE(ret.isOk()); + + ret = allocatorV3->allocate(descriptor, 1u, + [&](android::hardware::graphics::mapper::V3_0::Error err, uint32_t /*stride*/, + const ::android::hardware::hidl_vec<::android::hardware::hidl_handle>& buffers) { + ASSERT_EQ(android::hardware::graphics::mapper::V3_0::Error::NONE, err); + ASSERT_EQ(buffers.size(), 1u); + *buffer_handle = buffers[0]; + }); + ASSERT_TRUE(ret.isOk()); + } else { + ASSERT_NE(mapper.get(), nullptr); + ASSERT_NE(allocator.get(), nullptr); + android::hardware::graphics::mapper::V2_0::IMapper::BufferDescriptorInfo descriptorInfo {}; + descriptorInfo.width = width; + descriptorInfo.height = height; + descriptorInfo.layerCount = 1; + descriptorInfo.format = format; + descriptorInfo.usage = usage; + + auto ret = mapper->createDescriptor( + descriptorInfo, [&descriptor](android::hardware::graphics::mapper::V2_0::Error err, + ::android::hardware::hidl_vec desc) { + ASSERT_EQ(err, android::hardware::graphics::mapper::V2_0::Error::NONE); + descriptor = desc; + }); + ASSERT_TRUE(ret.isOk()); + + ret = allocator->allocate(descriptor, 1u, + [&](android::hardware::graphics::mapper::V2_0::Error err, uint32_t /*stride*/, + const ::android::hardware::hidl_vec<::android::hardware::hidl_handle>& buffers) { + ASSERT_EQ(android::hardware::graphics::mapper::V2_0::Error::NONE, err); + ASSERT_EQ(buffers.size(), 1u); + *buffer_handle = buffers[0]; + }); + ASSERT_TRUE(ret.isOk()); + } } void CameraHidlTest::verifyRecommendedConfigs(const CameraMetadata& chars) { From 2bc0c5f292370cff232f377af0bd1c74a7c2b10f Mon Sep 17 00:00:00 2001 From: Prachi Hande Date: Tue, 23 Apr 2019 10:50:07 -0700 Subject: [PATCH 668/718] Add utility methods to create and parse handshake messages. Bug:131165419 Fixes: 131165419 Test: Added new unit tests for both the new functions in VmsUtilsTest. Ran the tests on Hawk. Change-Id: Ie750983762b5706054ace35c5671f88b6457477a --- .../common/include/vhal_v2_0/VmsUtils.h | 42 +++++++-- .../2.0/default/common/src/VmsUtils.cpp | 63 ++++++++++--- .../2.0/default/tests/VmsUtils_test.cpp | 94 ++++++++++++++++++- 3 files changed, 178 insertions(+), 21 deletions(-) diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h index 258dbd97a4..7082566d2e 100644 --- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h +++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h @@ -105,6 +105,24 @@ struct VmsAvailabilityState { std::vector associated_layers; }; +// An enum to represent the result of parsing START_SESSION message from the VMS service. +enum VmsSessionStatus { + // New server session is received if the new client ID is -1 and the new server ID is not an + // invalid ID. + kNewServerSession, + // Ack to new client session is received if the new client ID is same as the old one and the new + // server ID is not an invalid ID. + kAckToNewClientSession, + // Error codes: + // Invalid message with either invalid format or unexpected data. + kInvalidMessage, + // Invalid server ID. New ID should always be greater than or equal to max_of(0, current server + // ID) + kInvalidServiceId, + // Invalid client ID. New ID should always be either -1 or the current client ID. + kInvalidClientId +}; + // Creates an empty base VMS message with some pre-populated default fields. std::unique_ptr createBaseVmsMessage(size_t message_size); @@ -146,11 +164,21 @@ std::unique_ptr createSubscriptionsRequest(); // Creates a VehiclePropValue containing a message of type VmsMessageType.DATA. // Returns a nullptr if the byte string in bytes is empty. // -// For example, to build a VehiclePropMessage containing a proto, the caller +// For example, to build a VehiclePropValue message containing a proto, the caller // should convert the proto to a byte string using the SerializeToString proto // API, then use this inteface to build the VehicleProperty. std::unique_ptr createDataMessage(const std::string& bytes); +// Creates a VehiclePropValue containing a message of type +// VmsMessageType.PUBLISHER_ID_REQUEST with the given publisher information. +// Returns a nullptr if the input is empty. +std::unique_ptr createPublisherIdRequest( + const std::string& vms_provider_description); + +// Creates a VehiclePropValue message of type VmsMessageType.START_SESSION. +std::unique_ptr createStartSessionMessage(const int service_id, + const int client_id); + // Returns true if the VehiclePropValue pointed to by value contains a valid Vms // message, i.e. the VehicleProperty, VehicleArea, and VmsMessageType are all // valid. Note: If the VmsMessageType enum is extended, this function will @@ -169,12 +197,6 @@ VmsMessageType parseMessageType(const VehiclePropValue& value); // function to ParseFromString. std::string parseData(const VehiclePropValue& value); -// Creates a VehiclePropValue containing a message of type -// VmsMessageType.PUBLISHER_ID_REQUEST with the given publisher information. -// Returns a nullptr if the input is empty. -std::unique_ptr createPublisherIdRequest( - const std::string& vms_provider_description); - // Returns the publisher ID by parsing the VehiclePropValue containing the ID. // Returns null if the message is invalid. int32_t parsePublisherIdResponse(const VehiclePropValue& publisher_id_response); @@ -204,6 +226,12 @@ std::vector getSubscribedLayers(const VehiclePropValue& subscription_c // has newly started or restarted. bool hasServiceNewlyStarted(const VehiclePropValue& availability_change); +// Takes a start session message, current service ID, current client ID; and returns the type/status +// of the message. It also populates the new service ID with the correct value. +VmsSessionStatus parseStartSessionMessage(const VehiclePropValue& start_session, + const int service_id, const int client_id, + int* new_service_id); + } // namespace vms } // namespace V2_0 } // namespace vehicle diff --git a/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp b/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp index 1863191ed9..111f6eac8e 100644 --- a/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp +++ b/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp @@ -31,6 +31,7 @@ static constexpr int kPublisherIdSize = 1; static constexpr int kLayerNumberSize = 1; static constexpr int kLayerSize = 3; static constexpr int kLayerAndPublisherSize = 4; +static constexpr int kSessionIdsSize = 2; static constexpr int kPublisherIdIndex = toInt(VmsPublisherInformationIntegerValuesIndex::PUBLISHER_ID); static constexpr int kSubscriptionStateSequenceNumberIndex = @@ -41,9 +42,9 @@ static constexpr int kAvailabilitySequenceNumberIndex = // TODO(aditin): We should extend the VmsMessageType enum to include a first and // last, which would prevent breakages in this API. However, for all of the // functions in this module, we only need to guarantee that the message type is -// between SUBSCRIBE and PUBLISHER_ID_RESPONSE. +// between SUBSCRIBE and START_SESSION. static constexpr int kFirstMessageType = toInt(VmsMessageType::SUBSCRIBE); -static constexpr int kLastMessageType = toInt(VmsMessageType::PUBLISHER_ID_RESPONSE); +static constexpr int kLastMessageType = toInt(VmsMessageType::START_SESSION); std::unique_ptr createBaseVmsMessage(size_t message_size) { auto result = createVehiclePropValue(VehiclePropertyType::INT32, message_size); @@ -132,6 +133,28 @@ std::unique_ptr createDataMessage(const std::string& bytes) { return result; } +std::unique_ptr createPublisherIdRequest( + const std::string& vms_provider_description) { + auto result = createBaseVmsMessage(kMessageTypeSize); + result->value.int32Values = hidl_vec{ + toInt(VmsMessageType::PUBLISHER_ID_REQUEST), + }; + result->value.bytes = + std::vector(vms_provider_description.begin(), vms_provider_description.end()); + return result; +} + +std::unique_ptr createStartSessionMessage(const int service_id, + const int client_id) { + auto result = createBaseVmsMessage(kMessageTypeSize + kSessionIdsSize); + result->value.int32Values = hidl_vec{ + toInt(VmsMessageType::START_SESSION), + service_id, + client_id, + }; + return result; +} + bool isValidVmsProperty(const VehiclePropValue& value) { return (value.prop == toInt(VehicleProperty::VEHICLE_MAP_SERVICE)); } @@ -159,17 +182,6 @@ std::string parseData(const VehiclePropValue& value) { } } -std::unique_ptr createPublisherIdRequest( - const std::string& vms_provider_description) { - auto result = createBaseVmsMessage(kMessageTypeSize); - result->value.int32Values = hidl_vec{ - toInt(VmsMessageType::PUBLISHER_ID_REQUEST), - }; - result->value.bytes = - std::vector(vms_provider_description.begin(), vms_provider_description.end()); - return result; -} - int32_t parsePublisherIdResponse(const VehiclePropValue& publisher_id_response) { if (isValidVmsMessage(publisher_id_response) && parseMessageType(publisher_id_response) == VmsMessageType::PUBLISHER_ID_RESPONSE && @@ -256,6 +268,31 @@ bool hasServiceNewlyStarted(const VehiclePropValue& availability_change) { availability_change.value.int32Values[kAvailabilitySequenceNumberIndex] == 0); } +VmsSessionStatus parseStartSessionMessage(const VehiclePropValue& start_session, + const int service_id, const int client_id, + int* new_service_id) { + if (isValidVmsMessage(start_session) && + parseMessageType(start_session) == VmsMessageType::START_SESSION && + start_session.value.int32Values.size() == kSessionIdsSize + 1) { + *new_service_id = start_session.value.int32Values[1]; + const int new_client_id = start_session.value.int32Values[2]; + if (*new_service_id < std::max(0, service_id)) { + *new_service_id = service_id; + return VmsSessionStatus::kInvalidServiceId; + } + if (new_client_id == -1) { + return VmsSessionStatus::kNewServerSession; + } + if (new_client_id == client_id) { + return VmsSessionStatus::kAckToNewClientSession; + } + *new_service_id = service_id; + return VmsSessionStatus::kInvalidClientId; + } + *new_service_id = service_id; + return VmsSessionStatus::kInvalidMessage; +} + } // namespace vms } // namespace V2_0 } // namespace vehicle diff --git a/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp b/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp index 5ea5bd45c5..2b3efc70f0 100644 --- a/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp +++ b/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp @@ -158,7 +158,7 @@ TEST(VmsUtilsTest, emptyMessageInvalid) { TEST(VmsUtilsTest, invalidMessageType) { VmsLayer layer(1, 0, 2); auto message = createSubscribeMessage(layer); - message->value.int32Values[0] = 0; + message->value.int32Values[0] = -1; EXPECT_FALSE(isValidVmsMessage(*message)); } @@ -325,6 +325,98 @@ TEST(VmsUtilsTest, invalidAvailabilityChange) { EXPECT_FALSE(hasServiceNewlyStarted(*message)); } +TEST(VmsUtilsTest, startSessionRequest) { + auto message = createStartSessionMessage(123, 456); + ASSERT_NE(message, nullptr); + EXPECT_TRUE(isValidVmsMessage(*message)); + EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE)); + EXPECT_EQ(message->value.int32Values.size(), 0x3ul); + EXPECT_EQ(parseMessageType(*message), VmsMessageType::START_SESSION); + EXPECT_EQ(message->value.int32Values[1], 123); + EXPECT_EQ(message->value.int32Values[2], 456); +} + +TEST(VmsUtilsTest, startSessionServiceNewlyStarted) { + auto message = createBaseVmsMessage(3); + int new_service_id; + message->value.int32Values = hidl_vec{toInt(VmsMessageType::START_SESSION), 123, -1}; + EXPECT_EQ(parseStartSessionMessage(*message, 122, 456, &new_service_id), + VmsSessionStatus::kNewServerSession); + EXPECT_EQ(new_service_id, 123); +} + +TEST(VmsUtilsTest, startSessionServiceNewlyStartedEdgeCase) { + auto message = createBaseVmsMessage(3); + int new_service_id; + message->value.int32Values = hidl_vec{toInt(VmsMessageType::START_SESSION), 0, -1}; + EXPECT_EQ(parseStartSessionMessage(*message, -1, 0, &new_service_id), + VmsSessionStatus::kNewServerSession); + EXPECT_EQ(new_service_id, 0); +} + +TEST(VmsUtilsTest, startSessionClientNewlyStarted) { + auto message = createBaseVmsMessage(3); + int new_service_id; + message->value.int32Values = hidl_vec{toInt(VmsMessageType::START_SESSION), 123, 456}; + EXPECT_EQ(parseStartSessionMessage(*message, -1, 456, &new_service_id), + VmsSessionStatus::kAckToNewClientSession); + EXPECT_EQ(new_service_id, 123); +} + +TEST(VmsUtilsTest, startSessionClientNewlyStartedWithSameServerId) { + auto message = createBaseVmsMessage(3); + int new_service_id; + message->value.int32Values = hidl_vec{toInt(VmsMessageType::START_SESSION), 123, 456}; + EXPECT_EQ(parseStartSessionMessage(*message, 123, 456, &new_service_id), + VmsSessionStatus::kAckToNewClientSession); + EXPECT_EQ(new_service_id, 123); +} + +TEST(VmsUtilsTest, startSessionClientNewlyStartedEdgeCase) { + auto message = createBaseVmsMessage(3); + int new_service_id; + message->value.int32Values = hidl_vec{toInt(VmsMessageType::START_SESSION), 0, 0}; + EXPECT_EQ(parseStartSessionMessage(*message, 0, 0, &new_service_id), + VmsSessionStatus::kAckToNewClientSession); + EXPECT_EQ(new_service_id, 0); +} + +TEST(VmsUtilsTest, startSessionOldServiceId) { + auto message = createBaseVmsMessage(3); + int new_service_id; + message->value.int32Values = hidl_vec{toInt(VmsMessageType::START_SESSION), 120, 456}; + EXPECT_EQ(parseStartSessionMessage(*message, 123, 456, &new_service_id), + VmsSessionStatus::kInvalidServiceId); + EXPECT_EQ(new_service_id, 123); +} + +TEST(VmsUtilsTest, startSessionInvalidServiceIdEdgeCase) { + auto message = createBaseVmsMessage(3); + int new_service_id; + message->value.int32Values = hidl_vec{toInt(VmsMessageType::START_SESSION), -1, 456}; + EXPECT_EQ(parseStartSessionMessage(*message, -1, 456, &new_service_id), + VmsSessionStatus::kInvalidServiceId); + EXPECT_EQ(new_service_id, -1); +} + +TEST(VmsUtilsTest, startSessionInvalidClientId) { + auto message = createBaseVmsMessage(3); + int new_service_id; + message->value.int32Values = hidl_vec{toInt(VmsMessageType::START_SESSION), 123, 457}; + EXPECT_EQ(parseStartSessionMessage(*message, 123, 456, &new_service_id), + VmsSessionStatus::kInvalidClientId); + EXPECT_EQ(new_service_id, 123); +} + +TEST(VmsUtilsTest, startSessionInvalidMessageFormat) { + auto message = createBaseVmsMessage(2); + int new_service_id; + message->value.int32Values = hidl_vec{toInt(VmsMessageType::START_SESSION), 123}; + EXPECT_EQ(parseStartSessionMessage(*message, 123, 456, &new_service_id), + VmsSessionStatus::kInvalidMessage); + EXPECT_EQ(new_service_id, 123); +} + } // namespace } // namespace vms From d780fb427208d61116484000a551bb14acdb1340 Mon Sep 17 00:00:00 2001 From: Scott Randolph Date: Tue, 14 May 2019 12:55:43 -0700 Subject: [PATCH 669/718] Add pfg@ to owners for automotive HALs Test: NA Bug: 132709887 Change-Id: I68fe2c165cd7e4783bb7465bdc3a3eb149a97db4 --- automotive/OWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/automotive/OWNERS b/automotive/OWNERS index 4a944944f6..3cf4489e9a 100644 --- a/automotive/OWNERS +++ b/automotive/OWNERS @@ -1,3 +1,4 @@ randolphs@google.com pirozzoj@google.com twasilczyk@google.com +pfg@google.com From 8a9e5a645b3da0092e7380482e7a3c3838a82e08 Mon Sep 17 00:00:00 2001 From: Youming Ye Date: Wed, 15 May 2019 16:31:52 -0700 Subject: [PATCH 670/718] Add mnc and mcc string check Use the same resolution as 1.0 to check for invalid mnc and mcc values. Bug: 130206359 Test: Vts Change-Id: Iff766014ecfbe2d77db6771eda04fd4d9c84df14 --- radio/1.2/vts/functional/radio_hidl_hal_api.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp index 730d9696aa..828297f02c 100644 --- a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp +++ b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp @@ -757,6 +757,7 @@ TEST_F(RadioHidlTest_v1_2, getDataRegistrationState) { // Check the mcc [0, 999] and mnc [0, 999]. string hidl_mcc; string hidl_mnc; + bool checkMccMnc = true; int totalIdentitySizeExpected = 1; ::android::hardware::radio::V1_2::CellIdentity cellIdentities = radioRsp_v1_2->dataRegResp.cellIdentity; @@ -765,6 +766,7 @@ TEST_F(RadioHidlTest_v1_2, getDataRegistrationState) { if (cellInfoType == CellInfoType::NONE) { // All the fields are 0 totalIdentitySizeExpected = 0; + checkMccMnc = false; } else if (cellInfoType == CellInfoType::GSM) { EXPECT_EQ(1, cellIdentities.cellIdentityGsm.size()); ::android::hardware::radio::V1_2::CellIdentityGsm cig = cellIdentities.cellIdentityGsm[0]; @@ -791,6 +793,7 @@ TEST_F(RadioHidlTest_v1_2, getDataRegistrationState) { // CellIndentityCdma has no mcc and mnc. EXPECT_EQ(CellInfoType::CDMA, cellInfoType); EXPECT_EQ(1, cellIdentities.cellIdentityCdma.size()); + checkMccMnc = false; } // Check only one CellIdentity is size 1, and others must be 0. @@ -799,10 +802,13 @@ TEST_F(RadioHidlTest_v1_2, getDataRegistrationState) { cellIdentities.cellIdentityLte.size() + cellIdentities.cellIdentityWcdma.size() + cellIdentities.cellIdentityTdscdma.size()); - int mcc = stoi(hidl_mcc); - int mnc = stoi(hidl_mnc); - EXPECT_TRUE(mcc >= 0 && mcc <= 999); - EXPECT_TRUE(mnc >= 0 && mnc <= 999); + // 32 bit system might return invalid mcc and mnc hidl string "\xff\xff..." + if (checkMccMnc && hidl_mcc.size() < 4 && hidl_mnc.size() < 4) { + int mcc = stoi(hidl_mcc); + int mnc = stoi(hidl_mnc); + EXPECT_TRUE(mcc >= 0 && mcc <= 999); + EXPECT_TRUE(mnc >= 0 && mnc <= 999); + } } /* From 8236850bc0cde5a870109b93421ad5d74eb79fd4 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Thu, 16 May 2019 12:53:02 -0700 Subject: [PATCH 671/718] wifi(implementation): Invalidate NAN iface on STA iface removal NAN iface/RTT controllers are sharing the STA iface. When a STA iface is removed, we should remove these dependent modules as well to ensure proper cleanup. Bug: 132837537 Test: ./hardware/interfaces/wifi/1.3/default/tests/runtests.sh Test: Will send for regression tests. Change-Id: Ia2da1dcf66b388f54e916ae69e2f4e26f20ecfad --- .../default/tests/wifi_chip_unit_tests.cpp | 67 +++++++++++++++++++ wifi/1.3/default/wifi_chip.cpp | 28 ++++++++ wifi/1.3/default/wifi_chip.h | 3 + wifi/1.3/default/wifi_rtt_controller.cpp | 2 + wifi/1.3/default/wifi_rtt_controller.h | 1 + 5 files changed, 101 insertions(+) diff --git a/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp index 7928328489..22359e956c 100644 --- a/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp +++ b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp @@ -700,6 +700,72 @@ TEST_F(WifiChipV2_AwareIfaceCombinationTest, SelectTxScenarioWithOnlyAp) { }); } +TEST_F(WifiChipV2_AwareIfaceCombinationTest, + InvalidateAndRemoveNanOnStaRemove) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_EQ(createIface(IfaceType::STA), "wlan0"); + + // Create NAN iface + ASSERT_EQ(createIface(IfaceType::NAN), "wlan0"); + + // We should have 1 nan iface. + chip_->getNanIfaceNames( + [](const WifiStatus& status, const hidl_vec& iface_names) { + ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); + ASSERT_EQ(iface_names.size(), 1u); + ASSERT_EQ(iface_names[0], "wlan0"); + }); + // Retrieve the exact iface object. + sp nan_iface; + chip_->getNanIface("wlan0", [&nan_iface](const WifiStatus& status, + const sp& iface) { + ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); + ASSERT_NE(iface.get(), nullptr); + nan_iface = iface; + }); + + // Remove the STA iface. + removeIface(IfaceType::STA, "wlan0"); + // We should have 0 nan iface now. + chip_->getNanIfaceNames( + [](const WifiStatus& status, const hidl_vec& iface_names) { + ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); + ASSERT_EQ(iface_names.size(), 0u); + }); + // Any operation on the nan iface object should return error now. + nan_iface->getName( + [](const WifiStatus& status, const std::string& /* iface_name */) { + ASSERT_EQ(WifiStatusCode::ERROR_WIFI_IFACE_INVALID, status.code); + }); +} + +TEST_F(WifiChipV2_AwareIfaceCombinationTest, + InvalidateAndRemoveRttControllerOnStaRemove) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_EQ(createIface(IfaceType::STA), "wlan0"); + + // Create RTT controller + sp rtt_controller; + chip_->createRttController( + NULL, [&rtt_controller](const WifiStatus& status, + const sp& rtt) { + if (WifiStatusCode::SUCCESS == status.code) { + ASSERT_NE(rtt.get(), nullptr); + rtt_controller = rtt; + } + }); + + // Remove the STA iface. + removeIface(IfaceType::STA, "wlan0"); + + // Any operation on the rtt controller object should return error now. + rtt_controller->getBoundIface( + [](const WifiStatus& status, const sp& /* iface */) { + ASSERT_EQ(WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + status.code); + }); +} + ////////// V1 Iface Combinations when AP creation is disabled ////////// class WifiChipV1_AwareDisabledApIfaceCombinationTest : public WifiChipTest { public: @@ -732,6 +798,7 @@ TEST_F(WifiChipV2_AwareDisabledApIfaceCombinationTest, ASSERT_TRUE(createIface(IfaceType::AP).empty()); } +////////// Hypothetical Iface Combination with multiple ifaces ////////// class WifiChip_MultiIfaceTest : public WifiChipTest { public: void SetUp() override { diff --git a/wifi/1.3/default/wifi_chip.cpp b/wifi/1.3/default/wifi_chip.cpp index b768959f2a..27320c407b 100644 --- a/wifi/1.3/default/wifi_chip.cpp +++ b/wifi/1.3/default/wifi_chip.cpp @@ -634,6 +634,27 @@ void WifiChip::invalidateAndRemoveAllIfaces() { rtt_controllers_.clear(); } +void WifiChip::invalidateAndRemoveDependencies( + const std::string& removed_iface_name) { + for (const auto& nan_iface : nan_ifaces_) { + if (nan_iface->getName() == removed_iface_name) { + invalidateAndClear(nan_ifaces_, nan_iface); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback + ->onIfaceRemoved(IfaceType::NAN, removed_iface_name) + .isOk()) { + LOG(ERROR) << "Failed to invoke onIfaceRemoved callback"; + } + } + } + } + for (const auto& rtt : rtt_controllers_) { + if (rtt->getIfaceName() == removed_iface_name) { + invalidateAndClear(rtt_controllers_, rtt); + } + } +} + std::pair WifiChip::getIdInternal() { return {createWifiStatus(WifiStatusCode::SUCCESS), chip_id_}; } @@ -819,6 +840,11 @@ WifiStatus WifiChip::removeApIfaceInternal(const std::string& ifname) { if (!iface.get()) { return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); } + // Invalidate & remove any dependent objects first. + // Note: This is probably not required because we never create + // nan/rtt objects over AP iface. But, there is no harm to do it + // here and not make that assumption all over the place. + invalidateAndRemoveDependencies(ifname); invalidateAndClear(ap_ifaces_, iface); for (const auto& callback : event_cb_handler_.getCallbacks()) { if (!callback->onIfaceRemoved(IfaceType::AP, ifname).isOk()) { @@ -960,6 +986,8 @@ WifiStatus WifiChip::removeStaIfaceInternal(const std::string& ifname) { if (!iface.get()) { return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); } + // Invalidate & remove any dependent objects first. + invalidateAndRemoveDependencies(ifname); invalidateAndClear(sta_ifaces_, iface); for (const auto& callback : event_cb_handler_.getCallbacks()) { if (!callback->onIfaceRemoved(IfaceType::STA, ifname).isOk()) { diff --git a/wifi/1.3/default/wifi_chip.h b/wifi/1.3/default/wifi_chip.h index 3d12f4c9b7..d5ae900247 100644 --- a/wifi/1.3/default/wifi_chip.h +++ b/wifi/1.3/default/wifi_chip.h @@ -155,6 +155,9 @@ class WifiChip : public V1_3::IWifiChip { private: void invalidateAndRemoveAllIfaces(); + // When a STA iface is removed any dependent NAN-ifaces/RTT-controllers are + // invalidated & removed. + void invalidateAndRemoveDependencies(const std::string& removed_iface_name); // Corresponding worker functions for the HIDL methods. std::pair getIdInternal(); diff --git a/wifi/1.3/default/wifi_rtt_controller.cpp b/wifi/1.3/default/wifi_rtt_controller.cpp index fa317e3aeb..3dcbee687b 100644 --- a/wifi/1.3/default/wifi_rtt_controller.cpp +++ b/wifi/1.3/default/wifi_rtt_controller.cpp @@ -49,6 +49,8 @@ WifiRttController::getEventCallbacks() { return event_callbacks_; } +std::string WifiRttController::getIfaceName() { return ifname_; } + Return WifiRttController::getBoundIface(getBoundIface_cb hidl_status_cb) { return validateAndCall( this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, diff --git a/wifi/1.3/default/wifi_rtt_controller.h b/wifi/1.3/default/wifi_rtt_controller.h index 9798b79f8d..eedd22aeef 100644 --- a/wifi/1.3/default/wifi_rtt_controller.h +++ b/wifi/1.3/default/wifi_rtt_controller.h @@ -42,6 +42,7 @@ class WifiRttController : public V1_0::IWifiRttController { void invalidate(); bool isValid(); std::vector> getEventCallbacks(); + std::string getIfaceName(); // HIDL methods exposed. Return getBoundIface(getBoundIface_cb hidl_status_cb) override; From 52b35030640e960b6ff6ba98ca2c68eb7cb8b6a7 Mon Sep 17 00:00:00 2001 From: Nazanin Bakhshi Date: Wed, 15 May 2019 15:28:42 -0700 Subject: [PATCH 672/718] Add INVALID_STATE to list of errors for when there is only one modem available Bug: b/132818184 Test: VTS Change-Id: I2b57ab99a376bcab26012d08f00284d65f915bc3 --- current.txt | 1 + radio/1.3/IRadioResponse.hal | 3 +++ radio/1.3/vts/functional/radio_hidl_hal_api.cpp | 4 ++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/current.txt b/current.txt index 64fd4ae2e1..cd338830a1 100644 --- a/current.txt +++ b/current.txt @@ -525,6 +525,7 @@ abf98c2ae08bf765db54edc8068e36d52eb558cff6706b6fd7c18c65a1f3fc18 android.hardwar a1c6b0761bcb89d6bf15a156f9306b8090b3a916a15fea1689b4b0c1738e382f android.hardware.radio@1.3::IRadio e9d0f11a52715f5a29d89e2d8e2e21db1e16a43174af6b9d51a62d705cda1455 android.hardware.radio@1.3::IRadioIndication d233f0da44f55fdef0a95db5229231412787bb67695cd1ea197ce89a3c2908b9 android.hardware.radio@1.3::IRadioResponse +f5fbe4f28a9e346be36063eca4e6c864114a1a6fb64884db03fdd825791ad9b8 android.hardware.radio@1.3::IRadioResponse # b/132818184 for Android Q 750a363c8cec70baa1aac19e275c15233c5898e93c6bb5155fa2ca7f365490dc android.hardware.radio@1.3::types ef4ab741f7e7762fb45e2e24ca83871f72006ce05f57aa9addc574893dd29872 android.hardware.radio@1.4::IRadio 33d9e6895cca98aa56296bb01720d18b8acd0e4de4960beb712e63ad147438a5 android.hardware.radio@1.4::IRadioIndication diff --git a/radio/1.3/IRadioResponse.hal b/radio/1.3/IRadioResponse.hal index c3bbe659e6..85085e21e4 100644 --- a/radio/1.3/IRadioResponse.hal +++ b/radio/1.3/IRadioResponse.hal @@ -44,6 +44,9 @@ interface IRadioResponse extends @1.2::IRadioResponse { * RadioError:NONE * RadioError:RADIO_NOT_AVAILABLE * RadioError:MODEM_ERR + * RadioError:INVALID_STATE: this is for the case that the API is called in a single-sim + * mode, or when there is only one modem available, as this API should only + * be called in multi sim status. */ oneway enableModemResponse(RadioResponseInfo info); diff --git a/radio/1.3/vts/functional/radio_hidl_hal_api.cpp b/radio/1.3/vts/functional/radio_hidl_hal_api.cpp index 5b7a06de87..813dd133a5 100644 --- a/radio/1.3/vts/functional/radio_hidl_hal_api.cpp +++ b/radio/1.3/vts/functional/radio_hidl_hal_api.cpp @@ -35,7 +35,7 @@ TEST_F(RadioHidlTest_v1_3, enableModem) { toString(radioRsp_v1_3->rspInfo.error).c_str()); ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_3->rspInfo.error, {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, - RadioError::MODEM_ERR, RadioError::REQUEST_NOT_SUPPORTED})); + RadioError::MODEM_ERR, RadioError::INVALID_STATE})); // checking if getModemStackStatus returns true, as modem was enabled above if (RadioError::NONE == radioRsp_v1_3->rspInfo.error) { @@ -52,7 +52,7 @@ TEST_F(RadioHidlTest_v1_3, enableModem) { toString(radioRsp_v1_3->rspInfo.error).c_str()); ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_3->rspInfo.error, {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, - RadioError::MODEM_ERR, RadioError::REQUEST_NOT_SUPPORTED})); + RadioError::MODEM_ERR, RadioError::INVALID_STATE})); // verify that enableModem did set isEnabled correctly EXPECT_EQ(true, radioRsp_v1_3->isModemEnabled); } From dbb7d0d3049feb2151fec510a4002ff5068262cf Mon Sep 17 00:00:00 2001 From: Kevin Rocard Date: Mon, 20 May 2019 15:04:49 -0700 Subject: [PATCH 673/718] Validate HAL mic input Input value were not checked, resulting in out of range input accepted. This was checked by test but never implemented in the default HAL. Bug: 133105753 Test: atest VtsHalAudioV5_0Target Change-Id: Ie6dae638b60daff6923668dc9637067f29e48b21 Signed-off-by: Kevin Rocard --- .../include/common/all-versions/HidlSupport.h | 34 +++++++++++++++++++ audio/core/all-versions/default/StreamIn.cpp | 10 ++++++ 2 files changed, 44 insertions(+) create mode 100644 audio/common/all-versions/util/include/common/all-versions/HidlSupport.h diff --git a/audio/common/all-versions/util/include/common/all-versions/HidlSupport.h b/audio/common/all-versions/util/include/common/all-versions/HidlSupport.h new file mode 100644 index 0000000000..b514a43a85 --- /dev/null +++ b/audio/common/all-versions/util/include/common/all-versions/HidlSupport.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2019 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_audio_common_HidlSupport_H_ +#define android_hardware_audio_common_HidlSupport_H_ + + +#include +#include + +namespace android::hardware::audio::common::utils { + +template +bool isValidHidlEnum(Enum e) { + hidl_enum_range values; + return std::find(values.begin(), values.end(), e) != values.end(); +} + +} // namespace android::hardware::audio::common::utils + +#endif // android_hardware_audio_common_HidlSupport_H_ diff --git a/audio/core/all-versions/default/StreamIn.cpp b/audio/core/all-versions/default/StreamIn.cpp index daba6f7ef2..d316f83617 100644 --- a/audio/core/all-versions/default/StreamIn.cpp +++ b/audio/core/all-versions/default/StreamIn.cpp @@ -19,6 +19,7 @@ #include "core/default/StreamIn.h" #include "core/default/Conversions.h" #include "core/default/Util.h" +#include "common/all-versions/HidlSupport.h" //#define LOG_NDEBUG 0 #define ATRACE_TAG ATRACE_TAG_AUDIO @@ -27,6 +28,7 @@ #include #include #include +#include namespace android { namespace hardware { @@ -501,6 +503,10 @@ Return StreamIn::setMicrophoneDirection(MicrophoneDirection direction) { if (mStream->set_microphone_direction == nullptr) { return Result::NOT_SUPPORTED; } + if (!common::utils::isValidHidlEnum(direction)) { + ALOGE("%s: Invalid direction %d", __func__, direction); + return Result::INVALID_ARGUMENTS; + } return Stream::analyzeStatus( "set_microphone_direction", mStream->set_microphone_direction( @@ -511,6 +517,10 @@ Return StreamIn::setMicrophoneFieldDimension(float zoom) { if (mStream->set_microphone_field_dimension == nullptr) { return Result::NOT_SUPPORTED; } + if (std::isnan(zoom) || zoom < -1 || zoom > 1) { + ALOGE("%s: Invalid zoom %f", __func__, zoom); + return Result::INVALID_ARGUMENTS; + } return Stream::analyzeStatus("set_microphone_field_dimension", mStream->set_microphone_field_dimension(mStream, zoom)); } From 0c6f8b68593fd71ea5569145e12bbeaeae29c30d Mon Sep 17 00:00:00 2001 From: Shuzhen Wang Date: Mon, 20 May 2019 17:25:55 -0700 Subject: [PATCH 674/718] Camera: Fix remaining OWNER file include Bug: 133188173 Test: None Change-Id: I2da75bf9a7480974b3ca1c6eea52a58b46b0cc97 --- camera/common/1.0/default/OWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/camera/common/1.0/default/OWNERS b/camera/common/1.0/default/OWNERS index 70128c7f21..f48a95c5b3 100644 --- a/camera/common/1.0/default/OWNERS +++ b/camera/common/1.0/default/OWNERS @@ -1 +1 @@ -include platform/frameworks/av:camera/OWNERS +include platform/frameworks/av:/camera/OWNERS From ac4edf053e6862477b6269e96b4e19738c96643d Mon Sep 17 00:00:00 2001 From: Kai Date: Tue, 23 Apr 2019 13:20:09 -0700 Subject: [PATCH 675/718] Update VHAL documentation Clarify when range in VehcileAreaConfig need to be specified. Change Range_remaining to be read only. Update docmentation about Night Mode. Bug: 126908895 Bug: 128607457 Test: Flash and build Change-Id: Ifcf92bcc9eed3859d8a846d55e824c2b00d61d19 --- automotive/vehicle/2.0/types.hal | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal index b04d0962c4..91197a55c9 100644 --- a/automotive/vehicle/2.0/types.hal +++ b/automotive/vehicle/2.0/types.hal @@ -641,7 +641,9 @@ enum VehicleProperty : int32_t { /** * Night mode * - * True indicates that night mode is currently enabled. + * True indicates that the night mode sensor has detected that the car cabin environment has + * low light. The platform could use this, for example, to enable appropriate UI for + * better viewing in dark or low light environments. * * @change_mode VehiclePropertyChangeMode:ON_CHANGE * @access VehiclePropertyAccess:READ @@ -983,6 +985,10 @@ enum VehicleProperty : int32_t { * * Indicates whether the vehicle is displaying temperature to the user as * Celsius or Fahrenheit. + * VehiclePropConfig.configArray is used to indicate the supported temperature display units. + * For example: configArray[0] = CELSIUS + * configArray[1] = FAHRENHEIT + * * This parameter MAY be used for displaying any HVAC temperature in the system. * Values must be one of VehicleUnit::CELSIUS or VehicleUnit::FAHRENHEIT * Note that internally, all temperatures are represented in floating point Celsius. @@ -2770,6 +2776,14 @@ struct VehicleAreaConfig { */ int32_t areaId; + /** + * If the property has @data_enum, leave the range to zero. + * + * Range will be ignored in the following cases: + * - The VehiclePropertyType is not INT32, INT64 or FLOAT. + * - Both of min value and max value are zero. + */ + int32_t minInt32Value; int32_t maxInt32Value; From bdebb008a1bab9d0464a9264d8f7df415f382b21 Mon Sep 17 00:00:00 2001 From: Jordan Liu Date: Mon, 4 Mar 2019 15:00:24 -0800 Subject: [PATCH 676/718] Fix RadioConfig 1.0 vts test Bug: 122730535 Test: VtsHalRadioConfigV1_0Target Change-Id: Ib3843e9ce727f97972f76e69cf9b450124f7afae --- .../1.0/vts/functional/radio_config_response.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/radio/config/1.0/vts/functional/radio_config_response.cpp b/radio/config/1.0/vts/functional/radio_config_response.cpp index 97e8dca7e9..a92db64f7b 100644 --- a/radio/config/1.0/vts/functional/radio_config_response.cpp +++ b/radio/config/1.0/vts/functional/radio_config_response.cpp @@ -21,11 +21,15 @@ SimSlotStatus slotStatus; RadioConfigResponse::RadioConfigResponse(RadioConfigHidlTest& parent) : parent(parent) {} Return RadioConfigResponse::getSimSlotsStatusResponse( - const RadioResponseInfo& /* info */, - const ::android::hardware::hidl_vec& /* slotStatus */) { + const RadioResponseInfo& info, + const ::android::hardware::hidl_vec& /* slotStatus */) { + rspInfo = info; + parent.notify(); return Void(); } -Return RadioConfigResponse::setSimSlotsMappingResponse(const RadioResponseInfo& /* info */) { +Return RadioConfigResponse::setSimSlotsMappingResponse(const RadioResponseInfo& info) { + rspInfo = info; + parent.notify(); return Void(); -} \ No newline at end of file +} From 222803af276628667b3aff55845711149b731a7e Mon Sep 17 00:00:00 2001 From: Yifan Hong Date: Tue, 23 Apr 2019 12:05:27 -0700 Subject: [PATCH 677/718] Add current compatibility matrix for R. Bug: 126892442 Test: builds Change-Id: I1cccddf0736e0ffd5e3b5bb2da3bb5a32773f2f5 --- compatibility_matrices/Android.bp | 13 + compatibility_matrices/Android.mk | 1 + .../compatibility_matrix.current.xml | 509 ++++++++++++++++++ 3 files changed, 523 insertions(+) create mode 100644 compatibility_matrices/compatibility_matrix.current.xml diff --git a/compatibility_matrices/Android.bp b/compatibility_matrices/Android.bp index 7a779b93ec..799ab07ce2 100644 --- a/compatibility_matrices/Android.bp +++ b/compatibility_matrices/Android.bp @@ -75,3 +75,16 @@ vintf_compatibility_matrix { "kernel_config_q_4.19", ] } + +vintf_compatibility_matrix { + name: "framework_compatibility_matrix.current.xml", + stem: "compatibility_matrix.current.xml", + srcs: [ + "compatibility_matrix.current.xml", + ], + kernel_configs: [ + "kernel_config_current_4.9", + "kernel_config_current_4.14", + "kernel_config_current_4.19", + ] +} diff --git a/compatibility_matrices/Android.mk b/compatibility_matrices/Android.mk index b0caa7c367..7c7f87f655 100644 --- a/compatibility_matrices/Android.mk +++ b/compatibility_matrices/Android.mk @@ -97,6 +97,7 @@ my_system_matrix_deps := \ framework_compatibility_matrix.2.xml \ framework_compatibility_matrix.3.xml \ framework_compatibility_matrix.4.xml \ + framework_compatibility_matrix.current.xml \ framework_compatibility_matrix.device.xml \ my_framework_matrix_deps += \ diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml new file mode 100644 index 0000000000..59af5d0e90 --- /dev/null +++ b/compatibility_matrices/compatibility_matrix.current.xml @@ -0,0 +1,509 @@ + + + android.hardware.atrace + 1.0 + + IAtraceDevice + default + + + + android.hardware.audio + 5.0 + + IDevicesFactory + default + + + + android.hardware.audio.effect + 5.0 + + IEffectsFactory + default + + + + android.hardware.authsecret + 1.0 + + IAuthSecret + default + + + + android.hardware.automotive.audiocontrol + 1.0 + + IAudioControl + default + + + + android.hardware.automotive.evs + 1.0 + + IEvsEnumerator + default + + + + android.hardware.automotive.vehicle + 2.0 + + IVehicle + default + + + + android.hardware.biometrics.face + 1.0 + + IBiometricsFace + default + + + + android.hardware.biometrics.fingerprint + 2.1 + + IBiometricsFingerprint + default + + + + android.hardware.bluetooth + 1.0 + + IBluetoothHci + default + + + + android.hardware.bluetooth.audio + 2.0 + + IBluetoothAudioProvidersFactory + default + + + + android.hardware.boot + 1.0 + + IBootControl + default + + + + android.hardware.broadcastradio + 1.0-1 + + IBroadcastRadioFactory + default + + + + android.hardware.broadcastradio + 2.0 + + IBroadcastRadio + .* + + + + android.hardware.camera.provider + 2.4-5 + + ICameraProvider + [^/]+/[0-9]+ + + + + android.hardware.cas + 1.1 + + IMediaCasService + default + + + + android.hardware.configstore + 1.1 + + ISurfaceFlingerConfigs + default + + + + android.hardware.confirmationui + 1.0 + + IConfirmationUI + default + + + + android.hardware.contexthub + 1.0 + + IContexthub + default + + + + android.hardware.drm + 1.0-2 + + ICryptoFactory + .* + + + IDrmFactory + .* + + + + android.hardware.dumpstate + 1.0 + + IDumpstateDevice + default + + + + android.hardware.gatekeeper + 1.0 + + IGatekeeper + default + + + + android.hardware.gnss + + 1.1 + 2.0 + + IGnss + default + + + + android.hardware.graphics.allocator + 2.0 + 3.0 + + IAllocator + default + + + + android.hardware.graphics.composer + 2.1-3 + + IComposer + default + + + + android.hardware.graphics.mapper + 2.1 + 3.0 + + IMapper + default + + + + android.hardware.health + 2.0 + + IHealth + default + + + + android.hardware.health.storage + 1.0 + + IStorage + default + + + + android.hardware.ir + 1.0 + + IConsumerIr + default + + + + android.hardware.input.classifier + 1.0 + + IInputClassifier + default + + + + android.hardware.keymaster + 3.0 + 4.0 + + IKeymasterDevice + default + + + + android.hardware.keymaster + 4.0 + + IKeymasterDevice + strongbox + + + + android.hardware.light + 2.0 + + ILight + default + + + + android.hardware.media.c2 + 1.0 + + IComponentStore + default[0-9]* + vendor[0-9]*_software + + + + android.hardware.media.omx + 1.0 + + IOmx + default + + + IOmxStore + default + + + + android.hardware.memtrack + 1.0 + + IMemtrack + default + + + + android.hardware.neuralnetworks + 1.0-2 + + IDevice + .* + + + + android.hardware.nfc + 1.2 + + INfc + default + + + + android.hardware.oemlock + 1.0 + + IOemLock + default + + + + android.hardware.power + 1.0-3 + + IPower + default + + + + android.hardware.power.stats + 1.0 + + IPowerStats + default + + + + android.hardware.radio + 1.4 + + IRadio + slot1 + slot2 + slot3 + + + ISap + slot1 + + + + android.hardware.radio.config + 1.2 + + IRadioConfig + default + + + + android.hardware.renderscript + 1.0 + + IDevice + default + + + + android.hardware.secure_element + 1.0 + + ISecureElement + eSE[1-9][0-9]* + SIM[1-9][0-9]* + + + + android.hardware.sensors + 1.0 + 2.0 + + ISensors + default + + + + android.hardware.soundtrigger + 2.0-2 + + ISoundTriggerHw + default + + + + android.hardware.tetheroffload.config + 1.0 + + IOffloadConfig + default + + + + android.hardware.tetheroffload.control + 1.0 + + IOffloadControl + default + + + + android.hardware.thermal + 1.0-1 + 2.0 + + IThermal + default + + + + android.hardware.tv.cec + 1.0 + + IHdmiCec + default + + + + android.hardware.tv.input + 1.0 + + ITvInput + default + + + + android.hardware.usb + 1.0-2 + + IUsb + default + + + + android.hardware.usb.gadget + 1.0 + + IUsbGadget + default + + + + android.hardware.vibrator + 1.0-3 + + IVibrator + default + + + + android.hardware.vr + 1.0 + + IVr + default + + + + android.hardware.weaver + 1.0 + + IWeaver + default + + + + android.hardware.wifi + 1.0-3 + + IWifi + default + + + + android.hardware.wifi.hostapd + 1.0-1 + + IHostapd + default + + + + android.hardware.wifi.supplicant + 1.0-2 + + ISupplicant + default + + + From 944efca78d9717e1b17109b28c0da26a4cd9f790 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Mon, 20 May 2019 14:08:34 -0700 Subject: [PATCH 678/718] Allow impls to ignore incremental scan interval When incremental results are disabled for network scans, update the API documentation to allow implementations to ignore range checking for the incremental scan interval. Bug: 112486807 Test: compilation - docstring-only change Change-Id: I901335550b4b8c2cf75f91b39fd031f03ffae982 --- current.txt | 1 + radio/1.2/types.hal | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/current.txt b/current.txt index 35c0367f28..e6ac705ca8 100644 --- a/current.txt +++ b/current.txt @@ -410,6 +410,7 @@ eb754b58c93e5591613208b4c972811288b0fa16a82430d602f107c91a908b22 android.hardwar ed9da80ec0c96991fd03f0a46107815d0e50f764656e49dba4980fa5c31d5bc3 android.hardware.radio@1.0::types 1d19720d4fd38b1095f0f555a4bd92b3b12c9b1d0f560b0e9a474cd6dcc20db6 android.hardware.radio@1.2::IRadio cd1757867a5e3a3faa362e785239515870d1a3c9ce756c6f0cf0f0fd8aac2547 android.hardware.radio@1.2::types +722b3595548ed7f1953b6e0143dc842d4d6e290ff009a134eb518d7c17a09347 android.hardware.radio@1.2::types # b/112486807 e78cf871f9fd1c072874e481e06e18e2681763cf2aa38c1fd777d53bab4eb69b android.hardware.sensors@1.0::types 3d01e29e8129186f7567c4f9c8bee7480a0768e587b1be9b28adb0a6cbec6bf2 android.hardware.tv.cec@1.0::types 1722ad002317b1fae1400de709e90f442d94ef22864e05f7a12af48c32e8edc8 android.hardware.usb@1.1::types diff --git a/radio/1.2/types.hal b/radio/1.2/types.hal index 2dceeb158d..dffebd3e42 100644 --- a/radio/1.2/types.hal +++ b/radio/1.2/types.hal @@ -193,7 +193,8 @@ struct NetworkScanRequest { * the client (in seconds). * Expected range for the input is * [IncrementalResultsPeriodicityRange:MIN - IncrementalResultsPeriodicityRange:MAX] - * This value must be less than or equal to maxSearchTime. + * This value must be less than or equal to maxSearchTime. If incremental results are + * not requested, implementations may ignore this value. */ int32_t incrementalResultsPeriodicity; From f56b9a41dd68e0d3cc7d2a506b26ce7d0fac2a12 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Mon, 20 May 2019 14:12:27 -0700 Subject: [PATCH 679/718] Enable incremental scans for interval checks Currently tests that check for incremental scan interval range-checking have incremental scans disabled. This CL turns on incremental scans for tests where the invalid interval range checks are being validated. Bug: 112486807 Test: atest RadioHidlTest_v1_2#startNetworkScan_InvalidPeriodicity1; atest RadioHidlTest_v1_2#startNetworkScan_InvalidPeriodicity2; Change-Id: I94874f538d2df70a72913b489d9298f8d1cf9b56 --- radio/1.2/vts/functional/radio_hidl_hal_api.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp index a3073acca3..63d3187aed 100644 --- a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp +++ b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp @@ -228,7 +228,7 @@ TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidPeriodicity1) { .interval = 60, .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850}, .maxSearchTime = 600, - .incrementalResults = false, + .incrementalResults = true, .incrementalResultsPeriodicity = 0}; Return res = radio_v1_2->startNetworkScan_1_2(serial, request); @@ -260,7 +260,7 @@ TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidPeriodicity2) { .interval = 60, .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850}, .maxSearchTime = 600, - .incrementalResults = false, + .incrementalResults = true, .incrementalResultsPeriodicity = 11}; Return res = radio_v1_2->startNetworkScan_1_2(serial, request); From cba658074925bc0938b97e7d33ba92443b7fa589 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Mon, 20 May 2019 14:12:27 -0700 Subject: [PATCH 680/718] Enable incremental scans for interval checks Currently tests that check for incremental scan interval range-checking have incremental scans disabled. This CL turns on incremental scans for tests where the invalid interval range checks are being validated. Bug: 112486807 Test: atest RadioHidlTest_v1_2#startNetworkScan_InvalidPeriodicity1; atest RadioHidlTest_v1_2#startNetworkScan_InvalidPeriodicity2; Merged-In: I94874f538d2df70a72913b489d9298f8d1cf9b56 Change-Id: I94874f538d2df70a72913b489d9298f8d1cf9b56 (cherry picked from commit f56b9a41dd68e0d3cc7d2a506b26ce7d0fac2a12) --- radio/1.2/vts/functional/radio_hidl_hal_api.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp index feee37d4b2..7e05190ff6 100644 --- a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp +++ b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp @@ -228,7 +228,7 @@ TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidPeriodicity1) { .interval = 60, .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850}, .maxSearchTime = 600, - .incrementalResults = false, + .incrementalResults = true, .incrementalResultsPeriodicity = 0}; Return res = radio_v1_2->startNetworkScan_1_2(serial, request); @@ -260,7 +260,7 @@ TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidPeriodicity2) { .interval = 60, .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850}, .maxSearchTime = 600, - .incrementalResults = false, + .incrementalResults = true, .incrementalResultsPeriodicity = 11}; Return res = radio_v1_2->startNetworkScan_1_2(serial, request); From 356d5a6ed2163a85173bd1d414b29f7634e68bd2 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Fri, 17 May 2019 15:07:34 -0700 Subject: [PATCH 681/718] wifi(implementation): Send NAN disabled on wlan0 down & up When the iface state is toggled for MAC address change on the underlying interface for NAN operations, send NAN disabled event up to the framework. The iface down/up toggle resets all NAN operations in the firmware. So, this callback should trigger a cleanup of any operations initiated by the framework. Bug: 132943959 Test: Unit tests in the follow-up CL. Test: Will send for regression tests. Change-Id: I760dc5ca3b9276956f5edd40a97c3c13811f442c --- wifi/1.3/default/wifi_chip.cpp | 2 +- wifi/1.3/default/wifi_iface_util.cpp | 21 ++++++++++++++++++- wifi/1.3/default/wifi_iface_util.h | 13 ++++++++++++ wifi/1.3/default/wifi_nan_iface.cpp | 30 +++++++++++++++++++++++++--- wifi/1.3/default/wifi_nan_iface.h | 5 ++++- 5 files changed, 65 insertions(+), 6 deletions(-) diff --git a/wifi/1.3/default/wifi_chip.cpp b/wifi/1.3/default/wifi_chip.cpp index 27320c407b..6c2fd678da 100644 --- a/wifi/1.3/default/wifi_chip.cpp +++ b/wifi/1.3/default/wifi_chip.cpp @@ -861,7 +861,7 @@ std::pair> WifiChip::createNanIfaceInternal() { } // These are still assumed to be based on wlan0. std::string ifname = getFirstActiveWlanIfaceName(); - sp iface = new WifiNanIface(ifname, legacy_hal_); + sp iface = new WifiNanIface(ifname, legacy_hal_, iface_util_); nan_ifaces_.push_back(iface); for (const auto& callback : event_cb_handler_.getCallbacks()) { if (!callback->onIfaceAdded(IfaceType::NAN, ifname).isOk()) { diff --git a/wifi/1.3/default/wifi_iface_util.cpp b/wifi/1.3/default/wifi_iface_util.cpp index 5d61271410..7042af0b87 100644 --- a/wifi/1.3/default/wifi_iface_util.cpp +++ b/wifi/1.3/default/wifi_iface_util.cpp @@ -39,7 +39,8 @@ namespace V1_3 { namespace implementation { namespace iface_util { -WifiIfaceUtil::WifiIfaceUtil() : random_mac_address_(nullptr) {} +WifiIfaceUtil::WifiIfaceUtil() + : random_mac_address_(nullptr), event_handlers_map_() {} std::array WifiIfaceUtil::getFactoryMacAddress( const std::string& iface_name) { @@ -60,6 +61,14 @@ bool WifiIfaceUtil::setMacAddress(const std::string& iface_name, LOG(ERROR) << "SetUpState(true) failed."; return false; } + IfaceEventHandlers event_handlers = {}; + const auto it = event_handlers_map_.find(iface_name); + if (it != event_handlers_map_.end()) { + event_handlers = it->second; + } + if (event_handlers.on_state_toggle_off_on != nullptr) { + event_handlers.on_state_toggle_off_on(iface_name); + } LOG(DEBUG) << "Successfully SetMacAddress."; return true; } @@ -73,6 +82,16 @@ std::array WifiIfaceUtil::getOrCreateRandomMacAddress() { return *random_mac_address_.get(); } +void WifiIfaceUtil::registerIfaceEventHandlers(const std::string& iface_name, + IfaceEventHandlers handlers) { + event_handlers_map_[iface_name] = handlers; +} + +void WifiIfaceUtil::unregisterIfaceEventHandlers( + const std::string& iface_name) { + event_handlers_map_.erase(iface_name); +} + std::array WifiIfaceUtil::createRandomMacAddress() { std::array address = {}; std::random_device rd; diff --git a/wifi/1.3/default/wifi_iface_util.h b/wifi/1.3/default/wifi_iface_util.h index b2382344ed..325fbe8390 100644 --- a/wifi/1.3/default/wifi_iface_util.h +++ b/wifi/1.3/default/wifi_iface_util.h @@ -28,6 +28,13 @@ namespace V1_3 { namespace implementation { namespace iface_util { +// Iface event handlers. +struct IfaceEventHandlers { + // Callback to be invoked when the iface is set down & up for MAC address + // change. + std::function on_state_toggle_off_on; +}; + /** * Util class for common iface operations. */ @@ -45,11 +52,17 @@ class WifiIfaceUtil { // daemon. (So, changes on every reboot) virtual std::array getOrCreateRandomMacAddress(); + // Register for any iface event callbacks for the provided interface. + virtual void registerIfaceEventHandlers(const std::string& iface_name, + IfaceEventHandlers handlers); + virtual void unregisterIfaceEventHandlers(const std::string& iface_name); + private: std::array createRandomMacAddress(); wifi_system::InterfaceTool iface_tool_; std::unique_ptr> random_mac_address_; + std::map event_handlers_map_; }; } // namespace iface_util diff --git a/wifi/1.3/default/wifi_nan_iface.cpp b/wifi/1.3/default/wifi_nan_iface.cpp index 4325f44dad..ff9f4224df 100644 --- a/wifi/1.3/default/wifi_nan_iface.cpp +++ b/wifi/1.3/default/wifi_nan_iface.cpp @@ -30,8 +30,12 @@ using hidl_return_util::validateAndCall; WifiNanIface::WifiNanIface( const std::string& ifname, - const std::weak_ptr legacy_hal) - : ifname_(ifname), legacy_hal_(legacy_hal), is_valid_(true) { + const std::weak_ptr legacy_hal, + const std::weak_ptr iface_util) + : ifname_(ifname), + legacy_hal_(legacy_hal), + iface_util_(iface_util), + is_valid_(true) { // Register all the callbacks here. these should be valid for the lifetime // of the object. Whenever the mode changes legacy HAL will remove // all of these callbacks. @@ -498,6 +502,26 @@ WifiNanIface::WifiNanIface( LOG(ERROR) << "Failed to register nan callbacks. Invalidating object"; invalidate(); } + + // Register for iface state toggle events. + iface_util::IfaceEventHandlers event_handlers = {}; + event_handlers.on_state_toggle_off_on = + [weak_ptr_this](const std::string& /* iface_name */) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + // Tell framework that NAN has been disabled. + WifiNanStatus status = { + NanStatusType::UNSUPPORTED_CONCURRENCY_NAN_DISABLED, ""}; + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->eventDisabled(status).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + iface_util_.lock()->registerIfaceEventHandlers(ifname_, event_handlers); } void WifiNanIface::invalidate() { @@ -505,7 +529,7 @@ void WifiNanIface::invalidate() { legacy_hal_.lock()->nanDisableRequest(ifname_, 0xFFFF); legacy_hal_.lock()->nanDataInterfaceDelete(ifname_, 0xFFFE, "aware_data0"); legacy_hal_.lock()->nanDataInterfaceDelete(ifname_, 0xFFFD, "aware_data1"); - + iface_util_.lock()->unregisterIfaceEventHandlers(ifname_); legacy_hal_.reset(); event_cb_handler_.invalidate(); event_cb_handler_1_2_.invalidate(); diff --git a/wifi/1.3/default/wifi_nan_iface.h b/wifi/1.3/default/wifi_nan_iface.h index f735d61cf9..737be93217 100644 --- a/wifi/1.3/default/wifi_nan_iface.h +++ b/wifi/1.3/default/wifi_nan_iface.h @@ -22,6 +22,7 @@ #include #include "hidl_callback_util.h" +#include "wifi_iface_util.h" #include "wifi_legacy_hal.h" namespace android { @@ -37,7 +38,8 @@ using namespace android::hardware::wifi::V1_0; class WifiNanIface : public V1_2::IWifiNanIface { public: WifiNanIface(const std::string& ifname, - const std::weak_ptr legacy_hal); + const std::weak_ptr legacy_hal, + const std::weak_ptr iface_util); // Refer to |WifiChip::invalidate()|. void invalidate(); bool isValid(); @@ -147,6 +149,7 @@ class WifiNanIface : public V1_2::IWifiNanIface { std::string ifname_; std::weak_ptr legacy_hal_; + std::weak_ptr iface_util_; bool is_valid_; hidl_callback_util::HidlCallbackHandler event_cb_handler_; From c885df0af3d52a7cf307440fc7b75337e1b45e3c Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Tue, 21 May 2019 14:49:05 -0700 Subject: [PATCH 682/718] wifi(tests): Unit tests for iface event cb's Few class refactors to help with unit tests for ag/7567226. Bug: 132943959 Test: ./hardware/interfaces/wifi/1.3/default/tests/runtests.sh Change-Id: I62909f3f94899bc1593824684b93d29f44954eae --- wifi/1.3/default/Android.mk | 2 + wifi/1.3/default/service.cpp | 6 +- .../1.3/default/tests/mock_interface_tool.cpp | 29 ++++ wifi/1.3/default/tests/mock_interface_tool.h | 44 ++++++ .../default/tests/mock_wifi_iface_util.cpp | 4 +- wifi/1.3/default/tests/mock_wifi_iface_util.h | 6 +- .../default/tests/mock_wifi_legacy_hal.cpp | 4 +- wifi/1.3/default/tests/mock_wifi_legacy_hal.h | 3 +- .../tests/wifi_ap_iface_unit_tests.cpp | 7 +- .../default/tests/wifi_chip_unit_tests.cpp | 7 +- .../tests/wifi_iface_util_unit_tests.cpp | 46 +++++- .../tests/wifi_nan_iface_unit_tests.cpp | 148 ++++++++++++++++++ wifi/1.3/default/wifi.cpp | 4 +- wifi/1.3/default/wifi.h | 4 +- wifi/1.3/default/wifi_iface_util.cpp | 15 +- wifi/1.3/default/wifi_iface_util.h | 4 +- wifi/1.3/default/wifi_legacy_hal.cpp | 10 +- wifi/1.3/default/wifi_legacy_hal.h | 4 +- 18 files changed, 317 insertions(+), 30 deletions(-) create mode 100644 wifi/1.3/default/tests/mock_interface_tool.cpp create mode 100644 wifi/1.3/default/tests/mock_interface_tool.h create mode 100644 wifi/1.3/default/tests/wifi_nan_iface_unit_tests.cpp diff --git a/wifi/1.3/default/Android.mk b/wifi/1.3/default/Android.mk index 199ea3b9f8..1f918618f7 100644 --- a/wifi/1.3/default/Android.mk +++ b/wifi/1.3/default/Android.mk @@ -142,12 +142,14 @@ LOCAL_CPPFLAGS := -Wall -Werror -Wextra LOCAL_SRC_FILES := \ tests/hidl_struct_util_unit_tests.cpp \ tests/main.cpp \ + tests/mock_interface_tool.cpp \ tests/mock_wifi_feature_flags.cpp \ tests/mock_wifi_iface_util.cpp \ tests/mock_wifi_legacy_hal.cpp \ tests/mock_wifi_mode_controller.cpp \ tests/ringbuffer_unit_tests.cpp \ tests/wifi_ap_iface_unit_tests.cpp \ + tests/wifi_nan_iface_unit_tests.cpp \ tests/wifi_chip_unit_tests.cpp \ tests/wifi_iface_util_unit_tests.cpp LOCAL_STATIC_LIBRARIES := \ diff --git a/wifi/1.3/default/service.cpp b/wifi/1.3/default/service.cpp index 73015cf054..fcbc37c12b 100644 --- a/wifi/1.3/default/service.cpp +++ b/wifi/1.3/default/service.cpp @@ -48,12 +48,14 @@ int main(int /*argc*/, char** argv) { configureRpcThreadpool(1, true /* callerWillJoin */); + const auto iface_tool = + std::make_shared(); // Setup hwbinder service android::sp service = new android::hardware::wifi::V1_3::implementation::Wifi( - std::make_shared(), + iface_tool, std::make_shared(iface_tool), std::make_shared(), - std::make_shared(), + std::make_shared(iface_tool), std::make_shared()); if (kLazyService) { LazyServiceRegistrar registrar; diff --git a/wifi/1.3/default/tests/mock_interface_tool.cpp b/wifi/1.3/default/tests/mock_interface_tool.cpp new file mode 100644 index 0000000000..b99a16446c --- /dev/null +++ b/wifi/1.3/default/tests/mock_interface_tool.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2019 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 +#include +#include + +#undef NAN // This is weird, NAN is defined in bionic/libc/include/math.h:38 +#include "mock_interface_tool.h" + +namespace android { +namespace wifi_system { + +MockInterfaceTool::MockInterfaceTool() {} + +} // namespace wifi_system +} // namespace android diff --git a/wifi/1.3/default/tests/mock_interface_tool.h b/wifi/1.3/default/tests/mock_interface_tool.h new file mode 100644 index 0000000000..0f17551f96 --- /dev/null +++ b/wifi/1.3/default/tests/mock_interface_tool.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2019 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 MOCK_INTERFACE_TOOL_H +#define MOCK_INTERFACE_TOOL_H + +#include +#include + +namespace android { +namespace wifi_system { + +class MockInterfaceTool : public InterfaceTool { + public: + MockInterfaceTool(); + + MOCK_METHOD1(GetUpState, bool(const char* if_name)); + MOCK_METHOD2(SetUpState, bool(const char* if_name, bool request_up)); + MOCK_METHOD1(SetWifiUpState, bool(bool request_up)); + MOCK_METHOD2(SetMacAddress, + bool(const char* if_name, + const std::array& address)); + MOCK_METHOD1(GetFactoryMacAddress, + std::array(const char* if_name)); + +}; // class MockInterfaceTool + +} // namespace wifi_system +} // namespace android + +#endif // MOCK_INTERFACE_TOOL_H diff --git a/wifi/1.3/default/tests/mock_wifi_iface_util.cpp b/wifi/1.3/default/tests/mock_wifi_iface_util.cpp index 706cb6a5ef..3d877c0cbf 100644 --- a/wifi/1.3/default/tests/mock_wifi_iface_util.cpp +++ b/wifi/1.3/default/tests/mock_wifi_iface_util.cpp @@ -28,7 +28,9 @@ namespace V1_3 { namespace implementation { namespace iface_util { -MockWifiIfaceUtil::MockWifiIfaceUtil() : WifiIfaceUtil() {} +MockWifiIfaceUtil::MockWifiIfaceUtil( + const std::weak_ptr iface_tool) + : WifiIfaceUtil(iface_tool) {} } // namespace iface_util } // namespace implementation } // namespace V1_3 diff --git a/wifi/1.3/default/tests/mock_wifi_iface_util.h b/wifi/1.3/default/tests/mock_wifi_iface_util.h index 87ab5db412..8ec93eb471 100644 --- a/wifi/1.3/default/tests/mock_wifi_iface_util.h +++ b/wifi/1.3/default/tests/mock_wifi_iface_util.h @@ -30,12 +30,16 @@ namespace iface_util { class MockWifiIfaceUtil : public WifiIfaceUtil { public: - MockWifiIfaceUtil(); + MockWifiIfaceUtil( + const std::weak_ptr iface_tool); MOCK_METHOD1(getFactoryMacAddress, std::array(const std::string&)); MOCK_METHOD2(setMacAddress, bool(const std::string&, const std::array&)); MOCK_METHOD0(getOrCreateRandomMacAddress, std::array()); + MOCK_METHOD2(registerIfaceEventHandlers, + void(const std::string&, IfaceEventHandlers)); + MOCK_METHOD1(unregisterIfaceEventHandlers, void(const std::string&)); }; } // namespace iface_util } // namespace implementation diff --git a/wifi/1.3/default/tests/mock_wifi_legacy_hal.cpp b/wifi/1.3/default/tests/mock_wifi_legacy_hal.cpp index 4cd279d543..0a202c42d2 100644 --- a/wifi/1.3/default/tests/mock_wifi_legacy_hal.cpp +++ b/wifi/1.3/default/tests/mock_wifi_legacy_hal.cpp @@ -28,7 +28,9 @@ namespace V1_3 { namespace implementation { namespace legacy_hal { -MockWifiLegacyHal::MockWifiLegacyHal() : WifiLegacyHal() {} +MockWifiLegacyHal::MockWifiLegacyHal( + const std::weak_ptr iface_tool) + : WifiLegacyHal(iface_tool) {} } // namespace legacy_hal } // namespace implementation } // namespace V1_3 diff --git a/wifi/1.3/default/tests/mock_wifi_legacy_hal.h b/wifi/1.3/default/tests/mock_wifi_legacy_hal.h index 53fa8d6f4c..81cb1ded86 100644 --- a/wifi/1.3/default/tests/mock_wifi_legacy_hal.h +++ b/wifi/1.3/default/tests/mock_wifi_legacy_hal.h @@ -30,7 +30,8 @@ namespace legacy_hal { class MockWifiLegacyHal : public WifiLegacyHal { public: - MockWifiLegacyHal(); + MockWifiLegacyHal( + const std::weak_ptr iface_tool); MOCK_METHOD0(initialize, wifi_error()); MOCK_METHOD0(start, wifi_error()); MOCK_METHOD2(stop, wifi_error(std::unique_lock*, diff --git a/wifi/1.3/default/tests/wifi_ap_iface_unit_tests.cpp b/wifi/1.3/default/tests/wifi_ap_iface_unit_tests.cpp index 28e028b675..680f534c41 100644 --- a/wifi/1.3/default/tests/wifi_ap_iface_unit_tests.cpp +++ b/wifi/1.3/default/tests/wifi_ap_iface_unit_tests.cpp @@ -22,6 +22,7 @@ #undef NAN // This is weird, NAN is defined in bionic/libc/include/math.h:38 #include "wifi_ap_iface.h" +#include "mock_interface_tool.h" #include "mock_wifi_feature_flags.h" #include "mock_wifi_iface_util.h" #include "mock_wifi_legacy_hal.h" @@ -42,10 +43,12 @@ namespace implementation { class WifiApIfaceTest : public Test { protected: + std::shared_ptr> iface_tool_{ + new NiceMock}; std::shared_ptr> legacy_hal_{ - new NiceMock}; + new NiceMock(iface_tool_)}; std::shared_ptr> iface_util_{ - new NiceMock}; + new NiceMock(iface_tool_)}; std::shared_ptr> feature_flags_{new NiceMock}; }; diff --git a/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp index 22359e956c..d8ce2785b7 100644 --- a/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp +++ b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp @@ -22,6 +22,7 @@ #undef NAN // This is weird, NAN is defined in bionic/libc/include/math.h:38 #include "wifi_chip.h" +#include "mock_interface_tool.h" #include "mock_wifi_feature_flags.h" #include "mock_wifi_iface_util.h" #include "mock_wifi_legacy_hal.h" @@ -263,12 +264,14 @@ class WifiChipTest : public Test { sp chip_; ChipId chip_id_ = kFakeChipId; + std::shared_ptr> iface_tool_{ + new NiceMock}; std::shared_ptr> legacy_hal_{ - new NiceMock}; + new NiceMock(iface_tool_)}; std::shared_ptr> mode_controller_{new NiceMock}; std::shared_ptr> iface_util_{ - new NiceMock}; + new NiceMock(iface_tool_)}; std::shared_ptr> feature_flags_{new NiceMock}; diff --git a/wifi/1.3/default/tests/wifi_iface_util_unit_tests.cpp b/wifi/1.3/default/tests/wifi_iface_util_unit_tests.cpp index e5758facdb..28d23ffa71 100644 --- a/wifi/1.3/default/tests/wifi_iface_util_unit_tests.cpp +++ b/wifi/1.3/default/tests/wifi_iface_util_unit_tests.cpp @@ -21,10 +21,15 @@ #undef NAN #include "wifi_iface_util.h" +#include "mock_interface_tool.h" + +using testing::NiceMock; using testing::Test; namespace { constexpr uint8_t kValidUnicastLocallyAssignedMacAddressMask = 0x02; +constexpr uint8_t kMacAddress[] = {0x02, 0x12, 0x45, 0x56, 0xab, 0xcc}; +constexpr char kIfaceName[] = "test-wlan0"; bool isValidUnicastLocallyAssignedMacAddress( const std::array& mac_address) { @@ -38,19 +43,52 @@ namespace hardware { namespace wifi { namespace V1_3 { namespace implementation { +namespace iface_util { class WifiIfaceUtilTest : public Test { protected: - iface_util::WifiIfaceUtil iface_util_; + std::shared_ptr> iface_tool_{ + new NiceMock}; + WifiIfaceUtil* iface_util_ = new WifiIfaceUtil(iface_tool_); }; TEST_F(WifiIfaceUtilTest, GetOrCreateRandomMacAddress) { - auto mac_address = iface_util_.getOrCreateRandomMacAddress(); + auto mac_address = iface_util_->getOrCreateRandomMacAddress(); ASSERT_TRUE(isValidUnicastLocallyAssignedMacAddress(mac_address)); // All further calls should return the same MAC address. - ASSERT_EQ(mac_address, iface_util_.getOrCreateRandomMacAddress()); - ASSERT_EQ(mac_address, iface_util_.getOrCreateRandomMacAddress()); + ASSERT_EQ(mac_address, iface_util_->getOrCreateRandomMacAddress()); + ASSERT_EQ(mac_address, iface_util_->getOrCreateRandomMacAddress()); } + +TEST_F(WifiIfaceUtilTest, IfaceEventHandlers_SetMacAddress) { + std::array mac_address = {}; + std::copy(std::begin(kMacAddress), std::end(kMacAddress), + std::begin(mac_address)); + EXPECT_CALL(*iface_tool_, SetMacAddress(testing::_, testing::_)) + .WillRepeatedly(testing::Return(true)); + EXPECT_CALL(*iface_tool_, SetUpState(testing::_, testing::_)) + .WillRepeatedly(testing::Return(true)); + + // Register for iface state toggle events. + bool callback_invoked = false; + iface_util::IfaceEventHandlers event_handlers = {}; + event_handlers.on_state_toggle_off_on = + [&callback_invoked](const std::string& /* iface_name */) { + callback_invoked = true; + }; + iface_util_->registerIfaceEventHandlers(kIfaceName, event_handlers); + // Invoke setMacAddress and ensure that the cb is invoked. + ASSERT_TRUE(iface_util_->setMacAddress(kIfaceName, mac_address)); + ASSERT_TRUE(callback_invoked); + + // Unregister for iface state toggle events. + callback_invoked = false; + iface_util_->unregisterIfaceEventHandlers(kIfaceName); + // Invoke setMacAddress and ensure that the cb is not invoked. + ASSERT_TRUE(iface_util_->setMacAddress(kIfaceName, mac_address)); + ASSERT_FALSE(callback_invoked); +} +} // namespace iface_util } // namespace implementation } // namespace V1_3 } // namespace wifi diff --git a/wifi/1.3/default/tests/wifi_nan_iface_unit_tests.cpp b/wifi/1.3/default/tests/wifi_nan_iface_unit_tests.cpp new file mode 100644 index 0000000000..eb6c61065d --- /dev/null +++ b/wifi/1.3/default/tests/wifi_nan_iface_unit_tests.cpp @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2019, 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 +#include +#include +#include + +#undef NAN // This is weird, NAN is defined in bionic/libc/include/math.h:38 +#include "wifi_nan_iface.h" + +#include "mock_interface_tool.h" +#include "mock_wifi_feature_flags.h" +#include "mock_wifi_iface_util.h" +#include "mock_wifi_legacy_hal.h" + +using testing::NiceMock; +using testing::Return; +using testing::Test; + +namespace { +constexpr char kIfaceName[] = "mockWlan0"; +} // namespace + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { + +bool CaptureIfaceEventHandlers( + const std::string& /* iface_name*/, + iface_util::IfaceEventHandlers in_iface_event_handlers, + iface_util::IfaceEventHandlers* out_iface_event_handlers) { + *out_iface_event_handlers = in_iface_event_handlers; + return true; +} + +class MockNanIfaceEventCallback : public IWifiNanIfaceEventCallback { + public: + MockNanIfaceEventCallback() = default; + + MOCK_METHOD3(notifyCapabilitiesResponse, + Return(uint16_t, const WifiNanStatus&, + const NanCapabilities&)); + MOCK_METHOD2(notifyEnableResponse, + Return(uint16_t, const WifiNanStatus&)); + MOCK_METHOD2(notifyConfigResponse, + Return(uint16_t, const WifiNanStatus&)); + MOCK_METHOD2(notifyDisableResponse, + Return(uint16_t, const WifiNanStatus&)); + MOCK_METHOD3(notifyStartPublishResponse, + Return(uint16_t, const WifiNanStatus&, uint8_t)); + MOCK_METHOD2(notifyStopPublishResponse, + Return(uint16_t, const WifiNanStatus&)); + MOCK_METHOD3(notifyStartSubscribeResponse, + Return(uint16_t, const WifiNanStatus&, uint8_t)); + MOCK_METHOD2(notifyStopSubscribeResponse, + Return(uint16_t, const WifiNanStatus&)); + MOCK_METHOD2(notifyTransmitFollowupResponse, + Return(uint16_t, const WifiNanStatus&)); + MOCK_METHOD2(notifyCreateDataInterfaceResponse, + Return(uint16_t, const WifiNanStatus&)); + MOCK_METHOD2(notifyDeleteDataInterfaceResponse, + Return(uint16_t, const WifiNanStatus&)); + MOCK_METHOD3(notifyInitiateDataPathResponse, + Return(uint16_t, const WifiNanStatus&, uint32_t)); + MOCK_METHOD2(notifyRespondToDataPathIndicationResponse, + Return(uint16_t, const WifiNanStatus&)); + MOCK_METHOD2(notifyTerminateDataPathResponse, + Return(uint16_t, const WifiNanStatus&)); + MOCK_METHOD1(eventClusterEvent, Return(const NanClusterEventInd&)); + MOCK_METHOD1(eventDisabled, Return(const WifiNanStatus&)); + MOCK_METHOD2(eventPublishTerminated, + Return(uint8_t, const WifiNanStatus&)); + MOCK_METHOD2(eventSubscribeTerminated, + Return(uint8_t, const WifiNanStatus&)); + MOCK_METHOD1(eventMatch, Return(const NanMatchInd&)); + MOCK_METHOD2(eventMatchExpired, Return(uint8_t, uint32_t)); + MOCK_METHOD1(eventFollowupReceived, + Return(const NanFollowupReceivedInd&)); + MOCK_METHOD2(eventTransmitFollowup, + Return(uint16_t, const WifiNanStatus&)); + MOCK_METHOD1(eventDataPathRequest, + Return(const NanDataPathRequestInd&)); + MOCK_METHOD1(eventDataPathConfirm, + Return(const NanDataPathConfirmInd&)); + MOCK_METHOD1(eventDataPathTerminated, Return(uint32_t)); +}; + +class WifiNanIfaceTest : public Test { + protected: + std::shared_ptr> iface_tool_{ + new NiceMock}; + std::shared_ptr> legacy_hal_{ + new NiceMock(iface_tool_)}; + std::shared_ptr> iface_util_{ + new NiceMock(iface_tool_)}; +}; + +TEST_F(WifiNanIfaceTest, IfacEventHandlers_OnStateToggleOffOn) { + iface_util::IfaceEventHandlers captured_iface_event_handlers = {}; + EXPECT_CALL(*legacy_hal_, + nanRegisterCallbackHandlers(testing::_, testing::_)) + .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS)); + EXPECT_CALL(*iface_util_, + registerIfaceEventHandlers(testing::_, testing::_)) + .WillOnce(testing::Invoke( + bind(CaptureIfaceEventHandlers, std::placeholders::_1, + std::placeholders::_2, &captured_iface_event_handlers))); + sp nan_iface = + new WifiNanIface(kIfaceName, legacy_hal_, iface_util_); + + // Register a mock nan event callback. + sp> mock_event_callback{ + new NiceMock}; + nan_iface->registerEventCallback( + mock_event_callback, [](const WifiStatus& status) { + ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); + }); + // Ensure that the eventDisabled() function in mock callback will be + // invoked. + WifiNanStatus expected_nan_status = { + NanStatusType::UNSUPPORTED_CONCURRENCY_NAN_DISABLED, ""}; + EXPECT_CALL(*mock_event_callback, eventDisabled(expected_nan_status)) + .Times(1); + + // Trigger the iface state toggle callback. + captured_iface_event_handlers.on_state_toggle_off_on(kIfaceName); +} +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.3/default/wifi.cpp b/wifi/1.3/default/wifi.cpp index 1f640856c2..2f21819dbc 100644 --- a/wifi/1.3/default/wifi.cpp +++ b/wifi/1.3/default/wifi.cpp @@ -34,11 +34,13 @@ using hidl_return_util::validateAndCall; using hidl_return_util::validateAndCallWithLock; Wifi::Wifi( + const std::shared_ptr iface_tool, const std::shared_ptr legacy_hal, const std::shared_ptr mode_controller, const std::shared_ptr iface_util, const std::shared_ptr feature_flags) - : legacy_hal_(legacy_hal), + : iface_tool_(iface_tool), + legacy_hal_(legacy_hal), mode_controller_(mode_controller), iface_util_(iface_util), feature_flags_(feature_flags), diff --git a/wifi/1.3/default/wifi.h b/wifi/1.3/default/wifi.h index c4ab7732bd..1c2a15409e 100644 --- a/wifi/1.3/default/wifi.h +++ b/wifi/1.3/default/wifi.h @@ -40,7 +40,8 @@ namespace implementation { */ class Wifi : public V1_3::IWifi { public: - Wifi(const std::shared_ptr legacy_hal, + Wifi(const std::shared_ptr iface_tool, + const std::shared_ptr legacy_hal, const std::shared_ptr mode_controller, const std::shared_ptr iface_util, @@ -77,6 +78,7 @@ class Wifi : public V1_3::IWifi { // Instance is created in this root level |IWifi| HIDL interface object // and shared with all the child HIDL interface objects. + std::shared_ptr iface_tool_; std::shared_ptr legacy_hal_; std::shared_ptr mode_controller_; std::shared_ptr iface_util_; diff --git a/wifi/1.3/default/wifi_iface_util.cpp b/wifi/1.3/default/wifi_iface_util.cpp index 7042af0b87..34bc02d3f9 100644 --- a/wifi/1.3/default/wifi_iface_util.cpp +++ b/wifi/1.3/default/wifi_iface_util.cpp @@ -39,25 +39,28 @@ namespace V1_3 { namespace implementation { namespace iface_util { -WifiIfaceUtil::WifiIfaceUtil() - : random_mac_address_(nullptr), event_handlers_map_() {} +WifiIfaceUtil::WifiIfaceUtil( + const std::weak_ptr iface_tool) + : iface_tool_(iface_tool), + random_mac_address_(nullptr), + event_handlers_map_() {} std::array WifiIfaceUtil::getFactoryMacAddress( const std::string& iface_name) { - return iface_tool_.GetFactoryMacAddress(iface_name.c_str()); + return iface_tool_.lock()->GetFactoryMacAddress(iface_name.c_str()); } bool WifiIfaceUtil::setMacAddress(const std::string& iface_name, const std::array& mac) { - if (!iface_tool_.SetUpState(iface_name.c_str(), false)) { + if (!iface_tool_.lock()->SetUpState(iface_name.c_str(), false)) { LOG(ERROR) << "SetUpState(false) failed."; return false; } - if (!iface_tool_.SetMacAddress(iface_name.c_str(), mac)) { + if (!iface_tool_.lock()->SetMacAddress(iface_name.c_str(), mac)) { LOG(ERROR) << "SetMacAddress failed."; return false; } - if (!iface_tool_.SetUpState(iface_name.c_str(), true)) { + if (!iface_tool_.lock()->SetUpState(iface_name.c_str(), true)) { LOG(ERROR) << "SetUpState(true) failed."; return false; } diff --git a/wifi/1.3/default/wifi_iface_util.h b/wifi/1.3/default/wifi_iface_util.h index 325fbe8390..98073e0763 100644 --- a/wifi/1.3/default/wifi_iface_util.h +++ b/wifi/1.3/default/wifi_iface_util.h @@ -40,7 +40,7 @@ struct IfaceEventHandlers { */ class WifiIfaceUtil { public: - WifiIfaceUtil(); + WifiIfaceUtil(const std::weak_ptr iface_tool); virtual ~WifiIfaceUtil() = default; virtual std::array getFactoryMacAddress( @@ -60,7 +60,7 @@ class WifiIfaceUtil { private: std::array createRandomMacAddress(); - wifi_system::InterfaceTool iface_tool_; + std::weak_ptr iface_tool_; std::unique_ptr> random_mac_address_; std::map event_handlers_map_; }; diff --git a/wifi/1.3/default/wifi_legacy_hal.cpp b/wifi/1.3/default/wifi_legacy_hal.cpp index 7f9b63575e..485bd16634 100644 --- a/wifi/1.3/default/wifi_legacy_hal.cpp +++ b/wifi/1.3/default/wifi_legacy_hal.cpp @@ -333,10 +333,12 @@ void onAsyncNanEventScheduleUpdate(NanDataPathScheduleUpdateInd* event) { } // End of the free-standing "C" style callbacks. -WifiLegacyHal::WifiLegacyHal() +WifiLegacyHal::WifiLegacyHal( + const std::weak_ptr iface_tool) : global_handle_(nullptr), awaiting_event_loop_termination_(false), - is_started_(false) {} + is_started_(false), + iface_tool_(iface_tool) {} wifi_error WifiLegacyHal::initialize() { LOG(DEBUG) << "Initialize legacy HAL"; @@ -371,7 +373,7 @@ wifi_error WifiLegacyHal::start() { property_set(kDriverPropName, "ok"); LOG(DEBUG) << "Starting legacy HAL"; - if (!iface_tool_.SetWifiUpState(true)) { + if (!iface_tool_.lock()->SetWifiUpState(true)) { LOG(ERROR) << "Failed to set WiFi interface up"; return WIFI_ERROR_UNKNOWN; } @@ -407,7 +409,7 @@ wifi_error WifiLegacyHal::stop( // Invalidate all the internal pointers now that the HAL is // stopped. invalidate(); - iface_tool_.SetWifiUpState(false); + iface_tool_.lock()->SetWifiUpState(false); on_stop_complete_user_callback(); is_started_ = false; }; diff --git a/wifi/1.3/default/wifi_legacy_hal.h b/wifi/1.3/default/wifi_legacy_hal.h index a3ed460b11..9cfa172402 100644 --- a/wifi/1.3/default/wifi_legacy_hal.h +++ b/wifi/1.3/default/wifi_legacy_hal.h @@ -170,7 +170,7 @@ using on_radio_mode_change_callback = */ class WifiLegacyHal { public: - WifiLegacyHal(); + WifiLegacyHal(const std::weak_ptr iface_tool); virtual ~WifiLegacyHal() = default; // Initialize the legacy HAL function table. @@ -391,7 +391,7 @@ class WifiLegacyHal { std::condition_variable_any stop_wait_cv_; // Flag to indicate if the legacy HAL has been started. bool is_started_; - wifi_system::InterfaceTool iface_tool_; + std::weak_ptr iface_tool_; }; } // namespace legacy_hal From 806591aac84be88e052e24157bece78680d07a58 Mon Sep 17 00:00:00 2001 From: Pengquan Meng Date: Tue, 21 May 2019 11:54:14 -0700 Subject: [PATCH 683/718] Add Vts to enforce radioConfig is existed This vts enforce IRadioConfig is existed when IRadio service is supported. We didn't add IRadioConfigV1.2, so in this test IRadioConfigV1.1 will be checked. Bug: 132379735 Test: atest VtsHalRadioV1_4TargetTest Change-Id: I2062ed6b191193d9a8af4f25059fed6cc8dc09d8 --- radio/1.4/vts/functional/Android.bp | 4 +++- radio/1.4/vts/functional/radio_hidl_hal_test.cpp | 9 ++++++++- radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h | 2 ++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/radio/1.4/vts/functional/Android.bp b/radio/1.4/vts/functional/Android.bp index 2d0e0898b7..6827132948 100644 --- a/radio/1.4/vts/functional/Android.bp +++ b/radio/1.4/vts/functional/Android.bp @@ -31,7 +31,9 @@ cc_test { "android.hardware.radio@1.2", "android.hardware.radio@1.1", "android.hardware.radio@1.0", + "android.hardware.radio.config@1.0", + "android.hardware.radio.config@1.1", ], header_libs: ["radio.util.header@1.0"], test_suites: ["general-tests"] -} \ No newline at end of file +} diff --git a/radio/1.4/vts/functional/radio_hidl_hal_test.cpp b/radio/1.4/vts/functional/radio_hidl_hal_test.cpp index 4d80696c36..d2d21ce1f6 100644 --- a/radio/1.4/vts/functional/radio_hidl_hal_test.cpp +++ b/radio/1.4/vts/functional/radio_hidl_hal_test.cpp @@ -47,6 +47,13 @@ void RadioHidlTest_v1_4::SetUp() { EXPECT_EQ(serial, radioRsp_v1_4->rspInfo.serial); EXPECT_EQ(RadioError::NONE, radioRsp_v1_4->rspInfo.error); + sp<::android::hardware::radio::config::V1_1::IRadioConfig> radioConfig = + ::testing::VtsHalHidlTargetTestBase::getService< + ::android::hardware::radio::config::V1_1::IRadioConfig>(); + + /* Enforce Vts tesing with RadioConfig is existed. */ + ASSERT_NE(nullptr, radioConfig.get()); + /* Enforce Vts Testing with Sim Status Present only. */ EXPECT_EQ(CardState::PRESENT, cardStatus.base.base.cardState); } @@ -84,4 +91,4 @@ void RadioHidlTest_v1_4::updateSimCardStatus() { serial = GetRandomSerialNumber(); radio_v1_4->getIccCardStatus(serial); EXPECT_EQ(std::cv_status::no_timeout, wait()); -} \ No newline at end of file +} diff --git a/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h b/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h index de7742c7ce..f662472d22 100644 --- a/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h +++ b/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h @@ -22,6 +22,8 @@ #include #include +#include + #include #include #include From d2e4c074659dd731c2fac443f104fdf2df339cbb Mon Sep 17 00:00:00 2001 From: James Mattis Date: Wed, 22 May 2019 16:14:48 -0700 Subject: [PATCH 684/718] Fix so that dual access points (AP) works. Devices that only have dual AP setup without an STA were not working. A use case for this would be in a car, having a wifi hotspot active while also projecting to the car head unit from your phone. This was working but a recent change in CL a3e5b7f that forced STA to be on wlan0 and AP to start at wlan1 broke this functionality. This change is to augment the original CL to keep it's function in place while also taking into account devices that have dual AP. Bug: 132268977 Test: Manual boot of hawk device along with testing of tethering and local only hotspot. Change-Id: I8da5dd4f0baea1bf0f22d3275e356936a58fb3d1 --- wifi/1.3/default/wifi_chip.cpp | 15 ++++++++++++--- wifi/1.3/default/wifi_chip.h | 1 + 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/wifi/1.3/default/wifi_chip.cpp b/wifi/1.3/default/wifi_chip.cpp index b768959f2a..7bc85e8e15 100644 --- a/wifi/1.3/default/wifi_chip.cpp +++ b/wifi/1.3/default/wifi_chip.cpp @@ -1435,6 +1435,13 @@ bool WifiChip::isStaApConcurrencyAllowedInCurrentMode() { return canCurrentModeSupportIfaceCombo(req_iface_combo); } +bool WifiChip::isDualApAllowedInCurrentMode() { + // Check if we can support atleast 1 STA & 1 AP concurrently. + std::map req_iface_combo; + req_iface_combo[IfaceType::AP] = 2; + return canCurrentModeSupportIfaceCombo(req_iface_combo); +} + std::string WifiChip::getFirstActiveWlanIfaceName() { if (sta_ifaces_.size() > 0) return sta_ifaces_[0]->getName(); if (ap_ifaces_.size() > 0) return ap_ifaces_[0]->getName(); @@ -1460,10 +1467,12 @@ std::string WifiChip::allocateApOrStaIfaceName(uint32_t start_idx) { } // AP iface names start with idx 1 for modes supporting -// concurrent STA, else start with idx 0. +// concurrent STA and not dual AP, else start with idx 0. std::string WifiChip::allocateApIfaceName() { - return allocateApOrStaIfaceName( - isStaApConcurrencyAllowedInCurrentMode() ? 1 : 0); + return allocateApOrStaIfaceName((isStaApConcurrencyAllowedInCurrentMode() && + !isDualApAllowedInCurrentMode()) + ? 1 + : 0); } // STA iface names start with idx 0. diff --git a/wifi/1.3/default/wifi_chip.h b/wifi/1.3/default/wifi_chip.h index 3d12f4c9b7..aaed39db97 100644 --- a/wifi/1.3/default/wifi_chip.h +++ b/wifi/1.3/default/wifi_chip.h @@ -237,6 +237,7 @@ class WifiChip : public V1_3::IWifiChip { bool canCurrentModeSupportIfaceOfType(IfaceType requested_type); bool isValidModeId(ChipModeId mode_id); bool isStaApConcurrencyAllowedInCurrentMode(); + bool isDualApAllowedInCurrentMode(); std::string getFirstActiveWlanIfaceName(); std::string allocateApOrStaIfaceName(uint32_t start_idx); std::string allocateApIfaceName(); From 2b3d7740fbefb0802153739a4a73553023b9b4d3 Mon Sep 17 00:00:00 2001 From: Pengquan Meng Date: Wed, 22 May 2019 12:00:19 -0700 Subject: [PATCH 685/718] Send LTE|LTE_CA to modem in vts Bug: 132057161 Test: vts Change-Id: I963933aff316318053546b54ca680cb65e6a290a --- radio/1.4/vts/functional/radio_hidl_hal_api.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp index 2093c25475..696c746d65 100644 --- a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp +++ b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp @@ -119,6 +119,10 @@ TEST_F(RadioHidlTest_v1_4, setPreferredNetworkTypeBitmap) { network_type_bitmap |= ::android::hardware::radio::V1_4::RadioAccessFamily::LTE; + // TODO(b/131634656): LTE_CA will be sent to modem as a RAF in Q, but LTE_CA is not a RAF, + // we will not send it to modem as a RAF in R. + network_type_bitmap |= ::android::hardware::radio::V1_4::RadioAccessFamily::LTE_CA; + Return res = radio_v1_4->setPreferredNetworkTypeBitmap(serial, network_type_bitmap); ASSERT_OK(res); From 64a35d0d16b662b7c466c764c1f53114548dbcca Mon Sep 17 00:00:00 2001 From: Kevin Rocard Date: Thu, 23 May 2019 16:00:01 -0700 Subject: [PATCH 686/718] Audio: Document channel order convention This patch restores the documentation on the channel order convention that was present in the Audio HAL 2.0 but remove by mistake in 4.0. This is a vendor feedback. Test: mm Bug: 133453897 Change-Id: I8eabd8883612d39ced21481fc44661b0808754bb Signed-off-by: Kevin Rocard --- audio/common/5.0/types.hal | 8 +++++++- current.txt | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/audio/common/5.0/types.hal b/audio/common/5.0/types.hal index e1279ee64a..33a8d622c1 100644 --- a/audio/common/5.0/types.hal +++ b/audio/common/5.0/types.hal @@ -331,7 +331,13 @@ enum FixedChannelCount : int32_t { /** * A channel mask per se only defines the presence or absence of a channel, not - * the order. See AUDIO_INTERLEAVE_* for the platform convention of order. + * the order. + * + * The channel order convention is that channels are interleaved in order from + * least significant channel mask bit to most significant channel mask bit, + * with unused bits skipped. For example for stereo, LEFT would be first, + * followed by RIGHT. + * Any exceptions to this convention are noted at the appropriate API. * * AudioChannelMask is an opaque type and its internal layout should not be * assumed as it may change in the future. Instead, always use functions diff --git a/current.txt b/current.txt index e6ac705ca8..d572f21600 100644 --- a/current.txt +++ b/current.txt @@ -428,6 +428,7 @@ b9d41ff4031266de1ecef394a8a64de7d857634dd08dc6be855fca2fe3075975 android.hardwar 1b0500367ed2b32a841667ac3200edf3d3a164e8004aca445ff1b085ac831e93 android.hardware.audio@5.0::IStreamOutCallback 83e365479cc77d8717c155e1787ee668cd2ae4c557b467cf75b8e7cd53697ad8 android.hardware.audio@5.0::types 07d17800b298331e90d4ea5d8ba19a1ae3fe9c1dbff08d9f75fd3ade09496d67 android.hardware.audio.common@5.0::types +b3c1ec989f317b9a36eac10f4e7b66aad2997302156899481553a67476e148dd android.hardware.audio.common@5.0::types # b/133453897 f269297866765b95ddd1825676cc8a772f0c7c9863286df596fc302781a42ff5 android.hardware.audio.effect@5.0::IAcousticEchoCancelerEffect fa187b602d8939644ef708ed7627f2e3deac97899a4bda1de07f2ff126abe243 android.hardware.audio.effect@5.0::IAutomaticGainControlEffect e1bf864ccb8458c0da1dcc74a2e748b1dca8ac360df590591cf82d98292d7981 android.hardware.audio.effect@5.0::IBassBoostEffect From 26c952bf61b5c079a7bce7e1cdddc877df1da737 Mon Sep 17 00:00:00 2001 From: Pierre Fite-Georgel Date: Mon, 20 May 2019 17:27:23 -0700 Subject: [PATCH 687/718] Clarify documentation for AINFO_SENSOR_PLACEMENT Specify units of location vector and define the direction of the rotation matrix translation as Android device frame to local sensor frame. Fixes: 133264933 Test: n/a, comment update only Change-Id: I76dae7a6fae3c8f44a4dcd1fcc6b790abff86420 --- current.txt | 1 + sensors/1.0/types.hal | 38 ++++++++++++++++++++++++++++++++++---- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/current.txt b/current.txt index d572f21600..5742d667d0 100644 --- a/current.txt +++ b/current.txt @@ -412,6 +412,7 @@ ed9da80ec0c96991fd03f0a46107815d0e50f764656e49dba4980fa5c31d5bc3 android.hardwar cd1757867a5e3a3faa362e785239515870d1a3c9ce756c6f0cf0f0fd8aac2547 android.hardware.radio@1.2::types 722b3595548ed7f1953b6e0143dc842d4d6e290ff009a134eb518d7c17a09347 android.hardware.radio@1.2::types # b/112486807 e78cf871f9fd1c072874e481e06e18e2681763cf2aa38c1fd777d53bab4eb69b android.hardware.sensors@1.0::types +c28859a334c1f540dea0a7d4f0baef0551ba76a3232f53c936196543ee35bc4d android.hardware.sensors@1.0::types # b/133264933 3d01e29e8129186f7567c4f9c8bee7480a0768e587b1be9b28adb0a6cbec6bf2 android.hardware.tv.cec@1.0::types 1722ad002317b1fae1400de709e90f442d94ef22864e05f7a12af48c32e8edc8 android.hardware.usb@1.1::types 29c8da7a13c40d488f569c812441d5754ee45bdcdb8ce6564f524b708d10a057 android.hardware.vibrator@1.1::types diff --git a/sensors/1.0/types.hal b/sensors/1.0/types.hal index e91820c377..cbbe92f6f7 100644 --- a/sensors/1.0/types.hal +++ b/sensors/1.0/types.hal @@ -1008,10 +1008,40 @@ enum AdditionalInfoType : uint32_t { AINFO_VEC3_CALIBRATION, /** - * Location and orientation of sensor element in the device frame: origin is - * the geometric center of the mobile device screen surface; the axis - * definition corresponds to Android sensor definitions. - * float[12]: 3x4 matrix in row major order + * Provides the orientation and location of the sensor element in terms of + * the Android coordinate system. This data is given as a 3x4 matrix + * consisting of a 3x3 rotation matrix (R) concatenated with a 3x1 location + * vector (t). The rotation matrix provides the orientation of the Android + * device coordinate frame relative to the local coordinate frame of the + * sensor. Note that assuming the axes conventions of the sensor are the + * same as Android, this is the inverse of the matrix applied to raw + * samples read from the sensor to convert them into the Android + * representation. The location vector represents the translation from the + * origin of the Android sensor coordinate system to the geometric center + * of the sensor, specified in millimeters (mm). + * + * float[12]: 3x4 matrix in row major order [R; t] + * + * Example: + * This raw buffer: {0, 1, 0, 0, -1, 0, 0, 10, 0, 0, 1, -2.5} + * Corresponds to this 3x4 matrix: + * 0 1 0 0 + * -1 0 0 10 + * 0 0 1 -2.5 + * The sensor is oriented such that: + * - the device X axis corresponds to the sensor's local -Y axis + * - the device Y axis corresponds to the sensor's local X axis + * - the device Z axis and sensor's local Z axis are equivalent + * In other words, if viewing the origin of the Android coordinate + * system from the positive Z direction, the device coordinate frame is + * to be rotated 90 degrees counter-clockwise about the Z axis to align + * with the sensor's local coordinate frame. Equivalently, a vector in + * the Android coordinate frame may be multiplied with R to rotate it + * 90 degrees clockwise (270 degrees counter-clockwise), yielding its + * representation in the sensor's coordinate frame. + * Relative to the origin of the Android coordinate system, the physical + * center of the sensor is located 10mm in the positive Y direction, and + * 2.5mm in the negative Z direction. */ AINFO_SENSOR_PLACEMENT, From 18408a93d9da2f757618e6ecafa2798a65ee5816 Mon Sep 17 00:00:00 2001 From: Nate Jiang Date: Tue, 28 May 2019 20:05:25 -0700 Subject: [PATCH 688/718] [VTS][AWARE]Setting callbacktype type to invalid value before invoking HIDL call Avoid race condition between event callback and wait context. Make callbacktype to invalid before call function to change it. Test: atest VtsHalWifiNanV1_0TargetTest VtsHalWifiNanV1_2TargetTest Bug: 133484330 Change-Id: I9211c3e172727f56d0cceaf91b98f8d5b3c7fc7e --- wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp | 3 ++- wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp index 85bcccd230..64b4fb6d1a 100644 --- a/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp +++ b/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp @@ -91,12 +91,12 @@ class WifiNanIfaceHidlTest : public ::testing::VtsHalHidlTargetTestBase { }; /* Test code calls this function to wait for data/event callback */ + /* Must set callbackType = INVALID before call this function */ inline std::cv_status wait(CallbackType waitForCallbackType) { std::unique_lock lock(mtx_); EXPECT_NE(INVALID, waitForCallbackType); // can't ASSERT in a non-void-returning method - callbackType = INVALID; std::cv_status status = std::cv_status::no_timeout; auto now = std::chrono::system_clock::now(); while (count_ == 0) { @@ -469,6 +469,7 @@ TEST(WifiNanIfaceHidlTestNoFixture, FailOnIfaceInvalid) { */ TEST_F(WifiNanIfaceHidlTest, getCapabilitiesRequest) { uint16_t inputCmdId = 10; + callbackType = INVALID; ASSERT_EQ(WifiStatusCode::SUCCESS, HIDL_INVOKE(iwifiNanIface, getCapabilitiesRequest, inputCmdId).code); // wait for a callback diff --git a/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp b/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp index cc36faeafc..4dbc82bd99 100644 --- a/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp +++ b/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp @@ -100,13 +100,13 @@ class WifiNanIfaceHidlTest : public ::testing::VtsHalHidlTargetTestBase { }; /* Test code calls this function to wait for data/event callback */ + /* Must set callbackType = INVALID before call this function */ inline std::cv_status wait(CallbackType waitForCallbackType) { std::unique_lock lock(mtx_); EXPECT_NE(INVALID, waitForCallbackType); // can't ASSERT in a // non-void-returning method - callbackType = INVALID; std::cv_status status = std::cv_status::no_timeout; auto now = std::chrono::system_clock::now(); while (count_ == 0) { @@ -475,6 +475,7 @@ TEST(WifiNanIfaceHidlTestNoFixture, Create) { */ TEST_F(WifiNanIfaceHidlTest, enableRequest_1_2InvalidArgs) { uint16_t inputCmdId = 10; + callbackType = INVALID; NanEnableRequest nanEnableRequest = {}; NanConfigRequestSupplemental nanConfigRequestSupp = {}; ASSERT_EQ(WifiStatusCode::SUCCESS, @@ -509,6 +510,7 @@ TEST_F(WifiNanIfaceHidlTest, enableRequest_1_2ShimInvalidArgs) { */ TEST_F(WifiNanIfaceHidlTest, configRequest_1_2InvalidArgs) { uint16_t inputCmdId = 10; + callbackType = INVALID; NanConfigRequest nanConfigRequest = {}; NanConfigRequestSupplemental nanConfigRequestSupp = {}; ASSERT_EQ(WifiStatusCode::SUCCESS, From 26dcce67aa4860c07b1488cc82702fa300e57ddc Mon Sep 17 00:00:00 2001 From: Kai Date: Tue, 28 May 2019 14:24:05 -0700 Subject: [PATCH 689/718] Add number of ticks in HW_KEY_INPUT Bug: 132291593 Test: build and flash Change-Id: I0baf4d8bbb802f724122d63cd19af5c5f9f4ddfb --- automotive/vehicle/2.0/types.hal | 2 ++ 1 file changed, 2 insertions(+) diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal index e36468a1ae..259473e046 100644 --- a/automotive/vehicle/2.0/types.hal +++ b/automotive/vehicle/2.0/types.hal @@ -1329,6 +1329,8 @@ enum VehicleProperty : int32_t { * int32Values[2] : target display defined in VehicleDisplay. Events not * tied to specific display must be sent to * VehicleDisplay#MAIN. + * int32Values[3] : [optional] Number of ticks. The value must be equal or + * greater than 1. When omitted, Android will default to 1. * * @change_mode VehiclePropertyChangeMode:ON_CHANGE * @access VehiclePropertyAccess:READ From 15df27e428e83018850bea9f8b20cc0840a8d509 Mon Sep 17 00:00:00 2001 From: Jordan Liu Date: Wed, 29 May 2019 11:06:16 -0700 Subject: [PATCH 690/718] Add radio config 1.2 VTS tests Bug: 122730535 Test: run vts -m VtsHalRadioConfigV1_2Target Change-Id: Ib4fc17ea9f76caaf0cb0d4a2914595b7cfb7b041 --- radio/config/1.2/vts/functional/Android.bp | 35 +++++ .../VtsHalRadioConfigV1_2TargetTest.cpp | 26 ++++ .../functional/radio_config_hidl_hal_api.cpp | 30 ++++ .../functional/radio_config_hidl_hal_test.cpp | 66 +++++++++ .../functional/radio_config_hidl_hal_utils.h | 140 ++++++++++++++++++ .../functional/radio_config_indication.cpp | 25 ++++ .../vts/functional/radio_config_response.cpp | 66 +++++++++ 7 files changed, 388 insertions(+) create mode 100644 radio/config/1.2/vts/functional/Android.bp create mode 100644 radio/config/1.2/vts/functional/VtsHalRadioConfigV1_2TargetTest.cpp create mode 100644 radio/config/1.2/vts/functional/radio_config_hidl_hal_api.cpp create mode 100644 radio/config/1.2/vts/functional/radio_config_hidl_hal_test.cpp create mode 100644 radio/config/1.2/vts/functional/radio_config_hidl_hal_utils.h create mode 100644 radio/config/1.2/vts/functional/radio_config_indication.cpp create mode 100644 radio/config/1.2/vts/functional/radio_config_response.cpp diff --git a/radio/config/1.2/vts/functional/Android.bp b/radio/config/1.2/vts/functional/Android.bp new file mode 100644 index 0000000000..0cafc24160 --- /dev/null +++ b/radio/config/1.2/vts/functional/Android.bp @@ -0,0 +1,35 @@ +// +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +cc_test { + name: "VtsHalRadioConfigV1_2TargetTest", + defaults: ["VtsHalTargetTestDefaults"], + srcs: [ + "radio_config_hidl_hal_api.cpp", + "radio_config_hidl_hal_test.cpp", + "radio_config_response.cpp", + "radio_config_indication.cpp", + "VtsHalRadioConfigV1_2TargetTest.cpp", + ], + static_libs: [ + "RadioVtsTestUtilBase", + "android.hardware.radio.config@1.0", + "android.hardware.radio.config@1.1", + "android.hardware.radio.config@1.2", + ], + header_libs: ["radio.util.header@1.0"], + test_suites: ["general-tests"], +} diff --git a/radio/config/1.2/vts/functional/VtsHalRadioConfigV1_2TargetTest.cpp b/radio/config/1.2/vts/functional/VtsHalRadioConfigV1_2TargetTest.cpp new file mode 100644 index 0000000000..ec6544e659 --- /dev/null +++ b/radio/config/1.2/vts/functional/VtsHalRadioConfigV1_2TargetTest.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2019 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 + +int main(int argc, char** argv) { + ::testing::AddGlobalTestEnvironment(RadioConfigHidlEnvironment::Instance()); + ::testing::InitGoogleTest(&argc, argv); + RadioConfigHidlEnvironment::Instance()->init(&argc, argv); + int status = RUN_ALL_TESTS(); + LOG(INFO) << "Test result = " << status; + return status; +} diff --git a/radio/config/1.2/vts/functional/radio_config_hidl_hal_api.cpp b/radio/config/1.2/vts/functional/radio_config_hidl_hal_api.cpp new file mode 100644 index 0000000000..a3729aca2f --- /dev/null +++ b/radio/config/1.2/vts/functional/radio_config_hidl_hal_api.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2019 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 + +#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk()) + +/* + * Test IRadioConfig.getSimSlotsStatus() + */ +TEST_F(RadioConfigHidlTest, getSimSlotsStatus) { + const int serial = GetRandomSerialNumber(); + Return res = radioConfig->getSimSlotsStatus(serial); + ASSERT_OK(res); + ALOGI("getIccSlotsStatus, rspInfo.error = %s\n", + toString(radioConfigRsp->rspInfo.error).c_str()); +} diff --git a/radio/config/1.2/vts/functional/radio_config_hidl_hal_test.cpp b/radio/config/1.2/vts/functional/radio_config_hidl_hal_test.cpp new file mode 100644 index 0000000000..cd7a1726aa --- /dev/null +++ b/radio/config/1.2/vts/functional/radio_config_hidl_hal_test.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2019 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 + +void RadioConfigHidlTest::SetUp() { + radioConfig = ::testing::VtsHalHidlTargetTestBase::getService( + RadioConfigHidlEnvironment::Instance()->getServiceName( + hidl_string(RADIO_SERVICE_NAME))); + if (radioConfig == NULL) { + sleep(60); + radioConfig = ::testing::VtsHalHidlTargetTestBase::getService( + RadioConfigHidlEnvironment::Instance()->getServiceName( + hidl_string(RADIO_SERVICE_NAME))); + } + ASSERT_NE(nullptr, radioConfig.get()); + + radioConfigRsp = new (std::nothrow) RadioConfigResponse(*this); + ASSERT_NE(nullptr, radioConfigRsp.get()); + + count_ = 0; + + radioConfig->setResponseFunctions(radioConfigRsp, nullptr); +} + +/* + * Notify that the response message is received. + */ +void RadioConfigHidlTest::notify(int receivedSerial) { + std::unique_lock lock(mtx_); + if (serial == receivedSerial) { + count_++; + cv_.notify_one(); + } +} + +/* + * Wait till the response message is notified or till TIMEOUT_PERIOD. + */ +std::cv_status RadioConfigHidlTest::wait() { + std::unique_lock lock(mtx_); + + std::cv_status status = std::cv_status::no_timeout; + auto now = std::chrono::system_clock::now(); + while (count_ == 0) { + status = cv_.wait_until(lock, now + std::chrono::seconds(TIMEOUT_PERIOD)); + if (status == std::cv_status::timeout) { + return status; + } + } + count_--; + return status; +} diff --git a/radio/config/1.2/vts/functional/radio_config_hidl_hal_utils.h b/radio/config/1.2/vts/functional/radio_config_hidl_hal_utils.h new file mode 100644 index 0000000000..a876766b48 --- /dev/null +++ b/radio/config/1.2/vts/functional/radio_config_hidl_hal_utils.h @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2019 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 + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "vts_test_util.h" + +using namespace ::android::hardware::radio::config::V1_2; + +using ::android::sp; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::radio::config::V1_1::IRadioConfig; +using ::android::hardware::radio::config::V1_1::ModemsConfig; +using ::android::hardware::radio::config::V1_1::PhoneCapability; +using ::android::hardware::radio::config::V1_2::SimSlotStatus; +using ::android::hardware::radio::V1_0::RadioResponseInfo; +using ::android::hardware::radio::V1_0::RadioResponseType; + +#define TIMEOUT_PERIOD 75 +#define RADIO_SERVICE_NAME "slot1" + +class RadioConfigHidlTest; + +/* Callback class for radio config response */ +class RadioConfigResponse : public IRadioConfigResponse { + protected: + RadioConfigHidlTest& parent; + + public: + RadioResponseInfo rspInfo; + PhoneCapability phoneCap; + + RadioConfigResponse(RadioConfigHidlTest& parent); + virtual ~RadioConfigResponse() = default; + + Return getSimSlotsStatusResponse( + const RadioResponseInfo& info, + const ::android::hardware::hidl_vec< + ::android::hardware::radio::config::V1_0::SimSlotStatus>& slotStatus); + + Return getSimSlotsStatusResponse_1_2( + const RadioResponseInfo& info, + const ::android::hardware::hidl_vec& slotStatus); + + Return setSimSlotsMappingResponse(const RadioResponseInfo& info); + + Return getPhoneCapabilityResponse(const RadioResponseInfo& info, + const PhoneCapability& phoneCapability); + + Return setPreferredDataModemResponse(const RadioResponseInfo& info); + + Return getModemsConfigResponse(const RadioResponseInfo& info, + const ModemsConfig& mConfig); + + Return setModemsConfigResponse(const RadioResponseInfo& info); +}; + +/* Callback class for radio config indication */ +class RadioConfigIndication : public IRadioConfigIndication { + protected: + RadioConfigHidlTest& parent; + + public: + RadioConfigIndication(RadioConfigHidlTest& parent); + virtual ~RadioConfigIndication() = default; + + Return simSlotsStatusChanged_1_2( + ::android::hardware::radio::V1_0::RadioIndicationType type, + const ::android::hardware::hidl_vec& slotStatus); +}; + +// Test environment for Radio HIDL HAL. +class RadioConfigHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { + public: + // get the test environment singleton + static RadioConfigHidlEnvironment* Instance() { + static RadioConfigHidlEnvironment* instance = new RadioConfigHidlEnvironment; + return instance; + } + virtual void registerTestServices() override { registerTestService(); } + + private: + RadioConfigHidlEnvironment() {} +}; + +// The main test class for Radio config HIDL. +class RadioConfigHidlTest : public ::testing::VtsHalHidlTargetTestBase { + protected: + std::mutex mtx_; + std::condition_variable cv_; + int count_; + + public: + virtual void SetUp() override; + + /* Used as a mechanism to inform the test about data/event callback */ + void notify(int receivedSerial); + + /* Test code calls this function to wait for response */ + std::cv_status wait(); + + void updateSimCardStatus(); + + /* Serial number for radio request */ + int serial; + + /* radio config service handle */ + sp radioConfig; + + /* radio config response handle */ + sp radioConfigRsp; +}; diff --git a/radio/config/1.2/vts/functional/radio_config_indication.cpp b/radio/config/1.2/vts/functional/radio_config_indication.cpp new file mode 100644 index 0000000000..0bacacb363 --- /dev/null +++ b/radio/config/1.2/vts/functional/radio_config_indication.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2019 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 + +RadioConfigIndication::RadioConfigIndication(RadioConfigHidlTest& parent) : parent(parent) {} + +Return RadioConfigIndication::simSlotsStatusChanged_1_2( + ::android::hardware::radio::V1_0::RadioIndicationType /*type*/, + const ::android::hardware::hidl_vec& /*slotStatus*/) { + return Void(); +} diff --git a/radio/config/1.2/vts/functional/radio_config_response.cpp b/radio/config/1.2/vts/functional/radio_config_response.cpp new file mode 100644 index 0000000000..ec0f88662a --- /dev/null +++ b/radio/config/1.2/vts/functional/radio_config_response.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2019 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 + +using ::android::hardware::radio::V1_0::RadioResponseInfo; + +// SimSlotStatus slotStatus; + +RadioConfigResponse::RadioConfigResponse(RadioConfigHidlTest& parent) : parent(parent) {} + +Return RadioConfigResponse::getSimSlotsStatusResponse( + const ::android::hardware::radio::V1_0::RadioResponseInfo& /* info */, + const ::android::hardware::hidl_vec< + ::android::hardware::radio::config::V1_0::SimSlotStatus>& /* slotStatus */) { + return Void(); +} + +Return RadioConfigResponse::getSimSlotsStatusResponse_1_2( + const ::android::hardware::radio::V1_0::RadioResponseInfo& /* info */, + const ::android::hardware::hidl_vec& /* slotStatus */) { + return Void(); +} + +Return RadioConfigResponse::setSimSlotsMappingResponse( + const ::android::hardware::radio::V1_0::RadioResponseInfo& /* info */) { + return Void(); +} + +Return RadioConfigResponse::getPhoneCapabilityResponse( + const ::android::hardware::radio::V1_0::RadioResponseInfo& info, + const PhoneCapability& phoneCapability) { + rspInfo = info; + phoneCap = phoneCapability; + parent.notify(info.serial); + return Void(); +} + +Return RadioConfigResponse::setPreferredDataModemResponse( + const ::android::hardware::radio::V1_0::RadioResponseInfo& /* info */) { + return Void(); +} + +Return RadioConfigResponse::getModemsConfigResponse( + const ::android::hardware::radio::V1_0::RadioResponseInfo& /* info */, + const ModemsConfig& /* mConfig */) { + return Void(); +} + +Return RadioConfigResponse::setModemsConfigResponse( + const ::android::hardware::radio::V1_0::RadioResponseInfo& /* info */) { + return Void(); +} From 17aa6d351271222bb8abc8dbb61e00757e358f31 Mon Sep 17 00:00:00 2001 From: Changyeon Jo Date: Sat, 25 May 2019 12:02:43 -0700 Subject: [PATCH 691/718] Update EVS VTS test cases This change modifies existing test cases and adds one new test case for EVS manager implementation. Bug: 122468953 Change-Id: I5cee01dfe0b0617c3f5c46beb94dcda0387f4ba0 Signed-off-by: Changyeon Jo --- .../evs/1.0/vts/functional/FrameHandler.cpp | 14 ++ .../evs/1.0/vts/functional/FrameHandler.h | 3 + .../functional/VtsHalEvsV1_0TargetTest.cpp | 123 ++++++++++++++++-- 3 files changed, 131 insertions(+), 9 deletions(-) diff --git a/automotive/evs/1.0/vts/functional/FrameHandler.cpp b/automotive/evs/1.0/vts/functional/FrameHandler.cpp index d44ba41c5d..bc3790f385 100644 --- a/automotive/evs/1.0/vts/functional/FrameHandler.cpp +++ b/automotive/evs/1.0/vts/functional/FrameHandler.cpp @@ -137,6 +137,10 @@ Return FrameHandler::deliverFrame(const BufferDesc& bufferArg) { // Signal that the last frame has been received and the stream is stopped timeToStop = true; } else { + // Store a dimension of a received frame. + mFrameWidth = bufferArg.width; + mFrameHeight = bufferArg.height; + // If we were given an opened display at construction time, then send the received // image back down the camera. if (mDisplay.get()) { @@ -299,3 +303,13 @@ bool FrameHandler::copyBufferContents(const BufferDesc& tgtBuffer, return success; } + +void FrameHandler::getFrameDimension(unsigned* width, unsigned* height) { + if (width) { + *width = mFrameWidth; + } + + if (height) { + *height = mFrameHeight; + } +} diff --git a/automotive/evs/1.0/vts/functional/FrameHandler.h b/automotive/evs/1.0/vts/functional/FrameHandler.h index 17a39803fa..3f6103d8ac 100644 --- a/automotive/evs/1.0/vts/functional/FrameHandler.h +++ b/automotive/evs/1.0/vts/functional/FrameHandler.h @@ -61,6 +61,7 @@ public: void waitForFrameCount(unsigned frameCount); void getFramesCounters(unsigned* received, unsigned* displayed); + void getFrameDimension(unsigned* width, unsigned* height); private: // Implementation for ::android::hardware::automotive::evs::V1_0::ICarCameraStream @@ -85,6 +86,8 @@ private: bool mRunning = false; unsigned mFramesReceived = 0; // Simple counter -- rolls over eventually! unsigned mFramesDisplayed = 0; // Simple counter -- rolls over eventually! + unsigned mFrameWidth = 0; + unsigned mFrameHeight = 0; }; diff --git a/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp b/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp index d904ad06bf..f7580f02a8 100644 --- a/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp +++ b/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp @@ -84,9 +84,12 @@ class EvsHidlTest : public ::testing::VtsHalHidlTargetTestBase { public: virtual void SetUp() override { // Make sure we can connect to the enumerator - pEnumerator = getService( - EvsHidlEnvironment::Instance()->getServiceName(kEnumeratorName)); + string service_name = + EvsHidlEnvironment::Instance()->getServiceName(kEnumeratorName); + pEnumerator = getService(service_name); ASSERT_NE(pEnumerator.get(), nullptr); + + mIsHwModule = !service_name.compare(kEnumeratorName); } virtual void TearDown() override {} @@ -114,12 +117,13 @@ protected: sp pEnumerator; // Every test needs access to the service std::vector cameraInfo; // Empty unless/until loadCameraList() is called + bool mIsHwModule; // boolean to tell current module under testing + // is HW module implementation. }; -// -// Tests start here... -// +// Test cases, their implementations, and corresponding requirements are +// documented at go/aae-evs-public-api-test. /* * CameraOpenClean: @@ -180,9 +184,14 @@ TEST_F(EvsHidlTest, CameraOpenAggressive) { ASSERT_NE(pCam, pCam2); ASSERT_NE(pCam2, nullptr); - // Verify that the old camera rejects calls - Return badResult = pCam->setMaxFramesInFlight(2); - EXPECT_EQ(EvsResult::OWNERSHIP_LOST, EvsResult(badResult)); + Return result = pCam->setMaxFramesInFlight(2); + if (mIsHwModule) { + // Verify that the old camera rejects calls via HW module. + EXPECT_EQ(EvsResult::OWNERSHIP_LOST, EvsResult(result)); + } else { + // default implementation supports multiple clients. + EXPECT_EQ(EvsResult::OK, EvsResult(result)); + } // Close the superceded camera pEnumerator->closeCamera(pCam); @@ -194,7 +203,8 @@ TEST_F(EvsHidlTest, CameraOpenAggressive) { } ); - // Leave the second camera dangling so it gets cleaned up by the destructor path + // Close the second camera instance + pEnumerator->closeCamera(pCam2); } // Sleep here to ensure the destructor cleanup has time to run so we don't break follow on tests @@ -343,6 +353,11 @@ TEST_F(EvsHidlTest, CameraStreamPerformance) { printf("Measured time to first frame %0.2f ms\n", timeToFirstFrame * kNanoToMilliseconds); ALOGI("Measured time to first frame %0.2f ms", timeToFirstFrame * kNanoToMilliseconds); + // Check aspect ratio + unsigned width = 0, height = 0; + frameHandler->getFrameDimension(&width, &height); + EXPECT_GE(width, height); + // Wait a bit, then ensure we get at least the required minimum number of frames sleep(5); nsecs_t end = systemTime(SYSTEM_TIME_MONOTONIC); @@ -496,6 +511,96 @@ TEST_F(EvsHidlTest, CameraToDisplayRoundTrip) { pEnumerator->closeDisplay(pDisplay); } + +/* + * MultiCameraStream: + * Verify that each client can start and stop video streams on the same + * underlying camera. + */ +TEST_F(EvsHidlTest, MultiCameraStream) { + ALOGI("Starting MultiCameraStream test"); + + if (mIsHwModule) { + // This test is not for HW module implementation. + return; + } + + // Get the camera list + loadCameraList(); + + // Test each reported camera + for (auto&& cam: cameraInfo) { + // Create two camera clients. + sp pCam0 = pEnumerator->openCamera(cam.cameraId); + ASSERT_NE(pCam0, nullptr); + + sp pCam1 = pEnumerator->openCamera(cam.cameraId); + ASSERT_NE(pCam1, nullptr); + + // Set up per-client frame receiver objects which will fire up its own thread + sp frameHandler0 = new FrameHandler(pCam0, cam, + nullptr, + FrameHandler::eAutoReturn); + ASSERT_NE(frameHandler0, nullptr); + + sp frameHandler1 = new FrameHandler(pCam1, cam, + nullptr, + FrameHandler::eAutoReturn); + ASSERT_NE(frameHandler1, nullptr); + + // Start the camera's video stream via client 0 + bool startResult = false; + startResult = frameHandler0->startStream() && + frameHandler1->startStream(); + ASSERT_TRUE(startResult); + + // Ensure the stream starts + frameHandler0->waitForFrameCount(1); + frameHandler1->waitForFrameCount(1); + + nsecs_t firstFrame = systemTime(SYSTEM_TIME_MONOTONIC); + + // Wait a bit, then ensure both clients get at least the required minimum number of frames + sleep(5); + nsecs_t end = systemTime(SYSTEM_TIME_MONOTONIC); + unsigned framesReceived0 = 0, framesReceived1 = 0; + frameHandler0->getFramesCounters(&framesReceived0, nullptr); + frameHandler1->getFramesCounters(&framesReceived1, nullptr); + framesReceived0 = framesReceived0 - 1; // Back out the first frame we already waited for + framesReceived1 = framesReceived1 - 1; // Back out the first frame we already waited for + nsecs_t runTime = end - firstFrame; + float framesPerSecond0 = framesReceived0 / (runTime * kNanoToSeconds); + float framesPerSecond1 = framesReceived1 / (runTime * kNanoToSeconds); + printf("Measured camera rate %3.2f fps and %3.2f fps\n", framesPerSecond0, framesPerSecond1); + ALOGI("Measured camera rate %3.2f fps and %3.2f fps", framesPerSecond0, framesPerSecond1); + EXPECT_GE(framesPerSecond0, kMinimumFramesPerSecond); + EXPECT_GE(framesPerSecond1, kMinimumFramesPerSecond); + + // Shutdown one client + frameHandler0->shutdown(); + + // Read frame counters again + frameHandler0->getFramesCounters(&framesReceived0, nullptr); + frameHandler1->getFramesCounters(&framesReceived1, nullptr); + + // Wait a bit again + sleep(5); + unsigned framesReceivedAfterStop0 = 0, framesReceivedAfterStop1 = 0; + frameHandler0->getFramesCounters(&framesReceivedAfterStop0, nullptr); + frameHandler1->getFramesCounters(&framesReceivedAfterStop1, nullptr); + EXPECT_EQ(framesReceived0, framesReceivedAfterStop0); + EXPECT_LT(framesReceived1, framesReceivedAfterStop1); + + // Shutdown another + frameHandler1->shutdown(); + + // Explicitly release the camera + pEnumerator->closeCamera(pCam0); + pEnumerator->closeCamera(pCam1); + } +} + + int main(int argc, char** argv) { ::testing::AddGlobalTestEnvironment(EvsHidlEnvironment::Instance()); ::testing::InitGoogleTest(&argc, argv); From 22f6dcec7e81c1a747b516377d2e7fc8cb06c508 Mon Sep 17 00:00:00 2001 From: Shuzhen Wang Date: Mon, 20 May 2019 11:04:29 -0700 Subject: [PATCH 692/718] Camera: Use original dataspace/format for 3.5 device Starting from CameraDeviceSession 3.5, for IMPLEMENTATION_DEFINED pixel format, configureStreams call uses original format and dataspace instead of the overridden value. This makes sure the HAL interface behavior is consistent between first and subsequent processCaptureRequest() calls. Test: Camera CTS and partner testing Bug: 131864007 Change-Id: Id701141d2c11089ef063fd3f32444212855f84ab --- .../3.4/default/CameraDeviceSession.cpp | 29 ++++++++++++++----- .../device_v3_4_impl/CameraDeviceSession.h | 4 +-- camera/device/3.5/ICameraDeviceSession.hal | 6 ++++ .../3.5/default/CameraDeviceSession.cpp | 2 +- current.txt | 1 + 5 files changed, 31 insertions(+), 11 deletions(-) diff --git a/camera/device/3.4/default/CameraDeviceSession.cpp b/camera/device/3.4/default/CameraDeviceSession.cpp index 03b6050397..b4ebe22701 100644 --- a/camera/device/3.4/default/CameraDeviceSession.cpp +++ b/camera/device/3.4/default/CameraDeviceSession.cpp @@ -75,7 +75,7 @@ Return CameraDeviceSession::configureStreams_3_4( void CameraDeviceSession::configureStreams_3_4_Impl( const StreamConfiguration& requestedConfiguration, ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb, - uint32_t streamConfigCounter) { + uint32_t streamConfigCounter, bool useOverriddenFields) { Status status = initStatus(); HalStreamConfiguration outStreams; @@ -133,7 +133,8 @@ void CameraDeviceSession::configureStreams_3_4_Impl( mStreamConfigCounter = streamConfigCounter; hidl_vec streams; stream_list.session_parameters = paramBuffer; - if (!preProcessConfigurationLocked_3_4(requestedConfiguration, &stream_list, &streams)) { + if (!preProcessConfigurationLocked_3_4(requestedConfiguration, + useOverriddenFields, &stream_list, &streams)) { _hidl_cb(Status::INTERNAL_ERROR, outStreams); return; } @@ -164,7 +165,7 @@ void CameraDeviceSession::configureStreams_3_4_Impl( } bool CameraDeviceSession::preProcessConfigurationLocked_3_4( - const StreamConfiguration& requestedConfiguration, + const StreamConfiguration& requestedConfiguration, bool useOverriddenFields, camera3_stream_configuration_t *stream_list /*out*/, hidl_vec *streams /*out*/) { @@ -189,19 +190,31 @@ bool CameraDeviceSession::preProcessConfigurationLocked_3_4( mStreamMap[id].data_space); mCirculatingBuffers.emplace(stream.mId, CirculatingBuffers{}); } else { - // width/height/format must not change, but usage/rotation might need to change + // width/height/format must not change, but usage/rotation might need to change. + // format and data_space may change. if (mStreamMap[id].stream_type != (int) requestedConfiguration.streams[i].v3_2.streamType || mStreamMap[id].width != requestedConfiguration.streams[i].v3_2.width || mStreamMap[id].height != requestedConfiguration.streams[i].v3_2.height || - mStreamMap[id].format != (int) requestedConfiguration.streams[i].v3_2.format || - mStreamMap[id].data_space != - mapToLegacyDataspace( static_cast ( - requestedConfiguration.streams[i].v3_2.dataSpace)) || mPhysicalCameraIdMap[id] != requestedConfiguration.streams[i].physicalCameraId) { ALOGE("%s: stream %d configuration changed!", __FUNCTION__, id); return false; } + if (useOverriddenFields) { + android_dataspace_t requestedDataSpace = + mapToLegacyDataspace(static_cast( + requestedConfiguration.streams[i].v3_2.dataSpace)); + if (mStreamMap[id].format != (int) requestedConfiguration.streams[i].v3_2.format || + mStreamMap[id].data_space != requestedDataSpace) { + ALOGE("%s: stream %d configuration changed!", __FUNCTION__, id); + return false; + } + } else { + mStreamMap[id].format = + (int) requestedConfiguration.streams[i].v3_2.format; + mStreamMap[id].data_space = (android_dataspace_t) + requestedConfiguration.streams[i].v3_2.dataSpace; + } mStreamMap[id].rotation = (int) requestedConfiguration.streams[i].v3_2.rotation; mStreamMap[id].usage = (uint32_t) requestedConfiguration.streams[i].v3_2.usage; } diff --git a/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h b/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h index 1db7b41dec..280c4bec46 100644 --- a/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h +++ b/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h @@ -80,7 +80,7 @@ protected: ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb); bool preProcessConfigurationLocked_3_4( - const StreamConfiguration& requestedConfiguration, + const StreamConfiguration& requestedConfiguration, bool useOverriddenFields, camera3_stream_configuration_t *stream_list /*out*/, hidl_vec *streams /*out*/); void postProcessConfigurationLocked_3_4(const StreamConfiguration& requestedConfiguration); @@ -91,7 +91,7 @@ protected: const StreamConfiguration& requestedConfiguration, ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb, // Optional argument for ICameraDeviceSession@3.5 impl - uint32_t streamConfigCounter = 0); + uint32_t streamConfigCounter = 0, bool useOverriddenFields = true); Return processCaptureRequest_3_4( const hidl_vec& requests, diff --git a/camera/device/3.5/ICameraDeviceSession.hal b/camera/device/3.5/ICameraDeviceSession.hal index d0cfe392ae..c868e1e96c 100644 --- a/camera/device/3.5/ICameraDeviceSession.hal +++ b/camera/device/3.5/ICameraDeviceSession.hal @@ -36,6 +36,12 @@ interface ICameraDeviceSession extends @3.4::ICameraDeviceSession { * * - a streamConfigCounter counter is provided to check for race condition * between configureStreams_3_5 and signalStreamFlush call. + * - In case the HAL overrides dataspace or format for + * IMPLEMENTATION_DEFINED pixel format, camera framework must use original + * dataspace and format in subsequent configureStreams_3_5 calls for the same + * stream. HAL is allowed to change the overriding behavior of format or + * dataspace for reconfiguration of the same stream depending on the stream + * combination. * * @return status Status code for the operation, one of: * OK: diff --git a/camera/device/3.5/default/CameraDeviceSession.cpp b/camera/device/3.5/default/CameraDeviceSession.cpp index e812e50f5f..44d067d475 100644 --- a/camera/device/3.5/default/CameraDeviceSession.cpp +++ b/camera/device/3.5/default/CameraDeviceSession.cpp @@ -66,7 +66,7 @@ Return CameraDeviceSession::configureStreams_3_5( const StreamConfiguration& requestedConfiguration, ICameraDeviceSession::configureStreams_3_5_cb _hidl_cb) { configureStreams_3_4_Impl(requestedConfiguration.v3_4, _hidl_cb, - requestedConfiguration.streamConfigCounter); + requestedConfiguration.streamConfigCounter, false /*useOverriddenFields*/); return Void(); } diff --git a/current.txt b/current.txt index 5742d667d0..6510134204 100644 --- a/current.txt +++ b/current.txt @@ -455,6 +455,7 @@ f7431f3e3e4e3387fc6f27a6cf423eddcd824a395dc4349d302c995ab44a9895 android.hardwar 09ab9b24994429d9bb32a3fb420b6f6be3e47eb655139a2c08c4e80d3f33ff95 android.hardware.camera.device@3.5::ICameraDevice 06237de53c42890029e3f8fe7d1480d078469c0d07608e51c37b4d485d342992 android.hardware.camera.device@3.5::ICameraDeviceCallback 08c68b196e2fc4e5ba67ba0d0917bde828a87cbe2cffec19d04733972da9eb49 android.hardware.camera.device@3.5::ICameraDeviceSession +feabf0b7caa947757bf74375aceb4919a5aa99dd6a36216843553b6adec7eb5d android.hardware.camera.device@3.5::ICameraDeviceSession # b/131864007 f9b8b388c0c76669e4b9189e4943efd2982f9bda5c10e276f96cc91bc8e818d6 android.hardware.camera.device@3.5::types f727d5f350f55a6d3354aad2feb64e43200de77c10d9d642465566bc260bb8ec android.hardware.camera.metadata@3.4::types 0fb39a7809ad1c52b3efbbed5ef4749b06c2a4f1f19cdc3efa2e3d9b28f1205c android.hardware.camera.provider@2.5::ICameraProvider From b6b28e58c421c12ca70c71d2f396e9ce11e2e5df Mon Sep 17 00:00:00 2001 From: Brian Duddie Date: Mon, 10 Jun 2019 09:14:14 -0700 Subject: [PATCH 693/718] Fix null deref in sensors 2.0 VTS teardown Avoid attempting to clean up resources that were never initialized, e.g. if the target device doesn't support the version of the HAL in question. Fixes: 134911861 Test: run VtsHalSensorsV2_0Target on device that only supports HAL v1.0 Change-Id: I6b529fae13b1347d533a19e04f1c7748bcda961b --- .../vts/functional/SensorsHidlEnvironmentV2_0.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp index be7415bb7c..5f71654e97 100644 --- a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp +++ b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp @@ -109,11 +109,15 @@ bool SensorsHidlEnvironmentV2_0::resetHal() { void SensorsHidlEnvironmentV2_0::HidlTearDown() { mStopThread = true; - // Wake up the event queue so the poll thread can exit - mEventQueueFlag->wake(asBaseType(EventQueueFlagBits::READ_AND_PROCESS)); - mPollThread.join(); + if (mEventQueueFlag != nullptr) { + // Wake up the event queue so the poll thread can exit + mEventQueueFlag->wake(asBaseType(EventQueueFlagBits::READ_AND_PROCESS)); + if (mPollThread.joinable()) { + mPollThread.join(); + } - EventFlag::deleteEventFlag(&mEventQueueFlag); + EventFlag::deleteEventFlag(&mEventQueueFlag); + } } void SensorsHidlEnvironmentV2_0::startPollingThread() { From 9c93b3500aa13a62994d08640682a5abfe75d4d5 Mon Sep 17 00:00:00 2001 From: Tim Lin Date: Tue, 11 Jun 2019 11:31:37 +0800 Subject: [PATCH 694/718] Fix RadioConfig 1.1 vts test Bug: 134645639 Test: VtsHalRadioConfigV1_0Target VtsHalRadioConfigV1_1Target VtsHalRadioConfigV1_2Target Change-Id: I0c3171bf50de4f320b53d73962a4a5013a9c72e4 --- .../vts/functional/radio_config_hidl_hal_api.cpp | 6 ++++-- .../vts/functional/radio_config_hidl_hal_test.cpp | 5 +---- .../1.1/vts/functional/radio_config_response.cpp | 13 +++++++++---- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/radio/config/1.1/vts/functional/radio_config_hidl_hal_api.cpp b/radio/config/1.1/vts/functional/radio_config_hidl_hal_api.cpp index 122ce58a3e..5d0e867402 100644 --- a/radio/config/1.1/vts/functional/radio_config_hidl_hal_api.cpp +++ b/radio/config/1.1/vts/functional/radio_config_hidl_hal_api.cpp @@ -130,7 +130,8 @@ TEST_F(RadioConfigHidlTest, setPreferredDataModem) { EXPECT_EQ(std::cv_status::no_timeout, wait()); EXPECT_EQ(RadioResponseType::SOLICITED, radioConfigRsp->rspInfo.type); EXPECT_EQ(serial, radioConfigRsp->rspInfo.serial); - ALOGI("getModemsConfig, rspInfo.error = %s\n", toString(radioConfigRsp->rspInfo.error).c_str()); + ALOGI("setPreferredDataModem, rspInfo.error = %s\n", + toString(radioConfigRsp->rspInfo.error).c_str()); ASSERT_TRUE(CheckAnyOfErrors( radioConfigRsp->rspInfo.error, @@ -149,7 +150,8 @@ TEST_F(RadioConfigHidlTest, setPreferredDataModem_invalidArgument) { EXPECT_EQ(std::cv_status::no_timeout, wait()); EXPECT_EQ(RadioResponseType::SOLICITED, radioConfigRsp->rspInfo.type); EXPECT_EQ(serial, radioConfigRsp->rspInfo.serial); - ALOGI("getModemsConfig, rspInfo.error = %s\n", toString(radioConfigRsp->rspInfo.error).c_str()); + ALOGI("setPreferredDataModem, rspInfo.error = %s\n", + toString(radioConfigRsp->rspInfo.error).c_str()); ASSERT_TRUE(CheckAnyOfErrors(radioConfigRsp->rspInfo.error, {RadioError::INVALID_ARGUMENTS, RadioError::RADIO_NOT_AVAILABLE, diff --git a/radio/config/1.1/vts/functional/radio_config_hidl_hal_test.cpp b/radio/config/1.1/vts/functional/radio_config_hidl_hal_test.cpp index a8c257d8fc..39e6487410 100644 --- a/radio/config/1.1/vts/functional/radio_config_hidl_hal_test.cpp +++ b/radio/config/1.1/vts/functional/radio_config_hidl_hal_test.cpp @@ -34,9 +34,6 @@ void RadioConfigHidlTest::SetUp() { count_ = 0; radioConfig->setResponseFunctions(radioConfigRsp, nullptr); - EXPECT_EQ(RadioResponseType::SOLICITED, radioConfigRsp->rspInfo.type); - EXPECT_EQ(serial, radioConfigRsp->rspInfo.serial); - EXPECT_EQ(RadioError::NONE, radioConfigRsp->rspInfo.error); } /* @@ -66,4 +63,4 @@ std::cv_status RadioConfigHidlTest::wait() { } count_--; return status; -} \ No newline at end of file +} diff --git a/radio/config/1.1/vts/functional/radio_config_response.cpp b/radio/config/1.1/vts/functional/radio_config_response.cpp index ce3dfdff5d..bd8c4cfa01 100644 --- a/radio/config/1.1/vts/functional/radio_config_response.cpp +++ b/radio/config/1.1/vts/functional/radio_config_response.cpp @@ -38,16 +38,21 @@ Return RadioConfigResponse::getPhoneCapabilityResponse( return Void(); } -Return RadioConfigResponse::setPreferredDataModemResponse( - const RadioResponseInfo& /* info */) { +Return RadioConfigResponse::setPreferredDataModemResponse(const RadioResponseInfo& info) { + rspInfo = info; + parent.notify(info.serial); return Void(); } -Return RadioConfigResponse::getModemsConfigResponse(const RadioResponseInfo& /* info */, +Return RadioConfigResponse::getModemsConfigResponse(const RadioResponseInfo& info, const ModemsConfig& /* mConfig */) { + rspInfo = info; + parent.notify(info.serial); return Void(); } -Return RadioConfigResponse::setModemsConfigResponse(const RadioResponseInfo& /* info */) { +Return RadioConfigResponse::setModemsConfigResponse(const RadioResponseInfo& info) { + rspInfo = info; + parent.notify(info.serial); return Void(); } From 085a82ecb152ad8bcac8eff0bb9cb3e94519edf2 Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Mon, 10 Jun 2019 13:44:19 -0700 Subject: [PATCH 695/718] libhidltransport users user libhidlbase libhidltransport symbols are being moved into libhidlbase in order to optimize linking/memory usage. libhidltransport will no longer be required in the future (however removing references to it will come separately). Bug: 134961554 Test: boot Change-Id: Ibcc2db32d3bec1a786b60e11d4820ecd0605f403 --- graphics/composer/2.2/vts/functional/Android.bp | 1 + graphics/composer/2.3/vts/functional/Android.bp | 1 + health/storage/1.0/vts/functional/Android.bp | 3 ++- wifi/1.3/default/Android.mk | 2 +- 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/graphics/composer/2.2/vts/functional/Android.bp b/graphics/composer/2.2/vts/functional/Android.bp index b62f3021b9..4cb0bdf078 100644 --- a/graphics/composer/2.2/vts/functional/Android.bp +++ b/graphics/composer/2.2/vts/functional/Android.bp @@ -25,6 +25,7 @@ cc_test { // TODO(b/64437680): Assume these libs are always available on the device. shared_libs: [ "libfmq", + "libhidlbase", "libhidltransport", "libsync", ], diff --git a/graphics/composer/2.3/vts/functional/Android.bp b/graphics/composer/2.3/vts/functional/Android.bp index 7548cb521e..ce675ee4ef 100644 --- a/graphics/composer/2.3/vts/functional/Android.bp +++ b/graphics/composer/2.3/vts/functional/Android.bp @@ -22,6 +22,7 @@ cc_test { // TODO(b/64437680): Assume these libs are always available on the device. shared_libs: [ "libfmq", + "libhidlbase", "libhidltransport", "libsync", ], diff --git a/health/storage/1.0/vts/functional/Android.bp b/health/storage/1.0/vts/functional/Android.bp index 250a7dcb84..b18e36f83e 100644 --- a/health/storage/1.0/vts/functional/Android.bp +++ b/health/storage/1.0/vts/functional/Android.bp @@ -20,7 +20,8 @@ cc_test { srcs: ["VtsHalHealthStorageV1_0TargetTest.cpp"], static_libs: ["android.hardware.health.storage@1.0"], shared_libs: [ - "libhidltransport" + "libhidlbase", + "libhidltransport", ], test_suites: ["general-tests"], } diff --git a/wifi/1.3/default/Android.mk b/wifi/1.3/default/Android.mk index 1f918618f7..0a3809cce5 100644 --- a/wifi/1.3/default/Android.mk +++ b/wifi/1.3/default/Android.mk @@ -155,11 +155,11 @@ LOCAL_SRC_FILES := \ LOCAL_STATIC_LIBRARIES := \ libgmock \ libgtest \ - libhidlbase \ android.hardware.wifi@1.0-service-lib LOCAL_SHARED_LIBRARIES := \ libbase \ libcutils \ + libhidlbase \ libhidltransport \ liblog \ libnl \ From 56ff57b4cefd100cb1efc9e2fa1edf25a71a9ee0 Mon Sep 17 00:00:00 2001 From: Mark Tabry Date: Fri, 14 Jun 2019 10:32:12 -0700 Subject: [PATCH 696/718] Move START_SESSION definition to bottom of VmsMessageType. Bug: 130313799 Test: N/A Change-Id: Iaa1be8f047c58491970b5aaa0dfab4e418164dee --- automotive/vehicle/2.0/types.hal | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal index 6c76d7ba57..f6ebcdd7d0 100644 --- a/automotive/vehicle/2.0/types.hal +++ b/automotive/vehicle/2.0/types.hal @@ -3286,16 +3286,6 @@ enum DiagnosticFloatSensorIndex : int32_t { * the message is decoded. */ enum VmsMessageType : int32_t { - /** - * A notification indicating that the sender has been reset. - * - * The receiving party must reset its internal state and respond to the - * sender with a START_SESSION message as acknowledgement. - * - * This message type uses enum VmsStartSessionMessageIntegerValuesIndex. - */ - START_SESSION = 17, - /** * A request from the subscribers to the VMS service to subscribe to a layer. * @@ -3412,6 +3402,16 @@ enum VmsMessageType : int32_t { */ PUBLISHER_INFORMATION_RESPONSE = 16, + /** + * A notification indicating that the sender has been reset. + * + * The receiving party must reset its internal state and respond to the + * sender with a START_SESSION message as acknowledgement. + * + * This message type uses enum VmsStartSessionMessageIntegerValuesIndex. + */ + START_SESSION = 17, + LAST_VMS_MESSAGE_TYPE = START_SESSION, }; From a69036fbfebc748b463b4f6cd7b8025806e6be5e Mon Sep 17 00:00:00 2001 From: Brian Duddie Date: Thu, 13 Jun 2019 16:45:46 -0700 Subject: [PATCH 697/718] Add guidance for avoiding race in Sensors HAL 2.0 Bug: 135216821 Test: n/a, comment change only Change-Id: Iad491c5e221c86a2724d4074ac645b8ee6e9af6f --- current.txt | 1 + sensors/2.0/ISensors.hal | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/current.txt b/current.txt index 6510134204..47e7d721cc 100644 --- a/current.txt +++ b/current.txt @@ -546,6 +546,7 @@ d8e7717e8187dd7453d4142f8f331e7c325e7a6f9e8d44ac0d52b3be502bfe83 android.hardwar 08d439c463e4044fa78874037d8e8379aa3cabecde32f08a775897eea5a538af android.hardware.secure_element@1.1::ISecureElement b53ac9d61c24efb16a2d63a861cef20680f6d57adb244a03b9778c675550628b android.hardware.secure_element@1.1::ISecureElementHalCallback 3702b1c52c0bb3427244618e9e7975c05228bf4ceb8720da7a93603a71cb0368 android.hardware.sensors@2.0::ISensors +c36670945ea09d92ae90a557147352ed9bd5223f957d347b367c2acb6f94870f android.hardware.sensors@2.0::ISensors # b/135216821 ae5faa38538a9f50eb71eb7f9b998271124d2c64b761cb11c4d820c7732b4ddc android.hardware.sensors@2.0::ISensorsCallback 3a98242a57d0820dacaca0f7db52bec433eae1f21c498763c6f1ece611c3967b android.hardware.sensors@2.0::types ce4b98211959449361146d4b1e5554dc841ceb4d4577154d7b2fb6d1eb504f76 android.hardware.soundtrigger@2.2::ISoundTriggerHw diff --git a/sensors/2.0/ISensors.hal b/sensors/2.0/ISensors.hal index 3a9af46bf5..a84c56e9ad 100644 --- a/sensors/2.0/ISensors.hal +++ b/sensors/2.0/ISensors.hal @@ -99,7 +99,11 @@ interface ISensors { * Lock FMQ. When the HAL reads the data from the Wake Lock FMQ, the HAL * decrements its current count of unprocessed WAKE_UP events and releases * its wake_lock if the current count of unprocessed WAKE_UP events is - * zero. + * zero. It is important to note that the HAL must acquire the wake lock and + * update its internal state regarding the number of outstanding WAKE_UP + * events _before_ posting the event to the Wake Lock FMQ, in order to avoid + * a race condition that can lead to loss of wake lock synchronization with + * the framework. * * The framework must use the WakeLockQueueFlagBits::DATA_WRITTEN value to * notify the HAL that data has been written to the Wake Lock FMQ and must From cf9daece29d8b74427c4b7a636525b227e4f7869 Mon Sep 17 00:00:00 2001 From: Max Bires Date: Wed, 22 May 2019 00:48:49 +0000 Subject: [PATCH 698/718] Removing an extraneous test Test: VTS passes Bug: 133316458 Change-Id: I98d73ff025515a89e2743ed20950c840aedb5114 (cherry picked from commit b28e69f37efe8d569db2a3fc9dd9c633c0ab8ba5) --- .../functional/keymaster_hidl_hal_test.cpp | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp index 3d37e9fb82..6f75a9720c 100644 --- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp +++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp @@ -4218,28 +4218,6 @@ TEST_F(AttestationTest, RsaAttestationRequiresAppId) { &cert_chain)); } -/* - * AttestationTest.RsaAttestationRequiresCorrectAppId - * - * Verifies that attesting to RSA requires the correct app ID. - */ -TEST_F(AttestationTest, RsaAttestationRequiresCorrectAppId) { - ASSERT_EQ(ErrorCode::OK, - GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .RsaSigningKey(2048, 65537) - .Digest(Digest::NONE) - .Padding(PaddingMode::NONE) - .Authorization(TAG_APPLICATION_ID, HidlBuf("lol")))); - - hidl_vec> cert_chain; - EXPECT_EQ(ErrorCode::ATTESTATION_APPLICATION_ID_MISSING, - AttestKey(AuthorizationSetBuilder() - .Authorization(TAG_ATTESTATION_CHALLENGE, HidlBuf("challenge")) - .Authorization(TAG_APPLICATION_ID, HidlBuf("heh")), - &cert_chain)); -} - /* * AttestationTest.EcAttestation * From 258c7c25047c11df6af6b11ee14ce2b3d56e5e4d Mon Sep 17 00:00:00 2001 From: Prachi Hande Date: Wed, 12 Jun 2019 15:49:25 -0700 Subject: [PATCH 699/718] VMS Utils: Fixed createDataMessage method. Before, it used to process only the payload but now it also takes in VMS layer info and publisher ID. Bug: 135051289 Fixes: 135051289 Test: Updated unit tests in VmsUtilsTest. Ran the tests on Hawk. Change-Id: I6c11f95a815af5d7b9fc9288692285766d2ca98f --- .../common/include/vhal_v2_0/VmsUtils.h | 14 ++++++++---- .../2.0/default/common/src/VmsUtils.cpp | 11 ++++++---- .../2.0/default/tests/VmsUtils_test.cpp | 22 ++++++++++++++----- 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h index 7082566d2e..87010cea0c 100644 --- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h +++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h @@ -60,6 +60,8 @@ struct VmsLayer { }; struct VmsLayerAndPublisher { + VmsLayerAndPublisher(VmsLayer layer, int publisher_id) + : layer(layer), publisher_id(publisher_id) {} VmsLayer layer; int publisher_id; }; @@ -162,12 +164,16 @@ std::unique_ptr createAvailabilityRequest(); std::unique_ptr createSubscriptionsRequest(); // Creates a VehiclePropValue containing a message of type VmsMessageType.DATA. -// Returns a nullptr if the byte string in bytes is empty. +// Returns a nullptr if the vms_packet string in bytes is empty or if the layer_publisher +// information in VmsLayerAndPublisher format is missing the later or publisher +// information. // // For example, to build a VehiclePropValue message containing a proto, the caller -// should convert the proto to a byte string using the SerializeToString proto -// API, then use this inteface to build the VehicleProperty. -std::unique_ptr createDataMessage(const std::string& bytes); +// should first convert the proto to a byte string (vms_packet) using the +// SerializeToString proto API. Then, it use this interface to build the VehicleProperty +// by passing publisher and layer information (layer_publisher) and the vms_packet. +std::unique_ptr CreateDataMessageWithLayerPublisherInfo( + const VmsLayerAndPublisher& layer_publisher, const std::string& vms_packet); // Creates a VehiclePropValue containing a message of type // VmsMessageType.PUBLISHER_ID_REQUEST with the given publisher information. diff --git a/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp b/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp index 111f6eac8e..f16489ce83 100644 --- a/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp +++ b/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp @@ -126,10 +126,13 @@ std::unique_ptr createSubscriptionsRequest() { return result; } -std::unique_ptr createDataMessage(const std::string& bytes) { - auto result = createBaseVmsMessage(kMessageTypeSize); - result->value.int32Values = hidl_vec{toInt(VmsMessageType::DATA)}; - result->value.bytes = std::vector(bytes.begin(), bytes.end()); +std::unique_ptr CreateDataMessageWithLayerPublisherInfo( + const VmsLayerAndPublisher& layer_publisher, const std::string& vms_packet) { + auto result = createBaseVmsMessage(kMessageTypeSize + kLayerAndPublisherSize); + result->value.int32Values = hidl_vec{ + toInt(VmsMessageType::DATA), layer_publisher.layer.type, layer_publisher.layer.subtype, + layer_publisher.layer.version, layer_publisher.publisher_id}; + result->value.bytes = std::vector(vms_packet.begin(), vms_packet.end()); return result; } diff --git a/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp b/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp index 2b3efc70f0..8a434c85b8 100644 --- a/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp +++ b/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp @@ -139,12 +139,23 @@ TEST(VmsUtilsTest, subscriptionsMessage) { } TEST(VmsUtilsTest, dataMessage) { - std::string bytes = "aaa"; - auto message = createDataMessage(bytes); + const std::string bytes = "aaa"; + const VmsLayerAndPublisher layer_and_publisher(VmsLayer(2, 0, 1), 123); + auto message = CreateDataMessageWithLayerPublisherInfo(layer_and_publisher, bytes); ASSERT_NE(message, nullptr); EXPECT_TRUE(isValidVmsMessage(*message)); EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE)); - EXPECT_EQ(message->value.int32Values.size(), 0x1ul); + EXPECT_EQ(message->value.int32Values.size(), 0x5ul); + EXPECT_EQ(message->value.int32Values[0], toInt(VmsMessageType::DATA)); + + // Layer + EXPECT_EQ(message->value.int32Values[1], 2); + EXPECT_EQ(message->value.int32Values[2], 0); + EXPECT_EQ(message->value.int32Values[3], 1); + + // Publisher ID + EXPECT_EQ(message->value.int32Values[4], 123); + EXPECT_EQ(parseMessageType(*message), VmsMessageType::DATA); EXPECT_EQ(message->value.bytes.size(), bytes.size()); EXPECT_EQ(memcmp(message->value.bytes.data(), bytes.data(), bytes.size()), 0); @@ -164,8 +175,9 @@ TEST(VmsUtilsTest, invalidMessageType) { } TEST(VmsUtilsTest, parseDataMessage) { - std::string bytes = "aaa"; - auto message = createDataMessage(bytes); + const std::string bytes = "aaa"; + const VmsLayerAndPublisher layer_and_publisher(VmsLayer(1, 0, 1), 123); + auto message = CreateDataMessageWithLayerPublisherInfo(layer_and_publisher, bytes); auto data_str = parseData(*message); ASSERT_FALSE(data_str.empty()); EXPECT_EQ(data_str, bytes); From 88eaae691326cabe2dbcf778815b8801c4dddaa3 Mon Sep 17 00:00:00 2001 From: Hsin-Yi Chen Date: Tue, 18 Jun 2019 16:05:57 +0800 Subject: [PATCH 700/718] Move main function out of namespace Bug: 135473483 Test: adb shell /data/local/tmp/VtsHalPowerStatsV1_0TargetTest \ --list_registered_services Test: vts-tradefed run vts -m VtsHalPowerStatsV1_0Target Change-Id: I01084afbf48cff268288a8cce23328a2e4d1e4a0 --- .../VtsHalPowerStatsV1_0TargetTest.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/power/stats/1.0/vts/functional/VtsHalPowerStatsV1_0TargetTest.cpp b/power/stats/1.0/vts/functional/VtsHalPowerStatsV1_0TargetTest.cpp index 9f007e47f2..835a47b023 100644 --- a/power/stats/1.0/vts/functional/VtsHalPowerStatsV1_0TargetTest.cpp +++ b/power/stats/1.0/vts/functional/VtsHalPowerStatsV1_0TargetTest.cpp @@ -566,15 +566,16 @@ TEST_F(PowerStatsHidlTest, StreamEnergyData) { thread1.join(); } -int main(int argc, char** argv) { - ::testing::AddGlobalTestEnvironment(PowerStatsHidlEnv::Instance()); - ::testing::InitGoogleTest(&argc, argv); - PowerStatsHidlEnv::Instance()->init(&argc, argv); - int status = RUN_ALL_TESTS(); - LOG(INFO) << "Test result = " << status; - return status; -} } // namespace vts } // namespace stats } // namespace power } // namespace android + +int main(int argc, char** argv) { + ::testing::AddGlobalTestEnvironment(android::power::stats::vts::PowerStatsHidlEnv::Instance()); + ::testing::InitGoogleTest(&argc, argv); + android::power::stats::vts::PowerStatsHidlEnv::Instance()->init(&argc, argv); + int status = RUN_ALL_TESTS(); + LOG(INFO) << "Test result = " << status; + return status; +} From a2affa66367f69a985bf490066f78df02db4fc11 Mon Sep 17 00:00:00 2001 From: terrycrhuang Date: Tue, 18 Jun 2019 15:11:13 +0800 Subject: [PATCH 701/718] VTS: stop network scan once trigger network scan success For some vendors do not supports independent radios, if there is one manual search ongoing, another manual search on other SIM is not supported. So sending stop network scan request once trigger network scan completed to exclude this modem limitation. Bug: 135005200 Test: atest RadioHidlTest_v1_2#startNetworkScan Change-Id: Iacfd59ac2ad4d44e763ee03697c1f8f57162ce38 --- .../1.2/vts/functional/radio_hidl_hal_api.cpp | 5 ++++ .../vts/functional/radio_hidl_hal_test.cpp | 27 ++++++++++++++++++- .../functional/radio_hidl_hal_utils_v1_2.h | 5 +++- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp index 63d3187aed..f11f0d8e9e 100644 --- a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp +++ b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp @@ -60,6 +60,11 @@ TEST_F(RadioHidlTest_v1_2, startNetworkScan) { {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED, RadioError::OPERATION_NOT_ALLOWED})); } + + if (radioRsp_v1_2->rspInfo.error == RadioError::NONE) { + ALOGI("Stop Network Scan"); + stopNetworkScan(); + } } /* diff --git a/radio/1.2/vts/functional/radio_hidl_hal_test.cpp b/radio/1.2/vts/functional/radio_hidl_hal_test.cpp index b34f138bbd..bff7481bed 100644 --- a/radio/1.2/vts/functional/radio_hidl_hal_test.cpp +++ b/radio/1.2/vts/functional/radio_hidl_hal_test.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #include void RadioHidlTest_v1_2::SetUp() { @@ -84,4 +85,28 @@ void RadioHidlTest_v1_2::updateSimCardStatus() { serial = GetRandomSerialNumber(); radio_v1_2->getIccCardStatus(serial); EXPECT_EQ(std::cv_status::no_timeout, wait()); -} \ No newline at end of file +} + +void RadioHidlTest_v1_2::stopNetworkScan() { + sp<::android::hardware::radio::V1_1::IRadio> radio_v1_1; + + radio_v1_1 = ::testing::VtsHalHidlTargetTestBase::getService< + ::android::hardware::radio::V1_1::IRadio>( + RadioHidlEnvironment::Instance() + ->getServiceName<::android::hardware::radio::V1_1::IRadio>( + hidl_string(RADIO_SERVICE_NAME))); + if (radio_v1_1 == NULL) { + sleep(60); + radio_v1_1 = ::testing::VtsHalHidlTargetTestBase::getService< + ::android::hardware::radio::V1_1::IRadio>( + RadioHidlEnvironment::Instance() + ->getServiceName<::android::hardware::radio::V1_1::IRadio>( + hidl_string(RADIO_SERVICE_NAME))); + } + ASSERT_NE(nullptr, radio_v1_1.get()); + + serial = GetRandomSerialNumber(); + + radio_v1_1->stopNetworkScan(serial); + EXPECT_EQ(std::cv_status::no_timeout, wait()); +} diff --git a/radio/1.2/vts/functional/radio_hidl_hal_utils_v1_2.h b/radio/1.2/vts/functional/radio_hidl_hal_utils_v1_2.h index 2e65bfb78f..3f780e555a 100644 --- a/radio/1.2/vts/functional/radio_hidl_hal_utils_v1_2.h +++ b/radio/1.2/vts/functional/radio_hidl_hal_utils_v1_2.h @@ -622,7 +622,10 @@ class RadioHidlTest_v1_2 : public ::testing::VtsHalHidlTargetTestBase { /* Update Sim Card Status */ void updateSimCardStatus(); - public: + /* Stop Network Scan Command */ + void stopNetworkScan(); + + public: virtual void SetUp() override; /* Used as a mechanism to inform the test about data/event callback */ From 441842e38e0f1d3ce50cbfe1d675f2709c330796 Mon Sep 17 00:00:00 2001 From: Brian Duddie Date: Tue, 18 Jun 2019 19:00:26 -0700 Subject: [PATCH 702/718] Notify HAL when events are read As defined in the HAL specification, the client of the HAL (framework or VTS) needs to set the EVENTS_READ flag when it fetches samples out of the FMQ, to support blocking write mode. Bug: 135442877 Test: run VTS on a device supporting HAL 2.0 Change-Id: Ic7755e869b999b638086275e4e579a84600be314 --- sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp index 5f71654e97..0525bdc63b 100644 --- a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp +++ b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp @@ -139,6 +139,7 @@ void SensorsHidlEnvironmentV2_0::readEvents() { size_t eventsToRead = std::min(availableEvents, mEventBuffer.size()); if (eventsToRead > 0) { if (mEventQueue->read(mEventBuffer.data(), eventsToRead)) { + mEventQueueFlag->wake(asBaseType(EventQueueFlagBits::EVENTS_READ)); for (size_t i = 0; i < eventsToRead; i++) { addEvent(mEventBuffer[i]); } From aba88c6cbc3ef052e812ff012f8e220bcadb4119 Mon Sep 17 00:00:00 2001 From: Yin-Chia Yeh Date: Wed, 19 Jun 2019 11:51:48 -0700 Subject: [PATCH 703/718] Camera: fix unknown bufId issue It's legit to have bufId 0 in processCaptureResult with HAL buffer manager, but not for returnStreamBuffers. Test: the failed test can now pass Bug: 135565913 Change-Id: I05947bc159bb9ba00a670b98d4622f685b4ac760 --- .../functional/VtsHalCameraProviderV2_4TargetTest.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp index 200dd3f199..c94c825a57 100644 --- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp +++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp @@ -1233,7 +1233,14 @@ bool CameraHidlTest::DeviceCb::processCaptureResultLocked(const CaptureResult& r } if (mUseHalBufManager) { - returnStreamBuffers(results.outputBuffers); + // Don't return buffers of bufId 0 (empty buffer) + std::vector buffers; + for (const auto& sb : results.outputBuffers) { + if (sb.bufferId != 0) { + buffers.push_back(sb); + } + } + returnStreamBuffers(buffers); } return notify; } From dca469c1808d57bde3c7f4d4fc4596da029d8526 Mon Sep 17 00:00:00 2001 From: Valerie Hau Date: Thu, 13 Jun 2019 09:49:44 -0700 Subject: [PATCH 704/718] Adding support for different Mapper versions in IComposer VTS tests Bug: 135139498 Test: build, boot, VtsHalGraphicsComposerV2_<1,2,3>TargetTest, Change-Id: I05e2832c64d4c06eb4afd64c3323d7edbd19a5f4 Merged-In: I05e2832c64d4c06eb4afd64c3323d7edbd19a5f4 --- .../hal/include/composer-hal/2.1/Composer.h | 3 +- graphics/composer/2.1/utils/vts/Android.bp | 2 + .../composer/2.1/utils/vts/ComposerVts.cpp | 71 +++++++++ .../include/composer-vts/2.1/ComposerVts.h | 36 +++++ .../composer/2.1/vts/functional/Android.bp | 3 + .../VtsHalGraphicsComposerV2_1TargetTest.cpp | 20 +-- graphics/composer/2.2/utils/vts/Android.bp | 4 + .../composer/2.2/utils/vts/ComposerVts.cpp | 42 +++++ .../include/composer-vts/2.2/ComposerVts.h | 26 +++ .../composer/2.2/vts/functional/Android.bp | 3 + ...VtsHalGraphicsComposerV2_2ReadbackTest.cpp | 150 +++++++++--------- .../VtsHalGraphicsComposerV2_2TargetTest.cpp | 36 ++--- graphics/composer/2.3/utils/vts/Android.bp | 6 + .../composer/2.3/vts/functional/Android.bp | 4 + .../VtsHalGraphicsComposerV2_3TargetTest.cpp | 14 +- graphics/mapper/2.1/utils/vts/MapperVts.cpp | 13 +- .../vts/include/mapper-vts/2.1/MapperVts.h | 25 +-- graphics/mapper/3.0/utils/vts/MapperVts.cpp | 19 ++- .../vts/include/mapper-vts/3.0/MapperVts.h | 86 +++++----- 19 files changed, 377 insertions(+), 186 deletions(-) diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/Composer.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/Composer.h index 581dc96288..ad985dafa3 100644 --- a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/Composer.h +++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/Composer.h @@ -80,7 +80,8 @@ class ComposerImpl : public Interface { Return createClient(IComposer::createClient_cb hidl_cb) override { std::unique_lock lock(mClientMutex); - if (!waitForClientDestroyedLocked(lock)) { + bool destroyed = waitForClientDestroyedLocked(lock); + if (!destroyed) { hidl_cb(Error::NO_RESOURCES, nullptr); return Void(); } diff --git a/graphics/composer/2.1/utils/vts/Android.bp b/graphics/composer/2.1/utils/vts/Android.bp index 846cfdf355..fcb327f365 100644 --- a/graphics/composer/2.1/utils/vts/Android.bp +++ b/graphics/composer/2.1/utils/vts/Android.bp @@ -25,6 +25,8 @@ cc_library_static { static_libs: [ "VtsHalHidlTargetTestBase", "android.hardware.graphics.composer@2.1", + "android.hardware.graphics.mapper@2.0-vts", + "android.hardware.graphics.mapper@3.0-vts", ], header_libs: [ "android.hardware.graphics.composer@2.1-command-buffer", diff --git a/graphics/composer/2.1/utils/vts/ComposerVts.cpp b/graphics/composer/2.1/utils/vts/ComposerVts.cpp index 7ba67d45b5..c5d5823398 100644 --- a/graphics/composer/2.1/utils/vts/ComposerVts.cpp +++ b/graphics/composer/2.1/utils/vts/ComposerVts.cpp @@ -315,6 +315,77 @@ void ComposerClient::execute(TestCommandReader* reader, CommandWriterBase* write writer->reset(); } +Gralloc::Gralloc() { + [this] { + ASSERT_NO_FATAL_FAILURE(mGralloc3 = std::make_shared("default", "default", + /*errOnFailure=*/false)); + if (mGralloc3->getAllocator() == nullptr || mGralloc3->getMapper() == nullptr) { + mGralloc3 = nullptr; + ASSERT_NO_FATAL_FAILURE(mGralloc2 = std::make_shared()); + } + }(); +} + +const native_handle_t* Gralloc::allocate(uint32_t width, uint32_t height, uint32_t layerCount, + PixelFormat format, uint64_t usage, bool import, + uint32_t* outStride) { + if (mGralloc3) { + IMapper3::BufferDescriptorInfo info{}; + info.width = width; + info.height = height; + info.layerCount = layerCount; + info.format = static_cast(format); + info.usage = usage; + return mGralloc3->allocate(info, import, outStride); + } else { + IMapper2::BufferDescriptorInfo info{}; + info.width = width; + info.height = height; + info.layerCount = layerCount; + info.format = format; + info.usage = usage; + return mGralloc2->allocate(info, import, outStride); + } +} + +void* Gralloc::lock(const native_handle_t* bufferHandle, uint64_t cpuUsage, + const AccessRegion& accessRegionRect, int acquireFence) { + if (mGralloc3) { + IMapper3::Rect accessRegion; + accessRegion.left = accessRegionRect.left; + accessRegion.top = accessRegionRect.top; + accessRegion.width = accessRegionRect.width; + accessRegion.height = accessRegionRect.height; + int32_t bytesPerPixel; + int32_t bytesPerStride; + return mGralloc3->lock(bufferHandle, cpuUsage, accessRegion, acquireFence, &bytesPerPixel, + &bytesPerStride); + } else { + IMapper2::Rect accessRegion; + accessRegion.left = accessRegionRect.left; + accessRegion.top = accessRegionRect.top; + accessRegion.width = accessRegionRect.width; + accessRegion.height = accessRegionRect.height; + return mGralloc2->lock(bufferHandle, cpuUsage, accessRegion, acquireFence); + } +} + +int Gralloc::unlock(const native_handle_t* bufferHandle) { + if (mGralloc3) { + return mGralloc3->unlock(bufferHandle); + } else { + return mGralloc2->unlock(bufferHandle); + } +} + +void Gralloc::freeBuffer(const native_handle_t* bufferHandle) { + if (mGralloc3) { + mGralloc3->freeBuffer(bufferHandle); + } else { + mGralloc2->freeBuffer(bufferHandle); + } +} + } // namespace vts } // namespace V2_1 } // namespace composer diff --git a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h index c97be76d9a..7811048270 100644 --- a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h +++ b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h @@ -25,8 +25,12 @@ #include #include #include +#include +#include #include +#include "gtest/gtest.h" + namespace android { namespace hardware { namespace graphics { @@ -38,6 +42,10 @@ using android::hardware::graphics::common::V1_0::ColorMode; using android::hardware::graphics::common::V1_0::Dataspace; using android::hardware::graphics::common::V1_0::Hdr; using android::hardware::graphics::common::V1_0::PixelFormat; +using IMapper2 = android::hardware::graphics::mapper::V2_0::IMapper; +using IMapper3 = android::hardware::graphics::mapper::V3_0::IMapper; +using Gralloc2 = android::hardware::graphics::mapper::V2_0::vts::Gralloc; +using Gralloc3 = android::hardware::graphics::mapper::V3_0::vts::Gralloc; class ComposerClient; @@ -119,6 +127,34 @@ class ComposerClient { const sp mClient; }; +class AccessRegion { + public: + int32_t left; + int32_t top; + int32_t width; + int32_t height; +}; + +class Gralloc { + public: + explicit Gralloc(); + + const native_handle_t* allocate(uint32_t width, uint32_t height, uint32_t layerCount, + PixelFormat format, uint64_t usage, bool import = true, + uint32_t* outStride = nullptr); + + void* lock(const native_handle_t* bufferHandle, uint64_t cpuUsage, + const AccessRegion& accessRegionRect, int acquireFence); + + int unlock(const native_handle_t* bufferHandle); + + void freeBuffer(const native_handle_t* bufferHandle); + + protected: + std::shared_ptr mGralloc2 = nullptr; + std::shared_ptr mGralloc3 = nullptr; +}; + } // namespace vts } // namespace V2_1 } // namespace composer diff --git a/graphics/composer/2.1/vts/functional/Android.bp b/graphics/composer/2.1/vts/functional/Android.bp index c98cc0deb8..d54da60f6d 100644 --- a/graphics/composer/2.1/vts/functional/Android.bp +++ b/graphics/composer/2.1/vts/functional/Android.bp @@ -26,10 +26,13 @@ cc_test { ], static_libs: [ "android.hardware.graphics.allocator@2.0", + "android.hardware.graphics.allocator@3.0", "android.hardware.graphics.composer@2.1", "android.hardware.graphics.composer@2.1-vts", "android.hardware.graphics.mapper@2.0", "android.hardware.graphics.mapper@2.0-vts", + "android.hardware.graphics.mapper@3.0", + "android.hardware.graphics.mapper@3.0-vts", ], header_libs: [ "android.hardware.graphics.composer@2.1-command-buffer", diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp index 3c408b7d7b..30b96949dc 100644 --- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp +++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -47,8 +48,6 @@ using android::hardware::graphics::common::V1_0::ColorTransform; using android::hardware::graphics::common::V1_0::Dataspace; using android::hardware::graphics::common::V1_0::PixelFormat; using android::hardware::graphics::common::V1_0::Transform; -using android::hardware::graphics::mapper::V2_0::IMapper; -using android::hardware::graphics::mapper::V2_0::vts::Gralloc; using GrallocError = android::hardware::graphics::mapper::V2_0::Error; // Test environment for graphics.composer @@ -669,7 +668,6 @@ class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest { ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::SetUp()); ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique()); - Config activeConfig = mComposerClient->getActiveConfig(mPrimaryDisplay); mDisplayWidth = mComposerClient->getDisplayAttribute(mPrimaryDisplay, activeConfig, IComposerClient::Attribute::WIDTH); @@ -685,16 +683,10 @@ class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest { } const native_handle_t* allocate() { - IMapper::BufferDescriptorInfo info{}; - info.width = mDisplayWidth; - info.height = mDisplayHeight; - info.layerCount = 1; - info.format = PixelFormat::RGBA_8888; - info.usage = - static_cast(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN | - BufferUsage::COMPOSER_OVERLAY); - - return mGralloc->allocate(info); + uint64_t usage = + static_cast(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN | + BufferUsage::COMPOSER_OVERLAY); + return mGralloc->allocate(mDisplayWidth, mDisplayHeight, 1, PixelFormat::RGBA_8888, usage); } void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); } @@ -705,7 +697,7 @@ class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest { int32_t mDisplayHeight; private: - std::unique_ptr mGralloc; + std::unique_ptr mGralloc; }; /** diff --git a/graphics/composer/2.2/utils/vts/Android.bp b/graphics/composer/2.2/utils/vts/Android.bp index c6b524d234..dd979cb08c 100644 --- a/graphics/composer/2.2/utils/vts/Android.bp +++ b/graphics/composer/2.2/utils/vts/Android.bp @@ -25,6 +25,10 @@ cc_library_static { "android.hardware.graphics.composer@2.1", "android.hardware.graphics.composer@2.1-vts", "android.hardware.graphics.composer@2.2", + "android.hardware.graphics.mapper@2.1", + "android.hardware.graphics.mapper@2.1-vts", + "android.hardware.graphics.mapper@3.0", + "android.hardware.graphics.mapper@3.0-vts", ], export_static_lib_headers: [ "android.hardware.graphics.composer@2.1-vts", diff --git a/graphics/composer/2.2/utils/vts/ComposerVts.cpp b/graphics/composer/2.2/utils/vts/ComposerVts.cpp index da994606bb..cd6772a485 100644 --- a/graphics/composer/2.2/utils/vts/ComposerVts.cpp +++ b/graphics/composer/2.2/utils/vts/ComposerVts.cpp @@ -180,6 +180,48 @@ std::array ComposerClient::getDataspaceSaturationMatrix(Dataspace dat return matrix; } +Gralloc::Gralloc() { + [this] { + ALOGD("Attempting to initialize gralloc3"); + ASSERT_NO_FATAL_FAILURE(mGralloc3 = std::make_shared("default", "default", + /*errOnFailure=*/false)); + if (mGralloc3->getMapper() == nullptr || mGralloc3->getAllocator() == nullptr) { + mGralloc3 = nullptr; + ALOGD("Failed to create gralloc3, initializing gralloc2_1"); + mGralloc2_1 = std::make_shared(/*errOnFailure*/ false); + if (!mGralloc2_1->getMapper()) { + mGralloc2_1 = nullptr; + ALOGD("Failed to create gralloc2_1, initializing gralloc2"); + ASSERT_NO_FATAL_FAILURE(mGralloc2 = std::make_shared()); + } + } + }(); +} + +bool Gralloc::validateBufferSize(const native_handle_t* bufferHandle, uint32_t width, + uint32_t height, uint32_t layerCount, PixelFormat format, + uint64_t usage, uint32_t stride) { + if (mGralloc3) { + IMapper3::BufferDescriptorInfo info{}; + info.width = width; + info.height = height; + info.layerCount = layerCount; + info.format = static_cast(format); + info.usage = usage; + return mGralloc3->validateBufferSize(bufferHandle, info, stride); + } else if (mGralloc2_1) { + IMapper2_1::BufferDescriptorInfo info{}; + info.width = width; + info.height = height; + info.layerCount = layerCount; + info.format = static_cast(format); + info.usage = usage; + return mGralloc2_1->validateBufferSize(bufferHandle, info, stride); + } else { + return true; + } +} + } // namespace vts } // namespace V2_2 } // namespace composer diff --git a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h index 263302124f..8fa9b7b3fe 100644 --- a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h +++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h @@ -27,6 +27,7 @@ #include #include #include +#include #include namespace android { @@ -41,6 +42,11 @@ using common::V1_1::ColorMode; using common::V1_1::Dataspace; using common::V1_1::PixelFormat; using common::V1_1::RenderIntent; +using IMapper2_1 = android::hardware::graphics::mapper::V2_1::IMapper; +using IMapper3 = android::hardware::graphics::mapper::V3_0::IMapper; +using Gralloc2 = android::hardware::graphics::mapper::V2_0::vts::Gralloc; +using Gralloc2_1 = android::hardware::graphics::mapper::V2_1::vts::Gralloc; +using Gralloc3 = android::hardware::graphics::mapper::V3_0::vts::Gralloc; class ComposerClient; @@ -84,6 +90,26 @@ class ComposerClient : public V2_1::vts::ComposerClient { const sp mClient; }; +class Gralloc : public V2_1::vts::Gralloc { + public: + Gralloc(); + const native_handle_t* allocate(uint32_t width, uint32_t height, uint32_t layerCount, + PixelFormat format, uint64_t usage, bool import = true, + uint32_t* outStride = nullptr) { + return V2_1::vts::Gralloc::allocate( + width, height, layerCount, + static_cast(format), usage, + import, outStride); + } + + bool validateBufferSize(const native_handle_t* bufferHandle, uint32_t width, uint32_t height, + uint32_t layerCount, PixelFormat format, uint64_t usage, + uint32_t stride); + + protected: + std::shared_ptr mGralloc2_1 = nullptr; +}; + } // namespace vts } // namespace V2_2 } // namespace composer diff --git a/graphics/composer/2.2/vts/functional/Android.bp b/graphics/composer/2.2/vts/functional/Android.bp index 4cb0bdf078..9f7e1cd22e 100644 --- a/graphics/composer/2.2/vts/functional/Android.bp +++ b/graphics/composer/2.2/vts/functional/Android.bp @@ -31,6 +31,7 @@ cc_test { ], static_libs: [ "android.hardware.graphics.allocator@2.0", + "android.hardware.graphics.allocator@3.0", "android.hardware.graphics.common@1.1", "android.hardware.graphics.composer@2.1", "android.hardware.graphics.composer@2.1-vts", @@ -40,6 +41,8 @@ cc_test { "android.hardware.graphics.mapper@2.0-vts", "android.hardware.graphics.mapper@2.1", "android.hardware.graphics.mapper@2.1-vts", + "android.hardware.graphics.mapper@3.0", + "android.hardware.graphics.mapper@3.0-vts", ], header_libs: [ "android.hardware.graphics.composer@2.1-command-buffer", diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp index da8858e037..0648b3456a 100644 --- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp +++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp @@ -39,9 +39,9 @@ using common::V1_1::BufferUsage; using common::V1_1::Dataspace; using common::V1_1::PixelFormat; using mapper::V2_1::IMapper; -using mapper::V2_1::vts::Gralloc; using V2_1::Display; using V2_1::Layer; +using V2_1::vts::AccessRegion; using V2_1::vts::TestCommandReader; static const IComposerClient::Color BLACK = {0, 0, 0, 0xff}; @@ -296,14 +296,13 @@ class ReadbackBuffer { mComposerClient = client; mGralloc = gralloc; - mPixelFormat = pixelFormat; + mFormat = pixelFormat; mDataspace = dataspace; - mInfo.width = width; - mInfo.height = height; - mInfo.layerCount = 1; - mInfo.format = mPixelFormat; - mInfo.usage = static_cast(BufferUsage::CPU_READ_OFTEN | BufferUsage::GPU_TEXTURE); + mWidth = width; + mHeight = height; + mLayerCount = 1; + mUsage = static_cast(BufferUsage::CPU_READ_OFTEN | BufferUsage::GPU_TEXTURE); mAccessRegion.top = 0; mAccessRegion.left = 0; @@ -322,8 +321,10 @@ class ReadbackBuffer { mGralloc->freeBuffer(mBufferHandle); mBufferHandle = nullptr; } - mBufferHandle = mGralloc->allocate(mInfo, /*import*/ true, &mStride); - ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle, mInfo, mStride)); + mBufferHandle = mGralloc->allocate(mWidth, mHeight, mLayerCount, mFormat, mUsage, + /*import*/ true, &mStride); + ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle, mWidth, mHeight, mLayerCount, + mFormat, mUsage, mStride)); ASSERT_NO_FATAL_FAILURE(mComposerClient->setReadbackBuffer(mDisplay, mBufferHandle, -1)); } @@ -332,13 +333,13 @@ class ReadbackBuffer { int32_t fenceHandle; ASSERT_NO_FATAL_FAILURE(mComposerClient->getReadbackBufferFence(mDisplay, &fenceHandle)); - void* bufData = mGralloc->lock(mBufferHandle, mInfo.usage, mAccessRegion, fenceHandle); - ASSERT_TRUE(mPixelFormat == PixelFormat::RGB_888 || mPixelFormat == PixelFormat::RGBA_8888); - int32_t bytesPerPixel = GraphicsComposerReadbackTest::GetBytesPerPixel(mPixelFormat); + void* bufData = mGralloc->lock(mBufferHandle, mUsage, mAccessRegion, fenceHandle); + ASSERT_TRUE(mFormat == PixelFormat::RGB_888 || mFormat == PixelFormat::RGBA_8888); + int32_t bytesPerPixel = GraphicsComposerReadbackTest::GetBytesPerPixel(mFormat); ASSERT_NE(-1, bytesPerPixel); - for (int row = 0; row < mInfo.height; row++) { - for (int col = 0; col < mInfo.width; col++) { - int pixel = row * mInfo.width + col; + for (int row = 0; row < mHeight; row++) { + for (int col = 0; col < mWidth; col++) { + int pixel = row * mWidth + col; int offset = (row * mStride + col) * bytesPerPixel; uint8_t* pixelColor = (uint8_t*)bufData + offset; @@ -354,12 +355,16 @@ class ReadbackBuffer { } } - protected: - IMapper::BufferDescriptorInfo mInfo; - IMapper::Rect mAccessRegion; + uint32_t mWidth; + uint32_t mHeight; + uint32_t mLayerCount; + PixelFormat mFormat; + uint64_t mUsage; + AccessRegion mAccessRegion; + + protected: uint32_t mStride; const native_handle_t* mBufferHandle = nullptr; - PixelFormat mPixelFormat; Dataspace mDataspace; Display mDisplay; std::shared_ptr mGralloc; @@ -392,13 +397,12 @@ class TestBufferLayer : public TestLayer { : TestLayer{client, display} { mGralloc = gralloc; mComposition = composition; - mInfo.width = width; - mInfo.height = height; - mInfo.layerCount = 1; - mInfo.format = format; - mInfo.usage = - static_cast(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_OVERLAY); + mWidth = width; + mHeight = height; + mLayerCount = 1; + mFormat = format; + mUsage = static_cast(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY); mAccessRegion.top = 0; mAccessRegion.left = 0; @@ -423,9 +427,9 @@ class TestBufferLayer : public TestLayer { } void fillBuffer(std::vector expectedColors) { - void* bufData = mGralloc->lock(mBufferHandle, mInfo.usage, mAccessRegion, -1); + void* bufData = mGralloc->lock(mBufferHandle, mUsage, mAccessRegion, -1); ASSERT_NO_FATAL_FAILURE(GraphicsComposerReadbackTest::fillBuffer( - mInfo.width, mInfo.height, mStride, bufData, mInfo.format, expectedColors)); + mWidth, mHeight, mStride, bufData, mFormat, expectedColors)); mFillFence = mGralloc->unlock(mBufferHandle); if (mFillFence != -1) { sync_wait(mFillFence, -1); @@ -437,10 +441,12 @@ class TestBufferLayer : public TestLayer { mGralloc->freeBuffer(mBufferHandle); mBufferHandle = nullptr; } - mBufferHandle = mGralloc->allocate(mInfo, /*import*/ true, &mStride); + mBufferHandle = mGralloc->allocate(mWidth, mHeight, mLayerCount, mFormat, mUsage, + /*import*/ true, &mStride); ASSERT_NE(nullptr, mBufferHandle); ASSERT_NO_FATAL_FAILURE(fillBuffer(colors)); - ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle, mInfo, mStride)); + ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle, mWidth, mHeight, mLayerCount, + mFormat, mUsage, mStride)); } void setToClientComposition(const std::shared_ptr& writer) { @@ -448,11 +454,15 @@ class TestBufferLayer : public TestLayer { writer->setLayerCompositionType(IComposerClient::Composition::CLIENT); } - IMapper::BufferDescriptorInfo mInfo; - IMapper::Rect mAccessRegion; + AccessRegion mAccessRegion; uint32_t mStride; + uint32_t mWidth; + uint32_t mHeight; + uint32_t mLayerCount; + PixelFormat mFormat; - protected: + protected: + uint64_t mUsage; IComposerClient::Composition mComposition; std::shared_ptr mGralloc; int32_t mFillFence; @@ -568,14 +578,11 @@ TEST_F(GraphicsComposerReadbackTest, SetLayerBufferNoEffect) { layer->write(mWriter); // This following buffer call should have no effect - IMapper::BufferDescriptorInfo bufferInfo{}; - bufferInfo.width = mDisplayWidth; - bufferInfo.height = mDisplayHeight; - bufferInfo.layerCount = 1; - bufferInfo.format = PixelFormat::RGBA_8888; - bufferInfo.usage = - static_cast(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN); - const native_handle_t* bufferHandle = mGralloc->allocate(bufferInfo); + PixelFormat format = PixelFormat::RGBA_8888; + uint64_t usage = + static_cast(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN); + const native_handle_t* bufferHandle = + mGralloc->allocate(mDisplayWidth, mDisplayHeight, 1, format, usage); mWriter->setLayerBuffer(0, bufferHandle, -1); // expected color for each pixel @@ -642,23 +649,20 @@ TEST_F(GraphicsComposerReadbackTest, ClientComposition) { // create client target buffer uint32_t clientStride; - IMapper::BufferDescriptorInfo clientInfo; - clientInfo.width = layer->mInfo.width; - clientInfo.height = layer->mInfo.height; - clientInfo.layerCount = layer->mInfo.layerCount; - clientInfo.format = PixelFormat::RGBA_8888; - clientInfo.usage = - static_cast(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_CLIENT_TARGET); + PixelFormat clientFormat = PixelFormat::RGBA_8888; + uint64_t clientUsage = + static_cast(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_CLIENT_TARGET); const native_handle_t* clientBufferHandle = - mGralloc->allocate(clientInfo, /*import*/ true, &clientStride); + mGralloc->allocate(layer->mWidth, layer->mHeight, layer->mLayerCount, clientFormat, + clientUsage, /*import*/ true, &clientStride); ASSERT_NE(nullptr, clientBufferHandle); void* clientBufData = - mGralloc->lock(clientBufferHandle, clientInfo.usage, layer->mAccessRegion, -1); + mGralloc->lock(clientBufferHandle, clientUsage, layer->mAccessRegion, -1); - ASSERT_NO_FATAL_FAILURE(fillBuffer(clientInfo.width, clientInfo.height, clientStride, - clientBufData, clientInfo.format, expectedColors)); + ASSERT_NO_FATAL_FAILURE(fillBuffer(layer->mWidth, layer->mHeight, clientStride, + clientBufData, clientFormat, expectedColors)); int clientFence = mGralloc->unlock(clientBufferHandle); if (clientFence != -1) { sync_wait(clientFence, -1); @@ -706,14 +710,13 @@ TEST_F(GraphicsComposerReadbackTest, DeviceAndClientComposition) { auto deviceLayer = std::make_shared(mComposerClient, mGralloc, mPrimaryDisplay, mDisplayWidth, mDisplayHeight / 2, PixelFormat::RGBA_8888); - std::vector deviceColors(deviceLayer->mInfo.width * - deviceLayer->mInfo.height); - fillColorsArea(deviceColors, deviceLayer->mInfo.width, - {0, 0, static_cast(deviceLayer->mInfo.width), - static_cast(deviceLayer->mInfo.height)}, + std::vector deviceColors(deviceLayer->mWidth * deviceLayer->mHeight); + fillColorsArea(deviceColors, deviceLayer->mWidth, + {0, 0, static_cast(deviceLayer->mWidth), + static_cast(deviceLayer->mHeight)}, GREEN); - deviceLayer->setDisplayFrame({0, 0, static_cast(deviceLayer->mInfo.width), - static_cast(deviceLayer->mInfo.height)}); + deviceLayer->setDisplayFrame({0, 0, static_cast(deviceLayer->mWidth), + static_cast(deviceLayer->mHeight)}); deviceLayer->setZOrder(10); ASSERT_NO_FATAL_FAILURE(deviceLayer->setBuffer(deviceColors)); deviceLayer->write(mWriter); @@ -728,30 +731,25 @@ TEST_F(GraphicsComposerReadbackTest, DeviceAndClientComposition) { execute(); ASSERT_EQ(0, mReader->mErrors.size()); - IMapper::BufferDescriptorInfo clientInfo; - clientInfo.width = mDisplayWidth; - clientInfo.height = mDisplayHeight; - clientInfo.layerCount = 1; - clientInfo.format = PixelFormat::RGBA_8888; - clientInfo.usage = - static_cast(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_CLIENT_TARGET); - + uint64_t clientUsage = + static_cast(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_CLIENT_TARGET); uint32_t clientStride; const native_handle_t* clientBufferHandle = - mGralloc->allocate(clientInfo, /*import*/ true, &clientStride); + mGralloc->allocate(mDisplayWidth, mDisplayHeight, 1, PixelFormat::RGBA_8888, + clientUsage, /*import*/ true, &clientStride); ASSERT_NE(nullptr, clientBufferHandle); - IMapper::Rect clientAccessRegion; + AccessRegion clientAccessRegion; clientAccessRegion.left = 0; clientAccessRegion.top = 0; clientAccessRegion.width = mDisplayWidth; clientAccessRegion.height = mDisplayHeight; - void* clientData = mGralloc->lock(clientBufferHandle, clientInfo.usage, clientAccessRegion, -1); - std::vector clientColors(clientInfo.width * clientInfo.height); - fillColorsArea(clientColors, clientInfo.width, clientFrame, RED); - ASSERT_NO_FATAL_FAILURE(fillBuffer(clientInfo.width, clientInfo.height, clientStride, - clientData, clientInfo.format, clientColors)); + void* clientData = mGralloc->lock(clientBufferHandle, clientUsage, clientAccessRegion, -1); + std::vector clientColors(mDisplayWidth * mDisplayHeight); + fillColorsArea(clientColors, mDisplayWidth, clientFrame, RED); + ASSERT_NO_FATAL_FAILURE(fillBuffer(mDisplayWidth, mDisplayHeight, clientStride, clientData, + PixelFormat::RGBA_8888, clientColors)); int clientFence = mGralloc->unlock(clientBufferHandle); if (clientFence != -1) { sync_wait(clientFence, -1); diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp index 9c80f4da5e..51832f9f4c 100644 --- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp +++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp @@ -40,7 +40,6 @@ using common::V1_1::Dataspace; using common::V1_1::PixelFormat; using common::V1_1::RenderIntent; using mapper::V2_0::IMapper; -using mapper::V2_0::vts::Gralloc; // Test environment for graphics.composer class GraphicsComposerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { @@ -171,15 +170,10 @@ class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest { } const native_handle_t* allocate() { - IMapper::BufferDescriptorInfo info{}; - info.width = 64; - info.height = 64; - info.layerCount = 1; - info.format = static_cast(PixelFormat::RGBA_8888); - info.usage = - static_cast(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN); - - return mGralloc->allocate(info); + uint64_t usage = + static_cast(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN); + return mGralloc->allocate(/*width*/ 64, /*height*/ 64, /*layerCount*/ 1, + PixelFormat::RGBA_8888, usage); } void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); } @@ -456,18 +450,15 @@ TEST_F(GraphicsComposerHidlTest, SetReadbackBuffer) { return; } - IMapper::BufferDescriptorInfo info{}; - info.width = mDisplayWidth; - info.height = mDisplayHeight; - info.layerCount = 1; - info.format = static_cast(mReadbackPixelFormat); // BufferUsage::COMPOSER_OUTPUT is missing - info.usage = static_cast(BufferUsage::COMPOSER_OVERLAY | BufferUsage::CPU_READ_OFTEN); + uint64_t usage = + static_cast(BufferUsage::COMPOSER_OVERLAY | BufferUsage::CPU_READ_OFTEN); std::unique_ptr gralloc; const native_handle_t* buffer; ASSERT_NO_FATAL_FAILURE(gralloc = std::make_unique()); - ASSERT_NO_FATAL_FAILURE(buffer = gralloc->allocate(info)); + ASSERT_NO_FATAL_FAILURE(buffer = gralloc->allocate(mDisplayWidth, mDisplayHeight, 1, + mReadbackPixelFormat, usage)); mComposerClient->setReadbackBuffer(mPrimaryDisplay, buffer, -1); } @@ -483,17 +474,14 @@ TEST_F(GraphicsComposerHidlTest, SetReadbackBufferBadDisplay) { return; } - IMapper::BufferDescriptorInfo info{}; - info.width = mDisplayWidth; - info.height = mDisplayHeight; - info.layerCount = 1; - info.format = static_cast(mReadbackPixelFormat); - info.usage = static_cast(BufferUsage::COMPOSER_OVERLAY | BufferUsage::CPU_READ_OFTEN); + uint64_t usage = + static_cast(BufferUsage::COMPOSER_OVERLAY | BufferUsage::CPU_READ_OFTEN); std::unique_ptr gralloc; const native_handle_t* buffer; ASSERT_NO_FATAL_FAILURE(gralloc = std::make_unique()); - ASSERT_NO_FATAL_FAILURE(buffer = gralloc->allocate(info)); + ASSERT_NO_FATAL_FAILURE(buffer = gralloc->allocate(mDisplayWidth, mDisplayHeight, 1, + mReadbackPixelFormat, usage)); Error error = mComposerClient->getRaw()->setReadbackBuffer(mInvalidDisplayId, buffer, nullptr); ASSERT_EQ(Error::BAD_DISPLAY, error); diff --git a/graphics/composer/2.3/utils/vts/Android.bp b/graphics/composer/2.3/utils/vts/Android.bp index 19438cbe26..2fe6cd6a40 100644 --- a/graphics/composer/2.3/utils/vts/Android.bp +++ b/graphics/composer/2.3/utils/vts/Android.bp @@ -27,6 +27,12 @@ cc_library_static { "android.hardware.graphics.composer@2.2", "android.hardware.graphics.composer@2.2-vts", "android.hardware.graphics.composer@2.3", + "android.hardware.graphics.mapper@2.0", + "android.hardware.graphics.mapper@2.0-vts", + "android.hardware.graphics.mapper@2.1", + "android.hardware.graphics.mapper@2.1-vts", + "android.hardware.graphics.mapper@3.0", + "android.hardware.graphics.mapper@3.0-vts", ], header_libs: [ "android.hardware.graphics.composer@2.1-command-buffer", diff --git a/graphics/composer/2.3/vts/functional/Android.bp b/graphics/composer/2.3/vts/functional/Android.bp index ce675ee4ef..2766638754 100644 --- a/graphics/composer/2.3/vts/functional/Android.bp +++ b/graphics/composer/2.3/vts/functional/Android.bp @@ -28,6 +28,7 @@ cc_test { ], static_libs: [ "android.hardware.graphics.allocator@2.0", + "android.hardware.graphics.allocator@3.0", "android.hardware.graphics.composer@2.1", "android.hardware.graphics.composer@2.1-vts", "android.hardware.graphics.composer@2.2", @@ -37,6 +38,9 @@ cc_test { "android.hardware.graphics.mapper@2.0", "android.hardware.graphics.mapper@2.0-vts", "android.hardware.graphics.mapper@2.1", + "android.hardware.graphics.mapper@2.1-vts", + "android.hardware.graphics.mapper@3.0", + "android.hardware.graphics.mapper@3.0-vts", ], header_libs: [ "android.hardware.graphics.composer@2.1-command-buffer", diff --git a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp index d51c30a307..dafe58786b 100644 --- a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp +++ b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp @@ -41,7 +41,7 @@ using common::V1_2::ColorMode; using common::V1_2::Dataspace; using common::V1_2::PixelFormat; using mapper::V2_0::IMapper; -using mapper::V2_0::vts::Gralloc; +using V2_2::vts::Gralloc; // Test environment for graphics.composer class GraphicsComposerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { @@ -156,15 +156,9 @@ class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest { } const native_handle_t* allocate() { - IMapper::BufferDescriptorInfo info{}; - info.width = 64; - info.height = 64; - info.layerCount = 1; - info.format = static_cast(PixelFormat::RGBA_8888); - info.usage = - static_cast(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN); - - return mGralloc->allocate(info); + return mGralloc->allocate( + 64, 64, 1, static_cast(PixelFormat::RGBA_8888), + static_cast(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN)); } void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); } diff --git a/graphics/mapper/2.1/utils/vts/MapperVts.cpp b/graphics/mapper/2.1/utils/vts/MapperVts.cpp index 078068e306..36f9cbbeb2 100644 --- a/graphics/mapper/2.1/utils/vts/MapperVts.cpp +++ b/graphics/mapper/2.1/utils/vts/MapperVts.cpp @@ -43,24 +43,25 @@ static_assert(sizeof(OldBufferDescriptorInfo) == sizeof(IMapper::BufferDescripto offsetof(IMapper::BufferDescriptorInfo, usage), ""); -Gralloc::Gralloc() : V2_0::vts::Gralloc() { +Gralloc::Gralloc(bool errOnFailure) : V2_0::vts::Gralloc() { if (::testing::Test::HasFatalFailure()) { return; } - init(); + init(errOnFailure); } -Gralloc::Gralloc(const std::string& allocatorServiceName, const std::string& mapperServiceName) +Gralloc::Gralloc(const std::string& allocatorServiceName, const std::string& mapperServiceName, + bool errOnFailure) : V2_0::vts::Gralloc(allocatorServiceName, mapperServiceName) { if (::testing::Test::HasFatalFailure()) { return; } - init(); + init(errOnFailure); } -void Gralloc::init() { +void Gralloc::init(bool errOnFailure) { mMapperV2_1 = IMapper::castFrom(V2_0::vts::Gralloc::getMapper()); - ASSERT_NE(nullptr, mMapperV2_1.get()) << "failed to get mapper 2.1 service"; + if (errOnFailure) ASSERT_NE(nullptr, mMapperV2_1.get()) << "failed to get mapper 2.1 service"; } sp Gralloc::getMapper() const { diff --git a/graphics/mapper/2.1/utils/vts/include/mapper-vts/2.1/MapperVts.h b/graphics/mapper/2.1/utils/vts/include/mapper-vts/2.1/MapperVts.h index 423d4b3c0d..bc683bb355 100644 --- a/graphics/mapper/2.1/utils/vts/include/mapper-vts/2.1/MapperVts.h +++ b/graphics/mapper/2.1/utils/vts/include/mapper-vts/2.1/MapperVts.h @@ -32,25 +32,26 @@ using V2_0::BufferDescriptor; // A wrapper to IAllocator and IMapper. class Gralloc : public V2_0::vts::Gralloc { public: - Gralloc(); - Gralloc(const std::string& allocatorServiceName, const std::string& mapperServiceName); + Gralloc(bool errOnFailure = true); + Gralloc(const std::string& allocatorServiceName, const std::string& mapperServiceName, + bool errOnFailure = true); - sp getMapper() const; + sp getMapper() const; - bool validateBufferSize(const native_handle_t* bufferHandle, - const IMapper::BufferDescriptorInfo& descriptorInfo, uint32_t stride); - void getTransportSize(const native_handle_t* bufferHandle, uint32_t* outNumFds, - uint32_t* outNumInts); + bool validateBufferSize(const native_handle_t* bufferHandle, + const IMapper::BufferDescriptorInfo& descriptorInfo, uint32_t stride); + void getTransportSize(const native_handle_t* bufferHandle, uint32_t* outNumFds, + uint32_t* outNumInts); - BufferDescriptor createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo); + BufferDescriptor createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo); - const native_handle_t* allocate(const IMapper::BufferDescriptorInfo& descriptorInfo, - bool import = true, uint32_t* outStride = nullptr); + const native_handle_t* allocate(const IMapper::BufferDescriptorInfo& descriptorInfo, + bool import = true, uint32_t* outStride = nullptr); protected: - void init(); + void init(bool errOnFailure = true); - sp mMapperV2_1; + sp mMapperV2_1; }; } // namespace vts diff --git a/graphics/mapper/3.0/utils/vts/MapperVts.cpp b/graphics/mapper/3.0/utils/vts/MapperVts.cpp index f2b7594b3f..c94e8db065 100644 --- a/graphics/mapper/3.0/utils/vts/MapperVts.cpp +++ b/graphics/mapper/3.0/utils/vts/MapperVts.cpp @@ -25,8 +25,13 @@ namespace mapper { namespace V3_0 { namespace vts { -Gralloc::Gralloc(const std::string& allocatorServiceName, const std::string& mapperServiceName) { - init(allocatorServiceName, mapperServiceName); +Gralloc::Gralloc(const std::string& allocatorServiceName, const std::string& mapperServiceName, + bool errOnFailure) { + if (errOnFailure) { + init(allocatorServiceName, mapperServiceName); + } else { + initNoErr(allocatorServiceName, mapperServiceName); + } } void Gralloc::init(const std::string& allocatorServiceName, const std::string& mapperServiceName) { @@ -38,6 +43,16 @@ void Gralloc::init(const std::string& allocatorServiceName, const std::string& m ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode"; } +void Gralloc::initNoErr(const std::string& allocatorServiceName, + const std::string& mapperServiceName) { + mAllocator = ::testing::VtsHalHidlTargetTestBase::getService(allocatorServiceName); + + mMapper = ::testing::VtsHalHidlTargetTestBase::getService(mapperServiceName); + if (mMapper.get()) { + ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode"; + } +} + Gralloc::~Gralloc() { for (auto bufferHandle : mClonedBuffers) { auto buffer = const_cast(bufferHandle); diff --git a/graphics/mapper/3.0/utils/vts/include/mapper-vts/3.0/MapperVts.h b/graphics/mapper/3.0/utils/vts/include/mapper-vts/3.0/MapperVts.h index ba79ca42b7..1141a881e0 100644 --- a/graphics/mapper/3.0/utils/vts/include/mapper-vts/3.0/MapperVts.h +++ b/graphics/mapper/3.0/utils/vts/include/mapper-vts/3.0/MapperVts.h @@ -36,62 +36,66 @@ using android::hardware::graphics::allocator::V3_0::IAllocator; // A wrapper to IAllocator and IMapper. class Gralloc { public: - Gralloc(const std::string& allocatorServiceName = "default", - const std::string& mapperServiceName = "default"); - ~Gralloc(); + Gralloc(const std::string& allocatorServiceName = "default", + const std::string& mapperServiceName = "default", bool errOnFailure = true); + ~Gralloc(); - // IAllocator methods + // IAllocator methods - sp getAllocator() const; + sp getAllocator() const; - std::string dumpDebugInfo(); + std::string dumpDebugInfo(); - // When import is false, this simply calls IAllocator::allocate. When import - // is true, the returned buffers are also imported into the mapper. - // - // Either case, the returned buffers must be freed with freeBuffer. - std::vector allocate(const BufferDescriptor& descriptor, uint32_t count, - bool import = true, uint32_t* outStride = nullptr); - const native_handle_t* allocate(const IMapper::BufferDescriptorInfo& descriptorInfo, - bool import = true, uint32_t* outStride = nullptr); + // When import is false, this simply calls IAllocator::allocate. When import + // is true, the returned buffers are also imported into the mapper. + // + // Either case, the returned buffers must be freed with freeBuffer. + std::vector allocate(const BufferDescriptor& descriptor, + uint32_t count, bool import = true, + uint32_t* outStride = nullptr); + const native_handle_t* allocate(const IMapper::BufferDescriptorInfo& descriptorInfo, + bool import = true, uint32_t* outStride = nullptr); - // IMapper methods + // IMapper methods - sp getMapper() const; + sp getMapper() const; - BufferDescriptor createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo); + BufferDescriptor createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo); - const native_handle_t* importBuffer(const hidl_handle& rawHandle); - void freeBuffer(const native_handle_t* bufferHandle); + const native_handle_t* importBuffer(const hidl_handle& rawHandle); + void freeBuffer(const native_handle_t* bufferHandle); - // We use fd instead of hidl_handle in these functions to pass fences - // in and out of the mapper. The ownership of the fd is always transferred - // with each of these functions. - void* lock(const native_handle_t* bufferHandle, uint64_t cpuUsage, - const IMapper::Rect& accessRegion, int acquireFence, int32_t* outBytesPerPixel, - int32_t* outBytesPerStride); - YCbCrLayout lockYCbCr(const native_handle_t* bufferHandle, uint64_t cpuUsage, - const IMapper::Rect& accessRegion, int acquireFence); - int unlock(const native_handle_t* bufferHandle); + // We use fd instead of hidl_handle in these functions to pass fences + // in and out of the mapper. The ownership of the fd is always transferred + // with each of these functions. + void* lock(const native_handle_t* bufferHandle, uint64_t cpuUsage, + const IMapper::Rect& accessRegion, int acquireFence, int32_t* outBytesPerPixel, + int32_t* outBytesPerStride); + YCbCrLayout lockYCbCr(const native_handle_t* bufferHandle, uint64_t cpuUsage, + const IMapper::Rect& accessRegion, int acquireFence); + int unlock(const native_handle_t* bufferHandle); - bool validateBufferSize(const native_handle_t* bufferHandle, - const IMapper::BufferDescriptorInfo& descriptorInfo, uint32_t stride); - void getTransportSize(const native_handle_t* bufferHandle, uint32_t* outNumFds, - uint32_t* outNumInts); + bool validateBufferSize(const native_handle_t* bufferHandle, + const IMapper::BufferDescriptorInfo& descriptorInfo, uint32_t stride); + void getTransportSize(const native_handle_t* bufferHandle, uint32_t* outNumFds, + uint32_t* outNumInts); - bool isSupported(const IMapper::BufferDescriptorInfo& descriptorInfo); + bool isSupported(const IMapper::BufferDescriptorInfo& descriptorInfo); private: - void init(const std::string& allocatorServiceName, const std::string& mapperServiceName); - const native_handle_t* cloneBuffer(const hidl_handle& rawHandle); + void init(const std::string& allocatorServiceName, const std::string& mapperServiceName); - sp mAllocator; - sp mMapper; + // initialize without checking for failure to get service + void initNoErr(const std::string& allocatorServiceName, const std::string& mapperServiceName); + const native_handle_t* cloneBuffer(const hidl_handle& rawHandle); - // Keep track of all cloned and imported handles. When a test fails with - // ASSERT_*, the destructor will free the handles for the test. - std::unordered_set mClonedBuffers; - std::unordered_set mImportedBuffers; + sp mAllocator; + sp mMapper; + + // Keep track of all cloned and imported handles. When a test fails with + // ASSERT_*, the destructor will free the handles for the test. + std::unordered_set mClonedBuffers; + std::unordered_set mImportedBuffers; }; } // namespace vts From a9c6df2ba9a9adeef5c14edb928d3fd943c0b6c7 Mon Sep 17 00:00:00 2001 From: Prachi Hande Date: Wed, 19 Jun 2019 18:57:52 -0700 Subject: [PATCH 705/718] Updated a method name in VmsUtils. Corrected "CreateDataMessageWithLayerPublisherInfo" to "createDataMessageWithLayerPublisherInfo" Bug: 135051289 Fixes: 135051289 Test: Updated tests in VmsUtilsTest. Ran the tests on Hawk. Change-Id: Ie5e130e125b90689d13a3f9bb8fa1f2f8a2bcbe0 --- .../vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h | 2 +- automotive/vehicle/2.0/default/common/src/VmsUtils.cpp | 2 +- automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h index 87010cea0c..f064367fdc 100644 --- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h +++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h @@ -172,7 +172,7 @@ std::unique_ptr createSubscriptionsRequest(); // should first convert the proto to a byte string (vms_packet) using the // SerializeToString proto API. Then, it use this interface to build the VehicleProperty // by passing publisher and layer information (layer_publisher) and the vms_packet. -std::unique_ptr CreateDataMessageWithLayerPublisherInfo( +std::unique_ptr createDataMessageWithLayerPublisherInfo( const VmsLayerAndPublisher& layer_publisher, const std::string& vms_packet); // Creates a VehiclePropValue containing a message of type diff --git a/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp b/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp index f16489ce83..a5fcbaf612 100644 --- a/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp +++ b/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp @@ -126,7 +126,7 @@ std::unique_ptr createSubscriptionsRequest() { return result; } -std::unique_ptr CreateDataMessageWithLayerPublisherInfo( +std::unique_ptr createDataMessageWithLayerPublisherInfo( const VmsLayerAndPublisher& layer_publisher, const std::string& vms_packet) { auto result = createBaseVmsMessage(kMessageTypeSize + kLayerAndPublisherSize); result->value.int32Values = hidl_vec{ diff --git a/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp b/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp index 8a434c85b8..3716738f66 100644 --- a/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp +++ b/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp @@ -141,7 +141,7 @@ TEST(VmsUtilsTest, subscriptionsMessage) { TEST(VmsUtilsTest, dataMessage) { const std::string bytes = "aaa"; const VmsLayerAndPublisher layer_and_publisher(VmsLayer(2, 0, 1), 123); - auto message = CreateDataMessageWithLayerPublisherInfo(layer_and_publisher, bytes); + auto message = createDataMessageWithLayerPublisherInfo(layer_and_publisher, bytes); ASSERT_NE(message, nullptr); EXPECT_TRUE(isValidVmsMessage(*message)); EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE)); @@ -177,7 +177,7 @@ TEST(VmsUtilsTest, invalidMessageType) { TEST(VmsUtilsTest, parseDataMessage) { const std::string bytes = "aaa"; const VmsLayerAndPublisher layer_and_publisher(VmsLayer(1, 0, 1), 123); - auto message = CreateDataMessageWithLayerPublisherInfo(layer_and_publisher, bytes); + auto message = createDataMessageWithLayerPublisherInfo(layer_and_publisher, bytes); auto data_str = parseData(*message); ASSERT_FALSE(data_str.empty()); EXPECT_EQ(data_str, bytes); From bf967c9bdb7f0ce0202a0826dc6b3f61b2ba191f Mon Sep 17 00:00:00 2001 From: Valerie Hau Date: Fri, 21 Jun 2019 11:06:48 -0700 Subject: [PATCH 706/718] Wait until old ComposerClient is fully destroyed before recreating Possible race condition where EventCallbacks are registered before old implementation deregisters on destruction. Stems from fact that strong pointer destruction does not mean the object has completely run its destructor method Bug: 135210708 Test: build, boot, VtsHalGraphicsComposerV2_1TargetTest Change-Id: I0851f1197d8341854f5bdac5fbb08553fc32b710 --- .../2.1/utils/hal/include/composer-hal/2.1/Composer.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/Composer.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/Composer.h index ad985dafa3..90d9b982a7 100644 --- a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/Composer.h +++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/Composer.h @@ -109,12 +109,10 @@ class ComposerImpl : public Interface { // inverted (create and then destroy). Wait for a brief period to // see if the existing client is destroyed. ALOGD("waiting for previous client to be destroyed"); - mClientDestroyedCondition.wait_for( - lock, 1s, [this]() -> bool { return mClient.promote() == nullptr; }); - if (mClient.promote() != nullptr) { + mClientDestroyedCondition.wait_for(lock, 1s, + [this]() -> bool { return mClient == nullptr; }); + if (mClient != nullptr) { ALOGD("previous client was not destroyed"); - } else { - mClient.clear(); } } From 6eba01f8f42914a6b19dfdecfdb8e64c707795f7 Mon Sep 17 00:00:00 2001 From: Yifan Hong Date: Fri, 21 Jun 2019 15:05:19 -0700 Subject: [PATCH 707/718] health storage hal vts test: add more tolerance. Test: run on blueline Bug: 135631007 Change-Id: Ie1770a4a152a045e5f40eaf9cd7b551fe391a0b1 Merged-In: Ie1770a4a152a045e5f40eaf9cd7b551fe391a0b1 (cherry picked from commit ae3d61c2c336a40cd6cdfd073ad112e5d70286c3) --- .../functional/VtsHalHealthStorageV1_0TargetTest.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/health/storage/1.0/vts/functional/VtsHalHealthStorageV1_0TargetTest.cpp b/health/storage/1.0/vts/functional/VtsHalHealthStorageV1_0TargetTest.cpp index 946e5f2470..2365124dcb 100644 --- a/health/storage/1.0/vts/functional/VtsHalHealthStorageV1_0TargetTest.cpp +++ b/health/storage/1.0/vts/functional/VtsHalHealthStorageV1_0TargetTest.cpp @@ -35,6 +35,9 @@ using ::std::literals::chrono_literals::operator""ms; // Dev GC timeout. This is the timeout used by vold. const uint64_t kDevGcTimeoutSec = 120; const std::chrono::seconds kDevGcTimeout{kDevGcTimeoutSec}; +// Dev GC timeout tolerance. The HAL may not immediately return after the +// timeout, so include an acceptable tolerance. +const std::chrono::seconds kDevGcTolerance{3}; // Time accounted for RPC calls. const std::chrono::milliseconds kRpcTime{1000}; @@ -156,8 +159,9 @@ TEST_F(HealthStorageHidlTest, GcNullCallback) { ASSERT_OK(ret); // Hold test process because HAL can be single-threaded and doing GC. - ASSERT_TRUE(ping(kDevGcTimeout + kRpcTime)) - << "Service must be available after " << toString(kDevGcTimeout + kRpcTime); + ASSERT_TRUE(ping(kDevGcTimeout + kDevGcTolerance + kRpcTime)) + << "Service must be available after " + << toString(kDevGcTimeout + kDevGcTolerance + kRpcTime); } /** @@ -167,7 +171,7 @@ TEST_F(HealthStorageHidlTest, GcNonNullCallback) { sp cb = new GcCallback(); auto ret = fs->garbageCollect(kDevGcTimeoutSec, cb); ASSERT_OK(ret); - cb->waitForResult(kDevGcTimeout + kRpcTime, Result::SUCCESS); + cb->waitForResult(kDevGcTimeout + kDevGcTolerance + kRpcTime, Result::SUCCESS); } } // namespace V1_0 From 42a26244ad0d1c72b023c5fed4d63aea179906b5 Mon Sep 17 00:00:00 2001 From: Kai Date: Thu, 20 Jun 2019 16:40:22 -0700 Subject: [PATCH 708/718] Add Speed_Display_Units property in DefaultHal Update properties for DefaultHal and it is also be a code sample for adding new properties. Bug: 134988550 Test: flash it and verify property by kitchenSink Change-Id: Iedf3ea5b288acfe95b3c676d90660435b34ed367 --- .../2.0/default/impl/vhal_v2_0/DefaultConfig.h | 11 +++++++++++ 1 file changed, 11 insertions(+) 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 39fe991339..a46de24b16 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 @@ -240,6 +240,17 @@ const ConfigDeclaration kVehicleProperties[]{ }, .initialValue = {.floatValues = {0.0f}}}, + {.config = + { + .prop = toInt(VehicleProperty::VEHICLE_SPEED_DISPLAY_UNITS), + .access = VehiclePropertyAccess::READ_WRITE, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + .configArray = {(int)VehicleUnit::METER_PER_SEC, + (int)VehicleUnit::MILES_PER_HOUR, + (int)VehicleUnit::KILOMETERS_PER_HOUR}, + }, + .initialValue = {.int32Values = {(int)VehicleUnit::KILOMETERS_PER_HOUR}}}, + {.config = { .prop = toInt(VehicleProperty::INFO_DRIVER_SEAT), From fa2a909836de0a82d0f4a52ffdf5d0cacd74eed9 Mon Sep 17 00:00:00 2001 From: Shuzhen Wang Date: Sun, 23 Jun 2019 22:52:16 -0700 Subject: [PATCH 709/718] Camera: VTS: Allow unsupported logical/physical combination Multi-camera API requirement is relaxed to allow camera device not support physical stream combinations. Adjust the test accordingly. Test: processMultiCaptureRequestPreview Bug: 135688720 Bug: 135728906 Change-Id: I8c5269c5d3fd7f6eef440c818706629af2233196 --- .../VtsHalCameraProviderV2_4TargetTest.cpp | 37 ++++++++++++++++--- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp index 200dd3f199..6cdbf0c5d6 100644 --- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp +++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp @@ -755,7 +755,8 @@ public: uint32_t *partialResultCount /*out*/, bool *useHalBufManager /*out*/, sp *cb /*out*/, - uint32_t streamConfigCounter = 0); + uint32_t streamConfigCounter = 0, + bool allowUnsupport = false); void configurePreviewStream(const std::string &name, int32_t deviceVersion, sp provider, const AvailableStream *previewThreshold, @@ -4048,7 +4049,7 @@ TEST_F(CameraHidlTest, processMultiCaptureRequestPreview) { for (const auto& name : cameraDeviceNames) { int deviceVersion = getCameraDeviceVersion(name, mProviderType); - if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_4) { + if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_5) { continue; } std::string version, deviceId; @@ -4120,8 +4121,11 @@ TEST_F(CameraHidlTest, processMultiCaptureRequestPreview) { configurePreviewStreams3_4(name, deviceVersion, mProvider, &previewThreshold, physicalIds, &session3_4, &session3_5, &previewStream, &halStreamConfig /*out*/, &supportsPartialResults /*out*/, &partialResultCount /*out*/, - &useHalBufManager /*out*/, &cb /*out*/); - ASSERT_NE(session3_4, nullptr); + &useHalBufManager /*out*/, &cb /*out*/, 0 /*streamConfigCounter*/, + true /*allowUnsupport*/); + if (session3_5 == nullptr) { + continue; + } std::shared_ptr resultQueue; auto resultQueueRet = @@ -5167,7 +5171,8 @@ void CameraHidlTest::configurePreviewStreams3_4(const std::string &name, int32_t uint32_t *partialResultCount /*out*/, bool *useHalBufManager /*out*/, sp *outCb /*out*/, - uint32_t streamConfigCounter) { + uint32_t streamConfigCounter, + bool allowUnsupport) { ASSERT_NE(nullptr, session3_4); ASSERT_NE(nullptr, session3_5); ASSERT_NE(nullptr, halStreamConfig); @@ -5266,6 +5271,28 @@ void CameraHidlTest::configurePreviewStreams3_4(const std::string &name, int32_t }); ASSERT_TRUE(ret.isOk()); + ASSERT_TRUE(!allowUnsupport || deviceVersion == CAMERA_DEVICE_API_VERSION_3_5); + if (allowUnsupport) { + sp cameraDevice3_5; + castDevice(device3_x, deviceVersion, &cameraDevice3_5); + + bool supported = false; + ret = cameraDevice3_5->isStreamCombinationSupported(config3_4, + [&supported](Status s, bool combStatus) { + ASSERT_TRUE((Status::OK == s) || + (Status::METHOD_NOT_SUPPORTED == s)); + if (Status::OK == s) { + supported = combStatus; + } + }); + ASSERT_TRUE(ret.isOk()); + // If stream combination is not supported, return null session. + if (!supported) { + *session3_5 = nullptr; + return; + } + } + if (*session3_5 != nullptr) { config3_5.v3_4 = config3_4; config3_5.streamConfigCounter = streamConfigCounter; From 9c0a45795f4f2cd099b673afa7063f48d1ca2f6c Mon Sep 17 00:00:00 2001 From: Garret Kelly Date: Mon, 24 Jun 2019 18:31:38 -0400 Subject: [PATCH 710/718] Increase leniency of attestation record timestamps The TEE keymaster has been seen to be almost a minute out of sync with the host clock during attestation. Increase the leniency window to two minutes. Bug: 134408892 Bug: 134408367 Test: VtsHalKeymasterV4_0TargetTest Change-Id: Ic256a939dcd7e7b108099cfcf237cacde8dde059 --- keymaster/4.0/vts/functional/KeymasterHidlTest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp b/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp index a7b6c981f4..3af1df32d3 100644 --- a/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp +++ b/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp @@ -216,8 +216,8 @@ void KeymasterHidlTest::CheckCreationDateTime( std::chrono::system_clock::now(); std::chrono::time_point reported_time{ std::chrono::milliseconds(sw_enforced[i].f.dateTime)}; - // The test is flaky for EC keys, so a buffer time of 1 second will be added. - EXPECT_LE(creation - 1s, reported_time); + // The test is flaky for EC keys, so a buffer time of 120 seconds will be added. + EXPECT_LE(creation - 120s, reported_time); EXPECT_LE(reported_time, now + 1s); } } From af6af767e7c99500e8e53945ed5e75a519bd4c81 Mon Sep 17 00:00:00 2001 From: Prachi Hande Date: Wed, 19 Jun 2019 15:50:07 -0700 Subject: [PATCH 711/718] Updated START_SESSION message interpretation Removed the dependency on the fact that the core's new ID is always >= existing ID. New ID and the old ID may not have any such relation. Bug: 135475397 Fixes: 135475397 Test: Updated unit tests in VmsUtilsTest. Ran the tests on Hawk. Change-Id: I5a7e72f36a84f5bf2d3c7bf1ccb89d27c5c0da97 --- .../common/include/vhal_v2_0/VmsUtils.h | 19 +++++-------- .../2.0/default/common/src/VmsUtils.cpp | 25 ++++++++--------- .../2.0/default/tests/VmsUtils_test.cpp | 27 +++++++------------ 3 files changed, 28 insertions(+), 43 deletions(-) diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h index 87010cea0c..4112ccc17a 100644 --- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h +++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h @@ -109,20 +109,13 @@ struct VmsAvailabilityState { // An enum to represent the result of parsing START_SESSION message from the VMS service. enum VmsSessionStatus { - // New server session is received if the new client ID is -1 and the new server ID is not an - // invalid ID. + // When a new session is received, the client should acknowledge it with the correct + // IDs in the START_SESSION message. kNewServerSession, - // Ack to new client session is received if the new client ID is same as the old one and the new - // server ID is not an invalid ID. - kAckToNewClientSession, - // Error codes: + // When an acknowledgement it received, the client can start using the connection. + kAckToCurrentSession, // Invalid message with either invalid format or unexpected data. - kInvalidMessage, - // Invalid server ID. New ID should always be greater than or equal to max_of(0, current server - // ID) - kInvalidServiceId, - // Invalid client ID. New ID should always be either -1 or the current client ID. - kInvalidClientId + kInvalidMessage }; // Creates an empty base VMS message with some pre-populated default fields. @@ -235,7 +228,7 @@ bool hasServiceNewlyStarted(const VehiclePropValue& availability_change); // Takes a start session message, current service ID, current client ID; and returns the type/status // of the message. It also populates the new service ID with the correct value. VmsSessionStatus parseStartSessionMessage(const VehiclePropValue& start_session, - const int service_id, const int client_id, + const int current_service_id, const int current_client_id, int* new_service_id); } // namespace vms diff --git a/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp b/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp index f16489ce83..1c149d497a 100644 --- a/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp +++ b/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp @@ -272,27 +272,28 @@ bool hasServiceNewlyStarted(const VehiclePropValue& availability_change) { } VmsSessionStatus parseStartSessionMessage(const VehiclePropValue& start_session, - const int service_id, const int client_id, + const int current_service_id, const int current_client_id, int* new_service_id) { if (isValidVmsMessage(start_session) && parseMessageType(start_session) == VmsMessageType::START_SESSION && start_session.value.int32Values.size() == kSessionIdsSize + 1) { *new_service_id = start_session.value.int32Values[1]; const int new_client_id = start_session.value.int32Values[2]; - if (*new_service_id < std::max(0, service_id)) { - *new_service_id = service_id; - return VmsSessionStatus::kInvalidServiceId; - } - if (new_client_id == -1) { + if (new_client_id != current_client_id) { + // If the new_client_id = -1, it means the service has newly started. + // But if it is not -1 and is different than the current client ID, then + // it means that the service did not have the correct client ID. In + // both these cases, the client should acknowledge with a START_SESSION + // message containing the correct client ID. So here, the status is returned as + // kNewServerSession. return VmsSessionStatus::kNewServerSession; + } else { + // kAckToCurrentSession is returned if the new client ID is same as the current one. + return VmsSessionStatus::kAckToCurrentSession; } - if (new_client_id == client_id) { - return VmsSessionStatus::kAckToNewClientSession; - } - *new_service_id = service_id; - return VmsSessionStatus::kInvalidClientId; } - *new_service_id = service_id; + // If the message is invalid then persist the old service ID. + *new_service_id = current_service_id; return VmsSessionStatus::kInvalidMessage; } diff --git a/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp b/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp index 8a434c85b8..474f6af3bb 100644 --- a/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp +++ b/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp @@ -371,25 +371,25 @@ TEST(VmsUtilsTest, startSessionClientNewlyStarted) { int new_service_id; message->value.int32Values = hidl_vec{toInt(VmsMessageType::START_SESSION), 123, 456}; EXPECT_EQ(parseStartSessionMessage(*message, -1, 456, &new_service_id), - VmsSessionStatus::kAckToNewClientSession); + VmsSessionStatus::kAckToCurrentSession); EXPECT_EQ(new_service_id, 123); } -TEST(VmsUtilsTest, startSessionClientNewlyStartedWithSameServerId) { +TEST(VmsUtilsTest, startSessionClientNewlyStartedWithSameServerAndClientId) { auto message = createBaseVmsMessage(3); int new_service_id; message->value.int32Values = hidl_vec{toInt(VmsMessageType::START_SESSION), 123, 456}; EXPECT_EQ(parseStartSessionMessage(*message, 123, 456, &new_service_id), - VmsSessionStatus::kAckToNewClientSession); + VmsSessionStatus::kAckToCurrentSession); EXPECT_EQ(new_service_id, 123); } -TEST(VmsUtilsTest, startSessionClientNewlyStartedEdgeCase) { +TEST(VmsUtilsTest, startSessionWithZeroAsIds) { auto message = createBaseVmsMessage(3); int new_service_id; message->value.int32Values = hidl_vec{toInt(VmsMessageType::START_SESSION), 0, 0}; EXPECT_EQ(parseStartSessionMessage(*message, 0, 0, &new_service_id), - VmsSessionStatus::kAckToNewClientSession); + VmsSessionStatus::kAckToCurrentSession); EXPECT_EQ(new_service_id, 0); } @@ -398,28 +398,19 @@ TEST(VmsUtilsTest, startSessionOldServiceId) { int new_service_id; message->value.int32Values = hidl_vec{toInt(VmsMessageType::START_SESSION), 120, 456}; EXPECT_EQ(parseStartSessionMessage(*message, 123, 456, &new_service_id), - VmsSessionStatus::kInvalidServiceId); - EXPECT_EQ(new_service_id, 123); + VmsSessionStatus::kAckToCurrentSession); + EXPECT_EQ(new_service_id, 120); } -TEST(VmsUtilsTest, startSessionInvalidServiceIdEdgeCase) { +TEST(VmsUtilsTest, startSessionNegativeServerId) { auto message = createBaseVmsMessage(3); int new_service_id; message->value.int32Values = hidl_vec{toInt(VmsMessageType::START_SESSION), -1, 456}; EXPECT_EQ(parseStartSessionMessage(*message, -1, 456, &new_service_id), - VmsSessionStatus::kInvalidServiceId); + VmsSessionStatus::kAckToCurrentSession); EXPECT_EQ(new_service_id, -1); } -TEST(VmsUtilsTest, startSessionInvalidClientId) { - auto message = createBaseVmsMessage(3); - int new_service_id; - message->value.int32Values = hidl_vec{toInt(VmsMessageType::START_SESSION), 123, 457}; - EXPECT_EQ(parseStartSessionMessage(*message, 123, 456, &new_service_id), - VmsSessionStatus::kInvalidClientId); - EXPECT_EQ(new_service_id, 123); -} - TEST(VmsUtilsTest, startSessionInvalidMessageFormat) { auto message = createBaseVmsMessage(2); int new_service_id; From c689517d59dbd9a7e27c3b3bd3b98d9badaf7d35 Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Tue, 25 Jun 2019 09:39:45 -0700 Subject: [PATCH 712/718] compatibility_matrix: specify @1.2::ISap directly @1.4::ISap and @1.3::ISap don't exist, so we can't declare a requirement for them. Bug: 135627722 Test: reproduce error with vts_treble_vintf_test and then test to see this change fixes it. Change-Id: I8e48fcaf56701087d5720d5133ffa9b23a4ea31e --- compatibility_matrices/compatibility_matrix.4.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compatibility_matrices/compatibility_matrix.4.xml b/compatibility_matrices/compatibility_matrix.4.xml index 7d6fc609f8..21a0847cfc 100644 --- a/compatibility_matrices/compatibility_matrix.4.xml +++ b/compatibility_matrices/compatibility_matrix.4.xml @@ -354,6 +354,10 @@ slot2 slot3 + + + android.hardware.radio + 1.2 ISap slot1 From 82205d576c62bcdafb2f9caead631ea1cd29d234 Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Tue, 25 Jun 2019 11:24:20 -0700 Subject: [PATCH 713/718] VINTF CM: changes from 4 into current. compatibility_matrix.4.xml was updated for a late fix in Q, so the current matrix also needs to be updated. Bug: 135627722 Test: vts_treble_vintf_test Change-Id: I0cca7c55007d42ed8e86256b7b280b075378bc40 --- compatibility_matrices/compatibility_matrix.current.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml index 59af5d0e90..2284723f0a 100644 --- a/compatibility_matrices/compatibility_matrix.current.xml +++ b/compatibility_matrices/compatibility_matrix.current.xml @@ -354,6 +354,10 @@ slot2 slot3 + + + android.hardware.radio + 1.2 ISap slot1 From 7af5384d2d17a735df0df0615966eaf76d6ff17e Mon Sep 17 00:00:00 2001 From: Jimmy Chen Date: Wed, 19 Jun 2019 18:51:59 +0800 Subject: [PATCH 714/718] p2p: skip MAC randomization vts test if not supported Bug: 135247522 Test: atest VtsHalWifiSupplicantP2pV1_2TargetTest Change-Id: I1aafcdbe88f93dbf73069d24ae90cad0d395df6e --- .../1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp b/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp index 36bde161c1..1b78ac3e01 100644 --- a/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp +++ b/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp @@ -127,25 +127,33 @@ TEST_F(SupplicantP2pIfaceHidlTest, AddGroup_1_2_FailureInvalidFrequency) { }); } +bool isMacRandomizationSupported(const SupplicantStatus& status) { + return status.code != SupplicantStatusCode::FAILURE_ARGS_INVALID; +} + /* * Verify that setMacRandomization successes. */ TEST_F(SupplicantP2pIfaceHidlTest, EnableMacRandomization) { p2p_iface_->setMacRandomization(true, [](const SupplicantStatus& status) { + if (!isMacRandomizationSupported(status)) return; EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code); }); // enable twice p2p_iface_->setMacRandomization(true, [](const SupplicantStatus& status) { + if (!isMacRandomizationSupported(status)) return; EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code); }); p2p_iface_->setMacRandomization(false, [](const SupplicantStatus& status) { + if (!isMacRandomizationSupported(status)) return; EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code); }); // disable twice p2p_iface_->setMacRandomization(false, [](const SupplicantStatus& status) { + if (!isMacRandomizationSupported(status)) return; EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code); }); } From b1d2df1ed0f1e1ec62ee464d3426682a7bc303bf Mon Sep 17 00:00:00 2001 From: Janis Danisevskis Date: Tue, 4 Jun 2019 17:01:25 -0700 Subject: [PATCH 715/718] Added HIDL based software implementation of gatekeeper This patch adds a HIDL based software implementation of gatekeeper based on libgatekeeper. Also adds OWNER files to the vts test and default implementation directories. Test: Manually tested in emulator. Changing passwords and login worked. VtsHalGatekeeperV1_0TargetTest gatekeeper-software-device-unit-tests Change-Id: I632aeb6677640c133ec1b79e72568840adbc0550 Merged-In: I632aeb6677640c133ec1b79e72568840adbc0550 --- gatekeeper/1.0/default/OWNERS | 2 + gatekeeper/1.0/software/Android.bp | 28 +++ gatekeeper/1.0/software/OWNERS | 2 + gatekeeper/1.0/software/SoftGateKeeper.h | 171 +++++++++++++++++ .../1.0/software/SoftGateKeeperDevice.cpp | 114 +++++++++++ .../1.0/software/SoftGateKeeperDevice.h | 80 ++++++++ ...ardware.gatekeeper@1.0-service.software.rc | 4 + ...rdware.gatekeeper@1.0-service.software.xml | 11 ++ gatekeeper/1.0/software/service.cpp | 39 ++++ gatekeeper/1.0/software/tests/Android.bp | 34 ++++ .../1.0/software/tests/gatekeeper_test.cpp | 178 ++++++++++++++++++ gatekeeper/1.0/vts/OWNERS | 3 + 12 files changed, 666 insertions(+) create mode 100644 gatekeeper/1.0/default/OWNERS create mode 100644 gatekeeper/1.0/software/Android.bp create mode 100644 gatekeeper/1.0/software/OWNERS create mode 100644 gatekeeper/1.0/software/SoftGateKeeper.h create mode 100644 gatekeeper/1.0/software/SoftGateKeeperDevice.cpp create mode 100644 gatekeeper/1.0/software/SoftGateKeeperDevice.h create mode 100644 gatekeeper/1.0/software/android.hardware.gatekeeper@1.0-service.software.rc create mode 100644 gatekeeper/1.0/software/android.hardware.gatekeeper@1.0-service.software.xml create mode 100644 gatekeeper/1.0/software/service.cpp create mode 100644 gatekeeper/1.0/software/tests/Android.bp create mode 100644 gatekeeper/1.0/software/tests/gatekeeper_test.cpp create mode 100644 gatekeeper/1.0/vts/OWNERS diff --git a/gatekeeper/1.0/default/OWNERS b/gatekeeper/1.0/default/OWNERS new file mode 100644 index 0000000000..335660da3b --- /dev/null +++ b/gatekeeper/1.0/default/OWNERS @@ -0,0 +1,2 @@ +jdanis@google.com +swillden@google.com diff --git a/gatekeeper/1.0/software/Android.bp b/gatekeeper/1.0/software/Android.bp new file mode 100644 index 0000000000..148c98938f --- /dev/null +++ b/gatekeeper/1.0/software/Android.bp @@ -0,0 +1,28 @@ +cc_binary { + name: "android.hardware.gatekeeper@1.0-service.software", + defaults: ["hidl_defaults"], + relative_install_path: "hw", + vendor: true, + init_rc: ["android.hardware.gatekeeper@1.0-service.software.rc"], + + srcs: [ + "service.cpp", + "SoftGateKeeperDevice.cpp", + ], + + shared_libs: [ + "android.hardware.gatekeeper@1.0", + "libbase", + "libhardware", + "libhidlbase", + "libhidltransport", + "libutils", + "liblog", + "libcrypto", + "libgatekeeper", + ], + + static_libs: ["libscrypt_static"], + + vintf_fragments: ["android.hardware.gatekeeper@1.0-service.software.xml"], +} diff --git a/gatekeeper/1.0/software/OWNERS b/gatekeeper/1.0/software/OWNERS new file mode 100644 index 0000000000..335660da3b --- /dev/null +++ b/gatekeeper/1.0/software/OWNERS @@ -0,0 +1,2 @@ +jdanis@google.com +swillden@google.com diff --git a/gatekeeper/1.0/software/SoftGateKeeper.h b/gatekeeper/1.0/software/SoftGateKeeper.h new file mode 100644 index 0000000000..3276d1ebbd --- /dev/null +++ b/gatekeeper/1.0/software/SoftGateKeeper.h @@ -0,0 +1,171 @@ +/* + * Copyright 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. + * + */ + +#ifndef SOFT_GATEKEEPER_H_ +#define SOFT_GATEKEEPER_H_ + +extern "C" { +#include +#include + +#include +} + +#include +#include + +#include +#include +#include + +namespace gatekeeper { + +struct fast_hash_t { + uint64_t salt; + uint8_t digest[SHA256_DIGEST_LENGTH]; +}; + +class SoftGateKeeper : public GateKeeper { + public: + static const uint32_t SIGNATURE_LENGTH_BYTES = 32; + + // scrypt params + static const uint64_t N = 16384; + static const uint32_t r = 8; + static const uint32_t p = 1; + + static const int MAX_UINT_32_CHARS = 11; + + SoftGateKeeper() { + key_.reset(new uint8_t[SIGNATURE_LENGTH_BYTES]); + memset(key_.get(), 0, SIGNATURE_LENGTH_BYTES); + } + + virtual ~SoftGateKeeper() {} + + virtual bool GetAuthTokenKey(const uint8_t** auth_token_key, uint32_t* length) const { + if (auth_token_key == NULL || length == NULL) return false; + *auth_token_key = key_.get(); + *length = SIGNATURE_LENGTH_BYTES; + return true; + } + + virtual void GetPasswordKey(const uint8_t** password_key, uint32_t* length) { + if (password_key == NULL || length == NULL) return; + *password_key = key_.get(); + *length = SIGNATURE_LENGTH_BYTES; + } + + virtual void ComputePasswordSignature(uint8_t* signature, uint32_t signature_length, + const uint8_t*, uint32_t, const uint8_t* password, + uint32_t password_length, salt_t salt) const { + if (signature == NULL) return; + crypto_scrypt(password, password_length, reinterpret_cast(&salt), sizeof(salt), N, + r, p, signature, signature_length); + } + + virtual void GetRandom(void* random, uint32_t requested_length) const { + if (random == NULL) return; + RAND_pseudo_bytes((uint8_t*)random, requested_length); + } + + virtual void ComputeSignature(uint8_t* signature, uint32_t signature_length, const uint8_t*, + uint32_t, const uint8_t*, const uint32_t) const { + if (signature == NULL) return; + memset(signature, 0, signature_length); + } + + virtual uint64_t GetMillisecondsSinceBoot() const { + struct timespec time; + int res = clock_gettime(CLOCK_BOOTTIME, &time); + if (res < 0) return 0; + return (time.tv_sec * 1000) + (time.tv_nsec / 1000 / 1000); + } + + virtual bool IsHardwareBacked() const { return false; } + + virtual bool GetFailureRecord(uint32_t uid, secure_id_t user_id, failure_record_t* record, + bool /* secure */) { + failure_record_t* stored = &failure_map_[uid]; + if (user_id != stored->secure_user_id) { + stored->secure_user_id = user_id; + stored->last_checked_timestamp = 0; + stored->failure_counter = 0; + } + memcpy(record, stored, sizeof(*record)); + return true; + } + + virtual bool ClearFailureRecord(uint32_t uid, secure_id_t user_id, bool /* secure */) { + failure_record_t* stored = &failure_map_[uid]; + stored->secure_user_id = user_id; + stored->last_checked_timestamp = 0; + stored->failure_counter = 0; + return true; + } + + virtual bool WriteFailureRecord(uint32_t uid, failure_record_t* record, bool /* secure */) { + failure_map_[uid] = *record; + return true; + } + + fast_hash_t ComputeFastHash(const SizedBuffer& password, uint64_t salt) { + fast_hash_t fast_hash; + size_t digest_size = password.size() + sizeof(salt); + std::unique_ptr digest(new uint8_t[digest_size]); + memcpy(digest.get(), &salt, sizeof(salt)); + memcpy(digest.get() + sizeof(salt), password.Data(), password.size()); + + SHA256(digest.get(), digest_size, (uint8_t*)&fast_hash.digest); + + fast_hash.salt = salt; + return fast_hash; + } + + bool VerifyFast(const fast_hash_t& fast_hash, const SizedBuffer& password) { + fast_hash_t computed = ComputeFastHash(password, fast_hash.salt); + return memcmp(computed.digest, fast_hash.digest, SHA256_DIGEST_LENGTH) == 0; + } + + bool DoVerify(const password_handle_t* expected_handle, const SizedBuffer& password) { + uint64_t user_id = android::base::get_unaligned(&expected_handle->user_id); + FastHashMap::const_iterator it = fast_hash_map_.find(user_id); + if (it != fast_hash_map_.end() && VerifyFast(it->second, password)) { + return true; + } else { + if (GateKeeper::DoVerify(expected_handle, password)) { + uint64_t salt; + GetRandom(&salt, sizeof(salt)); + fast_hash_map_[user_id] = ComputeFastHash(password, salt); + return true; + } + } + + return false; + } + + private: + typedef std::unordered_map FailureRecordMap; + typedef std::unordered_map FastHashMap; + + std::unique_ptr key_; + FailureRecordMap failure_map_; + FastHashMap fast_hash_map_; +}; +} // namespace gatekeeper + +#endif // SOFT_GATEKEEPER_H_ diff --git a/gatekeeper/1.0/software/SoftGateKeeperDevice.cpp b/gatekeeper/1.0/software/SoftGateKeeperDevice.cpp new file mode 100644 index 0000000000..d7a0b46ee6 --- /dev/null +++ b/gatekeeper/1.0/software/SoftGateKeeperDevice.cpp @@ -0,0 +1,114 @@ +/* + * 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. + */ + +#include "SoftGateKeeperDevice.h" +#include "SoftGateKeeper.h" + +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::gatekeeper::V1_0::GatekeeperStatusCode; +using ::gatekeeper::EnrollRequest; +using ::gatekeeper::EnrollResponse; +using ::gatekeeper::ERROR_INVALID; +using ::gatekeeper::ERROR_MEMORY_ALLOCATION_FAILED; +using ::gatekeeper::ERROR_NONE; +using ::gatekeeper::ERROR_RETRY; +using ::gatekeeper::SizedBuffer; +using ::gatekeeper::VerifyRequest; +using ::gatekeeper::VerifyResponse; + +#include + +namespace android { + +inline SizedBuffer hidl_vec2sized_buffer(const hidl_vec& vec) { + if (vec.size() == 0 || vec.size() > std::numeric_limits::max()) return {}; + auto dummy = new uint8_t[vec.size()]; + std::copy(vec.begin(), vec.end(), dummy); + return {dummy, static_cast(vec.size())}; +} + +Return SoftGateKeeperDevice::enroll(uint32_t uid, + const hidl_vec& currentPasswordHandle, + const hidl_vec& currentPassword, + const hidl_vec& desiredPassword, + enroll_cb _hidl_cb) { + if (desiredPassword.size() == 0) { + _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}}); + return {}; + } + + EnrollRequest request(uid, hidl_vec2sized_buffer(currentPasswordHandle), + hidl_vec2sized_buffer(desiredPassword), + hidl_vec2sized_buffer(currentPassword)); + EnrollResponse response; + impl_->Enroll(request, &response); + + if (response.error == ERROR_RETRY) { + _hidl_cb({GatekeeperStatusCode::ERROR_RETRY_TIMEOUT, response.retry_timeout, {}}); + } else if (response.error != ERROR_NONE) { + _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}}); + } else { + hidl_vec new_handle(response.enrolled_password_handle.Data(), + response.enrolled_password_handle.Data() + + response.enrolled_password_handle.size()); + _hidl_cb({GatekeeperStatusCode::STATUS_OK, response.retry_timeout, new_handle}); + } + return {}; +} + +Return SoftGateKeeperDevice::verify( + uint32_t uid, uint64_t challenge, + const ::android::hardware::hidl_vec& enrolledPasswordHandle, + const ::android::hardware::hidl_vec& providedPassword, verify_cb _hidl_cb) { + if (enrolledPasswordHandle.size() == 0) { + _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}}); + return {}; + } + + VerifyRequest request(uid, challenge, hidl_vec2sized_buffer(enrolledPasswordHandle), + hidl_vec2sized_buffer(providedPassword)); + VerifyResponse response; + + impl_->Verify(request, &response); + + if (response.error == ERROR_RETRY) { + _hidl_cb({GatekeeperStatusCode::ERROR_RETRY_TIMEOUT, response.retry_timeout, {}}); + } else if (response.error != ERROR_NONE) { + _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}}); + } else { + hidl_vec auth_token( + response.auth_token.Data(), + response.auth_token.Data() + response.auth_token.size()); + + _hidl_cb({response.request_reenroll ? GatekeeperStatusCode::STATUS_REENROLL + : GatekeeperStatusCode::STATUS_OK, + response.retry_timeout, auth_token}); + } + return {}; +} + +Return SoftGateKeeperDevice::deleteUser(uint32_t /*uid*/, deleteUser_cb _hidl_cb) { + _hidl_cb({GatekeeperStatusCode::ERROR_NOT_IMPLEMENTED, 0, {}}); + return {}; +} + +Return SoftGateKeeperDevice::deleteAllUsers(deleteAllUsers_cb _hidl_cb) { + _hidl_cb({GatekeeperStatusCode::ERROR_NOT_IMPLEMENTED, 0, {}}); + return {}; +} + +} // namespace android diff --git a/gatekeeper/1.0/software/SoftGateKeeperDevice.h b/gatekeeper/1.0/software/SoftGateKeeperDevice.h new file mode 100644 index 0000000000..17b474e4aa --- /dev/null +++ b/gatekeeper/1.0/software/SoftGateKeeperDevice.h @@ -0,0 +1,80 @@ +/* + * Copyright 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. + */ + +#ifndef SOFT_GATEKEEPER_DEVICE_H_ +#define SOFT_GATEKEEPER_DEVICE_H_ + +#include +#include + +#include +#include "SoftGateKeeper.h" + +namespace android { + +/** + * Software based GateKeeper implementation + */ +class SoftGateKeeperDevice : public ::android::hardware::gatekeeper::V1_0::IGatekeeper { + public: + SoftGateKeeperDevice() { impl_.reset(new ::gatekeeper::SoftGateKeeper()); } + + // Wrappers to translate the gatekeeper HAL API to the Kegyuard Messages API. + + /** + * Enrolls password_payload, which should be derived from a user selected pin or password, + * with the authentication factor private key used only for enrolling authentication + * factor data. + * + * Returns: 0 on success or an error code less than 0 on error. + * On error, enrolled_password_handle will not be allocated. + */ + ::android::hardware::Return enroll( + uint32_t uid, const ::android::hardware::hidl_vec& currentPasswordHandle, + const ::android::hardware::hidl_vec& currentPassword, + const ::android::hardware::hidl_vec& desiredPassword, + enroll_cb _hidl_cb) override; + + /** + * Verifies provided_password matches enrolled_password_handle. + * + * Implementations of this module may retain the result of this call + * to attest to the recency of authentication. + * + * On success, writes the address of a verification token to auth_token, + * usable to attest password verification to other trusted services. Clients + * may pass NULL for this value. + * + * Returns: 0 on success or an error code less than 0 on error + * On error, verification token will not be allocated + */ + ::android::hardware::Return verify( + uint32_t uid, uint64_t challenge, + const ::android::hardware::hidl_vec& enrolledPasswordHandle, + const ::android::hardware::hidl_vec& providedPassword, + verify_cb _hidl_cb) override; + + ::android::hardware::Return deleteUser(uint32_t uid, deleteUser_cb _hidl_cb) override; + + ::android::hardware::Return deleteAllUsers(deleteAllUsers_cb _hidl_cb) override; + + private: + std::unique_ptr<::gatekeeper::SoftGateKeeper> impl_; +}; + +} // namespace android + +#endif // SOFT_GATEKEEPER_DEVICE_H_ diff --git a/gatekeeper/1.0/software/android.hardware.gatekeeper@1.0-service.software.rc b/gatekeeper/1.0/software/android.hardware.gatekeeper@1.0-service.software.rc new file mode 100644 index 0000000000..60cb96c915 --- /dev/null +++ b/gatekeeper/1.0/software/android.hardware.gatekeeper@1.0-service.software.rc @@ -0,0 +1,4 @@ +service vendor.gatekeeper-1-0 /vendor/bin/hw/android.hardware.gatekeeper@1.0-service.software + class hal + user system + group system diff --git a/gatekeeper/1.0/software/android.hardware.gatekeeper@1.0-service.software.xml b/gatekeeper/1.0/software/android.hardware.gatekeeper@1.0-service.software.xml new file mode 100644 index 0000000000..19714a83b7 --- /dev/null +++ b/gatekeeper/1.0/software/android.hardware.gatekeeper@1.0-service.software.xml @@ -0,0 +1,11 @@ + + + android.hardware.gatekeeper + hwbinder + 1.0 + + IGatekeeper + default + + + diff --git a/gatekeeper/1.0/software/service.cpp b/gatekeeper/1.0/software/service.cpp new file mode 100644 index 0000000000..a48a964c08 --- /dev/null +++ b/gatekeeper/1.0/software/service.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define LOG_TAG "android.hardware.gatekeeper@1.0-service" + +#include +#include + +#include + +#include "SoftGateKeeperDevice.h" + +// Generated HIDL files +using android::SoftGateKeeperDevice; +using android::hardware::gatekeeper::V1_0::IGatekeeper; + +int main() { + ::android::hardware::configureRpcThreadpool(1, true /* willJoinThreadpool */); + android::sp gatekeeper(new SoftGateKeeperDevice()); + auto status = gatekeeper->registerAsService(); + if (status != android::OK) { + LOG(FATAL) << "Could not register service for Gatekeeper 1.0 (software) (" << status << ")"; + } + + android::hardware::joinRpcThreadpool(); + return -1; // Should never get here. +} diff --git a/gatekeeper/1.0/software/tests/Android.bp b/gatekeeper/1.0/software/tests/Android.bp new file mode 100644 index 0000000000..3f0300dc18 --- /dev/null +++ b/gatekeeper/1.0/software/tests/Android.bp @@ -0,0 +1,34 @@ +// +// 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. +// + +cc_test { + name: "gatekeeper-software-device-unit-tests", + + cflags: [ + "-g", + "-Wall", + "-Werror", + "-Wno-missing-field-initializers", + ], + shared_libs: [ + "libgatekeeper", + "libcrypto", + "libbase", + ], + static_libs: ["libscrypt_static"], + + srcs: ["gatekeeper_test.cpp"], +} diff --git a/gatekeeper/1.0/software/tests/gatekeeper_test.cpp b/gatekeeper/1.0/software/tests/gatekeeper_test.cpp new file mode 100644 index 0000000000..bf4a8bc5fa --- /dev/null +++ b/gatekeeper/1.0/software/tests/gatekeeper_test.cpp @@ -0,0 +1,178 @@ +/* + * Copyright 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. + */ + +#include +#include + +#include +#include + +#include "../SoftGateKeeper.h" + +using ::gatekeeper::EnrollRequest; +using ::gatekeeper::EnrollResponse; +using ::gatekeeper::secure_id_t; +using ::gatekeeper::SizedBuffer; +using ::gatekeeper::SoftGateKeeper; +using ::gatekeeper::VerifyRequest; +using ::gatekeeper::VerifyResponse; +using ::testing::Test; + +static SizedBuffer makePasswordBuffer(int init = 0) { + constexpr const uint32_t pw_buffer_size = 16; + auto pw_buffer = new uint8_t[pw_buffer_size]; + memset(pw_buffer, init, pw_buffer_size); + + return {pw_buffer, pw_buffer_size}; +} + +static SizedBuffer makeAndInitializeSizedBuffer(const uint8_t* data, uint32_t size) { + auto buffer = new uint8_t[size]; + memcpy(buffer, data, size); + return {buffer, size}; +} + +static SizedBuffer copySizedBuffer(const SizedBuffer& rhs) { + return makeAndInitializeSizedBuffer(rhs.Data(), rhs.size()); +} + +static void do_enroll(SoftGateKeeper& gatekeeper, EnrollResponse* response) { + EnrollRequest request(0, {}, makePasswordBuffer(), {}); + + gatekeeper.Enroll(request, response); +} + +TEST(GateKeeperTest, EnrollSuccess) { + SoftGateKeeper gatekeeper; + EnrollResponse response; + do_enroll(gatekeeper, &response); + ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error); +} + +TEST(GateKeeperTest, EnrollBogusData) { + SoftGateKeeper gatekeeper; + EnrollResponse response; + + EnrollRequest request(0, {}, {}, {}); + + gatekeeper.Enroll(request, &response); + + ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_INVALID, response.error); +} + +TEST(GateKeeperTest, VerifySuccess) { + SoftGateKeeper gatekeeper; + EnrollResponse enroll_response; + + do_enroll(gatekeeper, &enroll_response); + ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error); + VerifyRequest request(0, 1, std::move(enroll_response.enrolled_password_handle), + makePasswordBuffer()); + VerifyResponse response; + + gatekeeper.Verify(request, &response); + + ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error); + + auto auth_token = response.auth_token.Data(); + + ASSERT_NE(nullptr, auth_token); + ASSERT_EQ((uint32_t)HW_AUTH_PASSWORD, ntohl(auth_token->authenticator_type)); + ASSERT_EQ((uint64_t)1, auth_token->challenge); + ASSERT_NE(~((uint32_t)0), auth_token->timestamp); + ASSERT_NE((uint64_t)0, auth_token->user_id); + ASSERT_NE((uint64_t)0, auth_token->authenticator_id); +} + +TEST(GateKeeperTest, TrustedReEnroll) { + SoftGateKeeper gatekeeper; + EnrollResponse enroll_response; + + // do_enroll enrolls an all 0 password + do_enroll(gatekeeper, &enroll_response); + ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error); + + // verify first password + VerifyRequest request(0, 0, copySizedBuffer(enroll_response.enrolled_password_handle), + makePasswordBuffer()); + VerifyResponse response; + gatekeeper.Verify(request, &response); + ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error); + auto auth_token = response.auth_token.Data(); + ASSERT_NE(nullptr, auth_token); + + secure_id_t secure_id = auth_token->user_id; + + // enroll new password + EnrollRequest enroll_request(0, std::move(enroll_response.enrolled_password_handle), + makePasswordBuffer(1) /* new password */, + makePasswordBuffer() /* old password */); + gatekeeper.Enroll(enroll_request, &enroll_response); + ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error); + + // verify new password + VerifyRequest new_request(0, 0, std::move(enroll_response.enrolled_password_handle), + makePasswordBuffer(1)); + gatekeeper.Verify(new_request, &response); + ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error); + ASSERT_NE(nullptr, response.auth_token.Data()); + ASSERT_EQ(secure_id, response.auth_token.Data()->user_id); +} + +TEST(GateKeeperTest, UntrustedReEnroll) { + SoftGateKeeper gatekeeper; + SizedBuffer provided_password; + EnrollResponse enroll_response; + + // do_enroll enrolls an all 0 password + provided_password = makePasswordBuffer(); + do_enroll(gatekeeper, &enroll_response); + ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error); + + // verify first password + VerifyRequest request(0, 0, std::move(enroll_response.enrolled_password_handle), + std::move(provided_password)); + VerifyResponse response; + gatekeeper.Verify(request, &response); + ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error); + auto auth_token = response.auth_token.Data(); + ASSERT_NE(nullptr, auth_token); + + secure_id_t secure_id = auth_token->user_id; + + EnrollRequest enroll_request(0, {}, makePasswordBuffer(1), {}); + gatekeeper.Enroll(enroll_request, &enroll_response); + ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error); + + // verify new password + VerifyRequest new_request(0, 0, std::move(enroll_response.enrolled_password_handle), + makePasswordBuffer(1)); + gatekeeper.Verify(new_request, &response); + ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error); + ASSERT_NE(nullptr, response.auth_token.Data()); + ASSERT_NE(secure_id, response.auth_token.Data()->user_id); +} + +TEST(GateKeeperTest, VerifyBogusData) { + SoftGateKeeper gatekeeper; + VerifyResponse response; + + VerifyRequest request(0, 0, {}, {}); + + gatekeeper.Verify(request, &response); + + ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_INVALID, response.error); +} diff --git a/gatekeeper/1.0/vts/OWNERS b/gatekeeper/1.0/vts/OWNERS new file mode 100644 index 0000000000..738c71025a --- /dev/null +++ b/gatekeeper/1.0/vts/OWNERS @@ -0,0 +1,3 @@ +jdanis@google.com +swillden@google.com +guangzhu@google.com From 00bc962dea8ea8dd51679a6454bd744f46e5e72f Mon Sep 17 00:00:00 2001 From: Ilya Matyukhin Date: Tue, 25 Jun 2019 10:39:07 -0700 Subject: [PATCH 716/718] Update VTS tests to support the latest BiometricsFace.hal Bug: 134967390 Test: vts-tradefed run commandAndExit vts-hal -m VtsHalBiometricsFaceV1_0Target Change-Id: Ifbd04d127626315efd8c8ce36636e550cbb843ff --- .../VtsHalBiometricsFaceV1_0TargetTest.cpp | 381 +++++++----------- 1 file changed, 150 insertions(+), 231 deletions(-) diff --git a/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp b/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp index 40961f79b9..d3d738798b 100644 --- a/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp +++ b/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp @@ -14,29 +14,24 @@ * limitations under the License. */ -#define LOG_TAG "face_hidl_test" +#define LOG_TAG "biometrics_face_hidl_hal_test" +#include +#include + +#include #include #include #include -#include -#include -#include -#include -#include -#include -#include +#include #include -#include -#include +#include -using android::Condition; -using android::Mutex; using android::sp; -using android::base::GetUintProperty; using android::hardware::hidl_vec; using android::hardware::Return; +using android::hardware::Void; using android::hardware::biometrics::face::V1_0::FaceAcquiredInfo; using android::hardware::biometrics::face::V1_0::FaceError; using android::hardware::biometrics::face::V1_0::Feature; @@ -48,263 +43,203 @@ using android::hardware::biometrics::face::V1_0::Status; namespace { -const uint32_t kTimeout = 3; -const std::chrono::seconds kTimeoutInSeconds = std::chrono::seconds(kTimeout); -const uint32_t kUserId = 99; -const uint32_t kFaceId = 5; -const char kTmpDir[] = "/data/system/users/0/facedata"; -const int kIterations = 1000; +// Arbitrary, nonexistent userId +constexpr uint32_t kUserId = 9; +// Arbitrary, nonexistent faceId +constexpr uint32_t kFaceId = 5; +constexpr uint32_t kTimeoutSec = 3; +constexpr auto kTimeout = std::chrono::seconds(kTimeoutSec); +constexpr int kGenerateChallengeIterations = 10; +constexpr char kFacedataDir[] = "/data/vendor_de/0/facedata"; +constexpr char kCallbackNameOnEnrollResult[] = "onEnrollResult"; +constexpr char kCallbackNameOnAuthenticated[] = "onAuthenticated"; +constexpr char kCallbackNameOnAcquired[] = "onAcquired"; +constexpr char kCallbackNameOnError[] = "onError"; +constexpr char kCallbackNameOnRemoved[] = "onRemoved"; +constexpr char kCallbackNameOnEnumerate[] = "onEnumerate"; +constexpr char kCallbackNameOnLockoutChanged[] = "onLockoutChanged"; -const auto kAssertCallbackIsSet = [](const OptionalUint64& res) { - ASSERT_EQ(Status::OK, res.status); - // Makes sure the "deviceId" represented by "res.value" is not 0. - // 0 would mean the HIDL is not available. - ASSERT_NE(0UL, res.value); +// Callback arguments that need to be captured for the tests. +struct FaceCallbackArgs { + // The error passed to the last onError() callback. + FaceError error; + + // The userId passed to the last onRemoved() callback. + int32_t userId; }; -// Wait for a callback to occur (signaled by the given future) up to the -// provided timeout. If the future is invalid or the callback does not come -// within the given time, returns false. -template -bool waitForCallback(std::future future, - std::chrono::milliseconds timeout = kTimeoutInSeconds) { - auto expiration = std::chrono::system_clock::now() + timeout; - EXPECT_TRUE(future.valid()); - if (future.valid()) { - std::future_status status = future.wait_until(expiration); - EXPECT_NE(std::future_status::timeout, status) << "Timed out waiting for callback"; - if (status == std::future_status::ready) { - return true; - } - } - return false; -} - -// Base callback implementation that just logs all callbacks by default -class FaceCallbackBase : public IBiometricsFaceClientCallback { +// Test callback class for the BiometricsFace HAL. +// The HAL will call these callback methods to notify about completed operations +// or encountered errors. +class FaceCallback : public ::testing::VtsHalHidlTargetCallbackBase, + public IBiometricsFaceClientCallback { public: Return onEnrollResult(uint64_t, uint32_t, int32_t, uint32_t) override { - ALOGD("Enroll callback called."); - return Return(); + NotifyFromCallback(kCallbackNameOnEnrollResult); + return Void(); } Return onAuthenticated(uint64_t, uint32_t, int32_t, const hidl_vec&) override { - ALOGD("Authenticated callback called."); - return Return(); + NotifyFromCallback(kCallbackNameOnAuthenticated); + return Void(); } Return onAcquired(uint64_t, int32_t, FaceAcquiredInfo, int32_t) override { - ALOGD("Acquired callback called."); - return Return(); + NotifyFromCallback(kCallbackNameOnAcquired); + return Void(); } - Return onError(uint64_t, int32_t, FaceError, int32_t) override { - ALOGD("Error callback called."); - EXPECT_TRUE(false); // fail any test that triggers an error - return Return(); + Return onError(uint64_t, int32_t, FaceError error, int32_t) override { + FaceCallbackArgs args = {}; + args.error = error; + NotifyFromCallback(kCallbackNameOnError, args); + return Void(); } - Return onRemoved(uint64_t, const hidl_vec&, int32_t) override { - ALOGD("Removed callback called."); - return Return(); + Return onRemoved(uint64_t, const hidl_vec&, int32_t userId) override { + FaceCallbackArgs args = {}; + args.userId = userId; + NotifyFromCallback(kCallbackNameOnRemoved, args); + return Void(); } - Return onEnumerate(uint64_t, const hidl_vec&, int32_t /* userId */) override { - ALOGD("Enumerate callback called."); - return Return(); + Return onEnumerate(uint64_t, const hidl_vec&, int32_t) override { + NotifyFromCallback(kCallbackNameOnEnumerate); + return Void(); } Return onLockoutChanged(uint64_t) override { - ALOGD("LockoutChanged callback called."); - return Return(); + NotifyFromCallback(kCallbackNameOnLockoutChanged); + return Void(); } }; -class EnumerateCallback : public FaceCallbackBase { - public: - Return onEnumerate(uint64_t, const hidl_vec&, int32_t) override { - promise.set_value(); - return Return(); - } - - std::promise promise; -}; - -class ErrorCallback : public FaceCallbackBase { - public: - ErrorCallback(bool filterErrors = false, FaceError errorType = FaceError::HW_UNAVAILABLE) - : filterErrors(filterErrors), errorType(errorType), hasError(false) {} - - Return onError(uint64_t, int32_t, FaceError error, int32_t) override { - if ((filterErrors && errorType == error) || !filterErrors) { - hasError = true; - this->error = error; - promise.set_value(); - } - return Return(); - } - - bool filterErrors; - FaceError errorType; - bool hasError; - FaceError error; - std::promise promise; -}; - -class RemoveCallback : public FaceCallbackBase { - public: - explicit RemoveCallback(int32_t userId) : removeUserId(userId) {} - - Return onRemoved(uint64_t, const hidl_vec&, int32_t userId) override { - EXPECT_EQ(removeUserId, userId); - promise.set_value(); - return Return(); - } - - int32_t removeUserId; - std::promise promise; -}; - -class LockoutChangedCallback : public FaceCallbackBase { - public: - Return onLockoutChanged(uint64_t duration) override { - this->hasDuration = true; - this->duration = duration; - promise.set_value(); - return Return(); - } - bool hasDuration; - uint64_t duration; - std::promise promise; -}; - -// Test environment for Face HIDL HAL. +// Test environment for the BiometricsFace HAL. class FaceHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { public: - // get the test environment singleton + // Get the test environment singleton. static FaceHidlEnvironment* Instance() { static FaceHidlEnvironment* instance = new FaceHidlEnvironment; return instance; } void registerTestServices() override { registerTestService(); } + + private: + FaceHidlEnvironment() = default; }; +// Test class for the BiometricsFace HAL. class FaceHidlTest : public ::testing::VtsHalHidlTargetTestBase { public: void SetUp() override { mService = ::testing::VtsHalHidlTargetTestBase::getService( FaceHidlEnvironment::Instance()->getServiceName()); - ASSERT_FALSE(mService == nullptr); - Return res = mService->setActiveUser(kUserId, kTmpDir); - ASSERT_EQ(Status::OK, static_cast(res)); + ASSERT_NE(mService, nullptr); + mCallback = new FaceCallback(); + mCallback->SetWaitTimeoutDefault(kTimeout); + Return ret1 = mService->setCallback(mCallback, [](const OptionalUint64& res) { + ASSERT_EQ(Status::OK, res.status); + // Makes sure the "deviceId" represented by "res.value" is not 0. + // 0 would mean the HIDL is not available. + ASSERT_NE(0UL, res.value); + }); + ASSERT_TRUE(ret1.isOk()); + Return ret2 = mService->setActiveUser(kUserId, kFacedataDir); + ASSERT_EQ(Status::OK, static_cast(ret2)); } void TearDown() override {} sp mService; + sp mCallback; }; -// The service should be reachable. -TEST_F(FaceHidlTest, ConnectTest) { - sp cb = new FaceCallbackBase(); - mService->setCallback(cb, kAssertCallbackIsSet); -} - -// Starting the service with null callback should succeed. -TEST_F(FaceHidlTest, ConnectNullTest) { - mService->setCallback(nullptr, kAssertCallbackIsSet); -} - // generateChallenge should always return a unique, cryptographically secure, // non-zero number. TEST_F(FaceHidlTest, GenerateChallengeTest) { std::map m; - for (int i = 0; i < kIterations; ++i) { - mService->generateChallenge(kTimeout, [&m](const OptionalUint64& res) { - ASSERT_EQ(Status::OK, res.status); - EXPECT_NE(0UL, res.value); - m[res.value]++; - EXPECT_EQ(1UL, m[res.value]); - }); + for (int i = 0; i < kGenerateChallengeIterations; ++i) { + Return ret = + mService->generateChallenge(kTimeoutSec, [&m](const OptionalUint64& res) { + ASSERT_EQ(Status::OK, res.status); + EXPECT_NE(0UL, res.value); + m[res.value]++; + EXPECT_EQ(1UL, m[res.value]); + }); + ASSERT_TRUE(ret.isOk()); } } // enroll with an invalid (all zeroes) HAT should fail. TEST_F(FaceHidlTest, EnrollZeroHatTest) { - sp cb = new ErrorCallback(); - mService->setCallback(cb, kAssertCallbackIsSet); - + // Filling HAT with zeros hidl_vec token(69); for (size_t i = 0; i < 69; i++) { token[i] = 0; } - Return res = mService->enroll(token, kTimeout, {}); - ASSERT_EQ(Status::OK, static_cast(res)); + Return ret = mService->enroll(token, kTimeoutSec, {}); + ASSERT_EQ(Status::OK, static_cast(ret)); - // At least one call to onError should occur - ASSERT_TRUE(waitForCallback(cb->promise.get_future())); - ASSERT_TRUE(cb->hasError); + // onError should be called with a meaningful (nonzero) error. + auto res = mCallback->WaitForCallback(kCallbackNameOnError); + EXPECT_TRUE(res.no_timeout); + EXPECT_EQ(FaceError::UNABLE_TO_PROCESS, res.args->error); } // enroll with an invalid HAT should fail. TEST_F(FaceHidlTest, EnrollGarbageHatTest) { - sp cb = new ErrorCallback(); - mService->setCallback(cb, kAssertCallbackIsSet); - - // Filling HAT with invalid data + // Filling HAT with pseudorandom invalid data. + // Using default seed to make the test reproducible. + std::mt19937 gen(std::mt19937::default_seed); + std::uniform_int_distribution dist; hidl_vec token(69); for (size_t i = 0; i < 69; ++i) { - token[i] = i; + token[i] = dist(gen); } - Return res = mService->enroll(token, kTimeout, {}); - ASSERT_EQ(Status::OK, static_cast(res)); + Return ret = mService->enroll(token, kTimeoutSec, {}); + ASSERT_EQ(Status::OK, static_cast(ret)); - // At least one call to onError should occur - ASSERT_TRUE(waitForCallback(cb->promise.get_future())); - ASSERT_TRUE(cb->hasError); + // onError should be called with a meaningful (nonzero) error. + auto res = mCallback->WaitForCallback(kCallbackNameOnError); + EXPECT_TRUE(res.no_timeout); + EXPECT_EQ(FaceError::UNABLE_TO_PROCESS, res.args->error); } // setFeature with an invalid (all zeros) HAT should fail. TEST_F(FaceHidlTest, SetFeatureZeroHatTest) { - sp cb = new ErrorCallback(); - mService->setCallback(cb, kAssertCallbackIsSet); - hidl_vec token(69); for (size_t i = 0; i < 69; i++) { token[i] = 0; } - Return res = mService->setFeature(Feature::REQUIRE_DIVERSITY, false, token, 0); - ASSERT_EQ(Status::ILLEGAL_ARGUMENT, static_cast(res)); + Return ret = mService->setFeature(Feature::REQUIRE_DIVERSITY, false, token, 0); + ASSERT_EQ(Status::ILLEGAL_ARGUMENT, static_cast(ret)); } // setFeature with an invalid HAT should fail. TEST_F(FaceHidlTest, SetFeatureGarbageHatTest) { - sp cb = new ErrorCallback(); - mService->setCallback(cb, kAssertCallbackIsSet); - - // Filling HAT with invalid data + // Filling HAT with pseudorandom invalid data. + // Using default seed to make the test reproducible. + std::mt19937 gen(std::mt19937::default_seed); + std::uniform_int_distribution dist; hidl_vec token(69); for (size_t i = 0; i < 69; ++i) { - token[i] = i; + token[i] = dist(gen); } - Return res = mService->setFeature(Feature::REQUIRE_DIVERSITY, false, token, 0); - ASSERT_EQ(Status::ILLEGAL_ARGUMENT, static_cast(res)); + Return ret = mService->setFeature(Feature::REQUIRE_DIVERSITY, false, token, 0); + ASSERT_EQ(Status::ILLEGAL_ARGUMENT, static_cast(ret)); } -void assertGetFeatureFails(sp service, int faceId, Feature feature) { - std::promise promise; - +void assertGetFeatureFails(const sp& service, uint32_t faceId, Feature feature) { // Features cannot be retrieved for invalid faces. - Return res = service->getFeature(feature, faceId, [&promise](const OptionalBool& result) { + Return res = service->getFeature(feature, faceId, [](const OptionalBool& result) { ASSERT_EQ(Status::ILLEGAL_ARGUMENT, result.status); - promise.set_value(); }); - ASSERT_TRUE(waitForCallback(promise.get_future())); + ASSERT_TRUE(res.isOk()); } TEST_F(FaceHidlTest, GetFeatureRequireAttentionTest) { @@ -317,111 +252,95 @@ TEST_F(FaceHidlTest, GetFeatureRequireDiversityTest) { // revokeChallenge should always return within the timeout TEST_F(FaceHidlTest, RevokeChallengeTest) { - sp cb = new FaceCallbackBase(); - mService->setCallback(cb, kAssertCallbackIsSet); - auto start = std::chrono::system_clock::now(); - mService->revokeChallenge(); + Return ret = mService->revokeChallenge(); auto elapsed = std::chrono::system_clock::now() - start; - ASSERT_GE(kTimeoutInSeconds, elapsed); + ASSERT_EQ(Status::OK, static_cast(ret)); + ASSERT_GE(kTimeout, elapsed); } // The call to getAuthenticatorId should succeed. TEST_F(FaceHidlTest, GetAuthenticatorIdTest) { - mService->getAuthenticatorId( + Return ret = mService->getAuthenticatorId( [](const OptionalUint64& res) { ASSERT_EQ(Status::OK, res.status); }); + ASSERT_TRUE(ret.isOk()); } // The call to enumerate should succeed. TEST_F(FaceHidlTest, EnumerateTest) { - sp cb = new EnumerateCallback(); - mService->setCallback(cb, kAssertCallbackIsSet); - Return res = mService->enumerate(); - ASSERT_EQ(Status::OK, static_cast(res)); - ASSERT_TRUE(waitForCallback(cb->promise.get_future())); + Return ret = mService->enumerate(); + ASSERT_EQ(Status::OK, static_cast(ret)); + auto res = mCallback->WaitForCallback(kCallbackNameOnEnumerate); + EXPECT_TRUE(res.no_timeout); } // The call to remove should succeed for any faceId TEST_F(FaceHidlTest, RemoveFaceTest) { - sp cb = new ErrorCallback(); - mService->setCallback(cb, kAssertCallbackIsSet); - // Remove a face - Return res = mService->remove(kFaceId); - ASSERT_EQ(Status::OK, static_cast(res)); + Return ret = mService->remove(kFaceId); + ASSERT_EQ(Status::OK, static_cast(ret)); } // Remove should accept 0 to delete all faces TEST_F(FaceHidlTest, RemoveAllFacesTest) { - sp cb = new ErrorCallback(); - mService->setCallback(cb, kAssertCallbackIsSet); - // Remove all faces - Return res = mService->remove(0); - ASSERT_EQ(Status::OK, static_cast(res)); + Return ret = mService->remove(0); + ASSERT_EQ(Status::OK, static_cast(ret)); } // Active user should successfully set to a writable location. TEST_F(FaceHidlTest, SetActiveUserTest) { // Create an active user - Return res = mService->setActiveUser(2, kTmpDir); - ASSERT_EQ(Status::OK, static_cast(res)); + Return ret = mService->setActiveUser(2, kFacedataDir); + ASSERT_EQ(Status::OK, static_cast(ret)); // Reset active user - res = mService->setActiveUser(kUserId, kTmpDir); - ASSERT_EQ(Status::OK, static_cast(res)); + ret = mService->setActiveUser(kUserId, kFacedataDir); + ASSERT_EQ(Status::OK, static_cast(ret)); } // Active user should fail to set to an unwritable location. TEST_F(FaceHidlTest, SetActiveUserUnwritableTest) { // Create an active user to an unwritable location (device root dir) - Return res = mService->setActiveUser(3, "/"); - ASSERT_NE(Status::OK, static_cast(res)); + Return ret = mService->setActiveUser(3, "/"); + ASSERT_NE(Status::OK, static_cast(ret)); // Reset active user - res = mService->setActiveUser(kUserId, kTmpDir); - ASSERT_EQ(Status::OK, static_cast(res)); + ret = mService->setActiveUser(kUserId, kFacedataDir); + ASSERT_EQ(Status::OK, static_cast(ret)); } // Active user should fail to set to a null location. TEST_F(FaceHidlTest, SetActiveUserNullTest) { // Create an active user to a null location. - Return res = mService->setActiveUser(4, nullptr); - ASSERT_NE(Status::OK, static_cast(res)); + Return ret = mService->setActiveUser(4, nullptr); + ASSERT_NE(Status::OK, static_cast(ret)); // Reset active user - res = mService->setActiveUser(kUserId, kTmpDir); - ASSERT_EQ(Status::OK, static_cast(res)); + ret = mService->setActiveUser(kUserId, kFacedataDir); + ASSERT_EQ(Status::OK, static_cast(ret)); } // Cancel should always return CANCELED from any starting state including // the IDLE state. TEST_F(FaceHidlTest, CancelTest) { - sp cb = new ErrorCallback(true, FaceError::CANCELED); - mService->setCallback(cb, kAssertCallbackIsSet); - - Return res = mService->cancel(); + Return ret = mService->cancel(); // check that we were able to make an IPC request successfully - ASSERT_EQ(Status::OK, static_cast(res)); - - // make sure callback was invoked within kTimeoutInSeconds - ASSERT_TRUE(waitForCallback(cb->promise.get_future())); - // check error should be CANCELED - ASSERT_EQ(FaceError::CANCELED, cb->error); + ASSERT_EQ(Status::OK, static_cast(ret)); + auto res = mCallback->WaitForCallback(kCallbackNameOnError); + // make sure callback was invoked within kRevokeChallengeTimeout + EXPECT_TRUE(res.no_timeout); + EXPECT_EQ(FaceError::CANCELED, res.args->error); } TEST_F(FaceHidlTest, OnLockoutChangedTest) { - sp cb = new LockoutChangedCallback(); - mService->setCallback(cb, kAssertCallbackIsSet); - - // Update active user and ensure lockout duration 0 is received - mService->setActiveUser(5, kTmpDir); + // Update active user and ensure onLockoutChanged was called. + Return ret = mService->setActiveUser(kUserId + 1, kFacedataDir); + ASSERT_EQ(Status::OK, static_cast(ret)); // Make sure callback was invoked - ASSERT_TRUE(waitForCallback(cb->promise.get_future())); - - // Check that duration 0 was received - ASSERT_EQ(0, cb->duration); + auto res = mCallback->WaitForCallback(kCallbackNameOnLockoutChanged); + EXPECT_TRUE(res.no_timeout); } } // anonymous namespace From 7d350fed1eb720b292283d5601b9387b83935c50 Mon Sep 17 00:00:00 2001 From: Yifan Hong Date: Fri, 28 Jun 2019 11:03:58 -0700 Subject: [PATCH 717/718] Q matrix: use radio.config@1.2::IRadioConfig 1.1 IRadioConfig does not exist. radio.config@1.2 is a minor version uprev that only updates the sub interfaces, not the top level interface. Test: builds Test: on device with target-level 4, w/o this change, with radio config 1.1, see test failure on deprecated radio config HAL Test: on this device, with this change, with radio config 1.1, deprecated radio config HAL failure goes away. Bug: 135172251 Change-Id: Id51870a8a757af0895577a27723cff8ee3ba0fdd --- compatibility_matrices/compatibility_matrix.4.xml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/compatibility_matrices/compatibility_matrix.4.xml b/compatibility_matrices/compatibility_matrix.4.xml index 21a0847cfc..01ec172d89 100644 --- a/compatibility_matrices/compatibility_matrix.4.xml +++ b/compatibility_matrices/compatibility_matrix.4.xml @@ -365,7 +365,13 @@ android.hardware.radio.config - 1.2 + + 1.1 IRadioConfig default From f18a8328a1ed54e2978928bdf89ede60bedaf318 Mon Sep 17 00:00:00 2001 From: nagendra modadugu Date: Fri, 28 Jun 2019 11:43:45 -0700 Subject: [PATCH 718/718] keymaster: Relax testing under GSI GSI images do not have AVB verification enabled and therefore lack several properties the keymaster HAL test depended on. Selectively disable those parts of the test that would fail with AVB verification disabled. Also disable date format checks under GSI. When invoked from GSI the TEE-backed keymaster doesn't use the correct date format. Bug: 130843899 Test: VtsHalKeymasterV4_0TargetTest Exempt-From-Owner-Approval: change only affects VTS-on-GSI behavior Change-Id: Idaafb7b515c41290c766a8132f35d498ca15f48a --- .../functional/keymaster_hidl_hal_test.cpp | 73 +++++++++++-------- 1 file changed, 43 insertions(+), 30 deletions(-) diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp index 6f75a9720c..728bf69368 100644 --- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp +++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp @@ -309,6 +309,11 @@ std::string make_string(const uint8_t (&a)[N]) { return make_string(a, N); } +bool avb_verification_enabled() { + char value[PROPERTY_VALUE_MAX]; + return property_get("ro.boot.vbmeta.device_state", value, "") != 0; +} + } // namespace bool verify_attestation_record(const string& challenge, const string& app_id, @@ -359,26 +364,32 @@ bool verify_attestation_record(const string& challenge, const string& app_id, EXPECT_EQ(0, memcmp(challenge.data(), att_challenge.data(), challenge.length())); char property_value[PROPERTY_VALUE_MAX] = {}; - for (int i = 0; i < att_hw_enforced.size(); i++) { - if (att_hw_enforced[i].tag == TAG_BOOT_PATCHLEVEL || - att_hw_enforced[i].tag == TAG_VENDOR_PATCHLEVEL) { - std::string date = std::to_string(att_hw_enforced[i].f.integer); - // strptime seems to require delimiters, but the tag value will be YYYYMMDD - date.insert(6, "-"); - date.insert(4, "-"); - EXPECT_EQ(date.size(), 10); - struct tm time; - strptime(date.c_str(), "%Y-%m-%d", &time); + // TODO(b/136282179): When running under VTS-on-GSI the TEE-backed + // keymaster implementation will report YYYYMM dates instead of YYYYMMDD + // for the BOOT_PATCH_LEVEL. + if (avb_verification_enabled()) { + for (int i = 0; i < att_hw_enforced.size(); i++) { + if (att_hw_enforced[i].tag == TAG_BOOT_PATCHLEVEL || + att_hw_enforced[i].tag == TAG_VENDOR_PATCHLEVEL) { + std::string date = std::to_string(att_hw_enforced[i].f.integer); + // strptime seems to require delimiters, but the tag value will + // be YYYYMMDD + date.insert(6, "-"); + date.insert(4, "-"); + EXPECT_EQ(date.size(), 10); + struct tm time; + strptime(date.c_str(), "%Y-%m-%d", &time); - // Day of the month (0-31) - EXPECT_GE(time.tm_mday, 0); - EXPECT_LT(time.tm_mday, 32); - // Months since Jan (0-11) - EXPECT_GE(time.tm_mon, 0); - EXPECT_LT(time.tm_mon, 12); - // Years since 1900 - EXPECT_GT(time.tm_year, 110); - EXPECT_LT(time.tm_year, 200); + // Day of the month (0-31) + EXPECT_GE(time.tm_mday, 0); + EXPECT_LT(time.tm_mday, 32); + // Months since Jan (0-11) + EXPECT_GE(time.tm_mon, 0); + EXPECT_LT(time.tm_mon, 12); + // Years since 1900 + EXPECT_GT(time.tm_year, 110); + EXPECT_LT(time.tm_year, 200); + } } } @@ -410,18 +421,20 @@ bool verify_attestation_record(const string& challenge, const string& app_id, &verified_boot_state, &device_locked, &verified_boot_hash); EXPECT_EQ(ErrorCode::OK, error); - property_get("ro.boot.vbmeta.digest", property_value, "nogood"); - EXPECT_NE(strcmp(property_value, "nogood"), 0); - string prop_string(property_value); - EXPECT_EQ(prop_string.size(), 64); - EXPECT_EQ(prop_string, bin2hex(verified_boot_hash)); + if (avb_verification_enabled()) { + property_get("ro.boot.vbmeta.digest", property_value, "nogood"); + EXPECT_NE(strcmp(property_value, "nogood"), 0); + string prop_string(property_value); + EXPECT_EQ(prop_string.size(), 64); + EXPECT_EQ(prop_string, bin2hex(verified_boot_hash)); - property_get("ro.boot.vbmeta.device_state", property_value, "nogood"); - EXPECT_NE(property_value, "nogood"); - if (!strcmp(property_value, "unlocked")) { - EXPECT_FALSE(device_locked); - } else { - EXPECT_TRUE(device_locked); + property_get("ro.boot.vbmeta.device_state", property_value, "nogood"); + EXPECT_NE(strcmp(property_value, "nogood"), 0); + if (!strcmp(property_value, "unlocked")) { + EXPECT_FALSE(device_locked); + } else { + EXPECT_TRUE(device_locked); + } } // Verified boot key should be all 0's if the boot state is not verified or self signed