OSDN Git Service

Enlarge buffer size for direct report testing am: 3c01fef56c
authorPeng Xu <pengxu@google.com>
Thu, 12 Oct 2017 17:05:02 +0000 (17:05 +0000)
committerandroid-build-merger <android-build-merger@google.com>
Thu, 12 Oct 2017 17:05:02 +0000 (17:05 +0000)
am: b0fe06a06b

Change-Id: I06edfcd55eaa52c962f5ff6bda4060d3df9c4efe

417 files changed:
Android.bp
CleanSpec.mk
OWNERS [new file with mode: 0644]
audio/2.0/Android.bp
audio/2.0/default/Android.mk
audio/2.0/default/OWNERS [new file with mode: 0644]
audio/2.0/default/Stream.h
audio/2.0/default/StreamIn.cpp
audio/2.0/default/StreamOut.cpp
audio/2.0/default/service.cpp
audio/2.0/vts/functional/Android.bp
audio/2.0/vts/functional/AudioPrimaryHidlHalTest.cpp
audio/common/2.0/Android.bp
audio/common/2.0/default/Android.bp
audio/common/2.0/default/OWNERS [new file with mode: 0644]
audio/common/test/utility/OWNERS [new file with mode: 0644]
audio/effect/2.0/Android.bp
audio/effect/2.0/default/OWNERS [new file with mode: 0644]
audio/effect/2.0/vts/functional/Android.bp
audio/effect/2.0/vts/functional/ValidateAudioEffectsConfiguration.cpp [new file with mode: 0644]
audio/effect/2.0/xml/audio_effects_conf_V2_0.xsd [new file with mode: 0644]
automotive/Android.bp
automotive/evs/1.0/Android.bp
automotive/evs/1.0/default/Android.bp [new file with mode: 0644]
automotive/evs/1.0/default/Android.mk [deleted file]
automotive/evs/1.0/vts/functional/Android.bp
automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp [moved from automotive/evs/1.0/vts/functional/VtsEvsV1_0TargetTest.cpp with 97% similarity]
automotive/vehicle/2.0/Android.bp
automotive/vehicle/2.0/Android.mk
automotive/vehicle/2.0/default/Android.bp [new file with mode: 0644]
automotive/vehicle/2.0/default/Android.mk [deleted file]
automotive/vehicle/2.0/default/common/include/vhal_v2_0/Obd2SensorStore.h [moved from automotive/vehicle/2.1/default/common/include/vhal_v2_1/Obd2SensorStore.h with 76% similarity]
automotive/vehicle/2.0/default/common/src/Obd2SensorStore.cpp [moved from automotive/vehicle/2.1/default/common/src/Obd2SensorStore.cpp with 62% similarity]
automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/Android.bp [new file with mode: 0644]
automotive/vehicle/2.0/default/tests/VehicleHalTestUtils.h
automotive/vehicle/2.0/types.hal
automotive/vehicle/2.1/Android.bp [deleted file]
automotive/vehicle/2.1/Android.mk [deleted file]
automotive/vehicle/2.1/IVehicle.hal [deleted file]
automotive/vehicle/2.1/default/Android.mk [deleted file]
automotive/vehicle/2.1/default/android.hardware.automotive.vehicle@2.1-service.rc [deleted file]
automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultConfig.h [deleted file]
automotive/vehicle/2.1/default/impl/vhal_v2_1/EmulatedVehicleHal.cpp [deleted file]
automotive/vehicle/2.1/default/impl/vhal_v2_1/EmulatedVehicleHal.h [deleted file]
automotive/vehicle/2.1/default/service.cpp [deleted file]
automotive/vehicle/2.1/default/tests/Obd2SensorStore_test.cpp [deleted file]
automotive/vehicle/2.1/types.hal [deleted file]
biometrics/fingerprint/2.1/Android.bp
biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp
biometrics/fingerprint/2.1/default/BiometricsFingerprint.h
biometrics/fingerprint/2.1/vts/functional/Android.bp
bluetooth/1.0/Android.bp
bluetooth/1.0/default/async_fd_watcher.cc
bluetooth/1.0/default/bluetooth_address.cc
bluetooth/1.0/default/bluetooth_hci.h
bluetooth/1.0/default/h4_protocol.cc
bluetooth/1.0/default/hci_packetizer.cc
bluetooth/1.0/default/hci_protocol.cc
bluetooth/1.0/default/vendor_interface.cc
bluetooth/1.0/vts/functional/Android.bp
bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
boot/1.0/Android.bp
boot/1.0/vts/functional/Android.bp
broadcastradio/1.0/Android.bp
broadcastradio/1.0/default/OWNERS [new file with mode: 0644]
broadcastradio/1.0/types.hal
broadcastradio/1.0/vts/functional/Android.bp
broadcastradio/1.1/Android.bp
broadcastradio/1.1/IBroadcastRadio.hal
broadcastradio/1.1/IBroadcastRadioFactory.hal
broadcastradio/1.1/ITuner.hal
broadcastradio/1.1/ITunerCallback.hal
broadcastradio/1.1/WARNING [deleted file]
broadcastradio/1.1/default/Android.bp
broadcastradio/1.1/default/BroadcastRadio.cpp
broadcastradio/1.1/default/BroadcastRadio.h
broadcastradio/1.1/default/BroadcastRadioFactory.cpp
broadcastradio/1.1/default/BroadcastRadioFactory.h
broadcastradio/1.1/default/OWNERS [new file with mode: 0644]
broadcastradio/1.1/default/Tuner.cpp
broadcastradio/1.1/default/Tuner.h
broadcastradio/1.1/default/Utils.cpp [deleted file]
broadcastradio/1.1/default/Utils.h [deleted file]
broadcastradio/1.1/default/VirtualProgram.cpp [new file with mode: 0644]
broadcastradio/1.1/default/VirtualProgram.h [new file with mode: 0644]
broadcastradio/1.1/default/VirtualRadio.cpp [new file with mode: 0644]
broadcastradio/1.1/default/VirtualRadio.h [new file with mode: 0644]
broadcastradio/1.1/default/android.hardware.broadcastradio@1.1-service.rc [new file with mode: 0644]
broadcastradio/1.1/default/resources.h [new file with mode: 0644]
broadcastradio/1.1/default/service.cpp [new file with mode: 0644]
broadcastradio/1.1/tests/Android.bp [new file with mode: 0644]
broadcastradio/1.1/tests/OWNERS [new file with mode: 0644]
broadcastradio/1.1/tests/WorkerThread_test.cpp [new file with mode: 0644]
broadcastradio/1.1/types.hal
broadcastradio/1.1/utils/Android.bp [moved from power/1.1/default/Android.bp with 56% similarity]
broadcastradio/1.1/utils/OWNERS [new file with mode: 0644]
broadcastradio/1.1/utils/Utils.cpp [new file with mode: 0644]
broadcastradio/1.1/utils/WorkerThread.cpp [new file with mode: 0644]
broadcastradio/1.1/utils/include/broadcastradio-utils/Utils.h [new file with mode: 0644]
broadcastradio/1.1/utils/include/broadcastradio-utils/WorkerThread.h [new file with mode: 0644]
broadcastradio/1.1/vts/OWNERS [new file with mode: 0644]
broadcastradio/1.1/vts/functional/Android.bp
broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp
broadcastradio/1.1/vts/utils/Android.bp [new file with mode: 0644]
broadcastradio/1.1/vts/utils/call-barrier.cpp [new file with mode: 0644]
broadcastradio/1.1/vts/utils/include/broadcastradio-vts-utils/call-barrier.h [new file with mode: 0644]
broadcastradio/1.1/vts/utils/include/broadcastradio-vts-utils/mock-timeout.h [new file with mode: 0644]
broadcastradio/Android.bp
camera/Android.bp
camera/common/1.0/Android.bp
camera/common/1.0/default/CameraParameters.cpp
camera/device/1.0/Android.bp
camera/device/1.0/default/Android.bp
camera/device/1.0/default/CameraDevice.cpp
camera/device/1.0/default/CameraDevice_1_0.h
camera/device/1.0/default/OWNERS [new file with mode: 0644]
camera/device/3.2/Android.bp
camera/device/3.2/default/CameraDevice.cpp
camera/device/3.2/default/CameraDeviceSession.cpp
camera/device/3.2/default/CameraDeviceSession.h
camera/device/3.2/default/CameraDevice_3_2.h
camera/device/3.2/default/OWNERS [new file with mode: 0644]
camera/device/3.3/Android.bp [new file with mode: 0644]
camera/device/3.3/ICameraDeviceSession.hal [new file with mode: 0644]
camera/device/3.3/default/Android.bp [new file with mode: 0644]
camera/device/3.3/default/CameraDevice.cpp [new file with mode: 0644]
camera/device/3.3/default/CameraDeviceSession.cpp [new file with mode: 0644]
camera/device/3.3/default/CameraDeviceSession.h [new file with mode: 0644]
camera/device/3.3/default/CameraDevice_3_3.h [new file with mode: 0644]
camera/device/3.3/default/OWNERS [new file with mode: 0644]
camera/device/3.3/default/convert.cpp [new file with mode: 0644]
camera/device/3.3/default/include/convert.h [new file with mode: 0644]
camera/device/3.3/types.hal [new file with mode: 0644]
camera/device/README.md
camera/metadata/3.2/Android.bp
camera/provider/2.4/Android.bp
camera/provider/2.4/default/Android.bp
camera/provider/2.4/default/CameraProvider.cpp
camera/provider/2.4/default/CameraProvider.h
camera/provider/2.4/default/OWNERS [new file with mode: 0644]
camera/provider/2.4/vts/OWNERS [new file with mode: 0644]
camera/provider/2.4/vts/functional/Android.bp
camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
cas/1.0/Android.bp [new file with mode: 0644]
cas/1.0/CasHal.mk [new file with mode: 0644]
cas/1.0/ICas.hal [new file with mode: 0644]
cas/1.0/ICasListener.hal [new file with mode: 0644]
cas/1.0/IDescramblerBase.hal [new file with mode: 0644]
cas/1.0/IMediaCasService.hal [new file with mode: 0644]
cas/1.0/default/Android.bp [new file with mode: 0644]
cas/1.0/default/CasImpl.cpp [new file with mode: 0644]
cas/1.0/default/CasImpl.h [new file with mode: 0644]
cas/1.0/default/DescramblerImpl.cpp [new file with mode: 0644]
cas/1.0/default/DescramblerImpl.h [new file with mode: 0644]
cas/1.0/default/FactoryLoader.h [new file with mode: 0644]
cas/1.0/default/MediaCasService.cpp [new file with mode: 0644]
cas/1.0/default/MediaCasService.h [new file with mode: 0644]
cas/1.0/default/SharedLibrary.cpp [new file with mode: 0644]
cas/1.0/default/SharedLibrary.h [new file with mode: 0644]
cas/1.0/default/TypeConvert.cpp [new file with mode: 0644]
cas/1.0/default/TypeConvert.h [new file with mode: 0644]
cas/1.0/default/android.hardware.cas@1.0-service.rc [new file with mode: 0644]
cas/1.0/default/service.cpp [new file with mode: 0644]
cas/1.0/types.hal [new file with mode: 0644]
cas/1.0/vts/functional/Android.bp [new file with mode: 0644]
cas/1.0/vts/functional/VtsHalCasV1_0TargetTest.cpp [new file with mode: 0644]
cas/Android.bp [new file with mode: 0644]
cas/native/1.0/Android.bp [new file with mode: 0644]
cas/native/1.0/IDescrambler.hal [new file with mode: 0644]
cas/native/1.0/types.hal [new file with mode: 0644]
compatibility_matrix.26.xml
compatibility_matrix.27.xml [new file with mode: 0644]
compatibility_matrix.current.xml
compatibility_matrix.legacy.xml
configstore/1.0/Android.bp
configstore/1.0/default/Android.mk
configstore/1.0/default/seccomp_policy/configstore@1.0-arm64.policy [new file with mode: 0644]
configstore/1.0/default/service.cpp
configstore/1.0/vts/functional/Android.bp
configstore/utils/Android.bp
contexthub/1.0/Android.bp
contexthub/1.0/default/Contexthub.cpp
contexthub/1.0/vts/functional/Android.bp
current.txt
drm/1.0/Android.bp
drm/1.0/default/Android.mk
drm/1.0/default/CryptoFactory.h
drm/1.0/default/CryptoPlugin.cpp
drm/1.0/default/DrmFactory.h
drm/1.0/vts/functional/Android.bp
drm/1.0/vts/functional/drm_hal_clearkey_test.cpp
drm/1.0/vts/functional/drm_hal_vendor_test.cpp
drm/Android.bp
dumpstate/1.0/Android.bp
dumpstate/1.0/vts/functional/Android.bp
gatekeeper/1.0/Android.bp
gatekeeper/1.0/vts/functional/Android.bp
gnss/1.0/Android.bp
gnss/1.0/default/GnssMeasurement.cpp
gnss/1.0/default/OWNERS [new file with mode: 0644]
gnss/1.0/vts/OWNERS [new file with mode: 0644]
gnss/1.0/vts/functional/Android.bp
graphics/allocator/2.0/Android.bp
graphics/bufferqueue/1.0/Android.bp
graphics/common/1.0/Android.bp
graphics/composer/2.1/Android.bp
graphics/composer/2.1/default/Hwc.cpp
graphics/composer/2.1/default/Hwc.h
graphics/composer/2.1/default/IComposerCommandBuffer.h
graphics/composer/2.1/vts/functional/Android.bp
graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
graphics/mapper/2.0/Android.bp
graphics/mapper/2.0/vts/functional/Android.bp
health/1.0/Android.bp
health/1.0/default/Android.bp [new file with mode: 0644]
health/1.0/default/Android.mk
health/1.0/default/libhealthd/Android.bp [new file with mode: 0644]
health/1.0/default/libhealthd/Android.mk [deleted file]
health/1.0/vts/functional/Android.bp
health/Android.bp
ir/1.0/Android.bp
ir/1.0/vts/functional/Android.bp
keymaster/3.0/Android.bp
keymaster/3.0/vts/functional/Android.bp [new file with mode: 0644]
keymaster/3.0/vts/functional/Android.mk [deleted file]
keymaster/Android.bp
light/2.0/Android.bp
light/2.0/vts/functional/Android.bp
media/1.0/Android.bp
media/omx/1.0/Android.bp
media/omx/1.0/IOmxStore.hal
media/omx/1.0/vts/functional/audio/Android.bp
media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioDecTest.cpp
media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioEncTest.cpp
media/omx/1.0/vts/functional/audio/media_audio_hidl_test_common.cpp
media/omx/1.0/vts/functional/audio/media_audio_hidl_test_common.h
media/omx/1.0/vts/functional/common/Android.bp
media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
media/omx/1.0/vts/functional/common/media_hidl_test_common.h
media/omx/1.0/vts/functional/component/Android.bp
media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp
media/omx/1.0/vts/functional/master/Android.bp
media/omx/1.0/vts/functional/master/VtsHalMediaOmxV1_0TargetMasterTest.cpp
media/omx/1.0/vts/functional/video/Android.bp
media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp
media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp
media/omx/1.0/vts/functional/video/media_video_hidl_test_common.cpp
media/omx/1.0/vts/functional/video/media_video_hidl_test_common.h
media/res/bbb_aac_stereo_128kbps_48000hz.aac [changed mode: 0755->0644]
media/res/bbb_aac_stereo_128kbps_48000hz.info [changed mode: 0755->0644]
media/res/bbb_amrwb_1ch_14kbps_16000hz.amrwb [changed mode: 0755->0644]
media/res/bbb_amrwb_1ch_14kbps_16000hz.info [changed mode: 0755->0644]
media/res/bbb_avc_176x144_300kbps_60fps.h264 [new file with mode: 0644]
media/res/bbb_avc_176x144_300kbps_60fps.info [new file with mode: 0644]
media/res/bbb_flac_stereo_680kbps_48000hz.flac [new file with mode: 0644]
media/res/bbb_flac_stereo_680kbps_48000hz.info [new file with mode: 0644]
media/res/bbb_g711alaw_1ch_8khz.info [changed mode: 0755->0644]
media/res/bbb_g711alaw_1ch_8khz.raw [changed mode: 0755->0644]
media/res/bbb_g711mulaw_1ch_8khz.info [changed mode: 0755->0644]
media/res/bbb_g711mulaw_1ch_8khz.raw [changed mode: 0755->0644]
media/res/bbb_gsm_1ch_8khz_13kbps.info [changed mode: 0755->0644]
media/res/bbb_gsm_1ch_8khz_13kbps.raw [changed mode: 0755->0644]
media/res/bbb_hevc_176x144_176kbps_60fps.hevc [new file with mode: 0644]
media/res/bbb_hevc_176x144_176kbps_60fps.info [new file with mode: 0644]
media/res/bbb_mpeg2_352x288_1mbps_60fps.info [new file with mode: 0644]
media/res/bbb_mpeg2_352x288_1mbps_60fps.m2v [new file with mode: 0644]
media/res/bbb_opus_stereo_128kbps_48000hz.info [changed mode: 0755->0644]
media/res/bbb_opus_stereo_128kbps_48000hz.opus [changed mode: 0755->0644]
media/res/bbb_raw_1ch_8khz_s32le.info [changed mode: 0755->0644]
media/res/bbb_raw_1ch_8khz_s32le.raw [changed mode: 0755->0644]
media/res/bbb_vorbis_stereo_128kbps_48000hz.info [changed mode: 0755->0644]
media/res/bbb_vorbis_stereo_128kbps_48000hz.vorbis [changed mode: 0755->0644]
media/res/bbb_vp8_176x144_240kbps_60fps.info [new file with mode: 0644]
media/res/bbb_vp8_176x144_240kbps_60fps.vp8 [new file with mode: 0644]
media/res/bbb_vp9_176x144_285kbps_60fps.info [new file with mode: 0644]
media/res/bbb_vp9_176x144_285kbps_60fps.vp9 [new file with mode: 0644]
memtrack/1.0/Android.bp
memtrack/1.0/vts/functional/Android.bp
minijail/Android.mk [new file with mode: 0644]
minijail/HardwareMinijail.cpp [new file with mode: 0644]
minijail/include/hwminijail/HardwareMinijail.h [new file with mode: 0644]
neuralnetworks/1.0/Android.bp [new file with mode: 0644]
neuralnetworks/1.0/IDevice.hal [new file with mode: 0644]
neuralnetworks/1.0/IExecutionCallback.hal [new file with mode: 0644]
neuralnetworks/1.0/IPreparedModel.hal [new file with mode: 0644]
neuralnetworks/1.0/IPreparedModelCallback.hal [new file with mode: 0644]
neuralnetworks/1.0/types.hal [new file with mode: 0644]
neuralnetworks/1.0/vts/OWNERS [new file with mode: 0644]
neuralnetworks/1.0/vts/functional/Android.bp [new file with mode: 0644]
neuralnetworks/1.0/vts/functional/Callbacks.cpp [new file with mode: 0644]
neuralnetworks/1.0/vts/functional/Callbacks.h [new file with mode: 0644]
neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp [new file with mode: 0644]
neuralnetworks/1.0/vts/functional/Models.cpp [new file with mode: 0644]
neuralnetworks/1.0/vts/functional/Models.h [new file with mode: 0644]
neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.cpp [new file with mode: 0644]
neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.h [new file with mode: 0644]
neuralnetworks/Android.bp [new file with mode: 0644]
nfc/1.0/Android.bp
nfc/1.0/vts/functional/Android.bp
oemlock/1.0/Android.bp
oemlock/1.0/vts/functional/Android.bp
power/1.0/Android.bp
power/1.0/vts/functional/Android.bp
power/1.1/Android.bp
power/1.1/default/Power.cpp [deleted file]
power/1.1/default/Power.h [deleted file]
power/1.1/default/android.hardware.power@1.1-service.rc [deleted file]
power/1.1/default/service.cpp [deleted file]
power/1.1/vts/functional/Android.bp
power/Android.bp
radio/1.0/Android.bp
radio/1.0/IRadioResponse.hal
radio/1.0/types.hal
radio/1.0/vts/OWNERS [new file with mode: 0644]
radio/1.0/vts/functional/Android.bp
radio/1.0/vts/functional/radio_hidl_hal_misc.cpp
radio/1.0/vts/functional/radio_hidl_hal_voice.cpp
radio/1.1/Android.bp
radio/1.1/IRadioResponse.hal
radio/1.1/vts/OWNERS [new file with mode: 0644]
radio/1.1/vts/functional/Android.bp
radio/deprecated/1.0/Android.bp
renderscript/1.0/Android.bp
renderscript/1.0/default/Device.cpp
renderscript/1.0/vts/functional/Android.bp
renderscript/1.0/vts/functional/VtsHalRenderscriptV1_0TargetTest.cpp
sensors/1.0/Android.bp
sensors/1.0/default/Android.bp
sensors/1.0/default/android.hardware.sensors@1.0-service.rc
sensors/1.0/vts/functional/Android.bp
soundtrigger/2.0/Android.bp
soundtrigger/2.0/default/OWNERS [new file with mode: 0644]
soundtrigger/2.0/vts/functional/Android.bp
tests/Android.bp
tests/bar/1.0/.hidl_for_test [new file with mode: 0644]
tests/bar/1.0/Android.bp
tests/baz/1.0/.hidl_for_test [new file with mode: 0644]
tests/baz/1.0/Android.bp
tests/expression/1.0/.hidl_for_test [new file with mode: 0644]
tests/expression/1.0/Android.bp
tests/extension/light/2.0/.hidl_for_test [new file with mode: 0644]
tests/extension/light/2.0/Android.bp
tests/foo/1.0/.hidl_for_test [new file with mode: 0644]
tests/foo/1.0/Android.bp
tests/hash/1.0/.hidl_for_test [new file with mode: 0644]
tests/hash/1.0/Android.bp
tests/inheritance/1.0/.hidl_for_test [new file with mode: 0644]
tests/inheritance/1.0/Android.bp
tests/libhwbinder/1.0/.hidl_for_test [new file with mode: 0644]
tests/libhwbinder/1.0/Android.bp
tests/libhwbinder/1.0/default/Android.bp
tests/libhwbinder/aidl/.hidl_for_test [new file with mode: 0644]
tests/memory/1.0/.hidl_for_test [new file with mode: 0644]
tests/memory/1.0/Android.bp
tests/msgq/1.0/.hidl_for_test [new file with mode: 0644]
tests/msgq/1.0/Android.bp
tests/multithread/1.0/.hidl_for_test [new file with mode: 0644]
tests/multithread/1.0/Android.bp [new file with mode: 0644]
tests/multithread/1.0/Android.mk [new file with mode: 0644]
tests/multithread/1.0/IMultithread.hal [new file with mode: 0644]
tests/multithread/1.0/default/Android.bp [new file with mode: 0644]
tests/multithread/1.0/default/Multithread.cpp [new file with mode: 0644]
tests/multithread/1.0/default/Multithread.h [new file with mode: 0644]
tests/pointer/1.0/.hidl_for_test [new file with mode: 0644]
tests/pointer/1.0/Android.bp
tetheroffload/config/1.0/Android.bp
tetheroffload/config/1.0/vts/functional/Android.bp
tetheroffload/config/1.0/vts/functional/VtsHalTetheroffloadConfigV1_0TargetTest.cpp
tetheroffload/control/1.0/Android.bp
tetheroffload/control/1.0/vts/functional/Android.bp
tetheroffload/control/1.0/vts/functional/VtsHalTetheroffloadControlV1_0TargetTest.cpp
thermal/1.0/Android.bp
thermal/1.0/vts/functional/Android.bp
thermal/1.1/Android.bp [new file with mode: 0644]
thermal/1.1/Android.mk [new file with mode: 0644]
thermal/1.1/IThermal.hal [new file with mode: 0644]
thermal/1.1/IThermalCallback.hal [new file with mode: 0644]
thermal/1.1/vts/functional/Android.bp [new file with mode: 0644]
thermal/1.1/vts/functional/VtsHalThermalV1_1TargetTest.cpp [new file with mode: 0644]
thermal/Android.bp
tv/cec/1.0/Android.bp
tv/input/1.0/Android.bp
tv/input/1.0/vts/functional/Android.bp
usb/1.0/Android.bp
usb/1.0/vts/functional/Android.bp
usb/1.1/Android.bp
usb/1.1/vts/functional/Android.bp
vibrator/1.0/Android.bp
vibrator/1.0/vts/functional/Android.bp
vibrator/1.1/Android.bp
vibrator/1.1/vts/functional/Android.bp
vr/1.0/Android.bp
vr/1.0/vts/functional/Android.bp
weaver/1.0/Android.bp
weaver/1.0/vts/functional/Android.bp
wifi/1.0/Android.bp
wifi/1.0/README-NAN.md [new file with mode: 0644]
wifi/1.0/types.hal
wifi/1.0/vts/functional/Android.bp
wifi/1.1/Android.bp
wifi/1.1/default/OWNERS [new file with mode: 0644]
wifi/1.1/default/hidl_return_util.h
wifi/1.1/default/wifi.cpp
wifi/1.1/default/wifi.h
wifi/1.1/default/wifi_legacy_hal.cpp
wifi/1.1/default/wifi_legacy_hal.h
wifi/1.1/vts/functional/Android.bp
wifi/1.1/vts/functional/OWNERS [new file with mode: 0644]
wifi/Android.bp
wifi/offload/1.0/Android.bp
wifi/offload/1.0/vts/functional/Android.bp
wifi/supplicant/1.0/Android.bp
wifi/supplicant/1.0/vts/functional/Android.bp [new file with mode: 0644]
wifi/supplicant/1.0/vts/functional/Android.mk [deleted file]

index 79e8609..7ae00b6 100644 (file)
@@ -9,3 +9,32 @@ cc_defaults {
         "-Werror",
     ],
 }
+
+// VTS tests must link to HAL definition libraries statically.
+cc_defaults {
+    name: "VtsHalTargetTestDefaults",
+    defaults: ["hidl_defaults"],
+
+    // Lists all dependencies that can *not* be expected on the device.
+    static_libs: [
+        "VtsHalHidlTargetTestBase",
+    ],
+    group_static_libs: true,
+
+    // Lists all system dependencies that can be expected on the device.
+    shared_libs: [
+        "libbase",
+        // All the following are dependencies of any HAL definition library.
+        "libcutils",
+        "liblog",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+    ],
+    cflags: [
+        "-O0",
+        "-g",
+    ],
+
+}
index 14616e4..dd4cee0 100644 (file)
@@ -56,4 +56,10 @@ $(call add-clean-step, rm -rf $(OUT)/soong/.intermediates/)
 $(call add-clean-step, rm -rf $(OUT_DIR)/soong/.intermediates/hardware/interfaces/)
 $(call add-clean-step, rm -rf $(OUT_DIR)/soong/.intermediates/hardware/interfaces/)
 $(call add-clean-step, find $(PRODUCT_OUT)/system $(PRODUCT_OUT)/vendor -type f -name "android\.hardware\.configstore*" -print0 | xargs -0 rm -f)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/hw/android.hardware.automotive*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/hw/android.hardware.automotive*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib64/hw/android.hardware.automotive*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/init/android.hardware.automotive*)
 $(call add-clean-step, find $(PRODUCT_OUT)/system $(PRODUCT_OUT)/vendor -type f -name "android\.hardware\.configstore\@1\.1*" -print0 | xargs -0 rm -f)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/android.hardware.tests*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/vndk/android.hardware.tests*)
diff --git a/OWNERS b/OWNERS
new file mode 100644 (file)
index 0000000..9fbcb47
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1,5 @@
+elsk@google.com
+maco@google.com
+malchev@google.com
+smoreland@google.com
+yim@google.com  # vts tests
index b193c8f..cdaaa15 100644 (file)
@@ -81,13 +81,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.audio@2.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.audio@2.0_genc++"],
     generated_headers: ["android.hardware.audio@2.0_genc++_headers"],
     export_generated_headers: ["android.hardware.audio@2.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index 621853c..8dec482 100644 (file)
@@ -84,8 +84,4 @@ else
 LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
 endif
 
-ifeq ($(TARGET_USES_BCRADIO_FUTURE_FEATURES),true)
-LOCAL_CFLAGS += -DTARGET_USES_BCRADIO_FUTURE_FEATURES
-endif
-
 include $(BUILD_EXECUTABLE)
diff --git a/audio/2.0/default/OWNERS b/audio/2.0/default/OWNERS
new file mode 100644 (file)
index 0000000..6fdc97c
--- /dev/null
@@ -0,0 +1,3 @@
+elaurent@google.com
+krocard@google.com
+mnaganov@google.com
index 82f05a7..e29af53 100644 (file)
@@ -49,6 +49,13 @@ using ::android::sp;
 struct Stream : public IStream, public ParametersUtil {
     explicit Stream(audio_stream_t* stream);
 
+    /** 1GiB is the maximum buffer size the HAL client is allowed to request.
+     * This value has been chosen to be under SIZE_MAX and still big enough
+     * for all audio use case.
+     * Keep private for 2.0, put in .hal in 2.1
+     */
+    static constexpr uint32_t MAX_BUFFER_SIZE = 2 << 30 /* == 1GiB */;
+
     // Methods from ::android::hardware::audio::V2_0::IStream follow.
     Return<uint64_t> getFrameSize()  override;
     Return<uint64_t> getFrameCount()  override;
index b81cbb9..9c933a9 100644 (file)
@@ -347,14 +347,10 @@ Return<void> StreamIn::prepareForReading(uint32_t frameSize,
         sendError(Result::INVALID_ARGUMENTS);
         return Void();
     }
-    // A message queue asserts if it can not handle the requested buffer,
-    // thus the client has to guess the maximum size it can handle
-    // Choose an arbitrary margin for the overhead of a message queue
-    size_t metadataOverhead = 100000;
-    if (frameSize >
-        (std::numeric_limits<size_t>::max() - metadataOverhead) / framesCount) {
-        ALOGE("Buffer too big: %u*%u bytes can not fit in a message queue",
-              frameSize, framesCount);
+
+    if (frameSize > Stream::MAX_BUFFER_SIZE / framesCount) {
+        ALOGE("Buffer too big: %u*%u bytes > MAX_BUFFER_SIZE (%u)", frameSize, framesCount,
+              Stream::MAX_BUFFER_SIZE);
         sendError(Result::INVALID_ARGUMENTS);
         return Void();
     }
index 290d0b1..22dcd0c 100644 (file)
@@ -323,14 +323,9 @@ Return<void> StreamOut::prepareForWriting(uint32_t frameSize,
         sendError(Result::INVALID_ARGUMENTS);
         return Void();
     }
-    // A message queue asserts if it can not handle the requested buffer,
-    // thus the client has to guess the maximum size it can handle
-    size_t metadataOverhead =
-        100000;  // Arbitrary margin for the overhead of a message queue
-    if (frameSize >
-        (std::numeric_limits<size_t>::max() - metadataOverhead) / framesCount) {
-        ALOGE("Buffer too big: %u*%u bytes can not fit in a message queue",
-              frameSize, framesCount);
+    if (frameSize > Stream::MAX_BUFFER_SIZE / framesCount) {
+        ALOGE("Buffer too big: %u*%u bytes > MAX_BUFFER_SIZE (%u)", frameSize, framesCount,
+              Stream::MAX_BUFFER_SIZE);
         sendError(Result::INVALID_ARGUMENTS);
         return Void();
     }
index 7f28d7d..a215108 100644 (file)
@@ -21,8 +21,6 @@
 #include <android/hardware/audio/2.0/IDevicesFactory.h>
 #include <android/hardware/audio/effect/2.0/IEffectsFactory.h>
 #include <android/hardware/soundtrigger/2.0/ISoundTriggerHw.h>
-#include <android/hardware/broadcastradio/1.0/IBroadcastRadioFactory.h>
-#include <android/hardware/broadcastradio/1.1/IBroadcastRadioFactory.h>
 
 using android::hardware::configureRpcThreadpool;
 using android::hardware::joinRpcThreadpool;
@@ -32,13 +30,6 @@ using android::hardware::audio::effect::V2_0::IEffectsFactory;
 using android::hardware::audio::V2_0::IDevicesFactory;
 using android::hardware::soundtrigger::V2_0::ISoundTriggerHw;
 using android::hardware::registerPassthroughServiceImplementation;
-namespace broadcastradio = android::hardware::broadcastradio;
-
-#ifdef TARGET_USES_BCRADIO_FUTURE_FEATURES
-static const bool useBroadcastRadioFutureFeatures = true;
-#else
-static const bool useBroadcastRadioFutureFeatures = false;
-#endif
 
 using android::OK;
 
@@ -49,17 +40,9 @@ int main(int /* argc */, char* /* argv */ []) {
     LOG_ALWAYS_FATAL_IF(status != OK, "Error while registering audio service: %d", status);
     status = registerPassthroughServiceImplementation<IEffectsFactory>();
     LOG_ALWAYS_FATAL_IF(status != OK, "Error while registering audio effects service: %d", status);
-    // Soundtrigger and FM radio might be not present.
+    // Soundtrigger might be not present.
     status = registerPassthroughServiceImplementation<ISoundTriggerHw>();
     ALOGE_IF(status != OK, "Error while registering soundtrigger service: %d", status);
-    if (useBroadcastRadioFutureFeatures) {
-        status = registerPassthroughServiceImplementation<
-            broadcastradio::V1_1::IBroadcastRadioFactory>();
-    } else {
-        status = registerPassthroughServiceImplementation<
-            broadcastradio::V1_0::IBroadcastRadioFactory>();
-    }
-    ALOGE_IF(status != OK, "Error while registering fm radio service: %d", status);
     joinRpcThreadpool();
     return status;
 }
index b289709..f3b2ca7 100644 (file)
 
 cc_test {
     name: "VtsHalAudioV2_0TargetTest",
-    defaults: ["hidl_defaults"],
-    srcs: ["AudioPrimaryHidlHalTest.cpp",
-           "ValidateAudioConfiguration.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libhidlbase",
-        "libhidltransport",
-        "libutils",
-        "libcutils",
-        "libxml2",
-        "android.hardware.audio@2.0",
-        "android.hardware.audio.common@2.0",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "AudioPrimaryHidlHalTest.cpp",
+        "ValidateAudioConfiguration.cpp"
     ],
     static_libs: [
-        "VtsHalHidlTargetTestBase",
         "android.hardware.audio.common.test.utility",
+        "android.hardware.audio@2.0",
+        "android.hardware.audio.common@2.0",
+        "libxml2",
     ],
-    cflags: [
-        "-O0",
-        "-g",
-        "-Wall",
-        "-Wextra",
-        "-Werror",
+    shared_libs: [
+        "libicuuc",
     ],
 }
index 6688c27..eec2b10 100644 (file)
@@ -1004,34 +1004,27 @@ TEST_P(InputStreamTest, SetGain) {
         "InputStream::setGain");
 }
 
-static void testPrepareForReading(IStreamIn* stream, uint32_t frameSize, uint32_t framesCount,
-                                  bool allowSucceed) {
+static void testPrepareForReading(IStreamIn* stream, uint32_t frameSize,
+                                  uint32_t framesCount) {
     Result res;
-    // Ignore output parameters.
+    // Ignore output parameters as the call should fail
     ASSERT_OK(stream->prepareForReading(
         frameSize, framesCount,
         [&res](auto r, auto&, auto&, auto&, auto&) { res = r; }));
-    if (allowSucceed) {
-        auto status = {
-            Result::INVALID_ARGUMENTS, Result::OK,
-        };
-        EXPECT_RESULT(status, res);
-    } else {
-        EXPECT_RESULT(Result::INVALID_ARGUMENTS, res);
-    };
+    EXPECT_RESULT(Result::INVALID_ARGUMENTS, res);
 }
 
 TEST_P(InputStreamTest, PrepareForReadingWithZeroBuffer) {
     doc::test(
         "Preparing a stream for reading with a 0 sized buffer should fail");
-    testPrepareForReading(stream.get(), 0, 0, false /*allowSucceed*/);
+    testPrepareForReading(stream.get(), 0, 0);
 }
 
 TEST_P(InputStreamTest, PrepareForReadingWithHugeBuffer) {
     doc::test(
         "Preparing a stream for reading with a 2^32 sized buffer should fail");
-    testPrepareForReading(stream.get(), 1, std::numeric_limits<uint32_t>::max(),
-                          false /*allowSucceed*/);
+    testPrepareForReading(stream.get(), 1,
+                          std::numeric_limits<uint32_t>::max());
 }
 
 TEST_P(InputStreamTest, PrepareForReadingCheckOverflow) {
@@ -1039,8 +1032,7 @@ TEST_P(InputStreamTest, PrepareForReadingCheckOverflow) {
         "Preparing a stream for reading with a overflowing sized buffer should "
         "fail");
     auto uintMax = std::numeric_limits<uint32_t>::max();
-    // In O, the test fails for 32-bit HAL, and succeeds for 64-bit HAL.
-    testPrepareForReading(stream.get(), uintMax, uintMax, true /*allowSucceed*/);
+    testPrepareForReading(stream.get(), uintMax, uintMax);
 }
 
 TEST_P(InputStreamTest, GetInputFramesLost) {
@@ -1080,34 +1072,27 @@ TEST_P(OutputStreamTest, setVolume) {
         "setVolume");
 }
 
-static void testPrepareForWriting(IStreamOut* stream, uint32_t frameSize, uint32_t framesCount,
-                                  bool allowSucceed) {
+static void testPrepareForWriting(IStreamOut* stream, uint32_t frameSize,
+                                  uint32_t framesCount) {
     Result res;
-    // Ignore output parameters.
+    // Ignore output parameters as the call should fail
     ASSERT_OK(stream->prepareForWriting(
         frameSize, framesCount,
         [&res](auto r, auto&, auto&, auto&, auto&) { res = r; }));
-    if (allowSucceed) {
-        auto status = {
-            Result::INVALID_ARGUMENTS, Result::OK,
-        };
-        EXPECT_RESULT(status, res);
-    } else {
-        EXPECT_RESULT(Result::INVALID_ARGUMENTS, res);
-    };
+    EXPECT_RESULT(Result::INVALID_ARGUMENTS, res);
 }
 
 TEST_P(OutputStreamTest, PrepareForWriteWithZeroBuffer) {
     doc::test(
         "Preparing a stream for writing with a 0 sized buffer should fail");
-    testPrepareForWriting(stream.get(), 0, 0, false /*allowSucceed*/);
+    testPrepareForWriting(stream.get(), 0, 0);
 }
 
 TEST_P(OutputStreamTest, PrepareForWriteWithHugeBuffer) {
     doc::test(
         "Preparing a stream for writing with a 2^32 sized buffer should fail");
-    testPrepareForWriting(stream.get(), 1, std::numeric_limits<uint32_t>::max(),
-                          false /*allowSucceed*/);
+    testPrepareForWriting(stream.get(), 1,
+                          std::numeric_limits<uint32_t>::max());
 }
 
 TEST_P(OutputStreamTest, PrepareForWritingCheckOverflow) {
@@ -1115,8 +1100,7 @@ TEST_P(OutputStreamTest, PrepareForWritingCheckOverflow) {
         "Preparing a stream for writing with a overflowing sized buffer should "
         "fail");
     auto uintMax = std::numeric_limits<uint32_t>::max();
-    // In O, the test fails for 32-bit HAL, and succeeds for 64-bit HAL.
-    testPrepareForWriting(stream.get(), uintMax, uintMax, true /*allowSucceed*/);
+    testPrepareForWriting(stream.get(), uintMax, uintMax);
 }
 
 struct Capability {
index 39db15a..0007f44 100644 (file)
@@ -32,13 +32,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.audio.common@2.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.audio.common@2.0_genc++"],
     generated_headers: ["android.hardware.audio.common@2.0_genc++_headers"],
     export_generated_headers: ["android.hardware.audio.common@2.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index 0486a5c..104bbac 100644 (file)
@@ -16,6 +16,9 @@
 cc_library_shared {
     name: "android.hardware.audio.common@2.0-util",
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     srcs: [
         "EffectMap.cpp",
         "HidlUtils.cpp",
diff --git a/audio/common/2.0/default/OWNERS b/audio/common/2.0/default/OWNERS
new file mode 100644 (file)
index 0000000..6fdc97c
--- /dev/null
@@ -0,0 +1,3 @@
+elaurent@google.com
+krocard@google.com
+mnaganov@google.com
diff --git a/audio/common/test/utility/OWNERS b/audio/common/test/utility/OWNERS
new file mode 100644 (file)
index 0000000..6fdc97c
--- /dev/null
@@ -0,0 +1,3 @@
+elaurent@google.com
+krocard@google.com
+mnaganov@google.com
index a004263..fd667f0 100644 (file)
@@ -130,13 +130,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.audio.effect@2.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.audio.effect@2.0_genc++"],
     generated_headers: ["android.hardware.audio.effect@2.0_genc++_headers"],
     export_generated_headers: ["android.hardware.audio.effect@2.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/audio/effect/2.0/default/OWNERS b/audio/effect/2.0/default/OWNERS
new file mode 100644 (file)
index 0000000..6fdc97c
--- /dev/null
@@ -0,0 +1,3 @@
+elaurent@google.com
+krocard@google.com
+mnaganov@google.com
index 8a370cd..7b421cb 100644 (file)
 
 cc_test {
     name: "VtsHalAudioEffectV2_0TargetTest",
-    defaults: ["hidl_defaults"],
-    srcs: ["VtsHalAudioEffectV2_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "VtsHalAudioEffectV2_0TargetTest.cpp",
+        "ValidateAudioEffectsConfiguration.cpp"
+    ],
+    static_libs: [
+        "android.hardware.audio.common.test.utility",
         "android.hardware.audio.common@2.0",
         "android.hardware.audio.effect@2.0",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
+        "libxml2",
     ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
+    shared_libs: [
+        "libicuuc",
     ],
 }
diff --git a/audio/effect/2.0/vts/functional/ValidateAudioEffectsConfiguration.cpp b/audio/effect/2.0/vts/functional/ValidateAudioEffectsConfiguration.cpp
new file mode 100644 (file)
index 0000000..fdc1347
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <unistd.h>
+
+#include "utility/ValidateXml.h"
+
+TEST(CheckConfig, audioEffectsConfigurationValidation) {
+    RecordProperty("description",
+                   "Verify that the effects configuration file is valid according to the schema");
+    const char* xmlConfigFile = "/vendor/etc/audio_effects.xml";
+    // Not every device uses XML configuration, so only validate
+    // if the XML configuration actually exists.
+    if (access(xmlConfigFile, F_OK) == 0) {
+        ASSERT_VALID_XML(xmlConfigFile, "/data/local/tmp/audio_effects_conf_V2_0.xsd");
+    }
+}
diff --git a/audio/effect/2.0/xml/audio_effects_conf_V2_0.xsd b/audio/effect/2.0/xml/audio_effects_conf_V2_0.xsd
new file mode 100644 (file)
index 0000000..ca6a7dc
--- /dev/null
@@ -0,0 +1,249 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+           targetNamespace="http://schemas.android.com/audio/audio_effects_conf/v2_0"
+           xmlns:aec="http://schemas.android.com/audio/audio_effects_conf/v2_0"
+           elementFormDefault="qualified">
+
+  <!-- Simple types -->
+  <xs:simpleType name="versionType">
+    <xs:restriction base="xs:decimal">
+      <xs:enumeration value="2.0"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="uuidType">
+    <xs:restriction base="xs:string">
+      <xs:pattern value="[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="streamInputType">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="mic"/>
+      <xs:enumeration value="voice_uplink"/>
+      <xs:enumeration value="voice_downlink"/>
+      <xs:enumeration value="voice_call"/>
+      <xs:enumeration value="camcorder"/>
+      <xs:enumeration value="voice_recognition"/>
+      <xs:enumeration value="voice_communication"/>
+      <xs:enumeration value="unprocessed"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="streamOutputType">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="voice_call"/>
+      <xs:enumeration value="system"/>
+      <xs:enumeration value="ring"/>
+      <xs:enumeration value="music"/>
+      <xs:enumeration value="alarm"/>
+      <xs:enumeration value="notification"/>
+      <xs:enumeration value="bluetooth_sco"/>
+      <xs:enumeration value="enforced_audible"/>
+      <xs:enumeration value="dtmf"/>
+      <xs:enumeration value="tts"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="relativePathType">
+    <xs:restriction base="xs:string">
+      <xs:pattern value="[^/].*"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <!-- Complex types -->
+  <xs:complexType name="librariesType">
+    <xs:annotation>
+      <xs:documentation xml:lang="en">
+        List of effect libraries to load. Each library element must have "name" and
+        "path" attributes. The latter is giving the path of the library .so file
+        relative to the standard effect folders: /(vendor|odm|system)/lib(64)?/soundfx/
+
+        Example for a library in "/vendor/lib/soundfx/lib.so":
+        <library name="name" path="lib.so"/>
+
+      </xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element name="library" minOccurs="0" maxOccurs="unbounded">
+        <xs:complexType>
+          <xs:attribute name="name" type="xs:string" use="required"/>
+          <xs:attribute name="path" type="aec:relativePathType" use="required"/>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:complexType name="effectImplType">
+    <xs:attribute name="library" type="xs:string" use="required"/>
+    <xs:attribute name="uuid" type="aec:uuidType" use="required"/>
+  </xs:complexType>
+  <xs:complexType name="effectType">
+    <xs:complexContent>
+      <xs:extension base="aec:effectImplType">
+        <xs:attribute name="name" type="xs:string" use="required"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="effectProxyType">
+    <xs:complexContent>
+      <xs:extension base="aec:effectType">
+        <xs:sequence>
+          <xs:element name="libsw" type="aec:effectImplType"/>
+          <xs:element name="libhw" type="aec:effectImplType"/>
+        </xs:sequence>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="effectsType">
+    <xs:annotation>
+      <xs:documentation xml:lang="en">
+        List of effects to load. Each effect element must contain "name",
+        "library", and "uuid" attrs. The value of the "library" attr must
+        correspond to the name of a "library" element. The name of the effect
+        element is indicative, only the value of the "uuid" element designates
+        the effect for the audio framework.  The uuid is the implementation
+        specific UUID as specified by the effect vendor. This is not the generic
+        effect type UUID.
+
+        For effect proxy implementations, SW and HW implemetations of the effect
+        can be specified.
+
+        Example:
+
+        <effect name="name" library="lib" uuid="uuuu"/>
+        <effectProxy name="proxied" library="proxy" uuid="xxxx">
+            <libsw library="sw_bundle" uuid="yyyy"/>
+            <libhw library="offload_bundle" uuid="zzzz"/>
+        </effectProxy>
+
+      </xs:documentation>
+    </xs:annotation>
+    <xs:choice maxOccurs="unbounded">
+      <xs:element name="effect" type="aec:effectType" minOccurs="0" maxOccurs="unbounded"/>
+      <xs:element name="effectProxy" type="aec:effectProxyType" minOccurs="0" maxOccurs="unbounded"/>
+    </xs:choice>
+  </xs:complexType>
+  <xs:complexType name="streamProcessingType">
+    <xs:sequence>
+      <xs:element name="apply" minOccurs="0" maxOccurs="unbounded">
+        <xs:complexType>
+          <xs:attribute name="effect" type="xs:string" use="required"/>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:complexType name="streamPreprocessType">
+    <xs:annotation>
+      <xs:documentation xml:lang="en">
+        Audio preprocessing configuration. The processing configuration consists
+        of a list of elements each describing processing settings for a given
+        input stream. Valid input stream types are listed in "streamInputType".
+
+        Each stream element contains a list of "apply" elements. The value of the
+        "effect" attr must correspond to the name of an "effect" element.
+
+        Example:
+
+        <stream type="voice_communication">
+            <apply effect="effect1"/>
+            <apply effect="effect2"/>
+        </stream>
+
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexContent>
+      <xs:extension base="aec:streamProcessingType">
+        <xs:attribute name="type" type="aec:streamInputType" use="required"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="streamPostprocessType">
+    <xs:annotation>
+      <xs:documentation xml:lang="en">
+        Audio postprocessing configuration. The processing configuration consists
+        of a list of elements each describing processing settings for a given
+        output stream. Valid output stream types are listed in "streamOutputType".
+
+        Each stream element contains a list of "apply" elements. The value of the
+        "effect" attr must correspond to the name of an "effect" element.
+
+        Example:
+
+        <stream type="music">
+            <apply effect="effect1"/>
+        </stream>
+
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexContent>
+      <xs:extension base="aec:streamProcessingType">
+        <xs:attribute name="type" type="aec:streamOutputType" use="required"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+
+  <!-- Root element -->
+  <xs:element name="audio_effects_conf">
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element name="libraries" type="aec:librariesType"/>
+        <xs:element name="effects" type="aec:effectsType"/>
+        <xs:element name="postprocess" minOccurs="0" maxOccurs="1">
+          <xs:complexType>
+            <xs:sequence>
+              <xs:element name="stream" type="aec:streamPostprocessType" minOccurs="0" maxOccurs="unbounded"/>
+            </xs:sequence>
+          </xs:complexType>
+        </xs:element>
+        <xs:element name="preprocess" minOccurs="0" maxOccurs="1">
+          <xs:complexType>
+            <xs:sequence>
+              <xs:element name="stream" type="aec:streamPreprocessType" minOccurs="0" maxOccurs="unbounded"/>
+            </xs:sequence>
+          </xs:complexType>
+        </xs:element>
+      </xs:sequence>
+      <xs:attribute name="version" type="aec:versionType" use="required"/>
+    </xs:complexType>
+
+    <!-- Keys and references -->
+    <xs:key name="libraryName">
+      <xs:selector xpath="aec:libraries/aec:library"/>
+      <xs:field xpath="@name"/>
+    </xs:key>
+    <xs:keyref name="libraryNameRef1" refer="aec:libraryName">
+      <xs:selector xpath="aec:effects/aec:effect"/>
+      <xs:field xpath="@library"/>
+    </xs:keyref>
+    <xs:keyref name="libraryNameRef2" refer="aec:libraryName">
+      <xs:selector xpath="aec:effects/aec:effect/aec:libsw"/>
+      <xs:field xpath="@library"/>
+    </xs:keyref>
+    <xs:keyref name="libraryNameRef3" refer="aec:libraryName">
+      <xs:selector xpath="aec:effects/aec:effect/aec:libhw"/>
+      <xs:field xpath="@library"/>
+    </xs:keyref>
+    <xs:key name="effectName">
+      <xs:selector xpath="aec:effects/aec:effect"/>
+      <xs:field xpath="@name"/>
+    </xs:key>
+    <xs:keyref name="effectNamePreRef" refer="aec:effectName">
+      <xs:selector xpath="aec:preprocess/aec:stream/aec:apply"/>
+      <xs:field xpath="@effect"/>
+    </xs:keyref>
+    <xs:keyref name="effectNamePostRef" refer="aec:effectName">
+      <xs:selector xpath="aec:postprocess/aec:stream/aec:apply"/>
+      <xs:field xpath="@effect"/>
+    </xs:keyref>
+  </xs:element>
+</xs:schema>
index be58829..8cde817 100644 (file)
@@ -1,7 +1,9 @@
 // This is an autogenerated file, do not edit.
 subdirs = [
     "evs/1.0",
+    "evs/1.0/default",
     "evs/1.0/vts/functional",
     "vehicle/2.0",
-    "vehicle/2.1",
+    "vehicle/2.0/default",
+    "vehicle/2.0/default/impl/vhal_v2_0/proto",
 ]
index 9ca97a7..7ae2231 100644 (file)
@@ -60,13 +60,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.automotive.evs@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.automotive.evs@1.0_genc++"],
     generated_headers: ["android.hardware.automotive.evs@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.automotive.evs@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/automotive/evs/1.0/default/Android.bp b/automotive/evs/1.0/default/Android.bp
new file mode 100644 (file)
index 0000000..2574e86
--- /dev/null
@@ -0,0 +1,31 @@
+cc_binary {
+    name: "android.hardware.automotive.evs@1.0-service",
+    defaults: ["hidl_defaults"],
+    proprietary: true,
+    relative_install_path: "hw",
+    srcs: [
+        "service.cpp",
+        "EvsCamera.cpp",
+        "EvsEnumerator.cpp",
+        "EvsDisplay.cpp"
+    ],
+    init_rc: ["android.hardware.automotive.evs@1.0-service.rc"],
+
+    shared_libs: [
+        "android.hardware.automotive.evs@1.0",
+        "libui",
+        "libbase",
+        "libbinder",
+        "libcutils",
+        "libhardware",
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libutils",
+    ],
+
+    cflags: [
+        "-O0",
+        "-g",
+    ],
+}
diff --git a/automotive/evs/1.0/default/Android.mk b/automotive/evs/1.0/default/Android.mk
deleted file mode 100644 (file)
index 0ee7071..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-LOCAL_PATH:=$(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hardware.automotive.evs@1.0-service
-LOCAL_INIT_RC := android.hardware.automotive.evs@1.0-service.rc
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_VENDOR_MODULE := true
-
-LOCAL_SRC_FILES := \
-    service.cpp \
-    EvsCamera.cpp \
-    EvsEnumerator.cpp \
-    EvsDisplay.cpp \
-
-LOCAL_SHARED_LIBRARIES := \
-    android.hardware.automotive.evs@1.0 \
-    libui \
-    libbase \
-    libbinder \
-    libcutils \
-    libhardware \
-    libhidlbase \
-    libhidltransport \
-    liblog \
-    libutils \
-
-LOCAL_CFLAGS := -O0 -g
-
-include $(BUILD_EXECUTABLE)
index e86e9bc..555ff5b 100644 (file)
 //
 
 cc_test {
-    name: "VtsEvsV1_0Target",
+    name: "VtsHalEvsV1_0Target",
 
     srcs: [
-        "VtsEvsV1_0TargetTest.cpp",
+        "VtsHalEvsV1_0TargetTest.cpp",
         "FrameHandler.cpp",
         "FormatConvert.cpp"
     ],
@@ -43,4 +43,3 @@ cc_test {
         "-g",
     ],
 }
-
 #define LOG_TAG "VtsHalEvsTest"
 
 
-// TODO:  How should we configure these values to target appropriate hardware?
-const static char kEnumeratorName[]  = "EvsEnumeratorHw-Mock";
+// Note:  We have't got a great way to indicate which target
+// should be tested, so we'll leave the interface served by the
+// default (mock) EVS driver here for easy reference.  All
+// actual EVS drivers should serve on the EvsEnumeratorHw name,
+// however, so the code is checked in that way.
+//const static char kEnumeratorName[]  = "EvsEnumeratorHw-Mock";
+const static char kEnumeratorName[]  = "EvsEnumeratorHw";
 
 
 // These values are called out in the EVS design doc (as of Mar 8, 2017)
@@ -474,4 +479,4 @@ TEST_F(EvsHidlTest, CameraToDisplayRoundTrip) {
 
     // Explicitly release the display
     pEnumerator->closeDisplay(pDisplay);
-}
\ No newline at end of file
+}
index e21bef0..879fe0d 100644 (file)
@@ -46,13 +46,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.automotive.vehicle@2.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.automotive.vehicle@2.0_genc++"],
     generated_headers: ["android.hardware.automotive.vehicle@2.0_genc++_headers"],
     export_generated_headers: ["android.hardware.automotive.vehicle@2.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index eb05f35..5919487 100644 (file)
@@ -17,6 +17,177 @@ LOCAL_JAVA_LIBRARIES := \
 
 
 #
+# Build types.hal (DiagnosticFloatSensorIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/DiagnosticFloatSensorIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.DiagnosticFloatSensorIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (DiagnosticIntegerSensorIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/DiagnosticIntegerSensorIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.DiagnosticIntegerSensorIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2CommonIgnitionMonitors)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Obd2CommonIgnitionMonitors.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.Obd2CommonIgnitionMonitors
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2CompressionIgnitionMonitors)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Obd2CompressionIgnitionMonitors.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.Obd2CompressionIgnitionMonitors
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2FuelSystemStatus)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Obd2FuelSystemStatus.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.Obd2FuelSystemStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2FuelType)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Obd2FuelType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.Obd2FuelType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2IgnitionMonitorKind)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Obd2IgnitionMonitorKind.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.Obd2IgnitionMonitorKind
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2SecondaryAirStatus)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Obd2SecondaryAirStatus.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.Obd2SecondaryAirStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2SparkIgnitionMonitors)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Obd2SparkIgnitionMonitors.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.Obd2SparkIgnitionMonitors
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
 # Build types.hal (StatusCode)
 #
 GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/StatusCode.java
@@ -910,6 +1081,139 @@ $(GEN): $(LOCAL_PATH)/types.hal
 LOCAL_GENERATED_SOURCES += $(GEN)
 
 #
+# Build types.hal (VmsAvailabilityStateIntegerValuesIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VmsAvailabilityStateIntegerValuesIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.VmsAvailabilityStateIntegerValuesIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VmsBaseMessageIntegerValuesIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VmsBaseMessageIntegerValuesIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.VmsBaseMessageIntegerValuesIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VmsMessageType)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VmsMessageType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.VmsMessageType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VmsMessageWithLayerAndPublisherIdIntegerValuesIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VmsMessageWithLayerAndPublisherIdIntegerValuesIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.VmsMessageWithLayerAndPublisherIdIntegerValuesIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VmsMessageWithLayerIntegerValuesIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VmsMessageWithLayerIntegerValuesIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.VmsMessageWithLayerIntegerValuesIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VmsOfferingMessageIntegerValuesIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VmsOfferingMessageIntegerValuesIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.VmsOfferingMessageIntegerValuesIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VmsSubscriptionsStateIntegerValuesIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VmsSubscriptionsStateIntegerValuesIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.VmsSubscriptionsStateIntegerValuesIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
 # Build types.hal (Wheel)
 #
 GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Wheel.java
@@ -989,6 +1293,177 @@ LOCAL_STATIC_JAVA_LIBRARIES := \
 
 
 #
+# Build types.hal (DiagnosticFloatSensorIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/DiagnosticFloatSensorIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.DiagnosticFloatSensorIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (DiagnosticIntegerSensorIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/DiagnosticIntegerSensorIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.DiagnosticIntegerSensorIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2CommonIgnitionMonitors)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Obd2CommonIgnitionMonitors.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.Obd2CommonIgnitionMonitors
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2CompressionIgnitionMonitors)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Obd2CompressionIgnitionMonitors.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.Obd2CompressionIgnitionMonitors
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2FuelSystemStatus)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Obd2FuelSystemStatus.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.Obd2FuelSystemStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2FuelType)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Obd2FuelType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.Obd2FuelType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2IgnitionMonitorKind)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Obd2IgnitionMonitorKind.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.Obd2IgnitionMonitorKind
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2SecondaryAirStatus)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Obd2SecondaryAirStatus.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.Obd2SecondaryAirStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2SparkIgnitionMonitors)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Obd2SparkIgnitionMonitors.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.Obd2SparkIgnitionMonitors
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
 # Build types.hal (StatusCode)
 #
 GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/StatusCode.java
@@ -1882,6 +2357,139 @@ $(GEN): $(LOCAL_PATH)/types.hal
 LOCAL_GENERATED_SOURCES += $(GEN)
 
 #
+# Build types.hal (VmsAvailabilityStateIntegerValuesIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VmsAvailabilityStateIntegerValuesIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.VmsAvailabilityStateIntegerValuesIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VmsBaseMessageIntegerValuesIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VmsBaseMessageIntegerValuesIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.VmsBaseMessageIntegerValuesIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VmsMessageType)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VmsMessageType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.VmsMessageType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VmsMessageWithLayerAndPublisherIdIntegerValuesIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VmsMessageWithLayerAndPublisherIdIntegerValuesIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.VmsMessageWithLayerAndPublisherIdIntegerValuesIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VmsMessageWithLayerIntegerValuesIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VmsMessageWithLayerIntegerValuesIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.VmsMessageWithLayerIntegerValuesIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VmsOfferingMessageIntegerValuesIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VmsOfferingMessageIntegerValuesIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.VmsOfferingMessageIntegerValuesIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VmsSubscriptionsStateIntegerValuesIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VmsSubscriptionsStateIntegerValuesIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.VmsSubscriptionsStateIntegerValuesIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
 # Build types.hal (Wheel)
 #
 GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Wheel.java
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
new file mode 100644 (file)
index 0000000..1690163
--- /dev/null
@@ -0,0 +1,117 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//       http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_defaults {
+    name: "vhal_v2_0_defaults",
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libutils",
+        "android.hardware.automotive.vehicle@2.0",
+    ],
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
+}
+
+cc_library_headers {
+    name: "vhal_v2_0_common_headers",
+    vendor: true,
+    export_include_dirs: ["common/include/vhal_v2_0"],
+}
+
+// Vehicle reference implementation lib
+cc_library_static {
+    name: "android.hardware.automotive.vehicle@2.0-manager-lib",
+    vendor: true,
+    defaults: ["vhal_v2_0_defaults"],
+    srcs: [
+        "common/src/Obd2SensorStore.cpp",
+        "common/src/SubscriptionManager.cpp",
+        "common/src/VehicleHalManager.cpp",
+        "common/src/VehicleObjectPool.cpp",
+        "common/src/VehiclePropertyStore.cpp",
+        "common/src/VehicleUtils.cpp",
+    ],
+    local_include_dirs: ["common/include/vhal_v2_0"],
+    export_include_dirs: ["common/include"],
+}
+
+cc_library_shared {
+    name: "android.hardware.automotive.vehicle@2.0-manager-lib-shared",
+    vendor: true,
+    static_libs: ["android.hardware.automotive.vehicle@2.0-manager-lib"],
+    export_static_lib_headers: ["android.hardware.automotive.vehicle@2.0-manager-lib"],
+}
+
+// Vehicle default VehicleHAL implementation
+cc_library_static {
+    name: "android.hardware.automotive.vehicle@2.0-default-impl-lib",
+    vendor: true,
+    defaults: ["vhal_v2_0_defaults"],
+    srcs: [
+        "impl/vhal_v2_0/EmulatedVehicleHal.cpp",
+        "impl/vhal_v2_0/VehicleEmulator.cpp",
+        "impl/vhal_v2_0/PipeComm.cpp",
+        "impl/vhal_v2_0/SocketComm.cpp",
+    ],
+    local_include_dirs: ["common/include/vhal_v2_0"],
+    export_include_dirs: ["impl"],
+    whole_static_libs: ["android.hardware.automotive.vehicle@2.0-manager-lib"],
+    shared_libs: [
+        "libbase",
+        "libprotobuf-cpp-lite",
+    ],
+    static_libs: [
+        "libqemu_pipe",
+        "android.hardware.automotive.vehicle@2.0-libproto-native",
+    ],
+}
+
+cc_test {
+    name: "android.hardware.automotive.vehicle@2.0-manager-unit-tests",
+    vendor: true,
+    defaults: ["vhal_v2_0_defaults"],
+    whole_static_libs: ["android.hardware.automotive.vehicle@2.0-manager-lib"],
+    srcs: [
+        "tests/RecurrentTimer_test.cpp",
+        "tests/SubscriptionManager_test.cpp",
+        "tests/VehicleHalManager_test.cpp",
+        "tests/VehicleObjectPool_test.cpp",
+        "tests/VehiclePropConfigIndex_test.cpp",
+    ],
+    header_libs: ["libbase_headers"],
+}
+
+cc_binary {
+    name: "android.hardware.automotive.vehicle@2.0-service",
+    defaults: ["vhal_v2_0_defaults"],
+    init_rc: ["android.hardware.automotive.vehicle@2.0-service.rc"],
+    vendor: true,
+    relative_install_path: "hw",
+    srcs: ["VehicleService.cpp"],
+    shared_libs: [
+        "libbase",
+        "libprotobuf-cpp-lite",
+    ],
+    static_libs: [
+        "android.hardware.automotive.vehicle@2.0-manager-lib",
+        "android.hardware.automotive.vehicle@2.0-default-impl-lib",
+        "android.hardware.automotive.vehicle@2.0-libproto-native",
+        "libqemu_pipe",
+    ],
+}
diff --git a/automotive/vehicle/2.0/default/Android.mk b/automotive/vehicle/2.0/default/Android.mk
deleted file mode 100644 (file)
index 72e1364..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-vhal_v2_0 = android.hardware.automotive.vehicle@2.0
-
-###############################################################################
-# Vehicle reference implementation lib
-###############################################################################
-include $(CLEAR_VARS)
-LOCAL_MODULE := $(vhal_v2_0)-manager-lib
-LOCAL_SRC_FILES := \
-    common/src/SubscriptionManager.cpp \
-    common/src/VehicleHalManager.cpp \
-    common/src/VehicleObjectPool.cpp \
-    common/src/VehiclePropertyStore.cpp \
-    common/src/VehicleUtils.cpp \
-
-LOCAL_C_INCLUDES := \
-    $(LOCAL_PATH)/common/include/vhal_v2_0
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := \
-    $(LOCAL_PATH)/common/include
-
-LOCAL_SHARED_LIBRARIES := \
-    libhidlbase \
-    libhidltransport \
-    liblog \
-    libutils \
-    $(vhal_v2_0) \
-
-include $(BUILD_STATIC_LIBRARY)
-
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := $(vhal_v2_0)-manager-lib-shared
-LOCAL_SRC_FILES := \
-    common/src/SubscriptionManager.cpp \
-    common/src/VehicleHalManager.cpp \
-    common/src/VehicleObjectPool.cpp \
-    common/src/VehiclePropertyStore.cpp \
-    common/src/VehicleUtils.cpp \
-
-LOCAL_C_INCLUDES := \
-    $(LOCAL_PATH)/common/include/vhal_v2_0
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := \
-    $(LOCAL_PATH)/common/include
-
-LOCAL_SHARED_LIBRARIES := \
-    libhidlbase \
-    libhidltransport \
-    liblog \
-    libutils \
-    $(vhal_v2_0) \
-
-include $(BUILD_SHARED_LIBRARY)
-
-###############################################################################
-# Vehicle HAL Protobuf library
-###############################################################################
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(call all-proto-files-under, impl/vhal_v2_0/proto)
-
-LOCAL_PROTOC_OPTIMIZE_TYPE := nano
-
-LOCAL_MODULE := $(vhal_v2_0)-libproto-native
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_STRIP_MODULE := keep_symbols
-
-generated_sources_dir := $(call local-generated-sources-dir)
-LOCAL_EXPORT_C_INCLUDE_DIRS := \
-    $(generated_sources_dir)/proto/$(LOCAL_PATH)/impl/vhal_v2_0/proto
-
-include $(BUILD_STATIC_LIBRARY)
-
-
-###############################################################################
-# Vehicle default VehicleHAL implementation
-###############################################################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE:= $(vhal_v2_0)-default-impl-lib
-LOCAL_SRC_FILES:= \
-    impl/vhal_v2_0/EmulatedVehicleHal.cpp \
-    impl/vhal_v2_0/VehicleEmulator.cpp \
-    impl/vhal_v2_0/PipeComm.cpp \
-    impl/vhal_v2_0/SocketComm.cpp \
-
-LOCAL_C_INCLUDES := \
-    $(LOCAL_PATH)/impl/vhal_v2_0
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := \
-    $(LOCAL_PATH)/impl
-
-LOCAL_WHOLE_STATIC_LIBRARIES := \
-    $(vhal_v2_0)-manager-lib \
-
-LOCAL_SHARED_LIBRARIES := \
-    libbase \
-    libhidlbase \
-    libhidltransport \
-    liblog \
-    libprotobuf-cpp-lite \
-    libutils \
-    $(vhal_v2_0) \
-
-LOCAL_STATIC_LIBRARIES := \
-    libqemu_pipe \
-    $(vhal_v2_0)-libproto-native \
-
-LOCAL_CFLAGS += -Wall -Wextra -Werror
-
-include $(BUILD_STATIC_LIBRARY)
-
-
-###############################################################################
-# Vehicle reference implementation unit tests
-###############################################################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE:= $(vhal_v2_0)-manager-unit-tests
-
-LOCAL_WHOLE_STATIC_LIBRARIES := \
-    $(vhal_v2_0)-manager-lib \
-
-LOCAL_SRC_FILES:= \
-    tests/RecurrentTimer_test.cpp \
-    tests/SubscriptionManager_test.cpp \
-    tests/VehicleHalManager_test.cpp \
-    tests/VehicleObjectPool_test.cpp \
-    tests/VehiclePropConfigIndex_test.cpp \
-
-LOCAL_HEADER_LIBRARIES := \
-    libbase_headers
-
-LOCAL_SHARED_LIBRARIES := \
-    libhidlbase \
-    libhidltransport \
-    liblog \
-    libutils \
-    $(vhal_v2_0) \
-
-LOCAL_CFLAGS += -Wall -Wextra -Werror
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_NATIVE_TEST)
-
-
-###############################################################################
-# Vehicle HAL service
-###############################################################################
-include $(CLEAR_VARS)
-LOCAL_MODULE := $(vhal_v2_0)-service
-LOCAL_INIT_RC := $(vhal_v2_0)-service.rc
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := hw
-
-LOCAL_SRC_FILES := \
-    VehicleService.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-    libbase \
-    libhidlbase \
-    libhidltransport \
-    liblog \
-    libprotobuf-cpp-lite \
-    libutils \
-    $(vhal_v2_0) \
-
-LOCAL_STATIC_LIBRARIES := \
-    $(vhal_v2_0)-manager-lib \
-    $(vhal_v2_0)-default-impl-lib \
-    $(vhal_v2_0)-libproto-native \
-    libqemu_pipe \
-
-LOCAL_CFLAGS += -Wall -Wextra -Werror
-
-include $(BUILD_EXECUTABLE)
  * limitations under the License.
  */
 
-#ifndef android_hardware_automotive_vehicle_V2_1_Obd2SensorStore_H_
-#define android_hardware_automotive_vehicle_V2_1_Obd2SensorStore_H_
+#ifndef android_hardware_automotive_vehicle_V2_0_Obd2SensorStore_H_
+#define android_hardware_automotive_vehicle_V2_0_Obd2SensorStore_H_
 
 #include <vector>
 
-#include <android/hardware/automotive/vehicle/2.1/types.h>
+#include <android/hardware/automotive/vehicle/2.0/types.h>
 
 namespace android {
 namespace hardware {
 namespace automotive {
 namespace vehicle {
-namespace V2_1 {
+namespace V2_0 {
 
 // This class wraps all the logic required to create an OBD2 frame.
 // It allows storing sensor values, setting appropriate bitmasks as needed,
 // and returning appropriately laid out storage of sensor values suitable
 // for being returned via a VehicleHal implementation.
 class Obd2SensorStore {
-public:
+   public:
     // Creates a sensor storage with a given number of vendor-specific sensors.
-    Obd2SensorStore(size_t numVendorIntegerSensors,
-                    size_t numVendorFloatSensors);
+    Obd2SensorStore(size_t numVendorIntegerSensors, size_t numVendorFloatSensors);
 
     // Stores an integer-valued sensor.
-    V2_0::StatusCode setIntegerSensor(Obd2IntegerSensorIndex index, int32_t value);
+    StatusCode setIntegerSensor(DiagnosticIntegerSensorIndex index, int32_t value);
     // Stores an integer-valued sensor.
-    V2_0::StatusCode setIntegerSensor(size_t index, int32_t value);
+    StatusCode setIntegerSensor(size_t index, int32_t value);
 
     // Stores a float-valued sensor.
-    V2_0::StatusCode setFloatSensor(Obd2FloatSensorIndex index, float value);
+    StatusCode setFloatSensor(DiagnosticFloatSensorIndex index, float value);
     // Stores a float-valued sensor.
-    V2_0::StatusCode setFloatSensor(size_t index, float value);
+    StatusCode setFloatSensor(size_t index, float value);
 
     // Returns a vector that contains all integer sensors stored.
     const std::vector<int32_t>& getIntegerSensors() const;
@@ -55,11 +54,11 @@ public:
     const std::vector<uint8_t>& getSensorsBitmask() const;
 
     // Given a stringValue, fill in a VehiclePropValue
-    void fillPropValue(const std::string& dtc, V2_0::VehiclePropValue *propValue) const;
+    void fillPropValue(const std::string& dtc, VehiclePropValue* propValue) const;
 
-private:
+   private:
     class BitmaskInVector {
-    public:
+       public:
         BitmaskInVector(size_t numBits = 0);
         void resize(size_t numBits);
         bool get(size_t index) const;
@@ -67,7 +66,7 @@ private:
 
         const std::vector<uint8_t>& getBitmask() const;
 
-    private:
+       private:
         std::vector<uint8_t> mStorage;
     };
 
@@ -76,7 +75,7 @@ private:
     BitmaskInVector mSensorsBitmask;
 };
 
-}  // namespace V2_1
+}  // namespace V2_0
 }  // namespace vehicle
 }  // namespace automotive
 }  // namespace hardware
@@ -23,23 +23,21 @@ namespace android {
 namespace hardware {
 namespace automotive {
 namespace vehicle {
-namespace V2_1 {
+namespace V2_0 {
 
-Obd2SensorStore::BitmaskInVector::BitmaskInVector(size_t numBits)
-{
+Obd2SensorStore::BitmaskInVector::BitmaskInVector(size_t numBits) {
     resize(numBits);
 }
 
 void Obd2SensorStore::BitmaskInVector::resize(size_t numBits) {
-    mStorage = std::vector<uint8_t>((numBits+7)/8, 0);
+    mStorage = std::vector<uint8_t>((numBits + 7) / 8, 0);
 }
 
 void Obd2SensorStore::BitmaskInVector::set(size_t index, bool value) {
     const size_t byteIndex = index / 8;
     const size_t bitIndex = index % 8;
     const uint8_t byte = mStorage[byteIndex];
-    uint8_t newValue = value ? (byte | (1 << bitIndex)) :
-                               (byte & ~(1 << bitIndex));
+    uint8_t newValue = value ? (byte | (1 << bitIndex)) : (byte & ~(1 << bitIndex));
     mStorage[byteIndex] = newValue;
 }
 
@@ -54,37 +52,33 @@ const std::vector<uint8_t>& Obd2SensorStore::BitmaskInVector::getBitmask() const
     return mStorage;
 }
 
-Obd2SensorStore::Obd2SensorStore(size_t numVendorIntegerSensors,
-                                 size_t numVendorFloatSensors) {
-        // because the last index is valid *inclusive*
-        const size_t numSystemIntegerSensors = V2_0::toInt(Obd2IntegerSensorIndex::LAST_SYSTEM_INDEX)+1;
-        const size_t numSystemFloatSensors = V2_0::toInt(Obd2FloatSensorIndex::LAST_SYSTEM_INDEX)+1;
-        mIntegerSensors = std::vector<int32_t>(
-            numSystemIntegerSensors+numVendorIntegerSensors, 0);
-        mFloatSensors = std::vector<float>(
-            numSystemFloatSensors+numVendorFloatSensors, 0);
-        mSensorsBitmask.resize(mIntegerSensors.size()+mFloatSensors.size());
+Obd2SensorStore::Obd2SensorStore(size_t numVendorIntegerSensors, size_t numVendorFloatSensors) {
+    // because the last index is valid *inclusive*
+    const size_t numSystemIntegerSensors =
+        toInt(DiagnosticIntegerSensorIndex::LAST_SYSTEM_INDEX) + 1;
+    const size_t numSystemFloatSensors = toInt(DiagnosticFloatSensorIndex::LAST_SYSTEM_INDEX) + 1;
+    mIntegerSensors = std::vector<int32_t>(numSystemIntegerSensors + numVendorIntegerSensors, 0);
+    mFloatSensors = std::vector<float>(numSystemFloatSensors + numVendorFloatSensors, 0);
+    mSensorsBitmask.resize(mIntegerSensors.size() + mFloatSensors.size());
 }
 
-V2_0::StatusCode Obd2SensorStore::setIntegerSensor(Obd2IntegerSensorIndex index,
-    int32_t value) {
-    return setIntegerSensor(V2_0::toInt(index), value);
+StatusCode Obd2SensorStore::setIntegerSensor(DiagnosticIntegerSensorIndex index, int32_t value) {
+    return setIntegerSensor(toInt(index), value);
 }
-V2_0::StatusCode Obd2SensorStore::setFloatSensor(Obd2FloatSensorIndex index,
-    float value) {
-    return setFloatSensor(V2_0::toInt(index), value);
+StatusCode Obd2SensorStore::setFloatSensor(DiagnosticFloatSensorIndex index, float value) {
+    return setFloatSensor(toInt(index), value);
 }
 
-V2_0::StatusCode Obd2SensorStore::setIntegerSensor(size_t index, int32_t value) {
+StatusCode Obd2SensorStore::setIntegerSensor(size_t index, int32_t value) {
     mIntegerSensors[index] = value;
     mSensorsBitmask.set(index, true);
-    return V2_0::StatusCode::OK;
+    return StatusCode::OK;
 }
 
-V2_0::StatusCode Obd2SensorStore::setFloatSensor(size_t index, float value) {
+StatusCode Obd2SensorStore::setFloatSensor(size_t index, float value) {
     mFloatSensors[index] = value;
     mSensorsBitmask.set(index + mIntegerSensors.size(), true);
-    return V2_0::StatusCode::OK;
+    return StatusCode::OK;
 }
 
 const std::vector<int32_t>& Obd2SensorStore::getIntegerSensors() const {
@@ -99,8 +93,7 @@ const std::vector<uint8_t>& Obd2SensorStore::getSensorsBitmask() const {
     return mSensorsBitmask.getBitmask();
 }
 
-void Obd2SensorStore::fillPropValue(const std::string& dtc,
-                                    V2_0::VehiclePropValue *propValue) const {
+void Obd2SensorStore::fillPropValue(const std::string& dtc, VehiclePropValue* propValue) const {
     propValue->timestamp = elapsedRealtimeNano();
     propValue->value.int32Values = getIntegerSensors();
     propValue->value.floatValues = getFloatSensors();
@@ -108,8 +101,6 @@ void Obd2SensorStore::fillPropValue(const std::string& dtc,
     propValue->value.stringValue = dtc;
 }
 
-
-
 }  // namespace V2_0
 }  // namespace vehicle
 }  // namespace automotive
index fb63e36..08d3d79 100644 (file)
@@ -27,6 +27,18 @@ namespace vehicle {
 namespace V2_0 {
 
 namespace impl {
+//
+// Some handy constants to avoid conversions from enum to int.
+constexpr int ABS_ACTIVE = (int)VehicleProperty::ABS_ACTIVE;
+constexpr int OBD2_LIVE_FRAME = (int)VehicleProperty::OBD2_LIVE_FRAME;
+constexpr int OBD2_FREEZE_FRAME = (int)VehicleProperty::OBD2_FREEZE_FRAME;
+constexpr int OBD2_FREEZE_FRAME_INFO = (int)VehicleProperty::OBD2_FREEZE_FRAME_INFO;
+constexpr int OBD2_FREEZE_FRAME_CLEAR = (int)VehicleProperty::OBD2_FREEZE_FRAME_CLEAR;
+constexpr int TRACTION_CONTROL_ACTIVE = (int)VehicleProperty::TRACTION_CONTROL_ACTIVE;
+constexpr int VEHICLE_MAP_SERVICE = (int)VehicleProperty::VEHICLE_MAP_SERVICE;
+constexpr int WHEEL_TICK = (int)VehicleProperty::WHEEL_TICK;
+constexpr int ALL_WHEELS =
+    (int)(Wheel::LEFT_FRONT | Wheel::RIGHT_FRONT | Wheel::LEFT_REAR | Wheel::RIGHT_REAR);
 
 /*
  * This property is used for test purpose to generate fake events.
@@ -283,8 +295,68 @@ const ConfigDeclaration kVehicleProperties[]{
              .access = VehiclePropertyAccess::READ,
              .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
          },
-     .initialValue = {.int32Values = {1}}}
+     .initialValue = {.int32Values = {1}}},
+
+    {
+        .config =
+            {
+                .prop = WHEEL_TICK,
+                .access = VehiclePropertyAccess::READ,
+                .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
+                .configArray = {ALL_WHEELS, 50000, 50000, 50000, 50000},
+                .minSampleRate = 1.0f,
+                .maxSampleRate = 100.0f,
+            },
+    },
+
+    {
+        .config =
+            {
+                .prop = ABS_ACTIVE,
+                .access = VehiclePropertyAccess::READ,
+                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+            },
+    },
+
+    {
+        .config =
+            {
+                .prop = TRACTION_CONTROL_ACTIVE,
+                .access = VehiclePropertyAccess::READ,
+                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+            },
+    },
 
+    {
+        .config = {.prop = OBD2_LIVE_FRAME,
+                   .access = VehiclePropertyAccess::READ,
+                   .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                   .configArray = {0, 0}},
+    },
+
+    {
+        .config = {.prop = OBD2_FREEZE_FRAME,
+                   .access = VehiclePropertyAccess::READ,
+                   .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                   .configArray = {0, 0}},
+    },
+
+    {
+        .config = {.prop = OBD2_FREEZE_FRAME_INFO,
+                   .access = VehiclePropertyAccess::READ,
+                   .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
+    },
+
+    {
+        .config = {.prop = OBD2_FREEZE_FRAME_CLEAR,
+                   .access = VehiclePropertyAccess::WRITE,
+                   .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                   .configArray = {1}},
+    },
+
+    {.config = {.prop = VEHICLE_MAP_SERVICE,
+                .access = VehiclePropertyAccess::READ_WRITE,
+                .changeMode = VehiclePropertyChangeMode::ON_CHANGE}},
 };
 
 }  // impl
index fe34a3f..6bc0522 100644 (file)
@@ -19,6 +19,7 @@
 #include <android-base/macros.h>
 
 #include "EmulatedVehicleHal.h"
+#include "Obd2SensorStore.h"
 
 namespace android {
 namespace hardware {
@@ -28,6 +29,62 @@ namespace V2_0 {
 
 namespace impl {
 
+static std::unique_ptr<Obd2SensorStore> fillDefaultObd2Frame(size_t numVendorIntegerSensors,
+                                                             size_t numVendorFloatSensors) {
+    std::unique_ptr<Obd2SensorStore> sensorStore(
+        new Obd2SensorStore(numVendorIntegerSensors, numVendorFloatSensors));
+
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::FUEL_SYSTEM_STATUS,
+                                  toInt(Obd2FuelSystemStatus::CLOSED_LOOP));
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::MALFUNCTION_INDICATOR_LIGHT_ON, 0);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::IGNITION_MONITORS_SUPPORTED,
+                                  toInt(Obd2IgnitionMonitorKind::SPARK));
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::IGNITION_SPECIFIC_MONITORS,
+                                  Obd2CommonIgnitionMonitors::COMPONENTS_AVAILABLE |
+                                      Obd2CommonIgnitionMonitors::MISFIRE_AVAILABLE |
+                                      Obd2SparkIgnitionMonitors::AC_REFRIGERANT_AVAILABLE |
+                                      Obd2SparkIgnitionMonitors::EVAPORATIVE_SYSTEM_AVAILABLE);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::INTAKE_AIR_TEMPERATURE, 35);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::COMMANDED_SECONDARY_AIR_STATUS,
+                                  toInt(Obd2SecondaryAirStatus::FROM_OUTSIDE_OR_OFF));
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::NUM_OXYGEN_SENSORS_PRESENT, 1);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::RUNTIME_SINCE_ENGINE_START, 500);
+    sensorStore->setIntegerSensor(
+        DiagnosticIntegerSensorIndex::DISTANCE_TRAVELED_WITH_MALFUNCTION_INDICATOR_LIGHT_ON, 0);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::WARMUPS_SINCE_CODES_CLEARED, 51);
+    sensorStore->setIntegerSensor(
+        DiagnosticIntegerSensorIndex::DISTANCE_TRAVELED_SINCE_CODES_CLEARED, 365);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::ABSOLUTE_BAROMETRIC_PRESSURE, 30);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::CONTROL_MODULE_VOLTAGE, 12);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::AMBIENT_AIR_TEMPERATURE, 18);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::MAX_FUEL_AIR_EQUIVALENCE_RATIO, 1);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::FUEL_TYPE,
+                                  toInt(Obd2FuelType::GASOLINE));
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::CALCULATED_ENGINE_LOAD, 0.153);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::SHORT_TERM_FUEL_TRIM_BANK1, -0.16);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::LONG_TERM_FUEL_TRIM_BANK1, -0.16);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::SHORT_TERM_FUEL_TRIM_BANK2, -0.16);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::LONG_TERM_FUEL_TRIM_BANK2, -0.16);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::INTAKE_MANIFOLD_ABSOLUTE_PRESSURE, 7.5);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::ENGINE_RPM, 1250.);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::VEHICLE_SPEED, 40.);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::TIMING_ADVANCE, 2.5);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::THROTTLE_POSITION, 19.75);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::OXYGEN_SENSOR1_VOLTAGE, 0.265);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::FUEL_TANK_LEVEL_INPUT, 0.824);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::EVAPORATION_SYSTEM_VAPOR_PRESSURE,
+                                -0.373);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::CATALYST_TEMPERATURE_BANK1_SENSOR1,
+                                190.);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::RELATIVE_THROTTLE_POSITION, 3.);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::ABSOLUTE_THROTTLE_POSITION_B, 0.306);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::ACCELERATOR_PEDAL_POSITION_D, 0.188);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::ACCELERATOR_PEDAL_POSITION_E, 0.094);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::COMMANDED_THROTTLE_ACTUATOR, 0.024);
+
+    return sensorStore;
+}
+
 enum class FakeDataCommand : int32_t {
     Stop = 0,
     Start = 1,
@@ -40,7 +97,7 @@ EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore)
                                   this, std::placeholders::_1)),
       mFakeValueGenerator(std::bind(&EmulatedVehicleHal::onFakeValueGenerated,
                                     this, std::placeholders::_1, std::placeholders::_2)) {
-
+    initStaticConfig();
     for (size_t i = 0; i < arraysize(kVehicleProperties); i++) {
         mPropStore->registerProperty(kVehicleProperties[i].config);
     }
@@ -48,23 +105,39 @@ EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore)
 
 VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::get(
         const VehiclePropValue& requestedPropValue, StatusCode* outStatus) {
+    auto propId = requestedPropValue.prop;
+    auto& pool = *getValuePool();
     VehiclePropValuePtr v = nullptr;
 
-    auto internalPropValue = mPropStore->readValueOrNull(requestedPropValue);
-    if (internalPropValue != nullptr) {
-        v = getValuePool()->obtain(*internalPropValue);
+    switch (propId) {
+        case OBD2_FREEZE_FRAME:
+            v = pool.obtainComplex();
+            *outStatus = fillObd2FreezeFrame(requestedPropValue, v.get());
+            break;
+        case OBD2_FREEZE_FRAME_INFO:
+            v = pool.obtainComplex();
+            *outStatus = fillObd2DtcInfo(v.get());
+            break;
+        default:
+            auto internalPropValue = mPropStore->readValueOrNull(requestedPropValue);
+            if (internalPropValue != nullptr) {
+                v = getValuePool()->obtain(*internalPropValue);
+            }
+
+            *outStatus = v != nullptr ? StatusCode::OK : StatusCode::INVALID_ARG;
+            break;
     }
 
-    *outStatus = v != nullptr ? StatusCode::OK : StatusCode::INVALID_ARG;
     return v;
 }
 
 StatusCode EmulatedVehicleHal::set(const VehiclePropValue& propValue) {
     if (propValue.prop == kGenerateFakeDataControllingProperty) {
-        return handleGenerateFakeDataRequest(propValue);
-    };
-
-    if (mHvacPowerProps.count(propValue.prop)) {
+        StatusCode status = handleGenerateFakeDataRequest(propValue);
+        if (status != StatusCode::OK) {
+            return status;
+        }
+    } else if (mHvacPowerProps.count(propValue.prop)) {
         auto hvacPowerOn = mPropStore->readValueOrNull(toInt(VehicleProperty::HVAC_POWER_ON),
                                                       toInt(VehicleAreaZone::ROW_1));
 
@@ -72,6 +145,12 @@ StatusCode EmulatedVehicleHal::set(const VehiclePropValue& propValue) {
                 && hvacPowerOn->value.int32Values[0] == 0) {
             return StatusCode::NOT_AVAILABLE;
         }
+    } else if (propValue.prop == OBD2_FREEZE_FRAME_CLEAR) {
+        return clearObd2FreezeFrames(propValue);
+    } else if (propValue.prop == VEHICLE_MAP_SERVICE) {
+        // Placeholder for future implementation of VMS property in the default hal. For now, just
+        // returns OK; otherwise, hal clients crash with property not supported.
+        return StatusCode::OK;
     }
 
     if (!mPropStore->writeValue(propValue)) {
@@ -83,12 +162,29 @@ StatusCode EmulatedVehicleHal::set(const VehiclePropValue& propValue) {
     return StatusCode::OK;
 }
 
+static bool isDiagnosticProperty(VehiclePropConfig propConfig) {
+    switch (propConfig.prop) {
+        case OBD2_LIVE_FRAME:
+        case OBD2_FREEZE_FRAME:
+        case OBD2_FREEZE_FRAME_CLEAR:
+        case OBD2_FREEZE_FRAME_INFO:
+            return true;
+    }
+    return false;
+}
+
 // Parse supported properties list and generate vector of property values to hold current values.
 void EmulatedVehicleHal::onCreate() {
     for (auto& it : kVehicleProperties) {
         VehiclePropConfig cfg = it.config;
         int32_t supportedAreas = cfg.supportedAreas;
 
+        if (isDiagnosticProperty(cfg)) {
+            // do not write an initial empty value for the diagnostic properties
+            // as we will initialize those separately.
+            continue;
+        }
+
         //  A global property will have supportedAreas = 0
         if (isGlobalProp(cfg.prop)) {
             supportedAreas = 0;
@@ -120,6 +216,8 @@ void EmulatedVehicleHal::onCreate() {
 
         } while (supportedAreas != 0);
     }
+    initObd2LiveFrame(*mPropStore->getConfigOrDie(OBD2_LIVE_FRAME));
+    initObd2FreezeFrame(*mPropStore->getConfigOrDie(OBD2_FREEZE_FRAME));
 }
 
 std::vector<VehiclePropConfig> EmulatedVehicleHal::listProperties()  {
@@ -176,6 +274,13 @@ bool EmulatedVehicleHal::isContinuousProperty(int32_t propId) const {
 }
 
 bool EmulatedVehicleHal::setPropertyFromVehicle(const VehiclePropValue& propValue) {
+    if (propValue.prop == kGenerateFakeDataControllingProperty) {
+        StatusCode status = handleGenerateFakeDataRequest(propValue);
+        if (status != StatusCode::OK) {
+            return false;
+        }
+    }
+
     if (mPropStore->writeValue(propValue)) {
         doHalEvent(getValuePool()->obtain(propValue));
         return true;
@@ -263,6 +368,100 @@ void EmulatedVehicleHal::onFakeValueGenerated(int32_t propId, float value) {
     }
 }
 
+void EmulatedVehicleHal::initStaticConfig() {
+    for (auto&& it = std::begin(kVehicleProperties); it != std::end(kVehicleProperties); ++it) {
+        const auto& cfg = it->config;
+        VehiclePropertyStore::TokenFunction tokenFunction = nullptr;
+
+        switch (cfg.prop) {
+            case OBD2_FREEZE_FRAME: {
+                tokenFunction = [](const VehiclePropValue& propValue) {
+                    return propValue.timestamp;
+                };
+                break;
+            }
+            default:
+                break;
+        }
+
+        mPropStore->registerProperty(cfg, tokenFunction);
+    }
+}
+
+void EmulatedVehicleHal::initObd2LiveFrame(const VehiclePropConfig& propConfig) {
+    auto liveObd2Frame = createVehiclePropValue(VehiclePropertyType::COMPLEX, 0);
+    auto sensorStore = fillDefaultObd2Frame(static_cast<size_t>(propConfig.configArray[0]),
+                                            static_cast<size_t>(propConfig.configArray[1]));
+    sensorStore->fillPropValue("", liveObd2Frame.get());
+    liveObd2Frame->prop = OBD2_LIVE_FRAME;
+
+    mPropStore->writeValue(*liveObd2Frame);
+}
+
+void EmulatedVehicleHal::initObd2FreezeFrame(const VehiclePropConfig& propConfig) {
+    auto sensorStore = fillDefaultObd2Frame(static_cast<size_t>(propConfig.configArray[0]),
+                                            static_cast<size_t>(propConfig.configArray[1]));
+
+    static std::vector<std::string> sampleDtcs = {"P0070",
+                                                  "P0102"
+                                                  "P0123"};
+    for (auto&& dtc : sampleDtcs) {
+        auto freezeFrame = createVehiclePropValue(VehiclePropertyType::COMPLEX, 0);
+        sensorStore->fillPropValue(dtc, freezeFrame.get());
+        freezeFrame->prop = OBD2_FREEZE_FRAME;
+
+        mPropStore->writeValue(*freezeFrame);
+    }
+}
+
+StatusCode EmulatedVehicleHal::fillObd2FreezeFrame(const VehiclePropValue& requestedPropValue,
+                                                   VehiclePropValue* outValue) {
+    if (requestedPropValue.value.int64Values.size() != 1) {
+        ALOGE("asked for OBD2_FREEZE_FRAME without valid timestamp");
+        return StatusCode::INVALID_ARG;
+    }
+    auto timestamp = requestedPropValue.value.int64Values[0];
+    auto freezeFrame = mPropStore->readValueOrNull(OBD2_FREEZE_FRAME, 0, timestamp);
+    if (freezeFrame == nullptr) {
+        ALOGE("asked for OBD2_FREEZE_FRAME at invalid timestamp");
+        return StatusCode::INVALID_ARG;
+    }
+    outValue->prop = OBD2_FREEZE_FRAME;
+    outValue->value.int32Values = freezeFrame->value.int32Values;
+    outValue->value.floatValues = freezeFrame->value.floatValues;
+    outValue->value.bytes = freezeFrame->value.bytes;
+    outValue->value.stringValue = freezeFrame->value.stringValue;
+    outValue->timestamp = freezeFrame->timestamp;
+    return StatusCode::OK;
+}
+
+StatusCode EmulatedVehicleHal::clearObd2FreezeFrames(const VehiclePropValue& propValue) {
+    if (propValue.value.int64Values.size() == 0) {
+        mPropStore->removeValuesForProperty(OBD2_FREEZE_FRAME);
+        return StatusCode::OK;
+    } else {
+        for (int64_t timestamp : propValue.value.int64Values) {
+            auto freezeFrame = mPropStore->readValueOrNull(OBD2_FREEZE_FRAME, 0, timestamp);
+            if (freezeFrame == nullptr) {
+                ALOGE("asked for OBD2_FREEZE_FRAME at invalid timestamp");
+                return StatusCode::INVALID_ARG;
+            }
+            mPropStore->removeValue(*freezeFrame);
+        }
+    }
+    return StatusCode::OK;
+}
+
+StatusCode EmulatedVehicleHal::fillObd2DtcInfo(VehiclePropValue* outValue) {
+    std::vector<int64_t> timestamps;
+    for (const auto& freezeFrame : mPropStore->readValuesForProperty(OBD2_FREEZE_FRAME)) {
+        timestamps.push_back(freezeFrame.timestamp);
+    }
+    outValue->value.int64Values = timestamps;
+    outValue->prop = OBD2_FREEZE_FRAME_INFO;
+    return StatusCode::OK;
+}
+
 }  // impl
 
 }  // namespace V2_0
index c25e083..99d7edb 100644 (file)
@@ -70,8 +70,15 @@ private:
 
     void onContinuousPropertyTimer(const std::vector<int32_t>& properties);
     bool isContinuousProperty(int32_t propId) const;
-
-private:
+    void initStaticConfig();
+    void initObd2LiveFrame(const VehiclePropConfig& propConfig);
+    void initObd2FreezeFrame(const VehiclePropConfig& propConfig);
+    StatusCode fillObd2FreezeFrame(const VehiclePropValue& requestedPropValue,
+                                   VehiclePropValue* outValue);
+    StatusCode fillObd2DtcInfo(VehiclePropValue* outValue);
+    StatusCode clearObd2FreezeFrames(const VehiclePropValue& propValue);
+
+    /* Private members */
     VehiclePropertyStore* mPropStore;
     std::unordered_set<int32_t> mHvacPowerProps;
     RecurrentTimer mRecurrentTimer;
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/Android.bp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/Android.bp
new file mode 100644 (file)
index 0000000..ec35200
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//       http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Vehicle HAL Protobuf library
+cc_library_static {
+    name: "android.hardware.automotive.vehicle@2.0-libproto-native",
+    vendor: true,
+    proto: {
+        export_proto_headers: true,
+        type: "lite",
+    },
+    strip: {
+        keep_symbols: true,
+    },
+    srcs: ["VehicleHalProto.proto"]
+}
index 28e1a5a..2a06417 100644 (file)
@@ -222,54 +222,6 @@ inline std::string vecToString(const hidl_vec<T>& vec) {
     return ss.str();
 }
 
-inline std::string toString(const VehiclePropValue &v) {
-    std::stringstream ss;
-    ss << "VehiclePropValue {n"
-       << "  prop: " << hexString(v.prop) << ",\n"
-       << "  areaId: " << hexString(v.areaId) << ",\n"
-       << "  timestamp: " << v.timestamp << ",\n"
-       << "  value {\n"
-       << "    int32Values: " << vecToString(v.value.int32Values) << ",\n"
-       << "    floatValues: " << vecToString(v.value.floatValues) << ",\n"
-       << "    int64Values: " << vecToString(v.value.int64Values) << ",\n"
-       << "    bytes: " << vecToString(v.value.bytes) << ",\n"
-       << "    string: " << v.value.stringValue.c_str() << ",\n"
-       << "  }\n"
-       << "}\n";
-
-    return ss.str();
-}
-
-inline std::string toString(const VehiclePropConfig &config) {
-    std::stringstream ss;
-    ss << "VehiclePropConfig {\n"
-       << "  prop: " << hexString(config.prop) << ",\n"
-       << "  supportedAreas: " << hexString(config.supportedAreas) << ",\n"
-       << "  access: " << enumToHexString(config.access) << ",\n"
-       << "  changeMode: " << enumToHexString(config.changeMode) << ",\n"
-       << "  configFlags: " << hexString(config.configFlags) << ",\n"
-       << "  minSampleRate: " << config.minSampleRate << ",\n"
-       << "  maxSampleRate: " << config.maxSampleRate << ",\n"
-       << "  configString: " << config.configString.c_str() << ",\n";
-
-    ss << "  areaConfigs {\n";
-    for (size_t i = 0; i < config.areaConfigs.size(); i++) {
-        const auto &area = config.areaConfigs[i];
-        ss << "    areaId: " << hexString(area.areaId) << ",\n"
-           << "    minFloatValue: " << area.minFloatValue << ",\n"
-           << "    minFloatValue: " << area.maxFloatValue << ",\n"
-           << "    minInt32Value: " << area.minInt32Value << ",\n"
-           << "    minInt32Value: " << area.maxInt32Value << ",\n"
-           << "    minInt64Value: " << area.minInt64Value << ",\n"
-           << "    minInt64Value: " << area.maxInt64Value << ",\n";
-    }
-    ss << "  }\n"
-       << "}\n";
-
-    return ss.str();
-}
-
-
 }  // namespace V2_0
 }  // namespace vehicle
 }  // namespace automotive
index f1fb6bf..7c08b4a 100644 (file)
@@ -226,6 +226,50 @@ enum VehicleProperty: int32_t {
         | VehicleArea:GLOBAL),
 
     /**
+     * Reports wheel ticks
+     *
+     * The first four elements represent ticks for individual wheels in the
+     * following order: front left, front right, rear right, rear left.  All
+     * tick counts are cumulative.  Tick counts increment when the vehicle
+     * moves forward, and decrement when vehicles moves in reverse.  The ticks
+     * should be reset to 0 when the vehicle is started by the user.
+     *
+     * The next element in the vector is a reset count.  A reset indicates
+     * previous tick counts are not comparable with this and future ones.  Some
+     * sort of discontinuity in tick counting has occurred.
+     *
+     *  int64Values[0] = reset count
+     *  int64Values[1] = front left ticks
+     *  int64Values[2] = front right ticks
+     *  int64Values[3] = rear right ticks
+     *  int64Values[4] = rear left ticks
+     *
+     * configArray is used to indicate the micrometers-per-wheel-tick value as well as
+     * which wheels are supported.  configArray is set as follows:
+     *
+     *  configArray[0], bits [0:3] = supported wheels.  Uses enum Wheel.
+     *  configArray[1] = micrometers per front left wheel tick
+     *  configArray[2] = micrometers per front right wheel tick
+     *  configArray[3] = micrometers per rear right wheel tick
+     *  configArray[4] = micrometers per rear left wheel tick
+     *
+     * NOTE:  If a wheel is not supported, its value shall always be set to 0.
+     *
+     * VehiclePropValue.timestamp must be correctly filled in.
+     *
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+     * @access VehiclePropertyAccess:READ
+     *
+     * @since o.mr1
+     */
+    WHEEL_TICK = (
+      0x0306
+      | VehiclePropertyGroup:SYSTEM
+      | VehiclePropertyType:COMPLEX
+      | VehicleArea:GLOBAL),
+
+
+    /**
      * Currently selected gear
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
@@ -328,6 +372,34 @@ enum VehicleProperty: int32_t {
             | VehicleArea:GLOBAL),
 
     /**
+     * ABS is active.  Set to true whenever ABS is activated.  Reset to false when ABS is off.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     *
+     * @since o.mr1
+     */
+    ABS_ACTIVE = (
+        0x040A
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:BOOLEAN
+        | VehicleArea:GLOBAL),
+
+    /**
+     * Traction Control is active.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     *
+     * @since o.mr1
+     */
+    TRACTION_CONTROL_ACTIVE = (
+        0x040B
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:BOOLEAN
+        | VehicleArea:GLOBAL),
+
+    /**
      * Fan speed setting
      *
      * IVehicle#set may return StatusCode::NOT_AVAILABLE and IVehicle#get is not
@@ -604,6 +676,24 @@ enum VehicleProperty: int32_t {
         | VehicleArea:ZONE),
 
     /**
+     * Represents power state for HVAC. Some HVAC properties must require
+     * matching power to be turned on to get out of OFF state. For non-zoned
+     * HVAC properties, VEHICLE_ALL_ZONE corresponds to global power state.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @config_string list of HVAC properties whose power is controlled by this
+     *                property. Format is hexa-decimal number (0x...) separated
+     *                by comma like "0x500,0x503". All zones defined in these
+     *                affected properties must be available in the property.
+     */
+    HVAC_POWER_ON = (
+        0x0510
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:BOOLEAN
+        | VehicleArea:ZONE),
+
+    /**
      * Fan Positions Available
      *
      * This is a bit mask of fan positions available for the zone.  Each entry in
@@ -623,19 +713,18 @@ enum VehicleProperty: int32_t {
         | VehicleArea:ZONE),
 
     /**
-     * Represents power state for HVAC. Some HVAC properties must require
-     * matching power to be turned on to get out of OFF state. For non-zoned
-     * HVAC properties, VEHICLE_ALL_ZONE corresponds to global power state.
+     * Automatic re-circulation on/off
+     *
+     * IVehicle#set and IVehicle#get must return StatusCode::NOT_AVAILABLE when HVAC unit is off.
+     * See HVAC_POWER_ON property for details.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
-     * @config_string list of HVAC properties whose power is controlled by this
-     *                property. Format is hexa-decimal number (0x...) separated
-     *                by comma like "0x500,0x503". All zones defined in these
-     *                affected properties must be available in the property.
+     *
+     * @since o.mr1
      */
-    HVAC_POWER_ON = (
-        0x0510
+    HVAC_AUTO_RECIRC_ON = (
+        0x0512
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:BOOLEAN
         | VehicleArea:ZONE),
@@ -696,7 +785,8 @@ enum VehicleProperty: int32_t {
      * requested by Android side. The focus has both per stream characteristics
      * and global characteristics.
      *
-     * Focus request (get of this property) must take the following form:
+     * Focus request (get of this property) must take the following form with indices defined
+     * by VehicleAudioFocusIndex:
      *   int32Values[0]: VehicleAudioFocusRequest type
      *   int32Values[1]: bit flags of streams requested by this focus request.
      *                   There can be up to 32 streams.
@@ -714,7 +804,7 @@ enum VehicleProperty: int32_t {
      *                   REQUEST_RELEASE). In that case, audio module must
      *                   maintain mute state until user's explicit action to
      *                   play some media.
-     *   int32Values[3]: Currently active audio contexts. Use combination of
+     *   int32Values[3]: Audio contexts wishing to be active. Use combination of
      *                   flags from VehicleAudioContextFlag.
      *                   This can be used as a hint to adjust audio policy or
      *                   other policy decision.
@@ -729,7 +819,7 @@ enum VehicleProperty: int32_t {
      * request.
      *
      * Focus response (set and subscription callback for this property) must
-     * take the following form:
+     * take the following form with indices defined by VehicleAudioFocusIndex:
      *   int32Values[0]: VehicleAudioFocusState type
      *   int32Values[1]: bit flags of streams allowed.
      *   int32Values[2]: External focus state: bit flags of currently active
@@ -742,22 +832,26 @@ enum VehicleProperty: int32_t {
      *                   0 means no active audio focus holder outside Android.
      *                   The state must have following values for each
      *                   VehicleAudioFocusState:
-     *                   GAIN: 0 or VehicleAudioExtFocusFlag#PLAY_ONLY_FLAG
-     *                       when radio is active in Android side.
-     *                   GAIN_TRANSIENT: 0. Can be
+     *                   GAIN: VehicleAudioExtFocusFlag#PLAY_ONLY_FLAG
+     *                       when radio is active in Android side. Otherwise,
+     *                       VehicleAudioExtFocusFlag#NONE_FLAG.
+     *                   GAIN_TRANSIENT: Can be
      *                       VehicleAudioExtFocusFlag#PERMANENT_FLAG or
      *                       VehicleAudioExtFocusFlag#TRANSIENT_FLAG if android
      *                       side has requested
      *                       REQUEST_GAIN_TRANSIENT_MAY_DUCK and car side is
-     *                       ducking.
-     *                   LOSS: 0 when no focus is audio is active in car side.
+     *                       ducking. Otherwise
+     *                       VehicleAudioExtFocusFlag#NONE_FLAG.
+     *                   LOSS: VehicleAudioExtFocusFlag#NONE_FLAG when no focus
+     *                       is active in car side.
      *                       VehicleAudioExtFocusFlag#PERMANENT_FLAG when car
      *                       side is playing something permanent.
-     *                   LOSS_TRANSIENT: always must be
+     *                   LOSS_TRANSIENT: must always be
      *                       VehicleAudioExtFocusFlag#PERMANENT_FLAG
-     *   int32Values[3]: context requested by android side when responding to
-     *                   focus request. When car side is taking focus away,
-     *                   this must be zero.
+     *   int32Values[3]: Audio context(s) allowed to be active. When responding positively to a
+     *                   focus request from Android, the request's original context must be
+     *                   repeated here. When taking focus away, or denying a request, the
+     *                   rejected or stopped context would have its corresponding bit cleared.
      *
      * A focus response must be sent per each focus request even if there is
      * no change in focus state. This can happen in case like focus request
@@ -798,8 +892,8 @@ enum VehicleProperty: int32_t {
      *
      * VehiclePropConfig
      *   configArray[0] : bit flags of all supported audio contexts from
-     *                    VehicleAudioContextFlag. If this is 0, audio volume is
-     *                    controlled per physical stream.
+     *                    VehicleAudioContextFlag. If this is 0, audio volume
+     *                    is controlled per physical stream.
      *   configArray[1] : flags defined in VehicleAudioVolumeCapabilityFlag to
      *                    represent audio module's capability.
      *   configArray[2..3] : reserved
@@ -809,7 +903,7 @@ enum VehicleProperty: int32_t {
      *                         indicates mute state.
      *
      * Data type looks like:
-     *   int32Values[0] : stream context as defined in VehicleAudioContextFlag.
+     *   int32Values[0] : audio context as defined in VehicleAudioContextFlag.
      *                    If only physical stream is supported
      *                    (configArray[0] == 0), this must represent physical
      *                    stream number.
@@ -817,8 +911,8 @@ enum VehicleProperty: int32_t {
      *                    defined in the config.
      *   int32Values[2] : One of VehicleAudioVolumeState.
      *
-     * This property requires per stream based get. HAL implementation must
-     * check stream number in get call to return the right volume.
+     * HAL implementations must check the incoming value of audio context
+     * field in get call to return the right volume.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
@@ -857,18 +951,18 @@ enum VehicleProperty: int32_t {
      *                    to represent audio module's capability.
      *
      * Data type looks like:
-     *   int32Values[0] : stream context as defined in VehicleAudioFocusFlag.
+     *   int32Values[0] : audio context as defined in VehicleAudioContextFlag.
      *                    If only physical stream is supported
      *                    (configArray[0] == 0), this must represent physical
      *                    stream number.
      *   int32Values[1] : maximum volume set to the stream. If there is no
-     *                    restriction, this value must be  bigger than
+     *                    restriction, this value must be equal to
      *                    AUDIO_VOLUME's max value.
      *
      * If car does not support this feature, this property must not be
      * populated by HAL.
-     * This property requires per stream based get. HAL implementation must
-     * check stream number in get call to return the right volume.
+     * HAL implementations must check the incoming value of audio context
+     * field in get call to return the right volume.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
@@ -882,10 +976,8 @@ enum VehicleProperty: int32_t {
 
     /**
      * Property to share audio routing policy of android side. This property is
-     * set at the beginning to pass audio policy in android side down to
+     * set at startup to pass audio policy in android side down to
      * vehicle HAL and car audio module.
-     * This can be used as a hint to adjust audio policy or other policy
-     * decision.
      *
      *   int32Values[0] : audio stream where the audio for the application
      *                    context must be routed by default. Note that this is
@@ -893,7 +985,7 @@ enum VehicleProperty: int32_t {
      *                    still use different audio stream for whatever reason.
      *   int32Values[1] : All audio contexts that must be sent through the
      *                     physical stream. Flag is defined in
-     *                     VehicleAudioFocusFlag.
+     *                     VehicleAudioContextFlag.
 
      * Setting of this property must be done for all available physical streams
      * based on audio H/W variant information acquired from AUDIO_HW_VARIANT
@@ -909,11 +1001,11 @@ enum VehicleProperty: int32_t {
         | VehicleArea:GLOBAL),
 
     /**
-     * Property to return audio H/W variant type used in this car. This allows
-     * android side to support different audio policy based on H/W variant used.
-     * Note that other components like CarService may need overlay update to
-     * support additional variants. If this property does not
-     * exist, default audio policy must be used.
+     * Property to return audio H/W variant type used in this car. This is a
+     * zero based index into the set of audio routing policies defined in
+     * R.array.audioRoutingPolicy on CarService, which  may be overlaid to
+     * support multiple variants. If this property does not exist, the default
+     * audio policy must be used.
      *
      * @change_mode VehiclePropertyChangeMode:STATIC
      * @access VehiclePropertyAccess:READ
@@ -942,14 +1034,13 @@ enum VehicleProperty: int32_t {
      * for the routing.
      * This property can support up to 128 external routings.
      * To give full flexibility, there is no standard definition for each bit
-     * flag and assigning each big flag to specific routing type is decided by
+     * flag and assigning each bit flag to specific routing type is decided by
      * VehiclePropConfig#configString.  VehiclePropConfig#configString has
      * format of each entry separated by ',' and each entry has format of
      * bitFlagPositon:typeString[:physicalStreamNumber].
-     *  bitFlagPosition: represents which big flag will be set to enable this
-     *  routing. 0 means
-     *    LSB in int32Values[0]. 31 will be MSB in int32Values[0]. 127 will MSB
-     *    in int32Values[3].
+     *  bitFlagPosition: represents which bit flag will be set to enable this
+     *    routing. 0 means LSB in int32Values[0]. 31 will be MSB in
+     *    int32Values[0]. 127 will MSB in int32Values[3].
      *  typeString: string representation of external routing. Some types are
      *    already defined in AUDIO_EXT_ROUTING_SOURCE_* and use them first
      *    before adding something custom. Applications will find each routing
@@ -1126,10 +1217,11 @@ enum VehicleProperty: int32_t {
      *                    change. Instrument cluster still needs to send
      *                    event with new mode to trigger actual mode change.
      *   int32Values[1] : The current app context relevant for instrument
-     *                    cluster. Use the same flag with VehicleAudioFocusFlag
-     *                    but this context represents active apps, not
-     *                    active audio. Instrument cluster side may change mode
-     *                    depending on the currently active contexts.
+     *                    cluster. Use the same flag with
+     *                    VehicleAudioContextFlag but this context represents
+     *                    active apps, not active audio. Instrument cluster
+     *                    side may change mode depending on the currently
+     *                    active contexts.
      *  When system boots up, Android side will write {0, 0, 0, 0} when it is
      *  ready to render to instrument cluster. Before this message, rendering
      *  from android must not be visible in the cluster.
@@ -1790,85 +1882,240 @@ enum VehicleProperty: int32_t {
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:BOOLEAN
         | VehicleArea:GLOBAL),
+
+
+    /**
+     * Vehicle Maps Service (VMS) message
+     *
+     * This property uses COMPLEX data to communicate vms messages.
+     *
+     * Its contents are to be interpreted as follows:
+     * the indices defined in VmsMessageIntegerValuesIndex are to be used to
+     * read from int32Values;
+     * bytes is a serialized VMS message as defined in the vms protocol
+     * which is opaque to the framework;
+     *
+     * IVehicle#get must always return StatusCode::NOT_AVAILABLE.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     *
+     * @since o.mr1
+     */
+    VEHICLE_MAP_SERVICE = (
+        0x0C00
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:COMPLEX
+        | VehicleArea:GLOBAL),
+
+    /**
+     * OBD2 Live Sensor Data
+     *
+     * Reports a snapshot of the current (live) values of the OBD2 sensors available.
+     *
+     * The configArray is set as follows:
+     *   configArray[0] = number of vendor-specific integer-valued sensors
+     *   configArray[1] = number of vendor-specific float-valued sensors
+     *
+     * The values of this property are to be interpreted as in the following example.
+     * Considering a configArray = {2,3}
+     * int32Values must be a vector containing Obd2IntegerSensorIndex.LAST_SYSTEM_INDEX + 2
+     * elements (that is, 33 elements);
+     * floatValues must be a vector containing Obd2FloatSensorIndex.LAST_SYSTEM_INDEX + 3
+     * elements (that is, 73 elements);
+     *
+     * It is possible for each frame to contain a different subset of sensor values, both system
+     * provided sensors, and vendor-specific ones. In order to support that, the bytes element
+     * of the property value is used as a bitmask,.
+     *
+     * bytes must have a sufficient number of bytes to represent the total number of possible
+     * sensors (in this case, 14 bytes to represent 106 possible values); it is to be read as
+     * a contiguous bitmask such that each bit indicates the presence or absence of a sensor
+     * from the frame, starting with as many bits as the size of int32Values, immediately
+     * followed by as many bits as the size of floatValues.
+     *
+     * For example, should bytes[0] = 0x4C (0b01001100) it would mean that:
+     *   int32Values[0 and 1] are not valid sensor values
+     *   int32Values[2 and 3] are valid sensor values
+     *   int32Values[4 and 5] are not valid sensor values
+     *   int32Values[6] is a valid sensor value
+     *   int32Values[7] is not a valid sensor value
+     * Should bytes[5] = 0x61 (0b01100001) it would mean that:
+     *   int32Values[32] is a valid sensor value
+     *   floatValues[0 thru 3] are not valid sensor values
+     *   floatValues[4 and 5] are valid sensor values
+     *   floatValues[6] is not a valid sensor value
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     *
+     * @since o.mr1
+     */
+    OBD2_LIVE_FRAME = (
+      0x0D00
+      | VehiclePropertyGroup:SYSTEM
+      | VehiclePropertyType:COMPLEX
+      | VehicleArea:GLOBAL),
+
+    /**
+     * OBD2 Freeze Frame Sensor Data
+     *
+     * Reports a snapshot of the value of the OBD2 sensors available at the time that a fault
+     * occurred and was detected.
+     *
+     * A configArray must be provided with the same meaning as defined for OBD2_LIVE_FRAME.
+     *
+     * The values of this property are to be interpreted in a similar fashion as those for
+     * OBD2_LIVE_FRAME, with the exception that the stringValue field may contain a non-empty
+     * diagnostic troubleshooting code (DTC).
+     *
+     * A IVehicle#get request of this property must provide a value for int64Values[0].
+     * This will be interpreted as the timestamp of the freeze frame to retrieve. A list of
+     * timestamps can be obtained by a IVehicle#get of OBD2_FREEZE_FRAME_INFO.
+     *
+     * Should no freeze frame be available at the given timestamp, a response of NOT_AVAILABLE
+     * must be returned by the implementation. Because vehicles may have limited storage for
+     * freeze frames, it is possible for a frame request to respond with NOT_AVAILABLE even if
+     * the associated timestamp has been recently obtained via OBD2_FREEZE_FRAME_INFO.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     *
+     * @since o.mr1
+     */
+    OBD2_FREEZE_FRAME = (
+      0x0D01
+      | VehiclePropertyGroup:SYSTEM
+      | VehiclePropertyType:COMPLEX
+      | VehicleArea:GLOBAL),
+
+    /**
+     * OBD2 Freeze Frame Information
+     *
+     * This property describes the current freeze frames stored in vehicle
+     * memory and available for retrieval via OBD2_FREEZE_FRAME.
+     *
+     * The values are to be interpreted as follows:
+     * each element of int64Values must be the timestamp at which a a fault code
+     * has been detected and the corresponding freeze frame stored, and each
+     * such element can be used as the key to OBD2_FREEZE_FRAME to retrieve
+     * the corresponding freeze frame.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     *
+     * @since o.mr1
+     */
+    OBD2_FREEZE_FRAME_INFO = (
+      0x0D02
+      | VehiclePropertyGroup:SYSTEM
+      | VehiclePropertyType:COMPLEX
+      | VehicleArea:GLOBAL),
+
+    /**
+     * OBD2 Freeze Frame Clear
+     *
+     * This property allows deletion of any of the freeze frames stored in
+     * vehicle memory, as described by OBD2_FREEZE_FRAME_INFO.
+     *
+     * The configArray is set as follows:
+     *  configArray[0] = 1 if the implementation is able to clear individual freeze frames
+     *                   by timestamp, 0 otherwise
+     *
+     * IVehicle#set of this property is to be interpreted as follows:
+     *   if int64Values contains no elements, then all frames stored must be cleared;
+     *   if int64Values contains one or more elements, then frames at the timestamps
+     *   stored in int64Values must be cleared, and the others not cleared. Should the
+     *   vehicle not support selective clearing of freeze frames, this latter mode must
+     *   return NOT_AVAILABLE.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:WRITE
+     *
+     * @since o.mr1
+     */
+    OBD2_FREEZE_FRAME_CLEAR = (
+      0x0D03
+      | VehiclePropertyGroup:SYSTEM
+      | VehiclePropertyType:COMPLEX
+      | VehicleArea:GLOBAL),
 };
 
 /**
  * Bit flags for fan direction
  */
 enum VehicleHvacFanDirection : int32_t {
-  FACE = 0x1,
-  FLOOR = 0x2,
-  FACE_AND_FLOOR = 0x3,
-  DEFROST = 0x4,
-  DEFROST_AND_FLOOR = 0x5,
+    FACE = 0x1,
+    FLOOR = 0x2,
+    FACE_AND_FLOOR = 0x3,
+    DEFROST = 0x4,
+    DEFROST_AND_FLOOR = 0x5,
 };
 
 /**
  * Constants relevant to radio.
  */
 enum VehicleRadioConstants : int32_t {
-  /** Minimum value for the radio preset */
-  VEHICLE_RADIO_PRESET_MIN_VALUE = 1,
+    /** Minimum value for the radio preset */
+    VEHICLE_RADIO_PRESET_MIN_VALUE = 1,
 };
 
 enum VehicleAudioFocusRequest : int32_t {
-  REQUEST_GAIN = 0x1,
-  REQUEST_GAIN_TRANSIENT = 0x2,
-  REQUEST_GAIN_TRANSIENT_MAY_DUCK = 0x3,
-  /**
-   * This is for the case where android side plays sound like UI feedback
-   * and car side does not need to duck existing playback as long as
-   * requested stream is available.
-   */
-  REQUEST_GAIN_TRANSIENT_NO_DUCK = 0x4,
-  REQUEST_RELEASE = 0x5,
-
+    REQUEST_GAIN = 0x1,
+    REQUEST_GAIN_TRANSIENT = 0x2,
+    REQUEST_GAIN_TRANSIENT_MAY_DUCK = 0x3,
+    /**
+     * This is for the case where android side plays sound like UI feedback
+     * and car side does not need to duck existing playback as long as
+     * requested stream is available.
+     */
+    REQUEST_GAIN_TRANSIENT_NO_DUCK = 0x4,
+    REQUEST_RELEASE = 0x5,
 };
 
 enum VehicleAudioFocusState : int32_t {
-  /**
-   * Android side has permanent focus and can play allowed streams.
-   */
-  STATE_GAIN = 0x1,
-
-  /**
-   * Android side has transient focus and can play allowed streams.
-   */
-  STATE_GAIN_TRANSIENT = 0x2,
+    /**
+     * Android side has permanent focus and can play allowed streams.
+     */
+    STATE_GAIN = 0x1,
 
-  /**
-   * Car audio module is playing guidance kind of sound outside Android.
-   * Android side can still play through allowed streams with ducking.
-   */
-  STATE_LOSS_TRANSIENT_CAN_DUCK = 0x3,
+    /**
+     * Android side has transient focus and can play allowed streams.
+     */
+    STATE_GAIN_TRANSIENT = 0x2,
 
-  /**
-   * Car audio module is playing transient sound outside Android. Android side
-   * must stop playing any sounds.
-   */
-  STATE_LOSS_TRANSIENT = 0x4,
+    /**
+     * Car audio module is playing guidance kind of sound outside Android.
+     * Android side can still play through allowed streams with ducking.
+     */
+    STATE_LOSS_TRANSIENT_CAN_DUCK = 0x3,
 
-  /**
-   * Android side has lost focus and cannot play any sound.
-   */
-  STATE_LOSS = 0x5,
+    /**
+     * Car audio module is playing transient sound outside Android. Android side
+     * must stop playing any sounds.
+     */
+    STATE_LOSS_TRANSIENT = 0x4,
 
-  /**
-   * car audio module is playing safety critical sound, and Android side cannot
-   * request focus until the current state is finished. car audio module
-   * restore it to the previous state when it can allow Android to play.
-   */
-  STATE_LOSS_TRANSIENT_EXLCUSIVE = 0x6,
+    /**
+     * Android side has lost focus and cannot play any sound.
+     */
+    STATE_LOSS = 0x5,
 
+    /**
+     * car audio module is playing safety critical sound, and Android side cannot
+     * request focus until the current state is finished. car audio module
+     * restore it to the previous state when it can allow Android to play.
+     */
+    STATE_LOSS_TRANSIENT_EXLCUSIVE = 0x6,
 };
 
 /**
  * Flags to represent multiple streams by combining these.
  */
 enum VehicleAudioStreamFlag : int32_t {
-  STREAM0_FLAG = (0x1 << 0),
-  STREAM1_FLAG = (0x1 << 1),
-  STREAM2_FLAG = (0x1 << 2),
+    STREAM0_FLAG = (0x1 << 0),
+    STREAM1_FLAG = (0x1 << 1),
+    STREAM2_FLAG = (0x1 << 2),
 };
 
 /**
@@ -1876,107 +2123,110 @@ enum VehicleAudioStreamFlag : int32_t {
  * Can be used for audio related property expecting one stream.
  */
 enum VehicleAudioStream : int32_t {
-  STREAM0 = 0,
-  STREAM1 = 1,
+    STREAM0 = 0,
+    STREAM1 = 1,
 };
 
 /**
  * Flag to represent external focus state (outside Android).
  */
 enum VehicleAudioExtFocusFlag : int32_t {
-  /**
-   * No external focus holder.
-   */
-  NONE_FLAG = 0x0,
+    /**
+     * No external focus holder.
+     */
+    NONE_FLAG = 0x0,
 
-  /**
-   * Car side (outside Android) has component holding GAIN kind of focus state.
-   */
-  PERMANENT_FLAG = 0x1,
+    /**
+     * Car side (outside Android) has component holding GAIN kind of focus state.
+     */
+    PERMANENT_FLAG = 0x1,
 
-  /**
-   * Car side (outside Android) has component holding GAIN_TRANSIENT kind of
-   * focus state.
-   */
-  TRANSIENT_FLAG = 0x2,
+    /**
+     * Car side (outside Android) has component holding GAIN_TRANSIENT kind of
+     * focus state.
+     */
+    TRANSIENT_FLAG = 0x2,
 
-  /**
-   * Car side is expected to play something while focus is held by Android side.
-   * One example can be radio attached in car side. But Android's radio app
-   * still must have focus, and Android side must be in GAIN state, but
-   * media stream will not be allocated to Android side and car side can play
-   * radio any time while this flag is active.
-   */
-  PLAY_ONLY_FLAG = 0x4,
+    /**
+     * Car side is expected to play something while focus is held by Android side.
+     * One example can be radio attached in car side. But Android's radio app
+     * still must have focus, and Android side must be in GAIN state, but
+     * media stream will not be allocated to Android side and car side can play
+     * radio any time while this flag is active.
+     */
+    PLAY_ONLY_FLAG = 0x4,
 
-  /**
-   * Car side must mute any media including radio. This can be used with any
-   * focus request including GAIN* and RELEASE.
-   */
-  MUTE_MEDIA_FLAG = 0x8,
+    /**
+     * Car side must mute any media including radio. This can be used with any
+     * focus request including GAIN* and RELEASE.
+     */
+    MUTE_MEDIA_FLAG = 0x8,
 };
 
 /**
  * Index in int32Values for VehicleProperty#AUDIO_FOCUS property.
  */
 enum VehicleAudioFocusIndex : int32_t {
-  FOCUS = 0,
-  STREAMS = 1,
-  EXTERNAL_FOCUS_STATE = 2,
-  AUDIO_CONTEXTS = 3,
+    FOCUS = 0,
+    STREAMS = 1,
+    EXTERNAL_FOCUS_STATE = 2,
+    AUDIO_CONTEXTS = 3,
 };
 
 /**
  * Flags to tell the current audio context.
  */
 enum VehicleAudioContextFlag : int32_t {
-  /** Music playback is currently active. */
-  MUSIC_FLAG = 0x1,
+    /** Music playback is currently active. */
+    MUSIC_FLAG = 0x1,
 
-  /** Navigation is currently running. */
-  NAVIGATION_FLAG = 0x2,
+    /** Navigation is currently running. */
+    NAVIGATION_FLAG = 0x2,
 
-  /** Voice command session is currently running. */
-  VOICE_COMMAND_FLAG = 0x4,
+    /** Voice command session is currently running. */
+    VOICE_COMMAND_FLAG = 0x4,
 
-  /** Voice call is currently active. */
-  CALL_FLAG = 0x8,
+    /** Voice call is currently active. */
+    CALL_FLAG = 0x8,
 
-  /**
-   * Alarm is active.
-   * This must be only used in VehicleProperty#AUDIO_ROUTING_POLICY.
-   */
-  ALARM_FLAG = 0x10,
+    /**
+     * Alarm is active.
+     * This must be only used in VehicleProperty#AUDIO_ROUTING_POLICY.
+     */
+    ALARM_FLAG = 0x10,
 
-  /**
-   * Notification sound is active.
-   * This must be only used in VehicleProperty#AUDIO_ROUTING_POLICY.
-   */
-  NOTIFICATION_FLAG = 0x20,
+    /**
+     * Notification sound is active.
+     * This must be only used in VehicleProperty#AUDIO_ROUTING_POLICY.
+     */
+    NOTIFICATION_FLAG = 0x20,
 
-  /**
-   * Context unknown. Only used for VehicleProperty#AUDIO_ROUTING_POLICY to
-   * represent default stream for unknown contents.
-   */
-  UNKNOWN_FLAG = 0x40,
+    /**
+     * Context unknown. Only used for VehicleProperty#AUDIO_ROUTING_POLICY to
+     * represent default stream for unknown contents.
+     */
+    UNKNOWN_FLAG = 0x40,
+
+    /** Safety alert / warning is played. */
+    SAFETY_ALERT_FLAG = 0x80,
 
-  /** Safety alert / warning is played. */
-  SAFETY_ALERT_FLAG = 0x80,
+    /** CD / DVD kind of audio is played */
+    CD_ROM_FLAG = 0x100,
 
-  /** CD / DVD kind of audio is played */
-  CD_ROM_FLAG = 0x100,
+    /** Aux audio input is played */
+    AUX_AUDIO_FLAG = 0x200,
 
-  /** Aux audio input is played */
-  AUX_AUDIO_FLAG = 0x200,
+    /** system sound like UI feedback */
+    SYSTEM_SOUND_FLAG = 0x400,
 
-  /** system sound like UI feedback */
-  SYSTEM_SOUND_FLAG = 0x400,
+    /** Radio is played */
+    RADIO_FLAG = 0x800,
 
-  /** Radio is played */
-  RADIO_FLAG = 0x800,
+    /** Ext source is played. This is for tagging generic ext sources. */
+    EXT_SOURCE_FLAG = 0x1000,
 
-  /** Ext source is played. This is for tagging generic ext sources. */
-  EXT_SOURCE_FLAG = 0x1000,
+    /** The phone ring tone is played */
+    RINGTONE_FLAG = 0x2000
 };
 
 /**
@@ -1984,65 +2234,65 @@ enum VehicleAudioContextFlag : int32_t {
  * used in configArray[1] of VehiclePropConfig.
  */
 enum VehicleAudioVolumeCapabilityFlag : int32_t {
-  /**
-   * External audio module or vehicle hal has persistent storage
-   * to keep the volume level. This must be set only when per context
-   * volume level is supported. When this is set, audio volume level per
-   * each context will be retrieved from the property when system starts up.
-   * And external audio module is also expected to adjust volume automatically
-   * whenever there is an audio context change.
-   * When this flag is not set, android side will assume that there is no
-   * persistent storage and stored value in android side will be used to
-   * initialize the volume level. And android side will set volume level
-   * of each physical streams whenever there is an audio context change.
-   */
-  PERSISTENT_STORAGE = 0x1,
+    /**
+     * External audio module or vehicle hal has persistent storage to keep the
+     * volume level. When this is set, the audio volume level for each context
+     * will be retrieved from the property when the system starts up.
+     * And external audio module is also expected to adjust volume automatically
+     * whenever there is an audio context change.
+     * When this flag is not set, android side will assume that there is no
+     * persistent storage and the value stored in the android side will be used to
+     * initialize the volume level, and android side will set volume level
+     * of each physical stream whenever there is an audio context change.
+     */
+    PERSISTENT_STORAGE = 0x1,
 
-  /**
-   * When this flag is set, the H/W can support only single master volume for
-   * all streams.
-   * There is no way to set volume level differently per each stream or context.
-   */
-  MASTER_VOLUME_ONLY = 0x2,
+    /**
+     * [DEPRECATED]
+     * When this flag is set, the H/W can support only single master volume for
+     * all streams. There is no way to set volume level differently for each stream
+     * or context.
+     */
+    MASTER_VOLUME_ONLY = 0x2,
 };
 
 /**
  * enum to represent audio volume state.
  */
 enum VehicleAudioVolumeState : int32_t {
-  STATE_OK = 0,
+    STATE_OK = 0,
 
-  /**
-   * Audio volume has reached volume limit set in
-   * VehicleProperty#AUDIO_VOLUME_LIMIT and user's request to increase volume
-   * further is not allowed.
-   */
-  LIMIT_REACHED = 1,
+    /**
+     * Audio volume has reached volume limit set in
+     * VehicleProperty#AUDIO_VOLUME_LIMIT and user's request to increase volume
+     * further is not allowed.
+     */
+    STATE_LIMIT_REACHED = 1,
 };
 
 /**
  * Index in int32Values for VehicleProperty#AUDIO_VOLUME property.
  */
 enum VehicleAudioVolumeIndex : int32_t {
-  INDEX_STREAM = 0,
-  INDEX_VOLUME = 1,
-  INDEX_STATE = 2,
+    STREAM = 0,
+    VOLUME = 1,
+    STATE = 2,
 };
 
 /**
  * Index in int32Values for VehicleProperty#AUDIO_VOLUME_LIMIT property.
  */
 enum VehicleAudioVolumeLimitIndex : int32_t {
-  STREAM = 0,
-  MAX_VOLUME = 1,
+    STREAM = 0,
+    MAX_VOLUME = 1,
 };
 
 /**
  * Index in int32Values for VehicleProperty#AUDIO_ROUTING_POLICY property.
  */
 enum VehicleAudioRoutingPolicyIndex : int32_t {
-  STREAM = 0,
-  CONTEXTS = 1,
+    STREAM = 0,
+    CONTEXTS = 1,
 };
 
 /**
@@ -2054,172 +2304,172 @@ enum VehicleAudioHwVariantConfigFlag : int32_t {
    * Flag to tell that radio is internal to android and radio must
    * be treated like other android stream like media.
    * When this flag is not set or AUDIO_HW_VARIANT does not exist,
-   * radio is treated as external module. This brins some delta in audio focus
+   * radio is treated as external module. This may affect audio focus
    * handling as well.
    */
   INTERNAL_RADIO_FLAG = 0x1,
 };
 
 enum VehicleApPowerStateConfigFlag : int32_t /* NOTE: type is guessed */ {
-  /**
-   * AP can enter deep sleep state. If not set, AP will always shutdown from
-   * VehicleApPowerState#SHUTDOWN_PREPARE power state.
-   */
-  ENABLE_DEEP_SLEEP_FLAG = 0x1,
+    /**
+     * AP can enter deep sleep state. If not set, AP will always shutdown from
+     * VehicleApPowerState#SHUTDOWN_PREPARE power state.
+     */
+    ENABLE_DEEP_SLEEP_FLAG = 0x1,
 
-  /**
-   * The power controller can power on AP from off state after timeout
-   * specified in VehicleApPowerSet VEHICLE_AP_POWER_SET_SHUTDOWN_READY message.
-   */
-  CONFIG_SUPPORT_TIMER_POWER_ON_FLAG = 0x2,
+    /**
+     * The power controller can power on AP from off state after timeout
+     * specified in VehicleApPowerSet VEHICLE_AP_POWER_SET_SHUTDOWN_READY message.
+     */
+    CONFIG_SUPPORT_TIMER_POWER_ON_FLAG = 0x2,
 };
 
 enum VehicleApPowerState : int32_t /* NOTE: type is guessed */ {
-  /** vehicle HAL will never publish this state to AP */
-  OFF = 0,
+    /** vehicle HAL will never publish this state to AP */
+    OFF = 0,
 
-  /** vehicle HAL will never publish this state to AP */
-  DEEP_SLEEP = 1,
+    /** vehicle HAL will never publish this state to AP */
+    DEEP_SLEEP = 1,
 
-  /** AP is on but display must be off. */
-  ON_DISP_OFF = 2,
+    /** AP is on but display must be off. */
+    ON_DISP_OFF = 2,
 
-  /** AP is on with display on. This state allows full user interaction. */
-  ON_FULL = 3,
+    /** AP is on with display on. This state allows full user interaction. */
+    ON_FULL = 3,
 
-  /**
-   * The power controller has requested AP to shutdown. AP can either enter
-   * sleep state or start full shutdown. AP can also request postponing
-   * shutdown by sending VehicleApPowerSetState#SHUTDOWN_POSTPONE message. The
-   * power controller must change power state to this state to shutdown
-   * system.
-   *
-   * int32Values[1] : one of enum_vehicle_ap_power_state_shutdown_param_type
-   */
-  SHUTDOWN_PREPARE = 4,
+    /**
+     * The power controller has requested AP to shutdown. AP can either enter
+     * sleep state or start full shutdown. AP can also request postponing
+     * shutdown by sending VehicleApPowerSetState#SHUTDOWN_POSTPONE message. The
+     * power controller must change power state to this state to shutdown
+     * system.
+     *
+     * int32Values[1] : one of enum_vehicle_ap_power_state_shutdown_param_type
+     */
+    SHUTDOWN_PREPARE = 4,
 };
 
 enum VehicleApPowerStateShutdownParam : int32_t {
-  /** AP must shutdown immediately. Postponing is not allowed. */
-  SHUTDOWN_IMMEDIATELY = 1,
+    /** AP must shutdown immediately. Postponing is not allowed. */
+    SHUTDOWN_IMMEDIATELY = 1,
 
-  /** AP can enter deep sleep instead of shutting down completely. */
-  CAN_SLEEP = 2,
+    /** AP can enter deep sleep instead of shutting down completely. */
+    CAN_SLEEP = 2,
 
-  /** AP can only shutdown with postponing allowed. */
-  SHUTDOWN_ONLY = 3,
+    /** AP can only shutdown with postponing allowed. */
+    SHUTDOWN_ONLY = 3,
 };
 
 enum VehicleApPowerSetState : int32_t /* NOTE: type is guessed */ {
-  /**
-   * AP has finished boot up, and can start shutdown if requested by power
-   * controller.
-   */
-  BOOT_COMPLETE = 0x1,
+    /**
+     * AP has finished boot up, and can start shutdown if requested by power
+     * controller.
+     */
+    BOOT_COMPLETE = 0x1,
 
-  /**
-   * AP is entering deep sleep state. How this state is implemented may vary
-   * depending on each H/W, but AP's power must be kept in this state.
-   */
-  DEEP_SLEEP_ENTRY = 0x2,
+    /**
+     * AP is entering deep sleep state. How this state is implemented may vary
+     * depending on each H/W, but AP's power must be kept in this state.
+     */
+    DEEP_SLEEP_ENTRY = 0x2,
 
-  /**
-   * AP is exiting from deep sleep state, and is in
-   * VehicleApPowerState#SHUTDOWN_PREPARE state.
-   * The power controller may change state to other ON states based on the
-   * current state.
-   */
-  DEEP_SLEEP_EXIT = 0x3,
+    /**
+     * AP is exiting from deep sleep state, and is in
+     * VehicleApPowerState#SHUTDOWN_PREPARE state.
+     * The power controller may change state to other ON states based on the
+     * current state.
+     */
+    DEEP_SLEEP_EXIT = 0x3,
 
-  /**
-   * int32Values[1]: Time to postpone shutdown in ms. Maximum value can be
-   *                 5000 ms.
-   *                 If AP needs more time, it will send another POSTPONE
-   *                 message before the previous one expires.
-   */
-  SHUTDOWN_POSTPONE = 0x4,
+    /**
+     * int32Values[1]: Time to postpone shutdown in ms. Maximum value can be
+     *                 5000 ms.
+     *                 If AP needs more time, it will send another POSTPONE
+     *                 message before the previous one expires.
+     */
+    SHUTDOWN_POSTPONE = 0x4,
 
-  /**
-   * AP is starting shutting down. When system completes shutdown, everything
-   * will stop in AP as kernel will stop all other contexts. It is
-   * responsibility of vehicle HAL or lower level to synchronize that state
-   * with external power controller. As an example, some kind of ping
-   * with timeout in power controller can be a solution.
-   *
-   * int32Values[1]: Time to turn on AP in secs. Power controller may turn on
-   *                 AP after specified time so that AP can run tasks like
-   *                 update. If it is set to 0, there is no wake up, and power
-   *                 controller may not necessarily support wake-up. If power
-   *                 controller turns on AP due to timer, it must start with
-   *                 VehicleApPowerState#ON_DISP_OFF state, and after
-   *                 receiving VehicleApPowerSetState#BOOT_COMPLETE, it shall
-   *                 do state transition to
-   *                 VehicleApPowerState#SHUTDOWN_PREPARE.
-   */
-  SHUTDOWN_START = 0x5,
+    /**
+     * AP is starting shutting down. When system completes shutdown, everything
+     * will stop in AP as kernel will stop all other contexts. It is
+     * responsibility of vehicle HAL or lower level to synchronize that state
+     * with external power controller. As an example, some kind of ping
+     * with timeout in power controller can be a solution.
+     *
+     * int32Values[1]: Time to turn on AP in secs. Power controller may turn on
+     *                 AP after specified time so that AP can run tasks like
+     *                 update. If it is set to 0, there is no wake up, and power
+     *                 controller may not necessarily support wake-up. If power
+     *                 controller turns on AP due to timer, it must start with
+     *                 VehicleApPowerState#ON_DISP_OFF state, and after
+     *                 receiving VehicleApPowerSetState#BOOT_COMPLETE, it shall
+     *                 do state transition to
+     *                 VehicleApPowerState#SHUTDOWN_PREPARE.
+     */
+    SHUTDOWN_START = 0x5,
 
-  /**
-   * User has requested to turn off headunit's display, which is detected in
-   * android side.
-   * The power controller may change the power state to
-   * VehicleApPowerState#ON_DISP_OFF.
-   */
-  DISPLAY_OFF = 0x6,
+    /**
+     * User has requested to turn off headunit's display, which is detected in
+     * android side.
+     * The power controller may change the power state to
+     * VehicleApPowerState#ON_DISP_OFF.
+     */
+    DISPLAY_OFF = 0x6,
 
-  /**
-   * User has requested to turn on headunit's display, most probably from power
-   * key input which is attached to headunit. The power controller may change
-   * the power state to VehicleApPowerState#ON_FULL.
-   */
-  DISPLAY_ON = 0x7,
+    /**
+     * User has requested to turn on headunit's display, most probably from power
+     * key input which is attached to headunit. The power controller may change
+     * the power state to VehicleApPowerState#ON_FULL.
+     */
+    DISPLAY_ON = 0x7,
 };
 
 /**
  * Index in int32Values for VehicleProperty#AP_POWER_STATE property.
  */
 enum VehicleApPowerStateIndex : int32_t {
-  STATE = 0,
-  ADDITIONAL = 1,
+    STATE = 0,
+    ADDITIONAL = 1,
 };
 
 /**
  * Enum to represent bootup reason.
  */
 enum VehicleApPowerBootupReason : int32_t {
-  /**
-   * Power on due to user's pressing of power key or rotating of ignition
-   * switch.
-   */
-  USER_POWER_ON = 0,
+    /**
+     * Power on due to user's pressing of power key or rotating of ignition
+     * switch.
+     */
+    USER_POWER_ON = 0,
 
-  /**
-   * Automatic power on triggered by door unlock or any other kind of automatic
-   * user detection.
-   */
-  USER_UNLOCK = 1,
+    /**
+     * Automatic power on triggered by door unlock or any other kind of automatic
+     * user detection.
+     */
+    USER_UNLOCK = 1,
 
-  /**
-   * Automatic power on triggered by timer. This only happens when AP has asked
-   * wake-up after
-   * certain time through time specified in
-   * VehicleApPowerSetState#SHUTDOWN_START.
-   */
-  TIMER = 2,
+    /**
+     * Automatic power on triggered by timer. This only happens when AP has asked
+     * wake-up after
+     * certain time through time specified in
+     * VehicleApPowerSetState#SHUTDOWN_START.
+     */
+    TIMER = 2,
 };
 
 enum VehicleHwKeyInputAction : int32_t {
-  /** Key down */
-  ACTION_DOWN = 0,
+    /** Key down */
+    ACTION_DOWN = 0,
 
-  /** Key up */
-  ACTION_UP = 1,
+    /** Key up */
+    ACTION_UP = 1,
 };
 
 enum VehicleDisplay : int32_t {
-  /** center console */
-  MAIN = 0,
+    /** center console */
+    MAIN = 0,
 
-  INSTRUMENT_CLUSTER = 1,
+    INSTRUMENT_CLUSTER = 1,
 };
 
 /**
@@ -2312,11 +2562,11 @@ enum VehiclePropertyChangeMode : int32_t {
  * the expected output.
  */
 enum VehiclePropertyAccess : int32_t {
-  NONE = 0x00,
+    NONE = 0x00,
 
-  READ = 0x01,
-  WRITE = 0x02,
-  READ_WRITE = 0x03,
+    READ = 0x01,
+    WRITE = 0x02,
+    READ_WRITE = 0x03,
 };
 
 /**
@@ -2325,32 +2575,32 @@ enum VehiclePropertyAccess : int32_t {
  * The driving states determine what features of the UI will be accessible.
  */
 enum VehicleDrivingStatus : int32_t {
-  UNRESTRICTED = 0x00,
-  NO_VIDEO = 0x01,
-  NO_KEYBOARD_INPUT = 0x02,
-  NO_VOICE_INPUT = 0x04,
-  NO_CONFIG = 0x08,
-  LIMIT_MESSAGE_LEN = 0x10,
+    UNRESTRICTED = 0x00,
+    NO_VIDEO = 0x01,
+    NO_KEYBOARD_INPUT = 0x02,
+    NO_VOICE_INPUT = 0x04,
+    NO_CONFIG = 0x08,
+    LIMIT_MESSAGE_LEN = 0x10,
 };
 
 /**
  * Various gears which can be selected by user and chosen in system.
  */
 enum VehicleGear: int32_t {
-  GEAR_NEUTRAL = 0x0001,
-  GEAR_REVERSE = 0x0002,
-  GEAR_PARK = 0x0004,
-  GEAR_DRIVE = 0x0008,
-  GEAR_LOW = 0x0010,
-  GEAR_1 = 0x0010,
-  GEAR_2 = 0x0020,
-  GEAR_3 = 0x0040,
-  GEAR_4 = 0x0080,
-  GEAR_5 = 0x0100,
-  GEAR_6 = 0x0200,
-  GEAR_7 = 0x0400,
-  GEAR_8 = 0x0800,
-  GEAR_9 = 0x1000,
+    GEAR_NEUTRAL = 0x0001,
+    GEAR_REVERSE = 0x0002,
+    GEAR_PARK = 0x0004,
+    GEAR_DRIVE = 0x0008,
+    GEAR_LOW = 0x0010,
+    GEAR_1 = 0x0010,
+    GEAR_2 = 0x0020,
+    GEAR_3 = 0x0040,
+    GEAR_4 = 0x0080,
+    GEAR_5 = 0x0100,
+    GEAR_6 = 0x0200,
+    GEAR_7 = 0x0400,
+    GEAR_8 = 0x0800,
+    GEAR_9 = 0x1000,
 };
 
 /**
@@ -2610,73 +2860,73 @@ enum VehiclePropertyOperation : int32_t {
 
 
 enum SubscribeFlags : int32_t {
-  UNDEFINED = 0x0,
+    UNDEFINED = 0x0,
 
-  /**
-   * Subscribe to event that was originated in vehicle HAL
-   * (most likely this event came from the vehicle itself).
-   */
-  HAL_EVENT = 0x1,
+    /**
+     * Subscribe to event that was originated in vehicle HAL
+     * (most likely this event came from the vehicle itself).
+     */
+    HAL_EVENT = 0x1,
 
-  /**
-   * Use this flag to subscribe on events when IVehicle#set(...) was called by
-   * vehicle HAL's client (e.g. Car Service).
-   */
-  SET_CALL = 0x2,
+    /**
+     * Use this flag to subscribe on events when IVehicle#set(...) was called by
+     * vehicle HAL's client (e.g. Car Service).
+     */
+    SET_CALL = 0x2,
 
-  DEFAULT = HAL_EVENT,
+    DEFAULT = HAL_EVENT,
 };
 
 /**
  * Encapsulates information about subscription to vehicle property events.
  */
 struct SubscribeOptions {
-  /** Property to subscribe */
-  int32_t propId;
+    /** Property to subscribe */
+    int32_t propId;
 
-  /**
-   * Area ids - this must be a bit mask of areas to subscribe or 0 to subscribe
-   * to all areas.
-   */
-  int32_t vehicleAreas;
+    /**
+     * Area ids - this must be a bit mask of areas to subscribe or 0 to subscribe
+     * to all areas.
+     */
+    int32_t vehicleAreas;
 
-  /**
-   * Sample rate in Hz.
-   *
-   * Must be provided for properties with
-   * VehiclePropertyChangeMode::CONTINUOUS. The value must be within
-   * VehiclePropConfig#minSamplingRate .. VehiclePropConfig#maxSamplingRate
-   * for a given property.
-   * This value indicates how many updates per second client wants to receive.
-   */
-  float sampleRate;
+    /**
+     * Sample rate in Hz.
+     *
+     * Must be provided for properties with
+     * VehiclePropertyChangeMode::CONTINUOUS. The value must be within
+     * VehiclePropConfig#minSamplingRate .. VehiclePropConfig#maxSamplingRate
+     * for a given property.
+     * This value indicates how many updates per second client wants to receive.
+     */
+    float sampleRate;
 
-  /** Flags that indicate what kind of events listen to. */
-  SubscribeFlags flags;
+    /** Flags that indicate what kind of events listen to. */
+    SubscribeFlags flags;
 };
 
 /** Error codes used in vehicle HAL interface. */
 enum StatusCode : int32_t {
-  OK = 0,
+    OK = 0,
 
-  /** Try again. */
-  TRY_AGAIN = 1,
+    /** Try again. */
+    TRY_AGAIN = 1,
 
-  /** Invalid argument provided. */
-  INVALID_ARG = 2,
+    /** Invalid argument provided. */
+    INVALID_ARG = 2,
 
-  /**
-   * This code must be returned when device that associated with the vehicle
-   * property is not available. For example, when client tries to set HVAC
-   * temperature when the whole HVAC unit is turned OFF.
-   */
-  NOT_AVAILABLE = 3,
+    /**
+     * This code must be returned when device that associated with the vehicle
+     * property is not available. For example, when client tries to set HVAC
+     * temperature when the whole HVAC unit is turned OFF.
+     */
+    NOT_AVAILABLE = 3,
 
-  /** Access denied */
-  ACCESS_DENIED = 4,
+    /** Access denied */
+    ACCESS_DENIED = 4,
 
-  /** Something unexpected has happened in Vehicle HAL */
-  INTERNAL_ERROR = 5,
+    /** Something unexpected has happened in Vehicle HAL */
+    INTERNAL_ERROR = 5,
 };
 
 enum Wheel : int32_t {
@@ -2687,3 +2937,460 @@ enum Wheel : int32_t {
     LEFT_REAR = 0x4,
     RIGHT_REAR = 0x8,
 };
+
+/**
+ * The status of the vehicle's fuel system.
+ * These values come from the SAE J1979 standard.
+ */
+enum Obd2FuelSystemStatus : int32_t {
+    OPEN_INSUFFICIENT_ENGINE_TEMPERATURE = 1,
+    CLOSED_LOOP = 2,
+    OPEN_ENGINE_LOAD_OR_DECELERATION = 4,
+    OPEN_SYSTEM_FAILURE = 8,
+    CLOSED_LOOP_BUT_FEEDBACK_FAULT = 16,
+};
+
+/** Defines which ignition monitors are available to be read. */
+enum Obd2IgnitionMonitorKind : int32_t {
+    SPARK = 0,
+    COMPRESSION = 1,
+};
+
+/**
+ * Ignition monitors common to both SPARK and COMPRESSION.
+ * These values come from the SAE J1979 standard.
+ */
+enum Obd2CommonIgnitionMonitors : int32_t {
+    COMPONENTS_AVAILABLE = 0x1 << 0,
+    COMPONENTS_INCOMPLETE = 0x1 << 1,
+
+    FUEL_SYSTEM_AVAILABLE = 0x1 << 2,
+    FUEL_SYSTEM_INCOMPLETE = 0x1 << 3,
+
+    MISFIRE_AVAILABLE = 0x1 << 4,
+    MISFIRE_INCOMPLETE = 0x1 << 5,
+};
+
+/**
+ * Ignition monitors available for SPARK vehicles.
+ * These values come from the SAE J1979 standard.
+ */
+enum Obd2SparkIgnitionMonitors : Obd2CommonIgnitionMonitors {
+    EGR_AVAILABLE = 0x1 << 6,
+    EGR_INCOMPLETE = 0x1 << 7,
+
+    OXYGEN_SENSOR_HEATER_AVAILABLE = 0x1 << 8,
+    OXYGEN_SENSOR_HEATER_INCOMPLETE = 0x1 << 9,
+
+    OXYGEN_SENSOR_AVAILABLE = 0x1 << 10,
+    OXYGEN_SENSOR_INCOMPLETE = 0x1 << 11,
+
+    AC_REFRIGERANT_AVAILABLE = 0x1 << 12,
+    AC_REFRIGERANT_INCOMPLETE = 0x1 << 13,
+
+    SECONDARY_AIR_SYSTEM_AVAILABLE = 0x1 << 14,
+    SECONDARY_AIR_SYSTEM_INCOMPLETE = 0x1 << 15,
+
+    EVAPORATIVE_SYSTEM_AVAILABLE = 0x1 << 16,
+    EVAPORATIVE_SYSTEM_INCOMPLETE = 0x1 << 17,
+
+    HEATED_CATALYST_AVAILABLE = 0x1 << 18,
+    HEATED_CATALYST_INCOMPLETE = 0x1 << 19,
+
+    CATALYST_AVAILABLE = 0x1 << 20,
+    CATALYST_INCOMPLETE = 0x1 << 21,
+};
+
+/**
+ * Ignition monitors only available for COMPRESSION vehicles.
+ * These values come from the SAE J1979 standard.
+ */
+enum Obd2CompressionIgnitionMonitors : Obd2CommonIgnitionMonitors {
+    EGR_OR_VVT_AVAILABLE = 0x1 << 6,
+    EGR_OR_VVT_INCOMPLETE = 0x1 << 7,
+
+    PM_FILTER_AVAILABLE = 0x1 << 8,
+    PM_FILTER_INCOMPLETE = 0x1 << 9,
+
+    EXHAUST_GAS_SENSOR_AVAILABLE = 0x1 << 10,
+    EXHAUST_GAS_SENSOR_INCOMPLETE = 0x1 << 11,
+
+    BOOST_PRESSURE_AVAILABLE = 0x1 << 12,
+    BOOST_PRESSURE_INCOMPLETE = 0x1 << 13,
+
+    NOx_SCR_AVAILABLE = 0x1 << 14,
+    NOx_SCR_INCOMPLETE = 0x1 << 15,
+
+    NMHC_CATALYST_AVAILABLE = 0x1 << 16,
+    NMHC_CATALYST_INCOMPLETE = 0x1 << 17,
+};
+
+/**
+ * The status of the vehicle's secondary air system.
+ * These values come from the SAE J1979 standard.
+ */
+enum Obd2SecondaryAirStatus : int32_t {
+    UPSTREAM = 1,
+    DOWNSTREAM_OF_CATALYCIC_CONVERTER = 2,
+    FROM_OUTSIDE_OR_OFF = 4,
+    PUMP_ON_FOR_DIAGNOSTICS = 8,
+};
+
+/**
+ * The fuel type(s) supported by a vehicle.
+ * These values come from the SAE J1979 standard.
+ */
+enum Obd2FuelType : int32_t {
+    NOT_AVAILABLE = 0,
+    GASOLINE = 1,
+    METHANOL = 2,
+    ETHANOL = 3,
+    DIESEL = 4,
+    LPG = 5,
+    CNG = 6,
+    PROPANE = 7,
+    ELECTRIC = 8,
+    BIFUEL_RUNNING_GASOLINE = 9,
+    BIFUEL_RUNNING_METHANOL = 10,
+    BIFUEL_RUNNING_ETHANOL = 11,
+    BIFUEL_RUNNING_LPG = 12,
+    BIFUEL_RUNNING_CNG = 13,
+    BIFUEL_RUNNING_PROPANE = 14,
+    BIFUEL_RUNNING_ELECTRIC = 15,
+    BIFUEL_RUNNING_ELECTRIC_AND_COMBUSTION = 16,
+    HYBRID_GASOLINE = 17,
+    HYBRID_ETHANOL = 18,
+    HYBRID_DIESEL = 19,
+    HYBRID_ELECTRIC = 20,
+    HYBRID_RUNNING_ELECTRIC_AND_COMBUSTION = 21,
+    HYBRID_REGENERATIVE = 22,
+    BIFUEL_RUNNING_DIESEL = 23,
+};
+
+/**
+ * This enum provides the canonical mapping for sensor properties that have an integer value.
+ * The ordering of the values is taken from the OBD2 specification.
+ * Some of the properties are represented as an integer mapping to another enum. In those cases
+ * expect a comment by the property definition describing the enum to look at for the mapping.
+ * Any value greater than the last reserved index is available to vendors to map their extensions.
+ * While these values do not directly map to SAE J1979 PIDs, an equivalence is listed next
+ * to each one to aid implementors.
+ */
+enum DiagnosticIntegerSensorIndex : int32_t {
+    /** refer to FuelSystemStatus for a description of this value. */
+    FUEL_SYSTEM_STATUS = 0, /* PID 0x03 */
+    MALFUNCTION_INDICATOR_LIGHT_ON = 1, /* PID 0x01 */
+
+    /** refer to IgnitionMonitorKind for a description of this value. */
+    IGNITION_MONITORS_SUPPORTED = 2, /* PID 0x01 */
+
+    /**
+     * The value of this sensor is a bitmask that specifies whether ignition-specific
+     * tests are available and whether they are complete. The semantics of the individual
+     * bits in this value are given by, respectively, SparkIgnitionMonitors and
+     * CompressionIgnitionMonitors depending on the value of IGNITION_MONITORS_SUPPORTED.
+     */
+    IGNITION_SPECIFIC_MONITORS = 3, /* PID 0x01 */
+    INTAKE_AIR_TEMPERATURE = 4, /* PID 0x0F */
+
+    /** refer to SecondaryAirStatus for a description of this value. */
+    COMMANDED_SECONDARY_AIR_STATUS = 5, /* PID 0x12 */
+    NUM_OXYGEN_SENSORS_PRESENT = 6, /* PID 0x13 */
+    RUNTIME_SINCE_ENGINE_START = 7, /* PID 0x1F */
+    DISTANCE_TRAVELED_WITH_MALFUNCTION_INDICATOR_LIGHT_ON = 8, /* PID 0x21 */
+    WARMUPS_SINCE_CODES_CLEARED = 9, /* PID 0x30 */
+    DISTANCE_TRAVELED_SINCE_CODES_CLEARED = 10, /* PID 0x31 */
+    ABSOLUTE_BAROMETRIC_PRESSURE = 11, /* PID 0x33 */
+    CONTROL_MODULE_VOLTAGE = 12, /* PID 0x42 */
+    AMBIENT_AIR_TEMPERATURE = 13, /* PID 0x46 */
+    TIME_WITH_MALFUNCTION_LIGHT_ON = 14, /* PID 0x4D */
+    TIME_SINCE_TROUBLE_CODES_CLEARED = 15, /* PID 0x4E */
+    MAX_FUEL_AIR_EQUIVALENCE_RATIO = 16, /* PID 0x4F */
+    MAX_OXYGEN_SENSOR_VOLTAGE = 17, /* PID 0x4F */
+    MAX_OXYGEN_SENSOR_CURRENT = 18, /* PID 0x4F */
+    MAX_INTAKE_MANIFOLD_ABSOLUTE_PRESSURE = 19, /* PID 0x4F */
+    MAX_AIR_FLOW_RATE_FROM_MASS_AIR_FLOW_SENSOR = 20, /* PID 0x50 */
+
+    /** refer to FuelType for a description of this value. */
+    FUEL_TYPE = 21, /* PID 0x51 */
+    FUEL_RAIL_ABSOLUTE_PRESSURE = 22, /* PID 0x59 */
+    ENGINE_OIL_TEMPERATURE = 23, /* PID 0x5C */
+    DRIVER_DEMAND_PERCENT_TORQUE = 24, /* PID 0x61 */
+    ENGINE_ACTUAL_PERCENT_TORQUE = 25, /* PID 0x62 */
+    ENGINE_REFERENCE_PERCENT_TORQUE = 26, /* PID 0x63 */
+    ENGINE_PERCENT_TORQUE_DATA_IDLE = 27, /* PID 0x64 */
+    ENGINE_PERCENT_TORQUE_DATA_POINT1 = 28, /* PID 0x64 */
+    ENGINE_PERCENT_TORQUE_DATA_POINT2 = 29, /* PID 0x64 */
+    ENGINE_PERCENT_TORQUE_DATA_POINT3 = 30, /* PID 0x64 */
+    ENGINE_PERCENT_TORQUE_DATA_POINT4 = 31, /* PID 0x64 */
+    LAST_SYSTEM_INDEX = ENGINE_PERCENT_TORQUE_DATA_POINT4,
+};
+
+/**
+ * This enum provides the canonical mapping for sensor properties that have a floating-point value.
+ * The ordering of the values is taken from the OBD2 specification.
+ * Any value greater than the last reserved index is available to vendors to map their extensions.
+ * While these values do not directly map to SAE J1979 PIDs, an equivalence is listed next
+ * to each one to aid implementors.
+ */
+enum DiagnosticFloatSensorIndex : int32_t {
+    CALCULATED_ENGINE_LOAD = 0, /* PID 0x04 */
+    ENGINE_COOLANT_TEMPERATURE = 1, /* PID 0x05 */
+    SHORT_TERM_FUEL_TRIM_BANK1 = 2, /* PID 0x06 */
+    LONG_TERM_FUEL_TRIM_BANK1 = 3, /* PID 0x07 */
+    SHORT_TERM_FUEL_TRIM_BANK2 = 4, /* PID 0x08 */
+    LONG_TERM_FUEL_TRIM_BANK2 = 5, /* PID 0x09 */
+    FUEL_PRESSURE = 6, /* PID 0x0A */
+    INTAKE_MANIFOLD_ABSOLUTE_PRESSURE = 7, /* PID 0x0B */
+    ENGINE_RPM = 8, /* PID 0x0C */
+    VEHICLE_SPEED = 9, /* PID 0x0D */
+    TIMING_ADVANCE = 10, /* PID 0x0E */
+    MAF_AIR_FLOW_RATE = 11, /* PID 0x10 */
+    THROTTLE_POSITION = 12, /* PID 0x11 */
+    OXYGEN_SENSOR1_VOLTAGE = 13, /* PID 0x14 */
+    OXYGEN_SENSOR1_SHORT_TERM_FUEL_TRIM = 14, /* PID 0x14 */
+    OXYGEN_SENSOR1_FUEL_AIR_EQUIVALENCE_RATIO = 15, /* PID 0x24 */
+    OXYGEN_SENSOR2_VOLTAGE = 16, /* PID 0x15 */
+    OXYGEN_SENSOR2_SHORT_TERM_FUEL_TRIM = 17, /* PID 0x15 */
+    OXYGEN_SENSOR2_FUEL_AIR_EQUIVALENCE_RATIO = 18, /* PID 0x25 */
+    OXYGEN_SENSOR3_VOLTAGE = 19, /* PID 0x16 */
+    OXYGEN_SENSOR3_SHORT_TERM_FUEL_TRIM = 20, /* PID 0x16 */
+    OXYGEN_SENSOR3_FUEL_AIR_EQUIVALENCE_RATIO = 21, /* PID 0x26 */
+    OXYGEN_SENSOR4_VOLTAGE = 22, /* PID 0x17 */
+    OXYGEN_SENSOR4_SHORT_TERM_FUEL_TRIM = 23, /* PID 0x17 */
+    OXYGEN_SENSOR4_FUEL_AIR_EQUIVALENCE_RATIO = 24, /* PID 0x27 */
+    OXYGEN_SENSOR5_VOLTAGE = 25, /* PID 0x18 */
+    OXYGEN_SENSOR5_SHORT_TERM_FUEL_TRIM = 26, /* PID 0x18 */
+    OXYGEN_SENSOR5_FUEL_AIR_EQUIVALENCE_RATIO = 27, /* PID 0x28 */
+    OXYGEN_SENSOR6_VOLTAGE = 28, /* PID 0x19 */
+    OXYGEN_SENSOR6_SHORT_TERM_FUEL_TRIM = 29, /* PID 0x19 */
+    OXYGEN_SENSOR6_FUEL_AIR_EQUIVALENCE_RATIO = 30, /* PID 0x29 */
+    OXYGEN_SENSOR7_VOLTAGE = 31, /* PID 0x1A */
+    OXYGEN_SENSOR7_SHORT_TERM_FUEL_TRIM = 32, /* PID 0x1A */
+    OXYGEN_SENSOR7_FUEL_AIR_EQUIVALENCE_RATIO = 33, /* PID 0x2A */
+    OXYGEN_SENSOR8_VOLTAGE = 34, /* PID 0x1B */
+    OXYGEN_SENSOR8_SHORT_TERM_FUEL_TRIM = 35, /* PID 0x1B */
+    OXYGEN_SENSOR8_FUEL_AIR_EQUIVALENCE_RATIO = 36, /* PID 0x2B */
+    FUEL_RAIL_PRESSURE = 37, /* PID 0x22 */
+    FUEL_RAIL_GAUGE_PRESSURE = 38, /* PID 0x23 */
+    COMMANDED_EXHAUST_GAS_RECIRCULATION = 39, /* PID 0x2C */
+    EXHAUST_GAS_RECIRCULATION_ERROR = 40, /* PID 0x2D */
+    COMMANDED_EVAPORATIVE_PURGE = 41, /* PID 0x2E */
+    FUEL_TANK_LEVEL_INPUT = 42, /* PID 0x2F */
+    EVAPORATION_SYSTEM_VAPOR_PRESSURE = 43, /* PID 0x32 */
+    CATALYST_TEMPERATURE_BANK1_SENSOR1 = 44, /* PID 0x3C */
+    CATALYST_TEMPERATURE_BANK2_SENSOR1 = 45, /* PID 0x3D */
+    CATALYST_TEMPERATURE_BANK1_SENSOR2 = 46, /* PID 0x3E */
+    CATALYST_TEMPERATURE_BANK2_SENSOR2 = 47, /* PID 0x3F */
+    ABSOLUTE_LOAD_VALUE = 48, /* PID 0x43 */
+    FUEL_AIR_COMMANDED_EQUIVALENCE_RATIO = 49, /* PID 0x44 */
+    RELATIVE_THROTTLE_POSITION = 50, /* PID 0x45 */
+    ABSOLUTE_THROTTLE_POSITION_B = 51, /* PID 0x47 */
+    ABSOLUTE_THROTTLE_POSITION_C = 52, /* PID 0x48 */
+    ACCELERATOR_PEDAL_POSITION_D = 53, /* PID 0x49 */
+    ACCELERATOR_PEDAL_POSITION_E = 54, /* PID 0x4A */
+    ACCELERATOR_PEDAL_POSITION_F = 55, /* PID 0x4B */
+    COMMANDED_THROTTLE_ACTUATOR = 56, /* PID 0x4C */
+    ETHANOL_FUEL_PERCENTAGE = 57,/* PID 0x52 */
+    ABSOLUTE_EVAPORATION_SYSTEM_VAPOR_PRESSURE = 58, /* PID 0x53 */
+    SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK1 = 59, /* PID 0x55 */
+    SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK2 = 60, /* PID 0x57 */
+    SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK3 = 61,/* PID 0x55 */
+    SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK4 = 62, /* PID 0x57 */
+    LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK1 = 63, /* PID 0x56 */
+    LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK2 = 64, /* PID 0x58 */
+    LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK3 = 65, /* PID 0x56 */
+    LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK4 = 66, /* PID 0x58 */
+    RELATIVE_ACCELERATOR_PEDAL_POSITION = 67, /* PID 0x5A */
+    HYBRID_BATTERY_PACK_REMAINING_LIFE = 68, /* PID 0x5B */
+    FUEL_INJECTION_TIMING = 69, /* PID 0x5D */
+    ENGINE_FUEL_RATE = 70, /* PID 0x5E */
+    LAST_SYSTEM_INDEX = ENGINE_FUEL_RATE,
+};
+
+/**
+ * This enum lists the types of supported VMS messages. It is used as the first
+ * integer in the vehicle property integers array and determines how the rest of
+ * the message is decoded.
+ */
+enum VmsMessageType : int32_t {
+    /**
+     * A request from the subscribers to the VMS service to subscribe to a layer.
+     *
+     * This message type uses enum VmsMessageWithLayerIntegerValuesIndex.
+     */
+    SUBSCRIBE = 1,
+
+    /**
+     * A request from the subscribers to the VMS service to subscribe to a layer from a specific publisher.
+     *
+     * This message type uses enum VmsMessageWithLayerAndPublisherIdIntegerValuesIndex.
+     */
+    SUBSCRIBE_TO_PUBLISHER = 2,
+
+    /**
+     * A request from the subscribers to the VMS service to unsubscribes from a layer.
+     *
+     * This message type uses enum VmsMessageWithLayerIntegerValuesIndex.
+     */
+    UNSUBSCRIBE = 3,
+
+    /**
+     * A request from the subscribers to the VMS service to unsubscribes from a layer from a specific publisher.
+     *
+     * This message type uses enum VmsMessageWithLayerAndPublisherIdIntegerValuesIndex.
+     */
+    UNSUBSCRIBE_TO_PUBLISHER = 4,
+
+    /**
+     * Information from the publishers to the VMS service about the layers which the client can publish.
+     *
+     * This message type uses enum VmsOfferingMessageIntegerValuesIndex.
+     */
+    OFFERING = 5,
+
+    /**
+     * A request from the subscribers to the VMS service to get the available layers.
+     *
+     * This message type uses enum VmsBaseMessageIntegerValuesIndex.
+     */
+    AVAILABILITY_REQUEST = 6,
+
+    /**
+     * A request from the publishers to the VMS service to get the layers with subscribers.
+     *
+     * This message type uses enum VmsBaseMessageIntegerValuesIndex.
+     */
+    SUBSCRIPTIONS_REQUEST = 7,
+
+    /**
+     * A response from the VMS service to the subscribers to a VmsMessageType.AVAILABILITY_REQUEST
+     *
+     * This message type uses enum VmsAvailabilityStateIntegerValuesIndex.
+     */
+    AVAILABILITY_RESPONSE = 8,
+
+    /**
+     * A notification from the VMS service to the subscribers on a change in the available layers.
+     *
+     * This message type uses enum VmsAvailabilityStateIntegerValuesIndex.
+     */
+    AVAILABILITY_CHANGE = 9,
+
+    /**
+     * A response from the VMS service to the publishers to a VmsMessageType.SUBSCRIPTIONS_REQUEST
+     *
+     * This message type uses enum VmsSubscriptionsStateIntegerValuesIndex.
+     */
+    SUBSCRIPTIONS_RESPONSE = 10,
+
+    /**
+     * A notification from the VMS service to the publishers on a change in the layers with subscribers.
+     *
+     * This message type uses enum VmsSubscriptionsStateIntegerValuesIndex.
+     */
+    SUBSCRIPTIONS_CHANGE = 11,
+
+    /**
+     * A message from the VMS service to the subscribers or from the publishers to the VMS service
+     * with a serialized VMS data packet as defined in the VMS protocol.
+     *
+     * This message type uses enum VmsBaseMessageIntegerValuesIndex.
+     */
+    DATA = 12,
+};
+
+/**
+ * Every VMS message starts with the type of the message from the VmsMessageType enum.
+ * Messages with no parameters such as VmsMessageType.AVAILABILITY_REQUEST,
+ * VmsMessageType.SUBSCRIPTIONS_REQUEST and VmsMessageType.DATA are also based on this enum.
+ */
+enum VmsBaseMessageIntegerValuesIndex : int32_t {
+    /* The message type as enumerated by VmsMessageType enum. */
+    MESSAGE_TYPE = 0,
+};
+
+/*
+ * A VMS message with a layer is sent as part of a VmsMessageType.SUBSCRIBE or
+ * VmsMessageType.UNSUBSCRIBE messages.
+ *
+ * The layer type is defined in the VMS protocol, and the subtype and version are
+ * controlled by the implementer of the publisher.
+ */
+enum VmsMessageWithLayerIntegerValuesIndex : VmsBaseMessageIntegerValuesIndex {
+    LAYER_TYPE = 1,
+    LAYER_SUBTYPE = 2,
+    LAYER_VERSION = 3,
+};
+
+/*
+ * A VMS message with a layer and publisher ID is sent as part of a
+ * VmsMessageType.SUBSCRIBE_TO_PUBLISHER and VmsMessageType.UNSUBSCRIBE_TO_PUBLISHER messages.
+ */
+enum VmsMessageWithLayerAndPublisherIdIntegerValuesIndex : VmsMessageWithLayerIntegerValuesIndex {
+    PUBLISHER_ID = 4,
+};
+
+/*
+ * An offering can be sent by publishers as part of VmsMessageType.OFFERING in order to
+ * advertise which layers they can publish and under which constraints: e.g., I can publish Layer X
+ * if someone else will publish Layer Y.
+ * The offering contains the publisher ID which was assigned to the publisher by the VMS service.
+ * A single offering is represented as:
+ * - Layer type
+ * - Layer subtype
+ * - Layer version
+ * - Number of dependencies (N)
+ * - N x (Layer type, Layer subtype, Layer version)
+ */
+enum VmsOfferingMessageIntegerValuesIndex : VmsBaseMessageIntegerValuesIndex {
+    PUBLISHER_ID = 1,
+    NUMBER_OF_OFFERS = 2,
+    OFFERING_START = 3,
+};
+
+/**
+ * A subscriptions state is sent to the publishers in response to a change in the subscriptions
+ * as part of a VmsMessageType.SUBSCRIPTIONS_CHANGE, or in response to a
+ * VmsMessageType.SUBSCRIPTIONS_REQUEST message as part of VmsMessageType.SUBSCRIPTIONS_RESPONSE.
+ * The VMS service issues monotonically increasing sequence numbers, and in case a subscriber receives
+ * a smaller sequnce number it should ignore the message.
+ * The subscriptions are sent as a list of layers followed by a list of associated layers:
+ * {Sequence number, N, M, N x layer, M x associated layer}
+ * A subscribed layer is represented as three integers:
+ * - Layer type
+ * - Layer subtype
+ * - Layer version
+ * A subscribed associated layer is a layer with a list of publisher IDs. It is represented as:
+ * - Layer type
+ * - Layer subtype
+ * - Layer version
+ * - Number of publisher IDs (N)
+ * - N x publisher ID
+ */
+enum VmsSubscriptionsStateIntegerValuesIndex : VmsBaseMessageIntegerValuesIndex {
+    SEQUENCE_NUMBER = 1,
+    NUMBER_OF_LAYERS = 2,
+    NUMBER_OF_ASSOCIATED_LAYERS = 3,
+    SUBSCRIPTIONS_START = 4,
+};
+
+/**
+ * An availability state is sent to the subscribers in response to a change in the available
+ * layers as part of a VmsMessageType.AVAILABILITY_CHANGE message, or in response to a
+ * VmsMessageType.AVAILABILITY_REQUEST message as part of a VmsMessageType.AVAILABILITY_RESPONSE.
+ * The VMS service issues monotonically increasing sequence numbers, and in case a subscriber receives
+ * a smaller sequnce number, it should ignore the message.
+ * An available associated layer is a layer with a list of publisher IDs:
+ * - Layer type
+ * - Layer subtype
+ * - Layer version
+ * - Number of publisher IDs (N)
+ * - N x publisher ID
+*/
+enum VmsAvailabilityStateIntegerValuesIndex : VmsBaseMessageIntegerValuesIndex {
+    SEQUENCE_NUMBER = 1,
+    NUMBER_OF_ASSOCIATED_LAYERS = 2,
+    LAYERS_START = 3,
+};
+
diff --git a/automotive/vehicle/2.1/Android.bp b/automotive/vehicle/2.1/Android.bp
deleted file mode 100644 (file)
index 9e45fb5..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-// This file is autogenerated by hidl-gen. Do not edit manually.
-
-filegroup {
-    name: "android.hardware.automotive.vehicle@2.1_hal",
-    srcs: [
-        "types.hal",
-        "IVehicle.hal",
-    ],
-}
-
-genrule {
-    name: "android.hardware.automotive.vehicle@2.1_genc++",
-    tools: ["hidl-gen"],
-    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.automotive.vehicle@2.1",
-    srcs: [
-        ":android.hardware.automotive.vehicle@2.1_hal",
-    ],
-    out: [
-        "android/hardware/automotive/vehicle/2.1/types.cpp",
-        "android/hardware/automotive/vehicle/2.1/VehicleAll.cpp",
-    ],
-}
-
-genrule {
-    name: "android.hardware.automotive.vehicle@2.1_genc++_headers",
-    tools: ["hidl-gen"],
-    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.automotive.vehicle@2.1",
-    srcs: [
-        ":android.hardware.automotive.vehicle@2.1_hal",
-    ],
-    out: [
-        "android/hardware/automotive/vehicle/2.1/types.h",
-        "android/hardware/automotive/vehicle/2.1/hwtypes.h",
-        "android/hardware/automotive/vehicle/2.1/IVehicle.h",
-        "android/hardware/automotive/vehicle/2.1/IHwVehicle.h",
-        "android/hardware/automotive/vehicle/2.1/BnHwVehicle.h",
-        "android/hardware/automotive/vehicle/2.1/BpHwVehicle.h",
-        "android/hardware/automotive/vehicle/2.1/BsVehicle.h",
-    ],
-}
-
-cc_library_shared {
-    name: "android.hardware.automotive.vehicle@2.1",
-    defaults: ["hidl-module-defaults"],
-    generated_sources: ["android.hardware.automotive.vehicle@2.1_genc++"],
-    generated_headers: ["android.hardware.automotive.vehicle@2.1_genc++_headers"],
-    export_generated_headers: ["android.hardware.automotive.vehicle@2.1_genc++_headers"],
-    vendor_available: true,
-    shared_libs: [
-        "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
-        "liblog",
-        "libutils",
-        "libcutils",
-        "android.hardware.automotive.vehicle@2.0",
-    ],
-    export_shared_lib_headers: [
-        "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
-        "libutils",
-        "android.hardware.automotive.vehicle@2.0",
-    ],
-}
diff --git a/automotive/vehicle/2.1/Android.mk b/automotive/vehicle/2.1/Android.mk
deleted file mode 100644 (file)
index 8e1c0dd..0000000
+++ /dev/null
@@ -1,648 +0,0 @@
-# This file is autogenerated by hidl-gen. Do not edit manually.
-
-LOCAL_PATH := $(call my-dir)
-
-################################################################################
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hardware.automotive.vehicle-V2.1-java
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-
-intermediates := $(call local-generated-sources-dir, COMMON)
-
-HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
-
-LOCAL_JAVA_LIBRARIES := \
-    android.hardware.automotive.vehicle-V2.0-java \
-    android.hidl.base-V1.0-java \
-
-
-#
-# Build types.hal (CommonIgnitionMonitors)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/CommonIgnitionMonitors.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.CommonIgnitionMonitors
-
-$(GEN): $(LOCAL_PATH)/types.hal
-       $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (CompressionIgnitionMonitors)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/CompressionIgnitionMonitors.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.CompressionIgnitionMonitors
-
-$(GEN): $(LOCAL_PATH)/types.hal
-       $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (FuelSystemStatus)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/FuelSystemStatus.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.FuelSystemStatus
-
-$(GEN): $(LOCAL_PATH)/types.hal
-       $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (FuelType)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/FuelType.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.FuelType
-
-$(GEN): $(LOCAL_PATH)/types.hal
-       $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (IgnitionMonitorKind)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/IgnitionMonitorKind.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.IgnitionMonitorKind
-
-$(GEN): $(LOCAL_PATH)/types.hal
-       $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (Obd2FloatSensorIndex)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/Obd2FloatSensorIndex.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.Obd2FloatSensorIndex
-
-$(GEN): $(LOCAL_PATH)/types.hal
-       $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (Obd2IntegerSensorIndex)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/Obd2IntegerSensorIndex.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.Obd2IntegerSensorIndex
-
-$(GEN): $(LOCAL_PATH)/types.hal
-       $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (SecondaryAirStatus)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/SecondaryAirStatus.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.SecondaryAirStatus
-
-$(GEN): $(LOCAL_PATH)/types.hal
-       $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (SparkIgnitionMonitors)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/SparkIgnitionMonitors.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.SparkIgnitionMonitors
-
-$(GEN): $(LOCAL_PATH)/types.hal
-       $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleProperty)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VehicleProperty.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.VehicleProperty
-
-$(GEN): $(LOCAL_PATH)/types.hal
-       $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VmsBaseMessageIntegerValuesIndex)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsBaseMessageIntegerValuesIndex.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.VmsBaseMessageIntegerValuesIndex
-
-$(GEN): $(LOCAL_PATH)/types.hal
-       $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VmsMessageType)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsMessageType.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.VmsMessageType
-
-$(GEN): $(LOCAL_PATH)/types.hal
-       $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VmsOfferingMessageIntegerValuesIndex)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsOfferingMessageIntegerValuesIndex.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.VmsOfferingMessageIntegerValuesIndex
-
-$(GEN): $(LOCAL_PATH)/types.hal
-       $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VmsSimpleMessageIntegerValuesIndex)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsSimpleMessageIntegerValuesIndex.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.VmsSimpleMessageIntegerValuesIndex
-
-$(GEN): $(LOCAL_PATH)/types.hal
-       $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VmsSubscriptionResponseFormat)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsSubscriptionResponseFormat.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.VmsSubscriptionResponseFormat
-
-$(GEN): $(LOCAL_PATH)/types.hal
-       $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build IVehicle.hal
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/IVehicle.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IVehicle.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::IVehicle
-
-$(GEN): $(LOCAL_PATH)/IVehicle.hal
-       $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-include $(BUILD_JAVA_LIBRARY)
-
-
-################################################################################
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hardware.automotive.vehicle-V2.1-java-static
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-
-intermediates := $(call local-generated-sources-dir, COMMON)
-
-HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    android.hardware.automotive.vehicle-V2.0-java-static \
-    android.hidl.base-V1.0-java-static \
-
-
-#
-# Build types.hal (CommonIgnitionMonitors)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/CommonIgnitionMonitors.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.CommonIgnitionMonitors
-
-$(GEN): $(LOCAL_PATH)/types.hal
-       $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (CompressionIgnitionMonitors)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/CompressionIgnitionMonitors.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.CompressionIgnitionMonitors
-
-$(GEN): $(LOCAL_PATH)/types.hal
-       $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (FuelSystemStatus)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/FuelSystemStatus.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.FuelSystemStatus
-
-$(GEN): $(LOCAL_PATH)/types.hal
-       $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (FuelType)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/FuelType.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.FuelType
-
-$(GEN): $(LOCAL_PATH)/types.hal
-       $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (IgnitionMonitorKind)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/IgnitionMonitorKind.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.IgnitionMonitorKind
-
-$(GEN): $(LOCAL_PATH)/types.hal
-       $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (Obd2FloatSensorIndex)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/Obd2FloatSensorIndex.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.Obd2FloatSensorIndex
-
-$(GEN): $(LOCAL_PATH)/types.hal
-       $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (Obd2IntegerSensorIndex)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/Obd2IntegerSensorIndex.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.Obd2IntegerSensorIndex
-
-$(GEN): $(LOCAL_PATH)/types.hal
-       $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (SecondaryAirStatus)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/SecondaryAirStatus.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.SecondaryAirStatus
-
-$(GEN): $(LOCAL_PATH)/types.hal
-       $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (SparkIgnitionMonitors)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/SparkIgnitionMonitors.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.SparkIgnitionMonitors
-
-$(GEN): $(LOCAL_PATH)/types.hal
-       $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleProperty)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VehicleProperty.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.VehicleProperty
-
-$(GEN): $(LOCAL_PATH)/types.hal
-       $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VmsBaseMessageIntegerValuesIndex)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsBaseMessageIntegerValuesIndex.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.VmsBaseMessageIntegerValuesIndex
-
-$(GEN): $(LOCAL_PATH)/types.hal
-       $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VmsMessageType)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsMessageType.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.VmsMessageType
-
-$(GEN): $(LOCAL_PATH)/types.hal
-       $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VmsOfferingMessageIntegerValuesIndex)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsOfferingMessageIntegerValuesIndex.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.VmsOfferingMessageIntegerValuesIndex
-
-$(GEN): $(LOCAL_PATH)/types.hal
-       $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VmsSimpleMessageIntegerValuesIndex)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsSimpleMessageIntegerValuesIndex.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.VmsSimpleMessageIntegerValuesIndex
-
-$(GEN): $(LOCAL_PATH)/types.hal
-       $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VmsSubscriptionResponseFormat)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsSubscriptionResponseFormat.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.VmsSubscriptionResponseFormat
-
-$(GEN): $(LOCAL_PATH)/types.hal
-       $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build IVehicle.hal
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/IVehicle.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IVehicle.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::IVehicle
-
-$(GEN): $(LOCAL_PATH)/IVehicle.hal
-       $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/automotive/vehicle/2.1/IVehicle.hal b/automotive/vehicle/2.1/IVehicle.hal
deleted file mode 100644 (file)
index a22d1e6..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.1 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.1
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.automotive.vehicle@2.1;
-
-import android.hardware.automotive.vehicle@2.0;
-
-/**
- * New revision of IVehicle interface that supports properties defined in
- * VehicleProperty enum version 2.1.
- *
- * NOTE: this HAL interface is under development and shouldn't be used in
- *       production.
- *
- * TODO(pavelm): update comment when this interface is ready for prod.
- */
-interface IVehicle extends @2.0::IVehicle {
-};
diff --git a/automotive/vehicle/2.1/default/Android.mk b/automotive/vehicle/2.1/default/Android.mk
deleted file mode 100644 (file)
index f19263c..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-vhal_v2_0 = android.hardware.automotive.vehicle@2.0
-vhal_v2_1 = android.hardware.automotive.vehicle@2.1
-
-###############################################################################
-# Vehicle reference implementation lib
-###############################################################################
-include $(CLEAR_VARS)
-LOCAL_MODULE := $(vhal_v2_1)-manager-lib
-LOCAL_SRC_FILES := \
-    common/src/Obd2SensorStore.cpp
-
-LOCAL_C_INCLUDES := \
-    $(LOCAL_PATH)/common/include/vhal_v2_1 \
-    $(LOCAL_PATH)/../../2.0/default/common/include/vhal_v2_0 \
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := \
-    $(LOCAL_PATH)/common/include
-
-LOCAL_SHARED_LIBRARIES := \
-    libhidlbase \
-    libhidltransport \
-    libhwbinder \
-    liblog \
-    libutils \
-    $(vhal_v2_1) \
-
-include $(BUILD_STATIC_LIBRARY)
-
-###############################################################################
-# Vehicle default VehicleHAL implementation
-###############################################################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE:= $(vhal_v2_1)-default-impl-lib
-LOCAL_SRC_FILES:= \
-    impl/vhal_v2_1/EmulatedVehicleHal.cpp \
-
-LOCAL_C_INCLUDES := \
-    $(LOCAL_PATH)/impl/vhal_v2_1 \
-    $(LOCAL_PATH)/common/include
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := \
-    $(LOCAL_PATH)/impl \
-    $(LOCAL_PATH)/common/include
-
-
-# LOCAL_WHOLE_STATIC_LIBRARIES := \
-
-LOCAL_STATIC_LIBRARIES := \
-    $(vhal_v2_0)-default-impl-lib \
-    $(vhal_v2_0)-manager-lib \
-    libqemu_pipe \
-    $(vhal_v2_1)-manager-lib \
-    $(vhal_v2_0)-libproto-native
-
-LOCAL_SHARED_LIBRARIES := \
-    libbase \
-    libhidlbase \
-    libhidltransport \
-    libhwbinder \
-    liblog \
-    libutils \
-    libprotobuf-cpp-lite \
-    $(vhal_v2_0) \
-    $(vhal_v2_1) \
-
-LOCAL_CFLAGS += -Wall -Wextra -Werror
-
-include $(BUILD_STATIC_LIBRARY)
-
-###############################################################################
-# Vehicle HAL service
-###############################################################################
-include $(CLEAR_VARS)
-LOCAL_MODULE := $(vhal_v2_1)-service
-LOCAL_INIT_RC := $(vhal_v2_1)-service.rc
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_SRC_FILES := \
-    service.cpp
-
-LOCAL_WHOLE_STATIC_LIBRARIES := \
-    $(vhal_v2_0)-libproto-native \
-
-LOCAL_STATIC_LIBRARIES := \
-    $(vhal_v2_0)-manager-lib \
-    $(vhal_v2_0)-default-impl-lib \
-    $(vhal_v2_1)-default-impl-lib \
-    libqemu_pipe \
-    $(vhal_v2_1)-manager-lib \
-
-LOCAL_SHARED_LIBRARIES := \
-    libbase \
-    libhidlbase \
-    libhidltransport \
-    libhwbinder \
-    liblog \
-    libutils \
-    libprotobuf-cpp-lite \
-    $(vhal_v2_0) \
-    $(vhal_v2_1) \
-
-LOCAL_CFLAGS += -Wall -Wextra -Werror
-
-include $(BUILD_EXECUTABLE)
diff --git a/automotive/vehicle/2.1/default/android.hardware.automotive.vehicle@2.1-service.rc b/automotive/vehicle/2.1/default/android.hardware.automotive.vehicle@2.1-service.rc
deleted file mode 100644 (file)
index 8929d25..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-service vehicle-hal-2.1 /vendor/bin/hw/android.hardware.automotive.vehicle@2.1-service
-    class hal
-    user vehicle_network
-    group system inet
diff --git a/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultConfig.h b/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultConfig.h
deleted file mode 100644 (file)
index 0f10086..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef android_hardware_automotive_vehicle_V2_1_impl_DefaultConfig_H_
-#define android_hardware_automotive_vehicle_V2_1_impl_DefaultConfig_H_
-
-#include <android/hardware/automotive/vehicle/2.1/types.h>
-#include <vhal_v2_0/VehicleUtils.h>
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_1 {
-
-namespace impl {
-
-// Some handy constants to avoid conversions from enum to int.
-constexpr int OBD2_LIVE_FRAME = (int) V2_1::VehicleProperty::OBD2_LIVE_FRAME;
-constexpr int OBD2_FREEZE_FRAME = (int) V2_1::VehicleProperty::OBD2_FREEZE_FRAME;
-constexpr int OBD2_FREEZE_FRAME_INFO = (int) V2_1::VehicleProperty::OBD2_FREEZE_FRAME_INFO;
-constexpr int OBD2_FREEZE_FRAME_CLEAR = (int) V2_1::VehicleProperty::OBD2_FREEZE_FRAME_CLEAR;
-constexpr int VEHICLE_MAP_SERVICE = (int) V2_1::VehicleProperty::VEHICLE_MAP_SERVICE;
-constexpr int WHEEL_TICK = (int) V2_1::VehicleProperty::WHEEL_TICK;
-
-
-const V2_0::VehiclePropConfig kVehicleProperties[] = {
-    {
-        .prop = WHEEL_TICK,
-        .access = V2_0::VehiclePropertyAccess::READ,
-        .changeMode = V2_0::VehiclePropertyChangeMode::CONTINUOUS,
-        .minSampleRate = 1.0f,
-        .maxSampleRate = 100.0f,
-    },
-
-    {
-        .prop = OBD2_LIVE_FRAME,
-        .access = V2_0::VehiclePropertyAccess::READ,
-        .changeMode = V2_0::VehiclePropertyChangeMode::ON_CHANGE,
-        .configArray = {0,0}
-    },
-
-    {
-        .prop = OBD2_FREEZE_FRAME,
-        .access = V2_0::VehiclePropertyAccess::READ,
-        .changeMode = V2_0::VehiclePropertyChangeMode::ON_CHANGE,
-        .configArray = {0,0}
-    },
-
-    {
-        .prop = OBD2_FREEZE_FRAME_INFO,
-        .access = V2_0::VehiclePropertyAccess::READ,
-        .changeMode = V2_0::VehiclePropertyChangeMode::ON_CHANGE
-    },
-
-    {
-        .prop = OBD2_FREEZE_FRAME_CLEAR,
-        .access = V2_0::VehiclePropertyAccess::WRITE,
-        .changeMode = V2_0::VehiclePropertyChangeMode::ON_CHANGE
-    },
-
-    {
-        .prop = VEHICLE_MAP_SERVICE,
-        .access = V2_0::VehiclePropertyAccess::READ_WRITE,
-        .changeMode = V2_0::VehiclePropertyChangeMode::ON_CHANGE
-    }
-};
-
-}  // impl
-
-}  // namespace V2_1
-}  // namespace vehicle
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
-
-#endif // android_hardware_automotive_vehicle_V2_1_impl_DefaultConfig_H_
diff --git a/automotive/vehicle/2.1/default/impl/vhal_v2_1/EmulatedVehicleHal.cpp b/automotive/vehicle/2.1/default/impl/vhal_v2_1/EmulatedVehicleHal.cpp
deleted file mode 100644 (file)
index 46e062b..0000000
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "DefaultVehicleHal_v2_1"
-#include <android/log.h>
-
-#include <log/log.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <algorithm>
-
-#include "EmulatedVehicleHal.h"
-
-#define DEBUG_SOCKET    (33452)
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_1 {
-
-namespace impl {
-
-static std::unique_ptr<Obd2SensorStore> fillDefaultObd2Frame(
-        size_t numVendorIntegerSensors,
-        size_t numVendorFloatSensors) {
-    std::unique_ptr<Obd2SensorStore> sensorStore(new Obd2SensorStore(
-            numVendorIntegerSensors, numVendorFloatSensors));
-
-    sensorStore->setIntegerSensor(
-        Obd2IntegerSensorIndex::FUEL_SYSTEM_STATUS,
-        V2_0::toInt(FuelSystemStatus::CLOSED_LOOP));
-    sensorStore->setIntegerSensor(
-        Obd2IntegerSensorIndex::MALFUNCTION_INDICATOR_LIGHT_ON, 0);
-    sensorStore->setIntegerSensor(
-        Obd2IntegerSensorIndex::IGNITION_MONITORS_SUPPORTED,
-        V2_0::toInt(IgnitionMonitorKind::SPARK));
-    sensorStore->setIntegerSensor(Obd2IntegerSensorIndex::IGNITION_SPECIFIC_MONITORS,
-        CommonIgnitionMonitors::COMPONENTS_AVAILABLE |
-        CommonIgnitionMonitors::MISFIRE_AVAILABLE |
-        SparkIgnitionMonitors::AC_REFRIGERANT_AVAILABLE |
-        SparkIgnitionMonitors::EVAPORATIVE_SYSTEM_AVAILABLE);
-    sensorStore->setIntegerSensor(
-        Obd2IntegerSensorIndex::INTAKE_AIR_TEMPERATURE, 35);
-    sensorStore->setIntegerSensor(
-        Obd2IntegerSensorIndex::COMMANDED_SECONDARY_AIR_STATUS,
-        V2_0::toInt(SecondaryAirStatus::FROM_OUTSIDE_OR_OFF));
-    sensorStore->setIntegerSensor(
-        Obd2IntegerSensorIndex::NUM_OXYGEN_SENSORS_PRESENT, 1);
-    sensorStore->setIntegerSensor(
-        Obd2IntegerSensorIndex::RUNTIME_SINCE_ENGINE_START, 500);
-    sensorStore->setIntegerSensor(
-        Obd2IntegerSensorIndex::DISTANCE_TRAVELED_WITH_MALFUNCTION_INDICATOR_LIGHT_ON, 0);
-    sensorStore->setIntegerSensor(
-        Obd2IntegerSensorIndex::WARMUPS_SINCE_CODES_CLEARED, 51);
-    sensorStore->setIntegerSensor(
-        Obd2IntegerSensorIndex::DISTANCE_TRAVELED_SINCE_CODES_CLEARED, 365);
-    sensorStore->setIntegerSensor(
-        Obd2IntegerSensorIndex::ABSOLUTE_BAROMETRIC_PRESSURE, 30);
-    sensorStore->setIntegerSensor(
-        Obd2IntegerSensorIndex::CONTROL_MODULE_VOLTAGE, 12);
-    sensorStore->setIntegerSensor(
-        Obd2IntegerSensorIndex::AMBIENT_AIR_TEMPERATURE, 18);
-    sensorStore->setIntegerSensor(
-        Obd2IntegerSensorIndex::MAX_FUEL_AIR_EQUIVALENCE_RATIO, 1);
-    sensorStore->setIntegerSensor(
-        Obd2IntegerSensorIndex::FUEL_TYPE, V2_0::toInt(FuelType::GASOLINE));
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::CALCULATED_ENGINE_LOAD, 0.153);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::SHORT_TERM_FUEL_TRIM_BANK1, -0.16);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::LONG_TERM_FUEL_TRIM_BANK1, -0.16);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::SHORT_TERM_FUEL_TRIM_BANK2, -0.16);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::LONG_TERM_FUEL_TRIM_BANK2, -0.16);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::INTAKE_MANIFOLD_ABSOLUTE_PRESSURE, 7.5);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::ENGINE_RPM, 1250.);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::VEHICLE_SPEED, 40.);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::TIMING_ADVANCE, 2.5);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::THROTTLE_POSITION, 19.75);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::OXYGEN_SENSOR1_VOLTAGE, 0.265);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::FUEL_TANK_LEVEL_INPUT, 0.824);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::EVAPORATION_SYSTEM_VAPOR_PRESSURE, -0.373);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::CATALYST_TEMPERATURE_BANK1_SENSOR1, 190.);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::RELATIVE_THROTTLE_POSITION, 3.);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::ABSOLUTE_THROTTLE_POSITION_B, 0.306);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::ACCELERATOR_PEDAL_POSITION_D, 0.188);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::ACCELERATOR_PEDAL_POSITION_E, 0.094);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::COMMANDED_THROTTLE_ACTUATOR, 0.024);
-
-    return sensorStore;
-}
-
-void EmulatedVehicleHal::initObd2LiveFrame(const V2_0::VehiclePropConfig& propConfig) {
-    auto liveObd2Frame = createVehiclePropValue(V2_0::VehiclePropertyType::COMPLEX, 0);
-    auto sensorStore = fillDefaultObd2Frame(static_cast<size_t>(propConfig.configArray[0]),
-                                            static_cast<size_t>(propConfig.configArray[1]));
-    sensorStore->fillPropValue("", liveObd2Frame.get());
-    liveObd2Frame->prop = OBD2_LIVE_FRAME;
-
-    mPropStore->writeValue(*liveObd2Frame);
-}
-
-void EmulatedVehicleHal::initObd2FreezeFrame(const V2_0::VehiclePropConfig& propConfig) {
-    auto sensorStore = fillDefaultObd2Frame(static_cast<size_t>(propConfig.configArray[0]),
-                                            static_cast<size_t>(propConfig.configArray[1]));
-
-    static std::vector<std::string> sampleDtcs = { "P0070", "P0102" "P0123" };
-    for (auto&& dtc : sampleDtcs) {
-        auto freezeFrame = createVehiclePropValue(V2_0::VehiclePropertyType::COMPLEX, 0);
-        sensorStore->fillPropValue(dtc, freezeFrame.get());
-        freezeFrame->prop = OBD2_FREEZE_FRAME;
-
-        mPropStore->writeValue(*freezeFrame);
-    }
-}
-
-V2_0::StatusCode EmulatedVehicleHal::fillObd2FreezeFrame(
-        const V2_0::VehiclePropValue& requestedPropValue,
-        V2_0::VehiclePropValue* outValue) {
-    if (requestedPropValue.value.int64Values.size() != 1) {
-        ALOGE("asked for OBD2_FREEZE_FRAME without valid timestamp");
-        return V2_0::StatusCode::INVALID_ARG;
-    }
-    auto timestamp = requestedPropValue.value.int64Values[0];
-    auto freezeFrame = mPropStore->readValueOrNull(OBD2_FREEZE_FRAME, 0, timestamp);
-    if(freezeFrame == nullptr) {
-        ALOGE("asked for OBD2_FREEZE_FRAME at invalid timestamp");
-        return V2_0::StatusCode::INVALID_ARG;
-    }
-    outValue->prop = OBD2_FREEZE_FRAME;
-    outValue->value.int32Values = freezeFrame->value.int32Values;
-    outValue->value.floatValues = freezeFrame->value.floatValues;
-    outValue->value.bytes = freezeFrame->value.bytes;
-    outValue->value.stringValue = freezeFrame->value.stringValue;
-    outValue->timestamp = freezeFrame->timestamp;
-    return V2_0::StatusCode::OK;
-}
-
-V2_0::StatusCode EmulatedVehicleHal::clearObd2FreezeFrames(const V2_0::VehiclePropValue& propValue) {
-    if (propValue.value.int64Values.size() == 0) {
-        mPropStore->removeValuesForProperty(OBD2_FREEZE_FRAME);
-        return V2_0::StatusCode::OK;
-    } else {
-        for(int64_t timestamp: propValue.value.int64Values) {
-            auto freezeFrame = mPropStore->readValueOrNull(OBD2_FREEZE_FRAME, 0, timestamp);
-            if(freezeFrame == nullptr) {
-                ALOGE("asked for OBD2_FREEZE_FRAME at invalid timestamp");
-                return V2_0::StatusCode::INVALID_ARG;
-            }
-            mPropStore->removeValue(*freezeFrame);
-        }
-    }
-    return V2_0::StatusCode::OK;
-}
-
-V2_0::StatusCode EmulatedVehicleHal::fillObd2DtcInfo(V2_0::VehiclePropValue* outValue) {
-    std::vector<int64_t> timestamps;
-    for(const auto& freezeFrame: mPropStore->readValuesForProperty(OBD2_FREEZE_FRAME)) {
-        timestamps.push_back(freezeFrame.timestamp);
-    }
-    outValue->value.int64Values = timestamps;
-    return V2_0::StatusCode::OK;
-}
-
-void EmulatedVehicleHal::onCreate() {
-    V2_0::impl::EmulatedVehicleHal::onCreate();
-
-    initObd2LiveFrame(*mPropStore->getConfigOrDie(OBD2_LIVE_FRAME));
-    initObd2FreezeFrame(*mPropStore->getConfigOrDie(OBD2_FREEZE_FRAME));
-}
-
-void EmulatedVehicleHal::initStaticConfig() {
-    for (auto&& cfg = std::begin(kVehicleProperties); cfg != std::end(kVehicleProperties); ++cfg) {
-        V2_0::VehiclePropertyStore::TokenFunction tokenFunction = nullptr;
-
-        switch (cfg->prop) {
-            case OBD2_FREEZE_FRAME: {
-                tokenFunction = [] (const V2_0::VehiclePropValue& propValue) {
-                    return propValue.timestamp;
-                };
-                break;
-            }
-            default:
-                break;
-        }
-
-        mPropStore->registerProperty(*cfg, tokenFunction);
-    }
-}
-
-EmulatedVehicleHal::VehiclePropValuePtr EmulatedVehicleHal::get(
-        const V2_0::VehiclePropValue& requestedPropValue,
-        V2_0::StatusCode* outStatus) {
-
-    auto propId = requestedPropValue.prop;
-    VehiclePropValuePtr v = nullptr;
-    auto& pool = *getValuePool();
-
-    switch (propId) {
-    case OBD2_FREEZE_FRAME:
-        v = pool.obtainComplex();
-        *outStatus = fillObd2FreezeFrame(requestedPropValue, v.get());
-        return v;
-    case OBD2_FREEZE_FRAME_INFO:
-        v = pool.obtainComplex();
-        *outStatus = fillObd2DtcInfo(v.get());
-        return v;
-    default:
-        return V2_0::impl::EmulatedVehicleHal::get(requestedPropValue, outStatus);
-    }
-}
-
-V2_0::StatusCode EmulatedVehicleHal::set(const V2_0::VehiclePropValue& propValue) {
-    auto propId = propValue.prop;
-    switch (propId) {
-    case OBD2_FREEZE_FRAME_CLEAR:
-        return clearObd2FreezeFrames(propValue);
-    case VEHICLE_MAP_SERVICE:
-        // Placeholder for future implementation of VMS property in the default hal. For now, just
-        // returns OK; otherwise, hal clients crash with property not supported.
-        return V2_0::StatusCode::OK;
-    default:
-        return V2_0::impl::EmulatedVehicleHal::set(propValue);
-    }
-}
-
-}  // impl
-
-}  // namespace V2_1
-}  // namespace vehicle
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
diff --git a/automotive/vehicle/2.1/default/impl/vhal_v2_1/EmulatedVehicleHal.h b/automotive/vehicle/2.1/default/impl/vhal_v2_1/EmulatedVehicleHal.h
deleted file mode 100644 (file)
index 7cc3b79..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef android_hardware_automotive_vehicle_V2_1_impl_EmulatedVehicleHal_H_
-#define android_hardware_automotive_vehicle_V2_1_impl_EmulatedVehicleHal_H_
-
-#include <memory>
-
-#include <utils/SystemClock.h>
-
-#include <vhal_v2_0/EmulatedVehicleHal.h>
-#include <vhal_v2_0/VehicleHal.h>
-#include <vhal_v2_0/VehiclePropertyStore.h>
-#include <vhal_v2_1/Obd2SensorStore.h>
-
-#include "DefaultConfig.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_1 {
-
-namespace impl {
-
-using namespace std::placeholders;
-
-class EmulatedVehicleHal : public V2_0::impl::EmulatedVehicleHal {
-public:
-    EmulatedVehicleHal(V2_0::VehiclePropertyStore* propStore)
-        : V2_0::impl::EmulatedVehicleHal(propStore), mPropStore(propStore) {
-        initStaticConfig();
-    }
-
-    VehiclePropValuePtr get(const V2_0::VehiclePropValue& requestedPropValue,
-                            V2_0::StatusCode* outStatus) override;
-
-    V2_0::StatusCode set(const V2_0::VehiclePropValue& propValue) override;
-
-    void onCreate() override;
-
-private:
-    void initStaticConfig();
-    void initObd2LiveFrame(const V2_0::VehiclePropConfig& propConfig);
-    void initObd2FreezeFrame(const V2_0::VehiclePropConfig& propConfig);
-    V2_0::StatusCode fillObd2FreezeFrame(const V2_0::VehiclePropValue& requestedPropValue,
-                                        V2_0::VehiclePropValue* outValue);
-    V2_0::StatusCode fillObd2DtcInfo(V2_0::VehiclePropValue *outValue);
-    V2_0::StatusCode clearObd2FreezeFrames(const V2_0::VehiclePropValue& propValue);
-
-private:
-    V2_0::VehiclePropertyStore* mPropStore;
-};
-
-}  // impl
-
-}  // namespace V2_1
-}  // namespace vehicle
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
-
-
-#endif  // android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleHal_H_
diff --git a/automotive/vehicle/2.1/default/service.cpp b/automotive/vehicle/2.1/default/service.cpp
deleted file mode 100644 (file)
index bae64fd..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "automotive.vehicle@2.1-service"
-#include <android/log.h>
-#include <hidl/HidlTransportSupport.h>
-
-#include <iostream>
-
-#include <android/hardware/automotive/vehicle/2.1/IVehicle.h>
-
-#include <vhal_v2_0/VehicleHalManager.h>
-#include <vhal_v2_0/VehiclePropertyStore.h>
-#include <vhal_v2_0/EmulatedVehicleHal.h>
-
-#include <vhal_v2_1/EmulatedVehicleHal.h>
-
-using namespace android;
-using namespace android::hardware;
-
-namespace V2_1 = ::android::hardware::automotive::vehicle::V2_1;
-namespace V2_0 = ::android::hardware::automotive::vehicle::V2_0;
-
-using StatusCode = V2_0::StatusCode;
-using VehiclePropValue = V2_0::VehiclePropValue;
-
-/* Just wrapper that passes all calls to the provided V2_0::IVehicle object */
-struct Vehicle_V2_1 : public V2_1::IVehicle {
-
-    Vehicle_V2_1(V2_0::IVehicle* vehicle20) : mVehicle20(vehicle20) {}
-
-    // Methods derived from IVehicle
-    Return<void> getAllPropConfigs(getAllPropConfigs_cb _hidl_cb)  override {
-        return mVehicle20->getAllPropConfigs(_hidl_cb);
-    }
-
-    Return<void> getPropConfigs(const hidl_vec<int32_t>& properties,
-                                getPropConfigs_cb _hidl_cb)  override {
-        return mVehicle20->getPropConfigs(properties, _hidl_cb);
-    }
-
-    Return<void> get(const V2_0::VehiclePropValue& requestedPropValue,
-                     get_cb _hidl_cb)  override {
-        return mVehicle20->get(requestedPropValue, _hidl_cb);
-    }
-
-    Return<StatusCode> set(const VehiclePropValue& value) override {
-        return mVehicle20->set(value);
-    }
-
-    Return<StatusCode> subscribe(const sp<V2_0::IVehicleCallback>& callback,
-                                 const hidl_vec<V2_0::SubscribeOptions>&
-                                 options)  override {
-        return mVehicle20->subscribe(callback, options);
-    }
-
-    Return<StatusCode> unsubscribe(const sp<V2_0::IVehicleCallback>& callback,
-                                   int32_t propId)  override {
-        return mVehicle20->unsubscribe(callback, propId);
-    }
-
-    Return<void> debugDump(debugDump_cb _hidl_cb = nullptr) override {
-        return mVehicle20->debugDump(_hidl_cb);
-    }
-
-private:
-    V2_0::IVehicle* mVehicle20;
-};
-
-int main(int /* argc */, char* /* argv */ []) {
-    auto store = std::make_unique<V2_0::VehiclePropertyStore>();
-    auto hal = std::make_unique<V2_1::impl::EmulatedVehicleHal>(store.get());
-    auto emulator = std::make_unique<V2_0::impl::VehicleEmulator>(hal.get());
-    auto vehicleManager = std::make_unique<V2_0::VehicleHalManager>(hal.get());
-
-    Vehicle_V2_1 vehicle21(vehicleManager.get());
-
-    configureRpcThreadpool(1, true /* callerWillJoin */);
-
-    ALOGI("Registering as service...");
-    status_t status = vehicle21.registerAsService();
-
-    if (status != OK) {
-        ALOGE("Unable to register vehicle service (%d).", status);
-        return 1;
-    }
-
-    ALOGI("Ready");
-    joinRpcThreadpool();
-    return 1;
-}
diff --git a/automotive/vehicle/2.1/default/tests/Obd2SensorStore_test.cpp b/automotive/vehicle/2.1/default/tests/Obd2SensorStore_test.cpp
deleted file mode 100644 (file)
index a01c0f4..0000000
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
- #include <gtest/gtest.h>
-
-#include "vhal_v2_0/Obd2SensorStore.h"
-#include "vhal_v2_0/VehicleUtils.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace {
-
-static constexpr size_t getNumVendorIntegerSensors() {
-    return 5;
-}
-static constexpr size_t getNumVendorFloatSensors() {
-    return 3;
-}
-
-// this struct holds information necessary for a test to be able to validate
-// that the sensor bitmask contains the right data:
-//   - the index of the byte at which the bit for a given sensor lives
-//   - the expected value of that byte given that a certain sensor is present
-class BitmaskIndexingInfo {
-public:
-    size_t mByteIndex;
-    uint8_t mExpectedByteValue;
-
-    // Returns the information required to validate the bitmask for an
-    // integer-valued sensor.
-    static BitmaskIndexingInfo getForIntegerSensor(size_t index) {
-        const size_t indexInBitstream = index;
-        return getForBitstreamIndex(indexInBitstream);
-    }
-
-    // Returns the information required to validate the bitmask for a
-    // float-valued sensor.
-    static BitmaskIndexingInfo getForFloatSensor(size_t index) {
-        const size_t indexInBitstream = toInt(Obd2IntegerSensorIndex::LAST_SYSTEM_INDEX) +
-                                        1 + getNumVendorIntegerSensors() + index;
-        return getForBitstreamIndex(indexInBitstream);
-    }
-
-private:
-    static BitmaskIndexingInfo getForBitstreamIndex(size_t indexInBitstream) {
-        BitmaskIndexingInfo indexingInfo;
-        indexingInfo.mByteIndex = indexInBitstream / 8;
-        indexingInfo.mExpectedByteValue = 1 << (indexInBitstream % 8);
-        return indexingInfo;
-    }
-};
-
-static Obd2SensorStore getSensorStore() {
-    return Obd2SensorStore(getNumVendorIntegerSensors(),
-                           getNumVendorFloatSensors());
-}
-
-// Test that one can set and retrieve a value for the first integer sensor.
-TEST(Obd2SensorStoreTest, setFirstIntegerSensor) {
-    Obd2SensorStore sensorStore(getSensorStore());
-    sensorStore.setIntegerSensor(
-        Obd2IntegerSensorIndex::FUEL_SYSTEM_STATUS,
-        toInt(FuelSystemStatus::CLOSED_LOOP));
-    const auto& integerSensors(sensorStore.getIntegerSensors());
-    const auto& sensorBitmask(sensorStore.getSensorsBitmask());
-    ASSERT_EQ(
-        toInt(FuelSystemStatus::CLOSED_LOOP),
-        integerSensors[toInt(Obd2IntegerSensorIndex::FUEL_SYSTEM_STATUS)]);
-    const BitmaskIndexingInfo indexingInfo(BitmaskIndexingInfo::getForIntegerSensor(
-        toInt(Obd2IntegerSensorIndex::FUEL_SYSTEM_STATUS)));
-    ASSERT_EQ(
-        indexingInfo.mExpectedByteValue,
-        sensorBitmask[indexingInfo.mByteIndex]);
-}
-
-// Test that one can set and retrieve a value for the first float sensor.
-TEST(Obd2SensorStoreTest, setFirstFloatSensor) {
-    Obd2SensorStore sensorStore(getSensorStore());
-    sensorStore.setFloatSensor(
-        Obd2FloatSensorIndex::CALCULATED_ENGINE_LOAD,
-        1.25f);
-    const auto& floatSensors(sensorStore.getFloatSensors());
-    const auto& sensorBitmask(sensorStore.getSensorsBitmask());
-    ASSERT_EQ(
-        1.25f,
-        floatSensors[toInt(Obd2FloatSensorIndex::CALCULATED_ENGINE_LOAD)]);
-    const BitmaskIndexingInfo indexingInfo(BitmaskIndexingInfo::getForFloatSensor(
-        toInt(Obd2FloatSensorIndex::CALCULATED_ENGINE_LOAD)));
-    ASSERT_EQ(
-        indexingInfo.mExpectedByteValue,
-        sensorBitmask[indexingInfo.mByteIndex]);
-}
-
-// Test that one can set and retrieve a value for an integer sensor.
-TEST(Obd2SensorStoreTest, setAnyIntegerSensor) {
-    Obd2SensorStore sensorStore(getSensorStore());
-    sensorStore.setIntegerSensor(
-        Obd2IntegerSensorIndex::ABSOLUTE_BAROMETRIC_PRESSURE,
-        4000);
-    const auto& integerSensors(sensorStore.getIntegerSensors());
-    const auto& sensorBitmask(sensorStore.getSensorsBitmask());
-    ASSERT_EQ(4000,
-        integerSensors[toInt(Obd2IntegerSensorIndex::ABSOLUTE_BAROMETRIC_PRESSURE)]);
-    const BitmaskIndexingInfo indexingInfo(BitmaskIndexingInfo::getForIntegerSensor(
-        toInt(Obd2IntegerSensorIndex::ABSOLUTE_BAROMETRIC_PRESSURE)));
-    ASSERT_EQ(
-        indexingInfo.mExpectedByteValue,
-        sensorBitmask[indexingInfo.mByteIndex]);
-}
-
-// Test that one can set and retrieve a value for a float sensor.
-TEST(Obd2SensorStoreTest, setAnyFloatSensor) {
-    Obd2SensorStore sensorStore(getSensorStore());
-    sensorStore.setFloatSensor(
-        Obd2FloatSensorIndex::OXYGEN_SENSOR3_VOLTAGE,
-        2.5f);
-    const auto& floatSensors(sensorStore.getFloatSensors());
-    const auto& sensorBitmask(sensorStore.getSensorsBitmask());
-    ASSERT_EQ(2.5f,
-        floatSensors[toInt(Obd2FloatSensorIndex::OXYGEN_SENSOR3_VOLTAGE)]);
-    const BitmaskIndexingInfo indexingInfo(BitmaskIndexingInfo::getForFloatSensor(
-        toInt(Obd2FloatSensorIndex::OXYGEN_SENSOR3_VOLTAGE)));
-    ASSERT_EQ(
-        indexingInfo.mExpectedByteValue,
-        sensorBitmask[indexingInfo.mByteIndex]);
-}
-
-// Test that one can set and retrieve a value for the last system integer sensor.
-TEST(Obd2SensorStoreTest, setLastSystemIntegerSensor) {
-    Obd2SensorStore sensorStore(getSensorStore());
-    sensorStore.setIntegerSensor(
-        Obd2IntegerSensorIndex::LAST_SYSTEM_INDEX,
-        30);
-    const auto& integerSensors(sensorStore.getIntegerSensors());
-    const auto& sensorBitmask(sensorStore.getSensorsBitmask());
-    ASSERT_EQ(30,
-        integerSensors[toInt(Obd2IntegerSensorIndex::LAST_SYSTEM_INDEX)]);
-    const BitmaskIndexingInfo indexingInfo(BitmaskIndexingInfo::getForIntegerSensor(
-        toInt(Obd2IntegerSensorIndex::LAST_SYSTEM_INDEX)));
-    ASSERT_EQ(
-        indexingInfo.mExpectedByteValue,
-        sensorBitmask[indexingInfo.mByteIndex]);
-}
-
-// Test that one can set and retrieve a value for the last system float sensor.
-TEST(Obd2SensorStoreTest, setLastSystemFloatSensor) {
-    Obd2SensorStore sensorStore(getSensorStore());
-    sensorStore.setFloatSensor(
-        Obd2FloatSensorIndex::LAST_SYSTEM_INDEX,
-        2.5f);
-    const auto& floatSensors(sensorStore.getFloatSensors());
-    const auto& sensorBitmask(sensorStore.getSensorsBitmask());
-    ASSERT_EQ(2.5f,
-        floatSensors[toInt(Obd2FloatSensorIndex::LAST_SYSTEM_INDEX)]);
-    const BitmaskIndexingInfo indexingInfo(BitmaskIndexingInfo::getForFloatSensor(
-        toInt(Obd2FloatSensorIndex::LAST_SYSTEM_INDEX)));
-    ASSERT_EQ(
-        indexingInfo.mExpectedByteValue,
-        sensorBitmask[indexingInfo.mByteIndex]);
-}
-
-// Test that one can set and retrieve a value for two integer sensors at once.
-TEST(Obd2SensorStoreTest, setTwoIntegerSensors) {
-    Obd2SensorStore sensorStore(getSensorStore());
-    sensorStore.setIntegerSensor(
-        Obd2IntegerSensorIndex::CONTROL_MODULE_VOLTAGE,
-        6);
-    sensorStore.setIntegerSensor(
-        Obd2IntegerSensorIndex::TIME_SINCE_TROUBLE_CODES_CLEARED,
-        1245);
-    const auto& integerSensors(sensorStore.getIntegerSensors());
-    const auto& sensorBitmask(sensorStore.getSensorsBitmask());
-    ASSERT_EQ(6,
-        integerSensors[toInt(Obd2IntegerSensorIndex::CONTROL_MODULE_VOLTAGE)]);
-    ASSERT_EQ(1245,
-        integerSensors[toInt(Obd2IntegerSensorIndex::TIME_SINCE_TROUBLE_CODES_CLEARED)]);
-    const BitmaskIndexingInfo voltageIndexingInfo(BitmaskIndexingInfo::getForIntegerSensor(
-        toInt(Obd2IntegerSensorIndex::CONTROL_MODULE_VOLTAGE)));
-    const BitmaskIndexingInfo timeIndexingInfo(BitmaskIndexingInfo::getForIntegerSensor(
-        toInt(Obd2IntegerSensorIndex::TIME_SINCE_TROUBLE_CODES_CLEARED)));
-    if (voltageIndexingInfo.mByteIndex == timeIndexingInfo.mByteIndex) {
-        ASSERT_EQ(
-            voltageIndexingInfo.mExpectedByteValue |
-            timeIndexingInfo.mExpectedByteValue,
-            sensorBitmask[timeIndexingInfo.mByteIndex]);
-    }
-    else {
-        ASSERT_EQ(
-            timeIndexingInfo.mExpectedByteValue,
-            sensorBitmask[timeIndexingInfo.mByteIndex]);
-        ASSERT_EQ(
-            voltageIndexingInfo.mExpectedByteValue,
-            sensorBitmask[voltageIndexingInfo.mByteIndex]);
-    }
-}
-
-// Test that one can set and retrieve a value for two float sensors at once.
-TEST(Obd2SensorStoreTest, setTwoFloatSensors) {
-    Obd2SensorStore sensorStore(getSensorStore());
-    sensorStore.setFloatSensor(
-        Obd2FloatSensorIndex::VEHICLE_SPEED,
-        1.25f);
-    sensorStore.setFloatSensor(
-        Obd2FloatSensorIndex::MAF_AIR_FLOW_RATE,
-        2.5f);
-    const auto& floatSensors(sensorStore.getFloatSensors());
-    const auto& sensorBitmask(sensorStore.getSensorsBitmask());
-    ASSERT_EQ(1.25f,
-        floatSensors[toInt(Obd2FloatSensorIndex::VEHICLE_SPEED)]);
-    ASSERT_EQ(2.5f,
-        floatSensors[toInt(Obd2FloatSensorIndex::MAF_AIR_FLOW_RATE)]);
-    const BitmaskIndexingInfo speedIndexingInfo(BitmaskIndexingInfo::getForFloatSensor(
-        toInt(Obd2FloatSensorIndex::VEHICLE_SPEED)));
-    const BitmaskIndexingInfo airflowIndexingInfo(BitmaskIndexingInfo::getForFloatSensor(
-        toInt(Obd2FloatSensorIndex::MAF_AIR_FLOW_RATE)));
-    if (speedIndexingInfo.mByteIndex == airflowIndexingInfo.mByteIndex) {
-        ASSERT_EQ(
-            speedIndexingInfo.mExpectedByteValue |
-            airflowIndexingInfo.mExpectedByteValue,
-            sensorBitmask[airflowIndexingInfo.mByteIndex]);
-    }
-    else {
-        ASSERT_EQ(
-            speedIndexingInfo.mExpectedByteValue,
-            sensorBitmask[speedIndexingInfo.mByteIndex]);
-        ASSERT_EQ(
-            airflowIndexingInfo.mExpectedByteValue,
-            sensorBitmask[airflowIndexingInfo.mByteIndex]);
-    }
-}
-
-// Test that one can set and retrieve a value for a vendor integer sensor.
-TEST(Obd2SensorStoreTest, setVendorIntegerSensor) {
-    const size_t sensorIndex = toInt(Obd2IntegerSensorIndex::LAST_SYSTEM_INDEX) + 2;
-    Obd2SensorStore sensorStore(getSensorStore());
-    sensorStore.setIntegerSensor(sensorIndex, 22);
-    const auto& integerSensors(sensorStore.getIntegerSensors());
-    const auto& sensorBitmask(sensorStore.getSensorsBitmask());
-    ASSERT_EQ(22, integerSensors[sensorIndex]);
-    const BitmaskIndexingInfo indexingInfo(BitmaskIndexingInfo::getForIntegerSensor(
-        sensorIndex));
-    ASSERT_EQ(
-        indexingInfo.mExpectedByteValue,
-        sensorBitmask[indexingInfo.mByteIndex]);
-}
-
-// Test that one can set and retrieve a value for a vendor float sensor.
-TEST(Obd2SensorStoreTest, setVendorFloatSensor) {
-    const size_t sensorIndex = toInt(Obd2FloatSensorIndex::LAST_SYSTEM_INDEX) + 2;
-    Obd2SensorStore sensorStore(getSensorStore());
-    sensorStore.setFloatSensor(sensorIndex, 1.25f);
-    const auto& floatSensors(sensorStore.getFloatSensors());
-    const auto& sensorBitmask(sensorStore.getSensorsBitmask());
-    ASSERT_EQ(1.25f, floatSensors[sensorIndex]);
-    const BitmaskIndexingInfo indexingInfo(BitmaskIndexingInfo::getForFloatSensor(
-        sensorIndex));
-    ASSERT_EQ(
-        indexingInfo.mExpectedByteValue,
-        sensorBitmask[indexingInfo.mByteIndex]);
-}
-
-}  // namespace anonymous
-
-}  // namespace V2_0
-}  // namespace vehicle
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
diff --git a/automotive/vehicle/2.1/types.hal b/automotive/vehicle/2.1/types.hal
deleted file mode 100644 (file)
index 7be611c..0000000
+++ /dev/null
@@ -1,653 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.1 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.1
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.automotive.vehicle@2.1;
-
-import android.hardware.automotive.vehicle@2.0;
-
-/**
- * Extension of VehicleProperty enum declared in Vehicle HAL 2.0
- */
-enum VehicleProperty: @2.0::VehicleProperty {
-    /**
-     * Reports wheel rotational distance in meters since last wheel tick
-     * event
-     *
-     * The value is a vector each element represents distance for individual
-     * wheel in the following order: left front, right front, left rear,
-     * right rear. VehiclePropValue.timestamp must be correctly filled in.
-     *
-     * Vendors must specify wheels that support this sensor in
-     * VehiclePropConfig.configFlags. The format of this field is a bitset of
-     * values from Wheel enum.
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE |VehiclePropertyChangeMode:CONTINUOUS
-     * @access VehiclePropertyAccess:READ
-     * @unit VehicleUnit:METER
-     */
-    WHEEL_TICK = (
-      0x0306
-      | VehiclePropertyGroup:SYSTEM
-      | VehiclePropertyType:FLOAT_VEC
-      | VehicleArea:GLOBAL),
-
-    /**
-     * OBD2 Live Sensor Data
-     *
-     * This property uses COMPLEX data to send a snapshot of the current (live)
-     * values of the OBD2 sensors provided by the vehicle.
-     *
-     * VehiclePropConfig
-     *   configArray[0] : number of vendor-specific integer-valued sensors
-     *                    that can be returned in a frame.
-     *   configArray[1] : number of vendor-specific float-valued sensors
-     *                    that can be returned in a frame.
-     *
-     * The values are to be interpreted as follows:
-     * the indices defined in Obd2IntegerSensorIndex are to be used to
-     * read from int32Values;
-     * the indices defined in Obd2FloatSensorIndex are to be used to
-     * read from floatValues.
-     * the elements of bytes are to be interpreted as a bitmask, such that
-     * the bits 0 thru the integer value of
-     * Obd2IntegerSensorIndex.LAST_SYSTEM_INDEX + the value of configArray[0]
-     * are 1 if the corresponding index is a valid sensor index whose value can
-     * be read in the returned int32Values vector, 0 otherwise.
-     * the bits Obd2IntegerSensorIndex.LAST_SYSTEM_INDEX+1 thru
-     * Obd2FloatingSensorIndex.LAST_SYSTEM_INDEX + the value of configArray[1]
-     * are 1 if the corresponding index is a valid sensor index whose value
-     * can be read in the returned floatValues vector, 0 otherwise.
-     *
-     * For example, int32Values[0] corresponds to FUEL_SYSTEM_STATUS, and
-     * floatValues[0] corresponds to CALCULATED_ENGINE_LOAD, but that mapping
-     * is only valid if the corresponding bits in the bytes vector are set to 1.
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ
-     */
-    OBD2_LIVE_FRAME = (
-      0x0D00
-      | VehiclePropertyGroup:SYSTEM
-      | VehiclePropertyType:COMPLEX
-      | VehicleArea:GLOBAL),
-
-    /**
-     * OBD2 Freeze Frame Sensor Data
-     *
-     * This property uses COMPLEX data to send a snapshot of the values of the
-     * OBD2 sensors provided by the vehicle at the time that a diagnostic
-     * troubleshooting code (DTC) was recorded by the vehicle.
-     *
-     * VehiclePropConfig
-     *   configArray[0] : number of vendor-specific integer-valued sensors
-     *                    that can be returned in a frame.
-     *   configArray[1] : number of vendor-specific float-valued sensors
-     *                    that can be returned in a frame.
-     *
-     * A get of this property must take the following form:
-     *   int64Values[0]: timestamp of the freeze frame to retrieve.
-     *                   Valid timestamps are given by OBD2_DTC_INFO.
-     *
-     * The values are to be interpreted as follows:
-     * the indices defined in Obd2IntegerSensorIndex are to be used to
-     * read from int32Values;
-     * the indices defined in Obd2FloatSensorIndex are to be used to
-     * read from floatValues;
-     * the elements of bytes are to be interpreted as a bitmask, such that
-     * the bits 0 thru the integer value of
-     * Obd2IntegerSensorIndex.LAST_SYSTEM_INDEX + the value of configArray[0]
-     * are 1 if the corresponding index is a valid sensor index whose value can
-     * be read in the returned int32Values vector, 0 otherwise.
-     * the bits Obd2IntegerSensorIndex.LAST_SYSTEM_INDEX+1 thru
-     * Obd2FloatingSensorIndex.LAST_SYSTEM_INDEX + the value of configArray[1]
-     * are 1 if the corresponding index is a valid sensor index whose value
-     * can be read in the returned floatValues vector, 0 otherwise.
-     * stringValue is the DTC that caused this freeze frame to be recorded.
-     *
-     * For example, int32Values[0] corresponds to FUEL_SYSTEM_STATUS, and
-     * floatValues[0] corresponds to CALCULATED_ENGINE_LOAD, but that mapping
-     * is only valid if the corresponding bits in the bytes vector are set to 1,
-     * and a possible valid stringValue is "P0176" to indicate a malfunction
-     * of the fuel composition sensor circuit.
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ
-     */
-    OBD2_FREEZE_FRAME = (
-      0x0D01
-      | VehiclePropertyGroup:SYSTEM
-      | VehiclePropertyType:COMPLEX
-      | VehicleArea:GLOBAL),
-
-    /**
-     * OBD2 Freeze Frame Information
-     *
-     * This property describes the current freeze frames stored in vehicle
-     * memory and available for retrieval via OBD2_FREEZE_FRAME.
-     *
-     * The values are to be interpreted as follows:
-     * each element of int64Values is the timestamp at which a a fault code
-     * has been detected and the corresponding freeze frame stored, and each
-     * such element can be used as the key to OBD2_FREEZE_FRAME to retrieve
-     * the corresponding freeze frame.
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ
-     */
-    OBD2_FREEZE_FRAME_INFO = (
-      0x0D02
-      | VehiclePropertyGroup:SYSTEM
-      | VehiclePropertyType:COMPLEX
-      | VehicleArea:GLOBAL),
-
-    /**
-     * OBD2 Freeze Frame Clear
-     *
-     * This property allows deletion of any of the freeze frames stored in
-     * vehicle memory, as described by OBD2_DTC_INFO.
-     *
-     * A set of this property is to be interpreted as follows:
-     * if int64Values contains no elements, then all DTCs stored will be cleared;
-     * if int64Values contains one or more elements, then DTCs at the timestamps
-     * stored in int64Values will be cleared, and the others not cleared, except
-     * the memory will be compacted so that all remaining DTCs are stored
-     * contiguously.
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:WRITE
-     */
-    OBD2_FREEZE_FRAME_CLEAR = (
-      0x0D03
-      | VehiclePropertyGroup:SYSTEM
-      | VehiclePropertyType:COMPLEX
-      | VehicleArea:GLOBAL),
-
-    /**
-     * Vehicle Maps Service (VMS) message
-     *
-     * This property uses COMPLEX data to communicate vms messages.
-     *
-     * Its contents are to be interpreted as follows:
-     * the indices defined in VmsMessageIntegerValuesIndex are to be used to
-     * read from int32Values;
-     * bytes is a serialized VMS message as defined in the vms protocol
-     * which is opaque to the framework;
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ_WRITE
-     */
-    VEHICLE_MAP_SERVICE = (
-        0x0C00
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:COMPLEX
-        | VehicleArea:GLOBAL),
-};
-
-/** The status of a fuel system as described by the OBD2 specification. */
-enum FuelSystemStatus : int32_t {
-  OPEN_INSUFFICIENT_ENGINE_TEMPERATURE = 1,
-
-  CLOSED_LOOP = 2,
-
-  OPEN_ENGINE_LOAD_OR_DECELERATION = 4,
-
-  OPEN_SYSTEM_FAILURE = 8,
-
-  CLOSED_LOOP_BUT_FEEDBACK_FAULT = 16,
-};
-
-/** Defines which ignition monitors are available to be read. */
-enum IgnitionMonitorKind : int32_t {
-  SPARK = 0,
-
-  COMPRESSION = 1,
-};
-
-/** These ignition monitors are common to both SPARK and COMPRESSION. */
-enum CommonIgnitionMonitors : int32_t {
-  COMPONENTS_AVAILABLE = 0x1 << 0,
-  COMPONENTS_INCOMPLETE = 0x1 << 1,
-
-  FUEL_SYSTEM_AVAILABLE = 0x1 << 2,
-  FUEL_SYSTEM_INCOMPLETE = 0x1 << 3,
-
-  MISFIRE_AVAILABLE = 0x1 << 4,
-  MISFIRE_INCOMPLETE = 0x1 << 5,
-};
-
-/** Ignition monitors available for SPARK vehicles. */
-enum SparkIgnitionMonitors : CommonIgnitionMonitors {
-  EGR_AVAILABLE = 0x1 << 6,
-  EGR_INCOMPLETE = 0x1 << 7,
-
-  OXYGEN_SENSOR_HEATER_AVAILABLE = 0x1 << 8,
-  OXYGEN_SENSOR_HEATER_INCOMPLETE = 0x1 << 9,
-
-  OXYGEN_SENSOR_AVAILABLE = 0x1 << 10,
-  OXYGEN_SENSOR_INCOMPLETE = 0x1 << 11,
-
-  AC_REFRIGERANT_AVAILABLE = 0x1 << 12,
-  AC_REFRIGERANT_INCOMPLETE = 0x1 << 13,
-
-  SECONDARY_AIR_SYSTEM_AVAILABLE = 0x1 << 14,
-  SECONDARY_AIR_SYSTEM_INCOMPLETE = 0x1 << 15,
-
-  EVAPORATIVE_SYSTEM_AVAILABLE = 0x1 << 16,
-  EVAPORATIVE_SYSTEM_INCOMPLETE = 0x1 << 17,
-
-  HEATED_CATALYST_AVAILABLE = 0x1 << 18,
-  HEATED_CATALYST_INCOMPLETE = 0x1 << 19,
-
-  CATALYST_AVAILABLE = 0x1 << 20,
-  CATALYST_INCOMPLETE = 0x1 << 21,
-};
-
-/** Ignition monitors only available for COMPRESSION vehicles. */
-enum CompressionIgnitionMonitors : CommonIgnitionMonitors {
-  EGR_OR_VVT_AVAILABLE = 0x1 << 6,
-  EGR_OR_VVT_INCOMPLETE = 0x1 << 7,
-
-  PM_FILTER_AVAILABLE = 0x1 << 8,
-  PM_FILTER_INCOMPLETE = 0x1 << 9,
-
-  EXHAUST_GAS_SENSOR_AVAILABLE = 0x1 << 10,
-  EXHAUST_GAS_SENSOR_INCOMPLETE = 0x1 << 11,
-
-  BOOST_PRESSURE_AVAILABLE = 0x1 << 12,
-  BOOST_PRESSURE_INCOMPLETE = 0x1 << 13,
-
-  NOx_SCR__AVAILABLE = 0x1 << 14,
-  NOx_SCR_INCOMPLETE = 0x1 << 15,
-
-  NMHC_CATALYST_AVAILABLE = 0x1 << 16,
-  NMHC_CATALYST_INCOMPLETE = 0x1 << 17,
-};
-
-enum SecondaryAirStatus : int32_t {
-  UPSTREAM = 1,
-
-  DOWNSTREAM_OF_CATALYCIC_CONVERTER = 2,
-
-  FROM_OUTSIDE_OR_OFF = 4,
-
-  PUMP_ON_FOR_DIAGNOSTICS = 8,
-};
-
-enum FuelType : int32_t {
-  NOT_AVAILABLE = 0,
-
-  GASOLINE = 1,
-
-  METHANOL = 2,
-
-  ETHANOL = 3,
-
-  DIESEL = 4,
-
-  LPG = 5,
-
-  CNG = 6,
-
-  PROPANE = 7,
-
-  ELECTRIC = 8,
-
-  BIFUEL_RUNNING_GASOLINE = 9,
-
-  BIFUEL_RUNNING_METHANOL = 10,
-
-  BIFUEL_RUNNING_ETHANOL = 11,
-
-  BIFUEL_RUNNING_LPG = 12,
-
-  BIFUEL_RUNNING_CNG = 13,
-
-  BIFUEL_RUNNING_PROPANE = 14,
-
-  BIFUEL_RUNNING_ELECTRIC = 15,
-
-  BIFUEL_RUNNING_ELECTRIC_AND_COMBUSTION = 16,
-
-  HYBRID_GASOLINE = 17,
-
-  HYBRID_ETHANOL = 18,
-
-  HYBRID_DIESEL = 19,
-
-  HYBRID_ELECTRIC = 20,
-
-  HYBRID_RUNNING_ELECTRIC_AND_COMBUSTION = 21,
-
-  HYBRID_REGENERATIVE = 22,
-
-  BIFUEL_RUNNING_DIESEL = 23,
-};
-
-/**
- * This enum provides the canonical mapping for sensor properties that have an integer value.
- * The ordering of the values is taken from the OBD2 specification.
- * Some of the properties are represented as an integer mapping to another enum. In those cases
- * expect a comment by the property definition describing the enum to look at for the mapping.
- * Any value greater than the last reserved index is available to vendors to map their extensions.
- */
-enum Obd2IntegerSensorIndex : int32_t {
-  /** refer to FuelSystemStatus for a description of this value. */
-  FUEL_SYSTEM_STATUS = 0,
-
-  MALFUNCTION_INDICATOR_LIGHT_ON = 1,
-
-  /** refer to IgnitionMonitorKind for a description of this value. */
-  IGNITION_MONITORS_SUPPORTED = 2,
-
-  /**
-   * The value of this sensor is a bitmask that specifies whether ignition-specific
-   * tests are available and whether they are complete. The semantics of the individual
-   * bits in this value are given by, respectively, SparkIgnitionMonitors and
-   * CompressionIgnitionMonitors depending on the value of IGNITION_MONITORS_SUPPORTED.
-   */
-  IGNITION_SPECIFIC_MONITORS = 3,
-
-  INTAKE_AIR_TEMPERATURE = 4,
-
-  /** refer to SecondaryAirStatus for a description of this value. */
-  COMMANDED_SECONDARY_AIR_STATUS = 5,
-
-  NUM_OXYGEN_SENSORS_PRESENT = 6,
-
-  RUNTIME_SINCE_ENGINE_START = 7,
-
-  DISTANCE_TRAVELED_WITH_MALFUNCTION_INDICATOR_LIGHT_ON = 8,
-
-  WARMUPS_SINCE_CODES_CLEARED = 9,
-
-  DISTANCE_TRAVELED_SINCE_CODES_CLEARED = 10,
-
-  ABSOLUTE_BAROMETRIC_PRESSURE = 11,
-
-  CONTROL_MODULE_VOLTAGE = 12,
-
-  AMBIENT_AIR_TEMPERATURE = 13,
-
-  TIME_WITH_MALFUNCTION_LIGHT_ON = 14,
-
-  TIME_SINCE_TROUBLE_CODES_CLEARED = 15,
-
-  MAX_FUEL_AIR_EQUIVALENCE_RATIO = 16,
-
-  MAX_OXYGEN_SENSOR_VOLTAGE = 17,
-
-  MAX_OXYGEN_SENSOR_CURRENT = 18,
-
-  MAX_INTAKE_MANIFOLD_ABSOLUTE_PRESSURE = 19,
-
-  MAX_AIR_FLOW_RATE_FROM_MASS_AIR_FLOW_SENSOR = 20,
-
-  /** refer to FuelType for a description of this value. */
-  FUEL_TYPE = 21,
-
-  FUEL_RAIL_ABSOLUTE_PRESSURE = 22,
-
-  ENGINE_OIL_TEMPERATURE = 23,
-
-  DRIVER_DEMAND_PERCENT_TORQUE = 24,
-
-  ENGINE_ACTUAL_PERCENT_TORQUE = 25,
-
-  ENGINE_REFERENCE_PERCENT_TORQUE = 26,
-
-  ENGINE_PERCENT_TORQUE_DATA_IDLE = 27,
-
-  ENGINE_PERCENT_TORQUE_DATA_POINT1 = 28,
-
-  ENGINE_PERCENT_TORQUE_DATA_POINT2 = 29,
-
-  ENGINE_PERCENT_TORQUE_DATA_POINT3 = 30,
-
-  ENGINE_PERCENT_TORQUE_DATA_POINT4 = 31,
-
-  LAST_SYSTEM_INDEX = ENGINE_PERCENT_TORQUE_DATA_POINT4,
-};
-
-/**
- * This enum provides the canonical mapping for sensor properties that have a floating-point value.
- * The ordering of the values is taken from the OBD2 specification.
- * Any value greater than the last reserved index is available to vendors to map their extensions.
- */
-enum Obd2FloatSensorIndex : int32_t {
-  CALCULATED_ENGINE_LOAD = 0,
-
-  ENGINE_COOLANT_TEMPERATURE = 1,
-
-  SHORT_TERM_FUEL_TRIM_BANK1 = 2,
-
-  LONG_TERM_FUEL_TRIM_BANK1 = 3,
-
-  SHORT_TERM_FUEL_TRIM_BANK2 = 4,
-
-  LONG_TERM_FUEL_TRIM_BANK2 = 5,
-
-  FUEL_PRESSURE = 6,
-
-  INTAKE_MANIFOLD_ABSOLUTE_PRESSURE = 7,
-
-  ENGINE_RPM = 8,
-
-  VEHICLE_SPEED = 9,
-
-  TIMING_ADVANCE = 10,
-
-  MAF_AIR_FLOW_RATE = 11,
-
-  THROTTLE_POSITION = 12,
-
-  OXYGEN_SENSOR1_VOLTAGE = 13,
-
-  OXYGEN_SENSOR1_SHORT_TERM_FUEL_TRIM = 14,
-
-  OXYGEN_SENSOR1_FUEL_AIR_EQUIVALENCE_RATIO = 15,
-
-  OXYGEN_SENSOR2_VOLTAGE = 16,
-
-  OXYGEN_SENSOR2_SHORT_TERM_FUEL_TRIM = 17,
-
-  OXYGEN_SENSOR2_FUEL_AIR_EQUIVALENCE_RATIO = 18,
-
-  OXYGEN_SENSOR3_VOLTAGE = 19,
-
-  OXYGEN_SENSOR3_SHORT_TERM_FUEL_TRIM = 20,
-
-  OXYGEN_SENSOR3_FUEL_AIR_EQUIVALENCE_RATIO = 21,
-
-  OXYGEN_SENSOR4_VOLTAGE = 22,
-
-  OXYGEN_SENSOR4_SHORT_TERM_FUEL_TRIM = 23,
-
-  OXYGEN_SENSOR4_FUEL_AIR_EQUIVALENCE_RATIO = 24,
-
-  OXYGEN_SENSOR5_VOLTAGE = 25,
-
-  OXYGEN_SENSOR5_SHORT_TERM_FUEL_TRIM = 26,
-
-  OXYGEN_SENSOR5_FUEL_AIR_EQUIVALENCE_RATIO = 27,
-
-  OXYGEN_SENSOR6_VOLTAGE = 28,
-
-  OXYGEN_SENSOR6_SHORT_TERM_FUEL_TRIM = 29,
-
-  OXYGEN_SENSOR6_FUEL_AIR_EQUIVALENCE_RATIO = 30,
-
-  OXYGEN_SENSOR7_VOLTAGE = 31,
-
-  OXYGEN_SENSOR7_SHORT_TERM_FUEL_TRIM = 32,
-
-  OXYGEN_SENSOR7_FUEL_AIR_EQUIVALENCE_RATIO = 33,
-
-  OXYGEN_SENSOR8_VOLTAGE = 34,
-
-  OXYGEN_SENSOR8_SHORT_TERM_FUEL_TRIM = 35,
-
-  OXYGEN_SENSOR8_FUEL_AIR_EQUIVALENCE_RATIO = 36,
-
-  FUEL_RAIL_PRESSURE = 37,
-
-  FUEL_RAIL_GAUGE_PRESSURE = 38,
-
-  COMMANDED_EXHAUST_GAS_RECIRCULATION = 39,
-
-  EXHAUST_GAS_RECIRCULATION_ERROR = 40,
-
-  COMMANDED_EVAPORATIVE_PURGE = 41,
-
-  FUEL_TANK_LEVEL_INPUT = 42,
-
-  EVAPORATION_SYSTEM_VAPOR_PRESSURE = 43,
-
-  CATALYST_TEMPERATURE_BANK1_SENSOR1 = 44,
-
-  CATALYST_TEMPERATURE_BANK2_SENSOR1 = 45,
-
-  CATALYST_TEMPERATURE_BANK1_SENSOR2 = 46,
-
-  CATALYST_TEMPERATURE_BANK2_SENSOR2 = 47,
-
-  ABSOLUTE_LOAD_VALUE = 48,
-
-  FUEL_AIR_COMMANDED_EQUIVALENCE_RATIO = 49,
-
-  RELATIVE_THROTTLE_POSITION = 50,
-
-  ABSOLUTE_THROTTLE_POSITION_B = 51,
-
-  ABSOLUTE_THROTTLE_POSITION_C = 52,
-
-  ACCELERATOR_PEDAL_POSITION_D = 53,
-
-  ACCELERATOR_PEDAL_POSITION_E = 54,
-
-  ACCELERATOR_PEDAL_POSITION_F = 55,
-
-  COMMANDED_THROTTLE_ACTUATOR = 56,
-
-  ETHANOL_FUEL_PERCENTAGE = 57,
-
-  ABSOLUTE_EVAPORATION_SYSTEM_VAPOR_PRESSURE = 58,
-
-  SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK1 = 59,
-
-  SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK2 = 60,
-
-  SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK3 = 61,
-
-  SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK4 = 62,
-
-  LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK1 = 63,
-
-  LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK2 = 64,
-
-  LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK3 = 65,
-
-  LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK4 = 66,
-
-  RELATIVE_ACCELERATOR_PEDAL_POSITION = 67,
-
-  HYBRID_BATTERY_PACK_REMAINING_LIFE = 68,
-
-  FUEL_INJECTION_TIMING = 69,
-
-  ENGINE_FUEL_RATE = 70,
-
-  LAST_SYSTEM_INDEX = ENGINE_FUEL_RATE,
-};
-
-/**
- * This enum lists the types of supported VMS messages.
- */
-enum VmsMessageType : int32_t {
-  /** A client subscribes to a layer. */
-  SUBSCRIBE = 1,
-
-  /** A client unsubscribes from a layer. */
-  UNSUBSCRIBE = 2,
-
-  /** A client publishes a data packet. */
-  DATA = 3,
-
-  /* A client declaring layers offering. */
-  OFFERING = 4,
-
-  /* Requesting the list of available layers. */
-  AVAILABILITY_REQUEST = 5,
-
-  /* Returning the list of available layers. */
-  AVAILABILITY_RESPONSE = 6,
-
-  /** Requesting layers that have subscribers. */
-  SUBSCRIPTION_REQUEST = 7,
-
-  /** Returning layers that have subscribers. */
-  SUBSCRIPTION_RESPONSE = 8,
-};
-
-/**
- * This enum provides the canonical mapping for VMS properties that have an
- * integer value.
- */
-enum VmsBaseMessageIntegerValuesIndex : int32_t {
-  /* The message type as enumerated by VmsMessageType enum. */
-  VMS_MESSAGE_TYPE = 0,
-};
-
-/*
- * This enum provides the canonical mapping for VMS SUBMIT, UNSUBMIT and DATA
- * messages integer value properties.
- */
-enum VmsSimpleMessageIntegerValuesIndex : VmsBaseMessageIntegerValuesIndex {
-  /* The layer ID as defined in the vms protocol. */
-  VMS_LAYER_ID = 1,
-
-  /* The version of the VMS layer. */
-  VMS_LAYER_VERSION = 2,
-};
-
-/*
- * This enum provides the canonical mapping for VMS offering messages integer
- * value properties
- */
-enum VmsOfferingMessageIntegerValuesIndex : VmsBaseMessageIntegerValuesIndex {
-  /* The number of VMS layer dependencies. */
-  VMS_NUMBER_OF_LAYERS_DEPENDENCIES = 1,
-
-  /* The first index that contain dependencies */
-  FIRST_DEPENDENCIES_INDEX = 2,
-};
-
-/**
- * A VMS subscription request only contains its message type. The format of a VMS subscription
- * response is described below.
- */
-enum VmsSubscriptionResponseFormat : VmsBaseMessageIntegerValuesIndex {
-  /**
-    * Recipients should ignore any packet with a sequence number that is less than the highest
-    * sequence number they have seen thus far.
-    */
-  SEQUENCE_NUMBER = 1,
-
-  /** The number of VMS layers. Each layer has two integers: type and version. */
-  NUMBER_OF_LAYERS = 2,
-
-  /** The first index that contains a layer. */
-  FIRST_LAYER = 3,
-};
index c16fd78..3898da5 100644 (file)
@@ -46,13 +46,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.biometrics.fingerprint@2.1",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.biometrics.fingerprint@2.1_genc++"],
     generated_headers: ["android.hardware.biometrics.fingerprint@2.1_genc++_headers"],
     export_generated_headers: ["android.hardware.biometrics.fingerprint@2.1_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index c6774ca..f687959 100644 (file)
@@ -145,6 +145,7 @@ FingerprintAcquiredInfo BiometricsFingerprint::VendorAcquiredFilter(
 
 Return<uint64_t> BiometricsFingerprint::setNotify(
         const sp<IBiometricsFingerprintClientCallback>& clientCallback) {
+    std::lock_guard<std::mutex> lock(mClientCallbackMutex);
     mClientCallback = clientCallback;
     // This is here because HAL 2.1 doesn't have a way to propagate a
     // unique token for its driver. Subsequent versions should send a unique
@@ -259,6 +260,7 @@ fingerprint_device_t* BiometricsFingerprint::openHal() {
 void BiometricsFingerprint::notify(const fingerprint_msg_t *msg) {
     BiometricsFingerprint* thisPtr = static_cast<BiometricsFingerprint*>(
             BiometricsFingerprint::getInstance());
+    std::lock_guard<std::mutex> lock(thisPtr->mClientCallbackMutex);
     if (thisPtr == nullptr || thisPtr->mClientCallback == nullptr) {
         ALOGE("Receiving callbacks before the client callback is registered.");
         return;
index 5923c84..6d64e3d 100644 (file)
@@ -69,6 +69,7 @@ private:
     static FingerprintAcquiredInfo VendorAcquiredFilter(int32_t error, int32_t* vendorCode);
     static BiometricsFingerprint* sInstance;
 
+    std::mutex mClientCallbackMutex;
     sp<IBiometricsFingerprintClientCallback> mClientCallback;
     fingerprint_device_t *mDevice;
 };
index 27b7157..bee3657 100644 (file)
 
 cc_test {
     name: "VtsHalBiometricsFingerprintV2_1TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalBiometricsFingerprintV2_1TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "libhidltransport",
-        "libhardware",
-        "libhidlbase",
-        "liblog",
-        "libutils",
-        "android.hardware.biometrics.fingerprint@2.1",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ]
+    static_libs: ["android.hardware.biometrics.fingerprint@2.1"],
 }
 
index 48159b3..c883c59 100644 (file)
@@ -46,13 +46,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.bluetooth@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.bluetooth@1.0_genc++"],
     generated_headers: ["android.hardware.bluetooth@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.bluetooth@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index bc0bc92..78676b2 100644 (file)
@@ -24,7 +24,7 @@
 #include <map>
 #include <mutex>
 #include <thread>
-#include <utils/Log.h>
+#include <log/log.h>
 #include <vector>
 #include "fcntl.h"
 #include "sys/select.h"
index 65dc6a6..fd53e78 100644 (file)
@@ -19,6 +19,7 @@
 #include <cutils/properties.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <unistd.h>
 #include <utils/Log.h>
 
 namespace android {
index 6912405..e2797b1 100644 (file)
@@ -21,6 +21,8 @@
 
 #include <hidl/MQDescriptor.h>
 
+#include <functional>
+
 namespace android {
 namespace hardware {
 namespace bluetooth {
index 2008b00..163cc33 100644 (file)
@@ -22,6 +22,7 @@
 #include <fcntl.h>
 #include <log/log.h>
 #include <sys/uio.h>
+#include <unistd.h>
 
 namespace android {
 namespace hardware {
@@ -81,6 +82,12 @@ void H4Protocol::OnDataReady(int fd) {
       }
     }
     hci_packet_type_ = static_cast<HciPacketType>(buffer[0]);
+    if (hci_packet_type_ != HCI_PACKET_TYPE_ACL_DATA &&
+        hci_packet_type_ != HCI_PACKET_TYPE_SCO_DATA &&
+        hci_packet_type_ != HCI_PACKET_TYPE_EVENT) {
+      LOG_ALWAYS_FATAL("%s: Unimplemented packet type %d", __func__,
+                       static_cast<int>(hci_packet_type_));
+    }
   } else {
     hci_packetizer_.OnDataReady(fd, hci_packet_type_);
   }
index 2da1254..fde08ac 100644 (file)
@@ -21,6 +21,7 @@
 #include <dlfcn.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <unistd.h>
 #include <utils/Log.h>
 
 namespace {
index a208da1..bf94dfe 100644 (file)
@@ -18,7 +18,9 @@
 
 #define LOG_TAG "android.hardware.bluetooth-hci-hci_protocol"
 #include <assert.h>
+#include <errno.h>
 #include <fcntl.h>
+#include <unistd.h>
 #include <log/log.h>
 
 namespace android {
index 15b6c74..6ce2f11 100644 (file)
@@ -162,8 +162,10 @@ bool VendorInterface::Initialize(
     InitializeCompleteCallback initialize_complete_cb,
     PacketReadCallback event_cb, PacketReadCallback acl_cb,
     PacketReadCallback sco_cb) {
-  LOG_ALWAYS_FATAL_IF(g_vendor_interface, "%s: No previous Shutdown()?",
-                      __func__);
+  if (g_vendor_interface) {
+    ALOGE("%s: No previous Shutdown()?", __func__);
+    return false;
+  }
   g_vendor_interface = new VendorInterface();
   return g_vendor_interface->Open(initialize_complete_cb, event_cb, acl_cb,
                                   sco_cb);
index d2e6553..2e60588 100644 (file)
 
 cc_test {
     name: "VtsHalBluetoothV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalBluetoothV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
+    static_libs: [
         "android.hardware.bluetooth@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
+        "libbluetooth-types",
     ],
 }
index fb53366..6c9aa18 100644 (file)
@@ -464,8 +464,9 @@ void BluetoothHidlTest::sendAndCheckACL(int num_packets, size_t size,
 
 // Return the number of completed packets reported by the controller.
 int BluetoothHidlTest::wait_for_completed_packets_event(uint16_t handle) {
-    EXPECT_TRUE(bluetooth_cb->WaitForCallback(kCallbackNameHciEventReceived)
-                    .no_timeout);
+    if (!bluetooth_cb->WaitForCallback(kCallbackNameHciEventReceived).no_timeout) {
+        ALOGW("%s: WaitForCallback timed out.", __func__);
+    }
     int packets_processed = 0;
     while (event_queue.size() > 0) {
         hidl_vec<uint8_t> event = event_queue.front();
@@ -604,20 +605,24 @@ TEST_F(BluetoothHidlTest, LoopbackModeSinglePackets) {
 
   // This should work, but breaks on some current platforms.  Figure out how to
   // grandfather older devices but test new ones.
-  int sco_packets_sent = 0;
   if (0 && sco_connection_handles.size() > 0) {
     sendAndCheckSCO(1, max_sco_data_packet_length, sco_connection_handles[0]);
-    sco_packets_sent = 1;
-    EXPECT_EQ(sco_packets_sent,
-              wait_for_completed_packets_event(sco_connection_handles[0]));
+    int sco_packets_sent = 1;
+    int completed_packets = wait_for_completed_packets_event(sco_connection_handles[0]);
+    if (sco_packets_sent != completed_packets) {
+        ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__, sco_packets_sent,
+              completed_packets);
+    }
   }
 
-  int acl_packets_sent = 0;
   if (acl_connection_handles.size() > 0) {
     sendAndCheckACL(1, max_acl_data_packet_length, acl_connection_handles[0]);
-    acl_packets_sent = 1;
-    EXPECT_EQ(acl_packets_sent,
-              wait_for_completed_packets_event(acl_connection_handles[0]));
+    int acl_packets_sent = 1;
+    int completed_packets = wait_for_completed_packets_event(acl_connection_handles[0]);
+    if (acl_packets_sent != completed_packets) {
+        ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__, acl_packets_sent,
+              completed_packets);
+    }
   }
 }
 
@@ -633,22 +638,26 @@ TEST_F(BluetoothHidlTest, LoopbackModeBandwidth) {
 
   // This should work, but breaks on some current platforms.  Figure out how to
   // grandfather older devices but test new ones.
-  int sco_packets_sent = 0;
   if (0 && sco_connection_handles.size() > 0) {
     sendAndCheckSCO(NUM_SCO_PACKETS_BANDWIDTH, max_sco_data_packet_length,
                     sco_connection_handles[0]);
-    sco_packets_sent = NUM_SCO_PACKETS_BANDWIDTH;
-    EXPECT_EQ(sco_packets_sent,
-              wait_for_completed_packets_event(sco_connection_handles[0]));
+    int sco_packets_sent = NUM_SCO_PACKETS_BANDWIDTH;
+    int completed_packets = wait_for_completed_packets_event(sco_connection_handles[0]);
+    if (sco_packets_sent != completed_packets) {
+        ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__, sco_packets_sent,
+              completed_packets);
+    }
   }
 
-  int acl_packets_sent = 0;
   if (acl_connection_handles.size() > 0) {
     sendAndCheckACL(NUM_ACL_PACKETS_BANDWIDTH, max_acl_data_packet_length,
                     acl_connection_handles[0]);
-    acl_packets_sent = NUM_ACL_PACKETS_BANDWIDTH;
-    EXPECT_EQ(acl_packets_sent,
-              wait_for_completed_packets_event(acl_connection_handles[0]));
+    int acl_packets_sent = NUM_ACL_PACKETS_BANDWIDTH;
+    int completed_packets = wait_for_completed_packets_event(acl_connection_handles[0]);
+    if (acl_packets_sent != completed_packets) {
+        ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__, acl_packets_sent,
+              completed_packets);
+    }
   }
 }
 
index de42647..4e4efa3 100644 (file)
@@ -39,13 +39,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.boot@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.boot@1.0_genc++"],
     generated_headers: ["android.hardware.boot@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.boot@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index 5b14f54..2ef89f3 100644 (file)
 
 cc_test {
     name: "VtsHalBootV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalBootV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libnativehelper",
-        "libutils",
-        "android.hardware.boot@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ]
+    static_libs: ["android.hardware.boot@1.0"],
 }
index f0c4b22..5b8e239 100644 (file)
@@ -60,13 +60,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.broadcastradio@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.broadcastradio@1.0_genc++"],
     generated_headers: ["android.hardware.broadcastradio@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.broadcastradio@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/broadcastradio/1.0/default/OWNERS b/broadcastradio/1.0/default/OWNERS
new file mode 100644 (file)
index 0000000..b159083
--- /dev/null
@@ -0,0 +1,4 @@
+elaurent@google.com
+krocard@google.com
+mnaganov@google.com
+twasilczyk@google.com
index 045231d..8c3ec11 100644 (file)
@@ -146,8 +146,11 @@ enum MetadataType : int32_t {
     /** String */
     TEXT       = 1,
     /**
-     * Raw binary data (icon or art)
-       This data must be transparent to the android framework */
+     * Raw binary data (icon or art).
+     *
+     * The data should be a valid PNG, JPEG, GIF or BMP file.
+     * Invalid format must be handled gracefully as if the field was missing.
+     */
     RAW        = 2,
     /** clock data, see MetaDataClock */
     CLOCK      = 3,
@@ -155,7 +158,7 @@ enum MetadataType : int32_t {
 
 enum MetadataKey : int32_t {
     INVALID      = -1,
-    /** RDS PI                 - string  */
+    /** RDS PI                 - int32_t  */
     RDS_PI       = 0,
     /** RDS PS                 - string */
     RDS_PS       = 1,
@@ -173,9 +176,9 @@ enum MetadataKey : int32_t {
     ALBUM        = 7,
     /** Musical genre          - string  */
     GENRE        = 8,
-    /** Station icon           - raw  */
+    /** Station icon           - raw (int32_t for HAL 1.1) */
     ICON         = 9,
-    /** Album art              - raw  */
+    /** Album art              - raw (int32_t for HAL 1.1) */
     ART          = 10,
     /** Clock                  - MetaDataClock */
     CLOCK        = 11,
@@ -208,10 +211,24 @@ struct MetaData {
 struct ProgramInfo {
     uint32_t     channel;   /** current channel. (e.g kHz for band type AM_FM) */
     uint32_t     subChannel; /** current sub channel. (FM_HD) */
-    bool         tuned;     /** tuned to a program or not */
+
+    /**
+     * Tuned to a program (not a noise). It's the same condition that would
+     * stop scan operation.
+     */
+    bool         tuned;
+
     bool         stereo;    /** program is stereo or not */
     bool         digital;   /** digital program or not (e.g HD Radio program) */
-    uint32_t     signalStrength; /** signal strength from 0 to 100 */
-    vec<MetaData> metadata; /** non empty if meta data are present (e.g PTY, song title ...) */
+
+    /**
+     * Signal quality measured in 0% to 100% range.
+     *
+     * Despite the name, this is not a signal strength.
+     * The purpose of this field is primarily informative.
+     */
+    uint32_t signalStrength;
+
+    vec<MetaData> metadata; /** Metadata: PTY, song title etc. */
 };
 
index cf52f49..f31a2dc 100644 (file)
 
 cc_test {
     name: "VtsHalBroadcastradioV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalBroadcastradioV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
-        "android.hardware.broadcastradio@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
+    static_libs: ["android.hardware.broadcastradio@1.0"],
 }
index 3b50416..12e23d6 100644 (file)
@@ -60,13 +60,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.broadcastradio@1.1",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.broadcastradio@1.1_genc++"],
     generated_headers: ["android.hardware.broadcastradio@1.1_genc++_headers"],
     export_generated_headers: ["android.hardware.broadcastradio@1.1_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index dd37d49..dadba2a 100644 (file)
@@ -27,4 +27,38 @@ interface IBroadcastRadio extends @1.0::IBroadcastRadio {
      */
     getProperties_1_1() generates (Properties properties);
 
+    /**
+     * Fetch image from radio module.
+     *
+     * This call is meant to make V1_0::MetaData lightweight - instead of
+     * passing an image data blob in the MetadataType.RAW field, the HAL
+     * implementation only passes the identifier, so the client may cache images
+     * or even not fetch them.
+     *
+     * The identifier may be any arbitrary number - sequential, sha256 prefix,
+     * or any other unique value selected by the vendor.
+     *
+     * The data should be a valid PNG, JPEG, GIF or BMP file.
+     * Image data with an invalid format must be handled gracefully in the same
+     * way as a missing image.
+     *
+     * The image identifier may become invalid after some time from passing it
+     * with metadata struct (due to resource cleanup at the HAL implementation).
+     * However, it must remain valid for a currently tuned program at least
+     * until currentProgramInfoChanged or programListChanged is called and
+     * metadata changes for the current program.
+     *
+     * There is still a race condition possible (if the HAL deletes the old
+     * image immediately after notifying about the new one) between
+     * currentProgramInfoChanged callback propagating through the framework and
+     * the HAL implementation removing previous image. In such case, client
+     * application may expect the new currentProgramInfoChanged callback with
+     * updated image identifier.
+     *
+     * @param id Identifier of an image;
+     *           value of 0 is reserved and should be treated as invalid image.
+     * @return image A binary blob with image data
+     *               or a zero-length vector if identifier doesn't exist.
+     */
+    getImage(int32_t id) generates (vec<uint8_t> image);
 };
index fce1cc0..edf78ff 100644 (file)
@@ -19,8 +19,10 @@ package android.hardware.broadcastradio@1.1;
 import @1.0::IBroadcastRadioFactory;
 
 /**
- * To use 1.1 features you must cast specific interfaces after being returned from 1.0 HAL,
- * for example V1_1::ITuner::castFrom() after retrieving it from IBroadcastRadio::openTuner().
+ * To use 1.1 features you must cast specific interfaces returned from the
+ * 1.0 HAL. For example V1_0::IBroadcastRadio::openTuner() returns V1_0::ITuner,
+ * which can be cast with V1_1::ITuner::castFrom() call.
+ *
  * The 1.1 server must always return the 1.1 version of specific interface.
  */
 interface IBroadcastRadioFactory extends @1.0::IBroadcastRadioFactory {
index 7511629..b20c5f4 100644 (file)
@@ -21,6 +21,45 @@ import @1.0::ITuner;
 interface ITuner extends @1.0::ITuner {
 
     /**
+     * Tune to a specified program.
+     *
+     * For AM/FM, it must be called when a valid configuration has been applied.
+     * Automatically cancels pending scan, step or tune.
+     *
+     * If method returns OK, ITunerCallback.tuneComplete_1_1() MUST be called:
+     * - once successfully tuned;
+     * - after a time out;
+     * - after a full band scan, if no station found.
+     *
+     * The tuned field of ProgramInfo should indicate if tuned to a valid
+     * station or not.
+     *
+     * @param program Program to tune to.
+     * @return result OK if successfully started tunning.
+     *                INVALID_ARGUMENTS if invalid arguments are passed.
+     *                NOT_INITIALIZED if another error occurs.
+     */
+    tuneByProgramSelector(ProgramSelector program) generates (Result result);
+
+    /**
+     * Cancels announcement.
+     *
+     * If it was traffic announcement, trafficAnnouncement(false) callback
+     * should be called (just like it was ended in a normal way). Similarly for
+     * emergency announcement. If there was no announcement, then no action
+     * should be taken.
+     *
+     * There is a race condition between calling cancelAnnouncement and the
+     * actual announcement being finished, so trafficAnnouncement /
+     * emergencyAnnouncement callback should be tracked with proper locking.
+     *
+     * @return result OK if successfully cancelled announcement or there was
+     *                no announcement.
+     *                NOT_INITIALIZED if another error occurs.
+     */
+    cancelAnnouncement() generates (Result result);
+
+    /**
      * Retrieve current station information.
      * @return result OK if scan successfully started
      *                NOT_INITIALIZED if another error occurs
@@ -45,6 +84,13 @@ interface ITuner extends @1.0::ITuner {
      * subsequent calls to startBackgroundScan, issuing a single
      * backgroundScanComplete callback.
      *
+     * If a device supports continuous background scanning, it may succeed
+     * (return OK and call backgroundScanComplete) without any additional
+     * operation performed.
+     *
+     * Foreground scanning may be implemented in the front end app with
+     * @1.0::ITuner scan operation.
+     *
      * @return result OK if the scan was properly scheduled (this does not mean
      *                it successfully finished).
      *                UNAVAILABLE if the background scan is unavailable,
@@ -60,10 +106,8 @@ interface ITuner extends @1.0::ITuner {
      * This call does not trigger actual scan, but operates on the list cached
      * internally at the driver level.
      *
-     * @param filter vendor-specific filter for the stations to be retrieved.
-     *               An empty string MUST result in full list.
-     *               Client application MUST verify vendor/product name
-     *               before setting this parameter to anything else.
+     * @param vendorFilter vendor-specific filter for the stations to be retrieved.
+     *               An empty vector MUST result in full list for a given tuner.
      * @return result OK if the list was successfully retrieved.
      *                INVALID_ARGUMENTS if invalid arguments are passed
      *                NOT_READY if the scan is in progress.
@@ -72,23 +116,10 @@ interface ITuner extends @1.0::ITuner {
      *                NOT_INITIALIZED if any other error occurs.
      * @return programList List of stations available for user.
      */
-    getProgramList(string filter)
+    getProgramList(vec<VendorKeyValue> vendorFilter)
         generates (ProgramListResult result, vec<ProgramInfo> programList);
 
     /**
-     * Checks, if the analog playback is forced, see setAnalogForced.
-     *
-     * The isForced value is only valid if result was OK.
-     *
-     * @return result OK if the call succeeded and isForced is valid.
-     *                INVALID_STATE if the switch is not supported at current
-     *                configuration.
-     *                NOT_INITIALIZED if any other error occurs.
-     * @return isForced true if analog is forced, false otherwise.
-     */
-    isAnalogForced() generates (Result result, bool isForced);
-
-    /**
      * Forces the analog playback for the supporting radio technology.
      *
      * User may disable digital playback for FM HD Radio or hybrid FM/DAB with
@@ -104,4 +135,17 @@ interface ITuner extends @1.0::ITuner {
      *                NOT_INITIALIZED if any other error occurs.
      */
     setAnalogForced(bool isForced) generates (Result result);
+
+    /**
+     * Checks, if the analog playback is forced, see setAnalogForced.
+     *
+     * The isForced value is only valid if result was OK.
+     *
+     * @return result OK if the call succeeded and isForced is valid.
+     *                INVALID_STATE if the switch is not supported at current
+     *                configuration.
+     *                NOT_INITIALIZED if any other error occurs.
+     * @return isForced true if analog is forced, false otherwise.
+     */
+    isAnalogForced() generates (Result result, bool isForced);
 };
index 158e217..8bf5b7f 100644 (file)
@@ -28,16 +28,19 @@ interface ITunerCallback extends @1.0::ITunerCallback {
     /**
      * Method called by the HAL when a tuning operation completes
      * following a step(), scan() or tune() command.
+     *
+     * This callback supersedes V1_0::tuneComplete.
+     * The 1.0 callback must not be called when HAL implementation detects
+     * 1.1 client (by casting V1_0::ITunerCallback to V1_1::ITunerCallback).
+     *
+     * In case of success, currentProgramInfoChanged must be called too.
+     * It means the success case may (or may not) be handled by the client in
+     * currentProgramInfoChanged, instead of here.
+     *
      * @param result OK if tune succeeded or TIMEOUT in case of time out.
-     * @param info A ProgramInfo structure describing the tuned station.
+     * @param selector A ProgramSelector structure describing the tuned station.
      */
-    oneway tuneComplete_1_1(Result result, ProgramInfo info);
-
-    /**
-     * Method called by the HAL when a frequency switch occurs.
-     * @param info A ProgramInfo structure describing the new tuned station.
-     */
-    oneway afSwitch_1_1(ProgramInfo info);
+    oneway tuneComplete_1_1(Result result, ProgramSelector selector);
 
     /**
      * Called by the HAL when background scan feature becomes available or not.
@@ -63,10 +66,31 @@ interface ITunerCallback extends @1.0::ITunerCallback {
      * call it immediately, ie. it may wait for a short time to accumulate
      * multiple list change notifications into a single event.
      *
+     * This callback is only for notifying about insertions and deletions,
+     * not about metadata changes.
+     *
      * It may be triggered either by an explicitly issued background scan,
      * or a scan issued by the device internally.
      *
      * Client may retrieve the actual list with ITuner::getProgramList.
      */
     oneway programListChanged();
+
+    /**
+     * Method called by the HAL when current program information (including
+     * metadata) is updated.
+     *
+     * Client may retrieve the actual program info with
+     * ITuner::getProgramInformation_1_1.
+     *
+     * This may be called together with tuneComplete_1_1 or afSwitch_1_1.
+     *
+     * This callback supersedes V1_0::newMetadata and V1_0::afSwitch;
+     * partly V1_0::tuneComplete.
+     * 1.0 callbacks must not be called when HAL implementation detects
+     * 1.1 client (by casting V1_0::ITunerCallback to V1_1::ITunerCallback).
+     *
+     * @param info current program information
+     */
+    oneway currentProgramInfoChanged(ProgramInfo info);
 };
diff --git a/broadcastradio/1.1/WARNING b/broadcastradio/1.1/WARNING
deleted file mode 100644 (file)
index e867cfa..0000000
+++ /dev/null
@@ -1 +0,0 @@
-This is experimental interface, do not use it yet.
index 759eb09..6d26b11 100644 (file)
@@ -14,8 +14,9 @@
 // limitations under the License.
 //
 
-cc_library_shared {
-    name: "android.hardware.broadcastradio@1.1-impl",
+cc_binary {
+    name: "android.hardware.broadcastradio@1.1-service",
+    init_rc: ["android.hardware.broadcastradio@1.1-service.rc"],
     vendor: true,
     relative_install_path: "hw",
     cflags: [
@@ -27,16 +28,20 @@ cc_library_shared {
         "BroadcastRadio.cpp",
         "BroadcastRadioFactory.cpp",
         "Tuner.cpp",
-        "Utils.cpp",
+        "VirtualProgram.cpp",
+        "VirtualRadio.cpp",
+        "service.cpp"
+    ],
+    static_libs: [
+        "android.hardware.broadcastradio@1.1-utils-lib",
     ],
     shared_libs: [
+        "android.hardware.broadcastradio@1.0",
+        "android.hardware.broadcastradio@1.1",
+        "libbase",
         "libhidlbase",
         "libhidltransport",
-        "libutils",
         "liblog",
-        "libhardware",
-        "android.hardware.broadcastradio@1.0",
-        "android.hardware.broadcastradio@1.1",
-        "libradio_metadata",
+        "libutils",
     ],
 }
index 68c9b93..1bcfd82 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#define LOG_TAG "BroadcastRadio"
-//#define LOG_NDEBUG 0
+#define LOG_TAG "BroadcastRadioDefault.module"
+#define LOG_NDEBUG 0
+
+#include "BroadcastRadio.h"
 
 #include <log/log.h>
 
-#include "BroadcastRadio.h"
-#include "Tuner.h"
-#include "Utils.h"
+#include "resources.h"
 
 namespace android {
 namespace hardware {
@@ -28,117 +28,163 @@ namespace broadcastradio {
 namespace V1_1 {
 namespace implementation {
 
-using ::android::sp;
+using V1_0::Band;
+using V1_0::BandConfig;
+using V1_0::Class;
+using V1_0::Deemphasis;
+using V1_0::Rds;
+
+using std::lock_guard;
+using std::map;
+using std::mutex;
+using std::vector;
+
+// clang-format off
+static const map<Class, ModuleConfig> gModuleConfigs{
+    {Class::AM_FM, ModuleConfig({
+        "Digital radio mock",
+        {  // amFmBands
+            AmFmBandConfig({
+                Band::AM,
+                153,         // lowerLimit
+                26100,       // upperLimit
+                {5, 9, 10},  // spacings
+            }),
+            AmFmBandConfig({
+                Band::FM,
+                65800,           // lowerLimit
+                108000,          // upperLimit
+                {10, 100, 200},  // spacings
+            }),
+            AmFmBandConfig({
+                Band::AM_HD,
+                153,         // lowerLimit
+                26100,       // upperLimit
+                {5, 9, 10},  // spacings
+            }),
+            AmFmBandConfig({
+                Band::FM_HD,
+                87700,   // lowerLimit
+                107900,  // upperLimit
+                {200},   // spacings
+            }),
+        },
+    })},
+
+    {Class::SAT, ModuleConfig({
+        "Satellite radio mock",
+        {},  // amFmBands
+    })},
+};
+// clang-format on
 
 BroadcastRadio::BroadcastRadio(Class classId)
-        : mStatus(Result::NOT_INITIALIZED), mClassId(classId), mHwDevice(NULL)
-{
+    : mClassId(classId), mConfig(gModuleConfigs.at(classId)) {}
+
+bool BroadcastRadio::isSupported(Class classId) {
+    return gModuleConfigs.find(classId) != gModuleConfigs.end();
 }
 
-BroadcastRadio::~BroadcastRadio()
-{
-    if (mHwDevice != NULL) {
-        radio_hw_device_close(mHwDevice);
-    }
+Return<void> BroadcastRadio::getProperties(getProperties_cb _hidl_cb) {
+    ALOGV("%s", __func__);
+    return getProperties_1_1(
+        [&](const Properties& properties) { _hidl_cb(Result::OK, properties.base); });
 }
 
-void BroadcastRadio::onFirstRef()
-{
-    const hw_module_t *mod;
-    int rc;
-    ALOGI("%s mClassId %d", __FUNCTION__, mClassId);
-
-    mHwDevice = NULL;
-    const char *classString = Utils::getClassString(mClassId);
-    if (classString == NULL) {
-        ALOGE("invalid class ID %d", mClassId);
-        mStatus = Result::INVALID_ARGUMENTS;
-        return;
+Return<void> BroadcastRadio::getProperties_1_1(getProperties_1_1_cb _hidl_cb) {
+    ALOGV("%s", __func__);
+    Properties prop11 = {};
+    auto& prop10 = prop11.base;
+
+    prop10.classId = mClassId;
+    prop10.implementor = "Google";
+    prop10.product = mConfig.productName;
+    prop10.numTuners = 1;
+    prop10.numAudioSources = 1;
+    prop10.supportsCapture = false;
+    prop11.supportsBackgroundScanning = false;
+    prop11.supportedProgramTypes = hidl_vec<uint32_t>({
+        static_cast<uint32_t>(ProgramType::AM), static_cast<uint32_t>(ProgramType::FM),
+        static_cast<uint32_t>(ProgramType::AM_HD), static_cast<uint32_t>(ProgramType::FM_HD),
+    });
+    prop11.supportedIdentifierTypes = hidl_vec<uint32_t>({
+        static_cast<uint32_t>(IdentifierType::AMFM_FREQUENCY),
+        static_cast<uint32_t>(IdentifierType::RDS_PI),
+        static_cast<uint32_t>(IdentifierType::HD_STATION_ID_EXT),
+        static_cast<uint32_t>(IdentifierType::HD_SUBCHANNEL),
+    });
+    prop11.vendorInfo = hidl_vec<VendorKeyValue>({
+        {"com.google.dummy", "dummy"},
+    });
+
+    prop10.bands.resize(mConfig.amFmBands.size());
+    for (size_t i = 0; i < mConfig.amFmBands.size(); i++) {
+        auto& src = mConfig.amFmBands[i];
+        auto& dst = prop10.bands[i];
+
+        dst.type = src.type;
+        dst.antennaConnected = true;
+        dst.lowerLimit = src.lowerLimit;
+        dst.upperLimit = src.upperLimit;
+        dst.spacings = src.spacings;
+
+        if (utils::isAm(src.type)) {
+            dst.ext.am.stereo = true;
+        } else if (utils::isFm(src.type)) {
+            dst.ext.fm.deemphasis = static_cast<Deemphasis>(Deemphasis::D50 | Deemphasis::D75);
+            dst.ext.fm.stereo = true;
+            dst.ext.fm.rds = static_cast<Rds>(Rds::WORLD | Rds::US);
+            dst.ext.fm.ta = true;
+            dst.ext.fm.af = true;
+            dst.ext.fm.ea = true;
+        }
     }
 
-    ALOGI("%s RADIO_HARDWARE_MODULE_ID %s %s",
-            __FUNCTION__, RADIO_HARDWARE_MODULE_ID, classString);
-
-    rc = hw_get_module_by_class(RADIO_HARDWARE_MODULE_ID, classString, &mod);
-    if (rc != 0) {
-        ALOGE("couldn't load radio module %s.%s (%s)",
-                RADIO_HARDWARE_MODULE_ID, classString, strerror(-rc));
-        return;
-    }
-    rc = radio_hw_device_open(mod, &mHwDevice);
-    if (rc != 0) {
-        ALOGE("couldn't open radio hw device in %s.%s (%s)",
-                RADIO_HARDWARE_MODULE_ID, "primary", strerror(-rc));
-        mHwDevice = NULL;
-        return;
-    }
-    if (mHwDevice->common.version != RADIO_DEVICE_API_VERSION_CURRENT) {
-        ALOGE("wrong radio hw device version %04x", mHwDevice->common.version);
-        radio_hw_device_close(mHwDevice);
-        mHwDevice = NULL;
-    } else {
-        mStatus = Result::OK;
-    }
+    _hidl_cb(prop11);
+    return Void();
 }
 
-int BroadcastRadio::closeHalTuner(const struct radio_tuner *halTuner)
-{
-    ALOGV("%s", __FUNCTION__);
-    if (mHwDevice == NULL) {
-        return -ENODEV;
+Return<void> BroadcastRadio::openTuner(const BandConfig& config, bool audio __unused,
+                                       const sp<V1_0::ITunerCallback>& callback,
+                                       openTuner_cb _hidl_cb) {
+    ALOGV("%s(%s)", __func__, toString(config.type).c_str());
+    lock_guard<mutex> lk(mMut);
+
+    auto oldTuner = mTuner.promote();
+    if (oldTuner != nullptr) {
+        ALOGI("Force-closing previously opened tuner");
+        oldTuner->forceClose();
+        mTuner = nullptr;
     }
-    if (halTuner == 0) {
-        return -EINVAL;
-    }
-    return mHwDevice->close_tuner(mHwDevice, halTuner);
-}
 
-
-// Methods from ::android::hardware::broadcastradio::V1_1::IBroadcastRadio follow.
-Return<void> BroadcastRadio::getProperties(getProperties_cb _hidl_cb)
-{
-    int rc;
-    radio_hal_properties_t halProperties;
-    Properties properties;
-
-    if (mHwDevice == NULL) {
-        rc = -ENODEV;
-        goto exit;
-    }
-    rc = mHwDevice->get_properties(mHwDevice, &halProperties);
-    if (rc == 0) {
-        Utils::convertPropertiesFromHal(&properties, &halProperties);
+    sp<Tuner> newTuner = new Tuner(mClassId, callback);
+    mTuner = newTuner;
+    if (mClassId == Class::AM_FM) {
+        auto ret = newTuner->setConfiguration(config);
+        if (ret != Result::OK) {
+            _hidl_cb(Result::INVALID_ARGUMENTS, {});
+            return Void();
+        }
     }
 
-exit:
-    _hidl_cb(Utils::convertHalResult(rc), properties);
+    _hidl_cb(Result::OK, newTuner);
     return Void();
 }
 
-Return<void> BroadcastRadio::getProperties_1_1(getProperties_1_1_cb _hidl_cb __unused)
-{
-    return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION);
-}
+Return<void> BroadcastRadio::getImage(int32_t id, getImage_cb _hidl_cb) {
+    ALOGV("%s(%x)", __func__, id);
 
-Return<void> BroadcastRadio::openTuner(const BandConfig& config, bool audio,
-    const sp<V1_0::ITunerCallback>& callback, openTuner_cb _hidl_cb)
-{
-    sp<Tuner> tunerImpl = new Tuner(callback, this);
-
-    radio_hal_band_config_t halConfig;
-    const struct radio_tuner *halTuner;
-    Utils::convertBandConfigToHal(&halConfig, &config);
-    int rc = mHwDevice->open_tuner(mHwDevice, &halConfig, audio, Tuner::callback,
-            tunerImpl.get(), &halTuner);
-    if (rc == 0) {
-        tunerImpl->setHalTuner(halTuner);
+    if (id == resources::demoPngId) {
+        _hidl_cb(std::vector<uint8_t>(resources::demoPng, std::end(resources::demoPng)));
+        return {};
     }
 
-    _hidl_cb(Utils::convertHalResult(rc), tunerImpl);
+    ALOGI("Image %x doesn't exists", id);
+    _hidl_cb({});
     return Void();
 }
 
-} // namespace implementation
+}  // namespace implementation
 }  // namespace V1_1
 }  // namespace broadcastradio
 }  // namespace hardware
index 7de31a0..a96a2ab 100644 (file)
 #ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_BROADCASTRADIO_H
 #define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_BROADCASTRADIO_H
 
+#include "Tuner.h"
+
 #include <android/hardware/broadcastradio/1.1/IBroadcastRadio.h>
 #include <android/hardware/broadcastradio/1.1/types.h>
-#include <hardware/radio.h>
 
 namespace android {
 namespace hardware {
@@ -26,42 +27,49 @@ namespace broadcastradio {
 namespace V1_1 {
 namespace implementation {
 
-using V1_0::Class;
-using V1_0::BandConfig;
-using V1_0::Properties;
+struct AmFmBandConfig {
+    V1_0::Band type;
+    uint32_t lowerLimit;  // kHz
+    uint32_t upperLimit;  // kHz
+    std::vector<uint32_t> spacings;  // kHz
+};
+
+struct ModuleConfig {
+    std::string productName;
+    std::vector<AmFmBandConfig> amFmBands;
+};
 
 struct BroadcastRadio : public V1_1::IBroadcastRadio {
+    /**
+     * Constructs new broadcast radio module.
+     *
+     * Before calling a constructor with a given classId, it must be checked with isSupported
+     * method first. Otherwise it results in undefined behaviour.
+     *
+     * @param classId type of a radio.
+     */
+    BroadcastRadio(V1_0::Class classId);
 
-    BroadcastRadio(Class classId);
+    /**
+     * Checks, if a given radio type is supported.
+     *
+     * @param classId type of a radio.
+     */
+    static bool isSupported(V1_0::Class classId);
 
-    // Methods from ::android::hardware::broadcastradio::V1_1::IBroadcastRadio follow.
+    // V1_1::IBroadcastRadio methods
     Return<void> getProperties(getProperties_cb _hidl_cb) override;
     Return<void> getProperties_1_1(getProperties_1_1_cb _hidl_cb) override;
-    Return<void> openTuner(const BandConfig& config, bool audio,
-            const sp<V1_0::ITunerCallback>& callback, openTuner_cb _hidl_cb) override;
-
-    // RefBase
-    virtual void onFirstRef() override;
-
-    Result initCheck() { return mStatus; }
-    int closeHalTuner(const struct radio_tuner *halTuner);
-
-private:
-    virtual ~BroadcastRadio();
-
-    static const char * sClassModuleNames[];
-
-    Result convertHalResult(int rc);
-    void convertBandConfigFromHal(BandConfig *config,
-            const radio_hal_band_config_t *halConfig);
-    void convertPropertiesFromHal(Properties *properties,
-            const radio_hal_properties_t *halProperties);
-    void convertBandConfigToHal(radio_hal_band_config_t *halConfig,
-            const BandConfig *config);
+    Return<void> openTuner(const V1_0::BandConfig& config, bool audio,
+                           const sp<V1_0::ITunerCallback>& callback,
+                           openTuner_cb _hidl_cb) override;
+    Return<void> getImage(int32_t id, getImage_cb _hidl_cb);
 
-    Result mStatus;
-    Class mClassId;
-    struct radio_hw_device *mHwDevice;
+   private:
+    std::mutex mMut;
+    V1_0::Class mClassId;
+    ModuleConfig mConfig;
+    wp<Tuner> mTuner;
 };
 
 }  // namespace implementation
index c8b6c39..f57bc79 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#define LOG_TAG "BroadcastRadioDefault.factory"
+#define LOG_NDEBUG 0
+
 #include "BroadcastRadioFactory.h"
+
 #include "BroadcastRadio.h"
 
+#include <log/log.h>
+
 namespace android {
 namespace hardware {
 namespace broadcastradio {
 namespace V1_1 {
 namespace implementation {
 
-// Methods from ::android::hardware::broadcastradio::V1_0::IBroadcastRadioFactory follow.
-Return<void> BroadcastRadioFactory::connectModule(Class classId, connectModule_cb _hidl_cb)  {
-    sp<BroadcastRadio> impl = new BroadcastRadio(classId);
-    Result retval = Result::NOT_INITIALIZED;
-    if (impl != 0) {
-        retval = impl->initCheck();
+using V1_0::Class;
+
+using std::vector;
+
+static const vector<Class> gAllClasses = {
+    Class::AM_FM, Class::SAT, Class::DT,
+};
+
+IBroadcastRadioFactory* HIDL_FETCH_IBroadcastRadioFactory(const char* name __unused) {
+    return new BroadcastRadioFactory();
+}
+
+BroadcastRadioFactory::BroadcastRadioFactory() {
+    for (auto&& classId : gAllClasses) {
+        if (!BroadcastRadio::isSupported(classId)) continue;
+        mRadioModules[classId] = new BroadcastRadio(classId);
     }
-    _hidl_cb(retval, impl);
-    return Void();
 }
 
+Return<void> BroadcastRadioFactory::connectModule(Class classId, connectModule_cb _hidl_cb) {
+    ALOGV("%s(%s)", __func__, toString(classId).c_str());
 
-IBroadcastRadioFactory* HIDL_FETCH_IBroadcastRadioFactory(const char* /* name */) {
-    return new BroadcastRadioFactory();
+    auto moduleIt = mRadioModules.find(classId);
+    if (moduleIt == mRadioModules.end()) {
+        _hidl_cb(Result::INVALID_ARGUMENTS, nullptr);
+    } else {
+        _hidl_cb(Result::OK, moduleIt->second);
+    }
+
+    return Void();
 }
 
 }  // namespace implementation
index 8eb8514..8b67ac3 100644 (file)
@@ -16,6 +16,7 @@
 #ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_BROADCASTRADIOFACTORY_H
 #define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_BROADCASTRADIOFACTORY_H
 
+#include <android/hardware/broadcastradio/1.1/IBroadcastRadio.h>
 #include <android/hardware/broadcastradio/1.1/IBroadcastRadioFactory.h>
 #include <android/hardware/broadcastradio/1.1/types.h>
 
@@ -25,14 +26,17 @@ namespace broadcastradio {
 namespace V1_1 {
 namespace implementation {
 
-using V1_0::Class;
+extern "C" IBroadcastRadioFactory* HIDL_FETCH_IBroadcastRadioFactory(const char* name);
 
 struct BroadcastRadioFactory : public IBroadcastRadioFactory {
-    // Methods from ::android::hardware::broadcastradio::V1_0::IBroadcastRadioFactory follow.
-    Return<void> connectModule(Class classId, connectModule_cb _hidl_cb) override;
-};
+    BroadcastRadioFactory();
 
-extern "C" IBroadcastRadioFactory* HIDL_FETCH_IBroadcastRadioFactory(const char* name);
+    // V1_0::IBroadcastRadioFactory methods
+    Return<void> connectModule(V1_0::Class classId, connectModule_cb _hidl_cb) override;
+
+   private:
+    std::map<V1_0::Class, sp<IBroadcastRadio>> mRadioModules;
+};
 
 }  // namespace implementation
 }  // namespace V1_1
diff --git a/broadcastradio/1.1/default/OWNERS b/broadcastradio/1.1/default/OWNERS
new file mode 100644 (file)
index 0000000..0c27b71
--- /dev/null
@@ -0,0 +1,4 @@
+# Automotive team
+egranata@google.com
+keunyoung@google.com
+twasilczyk@google.com
index ae5848c..9a34cb1 100644 (file)
  * limitations under the License.
  */
 
-#define LOG_TAG "Tuner"
-//#define LOG_NDEBUG 0
-
-#include <log/log.h>
+#define LOG_TAG "BroadcastRadioDefault.tuner"
+#define LOG_NDEBUG 0
 
 #include "BroadcastRadio.h"
 #include "Tuner.h"
-#include "Utils.h"
-#include <system/RadioMetadataWrapper.h>
+
+#include <broadcastradio-utils/Utils.h>
+#include <log/log.h>
 
 namespace android {
 namespace hardware {
@@ -30,199 +29,351 @@ namespace broadcastradio {
 namespace V1_1 {
 namespace implementation {
 
-void Tuner::onCallback(radio_hal_event_t *halEvent)
-{
-    BandConfig config;
-    ProgramInfo info;
-    hidl_vec<MetaData> metadata;
-
-    if (mCallback != 0) {
-        switch(halEvent->type) {
-        case RADIO_EVENT_CONFIG:
-            Utils::convertBandConfigFromHal(&config, &halEvent->config);
-            mCallback->configChange(Utils::convertHalResult(halEvent->status), config);
-            break;
-        case RADIO_EVENT_ANTENNA:
-            mCallback->antennaStateChange(halEvent->on);
-            break;
-        case RADIO_EVENT_TUNED:
-            Utils::convertProgramInfoFromHal(&info, &halEvent->info);
-            if (mCallback1_1 != nullptr) {
-                mCallback1_1->tuneComplete_1_1(Utils::convertHalResult(halEvent->status), info);
-            }
-            mCallback->tuneComplete(Utils::convertHalResult(halEvent->status), info.base);
-            break;
-        case RADIO_EVENT_METADATA: {
-            uint32_t channel;
-            uint32_t sub_channel;
-            if (radio_metadata_get_channel(halEvent->metadata, &channel, &sub_channel) == 0) {
-                Utils::convertMetaDataFromHal(metadata, halEvent->metadata);
-                mCallback->newMetadata(channel, sub_channel, metadata);
-            }
-            } break;
-        case RADIO_EVENT_TA:
-            mCallback->trafficAnnouncement(halEvent->on);
-            break;
-        case RADIO_EVENT_AF_SWITCH:
-            Utils::convertProgramInfoFromHal(&info, &halEvent->info);
-            if (mCallback1_1 != nullptr) {
-                mCallback1_1->afSwitch_1_1(info);
-            }
-            mCallback->afSwitch(info.base);
-            break;
-        case RADIO_EVENT_EA:
-            mCallback->emergencyAnnouncement(halEvent->on);
-            break;
-        case RADIO_EVENT_HW_FAILURE:
-        default:
-            mCallback->hardwareFailure();
-            break;
+using namespace std::chrono_literals;
+
+using V1_0::Band;
+using V1_0::BandConfig;
+using V1_0::Class;
+using V1_0::Direction;
+using utils::HalRevision;
+
+using std::chrono::milliseconds;
+using std::lock_guard;
+using std::move;
+using std::mutex;
+using std::sort;
+using std::vector;
+
+const struct {
+    milliseconds config = 50ms;
+    milliseconds scan = 200ms;
+    milliseconds step = 100ms;
+    milliseconds tune = 150ms;
+} gDefaultDelay;
+
+Tuner::Tuner(V1_0::Class classId, const sp<V1_0::ITunerCallback>& callback)
+    : mClassId(classId),
+      mCallback(callback),
+      mCallback1_1(ITunerCallback::castFrom(callback).withDefault(nullptr)),
+      mVirtualRadio(getRadio(classId)),
+      mIsAnalogForced(false) {}
+
+void Tuner::forceClose() {
+    lock_guard<mutex> lk(mMut);
+    mIsClosed = true;
+    mThread.cancelAll();
+}
+
+Return<Result> Tuner::setConfiguration(const BandConfig& config) {
+    ALOGV("%s", __func__);
+    lock_guard<mutex> lk(mMut);
+    if (mIsClosed) return Result::NOT_INITIALIZED;
+    if (mClassId != Class::AM_FM) {
+        ALOGE("Can't set AM/FM configuration on SAT/DT radio tuner");
+        return Result::INVALID_STATE;
+    }
+
+    if (config.lowerLimit >= config.upperLimit) return Result::INVALID_ARGUMENTS;
+
+    auto task = [this, config]() {
+        ALOGI("Setting AM/FM config");
+        lock_guard<mutex> lk(mMut);
+
+        mAmfmConfig = move(config);
+        mAmfmConfig.antennaConnected = true;
+        mCurrentProgram = utils::make_selector(mAmfmConfig.type, mAmfmConfig.lowerLimit);
+
+        if (utils::isFm(mAmfmConfig.type)) {
+            mVirtualRadio = std::ref(getFmRadio());
+        } else {
+            mVirtualRadio = std::ref(getAmRadio());
         }
+
+        mIsAmfmConfigSet = true;
+        mCallback->configChange(Result::OK, mAmfmConfig);
+    };
+    mThread.schedule(task, gDefaultDelay.config);
+
+    return Result::OK;
+}
+
+Return<void> Tuner::getConfiguration(getConfiguration_cb _hidl_cb) {
+    ALOGV("%s", __func__);
+    lock_guard<mutex> lk(mMut);
+
+    if (!mIsClosed && mIsAmfmConfigSet) {
+        _hidl_cb(Result::OK, mAmfmConfig);
+    } else {
+        _hidl_cb(Result::NOT_INITIALIZED, {});
     }
+    return {};
 }
 
-//static
-void Tuner::callback(radio_hal_event_t *halEvent, void *cookie)
-{
-    wp<Tuner> weak(reinterpret_cast<Tuner*>(cookie));
-    sp<Tuner> tuner = weak.promote();
-    if (tuner == 0) return;
-    tuner->onCallback(halEvent);
+// makes ProgramInfo that points to no program
+static ProgramInfo makeDummyProgramInfo(const ProgramSelector& selector) {
+    ProgramInfo info11 = {};
+    auto& info10 = info11.base;
+
+    utils::getLegacyChannel(selector, &info10.channel, &info10.subChannel);
+    info11.selector = selector;
+    info11.flags |= ProgramInfoFlags::MUTED;
+
+    return info11;
 }
 
-Tuner::Tuner(const sp<V1_0::ITunerCallback>& callback, const wp<BroadcastRadio>& parentDevice)
-        : mHalTuner(NULL), mCallback(callback), mCallback1_1(ITunerCallback::castFrom(callback)),
-        mParentDevice(parentDevice)
-{
-    ALOGV("%s", __FUNCTION__);
+HalRevision Tuner::getHalRev() const {
+    if (mCallback1_1 != nullptr) {
+        return HalRevision::V1_1;
+    } else {
+        return HalRevision::V1_0;
+    }
 }
 
+void Tuner::tuneInternalLocked(const ProgramSelector& sel) {
+    VirtualProgram virtualProgram;
+    if (mVirtualRadio.get().getProgram(sel, virtualProgram)) {
+        mCurrentProgram = virtualProgram.selector;
+        mCurrentProgramInfo = virtualProgram.getProgramInfo(getHalRev());
+    } else {
+        mCurrentProgram = sel;
+        mCurrentProgramInfo = makeDummyProgramInfo(sel);
+    }
+    mIsTuneCompleted = true;
 
-Tuner::~Tuner()
-{
-    ALOGV("%s", __FUNCTION__);
-    const sp<BroadcastRadio> parentDevice = mParentDevice.promote();
-    if (parentDevice != 0) {
-        parentDevice->closeHalTuner(mHalTuner);
+    if (mCallback1_1 == nullptr) {
+        mCallback->tuneComplete(Result::OK, mCurrentProgramInfo.base);
+    } else {
+        mCallback1_1->tuneComplete_1_1(Result::OK, mCurrentProgramInfo.selector);
+        mCallback1_1->currentProgramInfoChanged(mCurrentProgramInfo);
     }
 }
 
-// Methods from ::android::hardware::broadcastradio::V1_1::ITuner follow.
-Return<Result> Tuner::setConfiguration(const BandConfig& config)  {
-    ALOGV("%s", __FUNCTION__);
-    if (mHalTuner == NULL) {
-        return Utils::convertHalResult(-ENODEV);
+Return<Result> Tuner::scan(Direction direction, bool skipSubChannel __unused) {
+    ALOGV("%s", __func__);
+    lock_guard<mutex> lk(mMut);
+    if (mIsClosed) return Result::NOT_INITIALIZED;
+
+    auto list = mVirtualRadio.get().getProgramList();
+
+    if (list.empty()) {
+        mIsTuneCompleted = false;
+        auto task = [this, direction]() {
+            ALOGI("Performing failed scan %s", toString(direction).c_str());
+
+            if (mCallback1_1 == nullptr) {
+                mCallback->tuneComplete(Result::TIMEOUT, {});
+            } else {
+                mCallback1_1->tuneComplete_1_1(Result::TIMEOUT, {});
+            }
+        };
+        mThread.schedule(task, gDefaultDelay.scan);
+
+        return Result::OK;
+    }
+
+    // Not optimal (O(sort) instead of O(n)), but not a big deal here;
+    // also, it's likely that list is already sorted (so O(n) anyway).
+    sort(list.begin(), list.end());
+    auto current = mCurrentProgram;
+    auto found = lower_bound(list.begin(), list.end(), VirtualProgram({current}));
+    if (direction == Direction::UP) {
+        if (found < list.end() - 1) {
+            if (utils::tunesTo(current, found->selector)) found++;
+        } else {
+            found = list.begin();
+        }
+    } else {
+        if (found > list.begin() && found != list.end()) {
+            found--;
+        } else {
+            found = list.end() - 1;
+        }
     }
-    radio_hal_band_config_t halConfig;
-    Utils::convertBandConfigToHal(&halConfig, &config);
-    int rc = mHalTuner->set_configuration(mHalTuner, &halConfig);
-    return Utils::convertHalResult(rc);
+    auto tuneTo = found->selector;
+
+    mIsTuneCompleted = false;
+    auto task = [this, tuneTo, direction]() {
+        ALOGI("Performing scan %s", toString(direction).c_str());
+
+        lock_guard<mutex> lk(mMut);
+        tuneInternalLocked(tuneTo);
+    };
+    mThread.schedule(task, gDefaultDelay.scan);
+
+    return Result::OK;
 }
 
-Return<void> Tuner::getConfiguration(getConfiguration_cb _hidl_cb)  {
-    int rc;
-    radio_hal_band_config_t halConfig;
-    BandConfig config;
+Return<Result> Tuner::step(Direction direction, bool skipSubChannel) {
+    ALOGV("%s", __func__);
+    lock_guard<mutex> lk(mMut);
+    if (mIsClosed) return Result::NOT_INITIALIZED;
 
-    ALOGV("%s", __FUNCTION__);
-    if (mHalTuner == NULL) {
-        rc = -ENODEV;
-        goto exit;
+    ALOGW_IF(!skipSubChannel, "can't step to next frequency without ignoring subChannel");
+
+    if (!utils::isAmFm(utils::getType(mCurrentProgram))) {
+        ALOGE("Can't step in anything else than AM/FM");
+        return Result::NOT_INITIALIZED;
     }
-    rc = mHalTuner->get_configuration(mHalTuner, &halConfig);
-    if (rc == 0) {
-        Utils::convertBandConfigFromHal(&config, &halConfig);
+
+    if (!mIsAmfmConfigSet) {
+        ALOGW("AM/FM config not set");
+        return Result::INVALID_STATE;
     }
+    mIsTuneCompleted = false;
+
+    auto task = [this, direction]() {
+        ALOGI("Performing step %s", toString(direction).c_str());
+
+        lock_guard<mutex> lk(mMut);
 
-exit:
-    _hidl_cb(Utils::convertHalResult(rc), config);
-    return Void();
+        auto current = utils::getId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY, 0);
+
+        if (direction == Direction::UP) {
+            current += mAmfmConfig.spacings[0];
+        } else {
+            current -= mAmfmConfig.spacings[0];
+        }
+
+        if (current > mAmfmConfig.upperLimit) current = mAmfmConfig.lowerLimit;
+        if (current < mAmfmConfig.lowerLimit) current = mAmfmConfig.upperLimit;
+
+        tuneInternalLocked(utils::make_selector(mAmfmConfig.type, current));
+    };
+    mThread.schedule(task, gDefaultDelay.step);
+
+    return Result::OK;
 }
 
-Return<Result> Tuner::scan(Direction direction, bool skipSubChannel)  {
-    if (mHalTuner == NULL) {
-        return Utils::convertHalResult(-ENODEV);
+Return<Result> Tuner::tune(uint32_t channel, uint32_t subChannel) {
+    ALOGV("%s(%d, %d)", __func__, channel, subChannel);
+    Band band;
+    {
+        lock_guard<mutex> lk(mMut);
+        band = mAmfmConfig.type;
     }
-    int rc = mHalTuner->scan(mHalTuner, static_cast<radio_direction_t>(direction), skipSubChannel);
-    return Utils::convertHalResult(rc);
+    return tuneByProgramSelector(utils::make_selector(band, channel, subChannel));
 }
 
-Return<Result> Tuner::step(Direction direction, bool skipSubChannel)  {
-    if (mHalTuner == NULL) {
-        return Utils::convertHalResult(-ENODEV);
+Return<Result> Tuner::tuneByProgramSelector(const ProgramSelector& sel) {
+    ALOGV("%s(%s)", __func__, toString(sel).c_str());
+    lock_guard<mutex> lk(mMut);
+    if (mIsClosed) return Result::NOT_INITIALIZED;
+
+    // checking if ProgramSelector is valid
+    auto programType = utils::getType(sel);
+    if (utils::isAmFm(programType)) {
+        if (!mIsAmfmConfigSet) {
+            ALOGW("AM/FM config not set");
+            return Result::INVALID_STATE;
+        }
+
+        auto freq = utils::getId(sel, IdentifierType::AMFM_FREQUENCY);
+        if (freq < mAmfmConfig.lowerLimit || freq > mAmfmConfig.upperLimit) {
+            return Result::INVALID_ARGUMENTS;
+        }
+    } else if (programType == ProgramType::DAB) {
+        if (!utils::hasId(sel, IdentifierType::DAB_SIDECC)) return Result::INVALID_ARGUMENTS;
+    } else if (programType == ProgramType::DRMO) {
+        if (!utils::hasId(sel, IdentifierType::DRMO_SERVICE_ID)) return Result::INVALID_ARGUMENTS;
+    } else if (programType == ProgramType::SXM) {
+        if (!utils::hasId(sel, IdentifierType::SXM_SERVICE_ID)) return Result::INVALID_ARGUMENTS;
+    } else {
+        return Result::INVALID_ARGUMENTS;
     }
-    int rc = mHalTuner->step(mHalTuner, static_cast<radio_direction_t>(direction), skipSubChannel);
-    return Utils::convertHalResult(rc);
+
+    mIsTuneCompleted = false;
+    auto task = [this, sel]() {
+        lock_guard<mutex> lk(mMut);
+        tuneInternalLocked(sel);
+    };
+    mThread.schedule(task, gDefaultDelay.tune);
+
+    return Result::OK;
 }
 
-Return<Result> Tuner::tune(uint32_t channel, uint32_t subChannel)  {
-    if (mHalTuner == NULL) {
-        return Utils::convertHalResult(-ENODEV);
-    }
-    int rc = mHalTuner->tune(mHalTuner, channel, subChannel);
-    return Utils::convertHalResult(rc);
+Return<Result> Tuner::cancel() {
+    ALOGV("%s", __func__);
+    lock_guard<mutex> lk(mMut);
+    if (mIsClosed) return Result::NOT_INITIALIZED;
+
+    mThread.cancelAll();
+    return Result::OK;
 }
 
-Return<Result> Tuner::cancel()  {
-    if (mHalTuner == NULL) {
-        return Utils::convertHalResult(-ENODEV);
-    }
-    int rc = mHalTuner->cancel(mHalTuner);
-    return Utils::convertHalResult(rc);
+Return<Result> Tuner::cancelAnnouncement() {
+    ALOGV("%s", __func__);
+    lock_guard<mutex> lk(mMut);
+    if (mIsClosed) return Result::NOT_INITIALIZED;
+
+    return Result::OK;
 }
 
-Return<void> Tuner::getProgramInformation(getProgramInformation_cb _hidl_cb)  {
-    ALOGV("%s", __FUNCTION__);
+Return<void> Tuner::getProgramInformation(getProgramInformation_cb _hidl_cb) {
+    ALOGV("%s", __func__);
     return getProgramInformation_1_1([&](Result result, const ProgramInfo& info) {
         _hidl_cb(result, info.base);
     });
 }
 
-Return<void> Tuner::getProgramInformation_1_1(getProgramInformation_1_1_cb _hidl_cb)  {
-    int rc;
-    radio_program_info_t halInfo;
-    RadioMetadataWrapper metadataWrapper(&halInfo.metadata);
-    ProgramInfo info;
-
-    ALOGV("%s", __FUNCTION__);
-    if (mHalTuner == NULL) {
-        rc = -ENODEV;
-        goto exit;
-    }
+Return<void> Tuner::getProgramInformation_1_1(getProgramInformation_1_1_cb _hidl_cb) {
+    ALOGV("%s", __func__);
+    lock_guard<mutex> lk(mMut);
 
-    rc = mHalTuner->get_program_information(mHalTuner, &halInfo);
-    if (rc == 0) {
-        Utils::convertProgramInfoFromHal(&info, &halInfo);
+    if (mIsClosed) {
+        _hidl_cb(Result::NOT_INITIALIZED, {});
+    } else if (mIsTuneCompleted) {
+        _hidl_cb(Result::OK, mCurrentProgramInfo);
+    } else {
+        _hidl_cb(Result::NOT_INITIALIZED, makeDummyProgramInfo(mCurrentProgram));
     }
-
-exit:
-    _hidl_cb(Utils::convertHalResult(rc), info);
-    return Void();
+    return {};
 }
 
 Return<ProgramListResult> Tuner::startBackgroundScan() {
+    ALOGV("%s", __func__);
+    lock_guard<mutex> lk(mMut);
+    if (mIsClosed) return ProgramListResult::NOT_INITIALIZED;
+
     return ProgramListResult::UNAVAILABLE;
 }
 
-Return<void> Tuner::getProgramList(const hidl_string& filter __unused, getProgramList_cb _hidl_cb) {
-    hidl_vec<ProgramInfo> pList;
-    // TODO(b/34054813): do the actual implementation.
-    _hidl_cb(ProgramListResult::NOT_STARTED, pList);
-    return Void();
+Return<void> Tuner::getProgramList(const hidl_vec<VendorKeyValue>& vendorFilter,
+                                   getProgramList_cb _hidl_cb) {
+    ALOGV("%s(%s)", __func__, toString(vendorFilter).substr(0, 100).c_str());
+    lock_guard<mutex> lk(mMut);
+    if (mIsClosed) {
+        _hidl_cb(ProgramListResult::NOT_INITIALIZED, {});
+        return {};
+    }
+
+    auto list = mVirtualRadio.get().getProgramList();
+    ALOGD("returning a list of %zu programs", list.size());
+    _hidl_cb(ProgramListResult::OK, getProgramInfoVector(list, getHalRev()));
+    return {};
 }
 
-Return<void> Tuner::isAnalogForced(isAnalogForced_cb _hidl_cb) {
-    // TODO(b/34348946): do the actual implementation.
-    _hidl_cb(Result::INVALID_STATE, false);
-    return Void();
+Return<Result> Tuner::setAnalogForced(bool isForced) {
+    ALOGV("%s", __func__);
+    lock_guard<mutex> lk(mMut);
+    if (mIsClosed) return Result::NOT_INITIALIZED;
+
+    mIsAnalogForced = isForced;
+    return Result::OK;
 }
 
-Return<Result> Tuner::setAnalogForced(bool isForced __unused) {
-    // TODO(b/34348946): do the actual implementation.
-    return Result::INVALID_STATE;
+Return<void> Tuner::isAnalogForced(isAnalogForced_cb _hidl_cb) {
+    ALOGV("%s", __func__);
+    lock_guard<mutex> lk(mMut);
+
+    if (mIsClosed) {
+        _hidl_cb(Result::NOT_INITIALIZED, false);
+    } else {
+        _hidl_cb(Result::OK, mIsAnalogForced);
+    }
+    return {};
 }
 
-} // namespace implementation
+}  // namespace implementation
 }  // namespace V1_1
 }  // namespace broadcastradio
 }  // namespace hardware
index 57eafd3..07d3189 100644 (file)
 #ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_TUNER_H
 #define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_TUNER_H
 
+#include "VirtualRadio.h"
+
 #include <android/hardware/broadcastradio/1.1/ITuner.h>
 #include <android/hardware/broadcastradio/1.1/ITunerCallback.h>
+#include <broadcastradio-utils/WorkerThread.h>
 
 namespace android {
 namespace hardware {
@@ -25,43 +28,48 @@ namespace broadcastradio {
 namespace V1_1 {
 namespace implementation {
 
-using V1_0::Direction;
-
-struct BroadcastRadio;
-
 struct Tuner : public ITuner {
+    Tuner(V1_0::Class classId, const sp<V1_0::ITunerCallback>& callback);
 
-    Tuner(const sp<V1_0::ITunerCallback>& callback, const wp<BroadcastRadio>& mParentDevice);
-
-    // Methods from ::android::hardware::broadcastradio::V1_1::ITuner follow.
-    Return<Result> setConfiguration(const BandConfig& config) override;
-    Return<void> getConfiguration(getConfiguration_cb _hidl_cb) override;
-    Return<Result> scan(Direction direction, bool skipSubChannel) override;
-    Return<Result> step(Direction direction, bool skipSubChannel) override;
-    Return<Result> tune(uint32_t channel, uint32_t subChannel) override;
-    Return<Result> cancel() override;
-    Return<void> getProgramInformation(getProgramInformation_cb _hidl_cb) override;
-    Return<void> getProgramInformation_1_1(getProgramInformation_1_1_cb _hidl_cb) override;
-    Return<ProgramListResult> startBackgroundScan() override;
-    Return<void> getProgramList(const hidl_string& filter, getProgramList_cb _hidl_cb) override;
-    Return<void> isAnalogForced(isAnalogForced_cb _hidl_cb) override;
-    Return<Result> setAnalogForced(bool isForced) override;
+    void forceClose();
 
-    static void callback(radio_hal_event_t *halEvent, void *cookie);
-    void onCallback(radio_hal_event_t *halEvent);
+    // V1_1::ITuner methods
+    virtual Return<Result> setConfiguration(const V1_0::BandConfig& config) override;
+    virtual Return<void> getConfiguration(getConfiguration_cb _hidl_cb) override;
+    virtual Return<Result> scan(V1_0::Direction direction, bool skipSubChannel) override;
+    virtual Return<Result> step(V1_0::Direction direction, bool skipSubChannel) override;
+    virtual Return<Result> tune(uint32_t channel, uint32_t subChannel) override;
+    virtual Return<Result> tuneByProgramSelector(const ProgramSelector& program) override;
+    virtual Return<Result> cancel() override;
+    virtual Return<Result> cancelAnnouncement() override;
+    virtual Return<void> getProgramInformation(getProgramInformation_cb _hidl_cb) override;
+    virtual Return<void> getProgramInformation_1_1(getProgramInformation_1_1_cb _hidl_cb) override;
+    virtual Return<ProgramListResult> startBackgroundScan() override;
+    virtual Return<void> getProgramList(const hidl_vec<VendorKeyValue>& filter,
+                                        getProgramList_cb _hidl_cb) override;
+    virtual Return<Result> setAnalogForced(bool isForced) override;
+    virtual Return<void> isAnalogForced(isAnalogForced_cb _hidl_cb) override;
 
-    void setHalTuner(const struct radio_tuner *halTuner) { mHalTuner = halTuner; }
-    const struct radio_tuner *getHalTuner() { return mHalTuner; }
+   private:
+    std::mutex mMut;
+    WorkerThread mThread;
+    bool mIsClosed = false;
 
-private:
-    ~Tuner();
-
-    const struct radio_tuner *mHalTuner;
+    V1_0::Class mClassId;
     const sp<V1_0::ITunerCallback> mCallback;
     const sp<V1_1::ITunerCallback> mCallback1_1;
-    const wp<BroadcastRadio> mParentDevice;
-};
 
+    std::reference_wrapper<VirtualRadio> mVirtualRadio;
+    bool mIsAmfmConfigSet = false;
+    V1_0::BandConfig mAmfmConfig;
+    bool mIsTuneCompleted = false;
+    ProgramSelector mCurrentProgram = {};
+    ProgramInfo mCurrentProgramInfo = {};
+    std::atomic<bool> mIsAnalogForced;
+
+    utils::HalRevision getHalRev() const;
+    void tuneInternalLocked(const ProgramSelector& sel);
+};
 
 }  // namespace implementation
 }  // namespace V1_1
diff --git a/broadcastradio/1.1/default/Utils.cpp b/broadcastradio/1.1/default/Utils.cpp
deleted file mode 100644 (file)
index e21344e..0000000
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#define LOG_TAG "BroadcastRadioHalUtils"
-//#define LOG_NDEBUG 0
-
-#include <log/log.h>
-#include <system/radio_metadata.h>
-
-#include "Utils.h"
-
-namespace android {
-namespace hardware {
-namespace broadcastradio {
-namespace V1_1 {
-namespace implementation {
-
-using V1_0::Band;
-using V1_0::Deemphasis;
-using V1_0::Direction;
-using V1_0::MetadataKey;
-using V1_0::MetadataType;
-using V1_0::Rds;
-
-const char *Utils::sClassModuleNames[] = {
-    RADIO_HARDWARE_MODULE_ID_FM, /* corresponds to RADIO_CLASS_AM_FM */
-    RADIO_HARDWARE_MODULE_ID_SAT,  /* corresponds to RADIO_CLASS_SAT */
-    RADIO_HARDWARE_MODULE_ID_DT,   /* corresponds to RADIO_CLASS_DT */
-};
-
-// make sure HIDL enum values are aligned with legacy values
-static_assert(RADIO_CLASS_AM_FM == static_cast<int>(Class::AM_FM),
-        "AM/FM class mismatch with legacy");
-static_assert(RADIO_CLASS_SAT == static_cast<int>(Class::SAT),
-        "SAT class mismatch with legacy");
-static_assert(RADIO_CLASS_DT == static_cast<int>(Class::DT),
-        "DT class mismatch with legacy");
-
-static_assert(RADIO_BAND_AM == static_cast<int>(Band::AM),
-        "AM band mismatch with legacy");
-static_assert(RADIO_BAND_FM == static_cast<int>(Band::FM),
-        "FM band mismatch with legacy");
-static_assert(RADIO_BAND_AM_HD == static_cast<int>(Band::AM_HD),
-        "AM HD band mismatch with legacy");
-static_assert(RADIO_BAND_FM_HD == static_cast<int>(Band::FM_HD),
-        "FM HD band mismatch with legacy");
-
-static_assert(RADIO_RDS_NONE == static_cast<int>(Rds::NONE),
-        "RDS NONE mismatch with legacy");
-static_assert(RADIO_RDS_WORLD == static_cast<int>(Rds::WORLD),
-        "RDS WORLD mismatch with legacy");
-static_assert(RADIO_RDS_US == static_cast<int>(Rds::US),
-        "RDS US mismatch with legacy");
-
-static_assert(RADIO_DEEMPHASIS_50 == static_cast<int>(Deemphasis::D50),
-        "De-emphasis 50 mismatch with legacy");
-static_assert(RADIO_DEEMPHASIS_75 == static_cast<int>(Deemphasis::D75),
-        "De-emphasis 75 mismatch with legacy");
-
-static_assert(RADIO_DIRECTION_UP == static_cast<int>(Direction::UP),
-        "Direction Up mismatch with legacy");
-static_assert(RADIO_DIRECTION_DOWN == static_cast<int>(Direction::DOWN),
-        "Direction Up mismatch with legacy");
-
-static_assert(RADIO_METADATA_TYPE_INVALID == static_cast<int>(MetadataType::INVALID),
-        "Metadata type INVALID mismatch with legacy");
-static_assert(RADIO_METADATA_TYPE_INT == static_cast<int>(MetadataType::INT),
-        "Metadata type INT mismatch with legacy");
-static_assert(RADIO_METADATA_TYPE_TEXT == static_cast<int>(MetadataType::TEXT),
-        "Metadata type TEXT mismatch with legacy");
-static_assert(RADIO_METADATA_TYPE_RAW == static_cast<int>(MetadataType::RAW),
-        "Metadata type RAW mismatch with legacy");
-static_assert(RADIO_METADATA_TYPE_CLOCK == static_cast<int>(MetadataType::CLOCK),
-        "Metadata type CLOCK mismatch with legacy");
-
-static_assert(RADIO_METADATA_KEY_INVALID == static_cast<int>(MetadataKey::INVALID),
-        "Metadata key INVALID mismatch with legacy");
-static_assert(RADIO_METADATA_KEY_RDS_PI == static_cast<int>(MetadataKey::RDS_PI),
-        "Metadata key RDS_PI mismatch with legacy");
-static_assert(RADIO_METADATA_KEY_RDS_PS == static_cast<int>(MetadataKey::RDS_PS),
-        "Metadata key RDS_PS mismatch with legacy");
-static_assert(RADIO_METADATA_KEY_RDS_PTY == static_cast<int>(MetadataKey::RDS_PTY),
-        "Metadata key RDS_PTY mismatch with legacy");
-static_assert(RADIO_METADATA_KEY_RBDS_PTY == static_cast<int>(MetadataKey::RBDS_PTY),
-        "Metadata key RBDS_PTY mismatch with legacy");
-static_assert(RADIO_METADATA_KEY_RDS_RT == static_cast<int>(MetadataKey::RDS_RT),
-        "Metadata key RDS_RT mismatch with legacy");
-static_assert(RADIO_METADATA_KEY_TITLE == static_cast<int>(MetadataKey::TITLE),
-        "Metadata key TITLE mismatch with legacy");
-static_assert(RADIO_METADATA_KEY_ARTIST == static_cast<int>(MetadataKey::ARTIST),
-        "Metadata key ARTIST mismatch with legacy");
-static_assert(RADIO_METADATA_KEY_ALBUM == static_cast<int>(MetadataKey::ALBUM),
-        "Metadata key ALBUM mismatch with legacy");
-static_assert(RADIO_METADATA_KEY_GENRE == static_cast<int>(MetadataKey::GENRE),
-        "Metadata key GENRE mismatch with legacy");
-static_assert(RADIO_METADATA_KEY_ICON == static_cast<int>(MetadataKey::ICON),
-        "Metadata key ICON mismatch with legacy");
-static_assert(RADIO_METADATA_KEY_ART == static_cast<int>(MetadataKey::ART),
-        "Metadata key ART mismatch with legacy");
-static_assert(RADIO_METADATA_KEY_CLOCK == static_cast<int>(MetadataKey::CLOCK),
-        "Metadata key CLOCK mismatch with legacy");
-
-
-//static
-const char * Utils::getClassString(Class ClassId)
-{
-    int id = static_cast<int>(ClassId);
-
-    if ((id < 0) ||
-            (id >= NELEM(sClassModuleNames))) {
-        ALOGE("invalid class ID %d", id);
-        return NULL;
-    }
-    return sClassModuleNames[id];
-}
-
-//static
-Result Utils::convertHalResult(int rc)
-{
-    switch (rc) {
-        case 0:
-            return Result::OK;
-        case -EINVAL:
-            return Result::INVALID_ARGUMENTS;
-        case -ENOSYS:
-            return Result::INVALID_STATE;
-        case -ETIMEDOUT:
-            return Result::TIMEOUT;
-        case -ENODEV:
-        default:
-            return Result::NOT_INITIALIZED;
-    }
-}
-
-//static
-void Utils::convertBandConfigFromHal(
-        BandConfig *config,
-        const radio_hal_band_config_t *halConfig)
-{
-
-    config->type = static_cast<Band>(halConfig->type);
-    config->antennaConnected = halConfig->antenna_connected;
-    config->lowerLimit = halConfig->lower_limit;
-    config->upperLimit = halConfig->upper_limit;
-    config->spacings.setToExternal(const_cast<unsigned int *>(&halConfig->spacings[0]),
-            halConfig->num_spacings * sizeof(uint32_t));
-    // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
-    config->spacings.resize(halConfig->num_spacings);
-
-    if (config->type == Band::FM) {
-        config->ext.fm.deemphasis = static_cast<Deemphasis>(halConfig->fm.deemphasis);
-        config->ext.fm.stereo = halConfig->fm.stereo;
-        config->ext.fm.rds = static_cast<Rds>(halConfig->fm.rds);
-        config->ext.fm.ta = halConfig->fm.ta;
-        config->ext.fm.af = halConfig->fm.af;
-        config->ext.fm.ea = halConfig->fm.ea;
-    } else {
-        config->ext.am.stereo = halConfig->am.stereo;
-    }
-}
-
-//static
-void Utils::convertPropertiesFromHal(Properties *properties,
-        const radio_hal_properties_t *halProperties)
-{
-    properties->classId = static_cast<Class>(halProperties->class_id);
-    properties->implementor.setToExternal(halProperties->implementor, strlen(halProperties->implementor));
-    properties->product.setToExternal(halProperties->product, strlen(halProperties->product));
-    properties->version.setToExternal(halProperties->version, strlen(halProperties->version));
-    properties->serial.setToExternal(halProperties->serial, strlen(halProperties->serial));
-    properties->numTuners = halProperties->num_tuners;
-    properties->numAudioSources = halProperties->num_audio_sources;
-    properties->supportsCapture = halProperties->supports_capture;
-
-    BandConfig *bands =
-            new BandConfig[halProperties->num_bands];
-    for (size_t i = 0; i < halProperties->num_bands; i++) {
-        convertBandConfigFromHal(&bands[i], &halProperties->bands[i]);
-    }
-    properties->bands.setToExternal(bands, halProperties->num_bands);
-    // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
-    properties->bands.resize(halProperties->num_bands);
-    delete[] bands;
-}
-
-//static
-void Utils::convertBandConfigToHal(radio_hal_band_config_t *halConfig, const BandConfig *config)
-{
-    halConfig->type = static_cast<radio_band_t>(config->type);
-    halConfig->antenna_connected = config->antennaConnected;
-    halConfig->lower_limit = config->lowerLimit;
-    halConfig->upper_limit = config->upperLimit;
-    halConfig->num_spacings = config->spacings.size();
-    if (halConfig->num_spacings > RADIO_NUM_SPACINGS_MAX) {
-        halConfig->num_spacings = RADIO_NUM_SPACINGS_MAX;
-    }
-    memcpy(halConfig->spacings, config->spacings.data(),
-           sizeof(uint32_t) * halConfig->num_spacings);
-
-    if (config->type == Band::FM) {
-        halConfig->fm.deemphasis = static_cast<radio_deemphasis_t>(config->ext.fm.deemphasis);
-        halConfig->fm.stereo = config->ext.fm.stereo;
-        halConfig->fm.rds = static_cast<radio_rds_t>(config->ext.fm.rds);
-        halConfig->fm.ta = config->ext.fm.ta;
-        halConfig->fm.af = config->ext.fm.af;
-        halConfig->fm.ea = config->ext.fm.ea;
-    } else {
-        halConfig->am.stereo = config->ext.am.stereo;
-    }
-}
-
-
-//static
-void Utils::convertProgramInfoFromHal(ProgramInfo *info, radio_program_info_t *halInfo)
-{
-    auto &info_1_1 = *info;
-    auto &info_1_0 = info->base;
-
-    info_1_0.channel = halInfo->channel;
-    info_1_0.subChannel = halInfo->sub_channel;
-    info_1_0.tuned = halInfo->tuned;
-    info_1_0.stereo = halInfo->stereo;
-    info_1_0.digital = halInfo->digital;
-    info_1_0.signalStrength = halInfo->signal_strength;
-    convertMetaDataFromHal(info_1_0.metadata, halInfo->metadata);
-    // TODO(b/34348946): add support for HAL 1.1 fields
-    info_1_1.flags = 0;
-}
-
-//static
-int Utils::convertMetaDataFromHal(hidl_vec<MetaData>& metadata, radio_metadata_t *halMetadata)
-{
-    if (halMetadata == NULL) {
-        ALOGE("Invalid argument: halMetadata is NULL");
-        return 0;
-    }
-
-    int count = radio_metadata_get_count(halMetadata);
-    if (count <= 0) {
-        return count;
-    }
-    MetaData *newMetadata = new MetaData[count];
-    int outCount = 0;
-    for (int i = 0; i < count; i++) {
-        radio_metadata_key_t key;
-        radio_metadata_type_t type;
-        void *value;
-        size_t size;
-        if (radio_metadata_get_at_index(halMetadata, i , &key, &type, &value, &size) != 0 ||
-                size == 0) {
-            continue;
-        }
-        switch (type) {
-            case RADIO_METADATA_TYPE_INT: {
-                newMetadata[outCount].intValue = *(static_cast<int32_t *>(value));
-            } break;
-            case RADIO_METADATA_TYPE_TEXT: {
-                newMetadata[outCount].stringValue = static_cast<char *>(value);
-            } break;
-            case RADIO_METADATA_TYPE_RAW: {
-                newMetadata[outCount].rawValue.setToExternal(static_cast<uint8_t *>(value), size);
-                // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
-                newMetadata[outCount].rawValue.resize(size);
-            } break;
-            case RADIO_METADATA_TYPE_CLOCK: {
-                radio_metadata_clock_t *clock = static_cast<radio_metadata_clock_t *>(value);
-                newMetadata[outCount].clockValue.utcSecondsSinceEpoch =
-                        clock->utc_seconds_since_epoch;
-                newMetadata[outCount].clockValue.timezoneOffsetInMinutes =
-                        clock->timezone_offset_in_minutes;
-            } break;
-        }
-        newMetadata[outCount].type = static_cast<MetadataType>(type);
-        newMetadata[outCount].key = static_cast<MetadataKey>(key);
-        outCount++;
-    }
-    metadata.setToExternal(newMetadata, outCount);
-    // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
-    metadata.resize(outCount);
-    return outCount;
-}
-
-}  // namespace implementation
-}  // namespace V1_1
-}  // namespace broadcastradio
-}  // namespace hardware
-}  // namespace android
diff --git a/broadcastradio/1.1/default/Utils.h b/broadcastradio/1.1/default/Utils.h
deleted file mode 100644 (file)
index 22902ba..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_UTILS_H
-#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_UTILS_H
-
-#include <android/hardware/broadcastradio/1.1/types.h>
-#include <hardware/radio.h>
-
-namespace android {
-namespace hardware {
-namespace broadcastradio {
-namespace V1_1 {
-namespace implementation {
-
-using V1_0::Class;
-using V1_0::BandConfig;
-using V1_0::MetaData;
-using V1_0::Properties;
-
-class Utils {
-public:
-    static const char * getClassString(Class ClassId);
-    static Result convertHalResult(int rc);
-    static void convertBandConfigFromHal(BandConfig *config,
-            const radio_hal_band_config_t *halConfig);
-    static void convertPropertiesFromHal(Properties *properties,
-            const radio_hal_properties_t *halProperties);
-    static void convertBandConfigToHal(radio_hal_band_config_t *halConfig,
-            const BandConfig *config);
-    static void convertProgramInfoFromHal(ProgramInfo *info,
-                                          radio_program_info_t *halInfo);
-    static int convertMetaDataFromHal(hidl_vec<MetaData>& metadata,
-                                       radio_metadata_t *halMetadata);
-private:
-    static const char * sClassModuleNames[];
-
-};
-
-}  // namespace implementation
-}  // namespace V1_1
-}  // namespace broadcastradio
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_UTILS_H
diff --git a/broadcastradio/1.1/default/VirtualProgram.cpp b/broadcastradio/1.1/default/VirtualProgram.cpp
new file mode 100644 (file)
index 0000000..7977391
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "VirtualProgram.h"
+
+#include <broadcastradio-utils/Utils.h>
+
+#include "resources.h"
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V1_1 {
+namespace implementation {
+
+using std::vector;
+
+using V1_0::MetaData;
+using V1_0::MetadataKey;
+using V1_0::MetadataType;
+using utils::HalRevision;
+
+static MetaData createDemoBitmap(MetadataKey key, HalRevision halRev) {
+    MetaData bmp = {MetadataType::INT, key, resources::demoPngId, {}, {}, {}};
+    if (halRev < HalRevision::V1_1) {
+        bmp.type = MetadataType::RAW;
+        bmp.intValue = 0;
+        bmp.rawValue = hidl_vec<uint8_t>(resources::demoPng, std::end(resources::demoPng));
+    }
+    return bmp;
+}
+
+ProgramInfo VirtualProgram::getProgramInfo(HalRevision halRev) const {
+    ProgramInfo info11 = {};
+    auto& info10 = info11.base;
+
+    utils::getLegacyChannel(selector, &info10.channel, &info10.subChannel);
+    info11.selector = selector;
+    info10.tuned = true;
+    info10.stereo = true;
+    info10.digital = utils::isDigital(selector);
+    info10.signalStrength = info10.digital ? 100 : 80;
+
+    info10.metadata = hidl_vec<MetaData>({
+        {MetadataType::TEXT, MetadataKey::RDS_PS, {}, {}, programName, {}},
+        {MetadataType::TEXT, MetadataKey::TITLE, {}, {}, songTitle, {}},
+        {MetadataType::TEXT, MetadataKey::ARTIST, {}, {}, songArtist, {}},
+        createDemoBitmap(MetadataKey::ICON, halRev),
+        createDemoBitmap(MetadataKey::ART, halRev),
+    });
+
+    info11.vendorInfo = hidl_vec<VendorKeyValue>({
+        {"com.google.dummy", "dummy"},
+        {"com.google.dummy.VirtualProgram", std::to_string(reinterpret_cast<uintptr_t>(this))},
+    });
+
+    return info11;
+}
+
+// Defining order on virtual programs, how they appear on band.
+// It's mostly for default implementation purposes, may not be complete or correct.
+bool operator<(const VirtualProgram& lhs, const VirtualProgram& rhs) {
+    auto& l = lhs.selector;
+    auto& r = rhs.selector;
+
+    // Two programs with the same primaryId is considered the same.
+    if (l.programType != r.programType) return l.programType < r.programType;
+    if (l.primaryId.type != r.primaryId.type) return l.primaryId.type < r.primaryId.type;
+    if (l.primaryId.value != r.primaryId.value) return l.primaryId.value < r.primaryId.value;
+
+    // A little exception for HD Radio subchannel - we check secondary ID too.
+    if (utils::hasId(l, IdentifierType::HD_SUBCHANNEL) &&
+        utils::hasId(r, IdentifierType::HD_SUBCHANNEL)) {
+        return utils::getId(l, IdentifierType::HD_SUBCHANNEL) <
+               utils::getId(r, IdentifierType::HD_SUBCHANNEL);
+    }
+
+    return false;
+}
+
+vector<ProgramInfo> getProgramInfoVector(const vector<VirtualProgram>& vec, HalRevision halRev) {
+    vector<ProgramInfo> out;
+    out.reserve(vec.size());
+    for (auto&& program : vec) {
+        out.push_back(program.getProgramInfo(halRev));
+    }
+    return out;
+}
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
diff --git a/broadcastradio/1.1/default/VirtualProgram.h b/broadcastradio/1.1/default/VirtualProgram.h
new file mode 100644 (file)
index 0000000..a14830d
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_VIRTUALPROGRAM_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_VIRTUALPROGRAM_H
+
+#include <android/hardware/broadcastradio/1.1/types.h>
+#include <broadcastradio-utils/Utils.h>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V1_1 {
+namespace implementation {
+
+/**
+ * A radio program mock.
+ *
+ * This represents broadcast waves flying over the air,
+ * not an entry for a captured station in the radio tuner memory.
+ */
+struct VirtualProgram {
+    ProgramSelector selector;
+
+    std::string programName = "";
+    std::string songArtist = "";
+    std::string songTitle = "";
+
+    ProgramInfo getProgramInfo(utils::HalRevision halRev) const;
+
+    friend bool operator<(const VirtualProgram& lhs, const VirtualProgram& rhs);
+};
+
+std::vector<ProgramInfo> getProgramInfoVector(const std::vector<VirtualProgram>& vec,
+                                              utils::HalRevision halRev);
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_VIRTUALPROGRAM_H
diff --git a/broadcastradio/1.1/default/VirtualRadio.cpp b/broadcastradio/1.1/default/VirtualRadio.cpp
new file mode 100644 (file)
index 0000000..36d47a9
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "BroadcastRadioDefault.VirtualRadio"
+//#define LOG_NDEBUG 0
+
+#include "VirtualRadio.h"
+
+#include <broadcastradio-utils/Utils.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V1_1 {
+namespace implementation {
+
+using V1_0::Band;
+using V1_0::Class;
+
+using std::lock_guard;
+using std::move;
+using std::mutex;
+using std::vector;
+
+using utils::make_selector;
+
+static const vector<VirtualProgram> gInitialFmPrograms{
+    {make_selector(Band::FM, 94900), "Wild 94.9", "Drake ft. Rihanna", "Too Good"},
+    {make_selector(Band::FM, 96500), "KOIT", "Celine Dion", "All By Myself"},
+    {make_selector(Band::FM, 97300), "Alice@97.3", "Drops of Jupiter", "Train"},
+    {make_selector(Band::FM, 99700), "99.7 Now!", "The Chainsmokers", "Closer"},
+    {make_selector(Band::FM, 101300), "101-3 KISS-FM", "Justin Timberlake", "Rock Your Body"},
+    {make_selector(Band::FM, 103700), "iHeart80s @ 103.7", "Michael Jackson", "Billie Jean"},
+    {make_selector(Band::FM, 106100), "106 KMEL", "Drake", "Marvins Room"},
+};
+
+static VirtualRadio gEmptyRadio({});
+static VirtualRadio gFmRadio(gInitialFmPrograms);
+
+VirtualRadio::VirtualRadio(const vector<VirtualProgram> initialList) : mPrograms(initialList) {}
+
+vector<VirtualProgram> VirtualRadio::getProgramList() {
+    lock_guard<mutex> lk(mMut);
+    return mPrograms;
+}
+
+bool VirtualRadio::getProgram(const ProgramSelector& selector, VirtualProgram& programOut) {
+    lock_guard<mutex> lk(mMut);
+    for (auto&& program : mPrograms) {
+        if (utils::tunesTo(selector, program.selector)) {
+            programOut = program;
+            return true;
+        }
+    }
+    return false;
+}
+
+VirtualRadio& getRadio(V1_0::Class classId) {
+    switch (classId) {
+        case Class::AM_FM:
+            return getFmRadio();
+        case Class::SAT:
+            return getSatRadio();
+        case Class::DT:
+            return getDigitalRadio();
+        default:
+            ALOGE("Invalid class ID");
+            return gEmptyRadio;
+    }
+}
+
+VirtualRadio& getAmRadio() {
+    return gEmptyRadio;
+}
+
+VirtualRadio& getFmRadio() {
+    return gFmRadio;
+}
+
+VirtualRadio& getSatRadio() {
+    return gEmptyRadio;
+}
+
+VirtualRadio& getDigitalRadio() {
+    return gEmptyRadio;
+}
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
diff --git a/broadcastradio/1.1/default/VirtualRadio.h b/broadcastradio/1.1/default/VirtualRadio.h
new file mode 100644 (file)
index 0000000..3c7ae5c
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_VIRTUALRADIO_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_VIRTUALRADIO_H
+
+#include "VirtualProgram.h"
+
+#include <mutex>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V1_1 {
+namespace implementation {
+
+/**
+ * A radio frequency space mock.
+ *
+ * This represents all broadcast waves in the air for a given radio technology,
+ * not a captured station list in the radio tuner memory.
+ *
+ * It's meant to abstract out radio content from default tuner implementation.
+ */
+class VirtualRadio {
+   public:
+    VirtualRadio(const std::vector<VirtualProgram> initialList);
+
+    std::vector<VirtualProgram> getProgramList();
+    bool getProgram(const ProgramSelector& selector, VirtualProgram& program);
+
+   private:
+    std::mutex mMut;
+    std::vector<VirtualProgram> mPrograms;
+};
+
+/**
+ * Get virtual radio space for a given radio class.
+ *
+ * As a space, each virtual radio always exists. For example, DAB frequencies
+ * exists in US, but contains no programs.
+ *
+ * The lifetime of the virtual radio space is virtually infinite, but for the
+ * needs of default implementation, it's bound with the lifetime of default
+ * implementation process.
+ *
+ * Internally, it's a static object, so trying to access the reference during
+ * default implementation library unloading may result in segmentation fault.
+ * It's unlikely for testing purposes.
+ *
+ * @param classId A class of radio technology.
+ * @return A reference to virtual radio space for a given technology.
+ */
+VirtualRadio& getRadio(V1_0::Class classId);
+
+VirtualRadio& getAmRadio();
+VirtualRadio& getFmRadio();
+VirtualRadio& getSatRadio();
+VirtualRadio& getDigitalRadio();
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_VIRTUALRADIO_H
diff --git a/broadcastradio/1.1/default/android.hardware.broadcastradio@1.1-service.rc b/broadcastradio/1.1/default/android.hardware.broadcastradio@1.1-service.rc
new file mode 100644 (file)
index 0000000..7c57135
--- /dev/null
@@ -0,0 +1,4 @@
+service broadcastradio-hal /vendor/bin/hw/android.hardware.broadcastradio@1.1-service
+    class hal
+    user audioserver
+    group audio
diff --git a/broadcastradio/1.1/default/resources.h b/broadcastradio/1.1/default/resources.h
new file mode 100644 (file)
index 0000000..b7e709f
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_RESOURCES_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_RESOURCES_H
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V1_1 {
+namespace implementation {
+namespace resources {
+
+constexpr int32_t demoPngId = 123456;
+constexpr uint8_t demoPng[] = {
+    0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44,
+    0x52, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x08, 0x02, 0x00, 0x00, 0x00, 0x25,
+    0x0b, 0xe6, 0x89, 0x00, 0x00, 0x00, 0x5d, 0x49, 0x44, 0x41, 0x54, 0x68, 0xde, 0xed, 0xd9,
+    0xc1, 0x09, 0x00, 0x30, 0x08, 0x04, 0xc1, 0x33, 0xfd, 0xf7, 0x6c, 0x6a, 0xc8, 0x23, 0x04,
+    0xc9, 0x6c, 0x01, 0xc2, 0x20, 0xbe, 0x4c, 0x86, 0x57, 0x49, 0xba, 0xfb, 0xd6, 0xf4, 0xba,
+    0x3e, 0x7f, 0x4d, 0xdf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x8f, 0x00, 0xbd, 0xce, 0x7f,
+    0xc0, 0x11, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0xb8, 0x0d, 0x32, 0xd4, 0x0c, 0x77, 0xbd,
+    0xfb, 0xc1, 0xce, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82};
+
+}  // namespace resources
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_RESOURCES_H
diff --git a/broadcastradio/1.1/default/service.cpp b/broadcastradio/1.1/default/service.cpp
new file mode 100644 (file)
index 0000000..f8af0b7
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "BroadcastRadioDefault.service"
+
+#include <android-base/logging.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include "BroadcastRadioFactory.h"
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::hardware::broadcastradio::V1_1::implementation::BroadcastRadioFactory;
+
+int main(int /* argc */, char** /* argv */) {
+    configureRpcThreadpool(4, true);
+
+    BroadcastRadioFactory broadcastRadioFactory;
+    auto status = broadcastRadioFactory.registerAsService();
+    CHECK_EQ(status, android::OK) << "Failed to register Broadcast Radio HAL implementation";
+
+    joinRpcThreadpool();
+    return 1;  // joinRpcThreadpool shouldn't exit
+}
diff --git a/broadcastradio/1.1/tests/Android.bp b/broadcastradio/1.1/tests/Android.bp
new file mode 100644 (file)
index 0000000..fa1fd94
--- /dev/null
@@ -0,0 +1,29 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+    name: "android.hardware.broadcastradio@1.1-utils-tests",
+    vendor: true,
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
+    srcs: [
+        "WorkerThread_test.cpp",
+    ],
+    static_libs: ["android.hardware.broadcastradio@1.1-utils-lib"],
+}
diff --git a/broadcastradio/1.1/tests/OWNERS b/broadcastradio/1.1/tests/OWNERS
new file mode 100644 (file)
index 0000000..aa5ce82
--- /dev/null
@@ -0,0 +1,8 @@
+# Automotive team
+egranata@google.com
+keunyoung@google.com
+twasilczyk@google.com
+
+# VTS team
+ryanjcampbell@google.com
+yim@google.com
diff --git a/broadcastradio/1.1/tests/WorkerThread_test.cpp b/broadcastradio/1.1/tests/WorkerThread_test.cpp
new file mode 100644 (file)
index 0000000..ed36de3
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <broadcastradio-utils/WorkerThread.h>
+#include <gtest/gtest.h>
+
+namespace {
+
+using namespace std::chrono_literals;
+
+using android::WorkerThread;
+
+using std::atomic;
+using std::chrono::time_point;
+using std::chrono::steady_clock;
+using std::is_sorted;
+using std::lock_guard;
+using std::mutex;
+using std::this_thread::sleep_for;
+using std::vector;
+
+#define ASSERT_EQ_WITH_TOLERANCE(val1, val2, tolerance) \
+    ASSERT_LE((val1) - (tolerance), (val2));            \
+    ASSERT_GE((val1) + (tolerance), (val2));
+
+TEST(WorkerThreadTest, oneTask) {
+    atomic<bool> executed(false);
+    atomic<time_point<steady_clock>> stop;
+    WorkerThread thread;
+
+    auto start = steady_clock::now();
+    thread.schedule(
+        [&]() {
+            stop = steady_clock::now();
+            executed = true;
+        },
+        100ms);
+
+    sleep_for(150ms);
+
+    ASSERT_TRUE(executed);
+    auto delta = stop.load() - start;
+    ASSERT_EQ_WITH_TOLERANCE(delta, 100ms, 50ms);
+}
+
+TEST(WorkerThreadTest, cancelSecond) {
+    atomic<bool> executed1(false);
+    atomic<bool> executed2(false);
+    WorkerThread thread;
+
+    thread.schedule([&]() { executed2 = true; }, 100ms);
+    thread.schedule([&]() { executed1 = true; }, 25ms);
+
+    sleep_for(50ms);
+    thread.cancelAll();
+    sleep_for(100ms);
+
+    ASSERT_TRUE(executed1);
+    ASSERT_FALSE(executed2);
+}
+
+TEST(WorkerThreadTest, executeInOrder) {
+    mutex mut;
+    vector<int> order;
+    WorkerThread thread;
+
+    thread.schedule(
+        [&]() {
+            lock_guard<mutex> lk(mut);
+            order.push_back(0);
+        },
+        50ms);
+
+    thread.schedule(
+        [&]() {
+            lock_guard<mutex> lk(mut);
+            order.push_back(4);
+        },
+        400ms);
+
+    thread.schedule(
+        [&]() {
+            lock_guard<mutex> lk(mut);
+            order.push_back(1);
+        },
+        100ms);
+
+    thread.schedule(
+        [&]() {
+            lock_guard<mutex> lk(mut);
+            order.push_back(3);
+        },
+        300ms);
+
+    thread.schedule(
+        [&]() {
+            lock_guard<mutex> lk(mut);
+            order.push_back(2);
+        },
+        200ms);
+
+    sleep_for(500ms);
+
+    ASSERT_EQ(5u, order.size());
+    ASSERT_TRUE(is_sorted(order.begin(), order.end()));
+}
+
+TEST(WorkerThreadTest, dontExecuteAfterDestruction) {
+    atomic<bool> executed1(false);
+    atomic<bool> executed2(false);
+    {
+        WorkerThread thread;
+
+        thread.schedule([&]() { executed2 = true; }, 100ms);
+        thread.schedule([&]() { executed1 = true; }, 25ms);
+
+        sleep_for(50ms);
+    }
+    sleep_for(100ms);
+
+    ASSERT_TRUE(executed1);
+    ASSERT_FALSE(executed2);
+}
+
+}  // anonymous namespace
index 5577ea0..8b8fc6f 100644 (file)
@@ -43,6 +43,35 @@ enum ProgramInfoFlags : uint32_t {
      * increasing volume too much.
      */
     MUTED = 1 << 1,
+
+    /**
+     * Station broadcasts traffic information regularly,
+     * but not necessarily right now.
+     */
+    TRAFFIC_PROGRAM = 1 << 2,
+
+    /**
+     * Station is broadcasting traffic information at the very moment.
+     */
+    TRAFFIC_ANNOUNCEMENT = 1 << 3,
+};
+
+/**
+ * A key-value pair for vendor-specific information to be passed as-is through
+ * Android framework to the front-end application.
+ */
+struct VendorKeyValue {
+    /**
+     * Key must be prefixed with unique vendor Java-style namespace,
+     * eg. 'com.somecompany.parameter1'.
+     */
+    string key;
+
+    /**
+     * Value must be passed through the framework without any changes.
+     * Format of this string can vary across vendors.
+     */
+    string value;
 };
 
 struct Properties {
@@ -55,16 +84,204 @@ struct Properties {
     bool supportsBackgroundScanning;
 
     /**
-     * Opaque vendor-specific string, to be passed to front-end without changes.
-     * Format of this string can vary across vendors.
+     * A list of supported ProgramType values.
+     *
+     * If a program type is supported by radio module, it means it can tune
+     * to ProgramSelector of a given type.
+     *
+     * Support for VENDOR program type does not guarantee compatibility, as
+     * other module properties (implementor, product, version) must be checked.
+     */
+    vec<uint32_t> supportedProgramTypes;
+
+    /**
+     * A list of supported IdentifierType values.
+     *
+     * If an identifier is supported by radio module, it means it can use it for
+     * tuning to ProgramSelector with either primary or secondary Identifier of
+     * a given type.
+     *
+     * Support for VENDOR identifier type does not guarantee compatibility, as
+     * other module properties (implementor, product, version) must be checked.
+     */
+    vec<uint32_t> supportedIdentifierTypes;
+
+    /**
+     * Vendor-specific information.
+     *
+     * It may be used for extra features, not supported by the platform,
+     * for example: com.me.preset-slots=6; com.me.ultra-hd-capable=false.
+     */
+    vec<VendorKeyValue> vendorInfo;
+};
+
+/**
+ * Type of modulation.
+ *
+ * Used as a value for DRMO_MODULATION IdentifierType.
+ */
+enum Modulation : uint32_t {
+    AM = 1,
+    FM,
+};
+
+/**
+ * Type of a radio technology.
+ *
+ * VENDOR program types must be opaque to the framework.
+ *
+ * There are multiple VENDOR program types just to make vendor implementation
+ * easier with multiple properitary radio technologies. They are treated the
+ * same by the framework.
+ *
+ * All other values are reserved for future use.
+ * Values not matching any enumerated constant must be ignored.
+ */
+enum ProgramType : uint32_t {
+    AM = 1,  // analogue AM radio (with or without RDS)
+    FM,      // analogue FM radio (with or without RDS)
+    AM_HD,   // AM HD Radio
+    FM_HD,   // FM HD Radio
+    DAB,     // Digital audio broadcasting
+    DRMO,    // Digital Radio Mondiale
+    SXM,     // SiriusXM Satellite Radio
+
+    // Vendor-specific, not synced across devices.
+    VENDOR_START = 1000,
+    VENDOR_END = 1999,
+};
+
+/**
+ * Type of program identifier component.
+ *
+ * It MUST match the radio technology for primary ID but does not have to match
+ * it for secondary IDs. For example, a satellite program may set AM/FM fallback
+ * frequency, if a station broadcasts both via satellite and AM/FM.
+ *
+ * VENDOR identifier types must be opaque to the framework.
+ *
+ * The value format for each (but VENDOR_PRIMARY) identifier is strictly defined
+ * to maintain interoperability between devices made by different vendors.
+ *
+ * All other values are reserved for future use.
+ * Values not matching any enumerated constant must be ignored.
+ */
+enum IdentifierType : uint32_t {
+    AMFM_FREQUENCY = 1,  // kHz
+    RDS_PI,              // 16bit
+
+    /**
+     * 64bit compound primary identifier for HD Radio.
+     *
+     * Consists of (from the LSB):
+     * - 32bit: Station ID number;
+     * - 4bit: HD_SUBCHANNEL;
+     * - 18bit: AMFM_FREQUENCY.
+     * The remaining bits should be set to zeros when writing on the chip side
+     * and ignored when read.
+     */
+    HD_STATION_ID_EXT,
+
+    /**
+     * HD Radio subchannel - a value of range 0-7.
+     *
+     * The subchannel index is 0-based (where 0 is MPS and 1..7 are SPS),
+     * as opposed to HD Radio standard (where it's 1-based).
+     */
+    HD_SUBCHANNEL,
+
+    /**
+     * 24bit compound primary identifier for DAB.
+     *
+     * Consists of (from the LSB):
+     * - 16bit: SId;
+     * - 8bit: ECC code.
+     * The remaining bits should be set to zeros when writing on the chip side
+     * and ignored when read.
+     */
+    DAB_SIDECC,
+
+    DAB_ENSEMBLE,     // 16bit
+    DAB_SCID,         // 12bit
+    DAB_FREQUENCY,    // kHz
+    DRMO_SERVICE_ID,  // 24bit
+    DRMO_FREQUENCY,   // kHz
+    DRMO_MODULATION,  // Modulation enum
+    SXM_SERVICE_ID,   // 32bit
+    SXM_CHANNEL,      // 0-999 range
+
+    /**
+     * Primary identifier for vendor-specific radio technology.
+     * The value format is determined by a vendor.
+     *
+     * It must not be used in any other programType than corresponding VENDOR
+     * type between VENDOR_START and VENDOR_END (eg. identifier type 1015 must
+     * not be used in any program type other than 1015).
+     */
+    VENDOR_PRIMARY_START = ProgramType:VENDOR_START,
+    VENDOR_PRIMARY_END = ProgramType:VENDOR_END,
+};
+
+/**
+ * A single program identifier component, eg. frequency or channel ID.
+ *
+ * The uint32_t type field maps to IdentifierType enum. It's not straight,
+ * because the enum may be extended in future versions of the HAL. Values out of
+ * the enum range must not be used when writing and ignored when reading.
+ *
+ * The uint64_t value field holds the value in format described in comments for
+ * IdentifierType enum.
+ */
+struct ProgramIdentifier {
+    uint32_t type;  // IdentifierType
+    uint64_t value;
+};
+
+/**
+ * A set of identifiers necessary to tune to a given station.
+ *
+ * This can hold various identifiers, like
+ * - AM/FM frequency
+ * - HD Radio subchannel
+ * - DAB channel info
+ *
+ * The uint32_t programType field maps to ProgramType enum. It's not straight,
+ * because the enum may be extended in future versions of the HAL. Values out of
+ * the enum range must not be used when writing and ignored when reading.
+ *
+ * The primary ID uniquely identifies a station and can be used for equality
+ * check. The secondary IDs are supplementary and can speed up tuning process,
+ * but the primary ID is sufficient (ie. after a full band scan).
+ *
+ * Two selectors with different secondary IDs, but the same primary ID are
+ * considered equal. In particular, secondary IDs vector may get updated for
+ * an entry on the program list (ie. when a better frequency for a given
+ * station is found).
+ *
+ * The primaryId of a given programType MUST be of a specific type:
+ * - AM, FM: RDS_PI if the station broadcasts RDS, AMFM_FREQUENCY otherwise;
+ * - AM_HD, FM_HD: HD_STATION_ID_EXT;
+ * - DAB: DAB_SIDECC;
+ * - DRMO: DRMO_SERVICE_ID;
+ * - SXM: SXM_SERVICE_ID;
+ * - VENDOR: VENDOR_PRIMARY.
+ */
+struct ProgramSelector {
+    uint32_t programType;  // ProgramType
+    ProgramIdentifier primaryId;  // uniquely identifies a station
+    vec<ProgramIdentifier> secondaryIds;
+
+    /**
+     * Opaque vendor-specific identifiers, to be passed to front-end
+     * without changes.
      *
-     * It may be used for extra features, that's not supported by a platform,
-     * for example: "preset-slots=6;ultra-hd-capable=false".
+     * The order is meaningful, ie. the first element may be defined as
+     * frequency, second as the subchannel etc.
      *
-     * Front-end application MUST verify vendor/product name from the
-     * @1.0::Properties struct before doing any interpretation of this value.
+     * The vector is not serialized (either locally or to the cloud),
+     * unless it's a VENDOR program type.
      */
-    string vendorExension;
+    vec<uint64_t> vendorIds;
 };
 
 /**
@@ -73,17 +290,16 @@ struct Properties {
  */
 struct ProgramInfo {
     @1.0::ProgramInfo base;
+
+    ProgramSelector selector;
+
     bitfield<ProgramInfoFlags> flags;
 
     /**
-     * Opaque vendor-specific string, to be passed to front-end without changes.
-     * Format of this string can vary across vendors.
-     *
-     * It may be used for extra features, that's not supported by a platform,
-     * for example: "paid-service=true;bitrate=320kbps".
+     * Vendor-specific information.
      *
-     * Front-end application MUST verify vendor/product name from the
-     * @1.0::Properties struct before doing any interpretation of this value.
+     * It may be used for extra features, not supported by the platform,
+     * for example: paid-service=true; bitrate=320kbps.
      */
-    string vendorExension;
+    vec<VendorKeyValue> vendorInfo;
 };
similarity index 56%
rename from power/1.1/default/Android.bp
rename to broadcastradio/1.1/utils/Android.bp
index 0b3598b..e80d133 100644 (file)
@@ -1,4 +1,5 @@
-// Copyright (C) 2016 The Android Open Source Project
+//
+// Copyright (C) 2017 The Android Open Source Project
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
+//
 
-cc_binary {
-    proprietary: true,
-    defaults: ["hidl_defaults"],
+cc_library_static {
+    name: "android.hardware.broadcastradio@1.1-utils-lib",
+    vendor_available: true,
     relative_install_path: "hw",
-    name: "android.hardware.power@1.1-service",
-    init_rc: ["android.hardware.power@1.1-service.rc"],
-    srcs: ["service.cpp" , "Power.cpp"],
-
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
+    srcs: [
+        "Utils.cpp",
+        "WorkerThread.cpp",
+    ],
+    export_include_dirs: ["include"],
     shared_libs: [
-        "liblog",
-        "libdl",
-        "libutils",
-        "libhardware",
-        "libhidlbase",
-        "libhidltransport",
-        "android.hardware.power@1.0",
-        "android.hardware.power@1.1",
+        "android.hardware.broadcastradio@1.1",
     ],
 }
diff --git a/broadcastradio/1.1/utils/OWNERS b/broadcastradio/1.1/utils/OWNERS
new file mode 100644 (file)
index 0000000..0c27b71
--- /dev/null
@@ -0,0 +1,4 @@
+# Automotive team
+egranata@google.com
+keunyoung@google.com
+twasilczyk@google.com
diff --git a/broadcastradio/1.1/utils/Utils.cpp b/broadcastradio/1.1/utils/Utils.cpp
new file mode 100644 (file)
index 0000000..4dd6b13
--- /dev/null
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "BroadcastRadioDefault.utils"
+//#define LOG_NDEBUG 0
+
+#include <broadcastradio-utils/Utils.h>
+
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V1_1 {
+namespace utils {
+
+using V1_0::Band;
+
+static bool isCompatibleProgramType(const uint32_t ia, const uint32_t ib) {
+    auto a = static_cast<ProgramType>(ia);
+    auto b = static_cast<ProgramType>(ib);
+
+    if (a == b) return true;
+    if (a == ProgramType::AM && b == ProgramType::AM_HD) return true;
+    if (a == ProgramType::AM_HD && b == ProgramType::AM) return true;
+    if (a == ProgramType::FM && b == ProgramType::FM_HD) return true;
+    if (a == ProgramType::FM_HD && b == ProgramType::FM) return true;
+    return false;
+}
+
+static bool bothHaveId(const ProgramSelector& a, const ProgramSelector& b,
+                       const IdentifierType type) {
+    return hasId(a, type) && hasId(b, type);
+}
+
+static bool anyHaveId(const ProgramSelector& a, const ProgramSelector& b,
+                      const IdentifierType type) {
+    return hasId(a, type) || hasId(b, type);
+}
+
+static bool haveEqualIds(const ProgramSelector& a, const ProgramSelector& b,
+                         const IdentifierType type) {
+    if (!bothHaveId(a, b, type)) return false;
+    /* We should check all Ids of a given type (ie. other AF),
+     * but it doesn't matter for default implementation.
+     */
+    auto aId = getId(a, type);
+    auto bId = getId(b, type);
+    return aId == bId;
+}
+
+bool tunesTo(const ProgramSelector& a, const ProgramSelector& b) {
+    if (!isCompatibleProgramType(a.programType, b.programType)) return false;
+
+    auto type = getType(a);
+
+    switch (type) {
+        case ProgramType::AM:
+        case ProgramType::AM_HD:
+        case ProgramType::FM:
+        case ProgramType::FM_HD:
+            if (haveEqualIds(a, b, IdentifierType::HD_STATION_ID_EXT)) return true;
+
+            // if HD Radio subchannel is specified, it must match
+            if (anyHaveId(a, b, IdentifierType::HD_SUBCHANNEL)) {
+                // missing subchannel (analog) is an equivalent of first subchannel (MPS)
+                auto aCh = getId(a, IdentifierType::HD_SUBCHANNEL, 0);
+                auto bCh = getId(b, IdentifierType::HD_SUBCHANNEL, 0);
+                if (aCh != bCh) return false;
+            }
+
+            if (haveEqualIds(a, b, IdentifierType::RDS_PI)) return true;
+
+            return haveEqualIds(a, b, IdentifierType::AMFM_FREQUENCY);
+        case ProgramType::DAB:
+            return haveEqualIds(a, b, IdentifierType::DAB_SIDECC);
+        case ProgramType::DRMO:
+            return haveEqualIds(a, b, IdentifierType::DRMO_SERVICE_ID);
+        case ProgramType::SXM:
+            if (anyHaveId(a, b, IdentifierType::SXM_SERVICE_ID)) {
+                return haveEqualIds(a, b, IdentifierType::SXM_SERVICE_ID);
+            }
+            return haveEqualIds(a, b, IdentifierType::SXM_CHANNEL);
+        default:  // includes all vendor types
+            ALOGW("Unsupported program type: %s", toString(type).c_str());
+            return false;
+    }
+}
+
+ProgramType getType(const ProgramSelector& sel) {
+    return static_cast<ProgramType>(sel.programType);
+}
+
+bool isAmFm(const ProgramType type) {
+    switch (type) {
+        case ProgramType::AM:
+        case ProgramType::FM:
+        case ProgramType::AM_HD:
+        case ProgramType::FM_HD:
+            return true;
+        default:
+            return false;
+    }
+}
+
+bool isAm(const Band band) {
+    return band == Band::AM || band == Band::AM_HD;
+}
+
+bool isFm(const Band band) {
+    return band == Band::FM || band == Band::FM_HD;
+}
+
+bool hasId(const ProgramSelector& sel, const IdentifierType type) {
+    auto itype = static_cast<uint32_t>(type);
+    if (sel.primaryId.type == itype) return true;
+    // not optimal, but we don't care in default impl
+    for (auto&& id : sel.secondaryIds) {
+        if (id.type == itype) return true;
+    }
+    return false;
+}
+
+uint64_t getId(const ProgramSelector& sel, const IdentifierType type) {
+    auto itype = static_cast<uint32_t>(type);
+    if (sel.primaryId.type == itype) return sel.primaryId.value;
+    // not optimal, but we don't care in default impl
+    for (auto&& id : sel.secondaryIds) {
+        if (id.type == itype) return id.value;
+    }
+    ALOGW("Identifier %s not found", toString(type).c_str());
+    return 0;
+}
+
+uint64_t getId(const ProgramSelector& sel, const IdentifierType type, uint64_t defval) {
+    if (!hasId(sel, type)) return defval;
+    return getId(sel, type);
+}
+
+ProgramSelector make_selector(Band band, uint32_t channel, uint32_t subChannel) {
+    ProgramSelector sel = {};
+
+    ALOGW_IF((subChannel > 0) && (band == Band::AM || band == Band::FM),
+             "got subChannel for non-HD AM/FM");
+
+    // we can't use ProgramType::AM_HD or FM_HD, because we don't know HD station ID
+    ProgramType type;
+    if (isAm(band)) {
+        type = ProgramType::AM;
+    } else if (isFm(band)) {
+        type = ProgramType::FM;
+    } else {
+        LOG_ALWAYS_FATAL("Unsupported band: %s", toString(band).c_str());
+    }
+
+    sel.programType = static_cast<uint32_t>(type);
+    sel.primaryId.type = static_cast<uint32_t>(IdentifierType::AMFM_FREQUENCY);
+    sel.primaryId.value = channel;
+    if (subChannel > 0) {
+        /* stating sub channel for AM/FM channel does not give any guarantees,
+         * but we can't do much more without HD station ID
+         *
+         * The legacy APIs had 1-based subChannels, while ProgramSelector is 0-based.
+         */
+        sel.secondaryIds = hidl_vec<ProgramIdentifier>{
+            {static_cast<uint32_t>(IdentifierType::HD_SUBCHANNEL), subChannel - 1},
+        };
+    }
+
+    return sel;
+}
+
+bool getLegacyChannel(const ProgramSelector& sel, uint32_t* channelOut, uint32_t* subChannelOut) {
+    if (channelOut) *channelOut = 0;
+    if (subChannelOut) *subChannelOut = 0;
+    if (isAmFm(getType(sel))) {
+        if (channelOut) *channelOut = getId(sel, IdentifierType::AMFM_FREQUENCY);
+        if (subChannelOut && hasId(sel, IdentifierType::HD_SUBCHANNEL)) {
+            // The legacy APIs had 1-based subChannels, while ProgramSelector is 0-based.
+            *subChannelOut = getId(sel, IdentifierType::HD_SUBCHANNEL) + 1;
+        }
+        return true;
+    }
+    return false;
+}
+
+bool isDigital(const ProgramSelector& sel) {
+    switch (getType(sel)) {
+        case ProgramType::AM:
+        case ProgramType::FM:
+            return false;
+        default:
+            // VENDOR might not be digital, but it doesn't matter for default impl.
+            return true;
+    }
+}
+
+}  // namespace utils
+}  // namespace V1_1
+
+namespace V1_0 {
+
+bool operator==(const BandConfig& l, const BandConfig& r) {
+    if (l.type != r.type) return false;
+    if (l.antennaConnected != r.antennaConnected) return false;
+    if (l.lowerLimit != r.lowerLimit) return false;
+    if (l.upperLimit != r.upperLimit) return false;
+    if (l.spacings != r.spacings) return false;
+    if (V1_1::utils::isAm(l.type)) {
+        return l.ext.am == r.ext.am;
+    } else if (V1_1::utils::isFm(l.type)) {
+        return l.ext.fm == r.ext.fm;
+    } else {
+        ALOGW("Unsupported band config type: %s", toString(l.type).c_str());
+        return false;
+    }
+}
+
+}  // namespace V1_0
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
diff --git a/broadcastradio/1.1/utils/WorkerThread.cpp b/broadcastradio/1.1/utils/WorkerThread.cpp
new file mode 100644 (file)
index 0000000..bfcbb39
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "WorkerThread"
+//#define LOG_NDEBUG 0
+
+#include <broadcastradio-utils/WorkerThread.h>
+
+#include <log/log.h>
+
+namespace android {
+
+using std::chrono::milliseconds;
+using std::chrono::steady_clock;
+using std::function;
+using std::lock_guard;
+using std::mutex;
+using std::priority_queue;
+using std::this_thread::sleep_for;
+using std::unique_lock;
+
+bool operator<(const WorkerThread::Task& lhs, const WorkerThread::Task& rhs) {
+    return lhs.when > rhs.when;
+}
+
+WorkerThread::WorkerThread() : mIsTerminating(false), mThread(&WorkerThread::threadLoop, this) {}
+
+WorkerThread::~WorkerThread() {
+    ALOGV("%s", __func__);
+    {
+        lock_guard<mutex> lk(mMut);
+        mIsTerminating = true;
+        mCond.notify_one();
+    }
+    mThread.join();
+}
+
+void WorkerThread::schedule(function<void()> task, milliseconds delay) {
+    ALOGV("%s", __func__);
+
+    auto when = steady_clock::now() + delay;
+
+    lock_guard<mutex> lk(mMut);
+    mTasks.push(Task({when, task}));
+    mCond.notify_one();
+}
+
+void WorkerThread::cancelAll() {
+    ALOGV("%s", __func__);
+
+    lock_guard<mutex> lk(mMut);
+    priority_queue<Task>().swap(mTasks);  // empty queue
+}
+
+void WorkerThread::threadLoop() {
+    ALOGV("%s", __func__);
+    while (!mIsTerminating) {
+        unique_lock<mutex> lk(mMut);
+        if (mTasks.empty()) {
+            mCond.wait(lk);
+            continue;
+        }
+
+        auto task = mTasks.top();
+        if (task.when > steady_clock::now()) {
+            mCond.wait_until(lk, task.when);
+            continue;
+        }
+
+        mTasks.pop();
+        lk.unlock();  // what() might need to schedule another task
+        task.what();
+    }
+}
+
+}  // namespace android
diff --git a/broadcastradio/1.1/utils/include/broadcastradio-utils/Utils.h b/broadcastradio/1.1/utils/include/broadcastradio-utils/Utils.h
new file mode 100644 (file)
index 0000000..24c60ee
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_UTILS_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_UTILS_H
+
+#include <android/hardware/broadcastradio/1.1/types.h>
+#include <chrono>
+#include <queue>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V1_1 {
+namespace utils {
+
+// TODO(b/64115813): move it out from frameworks/base/services/core/jni/BroadcastRadio/types.h
+enum class HalRevision : uint32_t {
+    V1_0 = 1,
+    V1_1,
+};
+
+/**
+ * Checks, if {@code pointer} tunes to {@channel}.
+ *
+ * For example, having a channel {AMFM_FREQUENCY = 103.3}:
+ * - selector {AMFM_FREQUENCY = 103.3, HD_SUBCHANNEL = 0} can tune to this channel;
+ * - selector {AMFM_FREQUENCY = 103.3, HD_SUBCHANNEL = 1} can't.
+ *
+ * @param pointer selector we're trying to match against channel.
+ * @param channel existing channel.
+ */
+bool tunesTo(const ProgramSelector& pointer, const ProgramSelector& channel);
+
+ProgramType getType(const ProgramSelector& sel);
+bool isAmFm(const ProgramType type);
+
+bool isAm(const V1_0::Band band);
+bool isFm(const V1_0::Band band);
+
+bool hasId(const ProgramSelector& sel, const IdentifierType type);
+
+/**
+ * Returns ID (either primary or secondary) for a given program selector.
+ *
+ * If the selector does not contain given type, returns 0 and emits a warning.
+ */
+uint64_t getId(const ProgramSelector& sel, const IdentifierType type);
+
+/**
+ * Returns ID (either primary or secondary) for a given program selector.
+ *
+ * If the selector does not contain given type, returns default value.
+ */
+uint64_t getId(const ProgramSelector& sel, const IdentifierType type, uint64_t defval);
+
+ProgramSelector make_selector(V1_0::Band band, uint32_t channel, uint32_t subChannel = 0);
+
+bool getLegacyChannel(const ProgramSelector& sel, uint32_t* channelOut, uint32_t* subChannelOut);
+
+bool isDigital(const ProgramSelector& sel);
+
+}  // namespace utils
+}  // namespace V1_1
+
+namespace V1_0 {
+
+bool operator==(const BandConfig& l, const BandConfig& r);
+
+}  // namespace V1_0
+
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_UTILS_H
diff --git a/broadcastradio/1.1/utils/include/broadcastradio-utils/WorkerThread.h b/broadcastradio/1.1/utils/include/broadcastradio-utils/WorkerThread.h
new file mode 100644 (file)
index 0000000..635876f
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_WORKERTHREAD_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_WORKERTHREAD_H
+
+#include <chrono>
+#include <queue>
+#include <thread>
+
+namespace android {
+
+class WorkerThread {
+   public:
+    WorkerThread();
+    virtual ~WorkerThread();
+
+    void schedule(std::function<void()> task, std::chrono::milliseconds delay);
+    void cancelAll();
+
+   private:
+    struct Task {
+        std::chrono::time_point<std::chrono::steady_clock> when;
+        std::function<void()> what;
+    };
+    friend bool operator<(const Task& lhs, const Task& rhs);
+
+    std::atomic<bool> mIsTerminating;
+    std::mutex mMut;
+    std::condition_variable mCond;
+    std::thread mThread;
+    std::priority_queue<Task> mTasks;
+
+    void threadLoop();
+};
+
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_WORKERTHREAD_H
diff --git a/broadcastradio/1.1/vts/OWNERS b/broadcastradio/1.1/vts/OWNERS
new file mode 100644 (file)
index 0000000..aa5ce82
--- /dev/null
@@ -0,0 +1,8 @@
+# Automotive team
+egranata@google.com
+keunyoung@google.com
+twasilczyk@google.com
+
+# VTS team
+ryanjcampbell@google.com
+yim@google.com
index a4c0849..4b93cbc 100644 (file)
 
 cc_test {
     name: "VtsHalBroadcastradioV1_1TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalBroadcastradioV1_1TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
+    static_libs: [
         "android.hardware.broadcastradio@1.0",
         "android.hardware.broadcastradio@1.1",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
+        "android.hardware.broadcastradio@1.1-utils-lib",
+        "android.hardware.broadcastradio@1.1-vts-utils-lib",
+        "libgmock",
     ],
 }
index aa5ab54..a46378e 100644 (file)
  * limitations under the License.
  */
 
-#define LOG_TAG "BroadcastRadioHidlHalTest"
+#define LOG_TAG "broadcastradio.vts"
+
 #include <VtsHalHidlTargetTestBase.h>
+#include <android/hardware/broadcastradio/1.1/IBroadcastRadio.h>
+#include <android/hardware/broadcastradio/1.1/IBroadcastRadioFactory.h>
+#include <android/hardware/broadcastradio/1.1/ITuner.h>
+#include <android/hardware/broadcastradio/1.1/ITunerCallback.h>
+#include <android/hardware/broadcastradio/1.1/types.h>
 #include <android-base/logging.h>
+#include <broadcastradio-utils/Utils.h>
+#include <broadcastradio-vts-utils/call-barrier.h>
+#include <broadcastradio-vts-utils/mock-timeout.h>
 #include <cutils/native_handle.h>
 #include <cutils/properties.h>
+#include <gmock/gmock.h>
 #include <hidl/HidlTransportSupport.h>
 #include <utils/threads.h>
 
-#include <android/hardware/broadcastradio/1.1/IBroadcastRadioFactory.h>
-#include <android/hardware/broadcastradio/1.0/IBroadcastRadio.h>
-#include <android/hardware/broadcastradio/1.1/ITuner.h>
-#include <android/hardware/broadcastradio/1.1/ITunerCallback.h>
-#include <android/hardware/broadcastradio/1.1/types.h>
-
-
-namespace V1_0 = ::android::hardware::broadcastradio::V1_0;
-
-using ::android::sp;
-using ::android::Mutex;
-using ::android::Condition;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::hardware::broadcastradio::V1_0::BandConfig;
-using ::android::hardware::broadcastradio::V1_0::Class;
-using ::android::hardware::broadcastradio::V1_0::Direction;
-using ::android::hardware::broadcastradio::V1_0::IBroadcastRadio;
-using ::android::hardware::broadcastradio::V1_0::MetaData;
-using ::android::hardware::broadcastradio::V1_0::Properties;
-using ::android::hardware::broadcastradio::V1_1::IBroadcastRadioFactory;
-using ::android::hardware::broadcastradio::V1_1::ITuner;
-using ::android::hardware::broadcastradio::V1_1::ITunerCallback;
-using ::android::hardware::broadcastradio::V1_1::ProgramInfo;
-using ::android::hardware::broadcastradio::V1_1::Result;
-using ::android::hardware::broadcastradio::V1_1::ProgramListResult;
-
-
-// The main test class for Broadcast Radio HIDL HAL.
-
-class BroadcastRadioHidlTest : public ::testing::VtsHalHidlTargetTestBase {
- protected:
-    virtual void SetUp() override {
-        auto factory = ::testing::VtsHalHidlTargetTestBase::getService<IBroadcastRadioFactory>();
-        if (factory != 0) {
-            factory->connectModule(Class::AM_FM,
-                             [&](Result retval, const ::android::sp<IBroadcastRadio>& result) {
-                if (retval == Result::OK) {
-                  mRadio = IBroadcastRadio::castFrom(result);
-                }
-            });
-        }
-        mTunerCallback = new MyCallback(this);
-        ASSERT_NE(nullptr, mRadio.get());
-        ASSERT_NE(nullptr, mTunerCallback.get());
-    }
-
-    virtual void TearDown() override {
-        mTuner.clear();
-        mRadio.clear();
-    }
+#include <chrono>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V1_1 {
+namespace vts {
+
+using namespace std::chrono_literals;
+
+using testing::_;
+using testing::AnyNumber;
+using testing::ByMove;
+using testing::DoAll;
+using testing::Invoke;
+using testing::SaveArg;
+
+using broadcastradio::vts::CallBarrier;
+using V1_0::BandConfig;
+using V1_0::Class;
+using V1_0::MetaData;
+using V1_0::MetadataKey;
+using V1_0::MetadataType;
+
+using std::chrono::steady_clock;
+using std::this_thread::sleep_for;
+
+static constexpr auto kConfigTimeout = 10s;
+static constexpr auto kConnectModuleTimeout = 1s;
+static constexpr auto kTuneTimeout = 30s;
+static constexpr auto kEventPropagationTimeout = 1s;
+static constexpr auto kFullScanTimeout = 1min;
+
+static constexpr ProgramType kStandardProgramTypes[] = {
+    ProgramType::AM,  ProgramType::FM,   ProgramType::AM_HD, ProgramType::FM_HD,
+    ProgramType::DAB, ProgramType::DRMO, ProgramType::SXM};
+
+static void printSkipped(std::string msg) {
+    std::cout << "[  SKIPPED ] " << msg << std::endl;
+}
 
-    class MyCallback : public ITunerCallback {
-     public:
+struct TunerCallbackMock : public ITunerCallback {
+    TunerCallbackMock() { EXPECT_CALL(*this, hardwareFailure()).Times(0); }
+
+    MOCK_METHOD0(hardwareFailure, Return<void>());
+    MOCK_TIMEOUT_METHOD2(configChange, Return<void>(Result, const BandConfig&));
+    MOCK_METHOD2(tuneComplete, Return<void>(Result, const V1_0::ProgramInfo&));
+    MOCK_TIMEOUT_METHOD2(tuneComplete_1_1, Return<void>(Result, const ProgramSelector&));
+    MOCK_METHOD1(afSwitch, Return<void>(const V1_0::ProgramInfo&));
+    MOCK_METHOD1(antennaStateChange, Return<void>(bool connected));
+    MOCK_METHOD1(trafficAnnouncement, Return<void>(bool active));
+    MOCK_METHOD1(emergencyAnnouncement, Return<void>(bool active));
+    MOCK_METHOD3(newMetadata, Return<void>(uint32_t ch, uint32_t subCh, const hidl_vec<MetaData>&));
+    MOCK_METHOD1(backgroundScanAvailable, Return<void>(bool));
+    MOCK_TIMEOUT_METHOD1(backgroundScanComplete, Return<void>(ProgramListResult));
+    MOCK_METHOD0(programListChanged, Return<void>());
+    MOCK_TIMEOUT_METHOD1(currentProgramInfoChanged, Return<void>(const ProgramInfo&));
+};
 
-        // ITunerCallback methods (see doc in ITunerCallback.hal)
-        virtual Return<void> hardwareFailure() {
-            ALOGI("%s", __FUNCTION__);
-            mParentTest->onHwFailureCallback();
-            return Void();
-        }
+class BroadcastRadioHalTest : public ::testing::VtsHalHidlTargetTestBase,
+                              public ::testing::WithParamInterface<Class> {
+   protected:
+    virtual void SetUp() override;
+    virtual void TearDown() override;
 
-        virtual Return<void> configChange(Result result, const BandConfig& config __unused) {
-            ALOGI("%s result %d", __FUNCTION__, result);
-            mParentTest->onResultCallback(result);
-            return Void();
-        }
+    bool openTuner();
+    bool nextBand();
+    bool getProgramList(std::function<void(const hidl_vec<ProgramInfo>& list)> cb);
 
-        virtual Return<void> tuneComplete(Result result __unused, const V1_0::ProgramInfo& info __unused) {
-            return Void();
-        }
+    Class radioClass;
+    bool skipped = false;
 
-        virtual Return<void> tuneComplete_1_1(Result result, const ProgramInfo& info __unused) {
-            ALOGI("%s result %d", __FUNCTION__, result);
-            mParentTest->onResultCallback(result);
-            return Void();
-        }
+    sp<IBroadcastRadio> mRadioModule;
+    sp<ITuner> mTuner;
+    sp<TunerCallbackMock> mCallback = new TunerCallbackMock();
 
-        virtual Return<void> afSwitch(const V1_0::ProgramInfo& info __unused) {
-            return Void();
-        }
+   private:
+    const BandConfig& getBand(unsigned idx);
 
-        virtual Return<void> afSwitch_1_1(const ProgramInfo& info __unused) {
-            return Void();
-        }
+    unsigned currentBandIndex = 0;
+    hidl_vec<BandConfig> mBands;
+};
 
-        virtual Return<void> antennaStateChange(bool connected) {
-            ALOGI("%s connected %d", __FUNCTION__, connected);
-            return Void();
+/**
+ * Clears strong pointer and waits until the object gets destroyed.
+ *
+ * @param ptr The pointer to get cleared.
+ * @param timeout Time to wait for other references.
+ */
+template <typename T>
+static void clearAndWait(sp<T>& ptr, std::chrono::milliseconds timeout) {
+    wp<T> wptr = ptr;
+    ptr.clear();
+    auto limit = steady_clock::now() + timeout;
+    while (wptr.promote() != nullptr) {
+        constexpr auto step = 10ms;
+        if (steady_clock::now() + step > limit) {
+            FAIL() << "Pointer was not released within timeout";
+            break;
         }
+        sleep_for(step);
+    }
+}
 
-        virtual Return<void> trafficAnnouncement(bool active) {
-            ALOGI("%s active %d", __FUNCTION__, active);
-            return Void();
-        }
+void BroadcastRadioHalTest::SetUp() {
+    radioClass = GetParam();
+
+    // lookup HIDL service
+    auto factory = getService<IBroadcastRadioFactory>();
+    ASSERT_NE(nullptr, factory.get());
+
+    // connect radio module
+    Result connectResult;
+    CallBarrier onConnect;
+    factory->connectModule(radioClass, [&](Result ret, const sp<V1_0::IBroadcastRadio>& radio) {
+        connectResult = ret;
+        if (ret == Result::OK) mRadioModule = IBroadcastRadio::castFrom(radio);
+        onConnect.call();
+    });
+    ASSERT_TRUE(onConnect.waitForCall(kConnectModuleTimeout));
+
+    if (connectResult == Result::INVALID_ARGUMENTS) {
+        printSkipped("This device class is not supported.");
+        skipped = true;
+        return;
+    }
+    ASSERT_EQ(connectResult, Result::OK);
+    ASSERT_NE(nullptr, mRadioModule.get());
+
+    // get module properties
+    Properties prop11;
+    auto& prop10 = prop11.base;
+    auto propResult =
+        mRadioModule->getProperties_1_1([&](const Properties& properties) { prop11 = properties; });
+
+    ASSERT_TRUE(propResult.isOk());
+    EXPECT_EQ(radioClass, prop10.classId);
+    EXPECT_GT(prop10.numTuners, 0u);
+    EXPECT_GT(prop11.supportedProgramTypes.size(), 0u);
+    EXPECT_GT(prop11.supportedIdentifierTypes.size(), 0u);
+    if (radioClass == Class::AM_FM) {
+        EXPECT_GT(prop10.bands.size(), 0u);
+    }
+    mBands = prop10.bands;
+}
 
-        virtual Return<void> emergencyAnnouncement(bool active) {
-            ALOGI("%s active %d", __FUNCTION__, active);
-            return Void();
-        }
+void BroadcastRadioHalTest::TearDown() {
+    mTuner.clear();
+    mRadioModule.clear();
+    clearAndWait(mCallback, 1s);
+}
 
-        virtual Return<void> newMetadata(uint32_t channel __unused, uint32_t subChannel __unused,
-                           const ::android::hardware::hidl_vec<MetaData>& metadata __unused) {
-            ALOGI("%s", __FUNCTION__);
-            return Void();
-        }
+bool BroadcastRadioHalTest::openTuner() {
+    EXPECT_EQ(nullptr, mTuner.get());
 
-        virtual Return<void> backgroundScanAvailable(bool isAvailable __unused) {
-            return Void();
-        }
+    if (radioClass == Class::AM_FM) {
+        EXPECT_TIMEOUT_CALL(*mCallback, configChange, Result::OK, _);
+    }
 
-        virtual Return<void> backgroundScanComplete(ProgramListResult result __unused) {
-            return Void();
-        }
+    Result halResult = Result::NOT_INITIALIZED;
+    auto openCb = [&](Result result, const sp<V1_0::ITuner>& tuner) {
+        halResult = result;
+        if (result != Result::OK) return;
+        mTuner = ITuner::castFrom(tuner);
+    };
+    currentBandIndex = 0;
+    auto hidlResult = mRadioModule->openTuner(getBand(0), true, mCallback, openCb);
 
-        virtual Return<void> programListChanged() {
-            return Void();
-        }
+    EXPECT_TRUE(hidlResult.isOk());
+    EXPECT_EQ(Result::OK, halResult);
+    EXPECT_NE(nullptr, mTuner.get());
+    if (radioClass == Class::AM_FM && mTuner != nullptr) {
+        EXPECT_TIMEOUT_CALL_WAIT(*mCallback, configChange, kConfigTimeout);
 
-                MyCallback(BroadcastRadioHidlTest *parentTest) : mParentTest(parentTest) {}
+        BandConfig halConfig;
+        Result halResult = Result::NOT_INITIALIZED;
+        mTuner->getConfiguration([&](Result result, const BandConfig& config) {
+            halResult = result;
+            halConfig = config;
+        });
+        EXPECT_EQ(Result::OK, halResult);
+        EXPECT_TRUE(halConfig.antennaConnected);
+    }
 
-     private:
-        // BroadcastRadioHidlTest instance to which callbacks will be notified.
-        BroadcastRadioHidlTest *mParentTest;
-    };
+    EXPECT_NE(nullptr, mTuner.get());
+    return nullptr != mTuner.get();
+}
 
+const BandConfig& BroadcastRadioHalTest::getBand(unsigned idx) {
+    static const BandConfig dummyBandConfig = {};
 
-    /**
-     * Method called by MyCallback when a callback with no status or boolean value is received
-     */
-    void onCallback() {
-        Mutex::Autolock _l(mLock);
-        onCallback_l();
+    if (radioClass != Class::AM_FM) {
+        ALOGD("Not AM/FM radio, returning dummy band config");
+        return dummyBandConfig;
     }
 
-    /**
-     * Method called by MyCallback when hardwareFailure() callback is received
-     */
-    void onHwFailureCallback() {
-        Mutex::Autolock _l(mLock);
-        mHwFailure = true;
-        onCallback_l();
+    EXPECT_GT(mBands.size(), idx);
+    if (mBands.size() <= idx) {
+        ALOGD("Band index out of bound, returning dummy band config");
+        return dummyBandConfig;
     }
 
-    /**
-     * Method called by MyCallback when a callback with status is received
-     */
-    void onResultCallback(Result result) {
-        Mutex::Autolock _l(mLock);
-        mResultCallbackData = result;
-        onCallback_l();
-    }
+    auto& band = mBands[idx];
+    ALOGD("Returning %s band", toString(band.type).c_str());
+    return band;
+}
 
-    /**
-     * Method called by MyCallback when a boolean indication is received
-     */
-    void onBoolCallback(bool result) {
-        Mutex::Autolock _l(mLock);
-        mBoolCallbackData = result;
-        onCallback_l();
-    }
+bool BroadcastRadioHalTest::nextBand() {
+    if (currentBandIndex + 1 >= mBands.size()) return false;
+    currentBandIndex++;
 
+    BandConfig bandCb;
+    EXPECT_TIMEOUT_CALL(*mCallback, configChange, Result::OK, _)
+        .WillOnce(DoAll(SaveArg<1>(&bandCb), testing::Return(ByMove(Void()))));
+    auto hidlResult = mTuner->setConfiguration(getBand(currentBandIndex));
+    EXPECT_EQ(Result::OK, hidlResult);
+    EXPECT_TIMEOUT_CALL_WAIT(*mCallback, configChange, kConfigTimeout);
+    EXPECT_EQ(getBand(currentBandIndex), bandCb);
 
-        BroadcastRadioHidlTest() :
-            mCallbackCalled(false), mBoolCallbackData(false),
-            mResultCallbackData(Result::OK), mHwFailure(false) {}
+    return true;
+}
 
-    void onCallback_l() {
-        if (!mCallbackCalled) {
-            mCallbackCalled = true;
-            mCallbackCond.broadcast();
-        }
-    }
+bool BroadcastRadioHalTest::getProgramList(
+    std::function<void(const hidl_vec<ProgramInfo>& list)> cb) {
+    ProgramListResult getListResult = ProgramListResult::NOT_INITIALIZED;
+    bool isListEmpty = true;
+    auto getListCb = [&](ProgramListResult result, const hidl_vec<ProgramInfo>& list) {
+        ALOGD("getListCb(%s, ProgramInfo[%zu])", toString(result).c_str(), list.size());
+        getListResult = result;
+        if (result != ProgramListResult::OK) return;
+        isListEmpty = (list.size() == 0);
+        if (!isListEmpty) cb(list);
+    };
 
+    // first try...
+    EXPECT_TIMEOUT_CALL(*mCallback, backgroundScanComplete, ProgramListResult::OK)
+        .Times(AnyNumber());
+    auto hidlResult = mTuner->getProgramList({}, getListCb);
+    EXPECT_TRUE(hidlResult.isOk());
+    if (!hidlResult.isOk()) return false;
 
-    bool waitForCallback(nsecs_t reltime = 0) {
-        Mutex::Autolock _l(mLock);
-        nsecs_t endTime = systemTime() + reltime;
-        while (!mCallbackCalled) {
-            if (reltime == 0) {
-                mCallbackCond.wait(mLock);
-            } else {
-                nsecs_t now = systemTime();
-                if (now > endTime) {
-                    return false;
-                }
-                mCallbackCond.waitRelative(mLock, endTime - now);
-            }
-        }
-        return true;
+    if (getListResult == ProgramListResult::NOT_STARTED) {
+        auto result = mTuner->startBackgroundScan();
+        EXPECT_EQ(ProgramListResult::OK, result);
+        getListResult = ProgramListResult::NOT_READY;  // continue as in NOT_READY case
+    }
+    if (getListResult == ProgramListResult::NOT_READY) {
+        EXPECT_TIMEOUT_CALL_WAIT(*mCallback, backgroundScanComplete, kFullScanTimeout);
+
+        // second (last) try...
+        hidlResult = mTuner->getProgramList({}, getListCb);
+        EXPECT_TRUE(hidlResult.isOk());
+        if (!hidlResult.isOk()) return false;
+        EXPECT_EQ(ProgramListResult::OK, getListResult);
     }
 
-    bool getProperties();
-    bool openTuner();
-    bool checkAntenna();
+    return !isListEmpty;
+}
 
-    static const nsecs_t kConfigCallbacktimeoutNs = seconds_to_nanoseconds(10);
-    static const nsecs_t kTuneCallbacktimeoutNs = seconds_to_nanoseconds(30);
+/**
+ * Test IBroadcastRadio::openTuner() method called twice.
+ *
+ * Verifies that:
+ *  - the openTuner method succeeds when called for the second time without
+ *    deleting previous ITuner instance.
+ *
+ * This is a more strict requirement than in 1.0, where a second openTuner
+ * might fail.
+ */
+TEST_P(BroadcastRadioHalTest, OpenTunerTwice) {
+    if (skipped) return;
 
-    sp<IBroadcastRadio> mRadio;
-    Properties mHalProperties;
-    sp<ITuner> mTuner;
-    sp<MyCallback> mTunerCallback;
-    Mutex mLock;
-    Condition mCallbackCond;
-    bool mCallbackCalled;
-    bool mBoolCallbackData;
-    Result mResultCallbackData;
-    bool mHwFailure;
-};
+    ASSERT_TRUE(openTuner());
 
-// A class for test environment setup (kept since this file is a template).
-class BroadcastRadioHidlEnvironment : public ::testing::Environment {
- public:
-    virtual void SetUp() {}
-    virtual void TearDown() {}
-};
+    auto secondTuner = mTuner;
+    mTuner.clear();
 
-bool BroadcastRadioHidlTest::getProperties()
-{
-    if (mHalProperties.bands.size() == 0) {
-        Result halResult = Result::NOT_INITIALIZED;
-        Return<void> hidlReturn =
-                mRadio->getProperties([&](Result result, const Properties& properties) {
-                        halResult = result;
-                        if (result == Result::OK) {
-                            mHalProperties = properties;
-                        }
-                    });
-
-        EXPECT_TRUE(hidlReturn.isOk());
-        EXPECT_EQ(Result::OK, halResult);
-        EXPECT_EQ(Class::AM_FM, mHalProperties.classId);
-        EXPECT_GT(mHalProperties.numTuners, 0u);
-        EXPECT_GT(mHalProperties.bands.size(), 0u);
-    }
-    return mHalProperties.bands.size() > 0;
+    ASSERT_TRUE(openTuner());
 }
 
-bool BroadcastRadioHidlTest::openTuner()
-{
-    if (!getProperties()) {
-        return false;
-    }
-    if (mTuner.get() == nullptr) {
-        Result halResult = Result::NOT_INITIALIZED;
-        auto hidlReturn = mRadio->openTuner(mHalProperties.bands[0], true, mTunerCallback,
-                [&](Result result, const sp<V1_0::ITuner>& tuner) {
-                    halResult = result;
-                    if (result == Result::OK) {
-                        mTuner = ITuner::castFrom(tuner);
-                    }
-                });
-        EXPECT_TRUE(hidlReturn.isOk());
-        EXPECT_EQ(Result::OK, halResult);
-        EXPECT_TRUE(waitForCallback(kConfigCallbacktimeoutNs));
-    }
-    EXPECT_NE(nullptr, mTuner.get());
-    return nullptr != mTuner.get();
-}
+/**
+ * Test tuning to program list entry.
+ *
+ * Verifies that:
+ *  - getProgramList either succeeds or returns NOT_STARTED/NOT_READY status;
+ *  - if the program list is NOT_STARTED, startBackgroundScan makes it completed
+ *    within a full scan timeout and the next getProgramList call succeeds;
+ *  - if the program list is not empty, tuneByProgramSelector call succeeds;
+ *  - getProgramInformation_1_1 returns the same selector as returned in tuneComplete_1_1 call.
+ */
+TEST_P(BroadcastRadioHalTest, TuneFromProgramList) {
+    if (skipped) return;
+    ASSERT_TRUE(openTuner());
 
-bool BroadcastRadioHidlTest::checkAntenna()
-{
-    BandConfig halConfig;
-    Result halResult = Result::NOT_INITIALIZED;
-    Return<void> hidlReturn =
-            mTuner->getConfiguration([&](Result result, const BandConfig& config) {
-                halResult = result;
-                if (result == Result::OK) {
-                    halConfig = config;
-                }
-            });
+    ProgramInfo firstProgram;
+    bool foundAny = false;
+    do {
+        auto getCb = [&](const hidl_vec<ProgramInfo>& list) {
+            // don't copy the whole list out, it might be heavy
+            firstProgram = list[0];
+        };
+        if (getProgramList(getCb)) foundAny = true;
+    } while (nextBand());
+    if (HasFailure()) return;
+    if (!foundAny) {
+        printSkipped("Program list is empty.");
+        return;
+    }
 
-    return ((halResult == Result::OK) && (halConfig.antennaConnected == true));
+    ProgramInfo infoCb;
+    ProgramSelector selCb;
+    EXPECT_CALL(*mCallback, tuneComplete(_, _)).Times(0);
+    EXPECT_TIMEOUT_CALL(*mCallback, tuneComplete_1_1, Result::OK, _)
+        .WillOnce(DoAll(SaveArg<1>(&selCb), testing::Return(ByMove(Void()))));
+    EXPECT_TIMEOUT_CALL(*mCallback, currentProgramInfoChanged, _)
+        .WillOnce(DoAll(SaveArg<0>(&infoCb), testing::Return(ByMove(Void()))));
+    auto tuneResult = mTuner->tuneByProgramSelector(firstProgram.selector);
+    ASSERT_EQ(Result::OK, tuneResult);
+    EXPECT_TIMEOUT_CALL_WAIT(*mCallback, tuneComplete_1_1, kTuneTimeout);
+    EXPECT_TIMEOUT_CALL_WAIT(*mCallback, currentProgramInfoChanged, kEventPropagationTimeout);
+    EXPECT_EQ(firstProgram.selector.primaryId, selCb.primaryId);
+    EXPECT_EQ(infoCb.selector, selCb);
+
+    bool called = false;
+    auto getResult = mTuner->getProgramInformation_1_1([&](Result result, ProgramInfo info) {
+        called = true;
+        EXPECT_EQ(Result::OK, result);
+        EXPECT_EQ(selCb, info.selector);
+    });
+    ASSERT_TRUE(getResult.isOk());
+    ASSERT_TRUE(called);
 }
 
-
 /**
- * Test IBroadcastRadio::getProperties() method
+ * Test that primary vendor identifier isn't used for standard program types.
  *
  * Verifies that:
- *  - the HAL implements the method
- *  - the method returns 0 (no error)
- *  - the implementation class is AM_FM
- *  - the implementation supports at least one tuner
- *  - the implementation supports at one band
+ *  - tuneByProgramSelector fails when VENDORn_PRIMARY is set as a primary
+ *    identifier for program types other than VENDORn.
  */
-TEST_F(BroadcastRadioHidlTest, GetProperties) {
-    EXPECT_TRUE(getProperties());
+TEST_P(BroadcastRadioHalTest, TuneFailsForPrimaryVendor) {
+    if (skipped) return;
+    ASSERT_TRUE(openTuner());
+
+    for (auto ptype : kStandardProgramTypes) {
+        ALOGD("Checking %s...", toString(ptype).c_str());
+        ProgramSelector sel = {};
+        sel.programType = static_cast<uint32_t>(ptype);
+        sel.primaryId.type = static_cast<uint32_t>(IdentifierType::VENDOR_PRIMARY_START);
+
+        auto tuneResult = mTuner->tuneByProgramSelector(sel);
+        ASSERT_NE(Result::OK, tuneResult);
+    }
 }
 
 /**
- * Test IBroadcastRadio::openTuner() method
+ * Test that tune with unknown program type fails.
  *
  * Verifies that:
- *  - the HAL implements the method
- *  - the method returns 0 (no error) and a valid ITuner interface
+ *  - tuneByProgramSelector fails with INVALID_ARGUMENT when unknown program type is passed.
  */
-TEST_F(BroadcastRadioHidlTest, OpenTuner) {
-    EXPECT_TRUE(openTuner());
+TEST_P(BroadcastRadioHalTest, TuneFailsForUnknownProgram) {
+    if (skipped) return;
+    ASSERT_TRUE(openTuner());
+
+    // Program type is 1-based, so 0 will be always invalid.
+    ProgramSelector sel = {};
+    auto tuneResult = mTuner->tuneByProgramSelector(sel);
+    ASSERT_EQ(Result::INVALID_ARGUMENTS, tuneResult);
 }
 
 /**
- * Test ITuner::setConfiguration() and getConfiguration methods
+ * Test cancelling announcement.
  *
  * Verifies that:
- *  - the HAL implements both methods
- *  - the methods return 0 (no error)
- *  - the configuration callback is received within kConfigCallbacktimeoutNs ns
- *  - the configuration read back from HAl has the same class Id
+ *  - cancelAnnouncement succeeds either when there is an announcement or there is none.
  */
-TEST_F(BroadcastRadioHidlTest, SetAndGetConfiguration) {
+TEST_P(BroadcastRadioHalTest, CancelAnnouncement) {
+    if (skipped) return;
     ASSERT_TRUE(openTuner());
-    // test setConfiguration
-    mCallbackCalled = false;
-    Return<Result> hidlResult = mTuner->setConfiguration(mHalProperties.bands[0]);
-    EXPECT_TRUE(hidlResult.isOk());
+
+    auto hidlResult = mTuner->cancelAnnouncement();
     EXPECT_EQ(Result::OK, hidlResult);
-    EXPECT_TRUE(waitForCallback(kConfigCallbacktimeoutNs));
-    EXPECT_EQ(Result::OK, mResultCallbackData);
-
-    // test getConfiguration
-    BandConfig halConfig;
-    Result halResult;
-    Return<void> hidlReturn =
-            mTuner->getConfiguration([&](Result result, const BandConfig& config) {
-                halResult = result;
-                if (result == Result::OK) {
-                    halConfig = config;
-                }
-            });
-    EXPECT_TRUE(hidlReturn.isOk());
-    EXPECT_EQ(Result::OK, halResult);
-    EXPECT_EQ(mHalProperties.bands[0].type, halConfig.type);
 }
 
 /**
- * Test ITuner::scan
+ * Test getImage call with invalid image ID.
  *
  * Verifies that:
- *  - the HAL implements the method
- *  - the method returns 0 (no error)
- *  - the tuned callback is received within kTuneCallbacktimeoutNs ns
+ * - getImage call handles argument 0 gracefully.
  */
-TEST_F(BroadcastRadioHidlTest, Scan) {
-    ASSERT_TRUE(openTuner());
-    ASSERT_TRUE(checkAntenna());
-    // test scan UP
-    mCallbackCalled = false;
-    Return<Result> hidlResult = mTuner->scan(Direction::UP, true);
-    EXPECT_TRUE(hidlResult.isOk());
-    EXPECT_EQ(Result::OK, hidlResult);
-    EXPECT_TRUE(waitForCallback(kTuneCallbacktimeoutNs));
+TEST_P(BroadcastRadioHalTest, GetNoImage) {
+    if (skipped) return;
 
-    // test scan DOWN
-    mCallbackCalled = false;
-    hidlResult = mTuner->scan(Direction::DOWN, true);
-    EXPECT_TRUE(hidlResult.isOk());
-    EXPECT_EQ(Result::OK, hidlResult);
-    EXPECT_TRUE(waitForCallback(kTuneCallbacktimeoutNs));
+    size_t len = 0;
+    auto hidlResult =
+        mRadioModule->getImage(0, [&](hidl_vec<uint8_t> rawImage) { len = rawImage.size(); });
+
+    ASSERT_TRUE(hidlResult.isOk());
+    ASSERT_EQ(0u, len);
 }
 
 /**
- * Test ITuner::step
+ * Test proper image format in metadata.
  *
  * Verifies that:
- *  - the HAL implements the method
- *  - the method returns 0 (no error)
- *  - the tuned callback is received within kTuneCallbacktimeoutNs ns
+ * - all images in metadata are provided out-of-band (by id, not as a binary blob);
+ * - images are available for getImage call.
  */
-TEST_F(BroadcastRadioHidlTest, Step) {
+TEST_P(BroadcastRadioHalTest, OobImagesOnly) {
+    if (skipped) return;
     ASSERT_TRUE(openTuner());
-    ASSERT_TRUE(checkAntenna());
-    // test step UP
-    mCallbackCalled = false;
-    Return<Result> hidlResult = mTuner->step(Direction::UP, true);
-    EXPECT_TRUE(hidlResult.isOk());
-    EXPECT_EQ(Result::OK, hidlResult);
-    EXPECT_TRUE(waitForCallback(kTuneCallbacktimeoutNs));
 
-    // test step DOWN
-    mCallbackCalled = false;
-    hidlResult = mTuner->step(Direction::DOWN, true);
-    EXPECT_TRUE(hidlResult.isOk());
-    EXPECT_EQ(Result::OK, hidlResult);
-    EXPECT_TRUE(waitForCallback(kTuneCallbacktimeoutNs));
+    std::vector<int> imageIds;
+
+    do {
+        auto getCb = [&](const hidl_vec<ProgramInfo>& list) {
+            for (auto&& program : list) {
+                for (auto&& entry : program.base.metadata) {
+                    EXPECT_NE(MetadataType::RAW, entry.type);
+                    if (entry.key != MetadataKey::ICON && entry.key != MetadataKey::ART) continue;
+                    EXPECT_NE(0, entry.intValue);
+                    EXPECT_EQ(0u, entry.rawValue.size());
+                    if (entry.intValue != 0) imageIds.push_back(entry.intValue);
+                }
+            }
+        };
+        getProgramList(getCb);
+    } while (nextBand());
+
+    if (imageIds.size() == 0) {
+        printSkipped("No images found");
+        return;
+    }
+
+    for (auto id : imageIds) {
+        ALOGD("Checking image %d", id);
+
+        size_t len = 0;
+        auto hidlResult =
+            mRadioModule->getImage(id, [&](hidl_vec<uint8_t> rawImage) { len = rawImage.size(); });
+
+        ASSERT_TRUE(hidlResult.isOk());
+        ASSERT_GT(len, 0u);
+    }
 }
 
 /**
- * Test ITuner::tune,  getProgramInformation and cancel methods
+ * Test AnalogForced switch.
  *
  * Verifies that:
- *  - the HAL implements the methods
- *  - the methods return 0 (no error)
- *  - the tuned callback is received within kTuneCallbacktimeoutNs ns after tune()
+ * - setAnalogForced results either with INVALID_STATE, or isAnalogForced replying the same.
  */
-TEST_F(BroadcastRadioHidlTest, TuneAndGetProgramInformationAndCancel) {
+TEST_P(BroadcastRadioHalTest, AnalogForcedSwitch) {
+    if (skipped) return;
     ASSERT_TRUE(openTuner());
-    ASSERT_TRUE(checkAntenna());
-
-    // test tune
-    ASSERT_GT(mHalProperties.bands[0].spacings.size(), 0u);
-    ASSERT_GT(mHalProperties.bands[0].upperLimit, mHalProperties.bands[0].lowerLimit);
-
-    // test scan UP
-    uint32_t lowerLimit = mHalProperties.bands[0].lowerLimit;
-    uint32_t upperLimit = mHalProperties.bands[0].upperLimit;
-    uint32_t spacing = mHalProperties.bands[0].spacings[0];
-
-    uint32_t channel =
-            lowerLimit + (((upperLimit - lowerLimit) / 2 + spacing - 1) / spacing) * spacing;
-    mCallbackCalled = false;
-    mResultCallbackData = Result::NOT_INITIALIZED;
-    Return<Result> hidlResult = mTuner->tune(channel, 0);
-    EXPECT_TRUE(hidlResult.isOk());
-    EXPECT_EQ(Result::OK, hidlResult);
-    EXPECT_TRUE(waitForCallback(kTuneCallbacktimeoutNs));
 
-    // test getProgramInformation
-    ProgramInfo halInfo;
-    Result halResult = Result::NOT_INITIALIZED;
-    Return<void> hidlReturn = mTuner->getProgramInformation_1_1(
-        [&](Result result, const ProgramInfo& info) {
-            halResult = result;
-            if (result == Result::OK) {
-                halInfo = info;
-            }
-        });
-    EXPECT_TRUE(hidlReturn.isOk());
-    EXPECT_EQ(Result::OK, halResult);
-    auto &halInfo_1_1 = halInfo.base;
-    if (mResultCallbackData == Result::OK) {
-        EXPECT_TRUE(halInfo_1_1.tuned);
-        EXPECT_LE(halInfo_1_1.channel, upperLimit);
-        EXPECT_GE(halInfo_1_1.channel, lowerLimit);
-    } else {
-        EXPECT_EQ(false, halInfo_1_1.tuned);
-    }
+    bool forced;
+    Result halIsResult;
+    auto isCb = [&](Result result, bool isForced) {
+        halIsResult = result;
+        forced = isForced;
+    };
 
-    // test cancel
-    mTuner->tune(lowerLimit, 0);
-    hidlResult = mTuner->cancel();
-    EXPECT_TRUE(hidlResult.isOk());
-    EXPECT_EQ(Result::OK, hidlResult);
+    // set analog mode
+    auto setResult = mTuner->setAnalogForced(true);
+    ASSERT_TRUE(setResult.isOk());
+    if (Result::INVALID_STATE == setResult) {
+        // if setter fails, getter should fail too - it means the switch is not supported at all
+        auto isResult = mTuner->isAnalogForced(isCb);
+        ASSERT_TRUE(isResult.isOk());
+        EXPECT_EQ(Result::INVALID_STATE, halIsResult);
+        return;
+    }
+    ASSERT_EQ(Result::OK, setResult);
+
+    // check, if it's analog
+    auto isResult = mTuner->isAnalogForced(isCb);
+    ASSERT_TRUE(isResult.isOk());
+    EXPECT_EQ(Result::OK, halIsResult);
+    ASSERT_TRUE(forced);
+
+    // set digital mode
+    setResult = mTuner->setAnalogForced(false);
+    ASSERT_EQ(Result::OK, setResult);
+
+    // check, if it's digital
+    isResult = mTuner->isAnalogForced(isCb);
+    ASSERT_TRUE(isResult.isOk());
+    EXPECT_EQ(Result::OK, halIsResult);
+    ASSERT_FALSE(forced);
 }
 
+INSTANTIATE_TEST_CASE_P(BroadcastRadioHalTestCases, BroadcastRadioHalTest,
+                        ::testing::Values(Class::AM_FM, Class::SAT, Class::DT));
+
+}  // namespace vts
+}  // namespace V1_1
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
 
 int main(int argc, char** argv) {
-  ::testing::AddGlobalTestEnvironment(new BroadcastRadioHidlEnvironment);
   ::testing::InitGoogleTest(&argc, argv);
   int status = RUN_ALL_TESTS();
   ALOGI("Test result = %d", status);
diff --git a/broadcastradio/1.1/vts/utils/Android.bp b/broadcastradio/1.1/vts/utils/Android.bp
new file mode 100644 (file)
index 0000000..0c7e2a4
--- /dev/null
@@ -0,0 +1,28 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_library_static {
+    name: "android.hardware.broadcastradio@1.1-vts-utils-lib",
+    srcs: [
+        "call-barrier.cpp",
+    ],
+    export_include_dirs: ["include"],
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
+}
diff --git a/broadcastradio/1.1/vts/utils/call-barrier.cpp b/broadcastradio/1.1/vts/utils/call-barrier.cpp
new file mode 100644 (file)
index 0000000..d8c4716
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <broadcastradio-vts-utils/call-barrier.h>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace vts {
+
+using std::lock_guard;
+using std::mutex;
+using std::unique_lock;
+
+void CallBarrier::call() {
+    lock_guard<mutex> lk(mMut);
+    mWasCalled = true;
+    mCond.notify_all();
+}
+
+bool CallBarrier::waitForCall(std::chrono::milliseconds timeout) {
+    unique_lock<mutex> lk(mMut);
+
+    if (mWasCalled) return true;
+
+    auto status = mCond.wait_for(lk, timeout);
+    return status == std::cv_status::no_timeout;
+}
+
+}  // namespace vts
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
diff --git a/broadcastradio/1.1/vts/utils/include/broadcastradio-vts-utils/call-barrier.h b/broadcastradio/1.1/vts/utils/include/broadcastradio-vts-utils/call-barrier.h
new file mode 100644 (file)
index 0000000..462396a
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_CALL_BARRIER
+#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_CALL_BARRIER
+
+#include <chrono>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace vts {
+
+/**
+ * A barrier for thread synchronization, where one should wait for another to
+ * reach a specific point in execution.
+ */
+class CallBarrier {
+   public:
+    /**
+     * Notify the other thread it may continue execution.
+     *
+     * This may be called before the other thread starts waiting on the barrier.
+     */
+    void call();
+
+    /**
+     * Wait for the other thread to reach call() execution point.
+     *
+     * @param timeout a maximum time to wait.
+     * @returns {@code false} if timed out, {@code true} otherwise.
+     */
+    bool waitForCall(std::chrono::milliseconds timeout);
+
+   private:
+    bool mWasCalled = false;
+    std::mutex mMut;
+    std::condition_variable mCond;
+};
+
+}  // namespace vts
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_CALL_BARRIER
diff --git a/broadcastradio/1.1/vts/utils/include/broadcastradio-vts-utils/mock-timeout.h b/broadcastradio/1.1/vts/utils/include/broadcastradio-vts-utils/mock-timeout.h
new file mode 100644 (file)
index 0000000..b0ce088
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_MOCK_TIMEOUT
+#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_MOCK_TIMEOUT
+
+#include <gmock/gmock.h>
+#include <thread>
+
+/**
+ * Common helper objects for gmock timeout extension.
+ *
+ * INTERNAL IMPLEMENTATION - don't use in user code.
+ */
+#define EGMOCK_TIMEOUT_METHOD_DEF_(Method, ...) \
+    std::atomic<bool> egmock_called_##Method;   \
+    std::mutex egmock_mut_##Method;             \
+    std::condition_variable egmock_cond_##Method;
+
+/**
+ * Common method body for gmock timeout extension.
+ *
+ * INTERNAL IMPLEMENTATION - don't use in user code.
+ */
+#define EGMOCK_TIMEOUT_METHOD_BODY_(Method, ...)             \
+    auto ret = egmock_##Method(__VA_ARGS__);                 \
+    {                                                        \
+        std::lock_guard<std::mutex> lk(egmock_mut_##Method); \
+        egmock_called_##Method = true;                       \
+        egmock_cond_##Method.notify_all();                   \
+    }                                                        \
+    return ret;
+
+/**
+ * Gmock MOCK_METHOD0 timeout-capable extension.
+ */
+#define MOCK_TIMEOUT_METHOD0(Method, ...)       \
+    MOCK_METHOD0(egmock_##Method, __VA_ARGS__); \
+    EGMOCK_TIMEOUT_METHOD_DEF_(Method);         \
+    virtual GMOCK_RESULT_(, __VA_ARGS__) Method() { EGMOCK_TIMEOUT_METHOD_BODY_(Method); }
+
+/**
+ * Gmock MOCK_METHOD1 timeout-capable extension.
+ */
+#define MOCK_TIMEOUT_METHOD1(Method, ...)                                                 \
+    MOCK_METHOD1(egmock_##Method, __VA_ARGS__);                                           \
+    EGMOCK_TIMEOUT_METHOD_DEF_(Method);                                                   \
+    virtual GMOCK_RESULT_(, __VA_ARGS__) Method(GMOCK_ARG_(, 1, __VA_ARGS__) egmock_a1) { \
+        EGMOCK_TIMEOUT_METHOD_BODY_(Method, egmock_a1);                                   \
+    }
+
+/**
+ * Gmock MOCK_METHOD2 timeout-capable extension.
+ */
+#define MOCK_TIMEOUT_METHOD2(Method, ...)                                                        \
+    MOCK_METHOD2(egmock_##Method, __VA_ARGS__);                                                  \
+    EGMOCK_TIMEOUT_METHOD_DEF_(Method);                                                          \
+    virtual GMOCK_RESULT_(, __VA_ARGS__)                                                         \
+        Method(GMOCK_ARG_(, 1, __VA_ARGS__) egmock_a1, GMOCK_ARG_(, 2, __VA_ARGS__) egmock_a2) { \
+        EGMOCK_TIMEOUT_METHOD_BODY_(Method, egmock_a1, egmock_a2);                               \
+    }
+
+/**
+ * Gmock EXPECT_CALL timeout-capable extension.
+ *
+ * It has slightly different syntax from the original macro, to make method name accessible.
+ * So, instead of typing
+ *     EXPECT_CALL(account, charge(100, Currency::USD));
+ * you need to inline arguments
+ *     EXPECT_TIMEOUT_CALL(account, charge, 100, Currency::USD);
+ */
+#define EXPECT_TIMEOUT_CALL(obj, Method, ...) \
+    (obj).egmock_called_##Method = false;     \
+    EXPECT_CALL(obj, egmock_##Method(__VA_ARGS__))
+
+/**
+ * Waits for an earlier EXPECT_TIMEOUT_CALL to execute.
+ *
+ * It does not fully support special constraints of the EXPECT_CALL clause, just proceeds when the
+ * first call to a given method comes. For example, in the following code:
+ *     EXPECT_TIMEOUT_CALL(account, charge, 100, _);
+ *     account.charge(50, Currency::USD);
+ *     EXPECT_TIMEOUT_CALL_WAIT(account, charge, 500ms);
+ * the wait clause will just continue, as the charge method was called.
+ *
+ * @param obj object for a call
+ * @param Method the method to wait for
+ * @param timeout the maximum time for waiting
+ */
+#define EXPECT_TIMEOUT_CALL_WAIT(obj, Method, timeout)                      \
+    {                                                                       \
+        std::unique_lock<std::mutex> lk((obj).egmock_mut_##Method);         \
+        if (!(obj).egmock_called_##Method) {                                \
+            auto status = (obj).egmock_cond_##Method.wait_for(lk, timeout); \
+            EXPECT_EQ(std::cv_status::no_timeout, status);                  \
+        }                                                                   \
+    }
+
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_MOCK_TIMEOUT
index 7a315fa..8c65bf6 100644 (file)
@@ -5,5 +5,8 @@ subdirs = [
     "1.0/vts/functional",
     "1.1",
     "1.1/default",
+    "1.1/tests",
+    "1.1/utils",
     "1.1/vts/functional",
+    "1.1/vts/utils",
 ]
index 3869766..0240751 100644 (file)
@@ -6,6 +6,8 @@ subdirs = [
     "device/1.0/default",
     "device/3.2",
     "device/3.2/default",
+    "device/3.3",
+    "device/3.3/default",
     "metadata/3.2",
     "provider/2.4",
     "provider/2.4/default",
index 252d490..ade7260 100644 (file)
@@ -32,13 +32,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.camera.common@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.camera.common@1.0_genc++"],
     generated_headers: ["android.hardware.camera.common@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.camera.common@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index d224483..e707b08 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <string.h>
 #include <stdlib.h>
+#include <unistd.h>
 #include "CameraParameters.h"
 #include <system/graphics.h>
 
index 3ef40c8..b8335f9 100644 (file)
@@ -53,13 +53,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.camera.device@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.camera.device@1.0_genc++"],
     generated_headers: ["android.hardware.camera.device@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.camera.device@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index 1a349d6..e0b31f0 100644 (file)
@@ -26,6 +26,9 @@ cc_library_shared {
     static_libs: [
         "android.hardware.camera.common@1.0-helper"
     ],
+    header_libs: [
+        "media_plugin_headers",
+    ],
     include_dirs: [
         "frameworks/native/include/media/openmax"
     ],
index c53c0d8..a03bbc8 100644 (file)
@@ -377,10 +377,14 @@ camera_memory_t* CameraDevice::sGetMemory(int fd, size_t buf_size, uint_t num_bu
     hidl_handle hidlHandle = mem->mHidlHandle;
     MemoryId id = object->mDeviceCallback->registerMemory(hidlHandle, buf_size, num_bufs);
     mem->handle.mId = id;
-    if (object->mMemoryMap.count(id) != 0) {
-        ALOGE("%s: duplicate MemoryId %d returned by client!", __FUNCTION__, id);
+
+    {
+        Mutex::Autolock _l(object->mMemoryMapLock);
+        if (object->mMemoryMap.count(id) != 0) {
+            ALOGE("%s: duplicate MemoryId %d returned by client!", __FUNCTION__, id);
+        }
+        object->mMemoryMap[id] = mem;
     }
-    object->mMemoryMap[id] = mem;
     mem->handle.mDevice = object;
     return &mem->handle;
 }
@@ -398,7 +402,10 @@ void CameraDevice::sPutMemory(camera_memory_t *data) {
         ALOGE("%s: camera HAL return memory while camera is not opened!", __FUNCTION__);
     }
     device->mDeviceCallback->unregisterMemory(mem->handle.mId);
-    device->mMemoryMap.erase(mem->handle.mId);
+    {
+        Mutex::Autolock _l(device->mMemoryMapLock);
+        device->mMemoryMap.erase(mem->handle.mId);
+    }
     mem->decStrong(mem);
 }
 
@@ -826,7 +833,16 @@ void CameraDevice::releaseRecordingFrameLocked(
         return;
     }
     if (mDevice->ops->release_recording_frame) {
-        CameraHeapMemory* camMemory = mMemoryMap.at(memId);
+        CameraHeapMemory* camMemory;
+        {
+            Mutex::Autolock _l(mMemoryMapLock);
+            auto it = mMemoryMap.find(memId);
+            if (it == mMemoryMap.end() || it->second == nullptr) {
+                ALOGE("%s unknown memoryId %d", __FUNCTION__, memId);
+                return;
+            }
+            camMemory = it->second;
+        }
         if (bufferIndex >= camMemory->mNumBufs) {
             ALOGE("%s: bufferIndex %d exceeds number of buffers %d",
                     __FUNCTION__, bufferIndex, camMemory->mNumBufs);
index c078596..2c980f0 100644 (file)
@@ -165,6 +165,8 @@ private:
 
     sp<ICameraDeviceCallback> mDeviceCallback = nullptr;
 
+    mutable Mutex mMemoryMapLock; // gating access to mMemoryMap
+                                  // must not hold mLock after this lock is acquired
     std::unordered_map<MemoryId, CameraHeapMemory*> mMemoryMap;
 
     bool mMetadataMode = false;
diff --git a/camera/device/1.0/default/OWNERS b/camera/device/1.0/default/OWNERS
new file mode 100644 (file)
index 0000000..18acfee
--- /dev/null
@@ -0,0 +1,6 @@
+cychen@google.com
+epeev@google.com
+etalvala@google.com
+shuzhenwang@google.com
+yinchiayeh@google.com
+zhijunhe@google.com
index dbc80ab..24c2151 100644 (file)
@@ -53,13 +53,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.camera.device@3.2",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.camera.device@3.2_genc++"],
     generated_headers: ["android.hardware.camera.device@3.2_genc++_headers"],
     export_generated_headers: ["android.hardware.camera.device@3.2_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index 637a1e6..295ee32 100644 (file)
@@ -177,7 +177,7 @@ Return<void> CameraDevice::open(const sp<ICameraDeviceCallback>& callback, open_
     if (callback == nullptr) {
         ALOGE("%s: cannot open camera %s. callback is null!",
                 __FUNCTION__, mCameraId.c_str());
-        _hidl_cb(Status::ILLEGAL_ARGUMENT, session);
+        _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
         return Void();
     }
 
@@ -186,7 +186,7 @@ Return<void> CameraDevice::open(const sp<ICameraDeviceCallback>& callback, open_
         // this must be a disconnected camera
         ALOGE("%s: cannot open camera %s. camera is disconnected!",
                 __FUNCTION__, mCameraId.c_str());
-        _hidl_cb(Status::CAMERA_DISCONNECTED, session);
+        _hidl_cb(Status::CAMERA_DISCONNECTED, nullptr);
         return Void();
     } else {
         mLock.lock();
@@ -239,7 +239,7 @@ Return<void> CameraDevice::open(const sp<ICameraDeviceCallback>& callback, open_
             return Void();
         }
 
-        session = new CameraDeviceSession(
+        session = createSession(
                 device, info.static_camera_characteristics, callback);
         if (session == nullptr) {
             ALOGE("%s: camera device session allocation failed", __FUNCTION__);
@@ -255,9 +255,19 @@ Return<void> CameraDevice::open(const sp<ICameraDeviceCallback>& callback, open_
             return Void();
         }
         mSession = session;
+
+        IF_ALOGV() {
+            session->getInterface()->interfaceChain([](
+                ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
+                    ALOGV("Session interface chain:");
+                    for (auto iface : interfaceChain) {
+                        ALOGV("  %s", iface.c_str());
+                    }
+                });
+        }
         mLock.unlock();
     }
-    _hidl_cb(status, session);
+    _hidl_cb(status, session->getInterface());
     return Void();
 }
 
@@ -286,6 +296,13 @@ Return<void> CameraDevice::dumpState(const ::android::hardware::hidl_handle& han
     session->dumpState(handle);
     return Void();
 }
+
+sp<CameraDeviceSession> CameraDevice::createSession(camera3_device_t* device,
+        const camera_metadata_t* deviceInfo,
+        const sp<ICameraDeviceCallback>& callback) {
+    return new CameraDeviceSession(device, deviceInfo, callback);
+}
+
 // End of methods from ::android::hardware::camera::device::V3_2::ICameraDevice.
 
 } // namespace implementation
index fcd134f..d6a04bc 100644 (file)
@@ -49,7 +49,6 @@ CameraDeviceSession::CameraDeviceSession(
         mDerivePostRawSensKey(false),
         mNumPartialResults(1),
         mResultBatcher(callback) {
-
     mDeviceInfo = deviceInfo;
     camera_metadata_entry partialResultsCount =
             mDeviceInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
@@ -328,7 +327,8 @@ void CameraDeviceSession::ResultBatcher::setBatchedStreams(
     mStreamsToBatch = streamsToBatch;
 }
 
-void CameraDeviceSession::ResultBatcher::setResultMetadataQueue(std::shared_ptr<ResultMetadataQueue> q) {
+void CameraDeviceSession::ResultBatcher::setResultMetadataQueue(
+        std::shared_ptr<ResultMetadataQueue> q) {
     Mutex::Autolock _l(mLock);
     mResultMetadataQueue = q;
 }
@@ -387,7 +387,8 @@ void CameraDeviceSession::ResultBatcher::checkAndRemoveFirstBatch() {
     }
 }
 
-void CameraDeviceSession::ResultBatcher::sendBatchShutterCbsLocked(std::shared_ptr<InflightBatch> batch) {
+void CameraDeviceSession::ResultBatcher::sendBatchShutterCbsLocked(
+        std::shared_ptr<InflightBatch> batch) {
     if (batch->mShutterDelivered) {
         ALOGW("%s: batch shutter callback already sent!", __FUNCTION__);
         return;
@@ -441,7 +442,8 @@ void CameraDeviceSession::ResultBatcher::pushStreamBuffer(
     }
 }
 
-void CameraDeviceSession::ResultBatcher::sendBatchBuffersLocked(std::shared_ptr<InflightBatch> batch) {
+void CameraDeviceSession::ResultBatcher::sendBatchBuffersLocked(
+        std::shared_ptr<InflightBatch> batch) {
     sendBatchBuffersLocked(batch, mStreamsToBatch);
 }
 
@@ -736,7 +738,7 @@ void CameraDeviceSession::ResultBatcher::processCaptureResult(CaptureResult& res
 
 // Methods from ::android::hardware::camera::device::V3_2::ICameraDeviceSession follow.
 Return<void> CameraDeviceSession::constructDefaultRequestSettings(
-        RequestTemplate type, constructDefaultRequestSettings_cb _hidl_cb)  {
+        RequestTemplate type, ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb)  {
     Status status = initStatus();
     CameraMetadata outMetadata;
     const camera_metadata_t *rawRequest;
@@ -802,7 +804,8 @@ android_dataspace CameraDeviceSession::mapToLegacyDataspace(
 }
 
 Return<void> CameraDeviceSession::configureStreams(
-        const StreamConfiguration& requestedConfiguration, configureStreams_cb _hidl_cb)  {
+        const StreamConfiguration& requestedConfiguration,
+        ICameraDeviceSession::configureStreams_cb _hidl_cb)  {
     Status status = initStatus();
     HalStreamConfiguration outStreams;
 
@@ -960,13 +963,13 @@ void CameraDeviceSession::updateBufferCaches(const hidl_vec<BufferCache>& caches
 }
 
 Return<void> CameraDeviceSession::getCaptureRequestMetadataQueue(
-    getCaptureRequestMetadataQueue_cb _hidl_cb) {
+    ICameraDeviceSession::getCaptureRequestMetadataQueue_cb _hidl_cb) {
     _hidl_cb(*mRequestMetadataQueue->getDesc());
     return Void();
 }
 
 Return<void> CameraDeviceSession::getCaptureResultMetadataQueue(
-    getCaptureResultMetadataQueue_cb _hidl_cb) {
+    ICameraDeviceSession::getCaptureResultMetadataQueue_cb _hidl_cb) {
     _hidl_cb(*mResultMetadataQueue->getDesc());
     return Void();
 }
@@ -974,7 +977,7 @@ Return<void> CameraDeviceSession::getCaptureResultMetadataQueue(
 Return<void> CameraDeviceSession::processCaptureRequest(
         const hidl_vec<CaptureRequest>& requests,
         const hidl_vec<BufferCache>& cachesToRemove,
-        processCaptureRequest_cb _hidl_cb)  {
+        ICameraDeviceSession::processCaptureRequest_cb _hidl_cb)  {
     updateBufferCaches(cachesToRemove);
 
     uint32_t numRequestProcessed = 0;
index 2fe189f..69e2e2c 100644 (file)
@@ -55,6 +55,8 @@ using ::android::hardware::hidl_string;
 using ::android::sp;
 using ::android::Mutex;
 
+struct Camera3Stream;
+
 /**
  * Function pointer types with C calling convention to
  * use for HAL callback functions.
@@ -69,12 +71,12 @@ extern "C" {
         const camera3_notify_msg_t *);
 }
 
-struct CameraDeviceSession : public ICameraDeviceSession, private camera3_callback_ops  {
+struct CameraDeviceSession : public virtual RefBase, protected camera3_callback_ops  {
 
     CameraDeviceSession(camera3_device_t*,
                         const camera_metadata_t* deviceInfo,
                         const sp<ICameraDeviceCallback>&);
-    ~CameraDeviceSession();
+    virtual ~CameraDeviceSession();
     // Call by CameraDevice to dump active device states
     void dumpState(const native_handle_t* fd);
     // Caller must use this method to check if CameraDeviceSession ctor failed
@@ -83,23 +85,35 @@ struct CameraDeviceSession : public ICameraDeviceSession, private camera3_callba
     void disconnect();
     bool isClosed();
 
-    // Methods from ::android::hardware::camera::device::V3_2::ICameraDeviceSession follow.
+    // Retrieve the HIDL interface, split into its own class to avoid inheritance issues when
+    // dealing with minor version revs and simultaneous implementation and interface inheritance
+    virtual sp<ICameraDeviceSession> getInterface() {
+        return new TrampolineSessionInterface_3_2(this);
+    }
+
+protected:
+
+    // Methods from ::android::hardware::camera::device::V3_2::ICameraDeviceSession follow
+
     Return<void> constructDefaultRequestSettings(
-            RequestTemplate type, constructDefaultRequestSettings_cb _hidl_cb) override;
+            RequestTemplate type,
+            ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb);
     Return<void> configureStreams(
-            const StreamConfiguration& requestedConfiguration, configureStreams_cb _hidl_cb) override;
+            const StreamConfiguration& requestedConfiguration,
+            ICameraDeviceSession::configureStreams_cb _hidl_cb);
     Return<void> getCaptureRequestMetadataQueue(
-        getCaptureRequestMetadataQueue_cb _hidl_cb) override;
+        ICameraDeviceSession::getCaptureRequestMetadataQueue_cb _hidl_cb);
     Return<void> getCaptureResultMetadataQueue(
-        getCaptureResultMetadataQueue_cb _hidl_cb) override;
+        ICameraDeviceSession::getCaptureResultMetadataQueue_cb _hidl_cb);
     Return<void> processCaptureRequest(
             const hidl_vec<CaptureRequest>& requests,
             const hidl_vec<BufferCache>& cachesToRemove,
-            processCaptureRequest_cb _hidl_cb) override;
-    Return<Status> flush() override;
-    Return<void> close() override;
+            ICameraDeviceSession::processCaptureRequest_cb _hidl_cb);
+    Return<Status> flush();
+    Return<void> close();
+
+protected:
 
-private:
     // protecting mClosed/mDisconnected/mInitFail
     mutable Mutex mStateLock;
     // device is closed either
@@ -302,6 +316,52 @@ private:
      */
     static callbacks_process_capture_result_t sProcessCaptureResult;
     static callbacks_notify_t sNotify;
+
+private:
+
+    struct TrampolineSessionInterface_3_2 : public ICameraDeviceSession {
+        TrampolineSessionInterface_3_2(sp<CameraDeviceSession> parent) :
+                mParent(parent) {}
+
+        virtual Return<void> constructDefaultRequestSettings(
+                V3_2::RequestTemplate type,
+                V3_2::ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb) override {
+            return mParent->constructDefaultRequestSettings(type, _hidl_cb);
+        }
+
+        virtual Return<void> configureStreams(
+                const V3_2::StreamConfiguration& requestedConfiguration,
+                V3_2::ICameraDeviceSession::configureStreams_cb _hidl_cb) override {
+            return mParent->configureStreams(requestedConfiguration, _hidl_cb);
+        }
+
+        virtual Return<void> processCaptureRequest(const hidl_vec<V3_2::CaptureRequest>& requests,
+                const hidl_vec<V3_2::BufferCache>& cachesToRemove,
+                V3_2::ICameraDeviceSession::processCaptureRequest_cb _hidl_cb) override {
+            return mParent->processCaptureRequest(requests, cachesToRemove, _hidl_cb);
+        }
+
+        virtual Return<void> getCaptureRequestMetadataQueue(
+                V3_2::ICameraDeviceSession::getCaptureRequestMetadataQueue_cb _hidl_cb) override  {
+            return mParent->getCaptureRequestMetadataQueue(_hidl_cb);
+        }
+
+        virtual Return<void> getCaptureResultMetadataQueue(
+                V3_2::ICameraDeviceSession::getCaptureResultMetadataQueue_cb _hidl_cb) override  {
+            return mParent->getCaptureResultMetadataQueue(_hidl_cb);
+        }
+
+        virtual Return<Status> flush() override {
+            return mParent->flush();
+        }
+
+        virtual Return<void> close() override {
+            return mParent->close();
+        }
+
+    private:
+        sp<CameraDeviceSession> mParent;
+    };
 };
 
 }  // namespace implementation
index 4e86067..9534707 100644 (file)
@@ -80,7 +80,13 @@ struct CameraDevice : public ICameraDevice {
     Return<void> dumpState(const ::android::hardware::hidl_handle& fd) override;
     /* End of Methods from ::android::hardware::camera::device::V3_2::ICameraDevice */
 
-private:
+protected:
+
+    // Overridden by child implementations for returning different versions of CameraDeviceSession
+    virtual sp<CameraDeviceSession> createSession(camera3_device_t*,
+            const camera_metadata_t* deviceInfo,
+            const sp<ICameraDeviceCallback>&);
+
     const sp<CameraModule> mModule;
     const std::string mCameraId;
     // const after ctor
diff --git a/camera/device/3.2/default/OWNERS b/camera/device/3.2/default/OWNERS
new file mode 100644 (file)
index 0000000..18acfee
--- /dev/null
@@ -0,0 +1,6 @@
+cychen@google.com
+epeev@google.com
+etalvala@google.com
+shuzhenwang@google.com
+yinchiayeh@google.com
+zhijunhe@google.com
diff --git a/camera/device/3.3/Android.bp b/camera/device/3.3/Android.bp
new file mode 100644 (file)
index 0000000..2a19991
--- /dev/null
@@ -0,0 +1,72 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+filegroup {
+    name: "android.hardware.camera.device@3.3_hal",
+    srcs: [
+        "types.hal",
+        "ICameraDeviceSession.hal",
+    ],
+}
+
+genrule {
+    name: "android.hardware.camera.device@3.3_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.camera.device@3.3",
+    srcs: [
+        ":android.hardware.camera.device@3.3_hal",
+    ],
+    out: [
+        "android/hardware/camera/device/3.3/types.cpp",
+        "android/hardware/camera/device/3.3/CameraDeviceSessionAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.camera.device@3.3_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.camera.device@3.3",
+    srcs: [
+        ":android.hardware.camera.device@3.3_hal",
+    ],
+    out: [
+        "android/hardware/camera/device/3.3/types.h",
+        "android/hardware/camera/device/3.3/hwtypes.h",
+        "android/hardware/camera/device/3.3/ICameraDeviceSession.h",
+        "android/hardware/camera/device/3.3/IHwCameraDeviceSession.h",
+        "android/hardware/camera/device/3.3/BnHwCameraDeviceSession.h",
+        "android/hardware/camera/device/3.3/BpHwCameraDeviceSession.h",
+        "android/hardware/camera/device/3.3/BsCameraDeviceSession.h",
+    ],
+}
+
+cc_library {
+    name: "android.hardware.camera.device@3.3",
+    defaults: ["hidl-module-defaults"],
+    generated_sources: ["android.hardware.camera.device@3.3_genc++"],
+    generated_headers: ["android.hardware.camera.device@3.3_genc++_headers"],
+    export_generated_headers: ["android.hardware.camera.device@3.3_genc++_headers"],
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hardware.camera.common@1.0",
+        "android.hardware.camera.device@3.2",
+        "android.hardware.graphics.common@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hardware.camera.common@1.0",
+        "android.hardware.camera.device@3.2",
+        "android.hardware.graphics.common@1.0",
+    ],
+}
diff --git a/camera/device/3.3/ICameraDeviceSession.hal b/camera/device/3.3/ICameraDeviceSession.hal
new file mode 100644 (file)
index 0000000..764392f
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera.device@3.3;
+
+import android.hardware.camera.common@1.0::Status;
+import android.hardware.camera.device@3.2::ICameraDeviceSession;
+import android.hardware.camera.device@3.2::StreamConfiguration;
+
+/**
+ * Camera device active session interface.
+ *
+ * Obtained via ICameraDevice::open(), this interface contains the methods to
+ * configure and request captures from an active camera device.
+ *
+ */
+interface ICameraDeviceSession extends @3.2::ICameraDeviceSession {
+
+    /**
+     * configureStreams_3_3:
+     *
+     * Identical to @3.2::ICameraDeviceSession.configureStreams, except that:
+     *
+     * - The output HalStreamConfiguration now contains an overrideDataspace
+     *   field, to be used by the HAL to select a different dataspace for some
+     *   use cases when dealing with the IMPLEMENTATION_DEFINED pixel format.
+     *
+     * Clients may invoke either this method or
+     * @3.2::ICameraDeviceSession.configureStreams() for stream configuration.
+     * This method is recommended for clients to use since it provides more
+     * flexibility.
+     */
+    configureStreams_3_3(StreamConfiguration requestedConfiguration)
+            generates (Status status,
+                    @3.3::HalStreamConfiguration halConfiguration);
+
+};
diff --git a/camera/device/3.3/default/Android.bp b/camera/device/3.3/default/Android.bp
new file mode 100644 (file)
index 0000000..b1e9b46
--- /dev/null
@@ -0,0 +1,30 @@
+cc_library_shared {
+    name: "camera.device@3.3-impl",
+    defaults: ["hidl_defaults"],
+    proprietary: true,
+    srcs: ["CameraDevice.cpp",
+           "CameraDeviceSession.cpp",
+           "convert.cpp"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libutils",
+        "libcutils",
+        "camera.device@3.2-impl",
+        "android.hardware.camera.device@3.2",
+        "android.hardware.camera.device@3.3",
+        "android.hardware.camera.provider@2.4",
+        "android.hardware.graphics.mapper@2.0",
+        "liblog",
+        "libhardware",
+        "libcamera_metadata",
+        "libfmq"
+    ],
+    static_libs: [
+        "android.hardware.camera.common@1.0-helper"
+    ],
+    export_include_dirs: ["."],
+    export_shared_lib_headers: [
+        "libfmq",
+    ]
+}
diff --git a/camera/device/3.3/default/CameraDevice.cpp b/camera/device/3.3/default/CameraDevice.cpp
new file mode 100644 (file)
index 0000000..ce5e1de
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "CamDev@3.3-impl"
+#include <log/log.h>
+
+#include <utils/Vector.h>
+#include <utils/Trace.h>
+#include "CameraDevice_3_3.h"
+#include <include/convert.h>
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V3_3 {
+namespace implementation {
+
+using ::android::hardware::camera::common::V1_0::Status;
+using namespace ::android::hardware::camera::device;
+
+CameraDevice::CameraDevice(
+    sp<CameraModule> module, const std::string& cameraId,
+    const SortedVector<std::pair<std::string, std::string>>& cameraDeviceNames) :
+        V3_2::implementation::CameraDevice(module, cameraId, cameraDeviceNames) {
+}
+
+CameraDevice::~CameraDevice() {
+}
+
+sp<V3_2::implementation::CameraDeviceSession> CameraDevice::createSession(camera3_device_t* device,
+        const camera_metadata_t* deviceInfo,
+        const sp<V3_2::ICameraDeviceCallback>& callback) {
+    sp<CameraDeviceSession> session = new CameraDeviceSession(device, deviceInfo, callback);
+    IF_ALOGV() {
+        session->getInterface()->interfaceChain([](
+            ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
+                ALOGV("Session interface chain:");
+                for (auto iface : interfaceChain) {
+                    ALOGV("  %s", iface.c_str());
+                }
+            });
+    }
+    return session;
+}
+
+// End of methods from ::android::hardware::camera::device::V3_2::ICameraDevice.
+
+} // namespace implementation
+}  // namespace V3_3
+}  // namespace device
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
diff --git a/camera/device/3.3/default/CameraDeviceSession.cpp b/camera/device/3.3/default/CameraDeviceSession.cpp
new file mode 100644 (file)
index 0000000..f877895
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "CamDevSession@3.3-impl"
+#include <android/log.h>
+
+#include <set>
+#include <utils/Trace.h>
+#include <hardware/gralloc.h>
+#include <hardware/gralloc1.h>
+#include "CameraDeviceSession.h"
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V3_3 {
+namespace implementation {
+
+CameraDeviceSession::CameraDeviceSession(
+    camera3_device_t* device,
+    const camera_metadata_t* deviceInfo,
+    const sp<V3_2::ICameraDeviceCallback>& callback) :
+        V3_2::implementation::CameraDeviceSession(device, deviceInfo, callback) {
+}
+
+CameraDeviceSession::~CameraDeviceSession() {
+}
+
+Return<void> CameraDeviceSession::configureStreams_3_3(
+        const StreamConfiguration& requestedConfiguration,
+        ICameraDeviceSession::configureStreams_3_3_cb _hidl_cb)  {
+    Status status = initStatus();
+    HalStreamConfiguration outStreams;
+
+    // hold the inflight lock for entire configureStreams scope since there must not be any
+    // inflight request/results during stream configuration.
+    Mutex::Autolock _l(mInflightLock);
+    if (!mInflightBuffers.empty()) {
+        ALOGE("%s: trying to configureStreams while there are still %zu inflight buffers!",
+                __FUNCTION__, mInflightBuffers.size());
+        _hidl_cb(Status::INTERNAL_ERROR, outStreams);
+        return Void();
+    }
+
+    if (!mInflightAETriggerOverrides.empty()) {
+        ALOGE("%s: trying to configureStreams while there are still %zu inflight"
+                " trigger overrides!", __FUNCTION__,
+                mInflightAETriggerOverrides.size());
+        _hidl_cb(Status::INTERNAL_ERROR, outStreams);
+        return Void();
+    }
+
+    if (!mInflightRawBoostPresent.empty()) {
+        ALOGE("%s: trying to configureStreams while there are still %zu inflight"
+                " boost overrides!", __FUNCTION__,
+                mInflightRawBoostPresent.size());
+        _hidl_cb(Status::INTERNAL_ERROR, outStreams);
+        return Void();
+    }
+
+    if (status != Status::OK) {
+        _hidl_cb(status, outStreams);
+        return Void();
+    }
+
+    camera3_stream_configuration_t stream_list;
+    hidl_vec<camera3_stream_t*> streams;
+
+    stream_list.operation_mode = (uint32_t) requestedConfiguration.operationMode;
+    stream_list.num_streams = requestedConfiguration.streams.size();
+    streams.resize(stream_list.num_streams);
+    stream_list.streams = streams.data();
+
+    for (uint32_t i = 0; i < stream_list.num_streams; i++) {
+        int id = requestedConfiguration.streams[i].id;
+
+        if (mStreamMap.count(id) == 0) {
+            Camera3Stream stream;
+            V3_2::implementation::convertFromHidl(requestedConfiguration.streams[i], &stream);
+            mStreamMap[id] = stream;
+            mStreamMap[id].data_space = mapToLegacyDataspace(
+                    mStreamMap[id].data_space);
+            mCirculatingBuffers.emplace(stream.mId, CirculatingBuffers{});
+        } else {
+            // width/height/format must not change, but usage/rotation might need to change
+            if (mStreamMap[id].stream_type !=
+                    (int) requestedConfiguration.streams[i].streamType ||
+                    mStreamMap[id].width != requestedConfiguration.streams[i].width ||
+                    mStreamMap[id].height != requestedConfiguration.streams[i].height ||
+                    mStreamMap[id].format != (int) requestedConfiguration.streams[i].format ||
+                    mStreamMap[id].data_space !=
+                            mapToLegacyDataspace( static_cast<android_dataspace_t> (
+                                    requestedConfiguration.streams[i].dataSpace))) {
+                ALOGE("%s: stream %d configuration changed!", __FUNCTION__, id);
+                _hidl_cb(Status::INTERNAL_ERROR, outStreams);
+                return Void();
+            }
+            mStreamMap[id].rotation = (int) requestedConfiguration.streams[i].rotation;
+            mStreamMap[id].usage = (uint32_t) requestedConfiguration.streams[i].usage;
+        }
+        streams[i] = &mStreamMap[id];
+    }
+
+    ATRACE_BEGIN("camera3->configure_streams");
+    status_t ret = mDevice->ops->configure_streams(mDevice, &stream_list);
+    ATRACE_END();
+
+    // In case Hal returns error most likely it was not able to release
+    // the corresponding resources of the deleted streams.
+    if (ret == OK) {
+        // delete unused streams, note we do this after adding new streams to ensure new stream
+        // will not have the same address as deleted stream, and HAL has a chance to reference
+        // the to be deleted stream in configure_streams call
+        for(auto it = mStreamMap.begin(); it != mStreamMap.end();) {
+            int id = it->first;
+            bool found = false;
+            for (const auto& stream : requestedConfiguration.streams) {
+                if (id == stream.id) {
+                    found = true;
+                    break;
+                }
+            }
+            if (!found) {
+                // Unmap all buffers of deleted stream
+                // in case the configuration call succeeds and HAL
+                // is able to release the corresponding resources too.
+                cleanupBuffersLocked(id);
+                it = mStreamMap.erase(it);
+            } else {
+                ++it;
+            }
+        }
+
+        // Track video streams
+        mVideoStreamIds.clear();
+        for (const auto& stream : requestedConfiguration.streams) {
+            if (stream.streamType == V3_2::StreamType::OUTPUT &&
+                stream.usage &
+                    graphics::common::V1_0::BufferUsage::VIDEO_ENCODER) {
+                mVideoStreamIds.push_back(stream.id);
+            }
+        }
+        mResultBatcher.setBatchedStreams(mVideoStreamIds);
+    }
+
+    if (ret == -EINVAL) {
+        status = Status::ILLEGAL_ARGUMENT;
+    } else if (ret != OK) {
+        status = Status::INTERNAL_ERROR;
+    } else {
+        convertToHidl(stream_list, &outStreams);
+        mFirstRequest = true;
+    }
+
+    _hidl_cb(status, outStreams);
+    return Void();
+}
+
+} // namespace implementation
+}  // namespace V3_3
+}  // namespace device
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
diff --git a/camera/device/3.3/default/CameraDeviceSession.h b/camera/device/3.3/default/CameraDeviceSession.h
new file mode 100644 (file)
index 0000000..dd52b35
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_CAMERA_DEVICE_V3_3_CAMERADEVICE3SESSION_H
+#define ANDROID_HARDWARE_CAMERA_DEVICE_V3_3_CAMERADEVICE3SESSION_H
+
+#include <android/hardware/camera/device/3.2/ICameraDevice.h>
+#include <android/hardware/camera/device/3.3/ICameraDeviceSession.h>
+#include <../../3.2/default/CameraDeviceSession.h>
+#include <fmq/MessageQueue.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <include/convert.h>
+#include <deque>
+#include <map>
+#include <unordered_map>
+#include "CameraMetadata.h"
+#include "HandleImporter.h"
+#include "hardware/camera3.h"
+#include "hardware/camera_common.h"
+#include "utils/Mutex.h"
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V3_3 {
+namespace implementation {
+
+using namespace ::android::hardware::camera::device;
+using ::android::hardware::camera::device::V3_2::CaptureRequest;
+using ::android::hardware::camera::device::V3_2::StreamConfiguration;
+using ::android::hardware::camera::device::V3_3::HalStreamConfiguration;
+using ::android::hardware::camera::device::V3_3::ICameraDeviceSession;
+using ::android::hardware::camera::common::V1_0::Status;
+using ::android::hardware::camera::common::V1_0::helper::HandleImporter;
+using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::MessageQueue;
+using ::android::hardware::MQDescriptorSync;
+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_2::implementation::CameraDeviceSession {
+
+    CameraDeviceSession(camera3_device_t*,
+            const camera_metadata_t* deviceInfo,
+            const sp<V3_2::ICameraDeviceCallback>&);
+    virtual ~CameraDeviceSession();
+
+    virtual sp<V3_2::ICameraDeviceSession> getInterface() override {
+        return new TrampolineSessionInterface_3_3(this);
+    }
+
+protected:
+    // Methods from v3.2 and earlier will trampoline to inherited implementation
+
+    // New methods for v3.3
+
+    Return<void> configureStreams_3_3(
+            const StreamConfiguration& requestedConfiguration,
+            ICameraDeviceSession::configureStreams_3_3_cb _hidl_cb);
+private:
+
+    struct TrampolineSessionInterface_3_3 : public ICameraDeviceSession {
+        TrampolineSessionInterface_3_3(sp<CameraDeviceSession> parent) :
+                mParent(parent) {}
+
+        virtual Return<void> constructDefaultRequestSettings(
+                V3_2::RequestTemplate type,
+                V3_3::ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb) override {
+            return mParent->constructDefaultRequestSettings(type, _hidl_cb);
+        }
+
+        virtual Return<void> configureStreams(
+                const V3_2::StreamConfiguration& requestedConfiguration,
+                V3_3::ICameraDeviceSession::configureStreams_cb _hidl_cb) override {
+            return mParent->configureStreams(requestedConfiguration, _hidl_cb);
+        }
+
+        virtual Return<void> processCaptureRequest(const hidl_vec<V3_2::CaptureRequest>& requests,
+                const hidl_vec<V3_2::BufferCache>& cachesToRemove,
+                V3_3::ICameraDeviceSession::processCaptureRequest_cb _hidl_cb) override {
+            return mParent->processCaptureRequest(requests, cachesToRemove, _hidl_cb);
+        }
+
+        virtual Return<void> getCaptureRequestMetadataQueue(
+                V3_3::ICameraDeviceSession::getCaptureRequestMetadataQueue_cb _hidl_cb) override  {
+            return mParent->getCaptureRequestMetadataQueue(_hidl_cb);
+        }
+
+        virtual Return<void> getCaptureResultMetadataQueue(
+                V3_3::ICameraDeviceSession::getCaptureResultMetadataQueue_cb _hidl_cb) override  {
+            return mParent->getCaptureResultMetadataQueue(_hidl_cb);
+        }
+
+        virtual Return<Status> flush() override {
+            return mParent->flush();
+        }
+
+        virtual Return<void> close() override {
+            return mParent->close();
+        }
+
+        virtual Return<void> configureStreams_3_3(
+                const StreamConfiguration& requestedConfiguration, configureStreams_3_3_cb _hidl_cb) override {
+            return mParent->configureStreams_3_3(requestedConfiguration, _hidl_cb);
+        }
+
+    private:
+        sp<CameraDeviceSession> mParent;
+    };
+};
+
+}  // namespace implementation
+}  // namespace V3_3
+}  // namespace device
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_CAMERA_DEVICE_V3_3_CAMERADEVICE3SESSION_H
diff --git a/camera/device/3.3/default/CameraDevice_3_3.h b/camera/device/3.3/default/CameraDevice_3_3.h
new file mode 100644 (file)
index 0000000..18b3fe8
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * 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_CAMERA_DEVICE_V3_3_CAMERADEVICE_H
+#define ANDROID_HARDWARE_CAMERA_DEVICE_V3_3_CAMERADEVICE_H
+
+#include "utils/Mutex.h"
+#include "CameraModule.h"
+#include "CameraMetadata.h"
+#include "CameraDeviceSession.h"
+#include <../../3.2/default/CameraDevice_3_2.h>
+
+#include <android/hardware/camera/device/3.2/ICameraDevice.h>
+#include <hidl/Status.h>
+#include <hidl/MQDescriptor.h>
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V3_3 {
+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_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/*
+ * The camera device HAL implementation is opened lazily (via the open call)
+ */
+struct CameraDevice : public V3_2::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_2
+    CameraDevice(sp<CameraModule> module,
+                 const std::string& cameraId,
+                 const SortedVector<std::pair<std::string, std::string>>& cameraDeviceNames);
+    ~CameraDevice();
+
+protected:
+    virtual sp<V3_2::implementation::CameraDeviceSession> createSession(camera3_device_t*,
+            const camera_metadata_t* deviceInfo,
+            const sp<V3_2::ICameraDeviceCallback>&) override;
+
+};
+
+}  // namespace implementation
+}  // namespace V3_3
+}  // namespace device
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_CAMERA_DEVICE_V3_3_CAMERADEVICE_H
diff --git a/camera/device/3.3/default/OWNERS b/camera/device/3.3/default/OWNERS
new file mode 100644 (file)
index 0000000..18acfee
--- /dev/null
@@ -0,0 +1,6 @@
+cychen@google.com
+epeev@google.com
+etalvala@google.com
+shuzhenwang@google.com
+yinchiayeh@google.com
+zhijunhe@google.com
diff --git a/camera/device/3.3/default/convert.cpp b/camera/device/3.3/default/convert.cpp
new file mode 100644 (file)
index 0000000..dae190b
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * 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 "android.hardware.camera.device@3.3-convert-impl"
+#include <log/log.h>
+
+#include "include/convert.h"
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V3_3 {
+namespace implementation {
+
+using ::android::hardware::graphics::common::V1_0::Dataspace;
+using ::android::hardware::graphics::common::V1_0::PixelFormat;
+using ::android::hardware::camera::device::V3_2::BufferUsageFlags;
+
+void convertToHidl(const Camera3Stream* src, HalStream* dst) {
+    dst->overrideDataSpace = src->data_space;
+    dst->v3_2.id = src->mId;
+    dst->v3_2.overrideFormat = (PixelFormat) src->format;
+    dst->v3_2.maxBuffers = src->max_buffers;
+    if (src->stream_type == CAMERA3_STREAM_OUTPUT) {
+        dst->v3_2.consumerUsage = (BufferUsageFlags)0;
+        dst->v3_2.producerUsage = (BufferUsageFlags)src->usage;
+    } else if (src->stream_type == CAMERA3_STREAM_INPUT) {
+        dst->v3_2.producerUsage = (BufferUsageFlags)0;
+        dst->v3_2.consumerUsage = (BufferUsageFlags)src->usage;
+    } else {
+        //Should not reach here per current HIDL spec, but we might end up adding
+        // bi-directional stream to HIDL.
+        ALOGW("%s: Stream type %d is not currently supported!",
+                __FUNCTION__, src->stream_type);
+    }
+}
+
+void convertToHidl(const camera3_stream_configuration_t& src, HalStreamConfiguration* dst) {
+    dst->streams.resize(src.num_streams);
+    for (uint32_t i = 0; i < src.num_streams; i++) {
+        convertToHidl(static_cast<Camera3Stream*>(src.streams[i]), &dst->streams[i]);
+    }
+    return;
+}
+
+}  // namespace implementation
+}  // namespace V3_3
+}  // namespace device
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
diff --git a/camera/device/3.3/default/include/convert.h b/camera/device/3.3/default/include/convert.h
new file mode 100644 (file)
index 0000000..23bb797
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * 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 HARDWARE_INTERFACES_CAMERA_DEVICE_V3_3_DEFAULT_INCLUDE_CONVERT_H_
+
+#define HARDWARE_INTERFACES_CAMERA_DEVICE_V3_3_DEFAULT_INCLUDE_CONVERT_H_
+
+#include <set>
+
+
+#include <android/hardware/graphics/common/1.0/types.h>
+#include <android/hardware/camera/device/3.3/types.h>
+#include "hardware/camera3.h"
+#include "../../3.2/default/include/convert.h"
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V3_3 {
+namespace implementation {
+
+using ::android::hardware::camera::device::V3_2::implementation::Camera3Stream;
+
+void convertToHidl(const Camera3Stream* src, HalStream* dst);
+
+void convertToHidl(const camera3_stream_configuration_t& src, HalStreamConfiguration* dst);
+
+}  // namespace implementation
+}  // namespace V3_3
+}  // namespace device
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HARDWARE_INTERFACES_CAMERA_DEVICE_V3_3_DEFAULT_INCLUDE_CONVERT_H_
diff --git a/camera/device/3.3/types.hal b/camera/device/3.3/types.hal
new file mode 100644 (file)
index 0000000..b4ad702
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera.device@3.3;
+
+import android.hardware.camera.device@3.2::DataspaceFlags;
+import android.hardware.camera.device@3.2::HalStream;
+
+/**
+ * HalStream:
+ *
+ * The camera HAL's response to each requested stream configuration.
+ *
+ * This version extends the @3.2 HalStream with the overrideDataspace
+ * field
+ */
+struct HalStream {
+    /**
+     * The definition of HalStream from the prior version.
+     */
+    @3.2::HalStream v3_2;
+
+    /**
+     * An override dataSpace for the buffers in this stream.
+     *
+     * The HAL must respect the requested dataSpace in Stream unless it is
+     * IMPLEMENTATION_DEFINED, in which case the override dataSpace here must be
+     * used by the client instead, for this stream. This allows cross-platform
+     * HALs to use a specific dataSpace since IMPLEMENTATION_DEFINED formats often
+     * require device-specific information for correct selection. In all other cases, the
+     * overrideFormat must match the requested format.
+     */
+    DataspaceFlags overrideDataSpace;
+};
+
+/**
+ * HalStreamConfiguration:
+ *
+ * Identical to @3.2::HalStreamConfiguration, except that it contains @3.3::HalStream entries.
+ *
+ */
+struct HalStreamConfiguration {
+    vec<HalStream> streams;
+};
index 6e5703a..9f60781 100644 (file)
@@ -33,6 +33,8 @@ support for ICameraDevice@1.0 will be removed with the Android R release.
 This HAL interface version only allows support at the LEGACY level for the
 android.hardware.camera2 API.
 
+Added in Android 8.0.
+
 Subsidiary HALs:
 
 #### ICameraDevice1PreviewCallback.hal@1.0:
@@ -62,6 +64,8 @@ The open() method actually opens the camera device for use, returning a Session
 interface for operating the active camera. It takes a Callback interface as an
 argument.
 
+Added in Android 8.0.
+
 Subsidiary HALs:
 
 #### ICameraDevice3Session.hal@3.2:
@@ -74,3 +78,12 @@ capture requests to it.
 
 Callback interface for sending completed captures and other asynchronous events
 from tehe HAL to the client.
+
+### ICameraDevice.hal@3.3:
+
+A minor revision to the ICameraDevice.hal@3.2.
+
+  - Adds support for overriding the output dataspace of a stream, which was
+    supported in the legacy camera HAL.
+
+Added in Android 8.1.
index 707b521..3c4b5e9 100644 (file)
@@ -32,13 +32,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.camera.metadata@3.2",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.camera.metadata@3.2_genc++"],
     generated_headers: ["android.hardware.camera.metadata@3.2_genc++_headers"],
     export_generated_headers: ["android.hardware.camera.metadata@3.2_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index 36a726a..82a3a78 100644 (file)
@@ -42,13 +42,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.camera.provider@2.4",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.camera.provider@2.4_genc++"],
     generated_headers: ["android.hardware.camera.provider@2.4_genc++_headers"],
     export_generated_headers: ["android.hardware.camera.provider@2.4_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index f2a2d2e..c0b3591 100644 (file)
@@ -11,8 +11,10 @@ cc_library_shared {
         "libcutils",
         "android.hardware.camera.device@1.0",
         "android.hardware.camera.device@3.2",
+        "android.hardware.camera.device@3.3",
         "camera.device@1.0-impl",
         "camera.device@3.2-impl",
+        "camera.device@3.3-impl",
         "android.hardware.camera.provider@2.4",
         "android.hardware.camera.common@1.0",
         "android.hardware.graphics.mapper@2.0",
@@ -43,6 +45,7 @@ cc_binary {
         "libutils",
         "android.hardware.camera.device@1.0",
         "android.hardware.camera.device@3.2",
+        "android.hardware.camera.device@3.3",
         "android.hardware.camera.provider@2.4",
         "android.hardware.camera.common@1.0",
     ],
index 19f7bdd..d50168a 100644 (file)
  */
 
 #define LOG_TAG "CamProvider@2.4-impl"
+//#define LOG_NDEBUG 0
 #include <android/log.h>
 
 #include "CameraProvider.h"
 #include "CameraDevice_1_0.h"
-#include "CameraDevice_3_2.h"
+#include "CameraDevice_3_3.h"
+#include <cutils/properties.h>
 #include <string.h>
 #include <utils/Trace.h>
 
@@ -36,6 +38,7 @@ const char *kLegacyProviderName = "legacy/0";
 // "device@<version>/legacy/<id>"
 const std::regex kDeviceNameRE("device@([0-9]+\\.[0-9]+)/legacy/(.+)");
 const char *kHAL3_2 = "3.2";
+const char *kHAL3_3 = "3.3";
 const char *kHAL1_0 = "1.0";
 const int kMaxCameraDeviceNameLen = 128;
 const int kMaxCameraIdLen = 16;
@@ -140,8 +143,9 @@ int CameraProvider::getCameraDeviceVersion(const hidl_string& deviceName) {
     if (!match) {
         return -1;
     }
-    if (deviceVersion == kHAL3_2) {
-        // maybe switched to 3.4 or define the hidl version enum later
+    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;
@@ -158,10 +162,12 @@ std::string CameraProvider::getHidlDeviceName(
             deviceVersion != CAMERA_DEVICE_API_VERSION_3_4 ) {
         return hidl_string("");
     }
-    const char* versionStr = (deviceVersion == CAMERA_DEVICE_API_VERSION_1_0) ? kHAL1_0 : kHAL3_2;
+    bool isV1 = deviceVersion == CAMERA_DEVICE_API_VERSION_1_0;
+    int versionMajor = isV1 ? 1 : 3;
+    int versionMinor = isV1 ? 0 : mPreferredHal3MinorVersion;
     char deviceName[kMaxCameraDeviceNameLen];
-    snprintf(deviceName, sizeof(deviceName), "device@%s/legacy/%s",
-            versionStr, cameraId.c_str());
+    snprintf(deviceName, sizeof(deviceName), "device@%d.%d/legacy/%s",
+            versionMajor, versionMinor, cameraId.c_str());
     return deviceName;
 }
 
@@ -205,6 +211,19 @@ bool CameraProvider::initialize() {
         return true;
     }
 
+    mPreferredHal3MinorVersion = property_get_int32("ro.camera.wrapper.hal3TrebleMinorVersion", 3);
+    ALOGV("Preferred HAL 3 minor version is %d", mPreferredHal3MinorVersion);
+    switch(mPreferredHal3MinorVersion) {
+        case 2:
+        case 3:
+            // OK
+            break;
+        default:
+            ALOGW("Unknown minor camera device HAL version %d in property "
+                    "'camera.wrapper.hal3TrebleMinorVersion', defaulting to 3", mPreferredHal3MinorVersion);
+            mPreferredHal3MinorVersion = 3;
+    }
+
     mNumberOfLegacyCameras = mModule->getNumberOfCameras();
     for (int i = 0; i < mNumberOfLegacyCameras; i++) {
         struct camera_info info;
@@ -461,23 +480,45 @@ Return<void> CameraProvider::getCameraDeviceInterface_V3_x(
         return Void();
     }
 
-    sp<android::hardware::camera::device::V3_2::implementation::CameraDevice> device =
-            new android::hardware::camera::device::V3_2::implementation::CameraDevice(
+    // 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.
+    sp<android::hardware::camera::device::V3_2::ICameraDevice> device;
+    switch (mPreferredHal3MinorVersion) {
+        case 2: { // Map legacy camera device v3 HAL to Treble camera device HAL v3.2
+            ALOGV("Constructing v3.2 camera device");
+            sp<android::hardware::camera::device::V3_2::implementation::CameraDevice> deviceImpl =
+                    new android::hardware::camera::device::V3_2::implementation::CameraDevice(
                     mModule, cameraId, mCameraDeviceNames);
-
-    if (device == nullptr) {
-        ALOGE("%s: cannot allocate camera device for id %s", __FUNCTION__, cameraId.c_str());
-        _hidl_cb(Status::INTERNAL_ERROR, nullptr);
-        return Void();
-    }
-
-    if (device->isInitFailed()) {
-        ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraId.c_str());
-        device = nullptr;
-        _hidl_cb(Status::INTERNAL_ERROR, nullptr);
-        return Void();
+            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<android::hardware::camera::device::V3_2::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);
     return Void();
 }
index 75971fa..4980711 100644 (file)
@@ -82,6 +82,8 @@ private:
     // (cameraId string, hidl device name) pairs
     SortedVector<std::pair<std::string, std::string>> mCameraDeviceNames;
 
+    int mPreferredHal3MinorVersion;
+
     // Must be queried before using any APIs.
     // APIs will only work when this returns true
     bool mInitFailed;
@@ -91,13 +93,13 @@ private:
     bool setUpVendorTags();
     int checkCameraVersion(int id, camera_info info);
 
+    // create HIDL device name from camera ID and legacy device version
+    std::string getHidlDeviceName(std::string cameraId, int deviceVersion);
+
     // 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);
 
-    // create HIDL device name from camera ID and device version
-    static std::string getHidlDeviceName(std::string cameraId, int deviceVersion);
-
     // convert conventional HAL status to HIDL Status
     static Status getHidlStatus(int);
 
diff --git a/camera/provider/2.4/default/OWNERS b/camera/provider/2.4/default/OWNERS
new file mode 100644 (file)
index 0000000..18acfee
--- /dev/null
@@ -0,0 +1,6 @@
+cychen@google.com
+epeev@google.com
+etalvala@google.com
+shuzhenwang@google.com
+yinchiayeh@google.com
+zhijunhe@google.com
diff --git a/camera/provider/2.4/vts/OWNERS b/camera/provider/2.4/vts/OWNERS
new file mode 100644 (file)
index 0000000..003fe71
--- /dev/null
@@ -0,0 +1,11 @@
+# Camera team
+cychen@google.com
+epeev@google.com
+etalvala@google.com
+shuzhenwang@google.com
+yinchiayeh@google.com
+zhijunhe@google.com
+
+# VTS team
+yim@google.com
+zhuoyao@google.com
index 439fe3d..81d3de1 100644 (file)
 
 cc_test {
     name: "VtsHalCameraProviderV2_4TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalCameraProviderV2_4TargetTest.cpp"],
+
+    // TODO(b/64437680): Assume these are always available on the device.
     shared_libs: [
-        "liblog",
-        "libhidlbase",
-        "libhidltransport",
-        "libcutils",
-        "libutils",
-        "android.hardware.camera.provider@2.4",
-        "android.hardware.camera.device@3.2",
-        "android.hardware.camera.device@1.0",
-        "libcamera_metadata",
         "libbinder",
+        "libcamera_metadata",
+        "libfmq",
         "libgui",
         "libui",
-        "libfmq",
     ],
+
+    // Statically link to libs not guaranteed to be present on the device.
     static_libs: [
-        "VtsHalHidlTargetTestBase",
-        "libgrallocusage",
+        "android.hardware.camera.common@1.0",
         "android.hardware.camera.common@1.0-helper",
-    ],
-    cflags: [
-        "-O0",
-        "-g",
+        "android.hardware.camera.device@1.0",
+        "android.hardware.camera.device@3.2",
+        "android.hardware.camera.device@3.3",
+        "android.hardware.camera.provider@2.4",
+        "android.hardware.graphics.common@1.0",
+        "android.hardware.graphics.mapper@2.0",
+        "libgrallocusage",
     ],
 }
index 6f04efc..e4cf9af 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <android/hardware/camera/device/1.0/ICameraDevice.h>
 #include <android/hardware/camera/device/3.2/ICameraDevice.h>
+#include <android/hardware/camera/device/3.3/ICameraDeviceSession.h>
 #include <android/hardware/camera/provider/2.4/ICameraProvider.h>
 #include <android/hidl/manager/1.0/IServiceManager.h>
 #include <binder/MemoryHeapBase.h>
@@ -43,6 +44,7 @@
 #include <ui/GraphicBuffer.h>
 
 #include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
 
 using ::android::hardware::Return;
 using ::android::hardware::Void;
@@ -100,8 +102,8 @@ using ::android::hardware::kSynchronizedReadWrite;
 using ResultMetadataQueue = MessageQueue<uint8_t, kSynchronizedReadWrite>;
 using ::android::hidl::manager::V1_0::IServiceManager;
 
-const char kCameraPassthroughServiceName[] = "legacy/0";
-const char *kProviderFQName = "android.hardware.camera.provider@2.4::ICameraProvider";
+using namespace ::android::hardware::camera;
+
 const uint32_t kMaxPreviewWidth = 1920;
 const uint32_t kMaxPreviewHeight = 1080;
 const uint32_t kMaxVideoWidth = 4096;
@@ -126,8 +128,10 @@ struct AvailableZSLInputOutput {
 namespace {
     // "device@<version>/legacy/<id>"
     const char *kDeviceNameRE = "device@([0-9]+\\.[0-9]+)/%s/(.+)";
+    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_3 = "3.3";
     const char *kHAL3_2 = "3.2";
     const char *kHAL1_0 = "1.0";
 
@@ -160,8 +164,9 @@ namespace {
             return -1;
         }
 
-        if (version.compare(kHAL3_2) == 0) {
-            // maybe switched to 3.4 or define the hidl version enumlater
+        if (version.compare(kHAL3_3) == 0) {
+            return CAMERA_DEVICE_API_VERSION_3_3;
+        } else if (version.compare(kHAL3_2) == 0) {
             return CAMERA_DEVICE_API_VERSION_3_2;
         } else if (version.compare(kHAL1_0) == 0) {
             return CAMERA_DEVICE_API_VERSION_1_0;
@@ -231,66 +236,26 @@ namespace {
 }
 
 // Test environment for camera
-class CameraHidlEnvironment : public ::testing::Environment {
-public:
+class CameraHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
     // get the test environment singleton
     static CameraHidlEnvironment* Instance() {
         static CameraHidlEnvironment* instance = new CameraHidlEnvironment;
         return instance;
     }
 
-    virtual void SetUp() override;
-    virtual void TearDown() override;
+    virtual void HidlSetUp() override { ALOGI("SetUp CameraHidlEnvironment"); }
 
-    std::unordered_map<std::string, sp<ICameraProvider> > mProviders;
+    virtual void HidlTearDown() override { ALOGI("TearDown CameraHidlEnvironment"); }
 
-private:
+    virtual void registerTestServices() override { registerTestService<ICameraProvider>(); }
+
+   private:
     CameraHidlEnvironment() {}
 
     GTEST_DISALLOW_COPY_AND_ASSIGN_(CameraHidlEnvironment);
 };
 
-void CameraHidlEnvironment::SetUp() {
-    sp<IServiceManager> manager = IServiceManager::getService();
-    ASSERT_NE(manager, nullptr);
-
-    manager->listByInterface(kProviderFQName,
-                             [this](const hidl_vec<hidl_string> &registered) {
-        std::string name;
-        uint32_t id;
-        sp<ICameraProvider> provider = nullptr;
-        for (size_t i = 0; i < registered.size(); i++) {
-            ASSERT_TRUE(parseProviderName(registered[i],
-                    &name /*out*/, &id /*out*/));
-            provider = ICameraProvider::tryGetService(registered[i]);
-            ALOGI_IF(provider, "provider is not nullptr, %p", provider.get());
-            if (nullptr != provider.get()) {
-                mProviders.emplace(name, provider);
-            }
-        }
-    });
-
-    std::string legacyName;
-    uint32_t legacyId;
-    ASSERT_TRUE(parseProviderName(kCameraPassthroughServiceName,
-            &legacyName /*out*/, &legacyId /*out*/));
-    auto legacyIt = mProviders.find(legacyName);
-    //Add any legacy passthrough implementations
-    if (legacyIt == mProviders.end()) {
-        sp<ICameraProvider> provider = ICameraProvider::tryGetService(
-                kCameraPassthroughServiceName);
-        if (nullptr != provider.get()) {
-            mProviders.emplace(legacyName, provider);
-        }
-    }
-
-    ASSERT_FALSE(mProviders.empty());
-}
-
-void CameraHidlEnvironment::TearDown() {
-    ALOGI("TearDown CameraHidlEnvironment");
-}
-
 struct BufferItemHander: public BufferItemConsumer::FrameAvailableListener {
     BufferItemHander(wp<BufferItemConsumer> consumer) : mConsumer(consumer) {}
 
@@ -533,23 +498,32 @@ Return<Status> PreviewWindowCb::setTimestamp(int64_t timestamp) {
 // The main test class for camera HIDL HAL.
 class CameraHidlTest : public ::testing::VtsHalHidlTargetTestBase {
 public:
-    virtual void SetUp() override {}
-    virtual void TearDown() override {}
-
-    hidl_vec<hidl_string> getCameraDeviceNames(sp<ICameraProvider> provider);
-
-    struct EmptyDeviceCb : public ICameraDeviceCallback {
-        virtual Return<void> processCaptureResult(const hidl_vec<CaptureResult>& /*results*/) override {
-            ALOGI("processCaptureResult callback");
-            ADD_FAILURE(); // Empty callback should not reach here
-            return Void();
-        }
-
-        virtual Return<void> notify(const hidl_vec<NotifyMsg>& /*msgs*/) override {
-            ALOGI("notify callback");
-            ADD_FAILURE(); // Empty callback should not reach here
-            return Void();
-        }
+ virtual void SetUp() override {
+     string service_name = CameraHidlEnvironment::Instance()->getServiceName<ICameraProvider>();
+     ALOGI("get service with name: %s", service_name.c_str());
+     mProvider = ::testing::VtsHalHidlTargetTestBase::getService<ICameraProvider>(service_name);
+     ASSERT_NE(mProvider, nullptr);
+
+     uint32_t id;
+     ASSERT_TRUE(parseProviderName(service_name, &mProviderType, &id));
+ }
+ virtual void TearDown() override {}
+
+ hidl_vec<hidl_string> getCameraDeviceNames(sp<ICameraProvider> provider);
+
+ struct EmptyDeviceCb : public ICameraDeviceCallback {
+     virtual Return<void> processCaptureResult(
+         const hidl_vec<CaptureResult>& /*results*/) override {
+         ALOGI("processCaptureResult callback");
+         ADD_FAILURE();  // Empty callback should not reach here
+         return Void();
+     }
+
+     virtual Return<void> notify(const hidl_vec<NotifyMsg>& /*msgs*/) override {
+         ALOGI("notify callback");
+         ADD_FAILURE();  // Empty callback should not reach here
+         return Void();
+     }
     };
 
     struct DeviceCb : public ICameraDeviceCallback {
@@ -637,6 +611,7 @@ public:
     void openEmptyDeviceSession(const std::string &name,
             sp<ICameraProvider> provider,
             sp<ICameraDeviceSession> *session /*out*/,
+            sp<device::V3_3::ICameraDeviceSession> *session3_3 /*out*/,
             camera_metadata_t **staticMeta /*out*/);
     void configurePreviewStream(const std::string &name,
             sp<ICameraProvider> provider,
@@ -743,6 +718,11 @@ protected:
 
     // Holds camera registered buffers
     std::unordered_map<uint32_t, sp<::android::MemoryHeapBase> > mMemoryPool;
+
+    // Camera provider service
+    sp<ICameraProvider> mProvider;
+    // Camera provider type.
+    std::string mProviderType;
 };
 
 Return<void> CameraHidlTest::Camera1DeviceCb::notifyCallback(
@@ -1044,59 +1024,45 @@ hidl_vec<hidl_string> CameraHidlTest::getCameraDeviceNames(sp<ICameraProvider> p
 // Test if ICameraProvider::isTorchModeSupported returns Status::OK
 TEST_F(CameraHidlTest, isTorchModeSupported) {
     Return<void> ret;
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        ret = provider.second->isSetTorchModeSupported(
-            [&](auto status, bool support) {
-                ALOGI("isSetTorchModeSupported returns status:%d supported:%d",
-                        (int)status, support);
-                ASSERT_EQ(Status::OK, status);
-            });
-        ASSERT_TRUE(ret.isOk());
-    }
+    ret = mProvider->isSetTorchModeSupported([&](auto status, bool support) {
+        ALOGI("isSetTorchModeSupported returns status:%d supported:%d", (int)status, support);
+        ASSERT_EQ(Status::OK, status);
+    });
+    ASSERT_TRUE(ret.isOk());
 }
 
 // TODO: consider removing this test if getCameraDeviceNames() has the same coverage
 TEST_F(CameraHidlTest, getCameraIdList) {
     Return<void> ret;
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        ret = provider.second->getCameraIdList(
-            [&](auto status, const auto& idList) {
-                ALOGI("getCameraIdList returns status:%d", (int)status);
-                for (size_t i = 0; i < idList.size(); i++) {
-                    ALOGI("Camera Id[%zu] is %s", i, idList[i].c_str());
-                }
-                ASSERT_EQ(Status::OK, status);
-                // This is true for internal camera provider.
-                // Not necessary hold for external cameras providers
-                ASSERT_GT(idList.size(), 0u);
-            });
-        ASSERT_TRUE(ret.isOk());
-    }
+    ret = mProvider->getCameraIdList([&](auto status, const auto& idList) {
+        ALOGI("getCameraIdList returns status:%d", (int)status);
+        for (size_t i = 0; i < idList.size(); i++) {
+            ALOGI("Camera Id[%zu] is %s", i, idList[i].c_str());
+        }
+        ASSERT_EQ(Status::OK, status);
+        // This is true for internal camera provider.
+        // Not necessary hold for external cameras providers
+        ASSERT_GT(idList.size(), 0u);
+    });
+    ASSERT_TRUE(ret.isOk());
 }
 
 // Test if ICameraProvider::getVendorTags returns Status::OK
 TEST_F(CameraHidlTest, getVendorTags) {
     Return<void> ret;
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        ret = provider.second->getVendorTags(
-            [&](auto status, const auto& vendorTagSecs) {
-                ALOGI("getVendorTags returns status:%d numSections %zu",
-                        (int)status, vendorTagSecs.size());
-                for (size_t i = 0; i < vendorTagSecs.size(); i++) {
-                    ALOGI("Vendor tag section %zu name %s",
-                            i, vendorTagSecs[i].sectionName.c_str());
-                    for (size_t j = 0; j < vendorTagSecs[i].tags.size(); j++) {
-                        const auto& tag = vendorTagSecs[i].tags[j];
-                        ALOGI("Vendor tag id %u name %s type %d",
-                                tag.tagId,
-                                tag.tagName.c_str(),
-                                (int) tag.tagType);
-                    }
-                }
-                ASSERT_EQ(Status::OK, status);
-            });
-        ASSERT_TRUE(ret.isOk());
-    }
+    ret = mProvider->getVendorTags([&](auto status, const auto& vendorTagSecs) {
+        ALOGI("getVendorTags returns status:%d numSections %zu", (int)status, vendorTagSecs.size());
+        for (size_t i = 0; i < vendorTagSecs.size(); i++) {
+            ALOGI("Vendor tag section %zu name %s", i, vendorTagSecs[i].sectionName.c_str());
+            for (size_t j = 0; j < vendorTagSecs[i].tags.size(); j++) {
+                const auto& tag = vendorTagSecs[i].tags[j];
+                ALOGI("Vendor tag id %u name %s type %d", tag.tagId, tag.tagName.c_str(),
+                      (int)tag.tagType);
+            }
+        }
+        ASSERT_EQ(Status::OK, status);
+    });
+    ASSERT_TRUE(ret.isOk());
 }
 
 // Test if ICameraProvider::setCallback returns Status::OK
@@ -1119,49 +1085,49 @@ TEST_F(CameraHidlTest, setCallback) {
         }
     };
     sp<ProviderCb> cb = new ProviderCb;
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        auto status = provider.second->setCallback(cb);
-        ASSERT_TRUE(status.isOk());
-        ASSERT_EQ(Status::OK, status);
-        // Reset callback since cb will go out of scope
-        status = provider.second->setCallback(nullptr);
-        ASSERT_TRUE(status.isOk());
-        ASSERT_EQ(Status::OK, status);
-    }
+    auto status = mProvider->setCallback(cb);
+    ASSERT_TRUE(status.isOk());
+    ASSERT_EQ(Status::OK, status);
+    status = mProvider->setCallback(nullptr);
+    ASSERT_TRUE(status.isOk());
+    ASSERT_EQ(Status::OK, status);
 }
 
 // Test if ICameraProvider::getCameraDeviceInterface returns Status::OK and non-null device
 TEST_F(CameraHidlTest, getCameraDeviceInterface) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
+    for (const auto& name : cameraDeviceNames) {
+        int deviceVersion = getCameraDeviceVersion(name, mProviderType);
+        switch (deviceVersion) {
+            case CAMERA_DEVICE_API_VERSION_3_3:
+            case CAMERA_DEVICE_API_VERSION_3_2: {
                 Return<void> ret;
-                ret = provider.second->getCameraDeviceInterface_V3_x(
-                    name,
-                    [&](auto status, const auto& device3_2) {
-                        ALOGI("getCameraDeviceInterface_V3_x returns status:%d",
-                              (int)status);
+                ret = mProvider->getCameraDeviceInterface_V3_x(
+                    name, [&](auto status, const auto& device3_x) {
+                        ALOGI("getCameraDeviceInterface_V3_x returns status:%d", (int)status);
                         ASSERT_EQ(Status::OK, status);
-                        ASSERT_NE(device3_2, nullptr);
+                        ASSERT_NE(device3_x, nullptr);
                     });
                 ASSERT_TRUE(ret.isOk());
-            } else if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
+            }
+            break;
+            case CAMERA_DEVICE_API_VERSION_1_0: {
                 Return<void> ret;
-                ret = provider.second->getCameraDeviceInterface_V1_x(
-                    name,
-                    [&](auto status, const auto& device1) {
-                        ALOGI("getCameraDeviceInterface_V1_x returns status:%d",
-                              (int)status);
+                ret = mProvider->getCameraDeviceInterface_V1_x(
+                    name, [&](auto status, const auto& device1) {
+                        ALOGI("getCameraDeviceInterface_V1_x returns status:%d", (int)status);
                         ASSERT_EQ(Status::OK, status);
                         ASSERT_NE(device1, nullptr);
                     });
                 ASSERT_TRUE(ret.isOk());
             }
+            break;
+            default: {
+                ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
+                ADD_FAILURE();
+            }
+            break;
         }
     }
 }
@@ -1169,66 +1135,67 @@ TEST_F(CameraHidlTest, getCameraDeviceInterface) {
 // Verify that the device resource cost can be retrieved and the values are
 // sane.
 TEST_F(CameraHidlTest, getResourceCost) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
-                ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_2;
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+
+    for (const auto& name : cameraDeviceNames) {
+        int deviceVersion = getCameraDeviceVersion(name, mProviderType);
+        switch (deviceVersion) {
+            case CAMERA_DEVICE_API_VERSION_3_3:
+            case CAMERA_DEVICE_API_VERSION_3_2: {
+                ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_x;
                 ALOGI("getResourceCost: Testing camera device %s", name.c_str());
                 Return<void> ret;
-                ret = provider.second->getCameraDeviceInterface_V3_x(
-                    name,
-                    [&](auto status, const auto& device) {
-                        ALOGI("getCameraDeviceInterface_V3_x returns status:%d",
-                              (int)status);
+                ret = mProvider->getCameraDeviceInterface_V3_x(
+                    name, [&](auto status, const auto& device) {
+                        ALOGI("getCameraDeviceInterface_V3_x returns status:%d", (int)status);
                         ASSERT_EQ(Status::OK, status);
                         ASSERT_NE(device, nullptr);
-                        device3_2 = device;
+                        device3_x = device;
                     });
                 ASSERT_TRUE(ret.isOk());
 
-                ret = device3_2->getResourceCost(
-                    [&](auto status, const auto& resourceCost) {
-                        ALOGI("getResourceCost returns status:%d", (int)status);
-                        ASSERT_EQ(Status::OK, status);
-                        ALOGI("    Resource cost is %d", resourceCost.resourceCost);
-                        ASSERT_LE(resourceCost.resourceCost, 100u);
-                        for (const auto& name : resourceCost.conflictingDevices) {
-                            ALOGI("    Conflicting device: %s", name.c_str());
-                        }
-                    });
+                ret = device3_x->getResourceCost([&](auto status, const auto& resourceCost) {
+                    ALOGI("getResourceCost returns status:%d", (int)status);
+                    ASSERT_EQ(Status::OK, status);
+                    ALOGI("    Resource cost is %d", resourceCost.resourceCost);
+                    ASSERT_LE(resourceCost.resourceCost, 100u);
+                    for (const auto& name : resourceCost.conflictingDevices) {
+                        ALOGI("    Conflicting device: %s", name.c_str());
+                    }
+                });
                 ASSERT_TRUE(ret.isOk());
-            } else {
+            }
+            break;
+            case CAMERA_DEVICE_API_VERSION_1_0: {
                 ::android::sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
                 ALOGI("getResourceCost: Testing camera device %s", name.c_str());
                 Return<void> ret;
-                ret = provider.second->getCameraDeviceInterface_V1_x(
-                    name,
-                    [&](auto status, const auto& device) {
-                        ALOGI("getCameraDeviceInterface_V1_x returns status:%d",
-                              (int)status);
+                ret = mProvider->getCameraDeviceInterface_V1_x(
+                    name, [&](auto status, const auto& device) {
+                        ALOGI("getCameraDeviceInterface_V1_x returns status:%d", (int)status);
                         ASSERT_EQ(Status::OK, status);
                         ASSERT_NE(device, nullptr);
                         device1 = device;
                     });
                 ASSERT_TRUE(ret.isOk());
 
-                ret = device1->getResourceCost(
-                    [&](auto status, const auto& resourceCost) {
-                        ALOGI("getResourceCost returns status:%d", (int)status);
-                        ASSERT_EQ(Status::OK, status);
-                        ALOGI("    Resource cost is %d",
-                              resourceCost.resourceCost);
-                        ASSERT_LE(resourceCost.resourceCost, 100u);
-                        for (const auto& name : resourceCost.conflictingDevices) {
-                            ALOGI("    Conflicting device: %s", name.c_str());
-                        }
-                    });
+                ret = device1->getResourceCost([&](auto status, const auto& resourceCost) {
+                    ALOGI("getResourceCost returns status:%d", (int)status);
+                    ASSERT_EQ(Status::OK, status);
+                    ALOGI("    Resource cost is %d", resourceCost.resourceCost);
+                    ASSERT_LE(resourceCost.resourceCost, 100u);
+                    for (const auto& name : resourceCost.conflictingDevices) {
+                        ALOGI("    Conflicting device: %s", name.c_str());
+                    }
+                });
                 ASSERT_TRUE(ret.isOk());
             }
+            break;
+            default: {
+                ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
+                ADD_FAILURE();
+            }
+            break;
         }
     }
 }
@@ -1236,143 +1203,117 @@ TEST_F(CameraHidlTest, getResourceCost) {
 // Verify that the static camera info can be retrieved
 // successfully.
 TEST_F(CameraHidlTest, getCameraInfo) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                ::android::sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                ALOGI("getCameraCharacteristics: Testing camera device %s",
-                      name.c_str());
-                Return<void> ret;
-                ret = provider.second->getCameraDeviceInterface_V1_x(
-                    name,
-                    [&](auto status, const auto& device) {
-                        ALOGI("getCameraDeviceInterface_V1_x returns status:%d",
-                              (int)status);
-                        ASSERT_EQ(Status::OK, status);
-                        ASSERT_NE(device, nullptr);
-                        device1 = device;
-                    });
-                ASSERT_TRUE(ret.isOk());
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            ::android::sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            ALOGI("getCameraCharacteristics: Testing camera device %s", name.c_str());
+            Return<void> ret;
+            ret = mProvider->getCameraDeviceInterface_V1_x(
+                name, [&](auto status, const auto& device) {
+                    ALOGI("getCameraDeviceInterface_V1_x returns status:%d", (int)status);
+                    ASSERT_EQ(Status::OK, status);
+                    ASSERT_NE(device, nullptr);
+                    device1 = device;
+                });
+            ASSERT_TRUE(ret.isOk());
 
-                ret = device1->getCameraInfo(
-                    [&](auto status, const auto& info) {
-                        ALOGI("getCameraInfo returns status:%d", (int)status);
-                        ASSERT_EQ(Status::OK, status);
-                        switch(info.orientation) {
-                            case 0:
-                            case 90:
-                            case 180:
-                            case 270:
-                                //Expected cases
-                                ALOGI("camera orientation: %d", info.orientation);
-                                break;
-                            default:
-                                FAIL() << "Unexpected camera orientation:" << info.orientation;
-                        }
-                        switch(info.facing) {
-                            case CameraFacing::BACK:
-                            case CameraFacing::FRONT:
-                            case CameraFacing::EXTERNAL:
-                                //Expected cases
-                                ALOGI("camera facing: %d", info.facing);
-                                break;
-                            default:
-                                FAIL() << "Unexpected camera facing:" << static_cast<uint32_t> (
-                                        info.facing);
-                        }
-                    });
-                ASSERT_TRUE(ret.isOk());
-            }
+            ret = device1->getCameraInfo([&](auto status, const auto& info) {
+                ALOGI("getCameraInfo returns status:%d", (int)status);
+                ASSERT_EQ(Status::OK, status);
+                switch (info.orientation) {
+                    case 0:
+                    case 90:
+                    case 180:
+                    case 270:
+                        // Expected cases
+                        ALOGI("camera orientation: %d", info.orientation);
+                        break;
+                    default:
+                        FAIL() << "Unexpected camera orientation:" << info.orientation;
+                }
+                switch (info.facing) {
+                    case CameraFacing::BACK:
+                    case CameraFacing::FRONT:
+                    case CameraFacing::EXTERNAL:
+                        // Expected cases
+                        ALOGI("camera facing: %d", info.facing);
+                        break;
+                    default:
+                        FAIL() << "Unexpected camera facing:" << static_cast<uint32_t>(info.facing);
+                }
+            });
+            ASSERT_TRUE(ret.isOk());
         }
     }
 }
 
 // Check whether preview window can be configured
 TEST_F(CameraHidlTest, setPreviewWindow) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                openCameraDevice(name, provider.second, &device1 /*out*/);
-                ASSERT_NE(nullptr, device1.get());
-                sp<BufferItemConsumer> bufferItemConsumer;
-                sp<BufferItemHander> bufferHandler;
-                setupPreviewWindow(device1,
-                        &bufferItemConsumer /*out*/, &bufferHandler /*out*/);
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            openCameraDevice(name, mProvider, &device1 /*out*/);
+            ASSERT_NE(nullptr, device1.get());
+            sp<BufferItemConsumer> bufferItemConsumer;
+            sp<BufferItemHander> bufferHandler;
+            setupPreviewWindow(device1, &bufferItemConsumer /*out*/, &bufferHandler /*out*/);
 
-                Return<void> ret;
-                ret = device1->close();
-                ASSERT_TRUE(ret.isOk());
-            }
+            Return<void> ret;
+            ret = device1->close();
+            ASSERT_TRUE(ret.isOk());
         }
     }
 }
 
 // Verify that setting preview window fails in case device is not open
 TEST_F(CameraHidlTest, setPreviewWindowInvalid) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                ::android::sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                ALOGI("getCameraCharacteristics: Testing camera device %s",
-                      name.c_str());
-                Return<void> ret;
-                ret = provider.second->getCameraDeviceInterface_V1_x(
-                    name,
-                    [&](auto status, const auto& device) {
-                        ALOGI("getCameraDeviceInterface_V1_x returns status:%d",
-                              (int)status);
-                        ASSERT_EQ(Status::OK, status);
-                        ASSERT_NE(device, nullptr);
-                        device1 = device;
-                    });
-                ASSERT_TRUE(ret.isOk());
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            ::android::sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            ALOGI("getCameraCharacteristics: Testing camera device %s", name.c_str());
+            Return<void> ret;
+            ret = mProvider->getCameraDeviceInterface_V1_x(
+                name, [&](auto status, const auto& device) {
+                    ALOGI("getCameraDeviceInterface_V1_x returns status:%d", (int)status);
+                    ASSERT_EQ(Status::OK, status);
+                    ASSERT_NE(device, nullptr);
+                    device1 = device;
+                });
+            ASSERT_TRUE(ret.isOk());
 
-                Return<Status> returnStatus = device1->setPreviewWindow(nullptr);
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_EQ(Status::OPERATION_NOT_SUPPORTED, returnStatus);
-            }
+            Return<Status> returnStatus = device1->setPreviewWindow(nullptr);
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_EQ(Status::OPERATION_NOT_SUPPORTED, returnStatus);
         }
     }
 }
 
 // Start and stop preview checking whether it gets enabled in between.
 TEST_F(CameraHidlTest, startStopPreview) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                openCameraDevice(name, provider.second, &device1 /*out*/);
-                ASSERT_NE(nullptr, device1.get());
-                sp<BufferItemConsumer> bufferItemConsumer;
-                sp<BufferItemHander> bufferHandler;
-                setupPreviewWindow(device1,
-                        &bufferItemConsumer /*out*/, &bufferHandler /*out*/);
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            openCameraDevice(name, mProvider, &device1 /*out*/);
+            ASSERT_NE(nullptr, device1.get());
+            sp<BufferItemConsumer> bufferItemConsumer;
+            sp<BufferItemHander> bufferHandler;
+            setupPreviewWindow(device1, &bufferItemConsumer /*out*/, &bufferHandler /*out*/);
 
-                startPreview(device1);
+            startPreview(device1);
 
-                Return<bool> returnBoolStatus = device1->previewEnabled();
-                ASSERT_TRUE(returnBoolStatus.isOk());
-                ASSERT_TRUE(returnBoolStatus);
+            Return<bool> returnBoolStatus = device1->previewEnabled();
+            ASSERT_TRUE(returnBoolStatus.isOk());
+            ASSERT_TRUE(returnBoolStatus);
 
-                stopPreviewAndClose(device1);
-            }
+            stopPreviewAndClose(device1);
         }
     }
 }
@@ -1380,646 +1321,552 @@ TEST_F(CameraHidlTest, startStopPreview) {
 // Start preview without active preview window. Preview should start as soon
 // as a valid active window gets configured.
 TEST_F(CameraHidlTest, startStopPreviewDelayed) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                openCameraDevice(name, provider.second, &device1 /*out*/);
-                ASSERT_NE(nullptr, device1.get());
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            openCameraDevice(name, mProvider, &device1 /*out*/);
+            ASSERT_NE(nullptr, device1.get());
 
-                Return<Status> returnStatus = device1->setPreviewWindow(nullptr);
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_EQ(Status::OK, returnStatus);
+            Return<Status> returnStatus = device1->setPreviewWindow(nullptr);
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_EQ(Status::OK, returnStatus);
 
-                startPreview(device1);
+            startPreview(device1);
 
-                sp<BufferItemConsumer> bufferItemConsumer;
-                sp<BufferItemHander> bufferHandler;
-                setupPreviewWindow(device1, &bufferItemConsumer /*out*/,
-                        &bufferHandler /*out*/);
+            sp<BufferItemConsumer> bufferItemConsumer;
+            sp<BufferItemHander> bufferHandler;
+            setupPreviewWindow(device1, &bufferItemConsumer /*out*/, &bufferHandler /*out*/);
 
-                //Preview should get enabled now
-                Return<bool> returnBoolStatus = device1->previewEnabled();
-                ASSERT_TRUE(returnBoolStatus.isOk());
-                ASSERT_TRUE(returnBoolStatus);
+            // Preview should get enabled now
+            Return<bool> returnBoolStatus = device1->previewEnabled();
+            ASSERT_TRUE(returnBoolStatus.isOk());
+            ASSERT_TRUE(returnBoolStatus);
 
-                stopPreviewAndClose(device1);
-            }
+            stopPreviewAndClose(device1);
         }
     }
 }
 
 // Verify that image capture behaves as expected along with preview callbacks.
 TEST_F(CameraHidlTest, takePicture) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                openCameraDevice(name, provider.second, &device1 /*out*/);
-                ASSERT_NE(nullptr, device1.get());
-                sp<BufferItemConsumer> bufferItemConsumer;
-                sp<BufferItemHander> bufferHandler;
-                setupPreviewWindow(device1, &bufferItemConsumer /*out*/,
-                        &bufferHandler /*out*/);
-
-                {
-                    std::unique_lock<std::mutex> l(mLock);
-                    mDataMessageTypeReceived = DataCallbackMsg::RAW_IMAGE_NOTIFY;
-                }
-
-                enableMsgType((unsigned int)DataCallbackMsg::PREVIEW_FRAME,
-                              device1);
-                startPreview(device1);
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            openCameraDevice(name, mProvider, &device1 /*out*/);
+            ASSERT_NE(nullptr, device1.get());
+            sp<BufferItemConsumer> bufferItemConsumer;
+            sp<BufferItemHander> bufferHandler;
+            setupPreviewWindow(device1, &bufferItemConsumer /*out*/, &bufferHandler /*out*/);
+
+            {
+                std::unique_lock<std::mutex> l(mLock);
+                mDataMessageTypeReceived = DataCallbackMsg::RAW_IMAGE_NOTIFY;
+            }
 
-                {
-                    std::unique_lock<std::mutex> l(mLock);
-                    waitForFrameLocked(DataCallbackMsg::PREVIEW_FRAME, l);
-                }
+            enableMsgType((unsigned int)DataCallbackMsg::PREVIEW_FRAME, device1);
+            startPreview(device1);
 
-                disableMsgType((unsigned int)DataCallbackMsg::PREVIEW_FRAME,
-                                device1);
-                enableMsgType((unsigned int)DataCallbackMsg::COMPRESSED_IMAGE,
-                        device1);
+            {
+                std::unique_lock<std::mutex> l(mLock);
+                waitForFrameLocked(DataCallbackMsg::PREVIEW_FRAME, l);
+            }
 
-                {
-                    std::unique_lock<std::mutex> l(mLock);
-                    mDataMessageTypeReceived = DataCallbackMsg::RAW_IMAGE_NOTIFY;
-                }
+            disableMsgType((unsigned int)DataCallbackMsg::PREVIEW_FRAME, device1);
+            enableMsgType((unsigned int)DataCallbackMsg::COMPRESSED_IMAGE, device1);
 
-                Return<Status> returnStatus = device1->takePicture();
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_EQ(Status::OK, returnStatus);
+            {
+                std::unique_lock<std::mutex> l(mLock);
+                mDataMessageTypeReceived = DataCallbackMsg::RAW_IMAGE_NOTIFY;
+            }
 
-                {
-                    std::unique_lock<std::mutex> l(mLock);
-                    waitForFrameLocked(DataCallbackMsg::COMPRESSED_IMAGE, l);
-                }
+            Return<Status> returnStatus = device1->takePicture();
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_EQ(Status::OK, returnStatus);
 
-                disableMsgType((unsigned int)DataCallbackMsg::COMPRESSED_IMAGE,
-                        device1);
-                stopPreviewAndClose(device1);
+            {
+                std::unique_lock<std::mutex> l(mLock);
+                waitForFrameLocked(DataCallbackMsg::COMPRESSED_IMAGE, l);
             }
+
+            disableMsgType((unsigned int)DataCallbackMsg::COMPRESSED_IMAGE, device1);
+            stopPreviewAndClose(device1);
         }
     }
 }
 
 // Image capture should fail in case preview didn't get enabled first.
 TEST_F(CameraHidlTest, takePictureFail) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                openCameraDevice(name, provider.second, &device1 /*out*/);
-                ASSERT_NE(nullptr, device1.get());
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            openCameraDevice(name, mProvider, &device1 /*out*/);
+            ASSERT_NE(nullptr, device1.get());
 
-                Return<Status> returnStatus = device1->takePicture();
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_NE(Status::OK, returnStatus);
+            Return<Status> returnStatus = device1->takePicture();
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_NE(Status::OK, returnStatus);
 
-                Return<void> ret = device1->close();
-                ASSERT_TRUE(ret.isOk());
-            }
+            Return<void> ret = device1->close();
+            ASSERT_TRUE(ret.isOk());
         }
     }
 }
 
 // Verify that image capture can be cancelled.
 TEST_F(CameraHidlTest, cancelPicture) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                openCameraDevice(name, provider.second, &device1 /*out*/);
-                ASSERT_NE(nullptr, device1.get());
-                sp<BufferItemConsumer> bufferItemConsumer;
-                sp<BufferItemHander> bufferHandler;
-                setupPreviewWindow(device1, &bufferItemConsumer /*out*/,
-                        &bufferHandler /*out*/);
-                startPreview(device1);
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            openCameraDevice(name, mProvider, &device1 /*out*/);
+            ASSERT_NE(nullptr, device1.get());
+            sp<BufferItemConsumer> bufferItemConsumer;
+            sp<BufferItemHander> bufferHandler;
+            setupPreviewWindow(device1, &bufferItemConsumer /*out*/, &bufferHandler /*out*/);
+            startPreview(device1);
 
-                Return<Status> returnStatus = device1->takePicture();
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_EQ(Status::OK, returnStatus);
+            Return<Status> returnStatus = device1->takePicture();
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_EQ(Status::OK, returnStatus);
 
-                returnStatus = device1->cancelPicture();
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_EQ(Status::OK, returnStatus);
+            returnStatus = device1->cancelPicture();
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_EQ(Status::OK, returnStatus);
 
-                stopPreviewAndClose(device1);
-            }
+            stopPreviewAndClose(device1);
         }
     }
 }
 
 // Image capture cancel is a no-op when image capture is not running.
 TEST_F(CameraHidlTest, cancelPictureNOP) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                openCameraDevice(name, provider.second, &device1 /*out*/);
-                ASSERT_NE(nullptr, device1.get());
-                sp<BufferItemConsumer> bufferItemConsumer;
-                sp<BufferItemHander> bufferHandler;
-                setupPreviewWindow(device1, &bufferItemConsumer /*out*/,
-                        &bufferHandler /*out*/);
-                startPreview(device1);
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            openCameraDevice(name, mProvider, &device1 /*out*/);
+            ASSERT_NE(nullptr, device1.get());
+            sp<BufferItemConsumer> bufferItemConsumer;
+            sp<BufferItemHander> bufferHandler;
+            setupPreviewWindow(device1, &bufferItemConsumer /*out*/, &bufferHandler /*out*/);
+            startPreview(device1);
 
-                Return<Status> returnStatus = device1->cancelPicture();
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_EQ(Status::OK, returnStatus);
+            Return<Status> returnStatus = device1->cancelPicture();
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_EQ(Status::OK, returnStatus);
 
-                stopPreviewAndClose(device1);
-            }
+            stopPreviewAndClose(device1);
         }
     }
 }
 
 // Test basic video recording.
 TEST_F(CameraHidlTest, startStopRecording) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                openCameraDevice(name, provider.second, &device1 /*out*/);
-                ASSERT_NE(nullptr, device1.get());
-                sp<BufferItemConsumer> bufferItemConsumer;
-                sp<BufferItemHander> bufferHandler;
-                setupPreviewWindow(device1, &bufferItemConsumer /*out*/,
-                        &bufferHandler /*out*/);
-
-                {
-                    std::unique_lock<std::mutex> l(mLock);
-                    mDataMessageTypeReceived = DataCallbackMsg::RAW_IMAGE_NOTIFY;
-                }
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            openCameraDevice(name, mProvider, &device1 /*out*/);
+            ASSERT_NE(nullptr, device1.get());
+            sp<BufferItemConsumer> bufferItemConsumer;
+            sp<BufferItemHander> bufferHandler;
+            setupPreviewWindow(device1, &bufferItemConsumer /*out*/, &bufferHandler /*out*/);
+
+            {
+                std::unique_lock<std::mutex> l(mLock);
+                mDataMessageTypeReceived = DataCallbackMsg::RAW_IMAGE_NOTIFY;
+            }
 
-                enableMsgType((unsigned int)DataCallbackMsg::PREVIEW_FRAME,
-                        device1);
-                startPreview(device1);
+            enableMsgType((unsigned int)DataCallbackMsg::PREVIEW_FRAME, device1);
+            startPreview(device1);
 
-                {
-                    std::unique_lock<std::mutex> l(mLock);
-                    waitForFrameLocked(DataCallbackMsg::PREVIEW_FRAME, l);
-                    mDataMessageTypeReceived = DataCallbackMsg::RAW_IMAGE_NOTIFY;
-                    mVideoBufferIndex = UINT32_MAX;
-                }
+            {
+                std::unique_lock<std::mutex> l(mLock);
+                waitForFrameLocked(DataCallbackMsg::PREVIEW_FRAME, l);
+                mDataMessageTypeReceived = DataCallbackMsg::RAW_IMAGE_NOTIFY;
+                mVideoBufferIndex = UINT32_MAX;
+            }
 
-                disableMsgType((unsigned int)DataCallbackMsg::PREVIEW_FRAME,
-                        device1);
+            disableMsgType((unsigned int)DataCallbackMsg::PREVIEW_FRAME, device1);
 
-                bool videoMetaEnabled = false;
-                Return<Status> returnStatus = device1->storeMetaDataInBuffers(
-                        true);
-                ASSERT_TRUE(returnStatus.isOk());
-                // It is allowed for devices to not support this feature
-                ASSERT_TRUE((Status::OK == returnStatus) ||
+            bool videoMetaEnabled = false;
+            Return<Status> returnStatus = device1->storeMetaDataInBuffers(true);
+            ASSERT_TRUE(returnStatus.isOk());
+            // It is allowed for devices to not support this feature
+            ASSERT_TRUE((Status::OK == returnStatus) ||
                         (Status::OPERATION_NOT_SUPPORTED == returnStatus));
-                if (Status::OK == returnStatus) {
-                    videoMetaEnabled = true;
-                }
+            if (Status::OK == returnStatus) {
+                videoMetaEnabled = true;
+            }
 
-                enableMsgType((unsigned int)DataCallbackMsg::VIDEO_FRAME,
-                        device1);
-                Return<bool> returnBoolStatus = device1->recordingEnabled();
-                ASSERT_TRUE(returnBoolStatus.isOk());
-                ASSERT_FALSE(returnBoolStatus);
+            enableMsgType((unsigned int)DataCallbackMsg::VIDEO_FRAME, device1);
+            Return<bool> returnBoolStatus = device1->recordingEnabled();
+            ASSERT_TRUE(returnBoolStatus.isOk());
+            ASSERT_FALSE(returnBoolStatus);
 
-                returnStatus = device1->startRecording();
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_EQ(Status::OK, returnStatus);
+            returnStatus = device1->startRecording();
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_EQ(Status::OK, returnStatus);
 
-                {
-                    std::unique_lock<std::mutex> l(mLock);
-                    waitForFrameLocked(DataCallbackMsg::VIDEO_FRAME, l);
-                    ASSERT_NE(UINT32_MAX, mVideoBufferIndex);
-                    disableMsgType((unsigned int)DataCallbackMsg::VIDEO_FRAME,
-                            device1);
-                }
-
-                returnBoolStatus = device1->recordingEnabled();
-                ASSERT_TRUE(returnBoolStatus.isOk());
-                ASSERT_TRUE(returnBoolStatus);
+            {
+                std::unique_lock<std::mutex> l(mLock);
+                waitForFrameLocked(DataCallbackMsg::VIDEO_FRAME, l);
+                ASSERT_NE(UINT32_MAX, mVideoBufferIndex);
+                disableMsgType((unsigned int)DataCallbackMsg::VIDEO_FRAME, device1);
+            }
 
-                Return<void> ret;
-                if (videoMetaEnabled) {
-                    ret = device1->releaseRecordingFrameHandle(mVideoData,
-                            mVideoBufferIndex, mVideoNativeHandle);
-                    ASSERT_TRUE(ret.isOk());
-                } else {
-                    ret = device1->releaseRecordingFrame(mVideoData,
-                            mVideoBufferIndex);
-                    ASSERT_TRUE(ret.isOk());
-                }
+            returnBoolStatus = device1->recordingEnabled();
+            ASSERT_TRUE(returnBoolStatus.isOk());
+            ASSERT_TRUE(returnBoolStatus);
 
-                ret = device1->stopRecording();
+            Return<void> ret;
+            if (videoMetaEnabled) {
+                ret = device1->releaseRecordingFrameHandle(mVideoData, mVideoBufferIndex,
+                                                           mVideoNativeHandle);
+                ASSERT_TRUE(ret.isOk());
+            } else {
+                ret = device1->releaseRecordingFrame(mVideoData, mVideoBufferIndex);
                 ASSERT_TRUE(ret.isOk());
-
-                stopPreviewAndClose(device1);
             }
+
+            ret = device1->stopRecording();
+            ASSERT_TRUE(ret.isOk());
+
+            stopPreviewAndClose(device1);
         }
     }
 }
 
 // It shouldn't be possible to start recording without enabling preview first.
 TEST_F(CameraHidlTest, startRecordingFail) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                openCameraDevice(name, provider.second, &device1 /*out*/);
-                ASSERT_NE(nullptr, device1.get());
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            openCameraDevice(name, mProvider, &device1 /*out*/);
+            ASSERT_NE(nullptr, device1.get());
 
-                Return<bool> returnBoolStatus = device1->recordingEnabled();
-                ASSERT_TRUE(returnBoolStatus.isOk());
-                ASSERT_FALSE(returnBoolStatus);
+            Return<bool> returnBoolStatus = device1->recordingEnabled();
+            ASSERT_TRUE(returnBoolStatus.isOk());
+            ASSERT_FALSE(returnBoolStatus);
 
-                Return<Status> returnStatus = device1->startRecording();
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_NE(Status::OK, returnStatus);
+            Return<Status> returnStatus = device1->startRecording();
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_NE(Status::OK, returnStatus);
 
-                Return<void> ret = device1->close();
-                ASSERT_TRUE(ret.isOk());
-            }
+            Return<void> ret = device1->close();
+            ASSERT_TRUE(ret.isOk());
         }
     }
 }
 
 // Check autofocus support if available.
 TEST_F(CameraHidlTest, autoFocus) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-        std::vector<const char *> focusModes = {CameraParameters::FOCUS_MODE_AUTO,
-                CameraParameters::FOCUS_MODE_CONTINUOUS_PICTURE,
-                CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO};
-
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                openCameraDevice(name, provider.second, &device1 /*out*/);
-                ASSERT_NE(nullptr, device1.get());
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    std::vector<const char*> focusModes = {CameraParameters::FOCUS_MODE_AUTO,
+                                           CameraParameters::FOCUS_MODE_CONTINUOUS_PICTURE,
+                                           CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO};
+
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            openCameraDevice(name, mProvider, &device1 /*out*/);
+            ASSERT_NE(nullptr, device1.get());
+
+            CameraParameters cameraParams;
+            getParameters(device1, &cameraParams /*out*/);
+
+            if (Status::OK !=
+                isAutoFocusModeAvailable(cameraParams, CameraParameters::FOCUS_MODE_AUTO)) {
+                Return<void> ret = device1->close();
+                ASSERT_TRUE(ret.isOk());
+                continue;
+            }
 
-                CameraParameters cameraParams;
-                getParameters(device1, &cameraParams /*out*/);
+            sp<BufferItemConsumer> bufferItemConsumer;
+            sp<BufferItemHander> bufferHandler;
+            setupPreviewWindow(device1, &bufferItemConsumer /*out*/, &bufferHandler /*out*/);
+            startPreview(device1);
+            enableMsgType((unsigned int)NotifyCallbackMsg::FOCUS, device1);
 
-                if (Status::OK != isAutoFocusModeAvailable(cameraParams,
-                        CameraParameters::FOCUS_MODE_AUTO)) {
-                    Return<void> ret = device1->close();
-                    ASSERT_TRUE(ret.isOk());
+            for (auto& iter : focusModes) {
+                if (Status::OK != isAutoFocusModeAvailable(cameraParams, iter)) {
                     continue;
                 }
 
-                sp<BufferItemConsumer> bufferItemConsumer;
-                sp<BufferItemHander> bufferHandler;
-                setupPreviewWindow(device1, &bufferItemConsumer /*out*/,
-                        &bufferHandler /*out*/);
-                startPreview(device1);
-                enableMsgType((unsigned int)NotifyCallbackMsg::FOCUS, device1);
-
-                for (auto &iter : focusModes) {
-                    if (Status::OK != isAutoFocusModeAvailable(cameraParams,
-                            iter)) {
-                        continue;
-                    }
+                cameraParams.set(CameraParameters::KEY_FOCUS_MODE, iter);
+                setParameters(device1, cameraParams);
+                {
+                    std::unique_lock<std::mutex> l(mLock);
+                    mNotifyMessage = NotifyCallbackMsg::ERROR;
+                }
 
-                    cameraParams.set(CameraParameters::KEY_FOCUS_MODE, iter);
-                    setParameters(device1, cameraParams);
-                    {
-                        std::unique_lock<std::mutex> l(mLock);
-                        mNotifyMessage = NotifyCallbackMsg::ERROR;
-                    }
+                Return<Status> returnStatus = device1->autoFocus();
+                ASSERT_TRUE(returnStatus.isOk());
+                ASSERT_EQ(Status::OK, returnStatus);
 
-                    Return<Status> returnStatus = device1->autoFocus();
-                    ASSERT_TRUE(returnStatus.isOk());
-                    ASSERT_EQ(Status::OK, returnStatus);
-
-                    {
-                        std::unique_lock<std::mutex> l(mLock);
-                        while (NotifyCallbackMsg::FOCUS != mNotifyMessage) {
-                            auto timeout = std::chrono::system_clock::now() +
-                                    std::chrono::seconds(kAutoFocusTimeoutSec);
-                            ASSERT_NE(std::cv_status::timeout,
-                                    mResultCondition.wait_until(l, timeout));
-                        }
+                {
+                    std::unique_lock<std::mutex> l(mLock);
+                    while (NotifyCallbackMsg::FOCUS != mNotifyMessage) {
+                        auto timeout = std::chrono::system_clock::now() +
+                                       std::chrono::seconds(kAutoFocusTimeoutSec);
+                        ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
                     }
                 }
-
-                disableMsgType((unsigned int)NotifyCallbackMsg::FOCUS, device1);
-                stopPreviewAndClose(device1);
             }
+
+            disableMsgType((unsigned int)NotifyCallbackMsg::FOCUS, device1);
+            stopPreviewAndClose(device1);
         }
     }
 }
 
 // In case autofocus is supported verify that it can be cancelled.
 TEST_F(CameraHidlTest, cancelAutoFocus) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                openCameraDevice(name, provider.second, &device1 /*out*/);
-                ASSERT_NE(nullptr, device1.get());
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            openCameraDevice(name, mProvider, &device1 /*out*/);
+            ASSERT_NE(nullptr, device1.get());
 
-                CameraParameters cameraParams;
-                getParameters(device1, &cameraParams /*out*/);
+            CameraParameters cameraParams;
+            getParameters(device1, &cameraParams /*out*/);
 
-                if (Status::OK != isAutoFocusModeAvailable(cameraParams,
-                        CameraParameters::FOCUS_MODE_AUTO)) {
-                    Return<void> ret = device1->close();
-                    ASSERT_TRUE(ret.isOk());
-                    continue;
-                }
+            if (Status::OK !=
+                isAutoFocusModeAvailable(cameraParams, CameraParameters::FOCUS_MODE_AUTO)) {
+                Return<void> ret = device1->close();
+                ASSERT_TRUE(ret.isOk());
+                continue;
+            }
 
-                // It should be fine to call before preview starts.
-                ASSERT_EQ(Status::OK, device1->cancelAutoFocus());
+            // It should be fine to call before preview starts.
+            ASSERT_EQ(Status::OK, device1->cancelAutoFocus());
 
-                sp<BufferItemConsumer> bufferItemConsumer;
-                sp<BufferItemHander> bufferHandler;
-                setupPreviewWindow(device1, &bufferItemConsumer /*out*/,
-                        &bufferHandler /*out*/);
-                startPreview(device1);
+            sp<BufferItemConsumer> bufferItemConsumer;
+            sp<BufferItemHander> bufferHandler;
+            setupPreviewWindow(device1, &bufferItemConsumer /*out*/, &bufferHandler /*out*/);
+            startPreview(device1);
 
-                // It should be fine to call after preview starts too.
-                Return<Status> returnStatus = device1->cancelAutoFocus();
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_EQ(Status::OK, returnStatus);
+            // It should be fine to call after preview starts too.
+            Return<Status> returnStatus = device1->cancelAutoFocus();
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_EQ(Status::OK, returnStatus);
 
-                returnStatus = device1->autoFocus();
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_EQ(Status::OK, returnStatus);
+            returnStatus = device1->autoFocus();
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_EQ(Status::OK, returnStatus);
 
-                returnStatus = device1->cancelAutoFocus();
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_EQ(Status::OK, returnStatus);
+            returnStatus = device1->cancelAutoFocus();
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_EQ(Status::OK, returnStatus);
 
-                stopPreviewAndClose(device1);
-            }
+            stopPreviewAndClose(device1);
         }
     }
 }
 
 // Check whether face detection is available and try to enable&disable.
 TEST_F(CameraHidlTest, sendCommandFaceDetection) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                openCameraDevice(name, provider.second, &device1 /*out*/);
-                ASSERT_NE(nullptr, device1.get());
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            openCameraDevice(name, mProvider, &device1 /*out*/);
+            ASSERT_NE(nullptr, device1.get());
 
-                CameraParameters cameraParams;
-                getParameters(device1, &cameraParams /*out*/);
+            CameraParameters cameraParams;
+            getParameters(device1, &cameraParams /*out*/);
 
-                int32_t hwFaces = cameraParams.getInt(
-                        CameraParameters::KEY_MAX_NUM_DETECTED_FACES_HW);
-                int32_t swFaces = cameraParams.getInt(
-                        CameraParameters::KEY_MAX_NUM_DETECTED_FACES_SW);
-                if ((0 >= hwFaces) && (0 >= swFaces)) {
-                    Return<void> ret = device1->close();
-                    ASSERT_TRUE(ret.isOk());
-                    continue;
-                }
+            int32_t hwFaces = cameraParams.getInt(CameraParameters::KEY_MAX_NUM_DETECTED_FACES_HW);
+            int32_t swFaces = cameraParams.getInt(CameraParameters::KEY_MAX_NUM_DETECTED_FACES_SW);
+            if ((0 >= hwFaces) && (0 >= swFaces)) {
+                Return<void> ret = device1->close();
+                ASSERT_TRUE(ret.isOk());
+                continue;
+            }
 
-                sp<BufferItemConsumer> bufferItemConsumer;
-                sp<BufferItemHander> bufferHandler;
-                setupPreviewWindow(device1, &bufferItemConsumer /*out*/,
-                        &bufferHandler /*out*/);
-                startPreview(device1);
-
-                if (0 < hwFaces) {
-                    Return<Status> returnStatus = device1->sendCommand(
-                            CommandType::START_FACE_DETECTION,
-                            CAMERA_FACE_DETECTION_HW, 0);
-                    ASSERT_TRUE(returnStatus.isOk());
-                    ASSERT_EQ(Status::OK, returnStatus);
-                    // TODO(epeev) : Enable and check for face notifications
-                    returnStatus = device1->sendCommand(
-                            CommandType::STOP_FACE_DETECTION,
-                            CAMERA_FACE_DETECTION_HW, 0);
-                    ASSERT_TRUE(returnStatus.isOk());
-                    ASSERT_EQ(Status::OK, returnStatus);
-                }
+            sp<BufferItemConsumer> bufferItemConsumer;
+            sp<BufferItemHander> bufferHandler;
+            setupPreviewWindow(device1, &bufferItemConsumer /*out*/, &bufferHandler /*out*/);
+            startPreview(device1);
 
-                if (0 < swFaces) {
-                    Return<Status> returnStatus = device1->sendCommand(
-                            CommandType::START_FACE_DETECTION,
-                            CAMERA_FACE_DETECTION_SW, 0);
-                    ASSERT_TRUE(returnStatus.isOk());
-                    ASSERT_EQ(Status::OK, returnStatus);
-                    // TODO(epeev) : Enable and check for face notifications
-                    returnStatus = device1->sendCommand(
-                            CommandType::STOP_FACE_DETECTION,
-                            CAMERA_FACE_DETECTION_SW, 0);
-                    ASSERT_TRUE(returnStatus.isOk());
-                    ASSERT_EQ(Status::OK, returnStatus);
-                }
+            if (0 < hwFaces) {
+                Return<Status> returnStatus = device1->sendCommand(
+                    CommandType::START_FACE_DETECTION, CAMERA_FACE_DETECTION_HW, 0);
+                ASSERT_TRUE(returnStatus.isOk());
+                ASSERT_EQ(Status::OK, returnStatus);
+                // TODO(epeev) : Enable and check for face notifications
+                returnStatus = device1->sendCommand(CommandType::STOP_FACE_DETECTION,
+                                                    CAMERA_FACE_DETECTION_HW, 0);
+                ASSERT_TRUE(returnStatus.isOk());
+                ASSERT_EQ(Status::OK, returnStatus);
+            }
 
-                stopPreviewAndClose(device1);
+            if (0 < swFaces) {
+                Return<Status> returnStatus = device1->sendCommand(
+                    CommandType::START_FACE_DETECTION, CAMERA_FACE_DETECTION_SW, 0);
+                ASSERT_TRUE(returnStatus.isOk());
+                ASSERT_EQ(Status::OK, returnStatus);
+                // TODO(epeev) : Enable and check for face notifications
+                returnStatus = device1->sendCommand(CommandType::STOP_FACE_DETECTION,
+                                                    CAMERA_FACE_DETECTION_SW, 0);
+                ASSERT_TRUE(returnStatus.isOk());
+                ASSERT_EQ(Status::OK, returnStatus);
             }
+
+            stopPreviewAndClose(device1);
         }
     }
 }
 
 // Check whether smooth zoom is available and try to enable&disable.
 TEST_F(CameraHidlTest, sendCommandSmoothZoom) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                openCameraDevice(name, provider.second, &device1 /*out*/);
-                ASSERT_NE(nullptr, device1.get());
-
-                CameraParameters cameraParams;
-                getParameters(device1, &cameraParams /*out*/);
-
-                const char *smoothZoomStr = cameraParams.get(
-                        CameraParameters::KEY_SMOOTH_ZOOM_SUPPORTED);
-                bool smoothZoomSupported = ((nullptr != smoothZoomStr) &&
-                        (strcmp(smoothZoomStr, CameraParameters::TRUE) == 0)) ?
-                                true : false;
-                if (!smoothZoomSupported) {
-                    Return<void> ret = device1->close();
-                    ASSERT_TRUE(ret.isOk());
-                    continue;
-                }
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            openCameraDevice(name, mProvider, &device1 /*out*/);
+            ASSERT_NE(nullptr, device1.get());
+
+            CameraParameters cameraParams;
+            getParameters(device1, &cameraParams /*out*/);
+
+            const char* smoothZoomStr =
+                cameraParams.get(CameraParameters::KEY_SMOOTH_ZOOM_SUPPORTED);
+            bool smoothZoomSupported =
+                ((nullptr != smoothZoomStr) && (strcmp(smoothZoomStr, CameraParameters::TRUE) == 0))
+                    ? true
+                    : false;
+            if (!smoothZoomSupported) {
+                Return<void> ret = device1->close();
+                ASSERT_TRUE(ret.isOk());
+                continue;
+            }
 
-                int32_t maxZoom = cameraParams.getInt(
-                        CameraParameters::KEY_MAX_ZOOM);
-                ASSERT_TRUE(0 < maxZoom);
+            int32_t maxZoom = cameraParams.getInt(CameraParameters::KEY_MAX_ZOOM);
+            ASSERT_TRUE(0 < maxZoom);
 
-                sp<BufferItemConsumer> bufferItemConsumer;
-                sp<BufferItemHander> bufferHandler;
-                setupPreviewWindow(device1, &bufferItemConsumer /*out*/,
-                        &bufferHandler /*out*/);
-                startPreview(device1);
-                setParameters(device1, cameraParams);
+            sp<BufferItemConsumer> bufferItemConsumer;
+            sp<BufferItemHander> bufferHandler;
+            setupPreviewWindow(device1, &bufferItemConsumer /*out*/, &bufferHandler /*out*/);
+            startPreview(device1);
+            setParameters(device1, cameraParams);
 
-                Return<Status> returnStatus = device1->sendCommand(
-                        CommandType::START_SMOOTH_ZOOM, maxZoom, 0);
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_EQ(Status::OK, returnStatus);
-                // TODO(epeev) : Enable and check for face notifications
-                returnStatus = device1->sendCommand(
-                        CommandType::STOP_SMOOTH_ZOOM, 0, 0);
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_EQ(Status::OK, returnStatus);
+            Return<Status> returnStatus =
+                device1->sendCommand(CommandType::START_SMOOTH_ZOOM, maxZoom, 0);
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_EQ(Status::OK, returnStatus);
+            // TODO(epeev) : Enable and check for face notifications
+            returnStatus = device1->sendCommand(CommandType::STOP_SMOOTH_ZOOM, 0, 0);
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_EQ(Status::OK, returnStatus);
 
-                stopPreviewAndClose(device1);
-            }
+            stopPreviewAndClose(device1);
         }
     }
 }
 
 // Basic sanity tests related to camera parameters.
 TEST_F(CameraHidlTest, getSetParameters) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                openCameraDevice(name, provider.second, &device1 /*out*/);
-                ASSERT_NE(nullptr, device1.get());
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            openCameraDevice(name, mProvider, &device1 /*out*/);
+            ASSERT_NE(nullptr, device1.get());
+
+            CameraParameters cameraParams;
+            getParameters(device1, &cameraParams /*out*/);
+
+            int32_t width, height;
+            cameraParams.getPictureSize(&width, &height);
+            ASSERT_TRUE((0 < width) && (0 < height));
+            cameraParams.getPreviewSize(&width, &height);
+            ASSERT_TRUE((0 < width) && (0 < height));
+            int32_t minFps, maxFps;
+            cameraParams.getPreviewFpsRange(&minFps, &maxFps);
+            ASSERT_TRUE((0 < minFps) && (0 < maxFps));
+            ASSERT_NE(nullptr, cameraParams.getPreviewFormat());
+            ASSERT_NE(nullptr, cameraParams.getPictureFormat());
+            ASSERT_TRUE(
+                strcmp(CameraParameters::PIXEL_FORMAT_JPEG, cameraParams.getPictureFormat()) == 0);
+
+            const char* flashMode = cameraParams.get(CameraParameters::KEY_FLASH_MODE);
+            ASSERT_TRUE((nullptr == flashMode) ||
+                        (strcmp(CameraParameters::FLASH_MODE_OFF, flashMode) == 0));
+
+            const char* wbMode = cameraParams.get(CameraParameters::KEY_WHITE_BALANCE);
+            ASSERT_TRUE((nullptr == wbMode) ||
+                        (strcmp(CameraParameters::WHITE_BALANCE_AUTO, wbMode) == 0));
+
+            const char* effect = cameraParams.get(CameraParameters::KEY_EFFECT);
+            ASSERT_TRUE((nullptr == effect) ||
+                        (strcmp(CameraParameters::EFFECT_NONE, effect) == 0));
+
+            ::android::Vector<Size> previewSizes;
+            cameraParams.getSupportedPreviewSizes(previewSizes);
+            ASSERT_FALSE(previewSizes.empty());
+            ::android::Vector<Size> pictureSizes;
+            cameraParams.getSupportedPictureSizes(pictureSizes);
+            ASSERT_FALSE(pictureSizes.empty());
+            const char* previewFormats =
+                cameraParams.get(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS);
+            ASSERT_NE(nullptr, previewFormats);
+            ::android::String8 previewFormatsString(previewFormats);
+            ASSERT_TRUE(previewFormatsString.contains(CameraParameters::PIXEL_FORMAT_YUV420SP));
+            ASSERT_NE(nullptr, cameraParams.get(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS));
+            ASSERT_NE(nullptr,
+                      cameraParams.get(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES));
+            const char* focusModes = cameraParams.get(CameraParameters::KEY_SUPPORTED_FOCUS_MODES);
+            ASSERT_NE(nullptr, focusModes);
+            ::android::String8 focusModesString(focusModes);
+            const char* focusMode = cameraParams.get(CameraParameters::KEY_FOCUS_MODE);
+            ASSERT_NE(nullptr, focusMode);
+            // Auto focus mode should be default
+            if (focusModesString.contains(CameraParameters::FOCUS_MODE_AUTO)) {
+                ASSERT_TRUE(strcmp(CameraParameters::FOCUS_MODE_AUTO, focusMode) == 0);
+            }
+            ASSERT_TRUE(0 < cameraParams.getInt(CameraParameters::KEY_FOCAL_LENGTH));
+            int32_t horizontalViewAngle =
+                cameraParams.getInt(CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE);
+            ASSERT_TRUE((0 < horizontalViewAngle) && (360 >= horizontalViewAngle));
+            int32_t verticalViewAngle =
+                cameraParams.getInt(CameraParameters::KEY_VERTICAL_VIEW_ANGLE);
+            ASSERT_TRUE((0 < verticalViewAngle) && (360 >= verticalViewAngle));
+            int32_t jpegQuality = cameraParams.getInt(CameraParameters::KEY_JPEG_QUALITY);
+            ASSERT_TRUE((1 <= jpegQuality) && (100 >= jpegQuality));
+            int32_t jpegThumbQuality =
+                cameraParams.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
+            ASSERT_TRUE((1 <= jpegThumbQuality) && (100 >= jpegThumbQuality));
 
-                CameraParameters cameraParams;
-                getParameters(device1, &cameraParams /*out*/);
-
-                int32_t width, height;
-                cameraParams.getPictureSize(&width, &height);
-                ASSERT_TRUE((0 < width) && (0 < height));
-                cameraParams.getPreviewSize(&width, &height);
-                ASSERT_TRUE((0 < width) && (0 < height));
-                int32_t minFps, maxFps;
-                cameraParams.getPreviewFpsRange(&minFps, &maxFps);
-                ASSERT_TRUE((0 < minFps) && (0 < maxFps));
-                ASSERT_NE(nullptr, cameraParams.getPreviewFormat());
-                ASSERT_NE(nullptr, cameraParams.getPictureFormat());
-                ASSERT_TRUE(strcmp(CameraParameters::PIXEL_FORMAT_JPEG,
-                        cameraParams.getPictureFormat()) == 0);
-
-                const char *flashMode = cameraParams.get(
-                        CameraParameters::KEY_FLASH_MODE);
-                ASSERT_TRUE((nullptr == flashMode) || (strcmp(
-                        CameraParameters::FLASH_MODE_OFF, flashMode) == 0));
-
-                const char *wbMode = cameraParams.get(
-                        CameraParameters::KEY_WHITE_BALANCE);
-                ASSERT_TRUE((nullptr == wbMode) || (strcmp(
-                        CameraParameters::WHITE_BALANCE_AUTO, wbMode) == 0));
-
-                const char *effect = cameraParams.get(
-                        CameraParameters::KEY_EFFECT);
-                ASSERT_TRUE((nullptr == effect) || (strcmp(
-                        CameraParameters::EFFECT_NONE, effect) == 0));
-
-                ::android::Vector<Size> previewSizes;
-                cameraParams.getSupportedPreviewSizes(previewSizes);
-                ASSERT_FALSE(previewSizes.empty());
-                ::android::Vector<Size> pictureSizes;
-                cameraParams.getSupportedPictureSizes(pictureSizes);
-                ASSERT_FALSE(pictureSizes.empty());
-                const char *previewFormats = cameraParams.get(
-                        CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS);
-                ASSERT_NE(nullptr, previewFormats);
-                ::android::String8 previewFormatsString(previewFormats);
-                ASSERT_TRUE(previewFormatsString.contains(
-                        CameraParameters::PIXEL_FORMAT_YUV420SP));
-                ASSERT_NE(nullptr, cameraParams.get(
-                        CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS));
-                ASSERT_NE(nullptr, cameraParams.get(
-                        CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES));
-                const char *focusModes = cameraParams.get(
-                        CameraParameters::KEY_SUPPORTED_FOCUS_MODES);
-                ASSERT_NE(nullptr, focusModes);
-                ::android::String8 focusModesString(focusModes);
-                const char *focusMode = cameraParams.get(
-                        CameraParameters::KEY_FOCUS_MODE);
-                ASSERT_NE(nullptr, focusMode);
-                // Auto focus mode should be default
-                if (focusModesString.contains(
-                        CameraParameters::FOCUS_MODE_AUTO)) {
-                    ASSERT_TRUE(strcmp(
-                            CameraParameters::FOCUS_MODE_AUTO, focusMode) == 0);
-                }
-                ASSERT_TRUE(0 < cameraParams.getInt(
-                        CameraParameters::KEY_FOCAL_LENGTH));
-                int32_t horizontalViewAngle = cameraParams.getInt(
-                        CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE);
-                ASSERT_TRUE((0 < horizontalViewAngle) &&
-                            (360 >= horizontalViewAngle));
-                int32_t verticalViewAngle = cameraParams.getInt(
-                        CameraParameters::KEY_VERTICAL_VIEW_ANGLE);
-                ASSERT_TRUE((0 < verticalViewAngle) &&
-                            (360 >= verticalViewAngle));
-                int32_t jpegQuality = cameraParams.getInt(
-                        CameraParameters::KEY_JPEG_QUALITY);
-                ASSERT_TRUE((1 <= jpegQuality) && (100 >= jpegQuality));
-                int32_t jpegThumbQuality = cameraParams.getInt(
-                        CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
-                ASSERT_TRUE((1 <= jpegThumbQuality) &&
-                            (100 >= jpegThumbQuality));
-
-                cameraParams.setPictureSize(pictureSizes[0].width,
-                        pictureSizes[0].height);
-                cameraParams.setPreviewSize(previewSizes[0].width,
-                        previewSizes[0].height);
+            cameraParams.setPictureSize(pictureSizes[0].width, pictureSizes[0].height);
+            cameraParams.setPreviewSize(previewSizes[0].width, previewSizes[0].height);
 
-                setParameters(device1, cameraParams);
-                getParameters(device1, &cameraParams /*out*/);
+            setParameters(device1, cameraParams);
+            getParameters(device1, &cameraParams /*out*/);
 
-                cameraParams.getPictureSize(&width, &height);
-                ASSERT_TRUE((pictureSizes[0].width == width) &&
-                        (pictureSizes[0].height == height));
-                cameraParams.getPreviewSize(&width, &height);
-                ASSERT_TRUE((previewSizes[0].width == width) &&
-                        (previewSizes[0].height == height));
+            cameraParams.getPictureSize(&width, &height);
+            ASSERT_TRUE((pictureSizes[0].width == width) && (pictureSizes[0].height == height));
+            cameraParams.getPreviewSize(&width, &height);
+            ASSERT_TRUE((previewSizes[0].width == width) && (previewSizes[0].height == height));
 
-                Return<void> ret = device1->close();
-                ASSERT_TRUE(ret.isOk());
-            }
+            Return<void> ret = device1->close();
+            ASSERT_TRUE(ret.isOk());
         }
     }
 }
@@ -2027,50 +1874,50 @@ TEST_F(CameraHidlTest, getSetParameters) {
 // Verify that the static camera characteristics can be retrieved
 // successfully.
 TEST_F(CameraHidlTest, getCameraCharacteristics) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
-                ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_2;
-                ALOGI("getCameraCharacteristics: Testing camera device %s",
-                      name.c_str());
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+
+    for (const auto& name : cameraDeviceNames) {
+        int deviceVersion = getCameraDeviceVersion(name, mProviderType);
+        switch (deviceVersion) {
+            case CAMERA_DEVICE_API_VERSION_3_3:
+            case CAMERA_DEVICE_API_VERSION_3_2: {
+                ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_x;
+                ALOGI("getCameraCharacteristics: Testing camera device %s", name.c_str());
                 Return<void> ret;
-                ret = provider.second->getCameraDeviceInterface_V3_x(
-                    name,
-                    [&](auto status, const auto& device) {
-                        ALOGI("getCameraDeviceInterface_V3_x returns status:%d",
-                              (int)status);
+                ret = mProvider->getCameraDeviceInterface_V3_x(
+                    name, [&](auto status, const auto& device) {
+                        ALOGI("getCameraDeviceInterface_V3_x returns status:%d", (int)status);
                         ASSERT_EQ(Status::OK, status);
                         ASSERT_NE(device, nullptr);
-                        device3_2 = device;
+                        device3_x = device;
                     });
                 ASSERT_TRUE(ret.isOk());
 
-                ret = device3_2->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);
-                    });
+                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);
+                });
                 ASSERT_TRUE(ret.isOk());
             }
+            break;
+            case CAMERA_DEVICE_API_VERSION_1_0: {
+                //Not applicable
+            }
+            break;
+            default: {
+                ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
+                ADD_FAILURE();
+            }
+            break;
         }
     }
 }
@@ -2078,44 +1925,39 @@ TEST_F(CameraHidlTest, getCameraCharacteristics) {
 //In case it is supported verify that torch can be enabled.
 //Check for corresponding toch callbacks as well.
 TEST_F(CameraHidlTest, setTorchMode) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-        bool torchControlSupported = false;
-        Return<void> ret;
-
-        ret = provider.second->isSetTorchModeSupported(
-            [&](auto status, bool support) {
-                ALOGI("isSetTorchModeSupported returns status:%d supported:%d",
-                        (int)status, support);
-                ASSERT_EQ(Status::OK, status);
-                torchControlSupported = support;
-            });
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    bool torchControlSupported = false;
+    Return<void> ret;
 
+    ret = mProvider->isSetTorchModeSupported([&](auto status, bool support) {
+        ALOGI("isSetTorchModeSupported returns status:%d supported:%d", (int)status, support);
+        ASSERT_EQ(Status::OK, status);
+        torchControlSupported = support;
+    });
 
-        sp<TorchProviderCb> cb = new TorchProviderCb(this);
-        Return<Status> returnStatus = provider.second->setCallback(cb);
-        ASSERT_TRUE(returnStatus.isOk());
-        ASSERT_EQ(Status::OK, returnStatus);
+    sp<TorchProviderCb> cb = new TorchProviderCb(this);
+    Return<Status> returnStatus = mProvider->setCallback(cb);
+    ASSERT_TRUE(returnStatus.isOk());
+    ASSERT_EQ(Status::OK, returnStatus);
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
-                ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_2;
+    for (const auto& name : cameraDeviceNames) {
+        int deviceVersion = getCameraDeviceVersion(name, mProviderType);
+        switch (deviceVersion) {
+            case CAMERA_DEVICE_API_VERSION_3_3:
+            case CAMERA_DEVICE_API_VERSION_3_2: {
+                ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_x;
                 ALOGI("setTorchMode: Testing camera device %s", name.c_str());
-                ret = provider.second->getCameraDeviceInterface_V3_x(
-                    name,
-                    [&](auto status, const auto& device) {
-                        ALOGI("getCameraDeviceInterface_V3_x returns status:%d",
-                              (int)status);
+                ret = mProvider->getCameraDeviceInterface_V3_x(
+                    name, [&](auto status, const auto& device) {
+                        ALOGI("getCameraDeviceInterface_V3_x returns status:%d", (int)status);
                         ASSERT_EQ(Status::OK, status);
                         ASSERT_NE(device, nullptr);
-                        device3_2 = device;
+                        device3_x = device;
                     });
                 ASSERT_TRUE(ret.isOk());
 
                 mTorchStatus = TorchModeStatus::NOT_AVAILABLE;
-                returnStatus = device3_2->setTorchMode(TorchMode::ON);
+                returnStatus = device3_x->setTorchMode(TorchMode::ON);
                 ASSERT_TRUE(returnStatus.isOk());
                 if (!torchControlSupported) {
                     ASSERT_EQ(Status::METHOD_NOT_SUPPORTED, returnStatus);
@@ -2127,16 +1969,14 @@ TEST_F(CameraHidlTest, setTorchMode) {
                             std::unique_lock<std::mutex> l(mTorchLock);
                             while (TorchModeStatus::NOT_AVAILABLE == mTorchStatus) {
                                 auto timeout = std::chrono::system_clock::now() +
-                                        std::chrono::seconds(kTorchTimeoutSec);
-                                ASSERT_NE(std::cv_status::timeout,
-                                        mTorchCond.wait_until(l, timeout));
+                                               std::chrono::seconds(kTorchTimeoutSec);
+                                ASSERT_NE(std::cv_status::timeout, mTorchCond.wait_until(l, timeout));
                             }
-                            ASSERT_EQ(TorchModeStatus::AVAILABLE_ON,
-                                    mTorchStatus);
+                            ASSERT_EQ(TorchModeStatus::AVAILABLE_ON, mTorchStatus);
                             mTorchStatus = TorchModeStatus::NOT_AVAILABLE;
                         }
 
-                        returnStatus = device3_2->setTorchMode(TorchMode::OFF);
+                        returnStatus = device3_x->setTorchMode(TorchMode::OFF);
                         ASSERT_TRUE(returnStatus.isOk());
                         ASSERT_EQ(Status::OK, returnStatus);
 
@@ -2144,24 +1984,21 @@ TEST_F(CameraHidlTest, setTorchMode) {
                             std::unique_lock<std::mutex> l(mTorchLock);
                             while (TorchModeStatus::NOT_AVAILABLE == mTorchStatus) {
                                 auto timeout = std::chrono::system_clock::now() +
-                                        std::chrono::seconds(kTorchTimeoutSec);
-                                ASSERT_NE(std::cv_status::timeout,
-                                        mTorchCond.wait_until(l, timeout));
+                                               std::chrono::seconds(kTorchTimeoutSec);
+                                ASSERT_NE(std::cv_status::timeout, mTorchCond.wait_until(l, timeout));
                             }
-                            ASSERT_EQ(TorchModeStatus::AVAILABLE_OFF,
-                                    mTorchStatus);
+                            ASSERT_EQ(TorchModeStatus::AVAILABLE_OFF, mTorchStatus);
                         }
                     }
                 }
-            } else if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
+            }
+            break;
+            case CAMERA_DEVICE_API_VERSION_1_0: {
                 ::android::sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
                 ALOGI("dumpState: Testing camera device %s", name.c_str());
-                ret = provider.second->getCameraDeviceInterface_V1_x(
-                    name,
-                    [&](auto status, const auto& device) {
-                        ALOGI("getCameraDeviceInterface_V1_x returns status:%d",
-                              (int)status);
+                ret = mProvider->getCameraDeviceInterface_V1_x(
+                    name, [&](auto status, const auto& device) {
+                        ALOGI("getCameraDeviceInterface_V1_x returns status:%d", (int)status);
                         ASSERT_EQ(Status::OK, status);
                         ASSERT_NE(device, nullptr);
                         device1 = device;
@@ -2181,12 +2018,11 @@ TEST_F(CameraHidlTest, setTorchMode) {
                             std::unique_lock<std::mutex> l(mTorchLock);
                             while (TorchModeStatus::NOT_AVAILABLE == mTorchStatus) {
                                 auto timeout = std::chrono::system_clock::now() +
-                                        std::chrono::seconds(kTorchTimeoutSec);
-                                ASSERT_NE(std::cv_status::timeout,
-                                        mTorchCond.wait_until(l, timeout));
+                                               std::chrono::seconds(kTorchTimeoutSec);
+                                ASSERT_NE(std::cv_status::timeout, mTorchCond.wait_until(l,
+                                        timeout));
                             }
-                            ASSERT_EQ(TorchModeStatus::AVAILABLE_ON,
-                                    mTorchStatus);
+                            ASSERT_EQ(TorchModeStatus::AVAILABLE_ON, mTorchStatus);
                             mTorchStatus = TorchModeStatus::NOT_AVAILABLE;
                         }
 
@@ -2198,46 +2034,49 @@ TEST_F(CameraHidlTest, setTorchMode) {
                             std::unique_lock<std::mutex> l(mTorchLock);
                             while (TorchModeStatus::NOT_AVAILABLE == mTorchStatus) {
                                 auto timeout = std::chrono::system_clock::now() +
-                                        std::chrono::seconds(kTorchTimeoutSec);
-                                ASSERT_NE(std::cv_status::timeout,
-                                        mTorchCond.wait_until(l, timeout));
+                                               std::chrono::seconds(kTorchTimeoutSec);
+                                ASSERT_NE(std::cv_status::timeout, mTorchCond.wait_until(l,
+                                        timeout));
                             }
-                            ASSERT_EQ(TorchModeStatus::AVAILABLE_OFF,
-                                    mTorchStatus);
+                            ASSERT_EQ(TorchModeStatus::AVAILABLE_OFF, mTorchStatus);
                         }
                     }
                 }
                 ret = device1->close();
                 ASSERT_TRUE(ret.isOk());
             }
+            break;
+            default: {
+                ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
+                ADD_FAILURE();
+            }
+            break;
         }
-
-        returnStatus = provider.second->setCallback(nullptr);
-        ASSERT_TRUE(returnStatus.isOk());
-        ASSERT_EQ(Status::OK, returnStatus);
     }
+
+    returnStatus = mProvider->setCallback(nullptr);
+    ASSERT_TRUE(returnStatus.isOk());
+    ASSERT_EQ(Status::OK, returnStatus);
 }
 
 // Check dump functionality.
 TEST_F(CameraHidlTest, dumpState) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-        Return<void> ret;
-
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
-                ::android::sp<ICameraDevice> device3_2;
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    Return<void> ret;
+
+    for (const auto& name : cameraDeviceNames) {
+        int deviceVersion = getCameraDeviceVersion(name, mProviderType);
+        switch (deviceVersion) {
+            case CAMERA_DEVICE_API_VERSION_3_3:
+            case CAMERA_DEVICE_API_VERSION_3_2: {
+                ::android::sp<ICameraDevice> device3_x;
                 ALOGI("dumpState: Testing camera device %s", name.c_str());
-                ret = provider.second->getCameraDeviceInterface_V3_x(
-                    name,
-                    [&](auto status, const auto& device) {
-                        ALOGI("getCameraDeviceInterface_V3_x returns status:%d",
-                              (int)status);
+                ret = mProvider->getCameraDeviceInterface_V3_x(
+                    name, [&](auto status, const auto& device) {
+                        ALOGI("getCameraDeviceInterface_V3_x returns status:%d", (int)status);
                         ASSERT_EQ(Status::OK, status);
                         ASSERT_NE(device, nullptr);
-                        device3_2 = device;
+                        device3_x = device;
                     });
                 ASSERT_TRUE(ret.isOk());
 
@@ -2245,19 +2084,18 @@ TEST_F(CameraHidlTest, dumpState) {
                 raw_handle->data[0] = open(kDumpOutput, O_RDWR);
                 ASSERT_GE(raw_handle->data[0], 0);
                 hidl_handle handle = raw_handle;
-                ret= device3_2->dumpState(handle);
+                ret = device3_x->dumpState(handle);
                 ASSERT_TRUE(ret.isOk());
                 close(raw_handle->data[0]);
                 native_handle_delete(raw_handle);
-            } else if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
+            }
+            break;
+            case CAMERA_DEVICE_API_VERSION_1_0: {
                 ::android::sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
                 ALOGI("dumpState: Testing camera device %s", name.c_str());
-                ret = provider.second->getCameraDeviceInterface_V1_x(
-                    name,
-                    [&](auto status, const auto& device) {
-                        ALOGI("getCameraDeviceInterface_V1_x returns status:%d",
-                              (int)status);
+                ret = mProvider->getCameraDeviceInterface_V1_x(
+                    name, [&](auto status, const auto& device) {
+                        ALOGI("getCameraDeviceInterface_V1_x returns status:%d", (int)status);
                         ASSERT_EQ(Status::OK, status);
                         ASSERT_NE(device, nullptr);
                         device1 = device;
@@ -2274,50 +2112,61 @@ TEST_F(CameraHidlTest, dumpState) {
                 close(raw_handle->data[0]);
                 native_handle_delete(raw_handle);
             }
+            break;
+            default: {
+                ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
+                ADD_FAILURE();
+            }
+            break;
         }
     }
 }
 
 // Open, dumpStates, then close
 TEST_F(CameraHidlTest, openClose) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-        Return<void> ret;
-
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
-                ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_2;
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    Return<void> ret;
+
+    for (const auto& name : cameraDeviceNames) {
+        int deviceVersion = getCameraDeviceVersion(name, mProviderType);
+        switch (deviceVersion) {
+            case CAMERA_DEVICE_API_VERSION_3_3:
+            case CAMERA_DEVICE_API_VERSION_3_2: {
+                ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_x;
                 ALOGI("openClose: Testing camera device %s", name.c_str());
-                ret = provider.second->getCameraDeviceInterface_V3_x(
-                    name,
-                    [&](auto status, const auto& device) {
-                        ALOGI("getCameraDeviceInterface_V3_x returns status:%d",
-                              (int)status);
+                ret = mProvider->getCameraDeviceInterface_V3_x(
+                    name, [&](auto status, const auto& device) {
+                        ALOGI("getCameraDeviceInterface_V3_x returns status:%d", (int)status);
                         ASSERT_EQ(Status::OK, status);
                         ASSERT_NE(device, nullptr);
-                        device3_2 = device;
+                        device3_x = device;
                     });
                 ASSERT_TRUE(ret.isOk());
 
                 sp<EmptyDeviceCb> cb = new EmptyDeviceCb;
                 sp<ICameraDeviceSession> session;
-                ret = device3_2->open(
-                    cb,
-                    [&](auto status, const auto& newSession) {
-                        ALOGI("device::open returns status:%d", (int)status);
-                        ASSERT_EQ(Status::OK, status);
-                        ASSERT_NE(newSession, nullptr);
-                        session = newSession;
-                    });
+                ret = device3_x->open(cb, [&](auto status, const auto& newSession) {
+                    ALOGI("device::open returns status:%d", (int)status);
+                    ASSERT_EQ(Status::OK, status);
+                    ASSERT_NE(newSession, nullptr);
+                    session = newSession;
+                });
                 ASSERT_TRUE(ret.isOk());
-
+                // Ensure that a device labeling itself as 3.3 can have its session interface cast
+                // to the 3.3 interface, and that lower versions can't be cast to it.
+                auto castResult = device::V3_3::ICameraDeviceSession::castFrom(session);
+                ASSERT_TRUE(castResult.isOk());
+                sp<device::V3_3::ICameraDeviceSession> sessionV3_3 = castResult;
+                if (deviceVersion == CAMERA_DEVICE_API_VERSION_3_3) {
+                    ASSERT_TRUE(sessionV3_3.get() != nullptr);
+                } else {
+                    ASSERT_TRUE(sessionV3_3.get() == nullptr);
+                }
                 native_handle_t* raw_handle = native_handle_create(1, 0);
                 raw_handle->data[0] = open(kDumpOutput, O_RDWR);
                 ASSERT_GE(raw_handle->data[0], 0);
                 hidl_handle handle = raw_handle;
-                ret = device3_2->dumpState(handle);
+                ret = device3_x->dumpState(handle);
                 ASSERT_TRUE(ret.isOk());
                 close(raw_handle->data[0]);
                 native_handle_delete(raw_handle);
@@ -2326,10 +2175,11 @@ TEST_F(CameraHidlTest, openClose) {
                 ASSERT_TRUE(ret.isOk());
                 // TODO: test all session API calls return INTERNAL_ERROR after close
                 // TODO: keep a wp copy here and verify session cannot be promoted out of this scope
-            } else if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
+            }
+            break;
+            case CAMERA_DEVICE_API_VERSION_1_0: {
                 sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                openCameraDevice(name, provider.second, &device1 /*out*/);
+                openCameraDevice(name, mProvider, &device1 /*out*/);
                 ASSERT_NE(nullptr, device1.get());
 
                 native_handle_t* raw_handle = native_handle_create(1, 0);
@@ -2345,6 +2195,12 @@ TEST_F(CameraHidlTest, openClose) {
                 ret = device1->close();
                 ASSERT_TRUE(ret.isOk());
             }
+            break;
+            default: {
+                ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
+                ADD_FAILURE();
+            }
+            break;
         }
     }
 }
@@ -2352,124 +2208,140 @@ TEST_F(CameraHidlTest, openClose) {
 // Check whether all common default request settings can be sucessfully
 // constructed.
 TEST_F(CameraHidlTest, constructDefaultRequestSettings) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
-                ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_2;
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+
+    for (const auto& name : cameraDeviceNames) {
+        int deviceVersion = getCameraDeviceVersion(name, mProviderType);
+        switch (deviceVersion) {
+            case CAMERA_DEVICE_API_VERSION_3_3:
+            case CAMERA_DEVICE_API_VERSION_3_2: {
+                ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_x;
                 Return<void> ret;
-                ALOGI("constructDefaultRequestSettings: Testing camera device %s",
-                      name.c_str());
-                ret = provider.second->getCameraDeviceInterface_V3_x(
-                    name,
-                    [&](auto status, const auto& device) {
-                        ALOGI("getCameraDeviceInterface_V3_x returns status:%d",
-                              (int)status);
+                ALOGI("constructDefaultRequestSettings: Testing camera device %s", name.c_str());
+                ret = mProvider->getCameraDeviceInterface_V3_x(
+                    name, [&](auto status, const auto& device) {
+                        ALOGI("getCameraDeviceInterface_V3_x returns status:%d", (int)status);
                         ASSERT_EQ(Status::OK, status);
                         ASSERT_NE(device, nullptr);
-                        device3_2 = device;
+                        device3_x = device;
                     });
                 ASSERT_TRUE(ret.isOk());
 
                 sp<EmptyDeviceCb> cb = new EmptyDeviceCb;
                 sp<ICameraDeviceSession> session;
-                ret = device3_2->open(
-                    cb,
-                    [&](auto status, const auto& newSession) {
-                        ALOGI("device::open returns status:%d", (int)status);
-                        ASSERT_EQ(Status::OK, status);
-                        ASSERT_NE(newSession, nullptr);
-                        session = newSession;
-                    });
+                ret = device3_x->open(cb, [&](auto status, const auto& newSession) {
+                    ALOGI("device::open returns status:%d", (int)status);
+                    ASSERT_EQ(Status::OK, status);
+                    ASSERT_NE(newSession, nullptr);
+                    session = newSession;
+                });
                 ASSERT_TRUE(ret.isOk());
 
-                for (uint32_t t = (uint32_t) RequestTemplate::PREVIEW;
-                        t <= (uint32_t) RequestTemplate::MANUAL; t++) {
-                    RequestTemplate reqTemplate = (RequestTemplate) t;
-                    ret = session->constructDefaultRequestSettings(
-                        reqTemplate,
-                        [&](auto status, const auto& req) {
-                            ALOGI("constructDefaultRequestSettings returns status:%d",
-                                  (int)status);
-                            if (reqTemplate == RequestTemplate::ZERO_SHUTTER_LAG ||
-                                    reqTemplate == RequestTemplate::MANUAL) {
-                                // optional templates
-                                ASSERT_TRUE((status == Status::OK) ||
-                                        (status == Status::ILLEGAL_ARGUMENT));
-                            } else {
-                                ASSERT_EQ(Status::OK, status);
-                            }
-
-                            if (status == Status::OK) {
-                                const camera_metadata_t* metadata =
-                                    (camera_metadata_t*) req.data();
-                                size_t expectedSize = req.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
-                                // request keys we've defined for each template
-                                ASSERT_GT(entryCount, 0u);
-                                ALOGI("template %u metadata entry count is %zu",
-                                      t, entryCount);
-                            } else {
-                                ASSERT_EQ(0u, req.size());
-                            }
-                        });
+                for (uint32_t t = (uint32_t)RequestTemplate::PREVIEW;
+                     t <= (uint32_t)RequestTemplate::MANUAL; t++) {
+                    RequestTemplate reqTemplate = (RequestTemplate)t;
+                    ret =
+                        session->constructDefaultRequestSettings(
+                            reqTemplate, [&](auto status, const auto& req) {
+                                ALOGI("constructDefaultRequestSettings returns status:%d",
+                                      (int)status);
+                                if (reqTemplate == RequestTemplate::ZERO_SHUTTER_LAG ||
+                                        reqTemplate == RequestTemplate::MANUAL) {
+                                    // optional templates
+                                    ASSERT_TRUE((status == Status::OK) ||
+                                            (status == Status::ILLEGAL_ARGUMENT));
+                                } else {
+                                    ASSERT_EQ(Status::OK, status);
+                                }
+
+                                if (status == Status::OK) {
+                                    const camera_metadata_t* metadata =
+                                        (camera_metadata_t*) req.data();
+                                    size_t expectedSize = req.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
+                                    // request keys we've defined for each template
+                                    ASSERT_GT(entryCount, 0u);
+                                    ALOGI("template %u metadata entry count is %zu",
+                                          t, entryCount);
+                                } else {
+                                    ASSERT_EQ(0u, req.size());
+                                }
+                            });
                     ASSERT_TRUE(ret.isOk());
                 }
                 ret = session->close();
                 ASSERT_TRUE(ret.isOk());
             }
+            break;
+            case CAMERA_DEVICE_API_VERSION_1_0: {
+                //Not applicable
+            }
+            break;
+            default: {
+                ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
+                ADD_FAILURE();
+            }
+            break;
         }
     }
 }
 
+
 // Verify that all supported stream formats and sizes can be configured
 // successfully.
 TEST_F(CameraHidlTest, configureStreamsAvailableOutputs) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-        std::vector<AvailableStream> outputStreams;
-
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
-                camera_metadata_t *staticMeta;
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    std::vector<AvailableStream> outputStreams;
+
+    for (const auto& name : cameraDeviceNames) {
+        int deviceVersion = getCameraDeviceVersion(name, mProviderType);
+        switch (deviceVersion) {
+            case CAMERA_DEVICE_API_VERSION_3_3:
+            case CAMERA_DEVICE_API_VERSION_3_2: {
+                camera_metadata_tstaticMeta;
                 Return<void> ret;
                 sp<ICameraDeviceSession> session;
-                openEmptyDeviceSession(name, provider.second, &session /*out*/,
-                        &staticMeta /*out*/);
+                sp<device::V3_3::ICameraDeviceSession> session3_3;
+                openEmptyDeviceSession(name, mProvider,
+                        &session /*out*/, &session3_3 /*out*/, &staticMeta /*out*/);
 
                 outputStreams.clear();
-                ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta,
-                        outputStreams));
+                ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, outputStreams));
                 ASSERT_NE(0u, outputStreams.size());
 
                 int32_t streamId = 0;
-                for (auto &it : outputStreams) {
-                    Stream stream = {streamId, StreamType::OUTPUT,
-                            static_cast<uint32_t> (it.width),
-                            static_cast<uint32_t> (it.height),
-                            static_cast<PixelFormat> (it.format),
-                            GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, 0,
-                            StreamRotation::ROTATION_0};
+                for (auto& it : outputStreams) {
+                    Stream stream = {streamId,
+                                     StreamType::OUTPUT,
+                                     static_cast<uint32_t>(it.width),
+                                     static_cast<uint32_t>(it.height),
+                                     static_cast<PixelFormat>(it.format),
+                                     GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
+                                     0,
+                                     StreamRotation::ROTATION_0};
                     ::android::hardware::hidl_vec<Stream> streams = {stream};
-                    StreamConfiguration config = {streams,
-                            StreamConfigurationMode::NORMAL_MODE};
-                    ret = session->configureStreams(config, [streamId] (Status s,
-                            HalStreamConfiguration halConfig) {
-                        ASSERT_EQ(Status::OK, s);
-                        ASSERT_EQ(1u, halConfig.streams.size());
-                        ASSERT_EQ(halConfig.streams[0].id, streamId);
-                    });
+                    StreamConfiguration config = {streams, StreamConfigurationMode::NORMAL_MODE};
+                    if (session3_3 == nullptr) {
+                        ret = session->configureStreams(config,
+                                [streamId](Status s, HalStreamConfiguration halConfig) {
+                                    ASSERT_EQ(Status::OK, s);
+                                    ASSERT_EQ(1u, halConfig.streams.size());
+                                    ASSERT_EQ(halConfig.streams[0].id, streamId);
+                                });
+                    } else {
+                        ret = session3_3->configureStreams_3_3(config,
+                                [streamId](Status s, device::V3_3::HalStreamConfiguration halConfig) {
+                                    ASSERT_EQ(Status::OK, s);
+                                    ASSERT_EQ(1u, halConfig.streams.size());
+                                    ASSERT_EQ(halConfig.streams[0].v3_2.id, streamId);
+                                });
+                    }
                     ASSERT_TRUE(ret.isOk());
                     streamId++;
                 }
@@ -2478,92 +2350,135 @@ TEST_F(CameraHidlTest, configureStreamsAvailableOutputs) {
                 ret = session->close();
                 ASSERT_TRUE(ret.isOk());
             }
+            break;
+            case CAMERA_DEVICE_API_VERSION_1_0: {
+                //Not applicable
+            }
+            break;
+            default: {
+                ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
+                ADD_FAILURE();
+            }
+            break;
         }
     }
 }
 
 // Check for correct handling of invalid/incorrect configuration parameters.
 TEST_F(CameraHidlTest, configureStreamsInvalidOutputs) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-        std::vector<AvailableStream> outputStreams;
-
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
-                camera_metadata_t *staticMeta;
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    std::vector<AvailableStream> outputStreams;
+
+    for (const auto& name : cameraDeviceNames) {
+        int deviceVersion = getCameraDeviceVersion(name, mProviderType);
+        switch (deviceVersion) {
+            case CAMERA_DEVICE_API_VERSION_3_3:
+            case CAMERA_DEVICE_API_VERSION_3_2: {
+                camera_metadata_tstaticMeta;
                 Return<void> ret;
                 sp<ICameraDeviceSession> session;
-                openEmptyDeviceSession(name, provider.second, &session /*out*/,
-                        &staticMeta /*out*/);
+                sp<device::V3_3::ICameraDeviceSession> session3_3;
+                openEmptyDeviceSession(name, mProvider,
+                        &session /*out*/, &session3_3 /*out*/, &staticMeta /*out*/);
 
                 outputStreams.clear();
-                ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta,
-                        outputStreams));
+                ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, outputStreams));
                 ASSERT_NE(0u, outputStreams.size());
 
                 int32_t streamId = 0;
-                Stream stream = {streamId++, StreamType::OUTPUT,
-                        static_cast<uint32_t> (0),
-                        static_cast<uint32_t> (0),
-                        static_cast<PixelFormat> (outputStreams[0].format),
-                        GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, 0,
-                        StreamRotation::ROTATION_0};
+                Stream stream = {streamId++,
+                                 StreamType::OUTPUT,
+                                 static_cast<uint32_t>(0),
+                                 static_cast<uint32_t>(0),
+                                 static_cast<PixelFormat>(outputStreams[0].format),
+                                 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
+                                 0,
+                                 StreamRotation::ROTATION_0};
                 ::android::hardware::hidl_vec<Stream> streams = {stream};
-                StreamConfiguration config = {streams,
-                        StreamConfigurationMode::NORMAL_MODE};
-                ret = session->configureStreams(config, [] (Status s,
-                        HalStreamConfiguration) {
-                    ASSERT_TRUE((Status::ILLEGAL_ARGUMENT == s) ||
-                                (Status::INTERNAL_ERROR == s));
-                });
+                StreamConfiguration config = {streams, StreamConfigurationMode::NORMAL_MODE};
+                if(session3_3 == nullptr) {
+                    ret = session->configureStreams(config,
+                        [](Status s, HalStreamConfiguration) {
+                            ASSERT_TRUE((Status::ILLEGAL_ARGUMENT == s) ||
+                                    (Status::INTERNAL_ERROR == s));
+                        });
+                } else {
+                    ret = session3_3->configureStreams_3_3(config,
+                        [](Status s, device::V3_3::HalStreamConfiguration) {
+                            ASSERT_TRUE((Status::ILLEGAL_ARGUMENT == s) ||
+                                    (Status::INTERNAL_ERROR == s));
+                        });
+                }
                 ASSERT_TRUE(ret.isOk());
 
-                stream = {streamId++, StreamType::OUTPUT,
-                        static_cast<uint32_t> (UINT32_MAX),
-                        static_cast<uint32_t> (UINT32_MAX),
-                        static_cast<PixelFormat> (outputStreams[0].format),
-                        GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, 0,
-                        StreamRotation::ROTATION_0};
+                stream = {streamId++,
+                          StreamType::OUTPUT,
+                          static_cast<uint32_t>(UINT32_MAX),
+                          static_cast<uint32_t>(UINT32_MAX),
+                          static_cast<PixelFormat>(outputStreams[0].format),
+                          GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
+                          0,
+                          StreamRotation::ROTATION_0};
                 streams[0] = stream;
-                config = {streams,
-                        StreamConfigurationMode::NORMAL_MODE};
-                ret = session->configureStreams(config, [] (Status s,
-                        HalStreamConfiguration) {
-                    ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
-                });
+                config = {streams, StreamConfigurationMode::NORMAL_MODE};
+                if(session3_3 == nullptr) {
+                    ret = session->configureStreams(config, [](Status s,
+                                HalStreamConfiguration) {
+                            ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
+                        });
+                } else {
+                    ret = session3_3->configureStreams_3_3(config, [](Status s,
+                                device::V3_3::HalStreamConfiguration) {
+                            ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
+                        });
+                }
                 ASSERT_TRUE(ret.isOk());
 
-                for (auto &it : outputStreams) {
-                    stream = {streamId++, StreamType::OUTPUT,
-                            static_cast<uint32_t> (it.width),
-                            static_cast<uint32_t> (it.height),
-                            static_cast<PixelFormat> (UINT32_MAX),
-                            GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, 0,
-                            StreamRotation::ROTATION_0};
+                for (auto& it : outputStreams) {
+                    stream = {streamId++,
+                              StreamType::OUTPUT,
+                              static_cast<uint32_t>(it.width),
+                              static_cast<uint32_t>(it.height),
+                              static_cast<PixelFormat>(UINT32_MAX),
+                              GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
+                              0,
+                              StreamRotation::ROTATION_0};
                     streams[0] = stream;
-                    config = {streams,
-                            StreamConfigurationMode::NORMAL_MODE};
-                    ret = session->configureStreams(config, [] (Status s,
-                            HalStreamConfiguration) {
-                        ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
-                    });
+                    config = {streams, StreamConfigurationMode::NORMAL_MODE};
+                    if(session3_3 == nullptr) {
+                        ret = session->configureStreams(config,
+                                [](Status s, HalStreamConfiguration) {
+                                    ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
+                                });
+                    } else {
+                        ret = session3_3->configureStreams_3_3(config,
+                                [](Status s, device::V3_3::HalStreamConfiguration) {
+                                    ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
+                                });
+                    }
                     ASSERT_TRUE(ret.isOk());
 
-                    stream = {streamId++, StreamType::OUTPUT,
-                            static_cast<uint32_t> (it.width),
-                            static_cast<uint32_t> (it.height),
-                            static_cast<PixelFormat> (it.format),
-                            GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, 0,
-                            static_cast<StreamRotation> (UINT32_MAX)};
+                    stream = {streamId++,
+                              StreamType::OUTPUT,
+                              static_cast<uint32_t>(it.width),
+                              static_cast<uint32_t>(it.height),
+                              static_cast<PixelFormat>(it.format),
+                              GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
+                              0,
+                              static_cast<StreamRotation>(UINT32_MAX)};
                     streams[0] = stream;
-                    config = {streams,
-                            StreamConfigurationMode::NORMAL_MODE};
-                    ret = session->configureStreams(config, [] (Status s,
-                            HalStreamConfiguration) {
-                        ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
-                    });
+                    config = {streams, StreamConfigurationMode::NORMAL_MODE};
+                    if(session3_3 == nullptr) {
+                        ret = session->configureStreams(config,
+                                [](Status s, HalStreamConfiguration) {
+                                    ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
+                                });
+                    } else {
+                        ret = session3_3->configureStreams_3_3(config,
+                                [](Status s, device::V3_3::HalStreamConfiguration) {
+                                    ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
+                                });
+                    }
                     ASSERT_TRUE(ret.isOk());
                 }
 
@@ -2571,6 +2486,16 @@ TEST_F(CameraHidlTest, configureStreamsInvalidOutputs) {
                 ret = session->close();
                 ASSERT_TRUE(ret.isOk());
             }
+            break;
+            case CAMERA_DEVICE_API_VERSION_1_0: {
+                //Not applicable
+            }
+            break;
+            default: {
+                ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
+                ADD_FAILURE();
+            }
+            break;
         }
     }
 }
@@ -2578,20 +2503,21 @@ TEST_F(CameraHidlTest, configureStreamsInvalidOutputs) {
 // Check whether all supported ZSL output stream combinations can be
 // configured successfully.
 TEST_F(CameraHidlTest, configureStreamsZSLInputOutputs) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-        std::vector<AvailableStream> inputStreams;
-        std::vector<AvailableZSLInputOutput> inputOutputMap;
-
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
-                camera_metadata_t *staticMeta;
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    std::vector<AvailableStream> inputStreams;
+    std::vector<AvailableZSLInputOutput> inputOutputMap;
+
+    for (const auto& name : cameraDeviceNames) {
+        int deviceVersion = getCameraDeviceVersion(name, mProviderType);
+        switch (deviceVersion) {
+            case CAMERA_DEVICE_API_VERSION_3_3:
+            case CAMERA_DEVICE_API_VERSION_3_2: {
+                camera_metadata_tstaticMeta;
                 Return<void> ret;
                 sp<ICameraDeviceSession> session;
-                openEmptyDeviceSession(name, provider.second, &session /*out*/,
-                        &staticMeta /*out*/);
+                sp<device::V3_3::ICameraDeviceSession> session3_3;
+                openEmptyDeviceSession(name, mProvider,
+                        &session /*out*/, &session3_3 /*out*/, &staticMeta /*out*/);
 
                 Status rc = isZSLModeAvailable(staticMeta);
                 if (Status::METHOD_NOT_SUPPORTED == rc) {
@@ -2602,55 +2528,69 @@ TEST_F(CameraHidlTest, configureStreamsZSLInputOutputs) {
                 ASSERT_EQ(Status::OK, rc);
 
                 inputStreams.clear();
-                ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta,
-                        inputStreams));
+                ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, inputStreams));
                 ASSERT_NE(0u, inputStreams.size());
 
                 inputOutputMap.clear();
-                ASSERT_EQ(Status::OK, getZSLInputOutputMap(staticMeta,
-                        inputOutputMap));
+                ASSERT_EQ(Status::OK, getZSLInputOutputMap(staticMeta, inputOutputMap));
                 ASSERT_NE(0u, inputOutputMap.size());
 
                 int32_t streamId = 0;
-                for (auto &inputIter : inputOutputMap) {
+                for (autoinputIter : inputOutputMap) {
                     AvailableStream input;
-                    ASSERT_EQ(Status::OK,
-                            findLargestSize(inputStreams, inputIter.inputFormat, input));
+                    ASSERT_EQ(Status::OK, findLargestSize(inputStreams, inputIter.inputFormat,
+                            input));
                     ASSERT_NE(0u, inputStreams.size());
 
                     AvailableStream outputThreshold = {INT32_MAX, INT32_MAX,
-                            inputIter.outputFormat};
+                                                       inputIter.outputFormat};
                     std::vector<AvailableStream> outputStreams;
-                    ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta,
-                            outputStreams, &outputThreshold));
-                    for (auto &outputIter : outputStreams) {
-                        Stream zslStream = {streamId++, StreamType::OUTPUT,
-                                static_cast<uint32_t> (input.width),
-                                static_cast<uint32_t> (input.height),
-                                static_cast<PixelFormat> (input.format),
-                                GRALLOC_USAGE_HW_CAMERA_ZSL, 0,
-                                StreamRotation::ROTATION_0};
-                        Stream inputStream = {streamId++, StreamType::INPUT,
-                                static_cast<uint32_t> (input.width),
-                                static_cast<uint32_t> (input.height),
-                                static_cast<PixelFormat> (input.format), 0, 0,
-                                StreamRotation::ROTATION_0};
-                        Stream outputStream = {streamId++, StreamType::OUTPUT,
-                                static_cast<uint32_t> (outputIter.width),
-                                static_cast<uint32_t> (outputIter.height),
-                                static_cast<PixelFormat> (outputIter.format),
-                                GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, 0,
-                                StreamRotation::ROTATION_0};
-
-                        ::android::hardware::hidl_vec<Stream> streams = {
-                                inputStream, zslStream, outputStream};
+                    ASSERT_EQ(Status::OK,
+                              getAvailableOutputStreams(staticMeta, outputStreams,
+                                      &outputThreshold));
+                    for (auto& outputIter : outputStreams) {
+                        Stream zslStream = {streamId++,
+                                            StreamType::OUTPUT,
+                                            static_cast<uint32_t>(input.width),
+                                            static_cast<uint32_t>(input.height),
+                                            static_cast<PixelFormat>(input.format),
+                                            GRALLOC_USAGE_HW_CAMERA_ZSL,
+                                            0,
+                                            StreamRotation::ROTATION_0};
+                        Stream inputStream = {streamId++,
+                                              StreamType::INPUT,
+                                              static_cast<uint32_t>(input.width),
+                                              static_cast<uint32_t>(input.height),
+                                              static_cast<PixelFormat>(input.format),
+                                              0,
+                                              0,
+                                              StreamRotation::ROTATION_0};
+                        Stream outputStream = {streamId++,
+                                               StreamType::OUTPUT,
+                                               static_cast<uint32_t>(outputIter.width),
+                                               static_cast<uint32_t>(outputIter.height),
+                                               static_cast<PixelFormat>(outputIter.format),
+                                               GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
+                                               0,
+                                               StreamRotation::ROTATION_0};
+
+                        ::android::hardware::hidl_vec<Stream> streams = {inputStream, zslStream,
+                                                                         outputStream};
                         StreamConfiguration config = {streams,
-                                StreamConfigurationMode::NORMAL_MODE};
-                        ret = session->configureStreams(config,
-                                                    [](Status s, HalStreamConfiguration halConfig) {
-                                                        ASSERT_EQ(Status::OK, s);
-                                                        ASSERT_EQ(3u, halConfig.streams.size());
-                                                    });
+                                                      StreamConfigurationMode::NORMAL_MODE};
+                        if (session3_3 == nullptr) {
+                            ret = session->configureStreams(config,
+                                    [](Status s, HalStreamConfiguration halConfig) {
+                                        ASSERT_EQ(Status::OK, s);
+                                        ASSERT_EQ(3u, halConfig.streams.size());
+                                    });
+                        } else {
+                            ret = session3_3->configureStreams_3_3(config,
+                                    [](Status s, device::V3_3::HalStreamConfiguration halConfig) {
+                                        ASSERT_EQ(Status::OK, s);
+                                        ASSERT_EQ(3u, halConfig.streams.size());
+                                    });
+                        }
                         ASSERT_TRUE(ret.isOk());
                     }
                 }
@@ -2659,6 +2599,16 @@ TEST_F(CameraHidlTest, configureStreamsZSLInputOutputs) {
                 ret = session->close();
                 ASSERT_TRUE(ret.isOk());
             }
+            break;
+            case CAMERA_DEVICE_API_VERSION_1_0: {
+                //Not applicable
+            }
+            break;
+            default: {
+                ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
+                ADD_FAILURE();
+            }
+            break;
         }
     }
 }
@@ -2666,59 +2616,73 @@ TEST_F(CameraHidlTest, configureStreamsZSLInputOutputs) {
 // Verify that all supported preview + still capture stream combinations
 // can be configured successfully.
 TEST_F(CameraHidlTest, configureStreamsPreviewStillOutputs) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-        std::vector<AvailableStream> outputBlobStreams;
-        std::vector<AvailableStream> outputPreviewStreams;
-        AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
-                static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
-        AvailableStream blobThreshold = {INT32_MAX, INT32_MAX,
-                static_cast<int32_t>(PixelFormat::BLOB)};
-
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
-                camera_metadata_t *staticMeta;
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    std::vector<AvailableStream> outputBlobStreams;
+    std::vector<AvailableStream> outputPreviewStreams;
+    AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
+                                        static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
+    AvailableStream blobThreshold = {INT32_MAX, INT32_MAX,
+                                     static_cast<int32_t>(PixelFormat::BLOB)};
+
+    for (const auto& name : cameraDeviceNames) {
+        int deviceVersion = getCameraDeviceVersion(name, mProviderType);
+        switch (deviceVersion) {
+            case CAMERA_DEVICE_API_VERSION_3_3:
+            case CAMERA_DEVICE_API_VERSION_3_2: {
+                camera_metadata_tstaticMeta;
                 Return<void> ret;
                 sp<ICameraDeviceSession> session;
-                openEmptyDeviceSession(name, provider.second, &session /*out*/,
-                        &staticMeta /*out*/);
+                sp<device::V3_3::ICameraDeviceSession> session3_3;
+                openEmptyDeviceSession(name, mProvider,
+                        &session /*out*/, &session3_3 /*out*/, &staticMeta /*out*/);
 
                 outputBlobStreams.clear();
-                ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta,
-                        outputBlobStreams, &blobThreshold));
+                ASSERT_EQ(Status::OK,
+                          getAvailableOutputStreams(staticMeta, outputBlobStreams,
+                                  &blobThreshold));
                 ASSERT_NE(0u, outputBlobStreams.size());
 
                 outputPreviewStreams.clear();
-                ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta,
-                        outputPreviewStreams, &previewThreshold));
+                ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, outputPreviewStreams,
+                        &previewThreshold));
                 ASSERT_NE(0u, outputPreviewStreams.size());
 
                 int32_t streamId = 0;
-                for (auto &blobIter : outputBlobStreams) {
-                    for (auto &previewIter : outputPreviewStreams) {
-                        Stream previewStream = {streamId++, StreamType::OUTPUT,
-                                static_cast<uint32_t> (previewIter.width),
-                                static_cast<uint32_t> (previewIter.height),
-                                static_cast<PixelFormat> (previewIter.format),
-                                GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, 0,
-                                StreamRotation::ROTATION_0};
-                        Stream blobStream = {streamId++, StreamType::OUTPUT,
-                                static_cast<uint32_t> (blobIter.width),
-                                static_cast<uint32_t> (blobIter.height),
-                                static_cast<PixelFormat> (blobIter.format),
-                                GRALLOC1_CONSUMER_USAGE_CPU_READ, 0,
-                                StreamRotation::ROTATION_0};
-                        ::android::hardware::hidl_vec<Stream> streams = {
-                                previewStream, blobStream};
+                for (auto& blobIter : outputBlobStreams) {
+                    for (auto& previewIter : outputPreviewStreams) {
+                        Stream previewStream = {streamId++,
+                                                StreamType::OUTPUT,
+                                                static_cast<uint32_t>(previewIter.width),
+                                                static_cast<uint32_t>(previewIter.height),
+                                                static_cast<PixelFormat>(previewIter.format),
+                                                GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
+                                                0,
+                                                StreamRotation::ROTATION_0};
+                        Stream blobStream = {streamId++,
+                                             StreamType::OUTPUT,
+                                             static_cast<uint32_t>(blobIter.width),
+                                             static_cast<uint32_t>(blobIter.height),
+                                             static_cast<PixelFormat>(blobIter.format),
+                                             GRALLOC1_CONSUMER_USAGE_CPU_READ,
+                                             0,
+                                             StreamRotation::ROTATION_0};
+                        ::android::hardware::hidl_vec<Stream> streams = {previewStream,
+                                                                         blobStream};
                         StreamConfiguration config = {streams,
-                                StreamConfigurationMode::NORMAL_MODE};
-                        ret = session->configureStreams(config,
-                                                    [](Status s, HalStreamConfiguration halConfig) {
-                                                        ASSERT_EQ(Status::OK, s);
-                                                        ASSERT_EQ(2u, halConfig.streams.size());
-                                                    });
+                                                      StreamConfigurationMode::NORMAL_MODE};
+                        if (session3_3 == nullptr) {
+                            ret = session->configureStreams(config,
+                                    [](Status s, HalStreamConfiguration halConfig) {
+                                        ASSERT_EQ(Status::OK, s);
+                                        ASSERT_EQ(2u, halConfig.streams.size());
+                                    });
+                        } else {
+                            ret = session3_3->configureStreams_3_3(config,
+                                    [](Status s, device::V3_3::HalStreamConfiguration halConfig) {
+                                        ASSERT_EQ(Status::OK, s);
+                                        ASSERT_EQ(2u, halConfig.streams.size());
+                                    });
+                        }
                         ASSERT_TRUE(ret.isOk());
                     }
                 }
@@ -2727,6 +2691,16 @@ TEST_F(CameraHidlTest, configureStreamsPreviewStillOutputs) {
                 ret = session->close();
                 ASSERT_TRUE(ret.isOk());
             }
+            break;
+            case CAMERA_DEVICE_API_VERSION_1_0: {
+                //Not applicable
+            }
+            break;
+            default: {
+                ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
+                ADD_FAILURE();
+            }
+            break;
         }
     }
 }
@@ -2735,18 +2709,19 @@ TEST_F(CameraHidlTest, configureStreamsPreviewStillOutputs) {
 // configured. Additionally check for common invalid inputs when
 // using this mode.
 TEST_F(CameraHidlTest, configureStreamsConstrainedOutputs) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
-                camera_metadata_t *staticMeta;
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+
+    for (const auto& name : cameraDeviceNames) {
+        int deviceVersion = getCameraDeviceVersion(name, mProviderType);
+        switch (deviceVersion) {
+            case CAMERA_DEVICE_API_VERSION_3_3:
+            case CAMERA_DEVICE_API_VERSION_3_2: {
+                camera_metadata_tstaticMeta;
                 Return<void> ret;
                 sp<ICameraDeviceSession> session;
-                openEmptyDeviceSession(name, provider.second, &session /*out*/,
-                        &staticMeta /*out*/);
+                sp<device::V3_3::ICameraDeviceSession> session3_3;
+                openEmptyDeviceSession(name, mProvider,
+                        &session /*out*/, &session3_3 /*out*/, &staticMeta /*out*/);
 
                 Status rc = isConstrainedModeAvailable(staticMeta);
                 if (Status::METHOD_NOT_SUPPORTED == rc) {
@@ -2761,73 +2736,119 @@ TEST_F(CameraHidlTest, configureStreamsConstrainedOutputs) {
                 ASSERT_EQ(Status::OK, rc);
 
                 int32_t streamId = 0;
-                Stream stream = {streamId, StreamType::OUTPUT,
-                        static_cast<uint32_t> (hfrStream.width),
-                        static_cast<uint32_t> (hfrStream.height),
-                        static_cast<PixelFormat> (hfrStream.format),
-                        GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER, 0,
-                        StreamRotation::ROTATION_0};
+                Stream stream = {streamId,
+                                 StreamType::OUTPUT,
+                                 static_cast<uint32_t>(hfrStream.width),
+                                 static_cast<uint32_t>(hfrStream.height),
+                                 static_cast<PixelFormat>(hfrStream.format),
+                                 GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER,
+                                 0,
+                                 StreamRotation::ROTATION_0};
                 ::android::hardware::hidl_vec<Stream> streams = {stream};
                 StreamConfiguration config = {streams,
-                        StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE};
-                ret = session->configureStreams(config, [streamId] (Status s,
-                        HalStreamConfiguration halConfig) {
-                    ASSERT_EQ(Status::OK, s);
-                    ASSERT_EQ(1u, halConfig.streams.size());
-                    ASSERT_EQ(halConfig.streams[0].id, streamId);
-                });
+                                              StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE};
+                if (session3_3 == nullptr) {
+                    ret = session->configureStreams(config,
+                            [streamId](Status s, HalStreamConfiguration halConfig) {
+                                ASSERT_EQ(Status::OK, s);
+                                ASSERT_EQ(1u, halConfig.streams.size());
+                                ASSERT_EQ(halConfig.streams[0].id, streamId);
+                            });
+                } else {
+                    ret = session3_3->configureStreams_3_3(config,
+                            [streamId](Status s, device::V3_3::HalStreamConfiguration halConfig) {
+                                ASSERT_EQ(Status::OK, s);
+                                ASSERT_EQ(1u, halConfig.streams.size());
+                                ASSERT_EQ(halConfig.streams[0].v3_2.id, streamId);
+                            });
+                }
                 ASSERT_TRUE(ret.isOk());
 
-                stream = {streamId++, StreamType::OUTPUT,
-                        static_cast<uint32_t> (0),
-                        static_cast<uint32_t> (0),
-                        static_cast<PixelFormat> (hfrStream.format),
-                        GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER, 0,
-                        StreamRotation::ROTATION_0};
+                stream = {streamId++,
+                          StreamType::OUTPUT,
+                          static_cast<uint32_t>(0),
+                          static_cast<uint32_t>(0),
+                          static_cast<PixelFormat>(hfrStream.format),
+                          GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER,
+                          0,
+                          StreamRotation::ROTATION_0};
                 streams[0] = stream;
-                config = {streams,
-                        StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE};
-                ret = session->configureStreams(config, [] (Status s,
-                        HalStreamConfiguration) {
-                    ASSERT_TRUE((Status::ILLEGAL_ARGUMENT == s) ||
-                                (Status::INTERNAL_ERROR == s));
-                });
+                config = {streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE};
+                if (session3_3 == nullptr) {
+                    ret = session->configureStreams(config,
+                            [](Status s, HalStreamConfiguration) {
+                                ASSERT_TRUE((Status::ILLEGAL_ARGUMENT == s) ||
+                                        (Status::INTERNAL_ERROR == s));
+                            });
+                } else {
+                    ret = session3_3->configureStreams_3_3(config,
+                            [](Status s, device::V3_3::HalStreamConfiguration) {
+                                ASSERT_TRUE((Status::ILLEGAL_ARGUMENT == s) ||
+                                        (Status::INTERNAL_ERROR == s));
+                            });
+                }
                 ASSERT_TRUE(ret.isOk());
 
-                stream = {streamId++, StreamType::OUTPUT,
-                        static_cast<uint32_t> (UINT32_MAX),
-                        static_cast<uint32_t> (UINT32_MAX),
-                        static_cast<PixelFormat> (hfrStream.format),
-                        GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER, 0,
-                        StreamRotation::ROTATION_0};
+                stream = {streamId++,
+                          StreamType::OUTPUT,
+                          static_cast<uint32_t>(UINT32_MAX),
+                          static_cast<uint32_t>(UINT32_MAX),
+                          static_cast<PixelFormat>(hfrStream.format),
+                          GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER,
+                          0,
+                          StreamRotation::ROTATION_0};
                 streams[0] = stream;
-                config = {streams,
-                        StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE};
-                ret = session->configureStreams(config, [] (Status s,
-                        HalStreamConfiguration) {
-                    ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
-                });
+                config = {streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE};
+                if (session3_3 == nullptr) {
+                    ret = session->configureStreams(config,
+                            [](Status s, HalStreamConfiguration) {
+                                ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
+                            });
+                } else {
+                    ret = session3_3->configureStreams_3_3(config,
+                            [](Status s, device::V3_3::HalStreamConfiguration) {
+                                ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
+                            });
+                }
                 ASSERT_TRUE(ret.isOk());
 
-                stream = {streamId++, StreamType::OUTPUT,
-                        static_cast<uint32_t> (hfrStream.width),
-                        static_cast<uint32_t> (hfrStream.height),
-                        static_cast<PixelFormat> (UINT32_MAX),
-                        GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER, 0,
-                        StreamRotation::ROTATION_0};
+                stream = {streamId++,
+                          StreamType::OUTPUT,
+                          static_cast<uint32_t>(hfrStream.width),
+                          static_cast<uint32_t>(hfrStream.height),
+                          static_cast<PixelFormat>(UINT32_MAX),
+                          GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER,
+                          0,
+                          StreamRotation::ROTATION_0};
                 streams[0] = stream;
-                config = {streams,
-                        StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE};
-                ret = session->configureStreams(config, [] (Status s,
-                        HalStreamConfiguration) {
-                    ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
-                });
+                config = {streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE};
+                if (session3_3 == nullptr) {
+                    ret = session->configureStreams(config,
+                            [](Status s, HalStreamConfiguration) {
+                                ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
+                            });
+                } else {
+                    ret = session3_3->configureStreams_3_3(config,
+                            [](Status s, device::V3_3::HalStreamConfiguration) {
+                                ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
+                            });
+                }
                 ASSERT_TRUE(ret.isOk());
 
                 free_camera_metadata(staticMeta);
                 ret = session->close();
                 ASSERT_TRUE(ret.isOk());
             }
+            break;
+            case CAMERA_DEVICE_API_VERSION_1_0: {
+                //Not applicable
+            }
+            break;
+            default: {
+                ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
+                ADD_FAILURE();
+            }
+            break;
         }
     }
 }
@@ -2835,59 +2856,73 @@ TEST_F(CameraHidlTest, configureStreamsConstrainedOutputs) {
 // Verify that all supported video + snapshot stream combinations can
 // be configured successfully.
 TEST_F(CameraHidlTest, configureStreamsVideoStillOutputs) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-        std::vector<AvailableStream> outputBlobStreams;
-        std::vector<AvailableStream> outputVideoStreams;
-        AvailableStream videoThreshold = {kMaxVideoWidth, kMaxVideoHeight,
-                static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
-        AvailableStream blobThreshold = {kMaxVideoWidth, kMaxVideoHeight,
-                static_cast<int32_t>(PixelFormat::BLOB)};
-
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
-                camera_metadata_t *staticMeta;
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    std::vector<AvailableStream> outputBlobStreams;
+    std::vector<AvailableStream> outputVideoStreams;
+    AvailableStream videoThreshold = {kMaxVideoWidth, kMaxVideoHeight,
+                                      static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
+    AvailableStream blobThreshold = {kMaxVideoWidth, kMaxVideoHeight,
+                                     static_cast<int32_t>(PixelFormat::BLOB)};
+
+    for (const auto& name : cameraDeviceNames) {
+        int deviceVersion = getCameraDeviceVersion(name, mProviderType);
+        switch (deviceVersion) {
+            case CAMERA_DEVICE_API_VERSION_3_3:
+            case CAMERA_DEVICE_API_VERSION_3_2: {
+                camera_metadata_tstaticMeta;
                 Return<void> ret;
                 sp<ICameraDeviceSession> session;
-                openEmptyDeviceSession(name, provider.second, &session /*out*/,
-                        &staticMeta /*out*/);
+                sp<device::V3_3::ICameraDeviceSession> session3_3;
+                openEmptyDeviceSession(name, mProvider,
+                        &session /*out*/, &session3_3 /*out*/, &staticMeta /*out*/);
 
                 outputBlobStreams.clear();
-                ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta,
-                        outputBlobStreams, &blobThreshold));
+                ASSERT_EQ(Status::OK,
+                          getAvailableOutputStreams(staticMeta, outputBlobStreams,
+                                  &blobThreshold));
                 ASSERT_NE(0u, outputBlobStreams.size());
 
                 outputVideoStreams.clear();
-                ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta,
-                        outputVideoStreams, &videoThreshold));
+                ASSERT_EQ(Status::OK,
+                          getAvailableOutputStreams(staticMeta, outputVideoStreams,
+                                  &videoThreshold));
                 ASSERT_NE(0u, outputVideoStreams.size());
 
                 int32_t streamId = 0;
-                for (auto &blobIter : outputBlobStreams) {
-                    for (auto &videoIter : outputVideoStreams) {
-                        Stream videoStream = {streamId++, StreamType::OUTPUT,
-                                static_cast<uint32_t> (videoIter.width),
-                                static_cast<uint32_t> (videoIter.height),
-                                static_cast<PixelFormat> (videoIter.format),
-                                GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER, 0,
-                                StreamRotation::ROTATION_0};
-                        Stream blobStream = {streamId++, StreamType::OUTPUT,
-                                static_cast<uint32_t> (blobIter.width),
-                                static_cast<uint32_t> (blobIter.height),
-                                static_cast<PixelFormat> (blobIter.format),
-                                GRALLOC1_CONSUMER_USAGE_CPU_READ, 0,
-                                StreamRotation::ROTATION_0};
-                        ::android::hardware::hidl_vec<Stream> streams = {
-                                videoStream, blobStream};
+                for (auto& blobIter : outputBlobStreams) {
+                    for (auto& videoIter : outputVideoStreams) {
+                        Stream videoStream = {streamId++,
+                                              StreamType::OUTPUT,
+                                              static_cast<uint32_t>(videoIter.width),
+                                              static_cast<uint32_t>(videoIter.height),
+                                              static_cast<PixelFormat>(videoIter.format),
+                                              GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER,
+                                              0,
+                                              StreamRotation::ROTATION_0};
+                        Stream blobStream = {streamId++,
+                                             StreamType::OUTPUT,
+                                             static_cast<uint32_t>(blobIter.width),
+                                             static_cast<uint32_t>(blobIter.height),
+                                             static_cast<PixelFormat>(blobIter.format),
+                                             GRALLOC1_CONSUMER_USAGE_CPU_READ,
+                                             0,
+                                             StreamRotation::ROTATION_0};
+                        ::android::hardware::hidl_vec<Stream> streams = {videoStream, blobStream};
                         StreamConfiguration config = {streams,
-                                StreamConfigurationMode::NORMAL_MODE};
-                        ret = session->configureStreams(config,
-                                                    [](Status s, HalStreamConfiguration halConfig) {
-                                                        ASSERT_EQ(Status::OK, s);
-                                                        ASSERT_EQ(2u, halConfig.streams.size());
-                                                    });
+                                                      StreamConfigurationMode::NORMAL_MODE};
+                        if (session3_3 == nullptr) {
+                            ret = session->configureStreams(config,
+                                    [](Status s, HalStreamConfiguration halConfig) {
+                                        ASSERT_EQ(Status::OK, s);
+                                        ASSERT_EQ(2u, halConfig.streams.size());
+                                    });
+                        } else {
+                            ret = session3_3->configureStreams_3_3(config,
+                                    [](Status s, device::V3_3::HalStreamConfiguration halConfig) {
+                                        ASSERT_EQ(Status::OK, s);
+                                        ASSERT_EQ(2u, halConfig.streams.size());
+                                    });
+                        }
                         ASSERT_TRUE(ret.isOk());
                     }
                 }
@@ -2896,76 +2931,89 @@ TEST_F(CameraHidlTest, configureStreamsVideoStillOutputs) {
                 ret = session->close();
                 ASSERT_TRUE(ret.isOk());
             }
+            break;
+            case CAMERA_DEVICE_API_VERSION_1_0: {
+                //Not applicable
+            }
+            break;
+            default: {
+                ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
+                ADD_FAILURE();
+            }
+            break;
         }
     }
 }
 
 // Generate and verify a camera capture request
 TEST_F(CameraHidlTest, processCaptureRequestPreview) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-        AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
-                static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
-        uint64_t bufferId = 1;
-        uint32_t frameNumber = 1;
-        ::android::hardware::hidl_vec<uint8_t> settings;
-
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
+                                        static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
+    uint64_t bufferId = 1;
+    uint32_t frameNumber = 1;
+    ::android::hardware::hidl_vec<uint8_t> settings;
+
+    for (const auto& name : cameraDeviceNames) {
+        int deviceVersion = getCameraDeviceVersion(name, mProviderType);
+        switch (deviceVersion) {
+            case CAMERA_DEVICE_API_VERSION_3_3:
+            case CAMERA_DEVICE_API_VERSION_3_2: {
                 Stream previewStream;
                 HalStreamConfiguration halStreamConfig;
                 sp<ICameraDeviceSession> session;
                 bool supportsPartialResults = false;
                 uint32_t partialResultCount = 0;
-                configurePreviewStream(name, provider.second, &previewThreshold,
-                        &session /*out*/, &previewStream /*out*/,
-                        &halStreamConfig /*out*/, &supportsPartialResults /*out*/,
-                        &partialResultCount/*out*/);
+                configurePreviewStream(name, mProvider, &previewThreshold, &session /*out*/,
+                                       &previewStream /*out*/, &halStreamConfig /*out*/,
+                                       &supportsPartialResults /*out*/,
+                                       &partialResultCount /*out*/);
 
                 std::shared_ptr<ResultMetadataQueue> resultQueue;
-                auto resultQueueRet = session->getCaptureResultMetadataQueue(
-                    [&resultQueue](const auto& descriptor) {
-                        resultQueue = std::make_shared<ResultMetadataQueue>(
-                                descriptor);
-                        if (!resultQueue->isValid() ||
-                                resultQueue->availableToWrite() <= 0) {
-                            ALOGE("%s: HAL returns empty result metadata fmq,"
-                                    " not use it", __func__);
-                            resultQueue = nullptr;
-                            // Don't use the queue onwards.
-                        }
-                    });
+                auto resultQueueRet =
+                    session->getCaptureResultMetadataQueue(
+                        [&resultQueue](const auto& descriptor) {
+                            resultQueue = std::make_shared<ResultMetadataQueue>(
+                                    descriptor);
+                            if (!resultQueue->isValid() ||
+                                    resultQueue->availableToWrite() <= 0) {
+                                ALOGE("%s: HAL returns empty result metadata fmq,"
+                                        " not use it", __func__);
+                                resultQueue = nullptr;
+                                // Don't use the queue onwards.
+                            }
+                        });
                 ASSERT_TRUE(resultQueueRet.isOk());
 
                 InFlightRequest inflightReq = {1, false, supportsPartialResults,
-                        partialResultCount, resultQueue};
+                                               partialResultCount, resultQueue};
 
                 RequestTemplate reqTemplate = RequestTemplate::PREVIEW;
                 Return<void> ret;
                 ret = session->constructDefaultRequestSettings(reqTemplate,
-                    [&](auto status, const auto& req) {
-                        ASSERT_EQ(Status::OK, status);
-                        settings = req; });
+                                                               [&](auto status, const auto& req) {
+                                                                   ASSERT_EQ(Status::OK, status);
+                                                                   settings = req;
+                                                               });
                 ASSERT_TRUE(ret.isOk());
 
                 sp<GraphicBuffer> gb = new GraphicBuffer(
                     previewStream.width, previewStream.height,
-                    static_cast<int32_t>(halStreamConfig.streams[0].overrideFormat),
-                    1, android_convertGralloc1To0Usage(
-                           halStreamConfig.streams[0].producerUsage,
-                           halStreamConfig.streams[0].consumerUsage));
+                    static_cast<int32_t>(halStreamConfig.streams[0].overrideFormat), 1,
+                    android_convertGralloc1To0Usage(halStreamConfig.streams[0].producerUsage,
+                                                    halStreamConfig.streams[0].consumerUsage));
                 ASSERT_NE(nullptr, gb.get());
                 StreamBuffer outputBuffer = {halStreamConfig.streams[0].id,
-                        bufferId, hidl_handle(gb->getNativeBuffer()->handle),
-                        BufferStatus::OK, nullptr, nullptr};
-                ::android::hardware::hidl_vec<StreamBuffer> outputBuffers = {
-                        outputBuffer};
-                StreamBuffer emptyInputBuffer = {-1, 0, nullptr,
-                        BufferStatus::ERROR, nullptr, nullptr};
-                CaptureRequest request = {frameNumber, 0 /* fmqSettingsSize */,
-                        settings, emptyInputBuffer, outputBuffers};
+                                             bufferId,
+                                             hidl_handle(gb->getNativeBuffer()->handle),
+                                             BufferStatus::OK,
+                                             nullptr,
+                                             nullptr};
+                ::android::hardware::hidl_vec<StreamBuffer> outputBuffers = {outputBuffer};
+                StreamBuffer emptyInputBuffer = {-1, 0, nullptr, BufferStatus::ERROR, nullptr,
+                                                 nullptr};
+                CaptureRequest request = {frameNumber, 0 /* fmqSettingsSize */, settings,
+                                          emptyInputBuffer, outputBuffers};
 
                 {
                     std::unique_lock<std::mutex> l(mLock);
@@ -2977,12 +3025,11 @@ TEST_F(CameraHidlTest, processCaptureRequestPreview) {
                 uint32_t numRequestProcessed = 0;
                 hidl_vec<BufferCache> cachesToRemove;
                 Return<void> returnStatus = session->processCaptureRequest(
-                        {request},
-                        cachesToRemove,
-                        [&status, &numRequestProcessed] (auto s, uint32_t n) {
-                            status = s;
-                            numRequestProcessed = n;
-                        });
+                    {request}, cachesToRemove, [&status, &numRequestProcessed](auto s,
+                            uint32_t n) {
+                        status = s;
+                        numRequestProcessed = n;
+                    });
                 ASSERT_TRUE(returnStatus.isOk());
                 ASSERT_EQ(Status::OK, status);
                 ASSERT_EQ(numRequestProcessed, 1u);
@@ -2990,39 +3037,37 @@ TEST_F(CameraHidlTest, processCaptureRequestPreview) {
                 {
                     std::unique_lock<std::mutex> l(mLock);
                     while (!inflightReq.errorCodeValid &&
-                            ((0 < inflightReq.numBuffersLeft) ||
-                                    (!inflightReq.haveResultMetadata))) {
+                           ((0 < inflightReq.numBuffersLeft) ||
+                                   (!inflightReq.haveResultMetadata))) {
                         auto timeout = std::chrono::system_clock::now() +
-                                std::chrono::seconds(kStreamBufferTimeoutSec);
+                                       std::chrono::seconds(kStreamBufferTimeoutSec);
                         ASSERT_NE(std::cv_status::timeout,
                                 mResultCondition.wait_until(l, timeout));
                     }
 
                     ASSERT_FALSE(inflightReq.errorCodeValid);
                     ASSERT_NE(inflightReq.resultOutputBuffers.size(), 0u);
-                    ASSERT_EQ(previewStream.id,
-                              inflightReq.resultOutputBuffers[0].streamId);
+                    ASSERT_EQ(previewStream.id, inflightReq.resultOutputBuffers[0].streamId);
 
                     request.frameNumber++;
-                    //Empty settings should be supported after the first call
-                    //for repeating requests.
+                    // Empty settings should be supported after the first call
+                    // for repeating requests.
                     request.settings.setToExternal(nullptr, 0, true);
                     // The buffer has been registered to HAL by bufferId, so per
                     // API contract we should send a null handle for this buffer
                     request.outputBuffers[0].buffer = nullptr;
                     mInflightMap.clear();
-                    inflightReq = {1, false, supportsPartialResults,
-                                        partialResultCount, resultQueue};
+                    inflightReq = {1, false, supportsPartialResults, partialResultCount,
+                                   resultQueue};
                     mInflightMap.add(request.frameNumber, &inflightReq);
                 }
 
                 returnStatus = session->processCaptureRequest(
-                        {request},
-                        cachesToRemove,
-                        [&status, &numRequestProcessed] (auto s, uint32_t n) {
-                            status = s;
-                            numRequestProcessed = n;
-                        });
+                    {request}, cachesToRemove, [&status, &numRequestProcessed](auto s,
+                            uint32_t n) {
+                        status = s;
+                        numRequestProcessed = n;
+                    });
                 ASSERT_TRUE(returnStatus.isOk());
                 ASSERT_EQ(Status::OK, status);
                 ASSERT_EQ(numRequestProcessed, 1u);
@@ -3030,23 +3075,32 @@ TEST_F(CameraHidlTest, processCaptureRequestPreview) {
                 {
                     std::unique_lock<std::mutex> l(mLock);
                     while (!inflightReq.errorCodeValid &&
-                            ((0 < inflightReq.numBuffersLeft) ||
-                                    (!inflightReq.haveResultMetadata))) {
+                           ((0 < inflightReq.numBuffersLeft) ||
+                                   (!inflightReq.haveResultMetadata))) {
                         auto timeout = std::chrono::system_clock::now() +
-                                std::chrono::seconds(kStreamBufferTimeoutSec);
+                                       std::chrono::seconds(kStreamBufferTimeoutSec);
                         ASSERT_NE(std::cv_status::timeout,
                                 mResultCondition.wait_until(l, timeout));
                     }
 
                     ASSERT_FALSE(inflightReq.errorCodeValid);
                     ASSERT_NE(inflightReq.resultOutputBuffers.size(), 0u);
-                    ASSERT_EQ(previewStream.id,
-                              inflightReq.resultOutputBuffers[0].streamId);
+                    ASSERT_EQ(previewStream.id, inflightReq.resultOutputBuffers[0].streamId);
                 }
 
                 ret = session->close();
                 ASSERT_TRUE(ret.isOk());
             }
+            break;
+            case CAMERA_DEVICE_API_VERSION_1_0: {
+                //Not applicable
+            }
+            break;
+            default: {
+                ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
+                ADD_FAILURE();
+            }
+            break;
         }
     }
 }
@@ -3054,57 +3108,57 @@ TEST_F(CameraHidlTest, processCaptureRequestPreview) {
 // Test whether an incorrect capture request with missing settings will
 // be reported correctly.
 TEST_F(CameraHidlTest, processCaptureRequestInvalidSinglePreview) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-        std::vector<AvailableStream> outputPreviewStreams;
-        AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
-                static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
-        uint64_t bufferId = 1;
-        uint32_t frameNumber = 1;
-        ::android::hardware::hidl_vec<uint8_t> settings;
-
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    std::vector<AvailableStream> outputPreviewStreams;
+    AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
+                                        static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
+    uint64_t bufferId = 1;
+    uint32_t frameNumber = 1;
+    ::android::hardware::hidl_vec<uint8_t> settings;
+
+    for (const auto& name : cameraDeviceNames) {
+        int deviceVersion = getCameraDeviceVersion(name, mProviderType);
+        switch (deviceVersion) {
+            case CAMERA_DEVICE_API_VERSION_3_3:
+            case CAMERA_DEVICE_API_VERSION_3_2: {
                 Stream previewStream;
                 HalStreamConfiguration halStreamConfig;
                 sp<ICameraDeviceSession> session;
                 bool supportsPartialResults = false;
                 uint32_t partialResultCount = 0;
-                configurePreviewStream(name, provider.second, &previewThreshold,
-                        &session /*out*/, &previewStream /*out*/,
-                        &halStreamConfig /*out*/, &supportsPartialResults /*out*/,
-                        &partialResultCount /*out*/);
+                configurePreviewStream(name, mProvider, &previewThreshold, &session /*out*/,
+                                       &previewStream /*out*/, &halStreamConfig /*out*/,
+                                       &supportsPartialResults /*out*/,
+                                       &partialResultCount /*out*/);
 
                 sp<GraphicBuffer> gb = new GraphicBuffer(
                     previewStream.width, previewStream.height,
-                    static_cast<int32_t>(halStreamConfig.streams[0].overrideFormat),
-                    1, android_convertGralloc1To0Usage(
-                           halStreamConfig.streams[0].producerUsage,
-                           halStreamConfig.streams[0].consumerUsage));
+                    static_cast<int32_t>(halStreamConfig.streams[0].overrideFormat), 1,
+                    android_convertGralloc1To0Usage(halStreamConfig.streams[0].producerUsage,
+                                                    halStreamConfig.streams[0].consumerUsage));
 
                 StreamBuffer outputBuffer = {halStreamConfig.streams[0].id,
-                        bufferId, hidl_handle(gb->getNativeBuffer()->handle),
-                        BufferStatus::OK, nullptr, nullptr};
-                ::android::hardware::hidl_vec<StreamBuffer> outputBuffers = {
-                        outputBuffer};
-                StreamBuffer emptyInputBuffer = {-1, 0, nullptr,
-                        BufferStatus::ERROR, nullptr, nullptr};
+                                             bufferId,
+                                             hidl_handle(gb->getNativeBuffer()->handle),
+                                             BufferStatus::OK,
+                                             nullptr,
+                                             nullptr};
+                ::android::hardware::hidl_vec<StreamBuffer> outputBuffers = {outputBuffer};
+                StreamBuffer emptyInputBuffer = {-1, 0, nullptr, BufferStatus::ERROR, nullptr,
+                                                 nullptr};
                 CaptureRequest request = {frameNumber, 0 /* fmqSettingsSize */, settings,
-                        emptyInputBuffer, outputBuffers};
+                                          emptyInputBuffer, outputBuffers};
 
-                //Settings were not correctly initialized, we should fail here
+                // Settings were not correctly initialized, we should fail here
                 Status status = Status::OK;
                 uint32_t numRequestProcessed = 0;
                 hidl_vec<BufferCache> cachesToRemove;
                 Return<void> ret = session->processCaptureRequest(
-                        {request},
-                        cachesToRemove,
-                        [&status, &numRequestProcessed] (auto s, uint32_t n) {
-                            status = s;
-                            numRequestProcessed = n;
-                        });
+                    {request}, cachesToRemove, [&status, &numRequestProcessed](auto s,
+                            uint32_t n) {
+                        status = s;
+                        numRequestProcessed = n;
+                    });
                 ASSERT_TRUE(ret.isOk());
                 ASSERT_EQ(Status::ILLEGAL_ARGUMENT, status);
                 ASSERT_EQ(numRequestProcessed, 0u);
@@ -3112,6 +3166,16 @@ TEST_F(CameraHidlTest, processCaptureRequestInvalidSinglePreview) {
                 ret = session->close();
                 ASSERT_TRUE(ret.isOk());
             }
+            break;
+            case CAMERA_DEVICE_API_VERSION_1_0: {
+                //Not applicable
+            }
+            break;
+            default: {
+                ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
+                ADD_FAILURE();
+            }
+            break;
         }
     }
 }
@@ -3119,53 +3183,53 @@ TEST_F(CameraHidlTest, processCaptureRequestInvalidSinglePreview) {
 // Check whether an invalid capture request with missing output buffers
 // will be reported correctly.
 TEST_F(CameraHidlTest, processCaptureRequestInvalidBuffer) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-        std::vector<AvailableStream> outputBlobStreams;
-        AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
-                static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
-        uint32_t frameNumber = 1;
-        ::android::hardware::hidl_vec<uint8_t> settings;
-
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    std::vector<AvailableStream> outputBlobStreams;
+    AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
+                                        static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
+    uint32_t frameNumber = 1;
+    ::android::hardware::hidl_vec<uint8_t> settings;
+
+    for (const auto& name : cameraDeviceNames) {
+        int deviceVersion = getCameraDeviceVersion(name, mProviderType);
+        switch (deviceVersion) {
+            case CAMERA_DEVICE_API_VERSION_3_3:
+            case CAMERA_DEVICE_API_VERSION_3_2: {
                 Stream previewStream;
                 HalStreamConfiguration halStreamConfig;
                 sp<ICameraDeviceSession> session;
                 bool supportsPartialResults = false;
                 uint32_t partialResultCount = 0;
-                configurePreviewStream(name, provider.second, &previewThreshold,
-                        &session /*out*/, &previewStream /*out*/,
-                        &halStreamConfig /*out*/, &supportsPartialResults/*out*/,
-                        &partialResultCount /*out*/);
+                configurePreviewStream(name, mProvider, &previewThreshold, &session /*out*/,
+                                       &previewStream /*out*/, &halStreamConfig /*out*/,
+                                       &supportsPartialResults /*out*/,
+                                       &partialResultCount /*out*/);
 
                 RequestTemplate reqTemplate = RequestTemplate::PREVIEW;
                 Return<void> ret;
                 ret = session->constructDefaultRequestSettings(reqTemplate,
-                    [&](auto status, const auto& req) {
-                        ASSERT_EQ(Status::OK, status);
-                        settings = req; });
+                                                               [&](auto status, const auto& req) {
+                                                                   ASSERT_EQ(Status::OK, status);
+                                                                   settings = req;
+                                                               });
                 ASSERT_TRUE(ret.isOk());
 
                 ::android::hardware::hidl_vec<StreamBuffer> emptyOutputBuffers;
-                StreamBuffer emptyInputBuffer = {-1, 0, nullptr,
-                        BufferStatus::ERROR, nullptr, nullptr};
-                CaptureRequest request = {frameNumber, 0/* fmqSettingsSize */,
-                        settings, emptyInputBuffer, emptyOutputBuffers};
+                StreamBuffer emptyInputBuffer = {-1, 0, nullptr, BufferStatus::ERROR, nullptr,
+                                                 nullptr};
+                CaptureRequest request = {frameNumber, 0 /* fmqSettingsSize */, settings,
+                                          emptyInputBuffer, emptyOutputBuffers};
 
-                //Output buffers are missing, we should fail here
+                // Output buffers are missing, we should fail here
                 Status status = Status::OK;
                 uint32_t numRequestProcessed = 0;
                 hidl_vec<BufferCache> cachesToRemove;
                 ret = session->processCaptureRequest(
-                        {request},
-                        cachesToRemove,
-                        [&status, &numRequestProcessed] (auto s, uint32_t n) {
-                            status = s;
-                            numRequestProcessed = n;
-                        });
+                    {request}, cachesToRemove, [&status, &numRequestProcessed](auto s,
+                            uint32_t n) {
+                        status = s;
+                        numRequestProcessed = n;
+                    });
                 ASSERT_TRUE(ret.isOk());
                 ASSERT_EQ(Status::ILLEGAL_ARGUMENT, status);
                 ASSERT_EQ(numRequestProcessed, 0u);
@@ -3173,76 +3237,89 @@ TEST_F(CameraHidlTest, processCaptureRequestInvalidBuffer) {
                 ret = session->close();
                 ASSERT_TRUE(ret.isOk());
             }
+            break;
+            case CAMERA_DEVICE_API_VERSION_1_0: {
+                //Not applicable
+            }
+            break;
+            default: {
+                ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
+                ADD_FAILURE();
+            }
+            break;
         }
     }
 }
 
 // Generate, trigger and flush a preview request
 TEST_F(CameraHidlTest, flushPreviewRequest) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-        std::vector<AvailableStream> outputPreviewStreams;
-        AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
-                static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
-        uint64_t bufferId = 1;
-        uint32_t frameNumber = 1;
-        ::android::hardware::hidl_vec<uint8_t> settings;
-
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    std::vector<AvailableStream> outputPreviewStreams;
+    AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
+                                        static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
+    uint64_t bufferId = 1;
+    uint32_t frameNumber = 1;
+    ::android::hardware::hidl_vec<uint8_t> settings;
+
+    for (const auto& name : cameraDeviceNames) {
+        int deviceVersion = getCameraDeviceVersion(name, mProviderType);
+        switch (deviceVersion) {
+            case CAMERA_DEVICE_API_VERSION_3_3:
+            case CAMERA_DEVICE_API_VERSION_3_2: {
                 Stream previewStream;
                 HalStreamConfiguration halStreamConfig;
                 sp<ICameraDeviceSession> session;
                 bool supportsPartialResults = false;
                 uint32_t partialResultCount = 0;
-                configurePreviewStream(name, provider.second, &previewThreshold,
-                        &session /*out*/, &previewStream /*out*/,
-                        &halStreamConfig /*out*/, &supportsPartialResults /*out*/,
-                        &partialResultCount /*out*/);
+                configurePreviewStream(name, mProvider, &previewThreshold, &session /*out*/,
+                                       &previewStream /*out*/, &halStreamConfig /*out*/,
+                                       &supportsPartialResults /*out*/,
+                                       &partialResultCount /*out*/);
 
                 std::shared_ptr<ResultMetadataQueue> resultQueue;
-                auto resultQueueRet = session->getCaptureResultMetadataQueue(
-                    [&resultQueue](const auto& descriptor) {
-                        resultQueue = std::make_shared<ResultMetadataQueue>(
-                                descriptor);
-                        if (!resultQueue->isValid() ||
-                                resultQueue->availableToWrite() <= 0) {
-                            ALOGE("%s: HAL returns empty result metadata fmq,"
-                                    " not use it", __func__);
-                            resultQueue = nullptr;
-                            // Don't use the queue onwards.
-                        }
-                    });
+                auto resultQueueRet =
+                    session->getCaptureResultMetadataQueue(
+                        [&resultQueue](const auto& descriptor) {
+                            resultQueue = std::make_shared<ResultMetadataQueue>(
+                                    descriptor);
+                            if (!resultQueue->isValid() ||
+                                    resultQueue->availableToWrite() <= 0) {
+                                ALOGE("%s: HAL returns empty result metadata fmq,"
+                                        " not use it", __func__);
+                                resultQueue = nullptr;
+                                // Don't use the queue onwards.
+                            }
+                        });
                 ASSERT_TRUE(resultQueueRet.isOk());
 
                 InFlightRequest inflightReq = {1, false, supportsPartialResults,
-                        partialResultCount, resultQueue};
+                                               partialResultCount, resultQueue};
                 RequestTemplate reqTemplate = RequestTemplate::PREVIEW;
                 Return<void> ret;
                 ret = session->constructDefaultRequestSettings(reqTemplate,
-                    [&](auto status, const auto& req) {
-                        ASSERT_EQ(Status::OK, status);
-                        settings = req; });
+                                                               [&](auto status, const auto& req) {
+                                                                   ASSERT_EQ(Status::OK, status);
+                                                                   settings = req;
+                                                               });
                 ASSERT_TRUE(ret.isOk());
 
                 sp<GraphicBuffer> gb = new GraphicBuffer(
                     previewStream.width, previewStream.height,
-                    static_cast<int32_t>(halStreamConfig.streams[0].overrideFormat),
-                    1, android_convertGralloc1To0Usage(
-                           halStreamConfig.streams[0].producerUsage,
-                           halStreamConfig.streams[0].consumerUsage));
+                    static_cast<int32_t>(halStreamConfig.streams[0].overrideFormat), 1,
+                    android_convertGralloc1To0Usage(halStreamConfig.streams[0].producerUsage,
+                                                    halStreamConfig.streams[0].consumerUsage));
                 ASSERT_NE(nullptr, gb.get());
                 StreamBuffer outputBuffer = {halStreamConfig.streams[0].id,
-                        bufferId, hidl_handle(gb->getNativeBuffer()->handle),
-                        BufferStatus::OK, nullptr, nullptr};
-                ::android::hardware::hidl_vec<StreamBuffer> outputBuffers = {
-                        outputBuffer};
+                                             bufferId,
+                                             hidl_handle(gb->getNativeBuffer()->handle),
+                                             BufferStatus::OK,
+                                             nullptr,
+                                             nullptr};
+                ::android::hardware::hidl_vec<StreamBuffer> outputBuffers = {outputBuffer};
                 const StreamBuffer emptyInputBuffer = {-1, 0, nullptr,
-                        BufferStatus::ERROR, nullptr, nullptr};
-                CaptureRequest request = {frameNumber, 0 /* fmqSettingsSize */,
-                        settings, emptyInputBuffer, outputBuffers};
+                                                       BufferStatus::ERROR, nullptr, nullptr};
+                CaptureRequest request = {frameNumber, 0 /* fmqSettingsSize */, settings,
+                                          emptyInputBuffer, outputBuffers};
 
                 {
                     std::unique_lock<std::mutex> l(mLock);
@@ -3254,17 +3331,16 @@ TEST_F(CameraHidlTest, flushPreviewRequest) {
                 uint32_t numRequestProcessed = 0;
                 hidl_vec<BufferCache> cachesToRemove;
                 ret = session->processCaptureRequest(
-                        {request},
-                        cachesToRemove,
-                        [&status, &numRequestProcessed] (auto s, uint32_t n) {
-                            status = s;
-                            numRequestProcessed = n;
-                        });
+                    {request}, cachesToRemove, [&status, &numRequestProcessed](auto s,
+                            uint32_t n) {
+                        status = s;
+                        numRequestProcessed = n;
+                    });
 
                 ASSERT_TRUE(ret.isOk());
                 ASSERT_EQ(Status::OK, status);
                 ASSERT_EQ(numRequestProcessed, 1u);
-                //Flush before waiting for request to complete.
+                // Flush before waiting for request to complete.
                 Return<Status> returnStatus = session->flush();
                 ASSERT_TRUE(returnStatus.isOk());
                 ASSERT_EQ(Status::OK, returnStatus);
@@ -3272,29 +3348,28 @@ TEST_F(CameraHidlTest, flushPreviewRequest) {
                 {
                     std::unique_lock<std::mutex> l(mLock);
                     while (!inflightReq.errorCodeValid &&
-                            ((0 < inflightReq.numBuffersLeft) ||
-                                    (!inflightReq.haveResultMetadata))) {
+                           ((0 < inflightReq.numBuffersLeft) ||
+                                   (!inflightReq.haveResultMetadata))) {
                         auto timeout = std::chrono::system_clock::now() +
-                                std::chrono::seconds(kStreamBufferTimeoutSec);
-                        ASSERT_NE(std::cv_status::timeout,
-                                mResultCondition.wait_until(l, timeout));
+                                       std::chrono::seconds(kStreamBufferTimeoutSec);
+                        ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l,
+                                timeout));
                     }
 
                     if (!inflightReq.errorCodeValid) {
                         ASSERT_NE(inflightReq.resultOutputBuffers.size(), 0u);
-                        ASSERT_EQ(previewStream.id,
-                                  inflightReq.resultOutputBuffers[0].streamId);
+                        ASSERT_EQ(previewStream.id, inflightReq.resultOutputBuffers[0].streamId);
                     } else {
                         switch (inflightReq.errorCode) {
                             case ErrorCode::ERROR_REQUEST:
                             case ErrorCode::ERROR_RESULT:
                             case ErrorCode::ERROR_BUFFER:
-                                //Expected
+                                // Expected
                                 break;
                             case ErrorCode::ERROR_DEVICE:
                             default:
-                                FAIL() << "Unexpected error:" << static_cast<uint32_t> (
-                                        inflightReq.errorCode);
+                                FAIL() << "Unexpected error:"
+                                       << static_cast<uint32_t>(inflightReq.errorCode);
                         }
                     }
 
@@ -3302,31 +3377,41 @@ TEST_F(CameraHidlTest, flushPreviewRequest) {
                     ASSERT_TRUE(ret.isOk());
                 }
             }
+            break;
+            case CAMERA_DEVICE_API_VERSION_1_0: {
+                //Not applicable
+            }
+            break;
+            default: {
+                ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
+                ADD_FAILURE();
+            }
+            break;
         }
     }
 }
 
 // Verify that camera flushes correctly without any pending requests.
 TEST_F(CameraHidlTest, flushEmpty) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-        std::vector<AvailableStream> outputPreviewStreams;
-        AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
-                static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
-
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    std::vector<AvailableStream> outputPreviewStreams;
+    AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
+                                        static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
+
+    for (const auto& name : cameraDeviceNames) {
+        int deviceVersion = getCameraDeviceVersion(name, mProviderType);
+        switch (deviceVersion) {
+            case CAMERA_DEVICE_API_VERSION_3_3:
+            case CAMERA_DEVICE_API_VERSION_3_2: {
                 Stream previewStream;
                 HalStreamConfiguration halStreamConfig;
                 sp<ICameraDeviceSession> session;
                 bool supportsPartialResults = false;
                 uint32_t partialResultCount = 0;
-                configurePreviewStream(name, provider.second, &previewThreshold,
-                        &session /*out*/, &previewStream /*out*/,
-                        &halStreamConfig /*out*/, &supportsPartialResults /*out*/,
-                        &partialResultCount /*out*/);
+                configurePreviewStream(name, mProvider, &previewThreshold, &session /*out*/,
+                                       &previewStream /*out*/, &halStreamConfig /*out*/,
+                                       &supportsPartialResults /*out*/,
+                                       &partialResultCount /*out*/);
 
                 Return<Status> returnStatus = session->flush();
                 ASSERT_TRUE(returnStatus.isOk());
@@ -3335,14 +3420,23 @@ TEST_F(CameraHidlTest, flushEmpty) {
                 {
                     std::unique_lock<std::mutex> l(mLock);
                     auto timeout = std::chrono::system_clock::now() +
-                            std::chrono::milliseconds(kEmptyFlushTimeoutMSec);
-                    ASSERT_EQ(std::cv_status::timeout,
-                            mResultCondition.wait_until(l, timeout));
+                                   std::chrono::milliseconds(kEmptyFlushTimeoutMSec);
+                    ASSERT_EQ(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
                 }
 
                 Return<void> ret = session->close();
                 ASSERT_TRUE(ret.isOk());
             }
+            break;
+            case CAMERA_DEVICE_API_VERSION_1_0: {
+                //Not applicable
+            }
+            break;
+            default: {
+                ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
+                ADD_FAILURE();
+            }
+            break;
         }
     }
 }
@@ -3546,7 +3640,7 @@ void CameraHidlTest::configurePreviewStream(const std::string &name,
     ASSERT_NE(nullptr, partialResultCount);
 
     std::vector<AvailableStream> outputPreviewStreams;
-    ::android::sp<ICameraDevice> device3_2;
+    ::android::sp<ICameraDevice> device3_x;
     ALOGI("configureStreams: Testing camera device %s", name.c_str());
     Return<void> ret;
     ret = provider->getCameraDeviceInterface_V3_x(
@@ -3556,12 +3650,12 @@ void CameraHidlTest::configurePreviewStream(const std::string &name,
                   (int)status);
             ASSERT_EQ(Status::OK, status);
             ASSERT_NE(device, nullptr);
-            device3_2 = device;
+            device3_x = device;
         });
     ASSERT_TRUE(ret.isOk());
 
     sp<DeviceCb> cb = new DeviceCb(this);
-    ret = device3_2->open(
+    ret = device3_x->open(
         cb,
         [&](auto status, const auto& newSession) {
             ALOGI("device::open returns status:%d", (int)status);
@@ -3571,8 +3665,12 @@ void CameraHidlTest::configurePreviewStream(const std::string &name,
         });
     ASSERT_TRUE(ret.isOk());
 
+    auto castResult = device::V3_3::ICameraDeviceSession::castFrom(*session);
+    ASSERT_TRUE(castResult.isOk());
+    sp<device::V3_3::ICameraDeviceSession> session3_3 = castResult;
+
     camera_metadata_t *staticMeta;
-    ret = device3_2->getCameraCharacteristics([&] (Status s,
+    ret = device3_x->getCameraCharacteristics([&] (Status s,
             CameraMetadata metadata) {
         ASSERT_EQ(Status::OK, s);
         staticMeta = clone_camera_metadata(
@@ -3604,12 +3702,24 @@ void CameraHidlTest::configurePreviewStream(const std::string &name,
     ::android::hardware::hidl_vec<Stream> streams = {*previewStream};
     StreamConfiguration config = {streams,
             StreamConfigurationMode::NORMAL_MODE};
-    ret = (*session)->configureStreams(config, [&] (Status s,
-            HalStreamConfiguration halConfig) {
-        ASSERT_EQ(Status::OK, s);
-        ASSERT_EQ(1u, halConfig.streams.size());
-        *halStreamConfig = halConfig;
-    });
+    if (session3_3 == nullptr) {
+        ret = (*session)->configureStreams(config,
+                [&] (Status s, HalStreamConfiguration halConfig) {
+                    ASSERT_EQ(Status::OK, s);
+                    ASSERT_EQ(1u, halConfig.streams.size());
+                    *halStreamConfig = halConfig;
+                });
+    } else {
+        ret = session3_3->configureStreams_3_3(config,
+                [&] (Status s, device::V3_3::HalStreamConfiguration halConfig) {
+                    ASSERT_EQ(Status::OK, s);
+                    ASSERT_EQ(1u, halConfig.streams.size());
+                    halStreamConfig->streams.resize(halConfig.streams.size());
+                    for (size_t i = 0; i < halConfig.streams.size(); i++) {
+                        halStreamConfig->streams[i] = halConfig.streams[i].v3_2;
+                    }
+                });
+    }
     ASSERT_TRUE(ret.isOk());
 }
 
@@ -3617,11 +3727,12 @@ void CameraHidlTest::configurePreviewStream(const std::string &name,
 void CameraHidlTest::openEmptyDeviceSession(const std::string &name,
         sp<ICameraProvider> provider,
         sp<ICameraDeviceSession> *session /*out*/,
+        sp<device::V3_3::ICameraDeviceSession> *session3_3 /*out*/,
         camera_metadata_t **staticMeta /*out*/) {
     ASSERT_NE(nullptr, session);
     ASSERT_NE(nullptr, staticMeta);
 
-    ::android::sp<ICameraDevice> device3_2;
+    ::android::sp<ICameraDevice> device3_x;
     ALOGI("configureStreams: Testing camera device %s", name.c_str());
     Return<void> ret;
     ret = provider->getCameraDeviceInterface_V3_x(
@@ -3631,12 +3742,12 @@ void CameraHidlTest::openEmptyDeviceSession(const std::string &name,
                   (int)status);
             ASSERT_EQ(Status::OK, status);
             ASSERT_NE(device, nullptr);
-            device3_2 = device;
+            device3_x = device;
         });
     ASSERT_TRUE(ret.isOk());
 
     sp<EmptyDeviceCb> cb = new EmptyDeviceCb();
-    ret = device3_2->open(cb, [&](auto status, const auto& newSession) {
+    ret = device3_x->open(cb, [&](auto status, const auto& newSession) {
             ALOGI("device::open returns status:%d", (int)status);
             ASSERT_EQ(Status::OK, status);
             ASSERT_NE(newSession, nullptr);
@@ -3644,7 +3755,7 @@ void CameraHidlTest::openEmptyDeviceSession(const std::string &name,
         });
     ASSERT_TRUE(ret.isOk());
 
-    ret = device3_2->getCameraCharacteristics([&] (Status s,
+    ret = device3_x->getCameraCharacteristics([&] (Status s,
             CameraMetadata metadata) {
         ASSERT_EQ(Status::OK, s);
         *staticMeta = clone_camera_metadata(
@@ -3652,6 +3763,12 @@ void CameraHidlTest::openEmptyDeviceSession(const std::string &name,
         ASSERT_NE(nullptr, *staticMeta);
     });
     ASSERT_TRUE(ret.isOk());
+
+    if(session3_3 != nullptr) {
+        auto castResult = device::V3_3::ICameraDeviceSession::castFrom(*session);
+        ASSERT_TRUE(castResult.isOk());
+        *session3_3 = castResult;
+    }
 }
 
 // Open a particular camera device.
@@ -3783,6 +3900,7 @@ void CameraHidlTest::setParameters(
 int main(int argc, char **argv) {
   ::testing::AddGlobalTestEnvironment(CameraHidlEnvironment::Instance());
   ::testing::InitGoogleTest(&argc, argv);
+  CameraHidlEnvironment::Instance()->init(&argc, argv);
   int status = RUN_ALL_TESTS();
   ALOGI("Test result = %d", status);
   return status;
diff --git a/cas/1.0/Android.bp b/cas/1.0/Android.bp
new file mode 100644 (file)
index 0000000..6d94793
--- /dev/null
@@ -0,0 +1,87 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+filegroup {
+    name: "android.hardware.cas@1.0_hal",
+    srcs: [
+        "types.hal",
+        "ICas.hal",
+        "ICasListener.hal",
+        "IDescramblerBase.hal",
+        "IMediaCasService.hal",
+    ],
+}
+
+genrule {
+    name: "android.hardware.cas@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.cas@1.0",
+    srcs: [
+        ":android.hardware.cas@1.0_hal",
+    ],
+    out: [
+        "android/hardware/cas/1.0/types.cpp",
+        "android/hardware/cas/1.0/CasAll.cpp",
+        "android/hardware/cas/1.0/CasListenerAll.cpp",
+        "android/hardware/cas/1.0/DescramblerBaseAll.cpp",
+        "android/hardware/cas/1.0/MediaCasServiceAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.cas@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.cas@1.0",
+    srcs: [
+        ":android.hardware.cas@1.0_hal",
+    ],
+    out: [
+        "android/hardware/cas/1.0/types.h",
+        "android/hardware/cas/1.0/hwtypes.h",
+        "android/hardware/cas/1.0/ICas.h",
+        "android/hardware/cas/1.0/IHwCas.h",
+        "android/hardware/cas/1.0/BnHwCas.h",
+        "android/hardware/cas/1.0/BpHwCas.h",
+        "android/hardware/cas/1.0/BsCas.h",
+        "android/hardware/cas/1.0/ICasListener.h",
+        "android/hardware/cas/1.0/IHwCasListener.h",
+        "android/hardware/cas/1.0/BnHwCasListener.h",
+        "android/hardware/cas/1.0/BpHwCasListener.h",
+        "android/hardware/cas/1.0/BsCasListener.h",
+        "android/hardware/cas/1.0/IDescramblerBase.h",
+        "android/hardware/cas/1.0/IHwDescramblerBase.h",
+        "android/hardware/cas/1.0/BnHwDescramblerBase.h",
+        "android/hardware/cas/1.0/BpHwDescramblerBase.h",
+        "android/hardware/cas/1.0/BsDescramblerBase.h",
+        "android/hardware/cas/1.0/IMediaCasService.h",
+        "android/hardware/cas/1.0/IHwMediaCasService.h",
+        "android/hardware/cas/1.0/BnHwMediaCasService.h",
+        "android/hardware/cas/1.0/BpHwMediaCasService.h",
+        "android/hardware/cas/1.0/BsMediaCasService.h",
+    ],
+}
+
+cc_library {
+    name: "android.hardware.cas@1.0",
+    defaults: ["hidl-module-defaults"],
+    generated_sources: ["android.hardware.cas@1.0_genc++"],
+    generated_headers: ["android.hardware.cas@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.cas@1.0_genc++_headers"],
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+    ],
+}
diff --git a/cas/1.0/CasHal.mk b/cas/1.0/CasHal.mk
new file mode 100644 (file)
index 0000000..3cae6bf
--- /dev/null
@@ -0,0 +1,192 @@
+#
+# 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.
+
+
+########################################################################
+# Included by frameworks/base for MediaCas. Hidl HAL can't be linked as
+# Java lib from frameworks because it has dependency on frameworks itself.
+#
+
+intermediates := $(TARGET_OUT_COMMON_GEN)/JAVA_LIBRARIES/android.hardware.cas-V1.0-java_intermediates
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+HIDL_PATH := system/libhidl/transport/base/1.0
+
+#
+# Build types.hal (DebugInfo)
+#
+GEN := $(intermediates)/android/hidl/base/V1_0/DebugInfo.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(HIDL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hidl:system/libhidl/transport \
+        android.hidl.base@1.0::types.DebugInfo
+
+$(GEN): $(HIDL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IBase.hal
+#
+GEN := $(intermediates)/android/hidl/base/V1_0/IBase.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(HIDL_PATH)/IBase.hal
+$(GEN): PRIVATE_DEPS += $(HIDL_PATH)/types.hal
+$(GEN): $(HIDL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hidl:system/libhidl/transport \
+        android.hidl.base@1.0::IBase
+
+$(GEN): $(HIDL_PATH)/IBase.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+HIDL_PATH := hardware/interfaces/cas/1.0
+
+#
+# Build types.hal (HidlCasPluginDescriptor)
+#
+GEN := $(intermediates)/android/hardware/cas/V1_0/HidlCasPluginDescriptor.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(HIDL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.cas@1.0::types.HidlCasPluginDescriptor
+
+$(GEN): $(HIDL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Status)
+#
+GEN := $(intermediates)/android/hardware/cas/V1_0/Status.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(HIDL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.cas@1.0::types.Status
+
+$(GEN): $(HIDL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build ICas.hal
+#
+GEN := $(intermediates)/android/hardware/cas/V1_0/ICas.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(HIDL_PATH)/ICas.hal
+$(GEN): PRIVATE_DEPS += $(HIDL_PATH)/types.hal
+$(GEN): $(HIDL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.cas@1.0::ICas
+
+$(GEN): $(HIDL_PATH)/ICas.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build ICasListener.hal
+#
+GEN := $(intermediates)/android/hardware/cas/V1_0/ICasListener.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(HIDL_PATH)/ICasListener.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.cas@1.0::ICasListener
+
+$(GEN): $(HIDL_PATH)/ICasListener.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IDescramblerBase.hal
+#
+GEN := $(intermediates)/android/hardware/cas/V1_0/IDescramblerBase.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(HIDL_PATH)/IDescramblerBase.hal
+$(GEN): PRIVATE_DEPS += $(HIDL_PATH)/types.hal
+$(GEN): $(HIDL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.cas@1.0::IDescramblerBase
+
+$(GEN): $(HIDL_PATH)/IDescramblerBase.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IMediaCasService.hal
+#
+GEN := $(intermediates)/android/hardware/cas/V1_0/IMediaCasService.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(HIDL_PATH)/IMediaCasService.hal
+$(GEN): PRIVATE_DEPS += $(HIDL_PATH)/ICas.hal
+$(GEN): $(HIDL_PATH)/ICas.hal
+$(GEN): PRIVATE_DEPS += $(HIDL_PATH)/ICasListener.hal
+$(GEN): $(HIDL_PATH)/ICasListener.hal
+$(GEN): PRIVATE_DEPS += $(HIDL_PATH)/IDescramblerBase.hal
+$(GEN): $(HIDL_PATH)/IDescramblerBase.hal
+$(GEN): PRIVATE_DEPS += $(HIDL_PATH)/types.hal
+$(GEN): $(HIDL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.cas@1.0::IMediaCasService
+
+$(GEN): $(HIDL_PATH)/IMediaCasService.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
diff --git a/cas/1.0/ICas.hal b/cas/1.0/ICas.hal
new file mode 100644 (file)
index 0000000..08a92da
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.cas@1.0;
+
+import android.hardware.cas@1.0::types;
+
+/**
+  * 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 {
+    /**
+     * Provide the CA private data from a CA_descriptor in the conditional
+     * access table to a CasPlugin.
+     *
+     * @param pvtData a byte array containing the private data, the format of
+     * which is scheme-specific and opaque to the framework.
+     * @return status the status of the call.
+     */
+    setPrivateData(vec<uint8_t> pvtData) generates (Status status);
+
+    /**
+     * Open a session to descramble one or more streams scrambled by the
+     * conditional access system.
+     *
+     * @return status the status of the call.
+     * @return sessionId the id of the newly opened session.
+     */
+    openSession() generates(Status status, HidlCasSessionId sessionId);
+
+    /**
+     * Close a session.
+     *
+     * @param sessionId the id of the session to be closed.
+     * @return status the status of the call.
+     */
+    closeSession(HidlCasSessionId sessionId) generates (Status status);
+
+    /**
+     * Provide the CA private data from a CA_descriptor in the program map
+     * table to a session.
+     *
+     * @param sessionId the id of the session which the private data applies to.
+     * @param pvtData a byte array containing the private data, the format of
+     * which is scheme-specific and opaque to the framework.
+     * @return status the status of the call.
+     */
+    setSessionPrivateData(HidlCasSessionId sessionId, vec<uint8_t> pvtData)
+        generates (Status status);
+
+    /**
+     * Process an ECM from the ECM stream for this session’s elementary stream.
+     *
+     * @param sessionId the id of the session which the ecm data applies to.
+     * @param ecm a byte array containing the ecm data.
+     * @return status the status of the call.
+     */
+    processEcm(HidlCasSessionId sessionId, vec<uint8_t> ecm)
+        generates (Status status);
+
+    /**
+     * Process an in-band EMM from the EMM stream.
+     *
+     * @param emm a byte array containing the emm data.
+     * @return status the status of the call.
+     */
+    processEmm(vec<uint8_t> emm) generates (Status status);
+
+    /**
+     * Send an scheme-specific event to the CasPlugin.
+     *
+     * @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.
+     */
+    sendEvent(int32_t event, int32_t arg, vec<uint8_t> eventData)
+        generates (Status status);
+
+    /**
+     * Initiate a provisioning operation for a CA system.
+     *
+     * @param provisionString string containing information needed for the
+     * provisioning operation, the format of which is scheme and implementation
+     * specific.
+     * @return status the status of the call.
+     */
+    provision(string provisionString) generates (Status status);
+
+    /**
+     * Notify the CA system to refresh entitlement keys.
+     *
+     * @param refreshType the type of the refreshment.
+     * @param refreshData private data associated with the refreshment.
+     * @return status the status of the call.
+     */
+    refreshEntitlements(int32_t refreshType, vec<uint8_t> refreshData)
+        generates (Status status);
+
+    /**
+     * Release the descrambler instance.
+     *
+     * @return status the status of the call.
+     */
+    release() generates (Status status);
+};
diff --git a/cas/1.0/ICasListener.hal b/cas/1.0/ICasListener.hal
new file mode 100644 (file)
index 0000000..8ae6014
--- /dev/null
@@ -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.
+ */
+package android.hardware.cas@1.0;
+
+interface ICasListener {
+    /**
+      * Notify the listener of a scheme-specific event from the CA system.
+      *
+      * @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.
+      */
+    onEvent(int32_t event, int32_t arg, vec<uint8_t> data);
+};
diff --git a/cas/1.0/IDescramblerBase.hal b/cas/1.0/IDescramblerBase.hal
new file mode 100644 (file)
index 0000000..a126084
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.cas@1.0;
+
+import android.hardware.cas@1.0::types;
+
+/**
+ * IDescramblerBase is the API to control the descrambler and is accessible
+ * from both Java and native level.
+ */
+
+interface IDescramblerBase {
+    /**
+     * Associate a MediaCas session with this MediaDescrambler instance.
+     *
+     * @param sessionId the id of the session to associate with this descrambler instance.
+     * @return status the status of the call.
+     */
+    setMediaCasSession(HidlCasSessionId sessionId) generates (Status status);
+
+    /**
+     * Query if the scrambling scheme requires the use of a secure decoder
+     * to decode data of the given mime type.
+     *
+     * @param mime the mime type of the media data.
+     * @return result whether the descrambler requires a secure decoder.
+     */
+    requiresSecureDecoderComponent(string mime) generates (bool result);
+
+    /**
+     * Release the descrambler instance.
+     *
+     * @return status the status of the call.
+     */
+    release() generates (Status status);
+};
diff --git a/cas/1.0/IMediaCasService.hal b/cas/1.0/IMediaCasService.hal
new file mode 100644 (file)
index 0000000..cfeafad
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.cas@1.0;
+
+import android.hardware.cas@1.0::ICas;
+import android.hardware.cas@1.0::ICasListener;
+import android.hardware.cas@1.0::IDescramblerBase;
+
+/**
+ * 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 {
+    /**
+     * List all available CA systems on the device.
+     *
+     * @return descriptors an array of descriptors for the available CA systems.
+     */
+    enumeratePlugins() generates (vec<HidlCasPluginDescriptor> descriptors);
+
+    /**
+     * Query if a certain CA system is supported on this device.
+     *
+     * @param CA_system_id the id of the CA system.
+     * @return result whether the specified CA system is supported on this device.
+     */
+    isSystemIdSupported(int32_t CA_system_id) generates (bool result);
+
+    /**
+     * Construct a new instance of a CasPlugin given a CA_system_id.
+     *
+     * @param CA_system_id 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.
+     */
+    createPlugin(int32_t CA_system_id, ICasListener listener) generates (ICas cas);
+
+    /**
+     * Query if the descrambling scheme for a CA system is supported on this device.
+     *
+     * @param CA_system_id the id of the CA system.
+     * @return result whether the specified descrambling scheme is supported on this device.
+     */
+    isDescramblerSupported(int32_t CA_system_id) generates (bool result);
+
+    /**
+     * Construct a new instance of a DescramblerPlugin given a CA_system_id.
+     *
+     * @param CA_system_id the id of the CA system.
+     * @return descrambler the newly created plugin interface.
+     */
+    createDescrambler(int32_t CA_system_id) generates (IDescramblerBase descrambler);
+};
diff --git a/cas/1.0/default/Android.bp b/cas/1.0/default/Android.bp
new file mode 100644 (file)
index 0000000..6da5cc4
--- /dev/null
@@ -0,0 +1,39 @@
+cc_binary {
+    name: "android.hardware.cas@1.0-service",
+    defaults: ["hidl_defaults"],
+    vendor: true,
+    relative_install_path: "hw",
+    srcs: [
+      "CasImpl.cpp",
+      "DescramblerImpl.cpp",
+      "MediaCasService.cpp",
+      "service.cpp",
+      "SharedLibrary.cpp",
+      "TypeConvert.cpp",
+    ],
+
+    product_variables: {
+        treble: {
+            cflags: ["-DUSE_VNDBINDER"],
+        },
+    },
+
+    compile_multilib: "32",
+    init_rc: ["android.hardware.cas@1.0-service.rc"],
+
+    shared_libs: [
+      "android.hardware.cas@1.0",
+      "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",
+    ],
+}
diff --git a/cas/1.0/default/CasImpl.cpp b/cas/1.0/default/CasImpl.cpp
new file mode 100644 (file)
index 0000000..9d1f4a3
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * 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_NDEBUG 0
+#define LOG_TAG "android.hardware.cas@1.0-CasImpl"
+
+#include <android/hardware/cas/1.0/ICasListener.h>
+#include <media/cas/CasAPI.h>
+#include <utils/Log.h>
+
+#include "CasImpl.h"
+#include "SharedLibrary.h"
+#include "TypeConvert.h"
+
+namespace android {
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+namespace implementation {
+
+struct CasImpl::PluginHolder : public RefBase {
+public:
+    explicit PluginHolder(CasPlugin *plugin) : mPlugin(plugin) {}
+    ~PluginHolder() { if (mPlugin != NULL) delete mPlugin; }
+    CasPlugin* get() { return mPlugin; }
+
+private:
+    CasPlugin *mPlugin;
+    DISALLOW_EVIL_CONSTRUCTORS(PluginHolder);
+};
+
+CasImpl::CasImpl(const sp<ICasListener> &listener)
+    : mPluginHolder(NULL), 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<CasImpl *>(appData);
+    casImpl->onEvent(event, arg, data, size);
+}
+
+void CasImpl::init(const sp<SharedLibrary>& library, CasPlugin *plugin) {
+    mLibrary = library;
+    mPluginHolder = new PluginHolder(plugin);
+}
+
+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);
+}
+
+Return<Status> CasImpl::setPrivateData(const HidlCasData& pvtData) {
+    ALOGV("%s", __FUNCTION__);
+    sp<PluginHolder> holder = mPluginHolder;
+    if (holder == NULL) {
+        return toStatus(INVALID_OPERATION);
+    }
+    return toStatus(holder->get()->setPrivateData(pvtData));
+}
+
+Return<void> CasImpl::openSession(openSession_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+    CasSessionId sessionId;
+
+    sp<PluginHolder> holder = mPluginHolder;
+    status_t err = INVALID_OPERATION;
+    if (holder != NULL) {
+        err = holder->get()->openSession(&sessionId);
+    }
+
+    _hidl_cb(toStatus(err), sessionId);
+
+    return Void();
+}
+
+Return<Status> CasImpl::setSessionPrivateData(
+        const HidlCasSessionId &sessionId, const HidlCasData& pvtData) {
+    ALOGV("%s: sessionId=%s", __FUNCTION__,
+            sessionIdToString(sessionId).string());
+    sp<PluginHolder> holder = mPluginHolder;
+    if (holder == NULL) {
+        return toStatus(INVALID_OPERATION);
+    }
+    return toStatus(
+            holder->get()->setSessionPrivateData(
+                    sessionId, pvtData));
+}
+
+Return<Status> CasImpl::closeSession(const HidlCasSessionId &sessionId) {
+    ALOGV("%s: sessionId=%s", __FUNCTION__,
+            sessionIdToString(sessionId).string());
+    sp<PluginHolder> holder = mPluginHolder;
+    if (holder == NULL) {
+        return toStatus(INVALID_OPERATION);
+    }
+    return toStatus(holder->get()->closeSession(sessionId));
+}
+
+Return<Status> CasImpl::processEcm(
+        const HidlCasSessionId &sessionId, const HidlCasData& ecm) {
+    ALOGV("%s: sessionId=%s", __FUNCTION__,
+            sessionIdToString(sessionId).string());
+    sp<PluginHolder> holder = mPluginHolder;
+    if (holder == NULL) {
+        return toStatus(INVALID_OPERATION);
+    }
+
+    return toStatus(holder->get()->processEcm(sessionId, ecm));
+}
+
+Return<Status> CasImpl::processEmm(const HidlCasData& emm) {
+    ALOGV("%s", __FUNCTION__);
+    sp<PluginHolder> holder = mPluginHolder;
+    if (holder == NULL) {
+        return toStatus(INVALID_OPERATION);
+    }
+
+    return toStatus(holder->get()->processEmm(emm));
+}
+
+Return<Status> CasImpl::sendEvent(
+        int32_t event, int32_t arg,
+        const HidlCasData& eventData) {
+    ALOGV("%s", __FUNCTION__);
+    sp<PluginHolder> holder = mPluginHolder;
+    if (holder == NULL) {
+        return toStatus(INVALID_OPERATION);
+    }
+
+    status_t err = holder->get()->sendEvent(event, arg, eventData);
+    return toStatus(err);
+}
+
+Return<Status> CasImpl::provision(const hidl_string& provisionString) {
+    ALOGV("%s: provisionString=%s", __FUNCTION__, provisionString.c_str());
+    sp<PluginHolder> holder = mPluginHolder;
+    if (holder == NULL) {
+        return toStatus(INVALID_OPERATION);
+    }
+
+    return toStatus(holder->get()->provision(String8(provisionString.c_str())));
+}
+
+Return<Status> CasImpl::refreshEntitlements(
+        int32_t refreshType,
+        const HidlCasData& refreshData) {
+    ALOGV("%s", __FUNCTION__);
+    sp<PluginHolder> holder = mPluginHolder;
+    if (holder == NULL) {
+        return toStatus(INVALID_OPERATION);
+    }
+
+    status_t err = holder->get()->refreshEntitlements(refreshType, refreshData);
+    return toStatus(err);
+}
+
+Return<Status> CasImpl::release() {
+    ALOGV("%s: plugin=%p", __FUNCTION__,
+            mPluginHolder != NULL ? mPluginHolder->get() : NULL);
+    mPluginHolder.clear();
+    return Status::OK;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace cas
+} // namespace hardware
+} // namespace android
diff --git a/cas/1.0/default/CasImpl.h b/cas/1.0/default/CasImpl.h
new file mode 100644 (file)
index 0000000..841d64e
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * 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_CAS_V1_0_CAS_IMPL_H_
+#define ANDROID_HARDWARE_CAS_V1_0_CAS_IMPL_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <android/hardware/cas/1.0/ICas.h>
+
+namespace android {
+struct CasPlugin;
+
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+struct ICasListener;
+namespace implementation {
+
+class SharedLibrary;
+
+class CasImpl : public ICas {
+public:
+    CasImpl(const sp<ICasListener> &listener);
+    virtual ~CasImpl();
+
+    static void OnEvent(
+            void *appData,
+            int32_t event,
+            int32_t arg,
+            uint8_t *data,
+            size_t size);
+
+    void init(const sp<SharedLibrary>& library, CasPlugin *plugin);
+    void onEvent(
+            int32_t event,
+            int32_t arg,
+            uint8_t *data,
+            size_t size);
+
+    // ICas inherits
+
+    virtual Return<Status> setPrivateData(
+            const HidlCasData& pvtData) override;
+
+    virtual Return<void> openSession(
+            openSession_cb _hidl_cb) override;
+
+    virtual Return<Status> closeSession(
+            const HidlCasSessionId& sessionId) override;
+
+    virtual Return<Status> setSessionPrivateData(
+            const HidlCasSessionId& sessionId,
+            const HidlCasData& pvtData) override;
+
+    virtual Return<Status> processEcm(
+            const HidlCasSessionId& sessionId,
+            const HidlCasData& ecm) override;
+
+    virtual Return<Status> processEmm(
+            const HidlCasData& emm) override;
+
+    virtual Return<Status> sendEvent(
+            int32_t event, int32_t arg,
+            const HidlCasData& eventData) override;
+
+    virtual Return<Status> provision(
+            const hidl_string& provisionString) override;
+
+    virtual Return<Status> refreshEntitlements(
+            int32_t refreshType,
+            const HidlCasData& refreshData) override;
+
+    virtual Return<Status> release() override;
+
+private:
+    struct PluginHolder;
+    sp<SharedLibrary> mLibrary;
+    sp<PluginHolder> mPluginHolder;
+    sp<ICasListener> mListener;
+
+    DISALLOW_EVIL_CONSTRUCTORS(CasImpl);
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace cas
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_CAS_V1_0_CAS_IMPL_H_
diff --git a/cas/1.0/default/DescramblerImpl.cpp b/cas/1.0/default/DescramblerImpl.cpp
new file mode 100644 (file)
index 0000000..3d90809
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * 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_NDEBUG 0
+#define LOG_TAG "android.hardware.cas@1.0-DescramblerImpl"
+
+#include <hidlmemory/mapping.h>
+#include <media/hardware/CryptoAPI.h>
+#include <media/cas/DescramblerAPI.h>
+#include <utils/Log.h>
+
+#include "DescramblerImpl.h"
+#include "SharedLibrary.h"
+#include "TypeConvert.h"
+
+namespace android {
+using hidl::memory::V1_0::IMemory;
+
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+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<SharedLibrary>& library, DescramblerPlugin *plugin) :
+        mLibrary(library), mPlugin(plugin) {
+    ALOGV("CTOR: mPlugin=%p", mPlugin);
+}
+
+DescramblerImpl::~DescramblerImpl() {
+    ALOGV("DTOR: mPlugin=%p", mPlugin);
+    release();
+}
+
+Return<Status> DescramblerImpl::setMediaCasSession(const HidlCasSessionId& sessionId) {
+    ALOGV("%s: sessionId=%s", __FUNCTION__,
+            sessionIdToString(sessionId).string());
+
+    return toStatus(mPlugin->setMediaCasSession(sessionId));
+}
+
+Return<bool> DescramblerImpl::requiresSecureDecoderComponent(
+        const hidl_string& mime) {
+    return mPlugin->requiresSecureDecoderComponent(String8(mime.c_str()));
+}
+
+Return<void> DescramblerImpl::descramble(
+        ScramblingControl scramblingControl,
+        const hidl_vec<SubSample>& subSamples,
+        const SharedBuffer& srcBuffer,
+        uint64_t srcOffset,
+        const DestinationBuffer& dstBuffer,
+        uint64_t dstOffset,
+        descramble_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    sp<IMemory> srcMem = mapMemory(srcBuffer.heapBase);
+    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;
+    } else {
+        native_handle_t *handle = const_cast<native_handle_t *>(
+                dstBuffer.secureMemory.getNativeHandle());
+        dstPtr = static_cast<void *>(handle);
+    }
+    // Casting hidl SubSample to DescramblerPlugin::SubSample, but need
+    // to ensure structs are actually idential
+
+    int32_t result = mPlugin->descramble(
+            dstBuffer.type != BufferType::SHARED_MEMORY,
+            (DescramblerPlugin::ScramblingControl)scramblingControl,
+            subSamples.size(),
+            (DescramblerPlugin::SubSample*)subSamples.data(),
+            srcPtr,
+            srcOffset,
+            dstPtr,
+            dstOffset,
+            NULL);
+
+    _hidl_cb(toStatus(result >= 0 ? OK : result), result, NULL);
+    return Void();
+}
+
+Return<Status> DescramblerImpl::release() {
+    ALOGV("%s: mPlugin=%p", __FUNCTION__, mPlugin);
+
+    if (mPlugin != NULL) {
+        delete mPlugin;
+        mPlugin = NULL;
+    }
+    return Status::OK;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace cas
+} // namespace hardware
+} // namespace android
diff --git a/cas/1.0/default/DescramblerImpl.h b/cas/1.0/default/DescramblerImpl.h
new file mode 100644 (file)
index 0000000..d3b146e
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * 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_CAS_V1_0_DESCRAMBLER_IMPL_H_
+#define ANDROID_HARDWARE_CAS_V1_0_DESCRAMBLER_IMPL_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <android/hardware/cas/native/1.0/IDescrambler.h>
+
+namespace android {
+struct DescramblerPlugin;
+using namespace hardware::cas::native::V1_0;
+
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+namespace implementation {
+
+class SharedLibrary;
+
+class DescramblerImpl : public IDescrambler {
+public:
+    DescramblerImpl(const sp<SharedLibrary>& library, DescramblerPlugin *plugin);
+    virtual ~DescramblerImpl();
+
+    virtual Return<Status> setMediaCasSession(
+            const HidlCasSessionId& sessionId) override;
+
+    virtual Return<bool> requiresSecureDecoderComponent(
+            const hidl_string& mime) override;
+
+    virtual Return<void> descramble(
+            ScramblingControl scramblingControl,
+            const hidl_vec<SubSample>& subSamples,
+            const SharedBuffer& srcBuffer,
+            uint64_t srcOffset,
+            const DestinationBuffer& dstBuffer,
+            uint64_t dstOffset,
+            descramble_cb _hidl_cb) override;
+
+    virtual Return<Status> release() override;
+
+private:
+    sp<SharedLibrary> mLibrary;
+    DescramblerPlugin *mPlugin;
+
+    DISALLOW_EVIL_CONSTRUCTORS(DescramblerImpl);
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace cas
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_CAS_V1_0_DESCRAMBLER_IMPL_H_
diff --git a/cas/1.0/default/FactoryLoader.h b/cas/1.0/default/FactoryLoader.h
new file mode 100644 (file)
index 0000000..18c2186
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * 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_CAS_V1_0_FACTORY_LOADER_H_
+#define ANDROID_HARDWARE_CAS_V1_0_FACTORY_LOADER_H_
+
+#include <dirent.h>
+#include <dlfcn.h>
+#include "SharedLibrary.h"
+#include <utils/KeyedVector.h>
+#include <utils/Mutex.h>
+#include <media/cas/CasAPI.h>
+
+using namespace std;
+
+namespace android {
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+namespace implementation {
+
+template <class T>
+class FactoryLoader {
+public:
+    FactoryLoader(const char *name) :
+        mFactory(NULL), mCreateFactoryFuncName(name) {}
+
+    virtual ~FactoryLoader() { closeFactory(); }
+
+    bool findFactoryForScheme(
+            int32_t CA_system_id,
+            sp<SharedLibrary> *library = NULL,
+            T** factory = NULL);
+
+    bool enumeratePlugins(vector<HidlCasPluginDescriptor>* results);
+
+private:
+    typedef T*(*CreateFactoryFunc)();
+
+    Mutex mMapLock;
+    T* mFactory;
+    const char *mCreateFactoryFuncName;
+    sp<SharedLibrary> mLibrary;
+    KeyedVector<int32_t, String8> mCASystemIdToLibraryPathMap;
+    KeyedVector<String8, wp<SharedLibrary> > mLibraryPathToOpenLibraryMap;
+
+    bool loadFactoryForSchemeFromPath(
+            const String8 &path,
+            int32_t CA_system_id,
+            sp<SharedLibrary> *library,
+            T** factory);
+
+    bool queryPluginsFromPath(
+            const String8 &path,
+            vector<HidlCasPluginDescriptor>* results);
+
+    bool openFactory(const String8 &path);
+    void closeFactory();
+};
+
+template <class T>
+bool FactoryLoader<T>::findFactoryForScheme(
+        int32_t CA_system_id, sp<SharedLibrary> *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 <class T>
+bool FactoryLoader<T>::enumeratePlugins(
+        vector<HidlCasPluginDescriptor>* 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 <class T>
+bool FactoryLoader<T>::loadFactoryForSchemeFromPath(
+        const String8 &path, int32_t CA_system_id,
+        sp<SharedLibrary> *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 <class T>
+bool FactoryLoader<T>::queryPluginsFromPath(
+        const String8 &path, vector<HidlCasPluginDescriptor>* results) {
+    closeFactory();
+
+    vector<CasPluginDescriptor> 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 <class T>
+bool FactoryLoader<T>::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 <class T>
+void FactoryLoader<T>::closeFactory() {
+    delete mFactory;
+    mFactory = NULL;
+    mLibrary.clear();
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace cas
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_CAS_V1_0_FACTORY_LOADER_H_
diff --git a/cas/1.0/default/MediaCasService.cpp b/cas/1.0/default/MediaCasService.cpp
new file mode 100644 (file)
index 0000000..ca43224
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * 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_NDEBUG 0
+#define LOG_TAG "android.hardware.cas@1.0-MediaCasService"
+
+#include <android/hardware/cas/1.0/ICasListener.h>
+#include <media/cas/CasAPI.h>
+#include <media/cas/DescramblerAPI.h>
+#include <utils/Log.h>
+
+#include "CasImpl.h"
+#include "DescramblerImpl.h"
+#include "MediaCasService.h"
+
+namespace android {
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+namespace implementation {
+
+MediaCasService::MediaCasService() :
+    mCasLoader("createCasFactory"),
+    mDescramblerLoader("createDescramblerFactory") {
+}
+
+MediaCasService::~MediaCasService() {
+}
+
+Return<void> MediaCasService::enumeratePlugins(enumeratePlugins_cb _hidl_cb) {
+
+    ALOGV("%s", __FUNCTION__);
+
+    vector<HidlCasPluginDescriptor> results;
+    mCasLoader.enumeratePlugins(&results);
+
+    _hidl_cb(results);
+    return Void();
+}
+
+Return<bool> MediaCasService::isSystemIdSupported(int32_t CA_system_id) {
+    ALOGV("isSystemIdSupported: CA_system_id=%d", CA_system_id);
+
+    return mCasLoader.findFactoryForScheme(CA_system_id);
+}
+
+Return<sp<ICas>> MediaCasService::createPlugin(
+        int32_t CA_system_id, const sp<ICasListener>& listener) {
+
+    ALOGV("%s: CA_system_id=%d", __FUNCTION__, CA_system_id);
+
+    sp<ICas> result;
+
+    CasFactory *factory;
+    sp<SharedLibrary> library;
+    if (mCasLoader.findFactoryForScheme(CA_system_id, &library, &factory)) {
+        CasPlugin *plugin = NULL;
+        sp<CasImpl> casImpl = new CasImpl(listener);
+        if (factory->createPlugin(CA_system_id, (uint64_t)casImpl.get(),
+                &CasImpl::OnEvent, &plugin) == OK && plugin != NULL) {
+            casImpl->init(library, plugin);
+            result = casImpl;
+        }
+    }
+
+    return result;
+}
+
+Return<bool> MediaCasService::isDescramblerSupported(int32_t CA_system_id) {
+    ALOGV("%s: CA_system_id=%d", __FUNCTION__, CA_system_id);
+
+    return mDescramblerLoader.findFactoryForScheme(CA_system_id);
+}
+
+Return<sp<IDescramblerBase>> MediaCasService::createDescrambler(int32_t CA_system_id) {
+
+    ALOGV("%s: CA_system_id=%d", __FUNCTION__, CA_system_id);
+
+    sp<IDescrambler> result;
+
+    DescramblerFactory *factory;
+    sp<SharedLibrary> 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_0
+} // namespace cas
+} // namespace hardware
+} // namespace android
diff --git a/cas/1.0/default/MediaCasService.h b/cas/1.0/default/MediaCasService.h
new file mode 100644 (file)
index 0000000..77ddac6
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * 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_CAS_V1_0_MEDIA_CAS_SERVICE_H_
+#define ANDROID_HARDWARE_CAS_V1_0_MEDIA_CAS_SERVICE_H_
+
+#include <android/hardware/cas/1.0/IMediaCasService.h>
+
+#include "FactoryLoader.h"
+
+namespace android {
+struct CasFactory;
+struct DescramblerFactory;
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+namespace implementation {
+
+class MediaCasService : public IMediaCasService {
+public:
+    MediaCasService();
+
+    virtual Return<void> enumeratePlugins(
+            enumeratePlugins_cb _hidl_cb) override;
+
+    virtual Return<bool> isSystemIdSupported(
+            int32_t CA_system_id) override;
+
+    virtual Return<sp<ICas>> createPlugin(
+            int32_t CA_system_id, const sp<ICasListener>& listener) override;
+
+    virtual Return<bool> isDescramblerSupported(
+            int32_t CA_system_id) override;
+
+    virtual Return<sp<IDescramblerBase>> createDescrambler(
+            int32_t CA_system_id) override;
+
+private:
+    FactoryLoader<CasFactory> mCasLoader;
+    FactoryLoader<DescramblerFactory> mDescramblerLoader;
+
+    virtual ~MediaCasService();
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace cas
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_CAS_V1_0_MEDIA_CAS_SERVICE_H_
diff --git a/cas/1.0/default/SharedLibrary.cpp b/cas/1.0/default/SharedLibrary.cpp
new file mode 100644 (file)
index 0000000..9c7f385
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * 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_NDEBUG 0
+#define LOG_TAG "android.hardware.cas@1.0-SharedLibrary"
+
+#include <dlfcn.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include "SharedLibrary.h"
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+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_0
+}  // namespace cas
+}  // namespace hardware
+}  // namespace android
diff --git a/cas/1.0/default/SharedLibrary.h b/cas/1.0/default/SharedLibrary.h
new file mode 100644 (file)
index 0000000..18130a5
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_CAS_V1_0_SHARED_LIBRARY_H_
+#define ANDROID_HARDWARE_CAS_V1_0_SHARED_LIBRARY_H_
+
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+#include <media/stagefright/foundation/ABase.h>
+
+namespace android {
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+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_0
+}  // namespace cas
+}  // namespace hardware
+}  // namespace android
+
+#endif // ANDROID_HARDWARE_CAS_V1_0_SHARED_LIBRARY_H_
diff --git a/cas/1.0/default/TypeConvert.cpp b/cas/1.0/default/TypeConvert.cpp
new file mode 100644 (file)
index 0000000..cd0efdb
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * 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_NDEBUG 0
+#define LOG_TAG "android.hardware.cas@1.0-TypeConvert"
+
+#include <utils/Log.h>
+#include "TypeConvert.h"
+
+namespace android {
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+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_0
+}  // namespace cas
+}  // namespace hardware
+}  // namespace android
diff --git a/cas/1.0/default/TypeConvert.h b/cas/1.0/default/TypeConvert.h
new file mode 100644 (file)
index 0000000..7c3dded
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * 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_CAS_V1_0_TYPE_CONVERT_H
+#define ANDROID_HARDWARE_CAS_V1_0_TYPE_CONVERT_H
+
+#include <android/hardware/cas/1.0/types.h>
+#include <media/cas/CasAPI.h>
+#include <media/stagefright/MediaErrors.h>
+#include <utils/String8.h>
+
+namespace android {
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+namespace implementation {
+
+Status toStatus(status_t legacyStatus);
+
+String8 sessionIdToString(const CasSessionId &sessionId);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace cas
+}  // namespace hardware
+}  // namespace android
+
+#endif // ANDROID_HARDWARE_CAS_V1_0_TYPE_CONVERT_H
diff --git a/cas/1.0/default/android.hardware.cas@1.0-service.rc b/cas/1.0/default/android.hardware.cas@1.0-service.rc
new file mode 100644 (file)
index 0000000..93de794
--- /dev/null
@@ -0,0 +1,6 @@
+service cas-hal-1-0 /vendor/bin/hw/android.hardware.cas@1.0-service
+    class hal
+    user media
+    group mediadrm drmrpc
+    ioprio rt 4
+    writepid /dev/cpuset/foreground/tasks
diff --git a/cas/1.0/default/service.cpp b/cas/1.0/default/service.cpp
new file mode 100644 (file)
index 0000000..3f1df5a
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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
+#define LOG_TAG "android.hardware.cas@1.0-service"
+
+#include <binder/ProcessState.h>
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/LegacySupport.h>
+
+#include "MediaCasService.h"
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::hardware::cas::V1_0::implementation::MediaCasService;
+using android::hardware::cas::V1_0::IMediaCasService;
+
+int main() {
+    ALOGD("android.hardware.cas@1.0-service starting...");
+
+#ifdef USE_VNDBINDER
+    // The CAS HAL may communicate to other vendor components via
+    // /dev/vndbinder
+    android::ProcessState::initWithDriver("/dev/vndbinder");
+#endif // USE_VNDBINDER
+
+    configureRpcThreadpool(8, true /* callerWillJoin */);
+
+    // Setup hwbinder service
+    android::sp<IMediaCasService> service = new MediaCasService();
+    android::status_t status = service->registerAsService();
+    LOG_ALWAYS_FATAL_IF(
+            status != android::OK,
+            "Error while registering cas service: %d", status);
+    joinRpcThreadpool();
+    return 0;
+}
diff --git a/cas/1.0/types.hal b/cas/1.0/types.hal
new file mode 100644 (file)
index 0000000..7337f00
--- /dev/null
@@ -0,0 +1,124 @@
+/**
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cas@1.0;
+
+enum Status : uint32_t {
+    /**
+     * The CAS plugin must return OK when an operation completes without any
+     * errors.
+     */
+    OK,
+
+    /**
+     * The CAS plugin must return ERROR_CAS_NO_LICENSE, when descrambling is
+     * attempted and no license keys have been provided.
+     */
+    ERROR_CAS_NO_LICENSE,
+
+    /**
+     * ERROR_CAS_LICENSE_EXPIRED must be returned when an attempt is made
+     * to use a license and the keys in that license have expired.
+     */
+    ERROR_CAS_LICENSE_EXPIRED,
+
+    /**
+     * The CAS plugin must return ERROR_CAS_SESSION_NOT_OPENED when an
+     * attempt is made to use a session that has not been opened.
+     */
+    ERROR_CAS_SESSION_NOT_OPENED,
+
+    /**
+     * The CAS plugin must return ERROR_CAS_CANNOT_HANDLE when an unsupported
+     * data format or operation is attempted.
+     */
+    ERROR_CAS_CANNOT_HANDLE,
+
+    /**
+     * ERROR_CAS_INVALID_STATE must be returned when the device is in a state
+     * where it is not able to perform descrambling.
+     */
+    ERROR_CAS_INVALID_STATE,
+
+    /**
+     * The CAS plugin must return BAD_VALUE whenever an illegal parameter is
+     * passed to one of the interface functions.
+     */
+    BAD_VALUE,
+
+    /**
+     * The CAS plugin must return ERROR_CAS_NOT_PROVISIONED when the device
+     * has not yet been provisioned.
+     */
+    ERROR_CAS_NOT_PROVISIONED,
+
+    /**
+     * ERROR_CAS_RESOURCE_BUSY must be returned when resources, such as CAS
+     * sessions or secure buffers are not available to perform a requested
+     * operation because they are already in use.
+     */
+    ERROR_CAS_RESOURCE_BUSY,
+
+    /**
+     * The CAS Plugin must return ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION
+     * when the output protection level enabled on the device is not
+     * sufficient to meet the requirements in the license policy. HDCP is an
+     * example of a form of output protection.
+     */
+    ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION,
+
+    /**
+     * The CAS Plugin must return ERROR_CAS_TAMPER_DETECTED if an attempt to
+     * tamper with the CAS system is detected.
+     */
+    ERROR_CAS_TAMPER_DETECTED,
+
+    /**
+     * The CAS Plugin must return ERROR_CAS_DEVICE_REVOKED if the response
+     * indicates that the device has been revoked. Device revocation means
+     * that the device is no longer permitted to play content.
+     */
+    ERROR_CAS_DEVICE_REVOKED,
+
+    /**
+     * The CAS plugin must return ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED when
+     * descrambling is failing because the session is not initialized properly.
+     */
+    ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED,
+
+    /**
+     * The CAS Plugin must return ERROR_CAS_DECRYPT if the DescramblerPlugin's
+     * descramble operation fails.
+     */
+    ERROR_CAS_DECRYPT,
+
+    /**
+     * ERROR_CAS_UNKNOWN must be returned when a fatal failure occurs and no
+     * other defined error is appropriate.
+     */
+    ERROR_CAS_UNKNOWN,
+};
+
+typedef vec<uint8_t> HidlCasSessionId;
+typedef vec<uint8_t> HidlCasData;
+
+/**
+ * Describes a CAS plugin with its system id and name.
+ */
+struct HidlCasPluginDescriptor {
+    int32_t caSystemId;
+    string name;
+};
diff --git a/cas/1.0/vts/functional/Android.bp b/cas/1.0/vts/functional/Android.bp
new file mode 100644 (file)
index 0000000..e1e09e9
--- /dev/null
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+    name: "VtsHalCasV1_0TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalCasV1_0TargetTest.cpp"],
+    static_libs: [
+        "android.hardware.cas@1.0",
+        "android.hardware.cas.native@1.0",
+        "android.hidl.allocator@1.0",
+        "android.hidl.memory@1.0",
+        "libhidlmemory",
+    ],
+    shared_libs: [
+        "libbinder",
+    ],
+}
+
diff --git a/cas/1.0/vts/functional/VtsHalCasV1_0TargetTest.cpp b/cas/1.0/vts/functional/VtsHalCasV1_0TargetTest.cpp
new file mode 100644 (file)
index 0000000..d3b0f1d
--- /dev/null
@@ -0,0 +1,623 @@
+/*
+ * 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 "mediacas_hidl_hal_test"
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <android-base/logging.h>
+#include <android/hardware/cas/1.0/ICas.h>
+#include <android/hardware/cas/1.0/ICasListener.h>
+#include <android/hardware/cas/1.0/IDescramblerBase.h>
+#include <android/hardware/cas/1.0/IMediaCasService.h>
+#include <android/hardware/cas/1.0/types.h>
+#include <android/hardware/cas/native/1.0/IDescrambler.h>
+#include <android/hardware/cas/native/1.0/types.h>
+#include <binder/MemoryDealer.h>
+#include <hidl/HidlSupport.h>
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/Status.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+
+#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::hardware::cas::V1_0::ICas;
+using android::hardware::cas::V1_0::ICasListener;
+using android::hardware::cas::V1_0::IDescramblerBase;
+using android::hardware::cas::native::V1_0::IDescrambler;
+using android::hardware::cas::native::V1_0::SubSample;
+using android::hardware::cas::native::V1_0::SharedBuffer;
+using android::hardware::cas::native::V1_0::DestinationBuffer;
+using android::hardware::cas::native::V1_0::BufferType;
+using android::hardware::cas::native::V1_0::ScramblingControl;
+using android::hardware::cas::V1_0::IMediaCasService;
+using android::hardware::cas::V1_0::HidlCasPluginDescriptor;
+using android::hardware::Void;
+using android::hardware::hidl_vec;
+using android::hardware::hidl_string;
+using android::hardware::hidl_handle;
+using android::hardware::hidl_memory;
+using android::hardware::Return;
+using android::hardware::cas::V1_0::Status;
+using android::IMemory;
+using android::IMemoryHeap;
+using android::MemoryDealer;
+using android::Mutex;
+using android::sp;
+
+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<void> onEvent(int32_t event, int32_t arg,
+                                 const hidl_vec<uint8_t>& data) override {
+        android::Mutex::Autolock autoLock(mMsgLock);
+        mEvent = event;
+        mEventArg = arg;
+        mEventData = data;
+
+        mEventReceived = true;
+        mMsgCondition.signal();
+        return Void();
+    }
+
+    void testEventEcho(sp<ICas>& mediaCas, int32_t& event, int32_t& eventArg,
+                       hidl_vec<uint8_t>& eventData);
+
+   private:
+    int32_t mEvent = -1;
+    int32_t mEventArg = -1;
+    bool mEventReceived = false;
+    hidl_vec<uint8_t> mEventData;
+    android::Mutex mMsgLock;
+    android::Condition mMsgCondition;
+};
+
+void MediaCasListener::testEventEcho(sp<ICas>& mediaCas, int32_t& event, int32_t& eventArg,
+                                     hidl_vec<uint8_t>& 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);
+}
+
+class MediaCasHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    virtual void SetUp() override {
+        mService = ::testing::VtsHalHidlTargetTestBase::getService<IMediaCasService>();
+        ASSERT_NE(mService, nullptr);
+    }
+
+    sp<IMediaCasService> mService;
+
+   protected:
+    static void description(const std::string& description) {
+        RecordProperty("description", description);
+    }
+
+    sp<ICas> mMediaCas;
+    sp<IDescramblerBase> mDescramblerBase;
+    sp<MediaCasListener> mCasListener;
+
+    ::testing::AssertionResult createCasPlugin(int32_t caSystemId);
+    ::testing::AssertionResult openCasSession(std::vector<uint8_t>* sessionId);
+    ::testing::AssertionResult descrambleTestInputBuffer(const sp<IDescrambler>& descrambler,
+                                                         Status* descrambleStatus,
+                                                         sp<IMemory>* hidlInMemory);
+};
+
+::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->createPlugin(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<uint8_t>* sessionId) {
+    Status sessionStatus;
+    auto returnVoid = mMediaCas->openSession([&](Status status, const hidl_vec<uint8_t>& id) {
+        sessionStatus = status;
+        *sessionId = id;
+    });
+    return ::testing::AssertionResult(returnVoid.isOk() && (Status::OK == sessionStatus));
+}
+
+::testing::AssertionResult MediaCasHidlTest::descrambleTestInputBuffer(
+    const sp<IDescrambler>& descrambler, Status* descrambleStatus, sp<IMemory>* inMemory) {
+    hidl_vec<SubSample> hidlSubSamples;
+    hidlSubSamples.setToExternal(const_cast<SubSample*>(kSubSamples),
+                                 (sizeof(kSubSamples) / sizeof(SubSample)), false /*own*/);
+
+    sp<MemoryDealer> dealer = new MemoryDealer(sizeof(kInBinaryBuffer), "vts-cas");
+    if (nullptr == dealer.get()) {
+        ALOGE("couldn't get MemoryDealer!");
+        return ::testing::AssertionFailure();
+    }
+
+    sp<IMemory> mem = dealer->allocate(sizeof(kInBinaryBuffer));
+    if (nullptr == mem.get()) {
+        ALOGE("couldn't allocate IMemory!");
+        return ::testing::AssertionFailure();
+    }
+    *inMemory = mem;
+
+    // build hidl_memory from memory heap
+    ssize_t offset;
+    size_t size;
+    sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
+    if (nullptr == heap.get()) {
+        ALOGE("couldn't get memory heap!");
+        return ::testing::AssertionFailure();
+    }
+
+    native_handle_t* nativeHandle = native_handle_create(1, 0);
+    if (!nativeHandle) {
+        ALOGE("failed to create native handle!");
+        return ::testing::AssertionFailure();
+    }
+    nativeHandle->data[0] = heap->getHeapID();
+
+    uint8_t* ipBuffer = static_cast<uint8_t*>(static_cast<void*>(mem->pointer()));
+    memcpy(ipBuffer, kInBinaryBuffer, sizeof(kInBinaryBuffer));
+
+    SharedBuffer srcBuffer = {
+            .heapBase = hidl_memory("ashmem", hidl_handle(nativeHandle), heap->getSize()),
+            .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());
+}
+
+TEST_F(MediaCasHidlTest, EnumeratePlugins) {
+    description("Test enumerate plugins");
+    hidl_vec<HidlCasPluginDescriptor> descriptors;
+    EXPECT_TRUE(mService
+                    ->enumeratePlugins([&descriptors](
+                        hidl_vec<HidlCasPluginDescriptor> const& desc) { descriptors = desc; })
+                    .isOk());
+
+    if (descriptors.size() == 0) {
+        ALOGW("[   WARN   ] enumeratePlugins list empty");
+        return;
+    }
+
+    sp<MediaCasListener> casListener = new MediaCasListener();
+    for (size_t i = 0; i < descriptors.size(); i++) {
+        int32_t caSystemId = descriptors[i].caSystemId;
+
+        ASSERT_TRUE(createCasPlugin(caSystemId));
+    }
+}
+
+TEST_F(MediaCasHidlTest, TestInvalidSystemIdFails) {
+    description("Test failure for invalid system ID");
+    sp<MediaCasListener> casListener = new MediaCasListener();
+
+    ASSERT_FALSE(mService->isSystemIdSupported(INVALID_SYSTEM_ID));
+    ASSERT_FALSE(mService->isDescramblerSupported(INVALID_SYSTEM_ID));
+
+    auto pluginStatus = mService->createPlugin(INVALID_SYSTEM_ID, casListener);
+    ASSERT_TRUE(pluginStatus.isOk());
+    sp<ICas> mediaCas = pluginStatus;
+    EXPECT_EQ(mediaCas, nullptr);
+
+    auto descramblerStatus = mService->createDescrambler(INVALID_SYSTEM_ID);
+    ASSERT_TRUE(descramblerStatus.isOk());
+    sp<IDescramblerBase> descramblerBase = descramblerStatus;
+    EXPECT_EQ(descramblerBase, nullptr);
+}
+
+TEST_F(MediaCasHidlTest, TestClearKeyPluginInstalled) {
+    description("Test if ClearKey plugin is installed");
+    hidl_vec<HidlCasPluginDescriptor> descriptors;
+    EXPECT_TRUE(mService
+                    ->enumeratePlugins([&descriptors](
+                        hidl_vec<HidlCasPluginDescriptor> const& desc) { descriptors = desc; })
+                    .isOk());
+
+    if (descriptors.size() == 0) {
+        ALOGW("[   WARN   ] enumeratePlugins list empty");
+    }
+
+    for (size_t i = 0; i < descriptors.size(); i++) {
+        int32_t caSystemId = descriptors[i].caSystemId;
+        if (CLEAR_KEY_SYSTEM_ID == caSystemId) {
+            return;
+        }
+    }
+
+    ASSERT_TRUE(false) << "ClearKey plugin not installed";
+}
+
+TEST_F(MediaCasHidlTest, TestClearKeyApis) {
+    description("Test that valid call sequences succeed");
+
+    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<uint8_t> hidlPvtData;
+    hidlPvtData.resize(256);
+    returnStatus = mMediaCas->setPrivateData(hidlPvtData);
+    EXPECT_TRUE(returnStatus.isOk());
+    EXPECT_EQ(Status::OK, returnStatus);
+
+    std::vector<uint8_t> sessionId;
+    ASSERT_TRUE(openCasSession(&sessionId));
+    returnStatus = mMediaCas->setSessionPrivateData(sessionId, hidlPvtData);
+    EXPECT_TRUE(returnStatus.isOk());
+    EXPECT_EQ(Status::OK, returnStatus);
+
+    std::vector<uint8_t> 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<uint8_t> hidlNullPtr;
+    hidlNullPtr.setToExternal(static_cast<uint8_t*>(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<uint8_t> hidlRefreshData;
+    hidlRefreshData.setToExternal(static_cast<uint8_t*>(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);
+
+    eventID = 3;
+    eventArg = 4;
+    uint8_t eventData[] = {'e', 'v', 'e', 'n', 't', 'd', 'a', 't', 'a'};
+    hidl_vec<uint8_t> hidlEventData;
+    hidlEventData.setToExternal(static_cast<uint8_t*>(eventData), sizeof(eventData));
+    mCasListener->testEventEcho(mMediaCas, eventID, eventArg, hidlEventData);
+
+    uint8_t clearKeyEmmData[] = {'c', 'l', 'e', 'a', 'r', 'k', 'e', 'y', 'e', 'm', 'm'};
+    hidl_vec<uint8_t> hidlClearKeyEmm;
+    hidlClearKeyEmm.setToExternal(static_cast<uint8_t*>(clearKeyEmmData), sizeof(clearKeyEmmData));
+    returnStatus = mMediaCas->processEmm(hidlClearKeyEmm);
+    EXPECT_TRUE(returnStatus.isOk());
+    EXPECT_EQ(Status::OK, returnStatus);
+
+    hidl_vec<uint8_t> hidlEcm;
+    hidlEcm.setToExternal(const_cast<uint8_t*>(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<IDescrambler> descrambler;
+    descrambler = IDescrambler::castFrom(mDescramblerBase);
+    ASSERT_NE(descrambler, nullptr);
+
+    Status descrambleStatus = Status::OK;
+    sp<IMemory> dataMemory;
+
+    ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory));
+    EXPECT_EQ(Status::OK, descrambleStatus);
+
+    ASSERT_NE(nullptr, dataMemory.get());
+    uint8_t* opBuffer = static_cast<uint8_t*>(static_cast<void*>(dataMemory->pointer()));
+
+    int compareResult =
+        memcmp(static_cast<const void*>(opBuffer), static_cast<const void*>(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);
+}
+
+TEST_F(MediaCasHidlTest, TestClearKeySessionClosedAfterRelease) {
+    description("Test that all sessions are closed after a MediaCas object is released");
+
+    ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID));
+
+    auto returnStatus = mMediaCas->provision(hidl_string(PROVISION_STR));
+    EXPECT_TRUE(returnStatus.isOk());
+    EXPECT_EQ(Status::OK, returnStatus);
+
+    std::vector<uint8_t> sessionId;
+    ASSERT_TRUE(openCasSession(&sessionId));
+    std::vector<uint8_t> streamSessionId;
+    ASSERT_TRUE(openCasSession(&streamSessionId));
+
+    returnStatus = mMediaCas->release();
+    EXPECT_TRUE(returnStatus.isOk());
+    EXPECT_EQ(Status::OK, returnStatus);
+
+    returnStatus = mDescramblerBase->setMediaCasSession(sessionId);
+    EXPECT_TRUE(returnStatus.isOk());
+    EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, returnStatus);
+
+    returnStatus = mDescramblerBase->setMediaCasSession(streamSessionId);
+    EXPECT_TRUE(returnStatus.isOk());
+    EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, returnStatus);
+}
+
+TEST_F(MediaCasHidlTest, TestClearKeyErrors) {
+    description("Test that invalid call sequences fail with expected error codes");
+
+    ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID));
+
+    /*
+     * Test MediaCas error codes
+     */
+    // Provision should fail with an invalid asset string
+    auto returnStatus = mMediaCas->provision(hidl_string("invalid asset string"));
+    EXPECT_TRUE(returnStatus.isOk());
+    EXPECT_EQ(Status::ERROR_CAS_NO_LICENSE, returnStatus);
+
+    // Open a session, then close it so that it should become invalid
+    std::vector<uint8_t> invalidSessionId;
+    ASSERT_TRUE(openCasSession(&invalidSessionId));
+    returnStatus = mMediaCas->closeSession(invalidSessionId);
+    EXPECT_TRUE(returnStatus.isOk());
+    EXPECT_EQ(Status::OK, returnStatus);
+
+    // processEcm should fail with an invalid session id
+    hidl_vec<uint8_t> hidlEcm;
+    hidlEcm.setToExternal(const_cast<uint8_t*>(kEcmBinaryBuffer), sizeof(kEcmBinaryBuffer));
+    returnStatus = mMediaCas->processEcm(invalidSessionId, hidlEcm);
+    EXPECT_TRUE(returnStatus.isOk());
+    EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, returnStatus);
+
+    std::vector<uint8_t> sessionId;
+    ASSERT_TRUE(openCasSession(&sessionId));
+
+    // processEcm should fail without provisioning
+    hidlEcm.setToExternal(const_cast<uint8_t*>(kEcmBinaryBuffer), sizeof(kEcmBinaryBuffer));
+    returnStatus = mMediaCas->processEcm(sessionId, hidlEcm);
+    EXPECT_TRUE(returnStatus.isOk());
+    EXPECT_EQ(Status::ERROR_CAS_NOT_PROVISIONED, returnStatus);
+
+    returnStatus = mMediaCas->provision(hidl_string(PROVISION_STR));
+    EXPECT_TRUE(returnStatus.isOk());
+    EXPECT_EQ(Status::OK, returnStatus);
+
+    // processEcm should fail with ecm buffer that's too short
+    hidlEcm.setToExternal(const_cast<uint8_t*>(kEcmBinaryBuffer), 8);
+    returnStatus = mMediaCas->processEcm(sessionId, hidlEcm);
+    EXPECT_TRUE(returnStatus.isOk());
+    EXPECT_EQ(Status::BAD_VALUE, returnStatus);
+
+    // processEcm should fail with ecm with bad descriptor count
+    uint8_t badDescriptor[sizeof(kEcmBinaryBuffer)];
+    memcpy(badDescriptor, kEcmBinaryBuffer, sizeof(kEcmBinaryBuffer));
+    badDescriptor[17] = 0x03;  // change the descriptor count field to 3 (invalid)
+    hidlEcm.setToExternal(static_cast<uint8_t*>(badDescriptor), sizeof(badDescriptor));
+    returnStatus = mMediaCas->processEcm(sessionId, hidlEcm);
+    EXPECT_TRUE(returnStatus.isOk());
+    EXPECT_EQ(Status::ERROR_CAS_UNKNOWN, returnStatus);
+
+    /*
+     * Test MediaDescrambler error codes
+     */
+    // setMediaCasSession should fail with an invalid session id
+    returnStatus = mDescramblerBase->setMediaCasSession(invalidSessionId);
+    EXPECT_TRUE(returnStatus.isOk());
+    EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, returnStatus);
+
+    // descramble should fail without a valid session
+    sp<IDescrambler> descrambler;
+    descrambler = IDescrambler::castFrom(mDescramblerBase);
+    ASSERT_NE(descrambler, nullptr);
+
+    Status descrambleStatus = Status::OK;
+    sp<IMemory> dataMemory;
+
+    ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory));
+    EXPECT_EQ(Status::ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED, descrambleStatus);
+
+    // Now set a valid session, should still fail because no valid ecm is processed
+    returnStatus = mDescramblerBase->setMediaCasSession(sessionId);
+    EXPECT_TRUE(returnStatus.isOk());
+    EXPECT_EQ(Status::OK, returnStatus);
+
+    ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory));
+    EXPECT_EQ(Status::ERROR_CAS_DECRYPT, descrambleStatus);
+
+    // Verify that requiresSecureDecoderComponent handles empty mime
+    EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent(""));
+
+    // Verify that requiresSecureDecoderComponent handles invalid mime
+    EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent("bad"));
+}
+
+}  // anonymous namespace
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    LOG(INFO) << "Test result = " << status;
+    return status;
+}
diff --git a/cas/Android.bp b/cas/Android.bp
new file mode 100644 (file)
index 0000000..8208d3d
--- /dev/null
@@ -0,0 +1,7 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "1.0",
+    "1.0/vts/functional",
+    "1.0/default",
+    "native/1.0",
+]
diff --git a/cas/native/1.0/Android.bp b/cas/native/1.0/Android.bp
new file mode 100644 (file)
index 0000000..e39cab1
--- /dev/null
@@ -0,0 +1,68 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+filegroup {
+    name: "android.hardware.cas.native@1.0_hal",
+    srcs: [
+        "types.hal",
+        "IDescrambler.hal",
+    ],
+}
+
+genrule {
+    name: "android.hardware.cas.native@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.cas.native@1.0",
+    srcs: [
+        ":android.hardware.cas.native@1.0_hal",
+    ],
+    out: [
+        "android/hardware/cas/native/1.0/types.cpp",
+        "android/hardware/cas/native/1.0/DescramblerAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.cas.native@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.cas.native@1.0",
+    srcs: [
+        ":android.hardware.cas.native@1.0_hal",
+    ],
+    out: [
+        "android/hardware/cas/native/1.0/types.h",
+        "android/hardware/cas/native/1.0/hwtypes.h",
+        "android/hardware/cas/native/1.0/IDescrambler.h",
+        "android/hardware/cas/native/1.0/IHwDescrambler.h",
+        "android/hardware/cas/native/1.0/BnHwDescrambler.h",
+        "android/hardware/cas/native/1.0/BpHwDescrambler.h",
+        "android/hardware/cas/native/1.0/BsDescrambler.h",
+    ],
+}
+
+cc_library {
+    name: "android.hardware.cas.native@1.0",
+    defaults: ["hidl-module-defaults"],
+    generated_sources: ["android.hardware.cas.native@1.0_genc++"],
+    generated_headers: ["android.hardware.cas.native@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.cas.native@1.0_genc++_headers"],
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hardware.cas@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hardware.cas@1.0",
+    ],
+}
diff --git a/cas/native/1.0/IDescrambler.hal b/cas/native/1.0/IDescrambler.hal
new file mode 100644 (file)
index 0000000..4822111
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.cas.native@1.0;
+
+import android.hardware.cas@1.0::IDescramblerBase;
+import android.hardware.cas@1.0::Status;
+
+/**
+ * IDescrambler is the native plugin API for descrambling operations.
+ */
+
+interface IDescrambler extends IDescramblerBase {
+    /**
+     * Descramble the data in a source SharedBuffer, described by an array of
+     * SubSample structures.
+     *
+     * @param scramblingControl an enumeration indicating the key that the subsamples
+     * were scrambled with.
+     * @param subSamples an array of SubSample structures describing the number of
+     * clear and scrambled bytes within each subsample.
+     * @param srcBuffer the SharedBuffer containing the source scrambled data.
+     * @param srcOffset the position where the source scrambled data starts at.
+     * @param dstBuffer the DestinationBuffer to hold the descrambled data.
+     * @param dstOffset the position where the descrambled data should start at.
+     *
+     * @return status the status of the call.
+     * @return bytesWritten number of bytes that have been successfully descrambled.
+     * @return detailedError a detailed message describing the error (if any).
+     */
+    descramble(ScramblingControl scramblingControl, vec<SubSample> subSamples,
+        SharedBuffer srcBuffer, uint64_t srcOffset, DestinationBuffer dstBuffer, uint64_t dstOffset)
+        generates(Status status, uint32_t bytesWritten, string detailedError);
+};
diff --git a/cas/native/1.0/types.hal b/cas/native/1.0/types.hal
new file mode 100644 (file)
index 0000000..d75338b
--- /dev/null
@@ -0,0 +1,88 @@
+/**
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cas.native@1.0;
+
+/**
+ * Enumerates the keys used to scramble the content.
+ */
+enum ScramblingControl : uint32_t {
+    UNSCRAMBLED = 0,
+    RESERVED    = 1,
+    EVENKEY     = 2,
+    ODDKEY      = 3,
+};
+
+/**
+ * A subsample consists of some number of bytes of clear (unscrambled)
+ * data followed by a number of bytes of scrambled data.
+ */
+struct SubSample {
+    uint32_t numBytesOfClearData;
+    uint32_t numBytesOfEncryptedData;
+};
+
+/**
+ * SharedBuffer describes a shared buffer which is defined by a heapBase, an
+ * offset and a size. The offset is relative to the shared memory base for the
+ * memory region identified by heapBase.
+ */
+struct SharedBuffer {
+    /**
+     * The shared memory base handle
+     */
+    memory heapBase;
+
+    /**
+     * The offset from the shared memory base
+     */
+    uint64_t offset;
+
+    /**
+     * The size of the shared buffer in bytes
+     */
+    uint64_t size;
+};
+
+/**
+ * A descrambling destination buffer can be either normal user-space shared
+ * memory for the non-secure descrambling case, or it can be a secure buffer
+ * which is referenced by a native-handle. The native handle is allocated
+ * by the vendor's buffer allocator.
+ */
+enum BufferType : uint32_t {
+    SHARED_MEMORY = 0,
+    NATIVE_HANDLE = 1,
+};
+
+struct DestinationBuffer {
+    /**
+     * The type of the buffer
+     */
+    BufferType type;
+
+    /**
+     * If type == SHARED_MEMORY, the descrambled data must be written
+     * to user-space non-secure shared memory.
+     */
+    SharedBuffer nonsecureMemory;
+
+    /**
+     * If type == NATIVE_HANDLE, the descrambled data must be written
+     * to secure memory referenced by the vendor's buffer allocator.
+     */
+    handle secureMemory;
+};
index 8c715dd..5c81f26 100644 (file)
@@ -57,7 +57,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.broadcastradio</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IBroadcastRadioFactory</name>
             <instance>default</instance>
             <instance>legacy/0</instance>
         </interface>
     </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.cas</name>
+        <version>1.0</version>
+        <interface>
+            <name>IMediaCasService</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="false">
         <name>android.hardware.configstore</name>
         <version>1.0</version>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
-        <name>android.hardware.power</name>
+        <name>android.hardware.oemlock</name>
         <version>1.0</version>
         <interface>
+            <name>IOemLock</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.power</name>
+        <version>1.0-1</version>
+        <interface>
             <name>IPower</name>
             <instance>default</instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.radio</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IRadio</name>
             <instance>slot1</instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
-        <name>android.hardware.thermal</name>
+        <name>android.hardware.tetheroffload.config</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffloadConfig</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tetheroffload.control</name>
         <version>1.0</version>
         <interface>
+            <name>IOffloadControl</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.thermal</name>
+        <version>1.0-1</version>
+        <interface>
             <name>IThermal</name>
             <instance>default</instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.usb</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IUsb</name>
             <instance>default</instance>
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.vibrator</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IVibrator</name>
             <instance>default</instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
-        <name>android.hardware.wifi</name>
+        <name>android.hardware.weaver</name>
         <version>1.0</version>
         <interface>
+            <name>IWeaver</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.wifi</name>
+        <version>1.0-1</version>
+        <interface>
             <name>IWifi</name>
             <instance>default</instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
+        <name>android.hardware.wifi.offload</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffload</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
         <name>android.hardware.wifi.supplicant</name>
         <version>1.0</version>
         <interface>
             <instance>default</instance>
         </interface>
     </hal>
-    <kernel version="4.9.0" />
-    <kernel version="4.4.0" />
-    <kernel version="3.18.0" />
 </compatibility-matrix>
diff --git a/compatibility_matrix.27.xml b/compatibility_matrix.27.xml
new file mode 100644 (file)
index 0000000..5c81f26
--- /dev/null
@@ -0,0 +1,370 @@
+<compatibility-matrix version="1.0" type="framework">
+    <hal format="hidl" optional="false">
+        <name>android.hardware.audio</name>
+        <version>2.0</version>
+        <interface>
+            <name>IDevicesFactory</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.audio.effect</name>
+        <version>2.0</version>
+        <interface>
+            <name>IEffectsFactory</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.automotive.evs</name>
+        <version>1.0</version>
+        <interface>
+            <name>IEvsEnumerator</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.automotive.vehicle</name>
+        <version>2.0</version>
+        <interface>
+            <name>IVehicle</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.biometrics.fingerprint</name>
+        <version>2.1</version>
+        <interface>
+            <name>IBiometricsFingerprint</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.bluetooth</name>
+        <version>1.0</version>
+        <interface>
+            <name>IBluetoothHci</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.boot</name>
+        <version>1.0</version>
+        <interface>
+            <name>IBootControl</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.broadcastradio</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IBroadcastRadioFactory</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.camera.provider</name>
+        <version>2.4</version>
+        <interface>
+            <name>ICameraProvider</name>
+            <instance>legacy/0</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.cas</name>
+        <version>1.0</version>
+        <interface>
+            <name>IMediaCasService</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.configstore</name>
+        <version>1.0</version>
+        <interface>
+            <name>ISurfaceFlingerConfigs</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.contexthub</name>
+        <version>1.0</version>
+        <interface>
+            <name>IContexthub</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.drm</name>
+        <version>1.0</version>
+        <interface>
+            <name>ICryptoFactory</name>
+            <instance>default</instance>
+        </interface>
+        <interface>
+            <name>IDrmFactory</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.dumpstate</name>
+        <version>1.0</version>
+        <interface>
+            <name>IDumpstateDevice</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.gatekeeper</name>
+        <version>1.0</version>
+        <interface>
+            <name>IGatekeeper</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.gnss</name>
+        <version>1.0</version>
+        <interface>
+            <name>IGnss</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.graphics.allocator</name>
+        <version>2.0</version>
+        <interface>
+            <name>IAllocator</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.graphics.composer</name>
+        <version>2.1</version>
+        <interface>
+            <name>IComposer</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.graphics.mapper</name>
+        <version>2.0</version>
+        <interface>
+            <name>IMapper</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.health</name>
+        <version>1.0</version>
+        <interface>
+            <name>IHealth</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.ir</name>
+        <version>1.0</version>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.keymaster</name>
+        <version>3.0</version>
+        <interface>
+            <name>IKeymasterDevice</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.light</name>
+        <version>2.0</version>
+        <interface>
+            <name>ILight</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.media.omx</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOmx</name>
+            <instance>default</instance>
+        </interface>
+        <interface>
+            <name>IOmxStore</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.memtrack</name>
+        <version>1.0</version>
+        <interface>
+            <name>IMemtrack</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.nfc</name>
+        <version>1.0</version>
+        <interface>
+            <name>INfc</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.oemlock</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOemLock</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.power</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IPower</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.radio</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IRadio</name>
+            <instance>slot1</instance>
+        </interface>
+        <interface>
+            <name>ISap</name>
+            <instance>slot1</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.radio.deprecated</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOemHook</name>
+            <instance>slot1</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.renderscript</name>
+        <version>1.0</version>
+        <interface>
+            <name>IDevice</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.sensors</name>
+        <version>1.0</version>
+        <interface>
+            <name>ISensors</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.soundtrigger</name>
+        <version>2.0</version>
+        <interface>
+            <name>ISoundTriggerHw</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tetheroffload.config</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffloadConfig</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tetheroffload.control</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffloadControl</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.thermal</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IThermal</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tv.cec</name>
+        <version>1.0</version>
+        <interface>
+            <name>IHdmiCec</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tv.input</name>
+        <version>1.0</version>
+        <interface>
+            <name>ITvInput</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.usb</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IUsb</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.vibrator</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IVibrator</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.vr</name>
+        <version>1.0</version>
+        <interface>
+            <name>IVr</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.weaver</name>
+        <version>1.0</version>
+        <interface>
+            <name>IWeaver</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.wifi</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IWifi</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.wifi.offload</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffload</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.wifi.supplicant</name>
+        <version>1.0</version>
+        <interface>
+            <name>ISupplicant</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</compatibility-matrix>
index e3c4e15..5c81f26 100644 (file)
@@ -57,7 +57,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.broadcastradio</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IBroadcastRadioFactory</name>
             <instance>default</instance>
             <instance>legacy/0</instance>
         </interface>
     </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.cas</name>
+        <version>1.0</version>
+        <interface>
+            <name>IMediaCasService</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="false">
         <name>android.hardware.configstore</name>
         <version>1.0</version>
     <hal format="hidl" optional="true">
         <name>android.hardware.oemlock</name>
         <version>1.0</version>
+        <interface>
+            <name>IOemLock</name>
+            <instance>default</instance>
+        </interface>
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.power</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IPower</name>
             <instance>default</instance>
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.radio</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IRadio</name>
             <instance>slot1</instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
-        <name>android.hardware.thermal</name>
+        <name>android.hardware.tetheroffload.config</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffloadConfig</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tetheroffload.control</name>
         <version>1.0</version>
         <interface>
+            <name>IOffloadControl</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.thermal</name>
+        <version>1.0-1</version>
+        <interface>
             <name>IThermal</name>
             <instance>default</instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.usb</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IUsb</name>
             <instance>default</instance>
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.vibrator</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IVibrator</name>
             <instance>default</instance>
     <hal format="hidl" optional="true">
         <name>android.hardware.weaver</name>
         <version>1.0</version>
+        <interface>
+            <name>IWeaver</name>
+            <instance>default</instance>
+        </interface>
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.wifi</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IWifi</name>
             <instance>default</instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
+        <name>android.hardware.wifi.offload</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffload</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
         <name>android.hardware.wifi.supplicant</name>
         <version>1.0</version>
         <interface>
             <instance>default</instance>
         </interface>
     </hal>
-    <kernel version="4.9.0" />
-    <kernel version="4.4.0" />
-    <kernel version="3.18.0" />
 </compatibility-matrix>
index 1dbbb05..5655fb9 100644 (file)
@@ -57,7 +57,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.broadcastradio</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IBroadcastRadioFactory</name>
             <instance>default</instance>
             <instance>legacy/0</instance>
         </interface>
     </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.cas</name>
+        <version>1.0</version>
+        <interface>
+            <name>IMediaCasService</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="false">
         <name>android.hardware.configstore</name>
         <version>1.0</version>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
-        <name>android.hardware.power</name>
+        <name>android.hardware.oemlock</name>
         <version>1.0</version>
         <interface>
+            <name>IOemLock</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.power</name>
+        <version>1.0-1</version>
+        <interface>
             <name>IPower</name>
             <instance>default</instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.radio</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IRadio</name>
             <instance>slot1</instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
-        <name>android.hardware.thermal</name>
+        <name>android.hardware.tetheroffload.config</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffloadConfig</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tetheroffload.control</name>
         <version>1.0</version>
         <interface>
+            <name>IOffloadControl</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.thermal</name>
+        <version>1.0-1</version>
+        <interface>
             <name>IThermal</name>
             <instance>default</instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.usb</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IUsb</name>
             <instance>default</instance>
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.vibrator</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IVibrator</name>
             <instance>default</instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
-        <name>android.hardware.wifi</name>
+        <name>android.hardware.weaver</name>
         <version>1.0</version>
         <interface>
+            <name>IWeaver</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.wifi</name>
+        <version>1.0-1</version>
+        <interface>
             <name>IWifi</name>
             <instance>default</instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
+        <name>android.hardware.wifi.offload</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffload</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
         <name>android.hardware.wifi.supplicant</name>
         <version>1.0</version>
         <interface>
             <instance>default</instance>
         </interface>
     </hal>
-    <kernel version="4.9.0" />
-    <kernel version="4.4.0" />
-    <kernel version="3.18.0" />
 </compatibility-matrix>
index 89f99f2..96ef00a 100644 (file)
@@ -39,13 +39,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.configstore@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.configstore@1.0_genc++"],
     generated_headers: ["android.hardware.configstore@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.configstore@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index e017cfd..8b24031 100644 (file)
@@ -3,6 +3,7 @@ LOCAL_PATH := $(call my-dir)
 ################################################################################
 include $(CLEAR_VARS)
 LOCAL_MODULE := android.hardware.configstore@1.0-service
+LOCAL_REQUIRED_MODULES_arm64 := configstore@1.0.policy
 LOCAL_PROPRIETARY_MODULE := true
 LOCAL_MODULE_CLASS := EXECUTABLES
 LOCAL_MODULE_RELATIVE_PATH := hw
@@ -16,7 +17,18 @@ LOCAL_SHARED_LIBRARIES := \
     libhidlbase \
     libhidltransport \
     libbase \
+    libhwminijail \
     liblog \
     libutils \
 
 include $(BUILD_EXECUTABLE)
+
+# seccomp filter for configstore
+ifeq ($(TARGET_ARCH), $(filter $(TARGET_ARCH), arm64))
+include $(CLEAR_VARS)
+LOCAL_MODULE := configstore@1.0.policy
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc/seccomp_policy
+LOCAL_SRC_FILES := seccomp_policy/configstore@1.0-$(TARGET_ARCH).policy
+include $(BUILD_PREBUILT)
+endif
diff --git a/configstore/1.0/default/seccomp_policy/configstore@1.0-arm64.policy b/configstore/1.0/default/seccomp_policy/configstore@1.0-arm64.policy
new file mode 100644 (file)
index 0000000..43bf1fa
--- /dev/null
@@ -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.
+
+futex: 1
+# ioctl: arg1 == BINDER_WRITE_READ
+ioctl: arg1 == 0xc0306201
+# prctl: arg0 == PR_SET_NAME || arg0 == PR_SET_VMA || arg0 == PR_SET_TIMERSLACK
+# || arg0 == PR_GET_NO_NEW_PRIVS # used by crash_dump
+prctl: arg0 == 15 || arg0 == 0x53564d41 || arg0 == 29 || arg0 == 39
+openat: 1
+mmap: 1
+mprotect: 1
+close: 1
+getuid: 1
+read: 1
+faccessat: 1
+write: 1
+fstat: 1
+clone: 1
+munmap: 1
+lseek: 1
+sigaltstack: 1
+writev: 1
+setpriority: 1
+restart_syscall: 1
+exit: 1
+exit_group: 1
+rt_sigreturn: 1
+getrlimit: 1
+madvise: 1
+clock_gettime: 1
+
+# used during process crash by crash_dump to dump process info
+rt_sigprocmask: 1
+rt_sigaction: 1
+# socket: arg0 == AF_LOCAL
+socket: arg0 == 1
+connect: 1
+recvmsg: 1
+rt_tgsigqueueinfo: 1
index 3dca739..c9c81a0 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
 #include <hidl/HidlTransportSupport.h>
+#include <hwminijail/HardwareMinijail.h>
 
 #include "SurfaceFlingerConfigs.h"
 
@@ -25,14 +26,16 @@ using android::hardware::configureRpcThreadpool;
 using android::hardware::joinRpcThreadpool;
 using android::hardware::configstore::V1_0::ISurfaceFlingerConfigs;
 using android::hardware::configstore::V1_0::implementation::SurfaceFlingerConfigs;
+using android::hardware::SetupMinijail;
 using android::sp;
 using android::status_t;
 using android::OK;
 
 int main() {
-    // TODO(b/34857894): tune the max thread count.
     configureRpcThreadpool(10, true);
 
+    SetupMinijail("/vendor/etc/seccomp_policy/configstore@1.0.policy");
+
     sp<ISurfaceFlingerConfigs> surfaceFlingerConfigs = new SurfaceFlingerConfigs;
     status_t status = surfaceFlingerConfigs->registerAsService();
     LOG_ALWAYS_FATAL_IF(status != OK, "Could not register ISurfaceFlingerConfigs");
index 1775538..1b8a591 100644 (file)
 
 cc_test {
     name: "VtsHalConfigstoreV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalConfigstoreV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "libhidlbase",
-        "liblog",
-        "libutils",
-        "android.hardware.configstore@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ]
+    static_libs: ["android.hardware.configstore@1.0"],
 }
 
index a4cad66..93e52f1 100644 (file)
@@ -17,6 +17,9 @@
 cc_library_shared {
     name: "android.hardware.configstore-utils",
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     defaults: ["hidl_defaults"],
 
     srcs: [ "ConfigStoreUtils.cpp" ],
index 45d2e5c..ae1bd08 100644 (file)
@@ -46,13 +46,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.contexthub@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.contexthub@1.0_genc++"],
     generated_headers: ["android.hardware.contexthub@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.contexthub@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index bf45900..3626a09 100644 (file)
@@ -440,18 +440,15 @@ Return<Result> Contexthub::loadNanoApp(uint32_t hubId,
     // Data from the nanoapp header is passed through HIDL as explicit fields,
     // but the legacy HAL expects it prepended to the binary, therefore we must
     // reconstruct it here prior to passing to the legacy HAL.
-    uint32_t targetChreApiVersion =
-        (appBinary.targetChreApiMajorVersion << 24) |
-        (appBinary.targetChreApiMinorVersion << 16);
     const struct nano_app_binary_t header = {
         .header_version = htole32(1),
-        .magic          = htole32(NANOAPP_MAGIC),
-        .app_id.id      = htole64(appBinary.appId),
-        .app_version    = htole32(appBinary.appVersion),
-        .flags          = htole32(appBinary.flags),
-        .hw_hub_type    = htole64(0),
-        .reserved[0]    = htole32(targetChreApiVersion),
-        .reserved[1]    = 0,
+        .magic = htole32(NANOAPP_MAGIC),
+        .app_id.id = htole64(appBinary.appId),
+        .app_version = htole32(appBinary.appVersion),
+        .flags = htole32(appBinary.flags),
+        .hw_hub_type = htole64(0),
+        .target_chre_api_major_version = appBinary.targetChreApiMajorVersion,
+        .target_chre_api_minor_version = appBinary.targetChreApiMinorVersion,
     };
     const uint8_t *headerBytes = reinterpret_cast<const uint8_t *>(&header);
 
index c35386d..7c6e8c7 100644 (file)
 
 cc_test {
     name: "VtsHalContexthubV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalContexthubV1_0TargetTest.cpp"],
-    shared_libs: [
-        "liblog",
-        "libhidlbase",
-        "libhidltransport",
-        "libutils",
-        "android.hardware.contexthub@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ]
+    static_libs: ["android.hardware.contexthub@1.0"],
 }
 
index 2ad1e09..1c67bc0 100644 (file)
@@ -187,13 +187,18 @@ b12ef0bdd8a4d247a8a6e960b227ed32383f2b0241f55d67fcea6eff6a6737fa android.hardwar
 d8f0877ae1d321c1d884c7631dfe36cab0ec8a4b2863d4b687f85d3549a63bcc android.hardware.wifi.supplicant@1.0::ISupplicantStaNetworkCallback
 fe3c3c2f572b72f15f8594c538b0577bd5c28722c31879cfe6231330cddb6747 android.hardware.wifi.supplicant@1.0::types
 
-# ABI preserving changes to HALs released in Android O
+# ABI preserving changes to HALs during Android O MR1 (Initial Set)
 
+26a4dd19a71f3a28249100af29be470f80e08355165fe6a7173aaa1ef264640d android.hardware.automotive.vehicle@2.0::types
+150a338ce11fcec70757c9675d83cf6a5d7b40d0c812741b91671fecce59eac9 android.hardware.broadcastradio@1.0::types
+dc7e6d4f537b9943e27edc4f86c5a03bb643b18f18f866f8c3c71c0ac4ea8cbc android.hardware.broadcastradio@1.0::types
 760485232f6cce07f8bb05e3475509956996b702f77415ee5bff05e2ec5a5bcc android.hardware.dumpstate@1.0::IDumpstateDevice
 e822cb7f4a1bdd45689c5e92ccd19a2201c20b771bd4b2ec1ae627e324591f9d android.hardware.radio@1.0::IRadioResponse
+6e69adb24d7c0b0ca3a54a38c49a5625b161b3f5d5f7d6fda0befdbbfc8e9e06 android.hardware.radio@1.0::IRadioResponse
 28e929b453df3d9f5060af2764e6cdb123ddb893e3e86923c877f6ff7e5f02c9 android.hardware.wifi@1.0::types
+df1d7b27e644bfed0a4f606a8c44d35d45cafce82c7c648494c8a25c7cd4a949 android.hardware.wifi@1.0::types
 
-# HALs released in Android O MR1
+# HALs released in Android O MR1 (Initial Set)
 
 4b65763663a94a3920134011691f8fbb42ccb7b7795589efddc049a9106047d6 android.hardware.oemlock@1.0::IOemLock
 e02cd3722cb5e8fa51179f5defacb4f7866f903c9c7c51dc01a3148473a71525 android.hardware.oemlock@1.0::types
@@ -220,3 +225,31 @@ c3354ab0d381a236c12dc486ad4b6bec28c979d26748b4661f12ede36f392808 android.hardwar
 b18caefefcc765092412285d776234fcf213b73bdf07ae1b67a5f71b2d2464e3 android.hardware.wifi.offload@1.0::types
 c26473e2e4a00af43e28a0ddf9002e5062a7d0940429e5efb6e5513a8abcb75c android.hardware.wifi@1.1::IWifi
 b056e1defab4071584214584057d0bc73a613081bf1152590549649d4582c13c android.hardware.wifi@1.1::IWifiChip
+
+# ABI preserving changes to HALs during Android O MR1 (Final Set)
+05aa3de6130a9788fdb6f4d3cc57c3ea90f067e77a5e09d6a772ec7f6bca33d2 android.hardware.radio@1.1::IRadioResponse
+
+# HALs released in Android O MR1 (Final Set)
+044cb039378b8a0e36f40ff1e6ce04dc0d339da02095f968d5062a051e99d108 android.hardware.broadcastradio@1.1::types
+c9699483f8cefe4f9b39b4b9609b76cab2dd1659a06188056b45797d337d4256 android.hardware.broadcastradio@1.1::IBroadcastRadio
+b5d62dcd663fc4fcc977b252af59b333043bdfe73de2f11fe6d6a8bf438a0f92 android.hardware.broadcastradio@1.1::IBroadcastRadioFactory
+bc7e054a6e93adebedff345aeed44549be89e6b1b6ffe071ff47a61de764b232 android.hardware.broadcastradio@1.1::ITuner
+e9139fc755be578693f17c8cd1e27c75f412cfc722157bab5bf03ee68896e31d android.hardware.broadcastradio@1.1::ITunerCallback
+63929c99e5755d9e09d9e0fd2527391fbb1609dda0508f5933b7943b92ae0fbc android.hardware.camera.device@3.3::types
+bbcfc3f748b078f6a66c4e228084a679d30bd61bfde8bb7a91efd507b91c1bfd android.hardware.camera.device@3.3::ICameraDeviceSession
+4a6998cd6793a3f9f03989c29d662589b1bc9d38826c6698c6c17864f7a814f5 android.hardware.cas@1.0::types
+0e656ba1bac11461a17096ef752b69d24b000d820ef5652f0150a0f9731d54c2 android.hardware.cas@1.0::ICas
+b80e1456b81f80032d0de7cb45652ac15af11e7474d520d757481ecaad796dff android.hardware.cas@1.0::ICasListener
+a432d6d9200248dc2126827bcd6cdea31dd65eff39b939f64585d27d915a5857 android.hardware.cas@1.0::IDescramblerBase
+86ba9c03978b79a742e990420bc5ced0673d25a939f82572996bef92621e2014 android.hardware.cas@1.0::IMediaCasService
+503da837d1a67cbdb7c08a033e927e5430ae1b159d98bf72c6336b4dcc5e76f5 android.hardware.cas.native@1.0::types
+619600109232ed64b827c8a11beed8070b1827ae464547d7aa146cf0473b4bca android.hardware.cas.native@1.0::IDescrambler
+0a159f81359cd4f71bbe00972ee8403ea79351fb7c0cd48be72ebb3e424dbaef android.hardware.radio@1.0::types
+09342041e17c429fce0034b9096d17849122111436a5f0053e7e59500e1cb89c android.hardware.media.omx@1.0::IOmxStore
+246a56d37d57a47224562c9d077b4a2886ce6242b9311bd98a17325944c280d7 android.hardware.neuralnetworks@1.0::types
+93eb3757ceaf21590fa4cd1d4a7dfe3b3794af5396100a6d25630879352abce9 android.hardware.neuralnetworks@1.0::IDevice
+f66f9a38541bf92001d3adcce678cd7e3da2262124befb460b1c9aea9492813b android.hardware.neuralnetworks@1.0::IExecutionCallback
+953607822954435874f4b81686440a604e2a88cdd2d9164c6293f3d5772510d7 android.hardware.neuralnetworks@1.0::IPreparedModel
+73e03573494ba96f0e711ab7f1956c5b2d54c3da690cd7ecf4d6d0f287447730 android.hardware.neuralnetworks@1.0::IPreparedModelCallback
+f4945e397b5dea41bb64518dfde59be71245d8a125fd1e0acffeb57ac7b08fed android.hardware.thermal@1.1::IThermal
+c8bc853546dd55584611def2a9fa1d99f657e3366c976d2f60fe6b8aa6d2cb87 android.hardware.thermal@1.1::IThermalCallback
index 731f58f..d004b82 100644 (file)
@@ -67,13 +67,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.drm@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.drm@1.0_genc++"],
     generated_headers: ["android.hardware.drm@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.drm@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
@@ -89,5 +92,3 @@ cc_library_shared {
         "libutils",
     ],
 }
-
-subdirs = ["default"]
index 0cc6e71..99773be 100644 (file)
@@ -42,6 +42,9 @@ LOCAL_STATIC_LIBRARIES := \
 LOCAL_C_INCLUDES := \
   hardware/interfaces/drm
 
+LOCAL_HEADER_LIBRARIES := \
+  media_plugin_headers
+
 # TODO(b/18948909) Some legacy DRM plugins only support 32-bit. They need to be
 # migrated to 64-bit. Once all of a device's legacy DRM plugins support 64-bit,
 # that device can turn on TARGET_ENABLE_MEDIADRM_64 to build this service as
index 6b1d1ff..86130dc 100644 (file)
@@ -20,7 +20,6 @@
 #include <hidl/Status.h>
 #include <media/hardware/CryptoAPI.h>
 #include <PluginLoader.h>
-#include <media/SharedLibrary.h>
 
 namespace android {
 namespace hardware {
index 591861a..fd75dbd 100644 (file)
@@ -51,7 +51,11 @@ namespace implementation {
 
     Return<void> CryptoPlugin::setSharedBufferBase(const hidl_memory& base,
             uint32_t bufferId) {
-        mSharedBufferMap[bufferId] = mapMemory(base);
+        sp<IMemory> hidlMemory = mapMemory(base);
+        ALOGE_IF(hidlMemory == nullptr, "mapMemory returns nullptr");
+
+        // allow mapMemory to return nullptr
+        mSharedBufferMap[bufferId] = hidlMemory;
         return Void();
     }
 
@@ -107,6 +111,10 @@ namespace implementation {
 
         AString detailMessage;
         sp<IMemory> sourceBase = mSharedBufferMap[source.bufferId];
+        if (sourceBase == nullptr) {
+            _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "source is a nullptr");
+            return Void();
+        }
 
         if (source.offset + offset + source.size > sourceBase->getSize()) {
             _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
@@ -121,6 +129,11 @@ namespace implementation {
         if (destination.type == BufferType::SHARED_MEMORY) {
             const SharedBuffer& destBuffer = destination.nonsecureMemory;
             sp<IMemory> destBase = mSharedBufferMap[destBuffer.bufferId];
+            if (destBase == nullptr) {
+                _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "destination is a nullptr");
+                return Void();
+            }
+
             if (destBuffer.offset + destBuffer.size > destBase->getSize()) {
                 _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
                 return Void();
index 726bf97..32e192d 100644 (file)
@@ -20,7 +20,6 @@
 #include <hidl/Status.h>
 #include <media/drm/DrmAPI.h>
 #include <PluginLoader.h>
-#include <media/SharedLibrary.h>
 
 namespace android {
 namespace hardware {
index b45ce84..57678fb 100644 (file)
 
 cc_test {
     name: "VtsHalDrmV1_0TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: [
         "drm_hal_clearkey_test.cpp",
         "drm_hal_vendor_test.cpp",
         "vendor_modules.cpp"
-        ],
-    shared_libs: [
+    ],
+    static_libs: [
         "android.hardware.drm@1.0",
+        "android.hardware.drm@1.0-helper",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
-        "libbase",
-        "libcutils",
-        "libhidlbase",
         "libhidlmemory",
-        "libhidltransport",
-        "libhwbinder",
-        "liblog",
         "libnativehelper",
         "libssl",
         "libcrypto",
-        "libutils",
-    ],
-    static_libs: [
-        "VtsHalHidlTargetTestBase",
-        "android.hardware.drm@1.0-helper",
-    ],
-    cflags: [
-        "-O0",
-        "-g",
     ],
 }
index 26641e8..4652c76 100644 (file)
@@ -76,10 +76,15 @@ using std::vector;
 #define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
 #define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk())
 
-static const uint8_t kClearKeyUUID[16] = {
+static const uint8_t kCommonPsshBoxUUID[16] = {
     0x10, 0x77, 0xEF, 0xEC, 0xC0, 0xB2, 0x4D, 0x02,
     0xAC, 0xE3, 0x3C, 0x1E, 0x52, 0xE2, 0xFB, 0x4B};
 
+// To be used in mpd to specify drm scheme for players
+static const uint8_t kClearKeyUUID[16] = {
+    0xE2, 0x71, 0x9D, 0x58, 0xA9, 0x85, 0xB3, 0xC9,
+    0x78, 0x1A, 0xB0, 0x30, 0xAF, 0x78, 0xD3, 0x0E};
+
 static const uint8_t kInvalidUUID[16] = {
     0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
     0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80};
@@ -94,10 +99,10 @@ class DrmHalClearkeyFactoryTest : public ::testing::VtsHalHidlTargetTestBase {
 
         drmFactory =
                 ::testing::VtsHalHidlTargetTestBase::getService<IDrmFactory>();
-        ASSERT_NE(drmFactory, nullptr);
+        ASSERT_NE(nullptr, drmFactory.get());
         cryptoFactory =
                 ::testing::VtsHalHidlTargetTestBase::getService<ICryptoFactory>();
-        ASSERT_NE(cryptoFactory, nullptr);
+        ASSERT_NE(nullptr, cryptoFactory.get());
     }
 
     virtual void TearDown() override {}
@@ -108,9 +113,12 @@ class DrmHalClearkeyFactoryTest : public ::testing::VtsHalHidlTargetTestBase {
 };
 
 /**
- * Ensure the factory supports the clearkey scheme UUID
+ * Ensure the factory supports both Common Pssh Box UUID and Clearkey Scheme UUID
  */
 TEST_F(DrmHalClearkeyFactoryTest, ClearKeyPluginSupported) {
+    EXPECT_TRUE(drmFactory->isCryptoSchemeSupported(kCommonPsshBoxUUID));
+    EXPECT_TRUE(cryptoFactory->isCryptoSchemeSupported(kCommonPsshBoxUUID));
+
     EXPECT_TRUE(drmFactory->isCryptoSchemeSupported(kClearKeyUUID));
     EXPECT_TRUE(cryptoFactory->isCryptoSchemeSupported(kClearKeyUUID));
 }
@@ -158,29 +166,57 @@ TEST_F(DrmHalClearkeyFactoryTest, ValidContentTypeSupported) {
 }
 
 /**
- * Ensure clearkey drm plugin can be created
+ * Ensure clearkey drm plugin can be created using Common Pssh Box UUID
+ */
+TEST_F(DrmHalClearkeyFactoryTest, CreateClearKeyDrmPluginUsingCommonPsshBoxUuid) {
+    hidl_string packageName("android.hardware.drm.test");
+    auto res = drmFactory->createPlugin(
+            kCommonPsshBoxUUID, packageName,
+            [&](Status status, const sp<IDrmPlugin>& plugin) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_NE(nullptr, plugin.get());
+            });
+    EXPECT_OK(res);
+}
+
+/**
+ * Ensure clearkey drm plugin can be created using ClearKey UUID
  */
-TEST_F(DrmHalClearkeyFactoryTest, CreateClearKeyDrmPlugin) {
+ TEST_F(DrmHalClearkeyFactoryTest, CreateClearKeyDrmPluginUsingClearKeyUuid) {
     hidl_string packageName("android.hardware.drm.test");
     auto res = drmFactory->createPlugin(
             kClearKeyUUID, packageName,
             [&](Status status, const sp<IDrmPlugin>& plugin) {
                 EXPECT_EQ(Status::OK, status);
-                EXPECT_NE(plugin, nullptr);
+                EXPECT_NE(nullptr, plugin.get());
             });
     EXPECT_OK(res);
 }
 
 /**
- * Ensure clearkey crypto plugin can be created
+ * Ensure clearkey crypto plugin can be created using Common Pssh Box UUID
  */
-TEST_F(DrmHalClearkeyFactoryTest, CreateClearKeyCryptoPlugin) {
+TEST_F(DrmHalClearkeyFactoryTest, CreateClearKeyCryptoPluginUsingCommonPsshBoxUuid) {
+    hidl_vec<uint8_t> initVec;
+    auto res = cryptoFactory->createPlugin(
+            kCommonPsshBoxUUID, initVec,
+            [&](Status status, const sp<ICryptoPlugin>& plugin) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_NE(nullptr, plugin.get());
+            });
+    EXPECT_OK(res);
+}
+
+/**
+ * Ensure clearkey crypto plugin can be created using ClearKey UUID
+ */
+TEST_F(DrmHalClearkeyFactoryTest, CreateClearKeyCryptoPluginUsingClearKeyUuid) {
     hidl_vec<uint8_t> initVec;
     auto res = cryptoFactory->createPlugin(
             kClearKeyUUID, initVec,
             [&](Status status, const sp<ICryptoPlugin>& plugin) {
                 EXPECT_EQ(Status::OK, status);
-                EXPECT_NE(plugin, nullptr);
+                EXPECT_NE(nullptr, plugin.get());
             });
     EXPECT_OK(res);
 }
@@ -194,7 +230,7 @@ TEST_F(DrmHalClearkeyFactoryTest, CreateInvalidDrmPlugin) {
             kInvalidUUID, packageName,
             [&](Status status, const sp<IDrmPlugin>& plugin) {
                 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
-                EXPECT_EQ(plugin, nullptr);
+                EXPECT_EQ(nullptr, plugin.get());
             });
     EXPECT_OK(res);
 }
@@ -208,7 +244,7 @@ TEST_F(DrmHalClearkeyFactoryTest, CreateInvalidCryptoPlugin) {
             kInvalidUUID, initVec,
             [&](Status status, const sp<ICryptoPlugin>& plugin) {
                 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
-                EXPECT_EQ(plugin, nullptr);
+                EXPECT_EQ(nullptr, plugin.get());
             });
     EXPECT_OK(res);
 }
@@ -219,13 +255,13 @@ class DrmHalClearkeyPluginTest : public DrmHalClearkeyFactoryTest {
         // Create factories
         DrmHalClearkeyFactoryTest::SetUp();
 
-        ASSERT_NE(drmFactory, nullptr);
+        ASSERT_NE(nullptr, drmFactory.get());
         hidl_string packageName("android.hardware.drm.test");
         auto res = drmFactory->createPlugin(
                 kClearKeyUUID, packageName,
                 [this](Status status, const sp<IDrmPlugin>& plugin) {
                     EXPECT_EQ(Status::OK, status);
-                    ASSERT_NE(plugin, nullptr);
+                    ASSERT_NE(nullptr, plugin.get());
                     drmPlugin = plugin;
                 });
         ASSERT_OK(res);
@@ -235,7 +271,7 @@ class DrmHalClearkeyPluginTest : public DrmHalClearkeyFactoryTest {
                 kClearKeyUUID, initVec,
                 [this](Status status, const sp<ICryptoPlugin>& plugin) {
                     EXPECT_EQ(Status::OK, status);
-                    ASSERT_NE(plugin, nullptr);
+                    ASSERT_NE(nullptr, plugin.get());
                     cryptoPlugin = plugin;
                 });
         ASSERT_OK(res);
@@ -326,32 +362,29 @@ hidl_vec<uint8_t> DrmHalClearkeyPluginTest::loadKeys(
         // 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,
+        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,
+        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};
 
     hidl_vec<uint8_t> expectedKeyRequest = {
-        0x7b, 0x22, 0x6b, 0x69, 0x64, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x59,
-        0x41, 0x59, 0x65, 0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2b,
-        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};
+        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};
 
     hidl_vec<uint8_t> 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, 0x2b, 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, 0x0a};
+        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, 0x0a};
 
     hidl_string mimeType = "video/mp4";
     KeyedVector optionalParameters;
@@ -866,7 +899,7 @@ TEST_F(DrmHalClearkeyPluginTest, NotifyResolution) {
 sp<IMemory> DrmHalClearkeyPluginTest::getDecryptMemory(size_t size,
                                                        size_t index) {
     sp<IAllocator> ashmemAllocator = IAllocator::getService("ashmem");
-    EXPECT_NE(ashmemAllocator, nullptr);
+    EXPECT_NE(nullptr, ashmemAllocator.get());
 
     hidl_memory hidlMemory;
     auto res = ashmemAllocator->allocate(
@@ -878,6 +911,7 @@ sp<IMemory> DrmHalClearkeyPluginTest::getDecryptMemory(size_t size,
     EXPECT_OK(res);
 
     sp<IMemory> mappedMemory = mapMemory(hidlMemory);
+    EXPECT_NE(nullptr, mappedMemory.get());
     EXPECT_OK(cryptoPlugin->setSharedBufferBase(hidlMemory, index));
     return mappedMemory;
 }
@@ -1063,8 +1097,6 @@ void DrmHalClearkeyDecryptTest::aes_cbc_decrypt(uint8_t* dest, uint8_t* src,
     AES_set_encrypt_key(&key[0], 128, &decryptionKey);
 
     size_t offset = 0;
-    size_t num = 0;
-    size_t ecount_buf = 0;
     for (size_t i = 0; i < subSamples.size(); i++) {
         memcpy(dest + offset, src + offset, subSamples[i].numBytesOfClearData);
         offset += subSamples[i].numBytesOfClearData;
@@ -1080,12 +1112,11 @@ void DrmHalClearkeyDecryptTest::aes_cbc_decrypt(uint8_t* dest, uint8_t* src,
  */
 TEST_F(DrmHalClearkeyDecryptTest, TestQueryKeyStatus) {
     auto sessionId = openSession();
-    auto res = drmPlugin->queryKeyStatus(sessionId,
-            [&](Status status, KeyedVector /* info */) {
-                // clearkey doesn't support this method
-                EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
-            });
+    auto res = drmPlugin->queryKeyStatus(
+        sessionId, [&](Status status, KeyedVector /* info */) { EXPECT_EQ(Status::OK, status); });
     EXPECT_OK(res);
+
+    closeSession(sessionId);
 }
 
 
@@ -1105,7 +1136,6 @@ TEST_F(DrmHalClearkeyDecryptTest, ClearSegmentTest) {
     Status status = cryptoPlugin->setMediaDrmSession(sessionId);
     EXPECT_EQ(Status::OK, status);
 
-    const bool kNotSecure = false;
     uint32_t byteCount = decrypt(Mode::UNENCRYPTED, &iv[0], subSamples,
             noPattern, Status::OK);
     EXPECT_EQ(kByteCount, byteCount);
@@ -1132,7 +1162,6 @@ TEST_F(DrmHalClearkeyDecryptTest, EncryptedAesCtrSegmentTest) {
     Status status = cryptoPlugin->setMediaDrmSession(sessionId);
     EXPECT_EQ(Status::OK, status);
 
-    const bool kNotSecure = false;
     uint32_t byteCount = decrypt(Mode::AES_CTR, &iv[0], subSamples,
             noPattern, Status::OK);
     EXPECT_EQ(kClearBytes + kEncryptedBytes, byteCount);
@@ -1153,7 +1182,6 @@ TEST_F(DrmHalClearkeyDecryptTest, EncryptedAesCtrSegmentTestNoKeys) {
     Status status = cryptoPlugin->setMediaDrmSession(sessionId);
     EXPECT_EQ(Status::OK, status);
 
-    const bool kNotSecure = false;
     uint32_t byteCount = decrypt(Mode::AES_CTR, &iv[0], subSamples,
             noPattern, Status::ERROR_DRM_NO_LICENSE);
     EXPECT_EQ(0u, byteCount);
index e651e19..47c6950 100644 (file)
@@ -113,7 +113,7 @@ class DrmHalVendorFactoryTest : public testing::TestWithParam<std::string> {
               test_info->test_case_name(), test_info->name(),
               GetParam().c_str());
 
-        ASSERT_NE(vendorModule, nullptr);
+        ASSERT_NE(nullptr, vendorModule.get());
 
         // First try the binderized service name provided by the vendor module.
         // If that fails, which it can on non-binderized devices, try the default
@@ -123,14 +123,14 @@ class DrmHalVendorFactoryTest : public testing::TestWithParam<std::string> {
         if (drmFactory == nullptr) {
             drmFactory = VtsTestBase::getService<IDrmFactory>();
         }
-        ASSERT_NE(drmFactory, nullptr);
+        ASSERT_NE(nullptr, drmFactory.get());
 
         // Do the same for the crypto factory
         cryptoFactory = VtsTestBase::getService<ICryptoFactory>(name);
         if (cryptoFactory == nullptr) {
             cryptoFactory = VtsTestBase::getService<ICryptoFactory>();
         }
-        ASSERT_NE(cryptoFactory, nullptr);
+        ASSERT_NE(nullptr, cryptoFactory.get());
 
         // If drm scheme not installed skip subsequent tests
         if (!drmFactory->isCryptoSchemeSupported(getVendorUUID())) {
@@ -239,7 +239,7 @@ TEST_P(DrmHalVendorFactoryTest, CreateVendorDrmPlugin) {
             getVendorUUID(), packageName,
             [&](Status status, const sp<IDrmPlugin>& plugin) {
                 EXPECT_EQ(Status::OK, status);
-                EXPECT_NE(plugin, nullptr);
+                EXPECT_NE(nullptr, plugin.get());
             });
     EXPECT_OK(res);
 }
@@ -254,7 +254,7 @@ TEST_P(DrmHalVendorFactoryTest, CreateVendorCryptoPlugin) {
             getVendorUUID(), initVec,
             [&](Status status, const sp<ICryptoPlugin>& plugin) {
                 EXPECT_EQ(Status::OK, status);
-                EXPECT_NE(plugin, nullptr);
+                EXPECT_NE(nullptr, plugin.get());
             });
     EXPECT_OK(res);
 }
@@ -269,7 +269,7 @@ TEST_P(DrmHalVendorFactoryTest, CreateInvalidDrmPlugin) {
             kInvalidUUID, packageName,
             [&](Status status, const sp<IDrmPlugin>& plugin) {
                 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
-                EXPECT_EQ(plugin, nullptr);
+                EXPECT_EQ(nullptr, plugin.get());
             });
     EXPECT_OK(res);
 }
@@ -284,7 +284,7 @@ TEST_P(DrmHalVendorFactoryTest, CreateInvalidCryptoPlugin) {
             kInvalidUUID, initVec,
             [&](Status status, const sp<ICryptoPlugin>& plugin) {
                 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
-                EXPECT_EQ(plugin, nullptr);
+                EXPECT_EQ(nullptr, plugin.get());
             });
     EXPECT_OK(res);
 }
@@ -302,7 +302,7 @@ class DrmHalVendorPluginTest : public DrmHalVendorFactoryTest {
                 getVendorUUID(), packageName,
                 [this](Status status, const sp<IDrmPlugin>& plugin) {
                     EXPECT_EQ(Status::OK, status);
-                    ASSERT_NE(plugin, nullptr);
+                    ASSERT_NE(nullptr, plugin.get());
                     drmPlugin = plugin;
                 });
         ASSERT_OK(res);
@@ -312,7 +312,7 @@ class DrmHalVendorPluginTest : public DrmHalVendorFactoryTest {
                 getVendorUUID(), initVec,
                 [this](Status status, const sp<ICryptoPlugin>& plugin) {
                     EXPECT_EQ(Status::OK, status);
-                    ASSERT_NE(plugin, nullptr);
+                    ASSERT_NE(nullptr, plugin.get());
                     cryptoPlugin = plugin;
                 });
         ASSERT_OK(res);
@@ -1185,7 +1185,7 @@ TEST_P(DrmHalVendorPluginTest, NotifyResolution) {
 sp<IMemory> DrmHalVendorPluginTest::getDecryptMemory(size_t size,
                                                      size_t index) {
     sp<IAllocator> ashmemAllocator = IAllocator::getService("ashmem");
-    EXPECT_NE(ashmemAllocator, nullptr);
+    EXPECT_NE(nullptr, ashmemAllocator.get());
 
     hidl_memory hidlMemory;
     auto res = ashmemAllocator->allocate(
@@ -1198,7 +1198,7 @@ sp<IMemory> DrmHalVendorPluginTest::getDecryptMemory(size_t size,
     EXPECT_OK(res);
 
     sp<IMemory> mappedMemory = mapMemory(hidlMemory);
-    EXPECT_NE(mappedMemory, nullptr);
+    EXPECT_NE(nullptr, mappedMemory.get());
     res = cryptoPlugin->setSharedBufferBase(hidlMemory, index);
     EXPECT_OK(res);
     return mappedMemory;
@@ -1406,8 +1406,6 @@ void DrmHalVendorDecryptTest::aes_cbc_decrypt(uint8_t* dest, uint8_t* src,
     AES_set_encrypt_key(&key[0], 128, &decryptionKey);
 
     size_t offset = 0;
-    size_t num = 0;
-    size_t ecount_buf = 0;
     for (size_t i = 0; i < subSamples.size(); i++) {
         const SubSample& subSample = subSamples[i];
 
index 33f70eb..ed19a37 100644 (file)
@@ -1,5 +1,6 @@
 // This is an autogenerated file, do not edit.
 subdirs = [
     "1.0",
+    "1.0/default",
     "1.0/vts/functional",
 ]
index 2424c33..b135e00 100644 (file)
@@ -35,13 +35,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.dumpstate@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.dumpstate@1.0_genc++"],
     generated_headers: ["android.hardware.dumpstate@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.dumpstate@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index a1c735b..1ab530f 100644 (file)
 
 cc_test {
     name: "VtsHalDumpstateV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalDumpstateV1_0TargetTest.cpp"],
-    shared_libs: [
-        "android.hardware.dumpstate@1.0",
-        "libcutils",
-        "libhidlbase",
-        "liblog",
-        "libutils",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ]
+    static_libs: ["android.hardware.dumpstate@1.0"],
 }
index eb70c09..f12f38f 100644 (file)
@@ -39,13 +39,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.gatekeeper@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.gatekeeper@1.0_genc++"],
     generated_headers: ["android.hardware.gatekeeper@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.gatekeeper@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index 70cb615..aa1da7b 100644 (file)
 
 cc_test {
     name: "VtsHalGatekeeperV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalGatekeeperV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
-        "android.hardware.gatekeeper@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ]
+    static_libs: ["android.hardware.gatekeeper@1.0"],
 }
index c2988de..6db98f6 100644 (file)
@@ -172,13 +172,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.gnss@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.gnss@1.0_genc++"],
     generated_headers: ["android.hardware.gnss@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.gnss@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index 6c9b838..d81f829 100644 (file)
@@ -182,7 +182,6 @@ void GnssMeasurement::gpsMeasurementCb(GpsData* gpsData) {
 
     auto clockVal = gpsData->clock;
     static uint32_t discontinuity_count_to_handle_old_clock_type = 0;
-    auto flags = clockVal.flags;
 
     gnssData.clock.leapSecond = clockVal.leap_second;
     /*
@@ -205,7 +204,7 @@ void GnssMeasurement::gpsMeasurementCb(GpsData* gpsData) {
             break;
         case GPS_CLOCK_TYPE_GPS_TIME:
             // GPS time, need to convert.
-            flags |= GPS_CLOCK_HAS_FULL_BIAS;
+            clockVal.flags |= GPS_CLOCK_HAS_FULL_BIAS;
             clockVal.full_bias_ns = clockVal.time_ns;
             clockVal.time_ns = 0;
             gnssData.clock.hwClockDiscontinuityCount =
diff --git a/gnss/1.0/default/OWNERS b/gnss/1.0/default/OWNERS
new file mode 100644 (file)
index 0000000..6c25bd7
--- /dev/null
@@ -0,0 +1,3 @@
+wyattriley@google.com
+gomo@google.com
+smalkos@google.com
diff --git a/gnss/1.0/vts/OWNERS b/gnss/1.0/vts/OWNERS
new file mode 100644 (file)
index 0000000..937d70a
--- /dev/null
@@ -0,0 +1,7 @@
+wyattriley@google.com
+gomo@google.com
+smalkos@google.com
+
+# VTS team
+yim@google.com
+trong@google.com
\ No newline at end of file
index 6d96059..d7713db 100644 (file)
 
 cc_test {
     name: "VtsHalGnssV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalGnssV1_0TargetTest.cpp"],
-    shared_libs: [
-        "android.hardware.gnss@1.0",
-        "libbase",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "liblog",
-        "libnativehelper",
-        "libutils",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
-}
\ No newline at end of file
+    static_libs: ["android.hardware.gnss@1.0"],
+}
index 2c2a3da..46faa17 100644 (file)
@@ -35,13 +35,17 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.graphics.allocator@2.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.graphics.allocator@2.0_genc++"],
     generated_headers: ["android.hardware.graphics.allocator@2.0_genc++_headers"],
     export_generated_headers: ["android.hardware.graphics.allocator@2.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+        support_system_process: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index 4773963..2d36fc7 100644 (file)
@@ -42,13 +42,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.graphics.bufferqueue@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.graphics.bufferqueue@1.0_genc++"],
     generated_headers: ["android.hardware.graphics.bufferqueue@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.graphics.bufferqueue@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index 3d9aa90..86438c1 100644 (file)
@@ -32,13 +32,17 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.graphics.common@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.graphics.common@1.0_genc++"],
     generated_headers: ["android.hardware.graphics.common@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.graphics.common@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+        support_system_process: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index 299570d..e875708 100644 (file)
@@ -53,13 +53,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.graphics.composer@2.1",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.graphics.composer@2.1_genc++"],
     generated_headers: ["android.hardware.graphics.composer@2.1_genc++_headers"],
     export_generated_headers: ["android.hardware.graphics.composer@2.1_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index 8ca0eb3..862dff1 100644 (file)
@@ -18,6 +18,7 @@
 
 #include "Hwc.h"
 
+#include <chrono>
 #include <type_traits>
 #include <log/log.h>
 
@@ -25,6 +26,8 @@
 #include "hardware/hwcomposer.h"
 #include "hwc2on1adapter/HWC2On1Adapter.h"
 
+using namespace std::chrono_literals;
+
 namespace android {
 namespace hardware {
 namespace graphics {
@@ -218,7 +221,24 @@ Return<void> HwcHal::createClient(createClient_cb hidl_cb)
     sp<ComposerClient> client;
 
     {
-        std::lock_guard<std::mutex> lock(mClientMutex);
+        std::unique_lock<std::mutex> lock(mClientMutex);
+
+        if (mClient != nullptr) {
+            // In surface flinger we delete a composer client on one thread and
+            // then create a new client on another thread. Although surface
+            // flinger ensures the calls are made in that sequence (destroy and
+            // then create), sometimes the calls land in the composer service
+            // inverted (create and then destroy). Wait for a brief period to
+            // see if the existing client is destroyed.
+            ALOGI("HwcHal::createClient: Client already exists. Waiting for"
+                    " it to be destroyed.");
+            mClientDestroyedWait.wait_for(lock, 1s,
+                    [this] { return mClient == nullptr; });
+            std::string doneMsg = mClient == nullptr ?
+                    "Existing client was destroyed." :
+                    "Existing client was never destroyed!";
+            ALOGI("HwcHal::createClient: Done waiting. %s", doneMsg.c_str());
+        }
 
         // only one client is allowed
         if (mClient == nullptr) {
@@ -245,6 +265,7 @@ void HwcHal::removeClient()
 {
     std::lock_guard<std::mutex> lock(mClientMutex);
     mClient = nullptr;
+    mClientDestroyedWait.notify_all();
 }
 
 void HwcHal::hotplugHook(hwc2_callback_data_t callbackData,
index b45389a..7561327 100644 (file)
@@ -17,8 +17,9 @@
 #ifndef ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_H
 #define ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_H
 
-#include <mutex>
+#include <condition_variable>
 #include <memory>
+#include <mutex>
 #include <unordered_set>
 #include <vector>
 
@@ -211,6 +212,7 @@ private:
     } mDispatch;
 
     std::mutex mClientMutex;
+    std::condition_variable mClientDestroyedWait;
     wp<ComposerClient> mClient;
 
     // If the HWC implementation version is < 2.0, use an adapter to interface
index 9ee5f4f..058709c 100644 (file)
@@ -92,6 +92,23 @@ public:
     bool writeQueue(bool* outQueueChanged, uint32_t* outCommandLength,
             hidl_vec<hidl_handle>* outCommandHandles)
     {
+        // After data are written to the queue, it may not be read by the
+        // remote reader when
+        //
+        //  - the writer does not send them (because of other errors)
+        //  - the hwbinder transaction fails
+        //  - the reader does not read them (because of other errors)
+        //
+        // Discard the stale data here.
+        size_t staleDataSize = mQueue ? mQueue->availableToRead() : 0;
+        if (staleDataSize > 0) {
+            ALOGW("discarding stale data from message queue");
+            CommandQueueType::MemTransaction tx;
+            if (mQueue->beginRead(staleDataSize, &tx)) {
+                mQueue->commitRead(staleDataSize);
+            }
+        }
+
         // write data to queue, optionally resizing it
         if (mQueue && (mDataMaxSize <= mQueue->getQuantumCount())) {
             if (!mQueue->write(mData.get(), mDataWritten)) {
index 2e87144..1ba7c9a 100644 (file)
@@ -44,33 +44,21 @@ cc_library_static {
 
 cc_test {
     name: "VtsHalGraphicsComposerV2_1TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalGraphicsComposerV2_1TargetTest.cpp"],
+
+    // TODO(b/64437680): Assume these libs are always available on the device.
     shared_libs: [
-        "android.hardware.graphics.allocator@2.0",
-        "android.hardware.graphics.composer@2.1",
-        "android.hardware.graphics.mapper@2.0",
-        "libbase",
-        "libcutils",
         "libfmq",
-        "libhidlbase",
-        "libhidltransport",
-        "liblog",
-        "libnativehelper",
         "libsync",
-        "libutils",
     ],
     static_libs: [
-        "libhwcomposer-command-buffer",
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.composer@2.1",
+        "android.hardware.graphics.mapper@2.0",
         "libVtsHalGraphicsComposerTestUtils",
         "libVtsHalGraphicsMapperTestUtils",
-        "VtsHalHidlTargetTestBase",
+        "libhwcomposer-command-buffer",
+        "libnativehelper",
     ],
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Werror",
-        "-O0",
-        "-g",
-    ]
 }
index 0f03546..9a749d7 100644 (file)
@@ -23,6 +23,7 @@
 #include "VtsHalGraphicsMapperTestUtils.h"
 
 #include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
 #include <unistd.h>
 
 #include <algorithm>
@@ -50,21 +51,40 @@ using android::hardware::graphics::mapper::V2_0::IMapper;
 using android::hardware::graphics::mapper::V2_0::tests::Gralloc;
 using GrallocError = android::hardware::graphics::mapper::V2_0::Error;
 
+// 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<IComposer>(); }
+
+   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<Composer>());
-    ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient());
+      ASSERT_NO_FATAL_FAILURE(
+          mComposer = std::make_unique<Composer>(
+              GraphicsComposerHidlEnvironment::Instance()->getServiceName<IComposer>()));
+      ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient());
 
-    mComposerCallback = new GraphicsComposerCallback;
-    mComposerClient->registerCallback(mComposerCallback);
+      mComposerCallback = new GraphicsComposerCallback;
+      mComposerClient->registerCallback(mComposerCallback);
 
-    // assume the first display is primary and is never removed
-    mPrimaryDisplay = waitForFirstDisplay();
+      // assume the first display is primary and is never removed
+      mPrimaryDisplay = waitForFirstDisplay();
 
-    // explicitly disable vsync
-    mComposerClient->setVsyncEnabled(mPrimaryDisplay, false);
-    mComposerCallback->setVsyncAllowed(false);
+      // explicitly disable vsync
+      mComposerClient->setVsyncEnabled(mPrimaryDisplay, false);
+      mComposerCallback->setVsyncAllowed(false);
   }
 
   void TearDown() override {
@@ -684,10 +704,11 @@ TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_Z_ORDER) {
 }  // namespace android
 
 int main(int argc, char** argv) {
-  ::testing::InitGoogleTest(&argc, argv);
-
-  int status = RUN_ALL_TESTS();
-  LOG(INFO) << "Test result = " << status;
-
-  return status;
+    using android::hardware::graphics::composer::V2_1::tests::GraphicsComposerHidlEnvironment;
+    ::testing::AddGlobalTestEnvironment(GraphicsComposerHidlEnvironment::Instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    GraphicsComposerHidlEnvironment::Instance()->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    ALOGI("Test result = %d", status);
+    return status;
 }
index 408d58f..f5913af 100644 (file)
@@ -39,13 +39,17 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.graphics.mapper@2.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.graphics.mapper@2.0_genc++"],
     generated_headers: ["android.hardware.graphics.mapper@2.0_genc++_headers"],
     export_generated_headers: ["android.hardware.graphics.mapper@2.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+        support_system_process: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index 1c0e4c5..ac6cb47 100644 (file)
@@ -37,30 +37,16 @@ cc_library_static {
 
 cc_test {
     name: "VtsHalGraphicsMapperV2_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalGraphicsMapperV2_0TargetTest.cpp"],
     shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
         "libsync",
-        "libutils",
+    ],
+    static_libs: [
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.mapper@2.0",
         "android.hardware.graphics.common@1.0",
-    ],
-    static_libs: [
         "libVtsHalGraphicsMapperTestUtils",
-        "VtsHalHidlTargetTestBase",
+        "libnativehelper",
     ],
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Werror",
-        "-O0",
-        "-g",
-    ]
 }
index 4fb2d7b..d8ebc20 100644 (file)
@@ -39,13 +39,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.health@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.health@1.0_genc++"],
     generated_headers: ["android.hardware.health@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.health@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/health/1.0/default/Android.bp b/health/1.0/default/Android.bp
new file mode 100644 (file)
index 0000000..cb2e87d
--- /dev/null
@@ -0,0 +1,20 @@
+cc_library_static {
+    name: "android.hardware.health@1.0-convert",
+    vendor_available: true,
+    srcs: ["convert.cpp"],
+    include_dirs: [
+        "system/core/base/include",
+    ],
+    header_libs: ["libhealthd_headers"],
+    export_header_lib_headers: ["libhealthd_headers"],
+    export_include_dirs: ["include"],
+    shared_libs: [
+        "libcutils",
+        "libhidlbase",
+        "libhidltransport",
+        "libutils",
+        "android.hardware.health@1.0",
+    ],
+
+}
+
index 96ff91f..199ab41 100644 (file)
@@ -4,10 +4,12 @@ include $(CLEAR_VARS)
 LOCAL_MODULE := android.hardware.health@1.0-impl
 LOCAL_PROPRIETARY_MODULE := true
 LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_C_INCLUDES := system/core/healthd/include system/core/base/include
+LOCAL_C_INCLUDES := system/core/base/include
 LOCAL_SRC_FILES := \
     Health.cpp \
 
+LOCAL_HEADER_LIBRARIES := libhealthd_headers
+
 LOCAL_SHARED_LIBRARIES := \
     libcutils \
     libhidlbase \
@@ -23,20 +25,6 @@ LOCAL_HAL_STATIC_LIBRARIES := libhealthd
 include $(BUILD_SHARED_LIBRARY)
 
 include $(CLEAR_VARS)
-LOCAL_MODULE := android.hardware.health@1.0-convert
-LOCAL_SRC_FILES := convert.cpp
-LOCAL_C_INCLUDES := system/core/healthd/include system/core/base/include
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_SHARED_LIBRARIES := \
-    libcutils \
-    libhidlbase \
-    libhidltransport \
-    libutils \
-    android.hardware.health@1.0 \
-
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
 LOCAL_PROPRIETARY_MODULE := true
 LOCAL_MODULE_RELATIVE_PATH := hw
 LOCAL_MODULE := android.hardware.health@1.0-service
diff --git a/health/1.0/default/libhealthd/Android.bp b/health/1.0/default/libhealthd/Android.bp
new file mode 100644 (file)
index 0000000..ce02e28
--- /dev/null
@@ -0,0 +1,10 @@
+// Copyright 2016 The Android Open Source Project
+
+cc_library_static {
+    srcs: ["healthd_board_default.cpp"],
+    name: "libhealthd.default",
+    vendor_available: true,
+    cflags: ["-Werror"],
+    include_dirs: ["system/core/base/include"],
+    header_libs: ["libhealthd_headers"],
+}
diff --git a/health/1.0/default/libhealthd/Android.mk b/health/1.0/default/libhealthd/Android.mk
deleted file mode 100644 (file)
index a5f4445..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright 2016 The Android Open Source Project
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := healthd_board_default.cpp
-LOCAL_MODULE := libhealthd.default
-LOCAL_CFLAGS := -Werror
-LOCAL_C_INCLUDES := system/core/healthd/include system/core/base/include
-include $(BUILD_STATIC_LIBRARY)
index 1a4c8c8..8742651 100644 (file)
 
 cc_test {
     name: "VtsHalHealthV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalHealthV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libhidlbase",
-        "liblog",
-        "libutils",
-        "android.hardware.health@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ]
+    static_libs: ["android.hardware.health@1.0"],
 }
index 33f70eb..a6f6017 100644 (file)
@@ -1,5 +1,7 @@
 // This is an autogenerated file, do not edit.
 subdirs = [
     "1.0",
+    "1.0/default",
+    "1.0/default/libhealthd",
     "1.0/vts/functional",
 ]
index a059da5..489f61f 100644 (file)
@@ -39,13 +39,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.ir@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.ir@1.0_genc++"],
     generated_headers: ["android.hardware.ir@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.ir@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index 4aac297..2a86f8e 100644 (file)
 
 cc_test {
     name: "VtsHalIrV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalIrV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libutils",
+    static_libs: [
         "android.hardware.ir@1.0",
     ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
 }
index 1846200..14cfab2 100644 (file)
@@ -39,13 +39,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.keymaster@3.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.keymaster@3.0_genc++"],
     generated_headers: ["android.hardware.keymaster@3.0_genc++_headers"],
     export_generated_headers: ["android.hardware.keymaster@3.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/keymaster/3.0/vts/functional/Android.bp b/keymaster/3.0/vts/functional/Android.bp
new file mode 100644 (file)
index 0000000..7d96704
--- /dev/null
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+    name: "VtsHalKeymasterV3_0TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "authorization_set.cpp",
+        "attestation_record.cpp",
+        "key_param_output.cpp",
+        "keymaster_hidl_hal_test.cpp",
+        "keystore_tags_utils.cpp",
+    ],
+    static_libs: [
+        "android.hardware.keymaster@3.0",
+        "libcrypto",
+        "libsoftkeymasterdevice",
+    ],
+}
diff --git a/keymaster/3.0/vts/functional/Android.mk b/keymaster/3.0/vts/functional/Android.mk
deleted file mode 100644 (file)
index 4098664..0000000
+++ /dev/null
@@ -1,39 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := VtsHalKeymasterV3_0TargetTest
-LOCAL_SRC_FILES := \
-        authorization_set.cpp \
-        attestation_record.cpp \
-        key_param_output.cpp \
-        keymaster_hidl_hal_test.cpp \
-        keystore_tags_utils.cpp \
-
-LOCAL_SHARED_LIBRARIES := \
-        android.hardware.keymaster@3.0 \
-        libcrypto \
-        libhidlbase \
-        liblog \
-        libsoftkeymasterdevice \
-        libutils \
-
-LOCAL_STATIC_LIBRARIES := \
-        VtsHalHidlTargetTestBase \
-
-LOCAL_CFLAGS := -Wall -Werror
-
-include $(BUILD_NATIVE_TEST)
index 09b8cb2..90a0195 100644 (file)
@@ -1,4 +1,5 @@
 // This is an autogenerated file, do not edit.
 subdirs = [
     "3.0",
+    "3.0/vts/functional",
 ]
index cffdbe0..7cc7f84 100644 (file)
@@ -39,13 +39,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.light@2.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.light@2.0_genc++"],
     generated_headers: ["android.hardware.light@2.0_genc++_headers"],
     export_generated_headers: ["android.hardware.light@2.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index 0558ff2..e0ec4cf 100644 (file)
 
 cc_test {
     name: "VtsHalLightV2_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalLightV2_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "libhidlbase",
-        "liblog",
-        "libutils",
-        "android.hardware.light@2.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ]
+    static_libs: ["android.hardware.light@2.0"],
 }
 
index 61eeb3f..de2187e 100644 (file)
@@ -32,13 +32,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.media@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.media@1.0_genc++"],
     generated_headers: ["android.hardware.media@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.media@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index 8e5527e..f8bed6e 100644 (file)
@@ -74,13 +74,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.media.omx@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.media.omx@1.0_genc++"],
     generated_headers: ["android.hardware.media.omx@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.media.omx@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index a224b0e..3ec0535 100644 (file)
@@ -39,7 +39,7 @@ interface IOmxStore {
      *   string:                arbitrary string
      *   size:                  <num>x<num>
      *   ratio:                 <num>:<num>
-     *   range<type>:           <type>-<type>
+     *   range<type>:           <type> | <type>-<type>
      *   list<type>:            <type> | <type>,<list<type>>
      */
     struct Attribute {
@@ -97,7 +97,7 @@ interface IOmxStore {
      *
      * Required node attributes for video nodes that are required by Android to
      * describe measured values for this device:
-     *   key: 'measured-frame-rate-<width>-<height>-range',
+     *   key: 'measured-frame-rate-<width>x<height>-range',
      *     value-type: range<num>; where width: num, height: num
      *
      * Optional node attributes for decoders to describe supported values:
@@ -111,7 +111,7 @@ interface IOmxStore {
      * Optional node attributes for encoders to describe supported values:
      *   key: 'complexity-default', value-type: num
      *   key: 'complexity-range', value-type: range<num>
-     *   key: 'feature-bitrate-control', value-type: list<enum<VBR,CBR,CQ>>
+     *   key: 'feature-bitrate-modes', value-type: list<enum<VBR,CBR,CQ>>
      *   key: 'feature-intra-refresh', value-type: enum<0,1>
      *   key: 'quality-default', value-type: num
      *   key: 'quality-range', value-type: range<num>
index 66fd20b..f517fa1 100644 (file)
 
 cc_test {
     name: "VtsHalMediaOmxV1_0TargetAudioEncTest",
-    defaults: ["hidl_defaults"],
-    srcs: ["VtsHalMediaOmxV1_0TargetAudioEncTest.cpp",
-           "media_audio_hidl_test_common.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidlmemory",
-        "libhidltransport",
-        "libhwbinder",
-        "libnativehelper",
-        "libutils",
-        "libstagefright_foundation",
-        "android.hidl.allocator@1.0",
-        "android.hidl.memory@1.0",
-        "android.hardware.media.omx@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase",
-                  "VtsHalMediaOmxV1_0CommonUtil"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
-    include_dirs: [
-        "frameworks/native/include/media/openmax/",
-        "hardware/interfaces/media/omx/1.0/vts/functional/common",
+    defaults: ["VtsHalMediaOmxV1_0Defaults"],
+    srcs: [
+        "VtsHalMediaOmxV1_0TargetAudioEncTest.cpp",
+        "media_audio_hidl_test_common.cpp"
     ],
 }
 
 cc_test {
     name: "VtsHalMediaOmxV1_0TargetAudioDecTest",
-    defaults: ["hidl_defaults"],
-    srcs: ["VtsHalMediaOmxV1_0TargetAudioDecTest.cpp",
-           "media_audio_hidl_test_common.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidlmemory",
-        "libhidltransport",
-        "libhwbinder",
-        "libnativehelper",
-        "libutils",
-        "libstagefright_foundation",
-        "android.hidl.allocator@1.0",
-        "android.hidl.memory@1.0",
-        "android.hardware.media.omx@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase",
-                  "VtsHalMediaOmxV1_0CommonUtil"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
-    include_dirs: [
-        "frameworks/native/include/media/openmax/",
-        "hardware/interfaces/media/omx/1.0/vts/functional/common",
+    defaults: ["VtsHalMediaOmxV1_0Defaults"],
+    srcs: [
+        "VtsHalMediaOmxV1_0TargetAudioDecTest.cpp",
+        "media_audio_hidl_test_common.cpp"
     ],
 }
 
index 1aae7bc..9e185f2 100644 (file)
  */
 
 #define LOG_TAG "media_omx_hidl_audio_dec_test"
+#ifdef __LP64__
+#define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
+#endif
+
 #include <android-base/logging.h>
 
 #include <android/hardware/media/omx/1.0/IOmx.h>
@@ -161,6 +165,7 @@ class AudioDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
                                this->omxNode = _nl;
                            })
                         .isOk());
+        ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
         ASSERT_NE(omxNode, nullptr);
         ASSERT_NE(gEnv->getRole().empty(), true) << "Invalid Component Role";
         struct StringToName {
@@ -171,7 +176,7 @@ class AudioDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
             {"mp3", mp3}, {"amrnb", amrnb},       {"amrwb", amrwb},
             {"aac", aac}, {"vorbis", vorbis},     {"opus", opus},
             {"pcm", pcm}, {"g711alaw", g711alaw}, {"g711mlaw", g711mlaw},
-            {"gsm", gsm}, {"raw", raw},
+            {"gsm", gsm}, {"raw", raw},           {"flac", flac},
         };
         const size_t kNumStringToName =
             sizeof(kStringToName) / sizeof(kStringToName[0]);
@@ -204,6 +209,7 @@ class AudioDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
             {g711mlaw, OMX_AUDIO_CodingG711},
             {gsm, OMX_AUDIO_CodingGSMFR},
             {raw, OMX_AUDIO_CodingPCM},
+            {flac, OMX_AUDIO_CodingFLAC},
         };
         static const size_t kNumCompToCoding =
             sizeof(kCompToCoding) / sizeof(kCompToCoding[0]);
@@ -219,7 +225,7 @@ class AudioDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
         framesReceived = 0;
         timestampUs = 0;
         timestampDevTest = false;
-        if (disableTest) std::cerr << "[          ] Warning !  Test Disabled\n";
+        if (disableTest) std::cout << "[   WARN   ] Test Disabled \n";
     }
 
     virtual void TearDown() override {
@@ -263,9 +269,8 @@ class AudioDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
                             EXPECT_EQ(tsHit, true)
                                 << "TimeStamp not recognized";
                         } else {
-                            std::cerr
-                                << "[          ] Warning ! Received non-zero "
-                                   "output / TimeStamp not recognized \n";
+                            std::cout << "[   INFO   ] Received non-zero "
+                                         "output / TimeStamp not recognized \n";
                         }
                     }
                 }
@@ -301,6 +306,7 @@ class AudioDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
         g711mlaw,
         gsm,
         raw,
+        flac,
         unknown_comp,
     };
 
@@ -418,6 +424,9 @@ void getInputChannelInfo(sp<IOmxNode> omxNode, OMX_U32 kPortIndexInput,
             ASSERT_EQ(status,
                       ::android::hardware::media::omx::V1_0::Status::OK);
             *nChannels = param.nChannels;
+            // NOTE: For amrnb sample rate is 8k and amrwb sample rate is 16k.
+            // There is no nSampleRate field in OMX_AUDIO_PARAM_AMRTYPE. Just
+            // return 8k to avoid returning uninit variable.
             *nSampleRate = 8000;
             break;
         }
@@ -431,6 +440,16 @@ void getInputChannelInfo(sp<IOmxNode> omxNode, OMX_U32 kPortIndexInput,
             *nSampleRate = param.nSampleRate;
             break;
         }
+        case OMX_AUDIO_CodingFLAC: {
+            OMX_AUDIO_PARAM_FLACTYPE param;
+            status = getPortParam(omxNode, OMX_IndexParamAudioFlac,
+                                  kPortIndexInput, &param);
+            ASSERT_EQ(status,
+                      ::android::hardware::media::omx::V1_0::Status::OK);
+            *nChannels = param.nChannels;
+            *nSampleRate = param.nSampleRate;
+            break;
+        }
         default:
             ASSERT_TRUE(false);
             break;
@@ -472,6 +491,9 @@ void GetURLForComponent(AudioDecHidlTest::standardComp comp, char* mURL,
          "bbb_gsm_1ch_8khz_13kbps.info"},
         {AudioDecHidlTest::standardComp::raw, "bbb_raw_1ch_8khz_s32le.raw",
          "bbb_raw_1ch_8khz_s32le.info"},
+        {AudioDecHidlTest::standardComp::flac,
+         "bbb_flac_stereo_680kbps_48000hz.flac",
+         "bbb_flac_stereo_680kbps_48000hz.info"},
     };
 
     for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) {
@@ -530,13 +552,13 @@ void portReconfiguration(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
             // set Port Params
             int32_t nChannels;
             int32_t nSampleRate;
-            getInputChannelInfo(omxNode, kPortIndexInput, eEncoding, &nChannels,
-                                &nSampleRate);
+            ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(
+                omxNode, kPortIndexInput, eEncoding, &nChannels, &nSampleRate));
             // Configure output port
             // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way
-            // to
-            // configure output PCM port. The port undergoes auto configuration
-            // internally basing on parsed elementary stream information.
+            // to configure output PCM port. The port undergoes auto
+            // configuration internally basing on parsed elementary stream
+            // information.
             if (comp != AudioDecHidlTest::standardComp::vorbis &&
                 comp != AudioDecHidlTest::standardComp::opus &&
                 comp != AudioDecHidlTest::standardComp::raw) {
@@ -545,9 +567,8 @@ void portReconfiguration(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
                                     nSampleRate);
             }
 
-            // If you can disable a port, then you should be able to
-            // enable
-            // it as well
+            // If you can disable a port, then you should be able to enable it
+            // as well
             status = omxNode->sendCommand(
                 toRawCommandType(OMX_CommandPortEnable), kPortIndexOutput);
             ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
@@ -558,7 +579,8 @@ void portReconfiguration(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
             ASSERT_EQ(status,
                       android::hardware::media::omx::V1_0::Status::TIMED_OUT);
 
-            allocatePortBuffers(omxNode, oBuffer, kPortIndexOutput);
+            ASSERT_NO_FATAL_FAILURE(
+                allocatePortBuffers(omxNode, oBuffer, kPortIndexOutput));
             status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer,
                                               oBuffer);
             ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
@@ -568,14 +590,14 @@ void portReconfiguration(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
 
             // dispatch output buffers
             for (size_t i = 0; i < oBuffer->size(); i++) {
-                dispatchOutputBuffer(omxNode, oBuffer, i);
+                ASSERT_NO_FATAL_FAILURE(
+                    dispatchOutputBuffer(omxNode, oBuffer, i));
             }
         } else {
             ASSERT_TRUE(false);
         }
     } else {
-        EXPECT_TRUE(false);
-        return;
+        ASSERT_TRUE(false);
     }
 }
 
@@ -588,18 +610,19 @@ void waitOnInputConsumption(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
                             AudioDecHidlTest::standardComp comp) {
     android::hardware::media::omx::V1_0::Status status;
     Message msg;
-    int timeOut = TIMEOUT_COUNTER;
+    int timeOut = TIMEOUT_COUNTER_Q;
 
     while (timeOut--) {
         size_t i = 0;
         status =
-            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
+            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
         if (status == android::hardware::media::omx::V1_0::Status::OK) {
-            EXPECT_EQ(msg.type, Message::Type::EVENT);
+            ASSERT_EQ(msg.type, Message::Type::EVENT);
             packedArgs audioArgs = {eEncoding, comp};
-            portReconfiguration(omxNode, observer, iBuffer, oBuffer,
-                                kPortIndexInput, kPortIndexOutput, msg,
-                                PortMode::PRESET_BYTE_BUFFER, &audioArgs);
+            ASSERT_NO_FATAL_FAILURE(
+                portReconfiguration(omxNode, observer, iBuffer, oBuffer,
+                                    kPortIndexInput, kPortIndexOutput, msg,
+                                    PortMode::PRESET_BYTE_BUFFER, &audioArgs));
         }
         // status == TIMED_OUT, it could be due to process time being large
         // than DEFAULT_TIMEOUT or component needs output buffers to start
@@ -612,9 +635,10 @@ void waitOnInputConsumption(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
         // Dispatch an output buffer assuming outQueue.empty() is true
         size_t index;
         if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
-            dispatchOutputBuffer(omxNode, oBuffer, index);
+            ASSERT_NO_FATAL_FAILURE(
+                dispatchOutputBuffer(omxNode, oBuffer, index));
+            timeOut = TIMEOUT_COUNTER_Q;
         }
-        timeOut--;
     }
 }
 
@@ -628,51 +652,29 @@ void decodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
                    AudioDecHidlTest::standardComp comp, bool signalEOS = true) {
     android::hardware::media::omx::V1_0::Status status;
     Message msg;
-
-    // dispatch output buffers
-    for (size_t i = 0; i < oBuffer->size(); i++) {
-        dispatchOutputBuffer(omxNode, oBuffer, i);
-    }
-    // dispatch input buffers
+    size_t index;
     uint32_t flags = 0;
     int frameID = offset;
-    for (size_t i = 0; (i < iBuffer->size()) && (frameID < (int)Info->size()) &&
-                       (frameID < (offset + range));
-         i++) {
-        char* ipBuffer = static_cast<char*>(
-            static_cast<void*>((*iBuffer)[i].mMemory->getPointer()));
-        ASSERT_LE((*Info)[frameID].bytesCount,
-                  static_cast<int>((*iBuffer)[i].mMemory->getSize()));
-        eleStream.read(ipBuffer, (*Info)[frameID].bytesCount);
-        ASSERT_EQ(eleStream.gcount(), (*Info)[frameID].bytesCount);
-        flags = (*Info)[frameID].flags;
-        if (signalEOS && ((frameID == (int)Info->size() - 1) ||
-                          (frameID == (offset + range - 1))))
-            flags |= OMX_BUFFERFLAG_EOS;
-        dispatchInputBuffer(omxNode, iBuffer, i, (*Info)[frameID].bytesCount,
-                            flags, (*Info)[frameID].timestamp);
-        frameID++;
-    }
+    int timeOut = TIMEOUT_COUNTER_Q;
+    bool iQueued, oQueued;
 
-    int timeOut = TIMEOUT_COUNTER;
-    bool stall = false;
     while (1) {
+        iQueued = oQueued = false;
         status =
-            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
-
+            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
         // Port Reconfiguration
         if (status == android::hardware::media::omx::V1_0::Status::OK &&
             msg.type == Message::Type::EVENT) {
             packedArgs audioArgs = {eEncoding, comp};
-            portReconfiguration(omxNode, observer, iBuffer, oBuffer,
-                                kPortIndexInput, kPortIndexOutput, msg,
-                                PortMode::PRESET_BYTE_BUFFER, &audioArgs);
+            ASSERT_NO_FATAL_FAILURE(
+                portReconfiguration(omxNode, observer, iBuffer, oBuffer,
+                                    kPortIndexInput, kPortIndexOutput, msg,
+                                    PortMode::PRESET_BYTE_BUFFER, &audioArgs));
         }
 
         if (frameID == (int)Info->size() || frameID == (offset + range)) break;
 
         // Dispatch input buffer
-        size_t index = 0;
         if ((index = getEmptyBufferID(iBuffer)) < iBuffer->size()) {
             char* ipBuffer = static_cast<char*>(
                 static_cast<void*>((*iBuffer)[index].mMemory->getPointer()));
@@ -681,28 +683,33 @@ void decodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
             eleStream.read(ipBuffer, (*Info)[frameID].bytesCount);
             ASSERT_EQ(eleStream.gcount(), (*Info)[frameID].bytesCount);
             flags = (*Info)[frameID].flags;
+            // Indicate to omx core that the buffer contains a full frame worth
+            // of data
+            flags |= OMX_BUFFERFLAG_ENDOFFRAME;
+            // Indicate the omx core that this is the last buffer it needs to
+            // process
             if (signalEOS && ((frameID == (int)Info->size() - 1) ||
                               (frameID == (offset + range - 1))))
                 flags |= OMX_BUFFERFLAG_EOS;
-            dispatchInputBuffer(omxNode, iBuffer, index,
-                                (*Info)[frameID].bytesCount, flags,
-                                (*Info)[frameID].timestamp);
+            ASSERT_NO_FATAL_FAILURE(dispatchInputBuffer(
+                omxNode, iBuffer, index, (*Info)[frameID].bytesCount, flags,
+                (*Info)[frameID].timestamp));
             frameID++;
-            stall = false;
-        } else
-            stall = true;
+            iQueued = true;
+        }
+        // Dispatch output buffer
         if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
-            dispatchOutputBuffer(omxNode, oBuffer, index);
-            stall = false;
-        } else
-            stall = true;
-        if (stall)
-            timeOut--;
+            ASSERT_NO_FATAL_FAILURE(
+                dispatchOutputBuffer(omxNode, oBuffer, index));
+            oQueued = true;
+        }
+        // Reset Counters when either input or output buffer is dispatched
+        if (iQueued || oQueued)
+            timeOut = TIMEOUT_COUNTER_Q;
         else
-            timeOut = TIMEOUT_COUNTER;
+            timeOut--;
         if (timeOut == 0) {
-            EXPECT_TRUE(false) << "Wait on Input/Output is found indefinite";
-            break;
+            ASSERT_TRUE(false) << "Wait on Input/Output is found indefinite";
         }
     }
 }
@@ -717,7 +724,7 @@ TEST_F(AudioDecHidlTest, SetRole) {
 }
 
 // port format enumeration
-TEST_F(AudioDecHidlTest, DISABLED_EnumeratePortFormat) {
+TEST_F(AudioDecHidlTest, EnumeratePortFormat) {
     description("Test Component on Mandatory Port Parameters (Port Format)");
     if (disableTest) return;
     android::hardware::media::omx::V1_0::Status status;
@@ -784,8 +791,8 @@ TEST_F(AudioDecHidlTest, DecodeTest) {
         setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
                             OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
                             32);
-    getInputChannelInfo(omxNode, kPortIndexInput, eEncoding, &nChannels,
-                        &nSampleRate);
+    ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(
+        omxNode, kPortIndexInput, eEncoding, &nChannels, &nSampleRate));
     // Configure output port
     // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
     // configure output PCM port. The port undergoes auto configuration
@@ -798,36 +805,37 @@ TEST_F(AudioDecHidlTest, DecodeTest) {
     android::Vector<BufferInfo> iBuffer, oBuffer;
 
     // set state to idle
-    changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput);
+    ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(omxNode, observer, &iBuffer,
+                                                    &oBuffer, kPortIndexInput,
+                                                    kPortIndexOutput));
     // set state to executing
-    changeStateIdletoExecute(omxNode, observer);
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
     // Port Reconfiguration
     eleStream.open(mURL, std::ifstream::binary);
     ASSERT_EQ(eleStream.is_open(), true);
-    decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
-                  kPortIndexInput, kPortIndexOutput, eleStream, &Info, 0,
-                  (int)Info.size(), compName);
+    ASSERT_NO_FATAL_FAILURE(decodeNFrames(
+        omxNode, observer, &iBuffer, &oBuffer, eEncoding, kPortIndexInput,
+        kPortIndexOutput, eleStream, &Info, 0, (int)Info.size(), compName));
     eleStream.close();
-    waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
-                           kPortIndexInput, kPortIndexOutput, compName);
+    ASSERT_NO_FATAL_FAILURE(
+        waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
+                               kPortIndexInput, kPortIndexOutput, compName));
     packedArgs audioArgs = {eEncoding, compName};
-    testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag, nullptr,
-            portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs);
+    ASSERT_NO_FATAL_FAILURE(testEOS(
+        omxNode, observer, &iBuffer, &oBuffer, false, eosFlag, nullptr,
+        portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs));
     if (timestampDevTest) EXPECT_EQ(timestampUslist.empty(), true);
     // set state to idle
-    changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
+    ASSERT_NO_FATAL_FAILURE(
+        changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
     // set state to executing
-    changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput);
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
+                                                    &oBuffer, kPortIndexInput,
+                                                    kPortIndexOutput));
 }
 
 // end of sequence test
-// SPECIAL CASE; Sending Empty input EOS buffer is not supported across all
-// components. For instance soft vorbis and soft opus expects CSD buffers at
-// the start. Disabling this test for now. We shall revisit this at a later
-// stage
-TEST_F(AudioDecHidlTest, DISABLED_EOSTest_M) {
+TEST_F(AudioDecHidlTest, EOSTest_M) {
     description("Test end of stream monkeying");
     if (disableTest) return;
     android::hardware::media::omx::V1_0::Status status;
@@ -849,8 +857,8 @@ TEST_F(AudioDecHidlTest, DISABLED_EOSTest_M) {
         setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
                             OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
                             32);
-    getInputChannelInfo(omxNode, kPortIndexInput, eEncoding, &nChannels,
-                        &nSampleRate);
+    ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(
+        omxNode, kPortIndexInput, eEncoding, &nChannels, &nSampleRate));
     // Configure output port
     // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
     // configure output PCM port. The port undergoes auto configuration
@@ -863,26 +871,31 @@ TEST_F(AudioDecHidlTest, DISABLED_EOSTest_M) {
     android::Vector<BufferInfo> iBuffer, oBuffer;
 
     // set state to idle
-    changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput);
+    ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(omxNode, observer, &iBuffer,
+                                                    &oBuffer, kPortIndexInput,
+                                                    kPortIndexOutput));
     // set state to executing
-    changeStateIdletoExecute(omxNode, observer);
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
 
     // request EOS at the start
     packedArgs audioArgs = {eEncoding, compName};
-    testEOS(omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, nullptr,
-            portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs);
-    flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
-               kPortIndexOutput);
+    ASSERT_NO_FATAL_FAILURE(testEOS(
+        omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, nullptr,
+        portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs));
+    ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
+                                       kPortIndexInput, kPortIndexOutput));
     EXPECT_GE(framesReceived, 0U);
     framesReceived = 0;
     timestampUs = 0;
 
     // set state to idle
-    changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
+    ASSERT_NO_FATAL_FAILURE(
+        changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
+
     // set state to executing
-    changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput);
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
+                                                    &oBuffer, kPortIndexInput,
+                                                    kPortIndexOutput));
 }
 
 // end of sequence test
@@ -928,8 +941,8 @@ TEST_F(AudioDecHidlTest, ThumbnailTest) {
         setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
                             OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
                             32);
-    getInputChannelInfo(omxNode, kPortIndexInput, eEncoding, &nChannels,
-                        &nSampleRate);
+    ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(
+        omxNode, kPortIndexInput, eEncoding, &nChannels, &nSampleRate));
     // Configure output port
     // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
     // configure output PCM port. The port undergoes auto configuration
@@ -942,10 +955,11 @@ TEST_F(AudioDecHidlTest, ThumbnailTest) {
     android::Vector<BufferInfo> iBuffer, oBuffer;
 
     // set state to idle
-    changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput);
+    ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(omxNode, observer, &iBuffer,
+                                                    &oBuffer, kPortIndexInput,
+                                                    kPortIndexOutput));
     // set state to executing
-    changeStateIdletoExecute(omxNode, observer);
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
 
     // request EOS for thumbnail
     // signal EOS flag with last frame
@@ -953,17 +967,19 @@ TEST_F(AudioDecHidlTest, ThumbnailTest) {
     while (!(Info[i].flags & OMX_BUFFERFLAG_SYNCFRAME)) i++;
     eleStream.open(mURL, std::ifstream::binary);
     ASSERT_EQ(eleStream.is_open(), true);
-    decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
-                  kPortIndexInput, kPortIndexOutput, eleStream, &Info, 0, i + 1,
-                  compName);
+    ASSERT_NO_FATAL_FAILURE(decodeNFrames(
+        omxNode, observer, &iBuffer, &oBuffer, eEncoding, kPortIndexInput,
+        kPortIndexOutput, eleStream, &Info, 0, i + 1, compName));
     eleStream.close();
-    waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
-                           kPortIndexInput, kPortIndexOutput, compName);
+    ASSERT_NO_FATAL_FAILURE(
+        waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
+                               kPortIndexInput, kPortIndexOutput, compName));
     packedArgs audioArgs = {eEncoding, compName};
-    testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag, nullptr,
-            portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs);
-    flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
-               kPortIndexOutput);
+    ASSERT_NO_FATAL_FAILURE(testEOS(
+        omxNode, observer, &iBuffer, &oBuffer, false, eosFlag, nullptr,
+        portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs));
+    ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
+                                       kPortIndexInput, kPortIndexOutput));
     EXPECT_GE(framesReceived, 1U);
     framesReceived = 0;
     timestampUs = 0;
@@ -971,25 +987,29 @@ TEST_F(AudioDecHidlTest, ThumbnailTest) {
     // signal EOS flag after last frame
     eleStream.open(mURL, std::ifstream::binary);
     ASSERT_EQ(eleStream.is_open(), true);
-    decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
-                  kPortIndexInput, kPortIndexOutput, eleStream, &Info, 0, i + 1,
-                  compName, false);
+    ASSERT_NO_FATAL_FAILURE(decodeNFrames(
+        omxNode, observer, &iBuffer, &oBuffer, eEncoding, kPortIndexInput,
+        kPortIndexOutput, eleStream, &Info, 0, i + 1, compName, false));
     eleStream.close();
-    waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
-                           kPortIndexInput, kPortIndexOutput, compName);
-    testEOS(omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, nullptr,
-            portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs);
-    flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
-               kPortIndexOutput);
+    ASSERT_NO_FATAL_FAILURE(
+        waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
+                               kPortIndexInput, kPortIndexOutput, compName));
+    ASSERT_NO_FATAL_FAILURE(testEOS(
+        omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, nullptr,
+        portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs));
+    ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
+                                       kPortIndexInput, kPortIndexOutput));
     EXPECT_GE(framesReceived, 1U);
     framesReceived = 0;
     timestampUs = 0;
 
     // set state to idle
-    changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
+    ASSERT_NO_FATAL_FAILURE(
+        changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
     // set state to executing
-    changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput);
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
+                                                    &oBuffer, kPortIndexInput,
+                                                    kPortIndexOutput));
 }
 
 // end of sequence test
@@ -1035,8 +1055,8 @@ TEST_F(AudioDecHidlTest, SimpleEOSTest) {
         setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
                             OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
                             32);
-    getInputChannelInfo(omxNode, kPortIndexInput, eEncoding, &nChannels,
-                        &nSampleRate);
+    ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(
+        omxNode, kPortIndexInput, eEncoding, &nChannels, &nSampleRate));
     // Configure output port
     // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
     // configure output PCM port. The port undergoes auto configuration
@@ -1049,33 +1069,39 @@ TEST_F(AudioDecHidlTest, SimpleEOSTest) {
     android::Vector<BufferInfo> iBuffer, oBuffer;
 
     // set state to idle
-    changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput);
+    ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(omxNode, observer, &iBuffer,
+                                                    &oBuffer, kPortIndexInput,
+                                                    kPortIndexOutput));
     // set state to executing
-    changeStateIdletoExecute(omxNode, observer);
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
 
     // request EOS at the end
     eleStream.open(mURL, std::ifstream::binary);
     ASSERT_EQ(eleStream.is_open(), true);
-    decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
-                  kPortIndexInput, kPortIndexOutput, eleStream, &Info, 0,
-                  (int)Info.size(), compName, false);
+    ASSERT_NO_FATAL_FAILURE(decodeNFrames(omxNode, observer, &iBuffer, &oBuffer,
+                                          eEncoding, kPortIndexInput,
+                                          kPortIndexOutput, eleStream, &Info, 0,
+                                          (int)Info.size(), compName, false));
     eleStream.close();
-    waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
-                           kPortIndexInput, kPortIndexOutput, compName);
+    ASSERT_NO_FATAL_FAILURE(
+        waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
+                               kPortIndexInput, kPortIndexOutput, compName));
     packedArgs audioArgs = {eEncoding, compName};
-    testEOS(omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, nullptr,
-            portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs);
-    flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
-               kPortIndexOutput);
+    ASSERT_NO_FATAL_FAILURE(testEOS(
+        omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, nullptr,
+        portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs));
+    ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
+                                       kPortIndexInput, kPortIndexOutput));
     framesReceived = 0;
     timestampUs = 0;
 
     // set state to idle
-    changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
+    ASSERT_NO_FATAL_FAILURE(
+        changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
     // set state to executing
-    changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput);
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
+                                                    &oBuffer, kPortIndexInput,
+                                                    kPortIndexOutput));
 }
 
 // test input/output port flush
@@ -1121,8 +1147,8 @@ TEST_F(AudioDecHidlTest, FlushTest) {
         setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
                             OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
                             32);
-    getInputChannelInfo(omxNode, kPortIndexInput, eEncoding, &nChannels,
-                        &nSampleRate);
+    ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(
+        omxNode, kPortIndexInput, eEncoding, &nChannels, &nSampleRate));
     // Configure output port
     // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
     // configure output PCM port. The port undergoes auto configuration
@@ -1135,10 +1161,11 @@ TEST_F(AudioDecHidlTest, FlushTest) {
     android::Vector<BufferInfo> iBuffer, oBuffer;
 
     // set state to idle
-    changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput);
+    ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(omxNode, observer, &iBuffer,
+                                                    &oBuffer, kPortIndexInput,
+                                                    kPortIndexOutput));
     // set state to executing
-    changeStateIdletoExecute(omxNode, observer);
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
 
     // Decode 128 frames and flush. here 128 is chosen to ensure there is a key
     // frame after this so that the below section can be convered for all
@@ -1146,12 +1173,11 @@ TEST_F(AudioDecHidlTest, FlushTest) {
     int nFrames = 128;
     eleStream.open(mURL, std::ifstream::binary);
     ASSERT_EQ(eleStream.is_open(), true);
-    decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
-                  kPortIndexInput, kPortIndexOutput, eleStream, &Info, 0,
-                  nFrames, compName, false);
-    // Note: Assumes 200 ms is enough to end any decode call that started
-    flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
-               kPortIndexOutput, 200000);
+    ASSERT_NO_FATAL_FAILURE(decodeNFrames(
+        omxNode, observer, &iBuffer, &oBuffer, eEncoding, kPortIndexInput,
+        kPortIndexOutput, eleStream, &Info, 0, nFrames, compName, false));
+    ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
+                                       kPortIndexInput, kPortIndexOutput));
     framesReceived = 0;
 
     // Seek to next key frame and start decoding till the end
@@ -1168,20 +1194,22 @@ TEST_F(AudioDecHidlTest, FlushTest) {
         index++;
     }
     if (keyFrame) {
-        decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
-                      kPortIndexInput, kPortIndexOutput, eleStream, &Info,
-                      index, Info.size() - index, compName, false);
+        ASSERT_NO_FATAL_FAILURE(
+            decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
+                          kPortIndexInput, kPortIndexOutput, eleStream, &Info,
+                          index, Info.size() - index, compName, false));
     }
-    // Note: Assumes 200 ms is enough to end any decode call that started
-    flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
-               kPortIndexOutput, 200000);
+    ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
+                                       kPortIndexInput, kPortIndexOutput));
     framesReceived = 0;
 
     // set state to idle
-    changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
+    ASSERT_NO_FATAL_FAILURE(
+        changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
     // set state to executing
-    changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput);
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
+                                                    &oBuffer, kPortIndexInput,
+                                                    kPortIndexOutput));
 }
 
 int main(int argc, char** argv) {
index ae79e82..d872444 100644 (file)
  */
 
 #define LOG_TAG "media_omx_hidl_audio_enc_test"
+#ifdef __LP64__
+#define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
+#endif
+
 #include <android-base/logging.h>
 
 #include <android/hardware/media/omx/1.0/IOmx.h>
@@ -161,6 +165,7 @@ class AudioEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
                                this->omxNode = _nl;
                            })
                         .isOk());
+        ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
         ASSERT_NE(omxNode, nullptr);
         ASSERT_NE(gEnv->getRole().empty(), true) << "Invalid Component Role";
         struct StringToName {
@@ -206,7 +211,7 @@ class AudioEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
         }
         if (i == kNumCompToCoding) disableTest = true;
         eosFlag = false;
-        if (disableTest) std::cerr << "[          ] Warning !  Test Disabled\n";
+        if (disableTest) std::cout << "[   WARN   ] Test Disabled \n";
     }
 
     virtual void TearDown() override {
@@ -342,13 +347,13 @@ void waitOnInputConsumption(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
                             android::Vector<BufferInfo>* oBuffer) {
     android::hardware::media::omx::V1_0::Status status;
     Message msg;
-    int timeOut = TIMEOUT_COUNTER;
+    int timeOut = TIMEOUT_COUNTER_Q;
 
     while (timeOut--) {
         size_t i = 0;
         status =
-            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
-        EXPECT_EQ(status,
+            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
+        ASSERT_EQ(status,
                   android::hardware::media::omx::V1_0::Status::TIMED_OUT);
         // status == TIMED_OUT, it could be due to process time being large
         // than DEFAULT_TIMEOUT or component needs output buffers to start
@@ -361,9 +366,10 @@ void waitOnInputConsumption(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
         // Dispatch an output buffer assuming outQueue.empty() is true
         size_t index;
         if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
-            dispatchOutputBuffer(omxNode, oBuffer, index);
+            ASSERT_NO_FATAL_FAILURE(
+                dispatchOutputBuffer(omxNode, oBuffer, index));
+            timeOut = TIMEOUT_COUNTER_Q;
         }
-        timeOut--;
     }
 }
 
@@ -376,43 +382,25 @@ void encodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
                    bool signalEOS = true) {
     android::hardware::media::omx::V1_0::Status status;
     Message msg;
-
-    // dispatch output buffers
-    for (size_t i = 0; i < oBuffer->size(); i++) {
-        dispatchOutputBuffer(omxNode, oBuffer, i);
-    }
-    // dispatch input buffers
+    size_t index;
     int bytesCount = samplesPerFrame * nChannels * 2;
     int32_t timestampIncr =
         (int)(((float)samplesPerFrame / nSampleRate) * 1000000);
     uint64_t timestamp = 0;
     uint32_t flags = 0;
-    for (size_t i = 0; i < iBuffer->size() && nFrames != 0; i++) {
-        char* ipBuffer = static_cast<char*>(
-            static_cast<void*>((*iBuffer)[i].mMemory->getPointer()));
-        ASSERT_LE(bytesCount,
-                  static_cast<int>((*iBuffer)[i].mMemory->getSize()));
-        eleStream.read(ipBuffer, bytesCount);
-        if (eleStream.gcount() != bytesCount) break;
-        if (signalEOS && (nFrames == 1)) flags = OMX_BUFFERFLAG_EOS;
-        dispatchInputBuffer(omxNode, iBuffer, i, bytesCount, flags, timestamp);
-        timestamp += timestampIncr;
-        nFrames--;
-    }
+    int timeOut = TIMEOUT_COUNTER_Q;
+    bool iQueued, oQueued;
 
-    int timeOut = TIMEOUT_COUNTER;
-    bool stall = false;
     while (1) {
+        iQueued = oQueued = false;
         status =
-            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
-
+            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
         if (status == android::hardware::media::omx::V1_0::Status::OK)
             ASSERT_TRUE(false);
 
         if (nFrames == 0) break;
 
         // Dispatch input buffer
-        size_t index = 0;
         if ((index = getEmptyBufferID(iBuffer)) < iBuffer->size()) {
             char* ipBuffer = static_cast<char*>(
                 static_cast<void*>((*iBuffer)[index].mMemory->getPointer()));
@@ -420,27 +408,27 @@ void encodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
                       static_cast<int>((*iBuffer)[index].mMemory->getSize()));
             eleStream.read(ipBuffer, bytesCount);
             if (eleStream.gcount() != bytesCount) break;
-            if (signalEOS && (nFrames == 1)) flags = OMX_BUFFERFLAG_EOS;
-            dispatchInputBuffer(omxNode, iBuffer, index, bytesCount, flags,
-                                timestamp);
+            flags = OMX_BUFFERFLAG_ENDOFFRAME;
+            if (signalEOS && (nFrames == 1)) flags |= OMX_BUFFERFLAG_EOS;
+            ASSERT_NO_FATAL_FAILURE(dispatchInputBuffer(
+                omxNode, iBuffer, index, bytesCount, flags, timestamp));
             timestamp += timestampIncr;
             nFrames--;
-            stall = false;
-        } else
-            stall = true;
+            iQueued = true;
+        }
         // Dispatch output buffer
         if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
-            dispatchOutputBuffer(omxNode, oBuffer, index);
-            stall = false;
-        } else
-            stall = true;
-        if (stall)
-            timeOut--;
+            ASSERT_NO_FATAL_FAILURE(
+                dispatchOutputBuffer(omxNode, oBuffer, index));
+            oQueued = true;
+        }
+        // Reset Counters when either input or output buffer is dispatched
+        if (iQueued || oQueued)
+            timeOut = TIMEOUT_COUNTER_Q;
         else
-            timeOut = TIMEOUT_COUNTER;
+            timeOut--;
         if (timeOut == 0) {
-            EXPECT_TRUE(false) << "Wait on Input/Output is found indefinite";
-            break;
+            ASSERT_TRUE(false) << "Wait on Input/Output is found indefinite";
         }
     }
 }
@@ -455,7 +443,7 @@ TEST_F(AudioEncHidlTest, SetRole) {
 }
 
 // port format enumeration
-TEST_F(AudioEncHidlTest, DISABLED_EnumeratePortFormat) {
+TEST_F(AudioEncHidlTest, EnumeratePortFormat) {
     description("Test Component on Mandatory Port Parameters (Port Format)");
     if (disableTest) return;
     android::hardware::media::omx::V1_0::Status status;
@@ -531,31 +519,39 @@ TEST_F(AudioEncHidlTest, SimpleEncodeTest) {
     }
     setupPCMPort(omxNode, kPortIndexInput, nChannels, OMX_NumericalDataSigned,
                  16, nSampleRate, OMX_AUDIO_PCMModeLinear);
+
     // Configure output port
-    setDefaultPortParam(omxNode, kPortIndexOutput, eEncoding, compName,
-                        nChannels, nSampleRate, nBitRate);
+    ASSERT_NO_FATAL_FAILURE(setDefaultPortParam(omxNode, kPortIndexOutput,
+                                                eEncoding, compName, nChannels,
+                                                nSampleRate, nBitRate));
 
     android::Vector<BufferInfo> iBuffer, oBuffer;
 
     // set state to idle
-    changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput);
+    ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(omxNode, observer, &iBuffer,
+                                                    &oBuffer, kPortIndexInput,
+                                                    kPortIndexOutput));
     // set state to executing
-    changeStateIdletoExecute(omxNode, observer);
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
 
     eleStream.open(mURL, std::ifstream::binary);
     ASSERT_EQ(eleStream.is_open(), true);
-    encodeNFrames(omxNode, observer, &iBuffer, &oBuffer, 128, samplesPerFrame,
-                  nChannels, nSampleRate, eleStream);
+    ASSERT_NO_FATAL_FAILURE(encodeNFrames(omxNode, observer, &iBuffer, &oBuffer,
+                                          128, samplesPerFrame, nChannels,
+                                          nSampleRate, eleStream));
     eleStream.close();
-    waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer);
-    testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag);
 
+    ASSERT_NO_FATAL_FAILURE(
+        waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer));
+    ASSERT_NO_FATAL_FAILURE(
+        testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag));
     // set state to idle
-    changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
+    ASSERT_NO_FATAL_FAILURE(
+        changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
     // set state to executing
-    changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput);
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
+                                                    &oBuffer, kPortIndexInput,
+                                                    kPortIndexOutput));
 }
 
 int main(int argc, char** argv) {
index 4c68219..9500094 100644 (file)
  */
 
 #define LOG_TAG "media_omx_hidl_audio_test_common"
+#ifdef __LP64__
+#define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
+#endif
+
 #include <android-base/logging.h>
 
 #include <android/hardware/media/omx/1.0/IOmx.h>
index 08b3d9c..b187d28 100644 (file)
 #include <media_hidl_test_common.h>
 
 /*
- * Random Index used for monkey testing while get/set parameters
- */
-#define RANDOM_INDEX 1729
-
-/*
  * Common audio utils
  */
 void enumerateProfile(sp<IOmxNode> omxNode, OMX_U32 portIndex,
index 93251fe..cdc52fb 100644 (file)
 
 cc_library_static {
     name: "VtsHalMediaOmxV1_0CommonUtil",
-    defaults: ["hidl_defaults"],
     srcs: ["media_hidl_test_common.cpp"],
-    shared_libs: [
-        "liblog",
+
+    header_libs: ["media_plugin_headers"],
+    export_header_lib_headers: ["media_plugin_headers"],
+    export_include_dirs: ["."],
+
+    static_libs: [
+        "VtsHalHidlTargetTestBase",
         "libhidlmemory",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
         "android.hardware.media.omx@1.0",
+        "android.hardware.graphics.allocator@2.0",
     ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [ "-O0", "-g", ],
-    include_dirs: [
-        "frameworks/native/include/media/openmax/",
+}
+
+cc_defaults {
+    name: "VtsHalMediaOmxV1_0Defaults",
+    defaults: ["VtsHalTargetTestDefaults"],
+
+    // Link to these statically as they are not guaranteed to be on the device.
+    static_libs: [
+        "VtsHalMediaOmxV1_0CommonUtil",
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.bufferqueue@1.0",
+        "android.hardware.graphics.common@1.0",
+        "android.hardware.media.omx@1.0",
+        "android.hardware.media@1.0",
+        "android.hidl.allocator@1.0",
+        "android.hidl.memory@1.0",
+        "libhidlmemory",
+        "libnativehelper",
+    ],
+
+    // TODO(b/64437680): Assume these libs are always available on the device.
+    shared_libs: [
+        "libstagefright_foundation",
     ],
 }
index 1f67e2b..34a96a0 100644 (file)
  */
 
 #define LOG_TAG "media_omx_hidl_video_test_common"
-
 #ifdef __LP64__
 #define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
 #endif
 
 #include <android-base/logging.h>
 
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <android/hardware/graphics/mapper/2.0/types.h>
 #include <android/hardware/media/omx/1.0/IOmx.h>
 #include <android/hardware/media/omx/1.0/IOmxNode.h>
 #include <android/hardware/media/omx/1.0/IOmxObserver.h>
 #include <android/hidl/allocator/1.0/IAllocator.h>
 #include <android/hidl/memory/1.0/IMapper.h>
 #include <android/hidl/memory/1.0/IMemory.h>
+#include <cutils/atomic.h>
 
+using ::android::hardware::graphics::common::V1_0::BufferUsage;
+using ::android::hardware::graphics::common::V1_0::PixelFormat;
 using ::android::hardware::media::omx::V1_0::IOmx;
 using ::android::hardware::media::omx::V1_0::IOmxObserver;
 using ::android::hardware::media::omx::V1_0::IOmxNode;
@@ -186,10 +191,157 @@ Return<android::hardware::media::omx::V1_0::Status> setAudioPortFormat(
     return status;
 }
 
+void allocateGraphicBuffers(sp<IOmxNode> omxNode, OMX_U32 portIndex,
+                            BufferInfo* buffer, uint32_t nFrameWidth,
+                            uint32_t nFrameHeight, int32_t* nStride,
+                            int format) {
+    android::hardware::media::omx::V1_0::Status status;
+    sp<android::hardware::graphics::allocator::V2_0::IAllocator> allocator =
+        android::hardware::graphics::allocator::V2_0::IAllocator::getService();
+    ASSERT_NE(nullptr, allocator.get());
+
+    sp<android::hardware::graphics::mapper::V2_0::IMapper> mapper =
+        android::hardware::graphics::mapper::V2_0::IMapper::getService();
+    ASSERT_NE(mapper.get(), nullptr);
+
+    android::hardware::graphics::mapper::V2_0::IMapper::BufferDescriptorInfo
+        descriptorInfo;
+    uint32_t usage;
+
+    descriptorInfo.width = nFrameWidth;
+    descriptorInfo.height = nFrameHeight;
+    descriptorInfo.layerCount = 1;
+    descriptorInfo.format = static_cast<PixelFormat>(format);
+    descriptorInfo.usage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN);
+    omxNode->getGraphicBufferUsage(
+        portIndex,
+        [&status, &usage](android::hardware::media::omx::V1_0::Status _s,
+                          uint32_t _n1) {
+            status = _s;
+            usage = _n1;
+        });
+    if (status == android::hardware::media::omx::V1_0::Status::OK) {
+        descriptorInfo.usage |= usage;
+    }
+
+    ::android::hardware::hidl_vec<uint32_t> descriptor;
+    android::hardware::graphics::mapper::V2_0::Error error;
+    mapper->createDescriptor(
+        descriptorInfo, [&error, &descriptor](
+                            android::hardware::graphics::mapper::V2_0::Error _s,
+                            ::android::hardware::hidl_vec<uint32_t> _n1) {
+            error = _s;
+            descriptor = _n1;
+        });
+    ASSERT_EQ(error, android::hardware::graphics::mapper::V2_0::Error::NONE);
+
+    static volatile int32_t nextId = 0;
+    uint64_t id = static_cast<uint64_t>(getpid()) << 32;
+    allocator->allocate(
+        descriptor, 1,
+        [&](android::hardware::graphics::mapper::V2_0::Error _s, uint32_t _n1,
+            const ::android::hardware::hidl_vec<
+                ::android::hardware::hidl_handle>& _n2) {
+            ASSERT_EQ(android::hardware::graphics::mapper::V2_0::Error::NONE,
+                      _s);
+            *nStride = _n1;
+            buffer->omxBuffer.nativeHandle = _n2[0];
+            buffer->omxBuffer.attr.anwBuffer.width = nFrameWidth;
+            buffer->omxBuffer.attr.anwBuffer.height = nFrameHeight;
+            buffer->omxBuffer.attr.anwBuffer.stride = _n1;
+            buffer->omxBuffer.attr.anwBuffer.format = descriptorInfo.format;
+            buffer->omxBuffer.attr.anwBuffer.usage = descriptorInfo.usage;
+            buffer->omxBuffer.attr.anwBuffer.layerCount =
+                descriptorInfo.layerCount;
+            buffer->omxBuffer.attr.anwBuffer.id =
+                id | static_cast<uint32_t>(android_atomic_inc(&nextId));
+        });
+}
+
+// allocate buffers needed on a component port
+void allocateBuffer(sp<IOmxNode> omxNode, BufferInfo* buffer, OMX_U32 portIndex,
+                    OMX_U32 nBufferSize, PortMode portMode) {
+    android::hardware::media::omx::V1_0::Status status;
+
+    if (portMode == PortMode::PRESET_SECURE_BUFFER) {
+        buffer->owner = client;
+        buffer->omxBuffer.type = CodecBuffer::Type::NATIVE_HANDLE;
+        omxNode->allocateSecureBuffer(
+            portIndex, nBufferSize,
+            [&status, &buffer](
+                android::hardware::media::omx::V1_0::Status _s, uint32_t id,
+                ::android::hardware::hidl_handle const& nativeHandle) {
+                status = _s;
+                buffer->id = id;
+                buffer->omxBuffer.nativeHandle = nativeHandle;
+            });
+        ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    } else if (portMode == PortMode::PRESET_BYTE_BUFFER ||
+               portMode == PortMode::DYNAMIC_ANW_BUFFER) {
+        sp<IAllocator> allocator = IAllocator::getService("ashmem");
+        ASSERT_NE(allocator.get(), nullptr);
+
+        buffer->owner = client;
+        buffer->omxBuffer.type = CodecBuffer::Type::SHARED_MEM;
+        buffer->omxBuffer.attr.preset.rangeOffset = 0;
+        buffer->omxBuffer.attr.preset.rangeLength = 0;
+        bool success = false;
+        if (portMode != PortMode::PRESET_BYTE_BUFFER) {
+            nBufferSize = sizeof(android::VideoNativeMetadata);
+        }
+        allocator->allocate(
+            nBufferSize,
+            [&success, &buffer](bool _s,
+                                ::android::hardware::hidl_memory const& mem) {
+                success = _s;
+                buffer->omxBuffer.sharedMemory = mem;
+            });
+        ASSERT_EQ(success, true);
+        ASSERT_EQ(buffer->omxBuffer.sharedMemory.size(), nBufferSize);
+        buffer->mMemory = mapMemory(buffer->omxBuffer.sharedMemory);
+        ASSERT_NE(buffer->mMemory, nullptr);
+        if (portMode == PortMode::DYNAMIC_ANW_BUFFER) {
+            android::VideoNativeMetadata* metaData =
+                static_cast<android::VideoNativeMetadata*>(
+                    static_cast<void*>(buffer->mMemory->getPointer()));
+            metaData->nFenceFd = -1;
+            buffer->slot = -1;
+        }
+        omxNode->useBuffer(
+            portIndex, buffer->omxBuffer,
+            [&status, &buffer](android::hardware::media::omx::V1_0::Status _s,
+                               uint32_t id) {
+                status = _s;
+                buffer->id = id;
+            });
+        ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    } else if (portMode == PortMode::PRESET_ANW_BUFFER) {
+        OMX_PARAM_PORTDEFINITIONTYPE portDef;
+        status = getPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
+                              &portDef);
+        ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+        int32_t nStride;
+        buffer->owner = client;
+        buffer->omxBuffer.type = CodecBuffer::Type::ANW_BUFFER;
+        ASSERT_NO_FATAL_FAILURE(allocateGraphicBuffers(
+            omxNode, portIndex, buffer, portDef.format.video.nFrameWidth,
+            portDef.format.video.nFrameHeight, &nStride,
+            portDef.format.video.eColorFormat));
+        omxNode->useBuffer(
+            portIndex, buffer->omxBuffer,
+            [&status, &buffer](android::hardware::media::omx::V1_0::Status _s,
+                               uint32_t id) {
+                status = _s;
+                buffer->id = id;
+            });
+        ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    }
+}
+
 // allocate buffers needed on a component port
 void allocatePortBuffers(sp<IOmxNode> omxNode,
                          android::Vector<BufferInfo>* buffArray,
-                         OMX_U32 portIndex, PortMode portMode) {
+                         OMX_U32 portIndex, PortMode portMode, bool allocGrap) {
     android::hardware::media::omx::V1_0::Status status;
     OMX_PARAM_PORTDEFINITIONTYPE portDef;
 
@@ -199,70 +351,18 @@ void allocatePortBuffers(sp<IOmxNode> omxNode,
                           &portDef);
     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
 
-    if (portMode == PortMode::PRESET_SECURE_BUFFER) {
-        for (size_t i = 0; i < portDef.nBufferCountActual; i++) {
-            BufferInfo buffer;
-            buffer.owner = client;
-            buffer.omxBuffer.type = CodecBuffer::Type::NATIVE_HANDLE;
-            omxNode->allocateSecureBuffer(
-                portIndex, portDef.nBufferSize,
-                [&status, &buffer](
-                    android::hardware::media::omx::V1_0::Status _s, uint32_t id,
-                    ::android::hardware::hidl_handle const& nativeHandle) {
-                    status = _s;
-                    buffer.id = id;
-                    buffer.omxBuffer.nativeHandle = nativeHandle;
-                });
-            buffArray->push(buffer);
-            ASSERT_EQ(status,
-                      ::android::hardware::media::omx::V1_0::Status::OK);
-        }
-    } else if (portMode == PortMode::PRESET_BYTE_BUFFER ||
-               portMode == PortMode::DYNAMIC_ANW_BUFFER) {
-        sp<IAllocator> allocator = IAllocator::getService("ashmem");
-        EXPECT_NE(allocator.get(), nullptr);
-
-        for (size_t i = 0; i < portDef.nBufferCountActual; i++) {
-            BufferInfo buffer;
-            buffer.owner = client;
-            buffer.omxBuffer.type = CodecBuffer::Type::SHARED_MEM;
-            buffer.omxBuffer.attr.preset.rangeOffset = 0;
-            buffer.omxBuffer.attr.preset.rangeLength = 0;
-            bool success = false;
-            if (portMode != PortMode::PRESET_BYTE_BUFFER) {
-                portDef.nBufferSize = sizeof(android::VideoNativeMetadata);
-            }
-            allocator->allocate(
-                portDef.nBufferSize,
-                [&success, &buffer](
-                    bool _s, ::android::hardware::hidl_memory const& mem) {
-                    success = _s;
-                    buffer.omxBuffer.sharedMemory = mem;
-                });
-            ASSERT_EQ(success, true);
-            ASSERT_EQ(buffer.omxBuffer.sharedMemory.size(),
-                      portDef.nBufferSize);
-            buffer.mMemory = mapMemory(buffer.omxBuffer.sharedMemory);
-            ASSERT_NE(buffer.mMemory, nullptr);
-            if (portMode == PortMode::DYNAMIC_ANW_BUFFER) {
-                android::VideoNativeMetadata* metaData =
-                    static_cast<android::VideoNativeMetadata*>(
-                        static_cast<void*>(buffer.mMemory->getPointer()));
-                metaData->nFenceFd = -1;
-                buffer.slot = -1;
-            }
-            omxNode->useBuffer(
-                portIndex, buffer.omxBuffer,
-                [&status, &buffer](
-                    android::hardware::media::omx::V1_0::Status _s,
-                    uint32_t id) {
-                    status = _s;
-                    buffer.id = id;
-                });
-            buffArray->push(buffer);
-            ASSERT_EQ(status,
-                      ::android::hardware::media::omx::V1_0::Status::OK);
+    for (size_t i = 0; i < portDef.nBufferCountActual; i++) {
+        BufferInfo buffer;
+        ASSERT_NO_FATAL_FAILURE(allocateBuffer(omxNode, &buffer, portIndex,
+                                               portDef.nBufferSize, portMode));
+        if (allocGrap && portMode == PortMode::DYNAMIC_ANW_BUFFER) {
+            int32_t nStride;
+            ASSERT_NO_FATAL_FAILURE(allocateGraphicBuffers(
+                omxNode, portIndex, &buffer, portDef.format.video.nFrameWidth,
+                portDef.format.video.nFrameHeight, &nStride,
+                portDef.format.video.eColorFormat));
         }
+        buffArray->push(buffer);
     }
 }
 
@@ -273,7 +373,7 @@ void changeStateLoadedtoIdle(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
                              android::Vector<BufferInfo>* iBuffer,
                              android::Vector<BufferInfo>* oBuffer,
                              OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
-                             PortMode* portMode) {
+                             PortMode* portMode, bool allocGrap) {
     android::hardware::media::omx::V1_0::Status status;
     Message msg;
     PortMode defaultPortMode[2], *pm;
@@ -292,14 +392,16 @@ void changeStateLoadedtoIdle(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
     ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT);
 
     // allocate buffers on input port
-    allocatePortBuffers(omxNode, iBuffer, kPortIndexInput, pm[0]);
+    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);
 
     // allocate buffers on output port
-    allocatePortBuffers(omxNode, oBuffer, kPortIndexOutput, pm[1]);
+    ASSERT_NO_FATAL_FAILURE(allocatePortBuffers(
+        omxNode, oBuffer, kPortIndexOutput, pm[1], allocGrap));
 
     // As the ports are populated, check if the state transition is complete
     status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
@@ -439,6 +541,7 @@ void dispatchOutputBuffer(sp<IOmxNode> omxNode,
             status =
                 omxNode->fillBuffer((*buffArray)[bufferIndex].id, t, fenceNh);
             break;
+        case PortMode::PRESET_ANW_BUFFER:
         case PortMode::PRESET_SECURE_BUFFER:
         case PortMode::PRESET_BYTE_BUFFER:
             t.sharedMemory = android::hardware::hidl_memory();
@@ -545,43 +648,45 @@ void testEOS(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
     if (signalEOS) {
         if ((i = getEmptyBufferID(iBuffer)) < iBuffer->size()) {
             // signal an empty buffer with flag set to EOS
-            dispatchInputBuffer(omxNode, iBuffer, i, 0, OMX_BUFFERFLAG_EOS, 0);
+            ASSERT_NO_FATAL_FAILURE(dispatchInputBuffer(omxNode, iBuffer, i, 0,
+                                                        OMX_BUFFERFLAG_EOS, 0));
         } else {
             ASSERT_TRUE(false);
         }
     }
 
-    int timeOut = TIMEOUT_COUNTER;
+    int timeOut = TIMEOUT_COUNTER_PE;
     while (timeOut--) {
         // Dispatch all client owned output buffers to recover remaining frames
         while (1) {
             if ((i = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
-                dispatchOutputBuffer(omxNode, oBuffer, i, pm[1]);
+                ASSERT_NO_FATAL_FAILURE(
+                    dispatchOutputBuffer(omxNode, oBuffer, i, pm[1]));
                 // if dispatch is successful, perhaps there is a latency
                 // in the component. Dont be in a haste to leave. reset timeout
                 // counter
-                timeOut = TIMEOUT_COUNTER;
+                timeOut = TIMEOUT_COUNTER_PE;
             } else {
                 break;
             }
         }
 
         Message msg;
-        status =
-            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
+        status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_PE, iBuffer,
+                                          oBuffer);
         if (status == android::hardware::media::omx::V1_0::Status::OK) {
             if (msg.data.eventData.event == OMX_EventPortSettingsChanged) {
                 if (fptr) {
-                    (*fptr)(omxNode, observer, iBuffer, oBuffer,
-                            kPortIndexInput, kPortIndexOutput, msg, pm[1],
-                            args);
+                    ASSERT_NO_FATAL_FAILURE((*fptr)(
+                        omxNode, observer, iBuffer, oBuffer, kPortIndexInput,
+                        kPortIndexOutput, msg, pm[1], args));
                 } else {
                     // something unexpected happened
-                    EXPECT_TRUE(false);
+                    ASSERT_TRUE(false);
                 }
             } else {
                 // something unexpected happened
-                EXPECT_TRUE(false);
+                ASSERT_TRUE(false);
             }
         }
         if (eosFlag == true) break;
index 0adea14..bec733d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016, The Android Open Source Project
+ * 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.
 #include <media/openmax/OMX_AudioExt.h>
 #include <media/openmax/OMX_VideoExt.h>
 
+/* TIME OUTS (Wait time in dequeueMessage()) */
+
+/* As component is switching states (loaded<->idle<->execute), dequeueMessage()
+ * expects the events to be received within this duration */
 #define DEFAULT_TIMEOUT 100000
-#define TIMEOUT_COUNTER (10000000 / DEFAULT_TIMEOUT)
+/* Time interval between successive Input/Output enqueues */
+#define DEFAULT_TIMEOUT_Q 2000
+/* While the component is amidst a process call, asynchronous commands like
+ * flush, change states can get delayed (at max by process call time). Instead
+ * of waiting on DEFAULT_TIMEOUT, we give an additional leeway. */
+#define DEFAULT_TIMEOUT_PE 500000
+
+/* Breakout Timeout :: 5 sec*/
+#define TIMEOUT_COUNTER_Q (5000000 / DEFAULT_TIMEOUT_Q)
+#define TIMEOUT_COUNTER_PE (5000000 / DEFAULT_TIMEOUT_PE)
 
 /*
  * Random Index used for monkey testing while get/set parameters
@@ -120,13 +133,15 @@ struct CodecObserver : public IOmxObserver {
                 if (it->type ==
                     android::hardware::media::omx::V1_0::Message::Type::EVENT) {
                     *msg = *it;
-                    msgQueue.erase(it);
+                    if (callBack) callBack(*it, nullptr);
+                    it = msgQueue.erase(it);
                     // OMX_EventBufferFlag event is sent when the component has
                     // processed a buffer with its EOS flag set. This event is
                     // not sent by soft omx components. Vendor components can
                     // send this. From IOMX point of view, we will ignore this
                     // event.
-                    if (msg->data.eventData.event == OMX_EventBufferFlag) break;
+                    if (msg->data.eventData.event == OMX_EventBufferFlag)
+                        continue;
                     return ::android::hardware::media::omx::V1_0::Status::OK;
                 } else if (it->type == android::hardware::media::omx::V1_0::
                                            Message::Type::FILL_BUFFER_DONE) {
@@ -137,7 +152,7 @@ struct CodecObserver : public IOmxObserver {
                                 it->data.bufferData.buffer) {
                                 if (callBack) callBack(*it, &(*oBuffers)[i]);
                                 oBuffers->editItemAt(i).owner = client;
-                                msgQueue.erase(it);
+                                it = msgQueue.erase(it);
                                 break;
                             }
                         }
@@ -152,24 +167,22 @@ struct CodecObserver : public IOmxObserver {
                                 it->data.bufferData.buffer) {
                                 if (callBack) callBack(*it, &(*iBuffers)[i]);
                                 iBuffers->editItemAt(i).owner = client;
-                                msgQueue.erase(it);
+                                it = msgQueue.erase(it);
                                 break;
                             }
                         }
                         EXPECT_LE(i, iBuffers->size());
                     }
+                } else {
+                    EXPECT_TRUE(false) << "Received unexpected message";
+                    ++it;
                 }
-                ++it;
             }
-            if (finishBy - android::ALooper::GetNowUs() < 0)
-                return toStatus(android::TIMED_OUT);
-            android::status_t err =
-                (timeoutUs < 0)
-                    ? msgCondition.wait(msgLock)
-                    : msgCondition.waitRelative(
-                          msgLock,
-                          (finishBy - android::ALooper::GetNowUs()) * 1000ll);
-            if (err == android::TIMED_OUT) return toStatus(err);
+            int64_t delayUs = finishBy - android::ALooper::GetNowUs();
+            if (delayUs < 0) return toStatus(android::TIMED_OUT);
+            (timeoutUs < 0)
+                ? msgCondition.wait(msgLock)
+                : msgCondition.waitRelative(msgLock, delayUs * 1000ll);
         }
     }
 
@@ -284,16 +297,21 @@ Return<android::hardware::media::omx::V1_0::Status> setVideoPortFormat(
 Return<android::hardware::media::omx::V1_0::Status> setAudioPortFormat(
     sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE eEncoding);
 
+void allocateBuffer(sp<IOmxNode> omxNode, BufferInfo* buffer, OMX_U32 portIndex,
+                    OMX_U32 nBufferSize, PortMode portMode);
+
 void allocatePortBuffers(sp<IOmxNode> omxNode,
                          android::Vector<BufferInfo>* buffArray,
                          OMX_U32 portIndex,
-                         PortMode portMode = PortMode::PRESET_BYTE_BUFFER);
+                         PortMode portMode = PortMode::PRESET_BYTE_BUFFER,
+                         bool allocGrap = false);
 
 void changeStateLoadedtoIdle(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
                              android::Vector<BufferInfo>* iBuffer,
                              android::Vector<BufferInfo>* oBuffer,
                              OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
-                             PortMode* portMode = nullptr);
+                             PortMode* portMode = nullptr,
+                             bool allocGrap = false);
 
 void changeStateIdletoLoaded(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
                              android::Vector<BufferInfo>* iBuffer,
@@ -322,7 +340,8 @@ void dispatchInputBuffer(sp<IOmxNode> omxNode,
 void flushPorts(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
                 android::Vector<BufferInfo>* iBuffer,
                 android::Vector<BufferInfo>* oBuffer, OMX_U32 kPortIndexInput,
-                OMX_U32 kPortIndexOutput, int64_t timeoutUs = DEFAULT_TIMEOUT);
+                OMX_U32 kPortIndexOutput,
+                int64_t timeoutUs = DEFAULT_TIMEOUT_PE);
 
 typedef void (*portreconfig)(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
                              android::Vector<BufferInfo>* iBuffer,
index fd3210f..f76b6e9 100644 (file)
 
 cc_test {
     name: "VtsHalMediaOmxV1_0TargetComponentTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalMediaOmxV1_0Defaults"],
     srcs: ["VtsHalMediaOmxV1_0TargetComponentTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidlmemory",
-        "libhidltransport",
-        "libhwbinder",
-        "libnativehelper",
-        "libutils",
-        "libstagefright_foundation",
-        "android.hidl.allocator@1.0",
-        "android.hidl.memory@1.0",
-        "android.hardware.media.omx@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase",
-                  "VtsHalMediaOmxV1_0CommonUtil"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
-    include_dirs: [
-        "frameworks/native/include/media/openmax/",
-        "hardware/interfaces/media/omx/1.0/vts/functional/common",
-    ],
 }
 
index 2d91e82..401e54a 100644 (file)
  */
 
 #define LOG_TAG "media_omx_hidl_component_test"
+#ifdef __LP64__
+#define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
+#endif
+
 #include <android-base/logging.h>
 
 #include <android/hardware/media/omx/1.0/IOmx.h>
@@ -145,6 +149,7 @@ class ComponentHidlTest : public ::testing::VtsHalHidlTargetTestBase {
                                this->omxNode = _nl;
                            })
                         .isOk());
+        ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
         ASSERT_NE(omxNode, nullptr);
         ASSERT_NE(gEnv->getRole().empty(), true) << "Invalid Component Role";
         struct StringToClass {
@@ -181,7 +186,7 @@ class ComponentHidlTest : public ::testing::VtsHalHidlTargetTestBase {
                             strlen(gEnv->getComponent().c_str()) - suffixLen,
                         ".secure");
         }
-        if (disableTest) std::cerr << "[          ] Warning !  Test Disabled\n";
+        if (disableTest) std::cout << "[   WARN   ] Test Disabled \n";
     }
 
     virtual void TearDown() override {
@@ -213,9 +218,6 @@ class ComponentHidlTest : public ::testing::VtsHalHidlTargetTestBase {
     }
 };
 
-// Random Index used for monkey testing while get/set parameters
-#define RANDOM_INDEX 1729
-
 void initPortMode(PortMode* pm, bool isSecure,
                   ComponentHidlTest::standardCompClass compClass) {
     pm[0] = PortMode::PRESET_BYTE_BUFFER;
@@ -232,7 +234,6 @@ void initPortMode(PortMode* pm, bool isSecure,
                 break;
         }
     }
-    return;
 }
 
 // test dispatch message API call
@@ -293,7 +294,7 @@ TEST_F(ComponentHidlTest, DISABLED_GetPortIndices) {
 }
 
 // port format enumeration
-TEST_F(ComponentHidlTest, DISABLED_EnumeratePortFormat) {
+TEST_F(ComponentHidlTest, EnumeratePortFormat) {
     description("Test Component on Mandatory Port Parameters (Port Format)");
     if (disableTest) return;
     android::hardware::media::omx::V1_0::Status status;
@@ -374,7 +375,7 @@ TEST_F(ComponentHidlTest, DISABLED_SetDefaultPortParams) {
         kPortIndexOutput = kPortIndexInput + 1;
     }
 
-    for (size_t i = kPortIndexInput; i < kPortIndexOutput; i++) {
+    for (size_t i = kPortIndexInput; i <= kPortIndexOutput; i++) {
         OMX_PARAM_PORTDEFINITIONTYPE portDef;
         status =
             getPortParam(omxNode, OMX_IndexParamPortDefinition, i, &portDef);
@@ -400,28 +401,31 @@ TEST_F(ComponentHidlTest, DISABLED_SetDefaultPortParams) {
             EXPECT_NE(status,
                       ::android::hardware::media::omx::V1_0::Status::OK);
 
-            // Edit Read-Only fields.
+            // Port Direction - Read Only
             portDef = mirror;
             portDef.eDir = static_cast<OMX_DIRTYPE>(RANDOM_INDEX);
             setPortParam(omxNode, OMX_IndexParamPortDefinition, i, &portDef);
             getPortParam(omxNode, OMX_IndexParamPortDefinition, i, &portDef);
+            if (portDef.eDir != mirror.eDir) {
+                std::cerr << "[   ERROR   ] port direction has to be read only "
+                             "but is changeable \n";
+            }
             EXPECT_EQ(portDef.eDir, mirror.eDir);
             setPortParam(omxNode, OMX_IndexParamPortDefinition, i, &mirror);
 
-            portDef = mirror;
-            portDef.nBufferSize >>= 1;
-            setPortParam(omxNode, OMX_IndexParamPortDefinition, i, &portDef);
-            getPortParam(omxNode, OMX_IndexParamPortDefinition, i, &portDef);
-            EXPECT_EQ(portDef.nBufferSize, mirror.nBufferSize);
-            setPortParam(omxNode, OMX_IndexParamPortDefinition, i, &mirror);
-
+            // Port Min BufferCount - Read Only
             portDef = mirror;
             portDef.nBufferCountMin += 1;
             setPortParam(omxNode, OMX_IndexParamPortDefinition, i, &portDef);
             getPortParam(omxNode, OMX_IndexParamPortDefinition, i, &portDef);
+            if (portDef.nBufferCountMin != mirror.nBufferCountMin) {
+                std::cerr << "[   ERROR   ] port Min BufferCount has to be "
+                             "read only  but is changeable \n";
+            }
             EXPECT_EQ(portDef.nBufferCountMin, mirror.nBufferCountMin);
             setPortParam(omxNode, OMX_IndexParamPortDefinition, i, &mirror);
 
+            // Port Actual BufferCount
             portDef = mirror;
             portDef.nBufferCountActual += 1;
             status = setPortParam(omxNode, OMX_IndexParamPortDefinition, i,
@@ -432,20 +436,49 @@ TEST_F(ComponentHidlTest, DISABLED_SetDefaultPortParams) {
                 EXPECT_EQ(portDef.nBufferCountActual,
                           mirror.nBufferCountActual + 1);
             }
+            setPortParam(omxNode, OMX_IndexParamPortDefinition, i, &mirror);
 
+            // Port BufferSize is although read only as per OMX-IL 1.2, android
+            // doesnt abide by this.
+            // Decrease buffer size
             portDef = mirror;
-            portDef.nBufferSize = mirror.nBufferSize << 1;
-            status = setPortParam(omxNode, OMX_IndexParamPortDefinition, i,
-                                  &portDef);
-            if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
-                status = getPortParam(omxNode, OMX_IndexParamPortDefinition, i,
-                                      &portDef);
-                if (portDef.nBufferSize != mirror.nBufferSize) {
-                    std::cout
-                        << "[          ] Warning ! Component input port does "
-                           "not  preserve Read-Only fields \n";
+            OMX_U32 nBufferSize = portDef.nBufferSize >> 1;
+            if (nBufferSize != 0) {
+                if (!strncmp(gEnv->getComponent().c_str(), "OMX.google.", 11)) {
+                    portDef.nBufferSize = nBufferSize;
+                } else {
+                    // Probable alignment requirements of vendor component
+                    portDef.nBufferSize = ALIGN_POWER_OF_TWO(nBufferSize, 12);
+                    nBufferSize = portDef.nBufferSize;
                 }
+            } else {
+                ASSERT_TRUE(false) << "Unexpected buffer size";
             }
+            setPortParam(omxNode, OMX_IndexParamPortDefinition, i, &portDef);
+            getPortParam(omxNode, OMX_IndexParamPortDefinition, i, &portDef);
+            // SPECIAL CASE: For video decoder, allow configuration of input
+            // buffer size even if it is less than minimum requirement and
+            // similarly for encoder allow configuration of output port buffer
+            // size.
+            if ((compClass == video_encoder && i == kPortIndexOutput) ||
+                (compClass == video_decoder && i == kPortIndexInput)) {
+                double dev = (portDef.nBufferSize / (double)nBufferSize);
+                dev -= 1;
+                if (dev < 0 || dev > 0.1) {
+                    std::cerr << "[   ERROR   ] port buffer size deviation "
+                                 "larger than expected \n";
+                }
+            } else {
+                EXPECT_EQ(portDef.nBufferSize, mirror.nBufferSize);
+            }
+            setPortParam(omxNode, OMX_IndexParamPortDefinition, i, &mirror);
+
+            // Increase buffer size
+            portDef = mirror;
+            portDef.nBufferSize = mirror.nBufferSize << 1;
+            setPortParam(omxNode, OMX_IndexParamPortDefinition, i, &portDef);
+            getPortParam(omxNode, OMX_IndexParamPortDefinition, i, &portDef);
+            EXPECT_EQ(portDef.nBufferSize, (mirror.nBufferSize << 1));
         }
     }
 }
@@ -470,8 +503,10 @@ TEST_F(ComponentHidlTest, DISABLED_PopulatePort) {
         portBase = params.nStartPortNumber;
     }
 
-    sp<IAllocator> allocator = IAllocator::getService("ashmem");
-    EXPECT_NE(allocator.get(), nullptr);
+    // set state to idle
+    status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
+                                  OMX_StateIdle);
+    ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
 
     OMX_PARAM_PORTDEFINITIONTYPE portDef;
     status =
@@ -485,30 +520,10 @@ TEST_F(ComponentHidlTest, DISABLED_PopulatePort) {
 
     for (size_t i = 0; i < portDef.nBufferCountActual; i++) {
         BufferInfo buffer;
-        buffer.owner = client;
-        buffer.omxBuffer.type = CodecBuffer::Type::SHARED_MEM;
-        buffer.omxBuffer.attr.preset.rangeOffset = 0;
-        buffer.omxBuffer.attr.preset.rangeLength = 0;
-        bool success = false;
-        allocator->allocate(
-            nBufferSize,
-            [&success, &buffer](bool _s,
-                                ::android::hardware::hidl_memory const& mem) {
-                success = _s;
-                buffer.omxBuffer.sharedMemory = mem;
-            });
-        ASSERT_EQ(success, true);
-        ASSERT_EQ(buffer.omxBuffer.sharedMemory.size(), nBufferSize);
-
-        omxNode->useBuffer(
-            portBase, buffer.omxBuffer,
-            [&status, &buffer](android::hardware::media::omx::V1_0::Status _s,
-                               uint32_t id) {
-                status = _s;
-                buffer.id = id;
-            });
+        ASSERT_NO_FATAL_FAILURE(allocateBuffer(omxNode, &buffer, portBase,
+                                               nBufferSize,
+                                               PortMode::PRESET_BYTE_BUFFER));
         pBuffer.push(buffer);
-        ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
     }
 
     status =
@@ -548,44 +563,52 @@ TEST_F(ComponentHidlTest, Flush) {
     PortMode portMode[2];
     initPortMode(portMode, isSecure, compClass);
     status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
-    EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
     status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
-    EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
 
     // set state to idle
-    changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput, portMode);
+    ASSERT_NO_FATAL_FAILURE(
+        changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
+                                kPortIndexInput, kPortIndexOutput, portMode));
     // set state to executing
-    changeStateIdletoExecute(omxNode, observer);
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
     // dispatch buffers
     for (size_t i = 0; i < oBuffer.size(); i++) {
-        dispatchOutputBuffer(omxNode, &oBuffer, i, portMode[1]);
+        ASSERT_NO_FATAL_FAILURE(
+            dispatchOutputBuffer(omxNode, &oBuffer, i, portMode[1]));
     }
     // flush port
-    flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
-               kPortIndexOutput);
+    ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
+                                       kPortIndexInput, kPortIndexOutput));
+#if 0
     // TODO: Sending empty input buffers is slightly tricky.
     // Components sometimes process input buffers even when output buffers are
     // not dispatched. For instance Parsing sequence header does not require
     // output buffers. In such instances sending 0 size input buffers might
     // make component to send error events. so lets skip this aspect of testing.
     // dispatch buffers
-    //    for (size_t i = 0; i < iBuffer.size(); i++) {
-    //        dispatchInputBuffer(omxNode, &iBuffer, i, 0, 0, 0, portMode[0]);
-    //    }
-    //    // flush ports
-    //    flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
-    //               kPortIndexOutput);
+    for (size_t i = 0; i < iBuffer.size(); i++) {
+        ASSERT_NO_FATAL_FAILURE(
+            dispatchInputBuffer(omxNode, &iBuffer, i, 0, 0, 0, portMode[0]));
+    }
+    // flush ports
+    ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
+                                       kPortIndexInput, kPortIndexOutput));
+#endif
+
     // set state to idle
-    changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
+    ASSERT_NO_FATAL_FAILURE(
+        changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
     // set state to loaded
-    changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput);
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
+                                                    &oBuffer, kPortIndexInput,
+                                                    kPortIndexOutput));
 }
 
-// state transitions test
-TEST_F(ComponentHidlTest, StateTransitions) {
-    description("Test State Transitions Loaded<->Idle<->Execute");
+// Flush test - monkeying
+TEST_F(ComponentHidlTest, Flush_M) {
+    description("Test Flush monkeying");
     if (disableTest) return;
     android::hardware::media::omx::V1_0::Status status;
     uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
@@ -611,33 +634,267 @@ TEST_F(ComponentHidlTest, StateTransitions) {
     PortMode portMode[2];
     initPortMode(portMode, isSecure, compClass);
     status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
+    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
+    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+
+    //    // Flush all ports ; receive error OMX_ErrorIncorrectStateOperation
+    //    status = omxNode->sendCommand(toRawCommandType(OMX_CommandFlush),
+    //    OMX_ALL);
+    //    ASSERT_NE(status, android::hardware::media::omx::V1_0::Status::OK);
+
+    // set state to idle
+    ASSERT_NO_FATAL_FAILURE(
+        changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
+                                kPortIndexInput, kPortIndexOutput, portMode));
+
+    //    // Flush all ports ; receive error OMX_ErrorIncorrectStateOperation
+    //    status = omxNode->sendCommand(toRawCommandType(OMX_CommandFlush),
+    //    OMX_ALL);
+    //    ASSERT_NE(status, android::hardware::media::omx::V1_0::Status::OK);
+
+    // set state to executing
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
+
+    // dispatch buffers
+    for (size_t i = 0; i < oBuffer.size(); i++) {
+        ASSERT_NO_FATAL_FAILURE(
+            dispatchOutputBuffer(omxNode, &oBuffer, i, portMode[1]));
+    }
+
+    //    // flush invalid port, expecting OMX_ErrorBadPortIndex
+    //    status = omxNode->sendCommand(toRawCommandType(OMX_CommandFlush),
+    //                                  RANDOM_INDEX);
+    //    ASSERT_NE(status, android::hardware::media::omx::V1_0::Status::OK);
+
+    // Flush all ports
+    status = omxNode->sendCommand(toRawCommandType(OMX_CommandFlush), OMX_ALL);
+    ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
+
+    for (int j = 0; j < 2; j++) {
+        status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_PE, &iBuffer,
+                                          &oBuffer);
+        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);
+        ASSERT_EQ(msg.data.eventData.data1, OMX_CommandFlush);
+        if (msg.data.eventData.data2 == kPortIndexInput) {
+            // test if client got all its buffers back
+            for (size_t i = 0; i < iBuffer.size(); ++i) {
+                EXPECT_EQ(iBuffer[i].owner, client);
+            }
+        } else if (msg.data.eventData.data2 == kPortIndexOutput) {
+            // test if client got all its buffers back
+            for (size_t i = 0; i < oBuffer.size(); ++i) {
+                EXPECT_EQ(oBuffer[i].owner, client);
+            }
+        } else {
+            EXPECT_TRUE(false) << "Bad port Index";
+        }
+    }
+
+    // SPECIAL CASE: When OMX_ALL is used as argument, Android OMX Core sends
+    // an additional flush event with argument OMX_ALL. This we believe is
+    // not recognized by OMX-IL Spec. So read this event and ignore it
+    status =
+        observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_PE, &iBuffer, &oBuffer);
+    if (status == android::hardware::media::omx::V1_0::Status::OK) {
+        ASSERT_EQ(msg.type, Message::Type::EVENT);
+        ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
+        ASSERT_EQ(msg.data.eventData.data1, OMX_CommandFlush);
+        ASSERT_EQ(msg.data.eventData.data2, OMX_ALL);
+    }
+
+    // set state to idle
+    ASSERT_NO_FATAL_FAILURE(
+        changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
+    // set state to loaded
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
+                                                    &oBuffer, kPortIndexInput,
+                                                    kPortIndexOutput));
+}
+
+// test port mode configuration when the component is in various states
+TEST_F(ComponentHidlTest, PortModeConfig) {
+    description("Test Port Mode Configuration");
+    if (disableTest) return;
+    android::hardware::media::omx::V1_0::Status status;
+    uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
+    Message msg;
+
+    status = setRole(omxNode, gEnv->getRole().c_str());
+    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    OMX_PORT_PARAM_TYPE params;
+    if (compClass == audio_decoder || compClass == audio_encoder) {
+        status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
+    } else {
+        status = getParam(omxNode, OMX_IndexParamVideoInit, &params);
+    }
+    if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
+        ASSERT_EQ(params.nPorts, 2U);
+        kPortIndexInput = params.nStartPortNumber;
+        kPortIndexOutput = kPortIndexInput + 1;
+    }
+
+    android::Vector<BufferInfo> iBuffer, oBuffer;
+
+    // set port mode
+    PortMode portMode[2];
+    initPortMode(portMode, isSecure, compClass);
+    status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
+    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
+    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+
+    // set state to idle
+    ASSERT_NO_FATAL_FAILURE(
+        changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
+                                kPortIndexInput, kPortIndexOutput, portMode));
+    // Only Allow Port Mode configuration in loaded state
+    status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
+    EXPECT_NE(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
+    EXPECT_NE(status, ::android::hardware::media::omx::V1_0::Status::OK);
+
+    // set state to executing
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
+    // Only Allow Port Mode configuration in loaded state
+    status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
+    EXPECT_NE(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
+    EXPECT_NE(status, ::android::hardware::media::omx::V1_0::Status::OK);
+
+    // set state to idle
+    ASSERT_NO_FATAL_FAILURE(
+        changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
+    // set state to loaded
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
+                                                    &oBuffer, kPortIndexInput,
+                                                    kPortIndexOutput));
+
+    status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
     status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+}
+
+// state transitions test
+TEST_F(ComponentHidlTest, StateTransitions) {
+    description("Test State Transitions Loaded<->Idle<->Execute");
+    if (disableTest) return;
+    android::hardware::media::omx::V1_0::Status status;
+    uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
+    OMX_U32 portBase = 0;
+    Message msg;
+    status = setRole(omxNode, gEnv->getRole().c_str());
+    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    OMX_PORT_PARAM_TYPE params;
+    if (compClass == audio_decoder || compClass == audio_encoder) {
+        status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
+    } else {
+        status = getParam(omxNode, OMX_IndexParamVideoInit, &params);
+    }
+    if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
+        ASSERT_EQ(params.nPorts, 2U);
+        portBase = params.nStartPortNumber;
+    }
+    kPortIndexInput = portBase;
+    kPortIndexOutput = portBase + 1;
+
+    android::Vector<BufferInfo> pBuffer[2];
+
+    // set port mode
+    PortMode portMode[2];
+    initPortMode(portMode, isSecure, compClass);
+    status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
+    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
+    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+
+    // set state to idle
+    status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
+                                  OMX_StateIdle);
+    ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
+
+    for (size_t j = portBase; j < portBase + 2; j++) {
+        pBuffer[j - portBase].clear();
 
+        OMX_PARAM_PORTDEFINITIONTYPE def;
+        status = getPortParam(omxNode, OMX_IndexParamPortDefinition, j, &def);
+        ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+
+        for (size_t i = 0; i < def.nBufferCountActual; i++) {
+            // Dont switch states until the ports are populated
+            status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
+                                              &pBuffer[0], &pBuffer[1]);
+            ASSERT_EQ(status,
+                      android::hardware::media::omx::V1_0::Status::TIMED_OUT);
+
+            BufferInfo buffer;
+            ASSERT_NO_FATAL_FAILURE(allocateBuffer(
+                omxNode, &buffer, j, def.nBufferSize, portMode[j - portBase]));
+            pBuffer[j - portBase].push(buffer);
+        }
+    }
+
+    // As the ports are populated, check if the state transition is complete
+    status = observer->dequeueMessage(&msg, DEFAULT_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.event, OMX_EventCmdComplete);
+    ASSERT_EQ(msg.data.eventData.data1, OMX_CommandStateSet);
+    ASSERT_EQ(msg.data.eventData.data2, OMX_StateIdle);
+
+    // set state to executing
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
+    // dispatch buffers
+    for (size_t i = 0; i < pBuffer[1].size(); i++) {
+        ASSERT_NO_FATAL_FAILURE(
+            dispatchOutputBuffer(omxNode, &pBuffer[1], i, portMode[1]));
+    }
     // set state to idle
-    changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput, portMode);
+    ASSERT_NO_FATAL_FAILURE(
+        changeStateExecutetoIdle(omxNode, observer, &pBuffer[0], &pBuffer[1]));
+#if 0
     // set state to executing
-    changeStateIdletoExecute(omxNode, observer);
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
+    // TODO: Sending empty input buffers is slightly tricky.
     // dispatch buffers
-    for (size_t i = 0; i < oBuffer.size(); i++) {
-        dispatchOutputBuffer(omxNode, &oBuffer, i, portMode[1]);
+    for (size_t i = 0; i < pBuffer[0].size(); i++) {
+        ASSERT_NO_FATAL_FAILURE(
+            dispatchInputBuffer(omxNode, &pBuffer[0], i, 0, 0, 0, portMode[0]));
     }
     // set state to idle
-    changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
-    //    // set state to executing
-    //    changeStateIdletoExecute(omxNode, observer);
-    //    // TODO: Sending empty input buffers is slightly tricky.
-    //    // dispatch buffers
-    //    for (size_t i = 0; i < iBuffer.size(); i++) {
-    //        dispatchInputBuffer(omxNode, &iBuffer, i, 0, 0, 0, portMode[0]);
-    //    }
-    //    // set state to idle
-    //    changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
+    ASSERT_NO_FATAL_FAILURE(
+        changeStateExecutetoIdle(omxNode, observer, &pBuffer[0], &pBuffer[1]));
+#endif
+
     // set state to loaded
-    changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput);
+    status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
+                                  OMX_StateLoaded);
+    ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
+
+    for (size_t j = portBase; j < portBase + 2; j++) {
+        for (size_t i = 0; i < pBuffer[j].size(); ++i) {
+            // Dont switch states until the ports are populated
+            status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
+                                              &pBuffer[0], &pBuffer[1]);
+            ASSERT_EQ(status,
+                      android::hardware::media::omx::V1_0::Status::TIMED_OUT);
+
+            status = omxNode->freeBuffer(j, pBuffer[j][i].id);
+            ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
+        }
+    }
+
+    status = observer->dequeueMessage(&msg, DEFAULT_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.event, OMX_EventCmdComplete);
+    ASSERT_EQ(msg.data.eventData.data1, OMX_CommandStateSet);
+    ASSERT_EQ(msg.data.eventData.data2, OMX_StateLoaded);
 }
 
 // state transitions test - monkeying
@@ -675,8 +932,9 @@ TEST_F(ComponentHidlTest, DISABLED_StateTransitions_M) {
     EXPECT_NE(status, android::hardware::media::omx::V1_0::Status::OK);
 
     // set state to idle
-    changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput);
+    ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(omxNode, observer, &iBuffer,
+                                                    &oBuffer, kPortIndexInput,
+                                                    kPortIndexOutput));
 
     // set state to idle ; receive error OMX_ErrorSameState
     status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
@@ -684,7 +942,7 @@ TEST_F(ComponentHidlTest, DISABLED_StateTransitions_M) {
     EXPECT_NE(status, android::hardware::media::omx::V1_0::Status::OK);
 
     // set state to executing
-    changeStateIdletoExecute(omxNode, observer);
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
 
     // set state to executing ; receive error OMX_ErrorSameState
     status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
@@ -696,12 +954,13 @@ TEST_F(ComponentHidlTest, DISABLED_StateTransitions_M) {
                                   OMX_StateLoaded);
     EXPECT_NE(status, android::hardware::media::omx::V1_0::Status::OK);
 
-    // set state to Idle
-    changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
-
-    // set state to Loaded
-    changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput);
+    // set state to idle
+    ASSERT_NO_FATAL_FAILURE(
+        changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
+    // set state to loaded
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
+                                                    &oBuffer, kPortIndexInput,
+                                                    kPortIndexOutput));
 }
 
 // port enable disable test
@@ -784,14 +1043,14 @@ TEST_F(ComponentHidlTest, PortEnableDisable_Idle) {
     PortMode portMode[2];
     initPortMode(portMode, isSecure, compClass);
     status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
-    EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
     status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
-    EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
 
     // set state to idle
-    changeStateLoadedtoIdle(omxNode, observer, &pBuffer[0], &pBuffer[1],
-                            kPortIndexInput, kPortIndexOutput, portMode);
-
+    ASSERT_NO_FATAL_FAILURE(
+        changeStateLoadedtoIdle(omxNode, observer, &pBuffer[0], &pBuffer[1],
+                                kPortIndexInput, kPortIndexOutput, portMode));
     for (size_t i = portBase; i < portBase + 2; i++) {
         status =
             omxNode->sendCommand(toRawCommandType(OMX_CommandPortDisable), i);
@@ -839,8 +1098,8 @@ TEST_F(ComponentHidlTest, PortEnableDisable_Idle) {
             ASSERT_EQ(status,
                       android::hardware::media::omx::V1_0::Status::TIMED_OUT);
 
-            allocatePortBuffers(omxNode, &pBuffer[i - portBase], i,
-                                portMode[i - portBase]);
+            ASSERT_NO_FATAL_FAILURE(allocatePortBuffers(
+                omxNode, &pBuffer[i - portBase], i, portMode[i - portBase]));
             status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
                                               &pBuffer[0], &pBuffer[1]);
             ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
@@ -854,8 +1113,9 @@ TEST_F(ComponentHidlTest, PortEnableDisable_Idle) {
     }
 
     // set state to Loaded
-    changeStateIdletoLoaded(omxNode, observer, &pBuffer[0], &pBuffer[1],
-                            kPortIndexInput, kPortIndexOutput);
+    ASSERT_NO_FATAL_FAILURE(
+        changeStateIdletoLoaded(omxNode, observer, &pBuffer[0], &pBuffer[1],
+                                kPortIndexInput, kPortIndexOutput));
 }
 
 // port enable disable test
@@ -888,20 +1148,20 @@ TEST_F(ComponentHidlTest, PortEnableDisable_Execute) {
     PortMode portMode[2];
     initPortMode(portMode, isSecure, compClass);
     status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
-    EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
     status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
-    EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
 
     // set state to idle
-    changeStateLoadedtoIdle(omxNode, observer, &pBuffer[0], &pBuffer[1],
-                            kPortIndexInput, kPortIndexOutput, portMode);
-
+    ASSERT_NO_FATAL_FAILURE(
+        changeStateLoadedtoIdle(omxNode, observer, &pBuffer[0], &pBuffer[1],
+                                kPortIndexInput, kPortIndexOutput, portMode));
     // set state to executing
-    changeStateIdletoExecute(omxNode, observer);
-
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
     // dispatch buffers
     for (size_t i = 0; i < pBuffer[1].size(); i++) {
-        dispatchOutputBuffer(omxNode, &pBuffer[1], i, portMode[1]);
+        ASSERT_NO_FATAL_FAILURE(
+            dispatchOutputBuffer(omxNode, &pBuffer[1], i, portMode[1]));
     }
 
     for (size_t i = portBase; i < portBase + 2; i++) {
@@ -954,8 +1214,8 @@ TEST_F(ComponentHidlTest, PortEnableDisable_Execute) {
             ASSERT_EQ(status,
                       android::hardware::media::omx::V1_0::Status::TIMED_OUT);
 
-            allocatePortBuffers(omxNode, &pBuffer[i - portBase], i,
-                                portMode[i - portBase]);
+            ASSERT_NO_FATAL_FAILURE(allocatePortBuffers(
+                omxNode, &pBuffer[i - portBase], i, portMode[i - portBase]));
             status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
                                               &pBuffer[0], &pBuffer[1]);
             ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
@@ -968,12 +1228,13 @@ TEST_F(ComponentHidlTest, PortEnableDisable_Execute) {
         }
     }
 
-    // set state to Idle
-    changeStateExecutetoIdle(omxNode, observer, &pBuffer[0], &pBuffer[1]);
-
-    // set state to Loaded
-    changeStateIdletoLoaded(omxNode, observer, &pBuffer[0], &pBuffer[1],
-                            kPortIndexInput, kPortIndexOutput);
+    // set state to idle
+    ASSERT_NO_FATAL_FAILURE(
+        changeStateExecutetoIdle(omxNode, observer, &pBuffer[0], &pBuffer[1]));
+    // set state to loaded
+    ASSERT_NO_FATAL_FAILURE(
+        changeStateIdletoLoaded(omxNode, observer, &pBuffer[0], &pBuffer[1],
+                                kPortIndexInput, kPortIndexOutput));
 }
 
 // port enable disable test - monkeying
index e24b79b..4a45e69 100644 (file)
 
 cc_test {
     name: "VtsHalMediaOmxV1_0TargetMasterTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalMediaOmxV1_0Defaults"],
     srcs: ["VtsHalMediaOmxV1_0TargetMasterTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
-        "libnativehelper",
-        "libutils",
-        "android.hidl.allocator@1.0",
-        "android.hidl.memory@1.0",
-        "android.hardware.media.omx@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
-    include_dirs: [
-        "frameworks/native/include/media/openmax/",
-        "hardware/interfaces/media/omx/1.0/vts/functional/common",
-    ],
 }
 
index e8f5f77..5a31d69 100644 (file)
  */
 
 #define LOG_TAG "media_omx_hidl_master_test"
+#ifdef __LP64__
+#define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
+#endif
+
 #include <android-base/logging.h>
 
 #include <android/hardware/media/omx/1.0/IOmx.h>
@@ -146,6 +150,7 @@ TEST_F(MasterHidlTest, ListServiceAttr) {
                         attributes = _nl;
                     })
                     .isOk());
+    ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
     if (attributes.size() == 0) ALOGV("Warning, Attribute list empty");
 }
 
@@ -182,6 +187,7 @@ TEST_F(MasterHidlTest, ListNodes) {
                nodeList = _nl;
            })
             .isOk());
+    ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
     if (nodeList.size() == 0)
         ALOGV("Warning, ComponentInfo list empty");
     else {
@@ -200,6 +206,7 @@ TEST_F(MasterHidlTest, ListNodes) {
                            omxNode = _nl;
                        })
                     .isOk());
+            ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
             if (omxNode == nullptr) {
                 isPass = false;
                 std::cerr << "[    !OK   ] " << nodeList[i].mName.c_str()
index 4e94f3b..f0da2b3 100644 (file)
 
 cc_test {
     name: "VtsHalMediaOmxV1_0TargetVideoDecTest",
-    defaults: ["hidl_defaults"],
-    srcs: ["VtsHalMediaOmxV1_0TargetVideoDecTest.cpp",
-           "media_video_hidl_test_common.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidlmemory",
-        "libhidltransport",
-        "libhwbinder",
-        "libnativehelper",
-        "libutils",
-        "libstagefright_foundation",
-        "android.hidl.allocator@1.0",
-        "android.hidl.memory@1.0",
-        "android.hardware.media.omx@1.0",
-        "android.hardware.graphics.allocator@2.0",
-        "android.hardware.graphics.mapper@2.0",
-        "android.hardware.graphics.common@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase",
-                  "VtsHalMediaOmxV1_0CommonUtil"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
-    include_dirs: [
-        "frameworks/native/include/media/openmax/",
-        "hardware/interfaces/media/omx/1.0/vts/functional/common",
+    defaults: ["VtsHalMediaOmxV1_0Defaults"],
+    srcs: [
+        "VtsHalMediaOmxV1_0TargetVideoDecTest.cpp",
+        "media_video_hidl_test_common.cpp"
     ],
 }
 
 cc_test {
     name: "VtsHalMediaOmxV1_0TargetVideoEncTest",
-    defaults: ["hidl_defaults"],
-    srcs: ["VtsHalMediaOmxV1_0TargetVideoEncTest.cpp",
-           "media_video_hidl_test_common.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidlmemory",
-        "libhidltransport",
-        "libhwbinder",
-        "libnativehelper",
-        "libnativewindow",
-        "libutils",
-        "libstagefright_foundation",
-        "android.hidl.allocator@1.0",
-        "android.hidl.memory@1.0",
-        "android.hardware.media.omx@1.0",
-        "android.hardware.graphics.bufferqueue@1.0",
-        "android.hardware.graphics.mapper@2.0",
+    defaults: ["VtsHalMediaOmxV1_0Defaults"],
+    srcs: [
+        "VtsHalMediaOmxV1_0TargetVideoEncTest.cpp",
+        "media_video_hidl_test_common.cpp"
     ],
-    static_libs: ["VtsHalHidlTargetTestBase",
-                  "VtsHalMediaOmxV1_0CommonUtil"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
-    include_dirs: [
-        "frameworks/native/include/media/openmax/",
-        "hardware/interfaces/media/omx/1.0/vts/functional/common",
+    static_libs: [
+        "libnativewindow",
     ],
 }
index ff031dd..667c2e1 100644 (file)
  */
 
 #define LOG_TAG "media_omx_hidl_video_dec_test"
+#ifdef __LP64__
+#define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
+#endif
+
 #include <android-base/logging.h>
 
-#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-#include <android/hardware/graphics/mapper/2.0/types.h>
 #include <android/hardware/media/omx/1.0/IOmx.h>
 #include <android/hardware/media/omx/1.0/IOmxNode.h>
 #include <android/hardware/media/omx/1.0/IOmxObserver.h>
 #include <android/hidl/allocator/1.0/IAllocator.h>
 #include <android/hidl/memory/1.0/IMapper.h>
 #include <android/hidl/memory/1.0/IMemory.h>
-#include <cutils/atomic.h>
 
-using ::android::hardware::graphics::common::V1_0::BufferUsage;
-using ::android::hardware::graphics::common::V1_0::PixelFormat;
 using ::android::hardware::media::omx::V1_0::IOmx;
 using ::android::hardware::media::omx::V1_0::IOmxObserver;
 using ::android::hardware::media::omx::V1_0::IOmxNode;
@@ -168,6 +166,7 @@ class VideoDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
                                this->omxNode = _nl;
                            })
                         .isOk());
+        ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
         ASSERT_NE(omxNode, nullptr);
         ASSERT_NE(gEnv->getRole().empty(), true) << "Invalid Component Role";
         struct StringToName {
@@ -219,6 +218,7 @@ class VideoDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
         timestampUs = 0;
         timestampDevTest = false;
         isSecure = false;
+        portSettingsChange = false;
         size_t suffixLen = strlen(".secure");
         if (strlen(gEnv->getComponent().c_str()) >= suffixLen) {
             isSecure =
@@ -227,7 +227,7 @@ class VideoDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
                         ".secure");
         }
         if (isSecure) disableTest = true;
-        if (disableTest) std::cout << "[          ] Warning !  Test Disabled\n";
+        if (disableTest) std::cout << "[   WARN   ] Test Disabled \n";
     }
 
     virtual void TearDown() override {
@@ -271,9 +271,8 @@ class VideoDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
                             EXPECT_EQ(tsHit, true)
                                 << "TimeStamp not recognized";
                         } else {
-                            std::cout
-                                << "[          ] Warning ! Received non-zero "
-                                   "output / TimeStamp not recognized \n";
+                            std::cout << "[   INFO   ] Received non-zero "
+                                         "output / TimeStamp not recognized \n";
                         }
                     }
                 }
@@ -295,6 +294,13 @@ class VideoDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
                 }
 #endif
             }
+        } else if (msg.type == Message::Type::EVENT) {
+            if (msg.data.eventData.event == OMX_EventPortSettingsChanged) {
+                if ((msg.data.eventData.data2 == OMX_IndexParamPortDefinition ||
+                     msg.data.eventData.data2 == 0)) {
+                    portSettingsChange = true;
+                }
+            }
         }
     }
 
@@ -322,6 +328,7 @@ class VideoDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
     ::android::List<uint64_t> timestampUslist;
     bool timestampDevTest;
     bool isSecure;
+    bool portSettingsChange;
 
    protected:
     static void description(const std::string& description) {
@@ -369,122 +376,61 @@ void getInputChannelInfo(sp<IOmxNode> omxNode, OMX_U32 kPortIndexInput,
     }
 }
 
+// number of elementary streams per component
+#define STREAM_COUNT 2
 // LookUpTable of clips and metadata for component testing
 void GetURLForComponent(VideoDecHidlTest::standardComp comp, char* mURL,
-                        char* info) {
+                        char* info, size_t streamIndex = 1) {
     struct CompToURL {
         VideoDecHidlTest::standardComp comp;
-        const char* mURL;
-        const char* info;
+        const char mURL[STREAM_COUNT][512];
+        const char info[STREAM_COUNT][512];
     };
+    ASSERT_TRUE(streamIndex < STREAM_COUNT);
+
     static const CompToURL kCompToURL[] = {
         {VideoDecHidlTest::standardComp::avc,
-         "bbb_avc_1920x1080_5000kbps_30fps.h264",
-         "bbb_avc_1920x1080_5000kbps_30fps.info"},
+         {"bbb_avc_176x144_300kbps_60fps.h264",
+          "bbb_avc_1920x1080_5000kbps_30fps.h264"},
+         {"bbb_avc_176x144_300kbps_60fps.info",
+          "bbb_avc_1920x1080_5000kbps_30fps.info"}},
         {VideoDecHidlTest::standardComp::hevc,
-         "bbb_hevc_640x360_1600kbps_30fps.hevc",
-         "bbb_hevc_640x360_1600kbps_30fps.info"},
+         {"bbb_hevc_176x144_176kbps_60fps.hevc",
+          "bbb_hevc_640x360_1600kbps_30fps.hevc"},
+         {"bbb_hevc_176x144_176kbps_60fps.info",
+          "bbb_hevc_640x360_1600kbps_30fps.info"}},
         {VideoDecHidlTest::standardComp::mpeg2,
-         "bbb_mpeg2_176x144_105kbps_25fps.m2v",
-         "bbb_mpeg2_176x144_105kbps_25fps.info"},
+         {"bbb_mpeg2_176x144_105kbps_25fps.m2v",
+          "bbb_mpeg2_352x288_1mbps_60fps.m2v"},
+         {"bbb_mpeg2_176x144_105kbps_25fps.info",
+          "bbb_mpeg2_352x288_1mbps_60fps.info"}},
         {VideoDecHidlTest::standardComp::h263,
-         "bbb_h263_352x288_300kbps_12fps.h263",
-         "bbb_h263_352x288_300kbps_12fps.info"},
+         {"", "bbb_h263_352x288_300kbps_12fps.h263"},
+         {"", "bbb_h263_352x288_300kbps_12fps.info"}},
         {VideoDecHidlTest::standardComp::mpeg4,
-         "bbb_mpeg4_1280x720_1000kbps_25fps.m4v",
-         "bbb_mpeg4_1280x720_1000kbps_25fps.info"},
-        {VideoDecHidlTest::standardComp::vp8, "bbb_vp8_640x360_2mbps_30fps.vp8",
-         "bbb_vp8_640x360_2mbps_30fps.info"},
+         {"", "bbb_mpeg4_1280x720_1000kbps_25fps.m4v"},
+         {"", "bbb_mpeg4_1280x720_1000kbps_25fps.info"}},
+        {VideoDecHidlTest::standardComp::vp8,
+         {"bbb_vp8_176x144_240kbps_60fps.vp8",
+          "bbb_vp8_640x360_2mbps_30fps.vp8"},
+         {"bbb_vp8_176x144_240kbps_60fps.info",
+          "bbb_vp8_640x360_2mbps_30fps.info"}},
         {VideoDecHidlTest::standardComp::vp9,
-         "bbb_vp9_640x360_1600kbps_30fps.vp9",
-         "bbb_vp9_640x360_1600kbps_30fps.info"},
+         {"bbb_vp9_176x144_285kbps_60fps.vp9",
+          "bbb_vp9_640x360_1600kbps_30fps.vp9"},
+         {"bbb_vp9_176x144_285kbps_60fps.info",
+          "bbb_vp9_640x360_1600kbps_30fps.info"}},
     };
 
     for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) {
         if (kCompToURL[i].comp == comp) {
-            strcat(mURL, kCompToURL[i].mURL);
-            strcat(info, kCompToURL[i].info);
+            strcat(mURL, kCompToURL[i].mURL[streamIndex]);
+            strcat(info, kCompToURL[i].info[streamIndex]);
             return;
         }
     }
 }
 
-void allocateGraphicBuffers(sp<IOmxNode> omxNode, OMX_U32 portIndex,
-                            android::Vector<BufferInfo>* buffArray,
-                            uint32_t nFrameWidth, uint32_t nFrameHeight,
-                            int32_t* nStride, int format, uint32_t count) {
-    android::hardware::media::omx::V1_0::Status status;
-    sp<android::hardware::graphics::allocator::V2_0::IAllocator> allocator =
-        android::hardware::graphics::allocator::V2_0::IAllocator::getService();
-    ASSERT_NE(nullptr, allocator.get());
-
-    sp<android::hardware::graphics::mapper::V2_0::IMapper> mapper =
-        android::hardware::graphics::mapper::V2_0::IMapper::getService();
-    ASSERT_NE(mapper.get(), nullptr);
-
-    android::hardware::graphics::mapper::V2_0::IMapper::BufferDescriptorInfo
-        descriptorInfo;
-    uint32_t usage;
-
-    descriptorInfo.width = nFrameWidth;
-    descriptorInfo.height = nFrameHeight;
-    descriptorInfo.layerCount = 1;
-    descriptorInfo.format = static_cast<PixelFormat>(format);
-    descriptorInfo.usage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN);
-    omxNode->getGraphicBufferUsage(
-        portIndex,
-        [&status, &usage](android::hardware::media::omx::V1_0::Status _s,
-                          uint32_t _n1) {
-            status = _s;
-            usage = _n1;
-        });
-    if (status == android::hardware::media::omx::V1_0::Status::OK) {
-        descriptorInfo.usage |= usage;
-    }
-
-    ::android::hardware::hidl_vec<uint32_t> descriptor;
-    android::hardware::graphics::mapper::V2_0::Error error;
-    mapper->createDescriptor(
-        descriptorInfo, [&error, &descriptor](
-                            android::hardware::graphics::mapper::V2_0::Error _s,
-                            ::android::hardware::hidl_vec<uint32_t> _n1) {
-            error = _s;
-            descriptor = _n1;
-        });
-    EXPECT_EQ(error, android::hardware::graphics::mapper::V2_0::Error::NONE);
-
-    EXPECT_EQ(buffArray->size(), count);
-
-    static volatile int32_t nextId = 0;
-    uint64_t id = static_cast<uint64_t>(getpid()) << 32;
-    allocator->allocate(
-        descriptor, count,
-        [&](android::hardware::graphics::mapper::V2_0::Error _s, uint32_t _n1,
-            const ::android::hardware::hidl_vec<
-                ::android::hardware::hidl_handle>& _n2) {
-            ASSERT_EQ(android::hardware::graphics::mapper::V2_0::Error::NONE,
-                      _s);
-            *nStride = _n1;
-            ASSERT_EQ(count, _n2.size());
-            for (uint32_t i = 0; i < count; i++) {
-                buffArray->editItemAt(i).omxBuffer.nativeHandle = _n2[i];
-                buffArray->editItemAt(i).omxBuffer.attr.anwBuffer.width =
-                    nFrameWidth;
-                buffArray->editItemAt(i).omxBuffer.attr.anwBuffer.height =
-                    nFrameHeight;
-                buffArray->editItemAt(i).omxBuffer.attr.anwBuffer.stride = _n1;
-                buffArray->editItemAt(i).omxBuffer.attr.anwBuffer.format =
-                    descriptorInfo.format;
-                buffArray->editItemAt(i).omxBuffer.attr.anwBuffer.usage =
-                    descriptorInfo.usage;
-                buffArray->editItemAt(i).omxBuffer.attr.anwBuffer.layerCount =
-                    descriptorInfo.layerCount;
-                buffArray->editItemAt(i).omxBuffer.attr.anwBuffer.id =
-                    id | static_cast<uint32_t>(android_atomic_inc(&nextId));
-            }
-        });
-}
-
 // port settings reconfiguration during runtime. reconfigures frame dimensions
 void portReconfiguration(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
                          android::Vector<BufferInfo>* iBuffer,
@@ -553,8 +499,7 @@ void portReconfiguration(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
                                     nFrameWidth, nFrameHeight, 0, xFramerate);
 
                 // If you can disable a port, then you should be able to
-                // enable
-                // it as well
+                // enable it as well
                 status = omxNode->sendCommand(
                     toRawCommandType(OMX_CommandPortEnable), kPortIndexOutput);
                 ASSERT_EQ(status,
@@ -567,23 +512,8 @@ void portReconfiguration(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
                     status,
                     android::hardware::media::omx::V1_0::Status::TIMED_OUT);
 
-                allocatePortBuffers(omxNode, oBuffer, kPortIndexOutput,
-                                    oPortMode);
-                if (oPortMode != PortMode::PRESET_BYTE_BUFFER) {
-                    OMX_PARAM_PORTDEFINITIONTYPE portDef;
-
-                    status = getPortParam(omxNode, OMX_IndexParamPortDefinition,
-                                          kPortIndexOutput, &portDef);
-                    ASSERT_EQ(
-                        status,
-                        ::android::hardware::media::omx::V1_0::Status::OK);
-                    allocateGraphicBuffers(omxNode, kPortIndexOutput, oBuffer,
-                                           portDef.format.video.nFrameWidth,
-                                           portDef.format.video.nFrameHeight,
-                                           &portDef.format.video.nStride,
-                                           portDef.format.video.eColorFormat,
-                                           portDef.nBufferCountActual);
-                }
+                ASSERT_NO_FATAL_FAILURE(allocatePortBuffers(
+                    omxNode, oBuffer, kPortIndexOutput, oPortMode, true));
                 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
                                                   iBuffer, oBuffer);
                 ASSERT_EQ(status,
@@ -604,23 +534,24 @@ void portReconfiguration(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
 
                 // dispatch output buffers
                 for (size_t i = 0; i < oBuffer->size(); i++) {
-                    dispatchOutputBuffer(omxNode, oBuffer, i, oPortMode);
+                    ASSERT_NO_FATAL_FAILURE(
+                        dispatchOutputBuffer(omxNode, oBuffer, i, oPortMode));
                 }
             } else {
                 ASSERT_TRUE(false);
             }
         } else if (msg.data.eventData.data2 ==
                    OMX_IndexConfigCommonOutputCrop) {
-            std::cout << "[          ] Warning ! OMX_EventPortSettingsChanged/ "
+            std::cout << "[   INFO   ] OMX_EventPortSettingsChanged/ "
                          "OMX_IndexConfigCommonOutputCrop not handled \n";
         } else if (msg.data.eventData.data2 == OMX_IndexVendorStartUnused + 3) {
-            std::cout << "[          ] Warning ! OMX_EventPortSettingsChanged/ "
+            std::cout << "[   INFO   ] OMX_EventPortSettingsChanged/ "
                          "kDescribeColorAspectsIndex not handled \n";
         }
     } else if (msg.data.eventData.event == OMX_EventError) {
-        std::cout << "[          ] Warning ! OMX_EventError/ "
+        std::cerr << "[   ERROR   ] OMX_EventError/ "
                      "Decode Frame Call might be failed \n";
-        return;
+        ASSERT_TRUE(false);
     } else {
         // something unexpected happened
         ASSERT_TRUE(false);
@@ -635,17 +566,17 @@ void waitOnInputConsumption(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
                             PortMode oPortMode) {
     android::hardware::media::omx::V1_0::Status status;
     Message msg;
-    int timeOut = TIMEOUT_COUNTER;
+    int timeOut = TIMEOUT_COUNTER_Q;
 
     while (timeOut--) {
         size_t i = 0;
         status =
-            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
+            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
         if (status == android::hardware::media::omx::V1_0::Status::OK) {
-            EXPECT_EQ(msg.type, Message::Type::EVENT);
-            portReconfiguration(omxNode, observer, iBuffer, oBuffer,
-                                kPortIndexInput, kPortIndexOutput, msg,
-                                oPortMode, nullptr);
+            ASSERT_EQ(msg.type, Message::Type::EVENT);
+            ASSERT_NO_FATAL_FAILURE(portReconfiguration(
+                omxNode, observer, iBuffer, oBuffer, kPortIndexInput,
+                kPortIndexOutput, msg, oPortMode, nullptr));
         }
         // status == TIMED_OUT, it could be due to process time being large
         // than DEFAULT_TIMEOUT or component needs output buffers to start
@@ -658,9 +589,10 @@ void waitOnInputConsumption(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
         // Dispatch an output buffer assuming outQueue.empty() is true
         size_t index;
         if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
-            dispatchOutputBuffer(omxNode, oBuffer, index, oPortMode);
+            ASSERT_NO_FATAL_FAILURE(
+                dispatchOutputBuffer(omxNode, oBuffer, index, oPortMode));
+            timeOut = TIMEOUT_COUNTER_Q;
         }
-        timeOut--;
     }
 }
 
@@ -674,50 +606,27 @@ void decodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
                    bool signalEOS = true) {
     android::hardware::media::omx::V1_0::Status status;
     Message msg;
-
-    // dispatch output buffers
-    for (size_t i = 0; i < oBuffer->size(); i++) {
-        dispatchOutputBuffer(omxNode, oBuffer, i, oPortMode);
-    }
-    // dispatch input buffers
+    size_t index;
     uint32_t flags = 0;
     int frameID = offset;
-    for (size_t i = 0; (i < iBuffer->size()) && (frameID < (int)Info->size()) &&
-                       (frameID < (offset + range));
-         i++) {
-        char* ipBuffer = static_cast<char*>(
-            static_cast<void*>((*iBuffer)[i].mMemory->getPointer()));
-        ASSERT_LE((*Info)[frameID].bytesCount,
-                  static_cast<int>((*iBuffer)[i].mMemory->getSize()));
-        eleStream.read(ipBuffer, (*Info)[frameID].bytesCount);
-        ASSERT_EQ(eleStream.gcount(), (*Info)[frameID].bytesCount);
-        flags = (*Info)[frameID].flags;
-        if (signalEOS && ((frameID == (int)Info->size() - 1) ||
-                          (frameID == (offset + range - 1))))
-            flags |= OMX_BUFFERFLAG_EOS;
-        dispatchInputBuffer(omxNode, iBuffer, i, (*Info)[frameID].bytesCount,
-                            flags, (*Info)[frameID].timestamp);
-        frameID++;
-    }
+    int timeOut = TIMEOUT_COUNTER_Q;
+    bool iQueued, oQueued;
 
-    int timeOut = TIMEOUT_COUNTER;
-    bool stall = false;
     while (1) {
+        iQueued = oQueued = false;
         status =
-            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
-
+            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
         // Port Reconfiguration
         if (status == android::hardware::media::omx::V1_0::Status::OK &&
             msg.type == Message::Type::EVENT) {
-            portReconfiguration(omxNode, observer, iBuffer, oBuffer,
-                                kPortIndexInput, kPortIndexOutput, msg,
-                                oPortMode, nullptr);
+            ASSERT_NO_FATAL_FAILURE(portReconfiguration(
+                omxNode, observer, iBuffer, oBuffer, kPortIndexInput,
+                kPortIndexOutput, msg, oPortMode, nullptr));
         }
 
         if (frameID == (int)Info->size() || frameID == (offset + range)) break;
 
         // Dispatch input buffer
-        size_t index = 0;
         if ((index = getEmptyBufferID(iBuffer)) < iBuffer->size()) {
             char* ipBuffer = static_cast<char*>(
                 static_cast<void*>((*iBuffer)[index].mMemory->getPointer()));
@@ -726,28 +635,33 @@ void decodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
             eleStream.read(ipBuffer, (*Info)[frameID].bytesCount);
             ASSERT_EQ(eleStream.gcount(), (*Info)[frameID].bytesCount);
             flags = (*Info)[frameID].flags;
+            // Indicate to omx core that the buffer contains a full frame worth
+            // of data
+            flags |= OMX_BUFFERFLAG_ENDOFFRAME;
+            // Indicate the omx core that this is the last buffer it needs to
+            // process
             if (signalEOS && ((frameID == (int)Info->size() - 1) ||
                               (frameID == (offset + range - 1))))
                 flags |= OMX_BUFFERFLAG_EOS;
-            dispatchInputBuffer(omxNode, iBuffer, index,
-                                (*Info)[frameID].bytesCount, flags,
-                                (*Info)[frameID].timestamp);
+            ASSERT_NO_FATAL_FAILURE(dispatchInputBuffer(
+                omxNode, iBuffer, index, (*Info)[frameID].bytesCount, flags,
+                (*Info)[frameID].timestamp));
             frameID++;
-            stall = false;
-        } else
-            stall = true;
+            iQueued = true;
+        }
+        // Dispatch output buffer
         if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
-            dispatchOutputBuffer(omxNode, oBuffer, index, oPortMode);
-            stall = false;
-        } else
-            stall = true;
-        if (stall)
-            timeOut--;
+            ASSERT_NO_FATAL_FAILURE(
+                dispatchOutputBuffer(omxNode, oBuffer, index, oPortMode));
+            oQueued = true;
+        }
+        // Reset Counters when either input or output buffer is dispatched
+        if (iQueued || oQueued)
+            timeOut = TIMEOUT_COUNTER_Q;
         else
-            timeOut = TIMEOUT_COUNTER;
+            timeOut--;
         if (timeOut == 0) {
-            EXPECT_TRUE(false) << "Wait on Input/Output is found indefinite";
-            break;
+            ASSERT_TRUE(false) << "Wait on Input/Output is found indefinite";
         }
     }
 }
@@ -840,7 +754,7 @@ void getDefaultColorFormat(sp<IOmxNode> omxNode, OMX_U32 kPortIndexOutput,
     OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat;
     *eColorFormat = OMX_COLOR_FormatUnused;
     portFormat.nIndex = 0;
-    while (1) {
+    while (portFormat.nIndex < 512) {
         status = getPortParam(omxNode, OMX_IndexParamVideoPortFormat,
                               kPortIndexOutput, &portFormat);
         if (status != ::android::hardware::media::omx::V1_0::Status::OK) break;
@@ -854,7 +768,9 @@ void getDefaultColorFormat(sp<IOmxNode> omxNode, OMX_U32 kPortIndexOutput,
             break;
         }
         if (OMX_COLOR_FormatYUV420SemiPlanar == portFormat.eColorFormat ||
-            OMX_COLOR_FormatYUV420Planar == portFormat.eColorFormat) {
+            OMX_COLOR_FormatYUV420Planar == portFormat.eColorFormat ||
+            OMX_COLOR_FormatYUV420PackedPlanar == portFormat.eColorFormat ||
+            OMX_COLOR_FormatYUV420PackedSemiPlanar == portFormat.eColorFormat) {
             *eColorFormat = portFormat.eColorFormat;
             break;
         }
@@ -971,47 +887,184 @@ TEST_F(VideoDecHidlTest, DecodeTest) {
     setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
                         eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate);
 
-    // disabling adaptive playback.
-    omxNode->prepareForAdaptivePlayback(kPortIndexOutput, false, 1920, 1080);
-
     android::Vector<BufferInfo> iBuffer, oBuffer;
 
     // set state to idle
-    changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput, portMode);
+    ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(
+        omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
+        kPortIndexOutput, portMode, true));
     // set state to executing
-    changeStateIdletoExecute(omxNode, observer);
-
-    if (portMode[1] != PortMode::PRESET_BYTE_BUFFER) {
-        OMX_PARAM_PORTDEFINITIONTYPE portDef;
-
-        status = getPortParam(omxNode, OMX_IndexParamPortDefinition,
-                              kPortIndexOutput, &portDef);
-        ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
-        allocateGraphicBuffers(
-            omxNode, kPortIndexOutput, &oBuffer,
-            portDef.format.video.nFrameWidth, portDef.format.video.nFrameHeight,
-            &portDef.format.video.nStride, portDef.format.video.eColorFormat,
-            portDef.nBufferCountActual);
-    }
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
 
     // Port Reconfiguration
     eleStream.open(mURL, std::ifstream::binary);
     ASSERT_EQ(eleStream.is_open(), true);
-    decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
-                  kPortIndexOutput, eleStream, &Info, 0, (int)Info.size(),
-                  portMode[1]);
+    ASSERT_NO_FATAL_FAILURE(decodeNFrames(
+        omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
+        kPortIndexOutput, eleStream, &Info, 0, (int)Info.size(), portMode[1]));
     eleStream.close();
-    waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer,
-                           kPortIndexInput, kPortIndexOutput, portMode[1]);
-    testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag, portMode,
-            portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr);
+    ASSERT_NO_FATAL_FAILURE(
+        waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer,
+                               kPortIndexInput, kPortIndexOutput, portMode[1]));
+    ASSERT_NO_FATAL_FAILURE(testEOS(
+        omxNode, observer, &iBuffer, &oBuffer, false, eosFlag, portMode,
+        portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr));
+    if (timestampDevTest) EXPECT_EQ(timestampUslist.empty(), true);
+    // set state to idle
+    ASSERT_NO_FATAL_FAILURE(
+        changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
+    // set state to executing
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
+                                                    &oBuffer, kPortIndexInput,
+                                                    kPortIndexOutput));
+}
+
+// Test for adaptive playback support
+TEST_F(VideoDecHidlTest, AdaptivePlaybackTest) {
+    description("Tests for Adaptive Playback support");
+    if (disableTest) return;
+    if (!(compName == avc || compName == hevc || compName == vp8 ||
+          compName == vp9 || compName == mpeg2))
+        return;
+    android::hardware::media::omx::V1_0::Status status;
+    uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
+    status = setRole(omxNode, gEnv->getRole().c_str());
+    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    OMX_PORT_PARAM_TYPE params;
+    status = getParam(omxNode, OMX_IndexParamVideoInit, &params);
+    if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
+        ASSERT_EQ(params.nPorts, 2U);
+        kPortIndexInput = params.nStartPortNumber;
+        kPortIndexOutput = kPortIndexInput + 1;
+    }
+
+    // set port mode
+    portMode[0] = PortMode::PRESET_BYTE_BUFFER;
+    portMode[1] = PortMode::DYNAMIC_ANW_BUFFER;
+    status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
+    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
+    if (status != ::android::hardware::media::omx::V1_0::Status::OK) {
+        portMode[1] = PortMode::PRESET_BYTE_BUFFER;
+        status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
+        ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    }
+
+    // prepare for adaptive playback
+    uint32_t adaptiveMaxWidth = 320;
+    uint32_t adaptiveMaxHeight = 240;
+    status = omxNode->prepareForAdaptivePlayback(
+        kPortIndexOutput, true, adaptiveMaxWidth, adaptiveMaxHeight);
+    if (strncmp(gEnv->getComponent().c_str(), "OMX.google.", 11) == 0) {
+        // SoftOMX Decoders donot support graphic buffer modes. So for them
+        // support for adaptive play back is mandatory in Byte Buffer mode
+        ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    } else {
+        // for vendor codecs, support for adaptive play back is optional
+        // in byte buffer mode.
+        if (portMode[1] == PortMode::PRESET_BYTE_BUFFER) return;
+        if (status != ::android::hardware::media::omx::V1_0::Status::OK) return;
+    }
+
+    // TODO: Handle this better !!!
+    // Without the knowledge of the maximum resolution of the frame to be
+    // decoded it is not possible to choose the size of the input buffer.
+    // The value below is based on the info. files of clips in res folder.
+    status = setPortBufferSize(omxNode, kPortIndexInput, 482304);
+    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+
+    // set Port Params
+    uint32_t nFrameWidth, nFrameHeight, xFramerate;
+    getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth, &nFrameHeight,
+                        &xFramerate);
+    // get default color format
+    OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused;
+    getDefaultColorFormat(omxNode, kPortIndexOutput, portMode[1],
+                          &eColorFormat);
+    ASSERT_NE(eColorFormat, OMX_COLOR_FormatUnused);
+    status =
+        setVideoPortFormat(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
+                           eColorFormat, xFramerate);
+    EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
+                        eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate);
+
+    android::Vector<BufferInfo> iBuffer, oBuffer;
+
+    // set state to idle
+    ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(
+        omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
+        kPortIndexOutput, portMode, true));
+    // set state to executing
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
+
+    timestampDevTest = true;
+    uint32_t timestampOffset = 0;
+    for (uint32_t i = 0; i < STREAM_COUNT * 2; i++) {
+        std::ifstream eleStream, eleInfo;
+        char mURL[512], info[512];
+        android::Vector<FrameData> Info;
+        strcpy(mURL, gEnv->getRes().c_str());
+        strcpy(info, gEnv->getRes().c_str());
+        GetURLForComponent(compName, mURL, info, i % STREAM_COUNT);
+        eleInfo.open(info);
+        ASSERT_EQ(eleInfo.is_open(), true);
+        int bytesCount = 0;
+        uint32_t flags = 0;
+        uint32_t timestamp = 0;
+        uint32_t timestampMax = 0;
+        while (1) {
+            if (!(eleInfo >> bytesCount)) break;
+            eleInfo >> flags;
+            eleInfo >> timestamp;
+            timestamp += timestampOffset;
+            Info.push_back({bytesCount, flags, timestamp});
+            if (timestampDevTest && (flags != OMX_BUFFERFLAG_CODECCONFIG))
+                timestampUslist.push_back(timestamp);
+            if (timestampMax < timestamp) timestampMax = timestamp;
+        }
+        timestampOffset = timestampMax;
+        eleInfo.close();
+
+        // Port Reconfiguration
+        eleStream.open(mURL, std::ifstream::binary);
+        ASSERT_EQ(eleStream.is_open(), true);
+        ASSERT_NO_FATAL_FAILURE(
+            decodeNFrames(omxNode, observer, &iBuffer, &oBuffer,
+                          kPortIndexInput, kPortIndexOutput, eleStream, &Info,
+                          0, (int)Info.size(), portMode[1], false));
+        eleStream.close();
+
+        getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth,
+                            &nFrameHeight, &xFramerate);
+        if ((nFrameWidth > adaptiveMaxWidth) ||
+            (nFrameHeight > adaptiveMaxHeight)) {
+            if (nFrameWidth > adaptiveMaxWidth) adaptiveMaxWidth = nFrameWidth;
+            if (nFrameHeight > adaptiveMaxHeight)
+                adaptiveMaxHeight = nFrameHeight;
+            EXPECT_TRUE(portSettingsChange);
+        } else {
+            // In DynamicANW Buffer mode, its ok to do a complete
+            // reconfiguration even if a partial reconfiguration is sufficient.
+            if (portMode[1] != PortMode::DYNAMIC_ANW_BUFFER)
+                EXPECT_FALSE(portSettingsChange);
+        }
+        portSettingsChange = false;
+    }
+    ASSERT_NO_FATAL_FAILURE(
+        waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer,
+                               kPortIndexInput, kPortIndexOutput, portMode[1]));
+    ASSERT_NO_FATAL_FAILURE(testEOS(
+        omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, portMode,
+        portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr));
     if (timestampDevTest) EXPECT_EQ(timestampUslist.empty(), true);
     // set state to idle
-    changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
+    ASSERT_NO_FATAL_FAILURE(
+        changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
     // set state to executing
-    changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput);
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
+                                                    &oBuffer, kPortIndexInput,
+                                                    kPortIndexOutput));
 }
 
 // end of sequence test
@@ -1055,25 +1108,29 @@ TEST_F(VideoDecHidlTest, EOSTest_M) {
     android::Vector<BufferInfo> iBuffer, oBuffer;
 
     // set state to idle
-    changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput, portMode);
+    ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(
+        omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
+        kPortIndexOutput, portMode, true));
     // set state to executing
-    changeStateIdletoExecute(omxNode, observer);
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
 
     // request EOS at the start
-    testEOS(omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, portMode,
-            portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr);
-    flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
-               kPortIndexOutput);
+    ASSERT_NO_FATAL_FAILURE(testEOS(
+        omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, portMode,
+        portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr));
+    ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
+                                       kPortIndexInput, kPortIndexOutput));
     EXPECT_GE(framesReceived, 0U);
     framesReceived = 0;
     timestampUs = 0;
 
     // set state to idle
-    changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
+    ASSERT_NO_FATAL_FAILURE(
+        changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
     // set state to executing
-    changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput);
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
+                                                    &oBuffer, kPortIndexInput,
+                                                    kPortIndexOutput));
 }
 
 // end of sequence test
@@ -1143,50 +1200,58 @@ TEST_F(VideoDecHidlTest, ThumbnailTest) {
     android::Vector<BufferInfo> iBuffer, oBuffer;
 
     // set state to idle
-    changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput, portMode);
+    ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(
+        omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
+        kPortIndexOutput, portMode, true));
     // set state to executing
-    changeStateIdletoExecute(omxNode, observer);
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
 
     // request EOS for thumbnail
     size_t i = 0;
     while (!(Info[i].flags & OMX_BUFFERFLAG_SYNCFRAME)) i++;
     eleStream.open(mURL, std::ifstream::binary);
     ASSERT_EQ(eleStream.is_open(), true);
-    decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
-                  kPortIndexOutput, eleStream, &Info, 0, i + 1, portMode[1]);
+    ASSERT_NO_FATAL_FAILURE(decodeNFrames(
+        omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
+        kPortIndexOutput, eleStream, &Info, 0, i + 1, portMode[1]));
     eleStream.close();
-    waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer,
-                           kPortIndexInput, kPortIndexOutput, portMode[1]);
-    testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag, portMode,
-            portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr);
-    flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
-               kPortIndexOutput);
+    ASSERT_NO_FATAL_FAILURE(
+        waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer,
+                               kPortIndexInput, kPortIndexOutput, portMode[1]));
+    ASSERT_NO_FATAL_FAILURE(testEOS(
+        omxNode, observer, &iBuffer, &oBuffer, false, eosFlag, portMode,
+        portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr));
+    ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
+                                       kPortIndexInput, kPortIndexOutput));
     EXPECT_GE(framesReceived, 1U);
     framesReceived = 0;
     timestampUs = 0;
 
     eleStream.open(mURL, std::ifstream::binary);
     ASSERT_EQ(eleStream.is_open(), true);
-    decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
-                  kPortIndexOutput, eleStream, &Info, 0, i + 1, portMode[1],
-                  false);
+    ASSERT_NO_FATAL_FAILURE(decodeNFrames(
+        omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
+        kPortIndexOutput, eleStream, &Info, 0, i + 1, portMode[1], false));
     eleStream.close();
-    waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer,
-                           kPortIndexInput, kPortIndexOutput, portMode[1]);
-    testEOS(omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, portMode,
-            portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr);
-    flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
-               kPortIndexOutput);
+    ASSERT_NO_FATAL_FAILURE(
+        waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer,
+                               kPortIndexInput, kPortIndexOutput, portMode[1]));
+    ASSERT_NO_FATAL_FAILURE(testEOS(
+        omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, portMode,
+        portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr));
+    ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
+                                       kPortIndexInput, kPortIndexOutput));
     EXPECT_GE(framesReceived, 1U);
     framesReceived = 0;
     timestampUs = 0;
 
     // set state to idle
-    changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
+    ASSERT_NO_FATAL_FAILURE(
+        changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
     // set state to executing
-    changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput);
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
+                                                    &oBuffer, kPortIndexInput,
+                                                    kPortIndexOutput));
 }
 
 // end of sequence test
@@ -1232,10 +1297,16 @@ TEST_F(VideoDecHidlTest, SimpleEOSTest) {
     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
 
     // set port mode
+    portMode[0] = PortMode::PRESET_BYTE_BUFFER;
+    portMode[1] = PortMode::PRESET_ANW_BUFFER;
     status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
     status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
-    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    if (status != ::android::hardware::media::omx::V1_0::Status::OK) {
+        portMode[1] = PortMode::PRESET_BYTE_BUFFER;
+        status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
+        ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    }
 
     // set Port Params
     uint32_t nFrameWidth, nFrameHeight, xFramerate;
@@ -1256,32 +1327,38 @@ TEST_F(VideoDecHidlTest, SimpleEOSTest) {
     android::Vector<BufferInfo> iBuffer, oBuffer;
 
     // set state to idle
-    changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput, portMode);
+    ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(
+        omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
+        kPortIndexOutput, portMode, true));
     // set state to executing
-    changeStateIdletoExecute(omxNode, observer);
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
 
     // request EOS at the end
     eleStream.open(mURL, std::ifstream::binary);
     ASSERT_EQ(eleStream.is_open(), true);
-    decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
-                  kPortIndexOutput, eleStream, &Info, 0, (int)Info.size(),
-                  portMode[1], false);
+    ASSERT_NO_FATAL_FAILURE(decodeNFrames(omxNode, observer, &iBuffer, &oBuffer,
+                                          kPortIndexInput, kPortIndexOutput,
+                                          eleStream, &Info, 0, (int)Info.size(),
+                                          portMode[1], false));
     eleStream.close();
-    waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer,
-                           kPortIndexInput, kPortIndexOutput, portMode[1]);
-    testEOS(omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, portMode,
-            portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr);
-    flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
-               kPortIndexOutput);
+    ASSERT_NO_FATAL_FAILURE(
+        waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer,
+                               kPortIndexInput, kPortIndexOutput, portMode[1]));
+    ASSERT_NO_FATAL_FAILURE(testEOS(
+        omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, portMode,
+        portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr));
+    ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
+                                       kPortIndexInput, kPortIndexOutput));
     framesReceived = 0;
     timestampUs = 0;
 
     // set state to idle
-    changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
+    ASSERT_NO_FATAL_FAILURE(
+        changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
     // set state to executing
-    changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput);
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
+                                                    &oBuffer, kPortIndexInput,
+                                                    kPortIndexOutput));
 }
 
 // test input/output port flush
@@ -1351,10 +1428,11 @@ TEST_F(VideoDecHidlTest, FlushTest) {
     android::Vector<BufferInfo> iBuffer, oBuffer;
 
     // set state to idle
-    changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput, portMode);
+    ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(
+        omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
+        kPortIndexOutput, portMode, true));
     // set state to executing
-    changeStateIdletoExecute(omxNode, observer);
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
 
     // Decode 128 frames and flush. here 128 is chosen to ensure there is a key
     // frame after this so that the below section can be convered for all
@@ -1362,12 +1440,11 @@ TEST_F(VideoDecHidlTest, FlushTest) {
     int nFrames = 128;
     eleStream.open(mURL, std::ifstream::binary);
     ASSERT_EQ(eleStream.is_open(), true);
-    decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
-                  kPortIndexOutput, eleStream, &Info, 0, nFrames, portMode[1],
-                  false);
-    // Note: Assumes 200 ms is enough to end any decode call that started
-    flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
-               kPortIndexOutput, 200000);
+    ASSERT_NO_FATAL_FAILURE(decodeNFrames(
+        omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
+        kPortIndexOutput, eleStream, &Info, 0, nFrames, portMode[1], false));
+    ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
+                                       kPortIndexInput, kPortIndexOutput));
     framesReceived = 0;
 
     // Seek to next key frame and start decoding till the end
@@ -1384,21 +1461,23 @@ TEST_F(VideoDecHidlTest, FlushTest) {
         index++;
     }
     if (keyFrame) {
-        decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
-                      kPortIndexOutput, eleStream, &Info, index,
-                      Info.size() - index, portMode[1], false);
+        ASSERT_NO_FATAL_FAILURE(
+            decodeNFrames(omxNode, observer, &iBuffer, &oBuffer,
+                          kPortIndexInput, kPortIndexOutput, eleStream, &Info,
+                          index, Info.size() - index, portMode[1], false));
     }
-    // Note: Assumes 200 ms is enough to end any decode call that started
     eleStream.close();
-    flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
-               kPortIndexOutput, 200000);
+    ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
+                                       kPortIndexInput, kPortIndexOutput));
     framesReceived = 0;
 
     // set state to idle
-    changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
+    ASSERT_NO_FATAL_FAILURE(
+        changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
     // set state to executing
-    changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput);
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
+                                                    &oBuffer, kPortIndexInput,
+                                                    kPortIndexOutput));
 }
 
 int main(int argc, char** argv) {
index c6d688f..743ff78 100644 (file)
@@ -179,6 +179,7 @@ class VideoEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
                                this->omxNode = _nl;
                            })
                         .isOk());
+        ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
         ASSERT_NE(omxNode, nullptr);
         ASSERT_NE(gEnv->getRole().empty(), true) << "Invalid Component Role";
         struct StringToName {
@@ -237,7 +238,7 @@ class VideoEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
                         ".secure");
         }
         if (isSecure) disableTest = true;
-        if (disableTest) std::cerr << "[          ] Warning !  Test Disabled\n";
+        if (disableTest) std::cout << "[   WARN   ] Test Disabled \n";
     }
 
     virtual void TearDown() override {
@@ -278,9 +279,8 @@ class VideoEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
                             EXPECT_EQ(tsHit, true)
                                 << "TimeStamp not recognized";
                         } else {
-                            std::cerr
-                                << "[          ] Warning ! Received non-zero "
-                                   "output / TimeStamp not recognized \n";
+                            std::cout << "[   INFO   ] Received non-zero "
+                                         "output / TimeStamp not recognized \n";
                         }
                     }
                 }
@@ -442,7 +442,7 @@ void requestIDR(sp<IOmxNode> omxNode, OMX_U32 portIndex) {
     status = setPortConfig(omxNode, OMX_IndexConfigVideoIntraVOPRefresh,
                            portIndex, &param);
     if (status != ::android::hardware::media::omx::V1_0::Status::OK)
-        std::cerr << "[          ] Warning ! unable to request IDR \n";
+        std::cout << "[   INFO   ] unable to request IDR \n";
 }
 
 // modify bitrate
@@ -453,7 +453,7 @@ void changeBitrate(sp<IOmxNode> omxNode, OMX_U32 portIndex, uint32_t nBitrate) {
     status =
         setPortConfig(omxNode, OMX_IndexConfigVideoBitrate, portIndex, &param);
     if (status != ::android::hardware::media::omx::V1_0::Status::OK)
-        std::cerr << "[          ] Warning ! unable to change Bitrate \n";
+        std::cout << "[   INFO   ] unable to change Bitrate \n";
 }
 
 // modify framerate
@@ -465,7 +465,7 @@ Return<android::hardware::media::omx::V1_0::Status> changeFrameRate(
     status = setPortConfig(omxNode, OMX_IndexConfigVideoFramerate, portIndex,
                            &param);
     if (status != ::android::hardware::media::omx::V1_0::Status::OK)
-        std::cerr << "[          ] Warning ! unable to change Framerate \n";
+        std::cout << "[   INFO   ] unable to change Framerate \n";
     return status;
 }
 
@@ -479,7 +479,7 @@ void changeRefreshPeriod(sp<IOmxNode> omxNode, OMX_U32 portIndex,
                            (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh,
                            portIndex, &param);
     if (status != ::android::hardware::media::omx::V1_0::Status::OK)
-        std::cerr << "[          ] Warning ! unable to change Refresh Period\n";
+        std::cout << "[   INFO   ] unable to change Refresh Period\n";
 }
 
 // set intra refresh interval
@@ -505,7 +505,7 @@ void setRefreshPeriod(sp<IOmxNode> omxNode, OMX_U32 portIndex,
     status = setPortParam(omxNode, OMX_IndexParamVideoIntraRefresh, portIndex,
                           &param);
     if (status != ::android::hardware::media::omx::V1_0::Status::OK)
-        std::cerr << "[          ] Warning ! unable to set Refresh Period \n";
+        std::cout << "[   INFO   ] unable to set Refresh Period \n";
 }
 
 void setLatency(sp<IOmxNode> omxNode, OMX_U32 portIndex, uint32_t latency) {
@@ -515,7 +515,7 @@ void setLatency(sp<IOmxNode> omxNode, OMX_U32 portIndex, uint32_t latency) {
     status = setPortConfig(omxNode, (OMX_INDEXTYPE)OMX_IndexConfigLatency,
                            portIndex, &param);
     if (status != ::android::hardware::media::omx::V1_0::Status::OK)
-        std::cerr << "[          ] Warning ! unable to set latency\n";
+        std::cout << "[   INFO   ] unable to set latency\n";
 }
 
 void getLatency(sp<IOmxNode> omxNode, OMX_U32 portIndex, uint32_t* latency) {
@@ -524,7 +524,7 @@ void getLatency(sp<IOmxNode> omxNode, OMX_U32 portIndex, uint32_t* latency) {
     status = getPortConfig(omxNode, (OMX_INDEXTYPE)OMX_IndexConfigLatency,
                            portIndex, &param);
     if (status != ::android::hardware::media::omx::V1_0::Status::OK)
-        std::cerr << "[          ] Warning ! unable to get latency\n";
+        std::cout << "[   INFO   ] unable to get latency\n";
     else
         *latency = param.nU32;
 }
@@ -532,12 +532,15 @@ void getLatency(sp<IOmxNode> omxNode, OMX_U32 portIndex, uint32_t* latency) {
 // Set Default port param.
 void setDefaultPortParam(sp<IOmxNode> omxNode, OMX_U32 portIndex,
                          OMX_VIDEO_CODINGTYPE eCompressionFormat,
+                         OMX_U32 nFrameWidth, OMX_U32 nFrameHeight,
                          OMX_U32 nBitrate, OMX_U32 xFramerate) {
     android::hardware::media::omx::V1_0::Status status;
     OMX_PARAM_PORTDEFINITIONTYPE portDef;
     status = getPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
                           &portDef);
     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    portDef.format.video.nFrameWidth = nFrameWidth;
+    portDef.format.video.nFrameHeight = nFrameHeight;
     portDef.format.video.nBitrate = nBitrate;
     portDef.format.video.xFramerate = xFramerate;
     portDef.format.video.bFlagErrorConcealment = OMX_TRUE;
@@ -609,13 +612,13 @@ void waitOnInputConsumption(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
                             sp<CodecProducerListener> listener = nullptr) {
     android::hardware::media::omx::V1_0::Status status;
     Message msg;
-    int timeOut = TIMEOUT_COUNTER;
+    int timeOut = TIMEOUT_COUNTER_Q;
 
     while (timeOut--) {
         size_t i = 0;
         status =
-            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
-        EXPECT_EQ(status,
+            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
+        ASSERT_EQ(status,
                   android::hardware::media::omx::V1_0::Status::TIMED_OUT);
         // status == TIMED_OUT, it could be due to process time being large
         // than DEFAULT_TIMEOUT or component needs output buffers to start
@@ -632,7 +635,9 @@ void waitOnInputConsumption(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
         // Dispatch an output buffer assuming outQueue.empty() is true
         size_t index;
         if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
-            dispatchOutputBuffer(omxNode, oBuffer, index);
+            ASSERT_NO_FATAL_FAILURE(
+                dispatchOutputBuffer(omxNode, oBuffer, index));
+            timeOut = TIMEOUT_COUNTER_Q;
         }
     }
 }
@@ -979,57 +984,25 @@ void encodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
                    sp<CodecProducerListener> listener = nullptr) {
     android::hardware::media::omx::V1_0::Status status;
     Message msg;
-    uint32_t ipCount = 0;
+    uint64_t timestamp = 0;
+    uint32_t flags = 0;
+    int timeOut = TIMEOUT_COUNTER_Q;
+    bool iQueued, oQueued;
 
+    uint32_t ipCount = 0;
     if (ipCount == 0) {
         status = changeFrameRate(omxNode, portIndexOutput, (24U << 16));
         if (status == ::android::hardware::media::omx::V1_0::Status::OK)
             xFramerate = (24U << 16);
     }
-
-    // dispatch output buffers
-    for (size_t i = 0; i < oBuffer->size(); i++) {
-        dispatchOutputBuffer(omxNode, oBuffer, i);
-    }
-    // dispatch input buffers
     int32_t timestampIncr = (int)((float)1000000 / (xFramerate >> 16));
-    // timestamp scale = Nano sec
-    if (inputDataIsMeta) timestampIncr *= 1000;
-    uint64_t timestamp = 0;
-    uint32_t flags = 0;
-    for (size_t i = 0; i < iBuffer->size() && nFrames != 0; i++) {
-        if (inputDataIsMeta) {
-            if (listener->freeBuffers > listener->minUnDequeuedCount) {
-                if (dispatchGraphicBuffer(omxNode, producer, listener, iBuffer,
-                                          portIndexInput, eleStream, timestamp))
-                    break;
-                timestamp += timestampIncr;
-                nFrames--;
-                ipCount++;
-            }
-        } else {
-            char* ipBuffer = static_cast<char*>(
-                static_cast<void*>((*iBuffer)[i].mMemory->getPointer()));
-            ASSERT_LE(bytesCount,
-                      static_cast<int>((*iBuffer)[i].mMemory->getSize()));
-            if (fillByteBuffer(omxNode, ipBuffer, portIndexInput, eleStream))
-                break;
-            if (signalEOS && (nFrames == 1)) flags = OMX_BUFFERFLAG_EOS;
-            dispatchInputBuffer(omxNode, iBuffer, i, bytesCount, flags,
-                                timestamp);
-            if (timestampUslist) timestampUslist->push_back(timestamp);
-            timestamp += timestampIncr;
-            nFrames--;
-            ipCount++;
-        }
-    }
+    if (inputDataIsMeta) timestampIncr *= 1000;  // timestamp scale: Nano sec
 
-    int timeOut = TIMEOUT_COUNTER;
-    bool stall = false;
     while (1) {
+        iQueued = oQueued = false;
         status =
-            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
-
+            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
+        // Port Reconfiguration
         if (status == android::hardware::media::omx::V1_0::Status::OK) {
             ASSERT_EQ(msg.type, Message::Type::EVENT);
             if (msg.data.eventData.event == OMX_EventPortSettingsChanged) {
@@ -1037,8 +1010,10 @@ void encodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
                 ASSERT_EQ(msg.data.eventData.data2,
                           OMX_IndexConfigAndroidIntraRefresh);
             } else if (msg.data.eventData.event == OMX_EventError) {
-                EXPECT_TRUE(false) << "Received OMX_EventError, not sure why";
-                break;
+                ASSERT_TRUE(false) << "Received OMX_EventError, not sure why";
+            } else if (msg.data.eventData.event == OMX_EventDataSpaceChanged) {
+                // TODO: how am i supposed to respond now?
+                std::cout << "[   INFO   ] OMX_EventDataSpaceChanged \n";
             } else {
                 ASSERT_TRUE(false);
             }
@@ -1051,14 +1026,17 @@ void encodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
         if (inputDataIsMeta) {
             if (listener->freeBuffers > listener->minUnDequeuedCount) {
                 if (dispatchGraphicBuffer(omxNode, producer, listener, iBuffer,
-                                          portIndexInput, eleStream, timestamp))
-                    break;
+                                          portIndexInput, eleStream,
+                                          timestamp)) {
+                    if (::testing::Test::HasFailure())
+                        ASSERT_TRUE(false);
+                    else
+                        break;
+                }
                 timestamp += timestampIncr;
                 nFrames--;
                 ipCount++;
-                stall = false;
-            } else {
-                stall = true;
+                iQueued = true;
             }
         } else {
             if ((index = getEmptyBufferID(iBuffer)) < iBuffer->size()) {
@@ -1070,31 +1048,32 @@ void encodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
                 if (fillByteBuffer(omxNode, ipBuffer, portIndexInput,
                                    eleStream))
                     break;
-                if (signalEOS && (nFrames == 1)) flags = OMX_BUFFERFLAG_EOS;
-                dispatchInputBuffer(omxNode, iBuffer, index, bytesCount, flags,
-                                    timestamp);
+                flags = OMX_BUFFERFLAG_ENDOFFRAME;
+                if (signalEOS && (nFrames == 1)) flags |= OMX_BUFFERFLAG_EOS;
+                ASSERT_NO_FATAL_FAILURE(dispatchInputBuffer(
+                    omxNode, iBuffer, index, bytesCount, flags, timestamp));
                 if (timestampUslist) timestampUslist->push_back(timestamp);
                 timestamp += timestampIncr;
                 nFrames--;
                 ipCount++;
-                stall = false;
-            } else {
-                stall = true;
+                iQueued = true;
             }
         }
+        // Dispatch output buffer
         if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
-            dispatchOutputBuffer(omxNode, oBuffer, index);
-            stall = false;
-        } else
-            stall = true;
-        if (stall)
-            timeOut--;
+            ASSERT_NO_FATAL_FAILURE(
+                dispatchOutputBuffer(omxNode, oBuffer, index));
+            oQueued = true;
+        }
+        // Reset Counters when either input or output buffer is dispatched
+        if (iQueued || oQueued)
+            timeOut = TIMEOUT_COUNTER_Q;
         else
-            timeOut = TIMEOUT_COUNTER;
+            timeOut--;
         if (timeOut == 0) {
-            EXPECT_TRUE(false) << "Wait on Input/Output is found indefinite";
-            break;
+            ASSERT_TRUE(false) << "Wait on Input/Output is found indefinite";
         }
+        // Runtime Param Configuration
         if (ipCount == 15) {
             changeBitrate(omxNode, portIndexOutput, 768000);
             requestIDR(omxNode, portIndexOutput);
@@ -1164,7 +1143,7 @@ TEST_F(VideoEncHidlTest, BufferSourceCallBacks) {
                  xFramerate, eColorFormat);
 
     sp<DummyBufferSource> buffersource = new DummyBufferSource(omxNode);
-    EXPECT_NE(buffersource, nullptr);
+    ASSERT_NE(buffersource, nullptr);
     status = omxNode->setInputSurface(buffersource);
     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
 
@@ -1178,20 +1157,20 @@ TEST_F(VideoEncHidlTest, BufferSourceCallBacks) {
     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
 
     // set state to idle
-    changeStateLoadedtoIdle(omxNode, observer, &buffersource->iBuffer,
-                            &buffersource->oBuffer, kPortIndexInput,
-                            kPortIndexOutput, portMode);
+    ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(
+        omxNode, observer, &buffersource->iBuffer, &buffersource->oBuffer,
+        kPortIndexInput, kPortIndexOutput, portMode));
     // set state to executing
-    changeStateIdletoExecute(omxNode, observer);
-    testEOS(omxNode, observer, &buffersource->iBuffer, &buffersource->oBuffer,
-            false, eosFlag);
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
+    ASSERT_NO_FATAL_FAILURE(testEOS(omxNode, observer, &buffersource->iBuffer,
+                                    &buffersource->oBuffer, false, eosFlag));
     // set state to idle
-    changeStateExecutetoIdle(omxNode, observer, &buffersource->iBuffer,
-                             &buffersource->oBuffer);
+    ASSERT_NO_FATAL_FAILURE(changeStateExecutetoIdle(
+        omxNode, observer, &buffersource->iBuffer, &buffersource->oBuffer));
     // set state to executing
-    changeStateIdletoLoaded(omxNode, observer, &buffersource->iBuffer,
-                            &buffersource->oBuffer, kPortIndexInput,
-                            kPortIndexOutput);
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(
+        omxNode, observer, &buffersource->iBuffer, &buffersource->oBuffer,
+        kPortIndexInput, kPortIndexOutput));
     // test for callbacks
     EXPECT_EQ(buffersource->callback, 31);
 }
@@ -1245,8 +1224,9 @@ TEST_F(VideoEncHidlTest, EncodeTest) {
 
     // Configure output port
     uint32_t nBitRate = 512000;
-    setDefaultPortParam(omxNode, kPortIndexOutput, eCompressionFormat, nBitRate,
-                        xFramerate);
+    ASSERT_NO_FATAL_FAILURE(
+        setDefaultPortParam(omxNode, kPortIndexOutput, eCompressionFormat,
+                            nFrameWidth, nFrameHeight, nBitRate, xFramerate));
     setRefreshPeriod(omxNode, kPortIndexOutput, 0);
 
     unsigned int index;
@@ -1263,8 +1243,7 @@ TEST_F(VideoEncHidlTest, EncodeTest) {
         status = setParam(omxNode, static_cast<OMX_INDEXTYPE>(index), &param);
     }
     if (status != ::android::hardware::media::omx::V1_0::Status::OK)
-        std::cerr
-            << "[          ] Warning ! unable to prependSPSPPSToIDRFrames\n";
+        std::cout << "[   INFO   ] unable to prependSPSPPSToIDRFrames\n";
     else
         prependSPSPPS = true;
 
@@ -1283,27 +1262,32 @@ TEST_F(VideoEncHidlTest, EncodeTest) {
     android::Vector<BufferInfo> iBuffer, oBuffer;
 
     // set state to idle
-    changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput, portMode);
+    ASSERT_NO_FATAL_FAILURE(
+        changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
+                                kPortIndexInput, kPortIndexOutput, portMode));
     // set state to executing
-    changeStateIdletoExecute(omxNode, observer);
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
 
     eleStream.open(mURL, std::ifstream::binary);
     ASSERT_EQ(eleStream.is_open(), true);
-    encodeNFrames(omxNode, observer, kPortIndexInput, kPortIndexOutput,
-                  &iBuffer, &oBuffer, 32, xFramerate,
-                  (nFrameWidth * nFrameHeight * 3) >> 1, eleStream,
-                  &timestampUslist);
+    ASSERT_NO_FATAL_FAILURE(encodeNFrames(
+        omxNode, observer, kPortIndexInput, kPortIndexOutput, &iBuffer,
+        &oBuffer, 32, xFramerate, (nFrameWidth * nFrameHeight * 3) >> 1,
+        eleStream, &timestampUslist));
     eleStream.close();
-    waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer);
-    testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag);
+    ASSERT_NO_FATAL_FAILURE(
+        waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer));
+    ASSERT_NO_FATAL_FAILURE(
+        testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag));
     if (timestampDevTest) EXPECT_EQ(timestampUslist.empty(), true);
 
     // set state to idle
-    changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
+    ASSERT_NO_FATAL_FAILURE(
+        changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
     // set state to executing
-    changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput);
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
+                                                    &oBuffer, kPortIndexInput,
+                                                    kPortIndexOutput));
 }
 
 // test raw stream encode (input is ANW buffers)
@@ -1330,6 +1314,11 @@ TEST_F(VideoEncHidlTest, EncodeTestBufferMetaModes) {
     setupRAWPort(omxNode, kPortIndexInput, nFrameWidth, nFrameHeight, 0,
                  xFramerate, eColorFormat);
 
+    // Configure output port
+    uint32_t nBitRate = 512000;
+    ASSERT_NO_FATAL_FAILURE(
+        setDefaultPortParam(omxNode, kPortIndexOutput, eCompressionFormat,
+                            nFrameWidth, nFrameHeight, nBitRate, xFramerate));
     // CreateInputSurface
     EXPECT_TRUE(omx->createInputSurface(
                        [&](android::hardware::media::omx::V1_0::Status _s,
@@ -1436,28 +1425,32 @@ TEST_F(VideoEncHidlTest, EncodeTestBufferMetaModes) {
 
     android::Vector<BufferInfo> iBuffer, oBuffer;
     // set state to idle
-    changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput, portMode);
+    ASSERT_NO_FATAL_FAILURE(
+        changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
+                                kPortIndexInput, kPortIndexOutput, portMode));
     // set state to executing
-    changeStateIdletoExecute(omxNode, observer);
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
 
     eleStream.open(mURL, std::ifstream::binary);
     ASSERT_EQ(eleStream.is_open(), true);
-    encodeNFrames(omxNode, observer, kPortIndexInput, kPortIndexOutput,
-                  &iBuffer, &oBuffer, 1024, xFramerate,
-                  (nFrameWidth * nFrameHeight * 3) >> 1, eleStream, nullptr,
-                  false, true, producer, listener);
+    ASSERT_NO_FATAL_FAILURE(encodeNFrames(
+        omxNode, observer, kPortIndexInput, kPortIndexOutput, &iBuffer,
+        &oBuffer, 1024, xFramerate, (nFrameWidth * nFrameHeight * 3) >> 1,
+        eleStream, nullptr, false, true, producer, listener));
     eleStream.close();
-    waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, true,
-                           listener);
-    testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag);
+    ASSERT_NO_FATAL_FAILURE(waitOnInputConsumption(omxNode, observer, &iBuffer,
+                                                   &oBuffer, true, listener));
+    ASSERT_NO_FATAL_FAILURE(
+        testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag));
 
     // set state to idle
-    changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
+    ASSERT_NO_FATAL_FAILURE(
+        changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
     EXPECT_EQ(portDef.nBufferCountActual, listener->freeBuffers);
     // set state to executing
-    changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput);
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
+                                                    &oBuffer, kPortIndexInput,
+                                                    kPortIndexOutput));
 
     returnval = producer->disconnect(
         NATIVE_WINDOW_API_CPU, IGraphicBufferProducer::DisconnectMode::API);
@@ -1551,24 +1544,28 @@ TEST_F(VideoEncHidlTest, EncodeTestEOS) {
 
     android::Vector<BufferInfo> iBuffer, oBuffer;
     // set state to idle
-    changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput, portMode);
+    ASSERT_NO_FATAL_FAILURE(
+        changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
+                                kPortIndexInput, kPortIndexOutput, portMode));
     // set state to executing
-    changeStateIdletoExecute(omxNode, observer);
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
 
     // send EOS
     status = source->signalEndOfInputStream();
     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
-    waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, true,
-                           listener);
-    testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag);
+    ASSERT_NO_FATAL_FAILURE(waitOnInputConsumption(omxNode, observer, &iBuffer,
+                                                   &oBuffer, true, listener));
+    ASSERT_NO_FATAL_FAILURE(
+        testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag));
 
     // set state to idle
-    changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
+    ASSERT_NO_FATAL_FAILURE(
+        changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
     EXPECT_EQ(portDef.nBufferCountActual, listener->freeBuffers);
     // set state to executing
-    changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput);
+    ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
+                                                    &oBuffer, kPortIndexInput,
+                                                    kPortIndexOutput));
 
     returnval = producer->disconnect(
         NATIVE_WINDOW_API_CPU, IGraphicBufferProducer::DisconnectMode::API);
index 91aecf2..e1b6022 100644 (file)
@@ -15,7 +15,6 @@
  */
 
 #define LOG_TAG "media_omx_hidl_video_test_common"
-
 #ifdef __LP64__
 #define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
 #endif
index c1d7aea..55de125 100644 (file)
 #define MEDIA_VIDEO_HIDL_TEST_COMMON_H
 
 /*
- * Random Index used for monkey testing while get/set parameters
- */
-#define RANDOM_INDEX 1729
-
-/*
  * Common video utils
  */
-
 void enumerateProfileAndLevel(sp<IOmxNode> omxNode, OMX_U32 portIndex,
                               std::vector<int32_t>* arrProfile,
                               std::vector<int32_t>* arrLevel);
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
diff --git a/media/res/bbb_avc_176x144_300kbps_60fps.h264 b/media/res/bbb_avc_176x144_300kbps_60fps.h264
new file mode 100644 (file)
index 0000000..da1e75d
Binary files /dev/null and b/media/res/bbb_avc_176x144_300kbps_60fps.h264 differ
diff --git a/media/res/bbb_avc_176x144_300kbps_60fps.info b/media/res/bbb_avc_176x144_300kbps_60fps.info
new file mode 100644 (file)
index 0000000..d88b540
--- /dev/null
@@ -0,0 +1,62 @@
+28 128 0
+10 128 0
+4780 32 33333
+960 0 100000
+480 0 66666
+246 0 50000
+264 0 83333
+1160 0 166666
+404 0 133333
+237 0 116666
+193 0 150000
+936 0 233333
+384 0 200000
+199 0 183333
+275 0 216666
+1086 0 300000
+520 0 266666
+301 0 250000
+270 0 283333
+1232 0 366666
+559 0 333333
+287 0 316666
+274 0 350000
+1084 0 433333
+485 0 400000
+307 0 383333
+284 0 416666
+1052 0 500000
+504 0 466666
+298 0 450000
+327 0 483333
+1189 0 566666
+358 0 533333
+172 0 516666
+185 0 550000
+1115 0 633333
+463 0 600000
+218 0 583333
+255 0 616666
+1155 0 700000
+622 0 666666
+356 0 650000
+341 0 683333
+1240 0 766666
+610 0 733333
+341 0 716666
+380 0 750000
+1326 0 833333
+620 0 800000
+396 0 783333
+353 0 816666
+1196 0 900000
+623 0 866666
+375 0 850000
+362 0 883333
+1192 0 966666
+654 0 933333
+359 0 916666
+352 0 950000
+828 0 1016666
+436 0 983333
+401 0 1000000
diff --git a/media/res/bbb_flac_stereo_680kbps_48000hz.flac b/media/res/bbb_flac_stereo_680kbps_48000hz.flac
new file mode 100644 (file)
index 0000000..db94d8e
Binary files /dev/null and b/media/res/bbb_flac_stereo_680kbps_48000hz.flac differ
diff --git a/media/res/bbb_flac_stereo_680kbps_48000hz.info b/media/res/bbb_flac_stereo_680kbps_48000hz.info
new file mode 100644 (file)
index 0000000..c572430
--- /dev/null
@@ -0,0 +1,415 @@
+42 128 0
+1386 32 0
+2401 32 24000
+2321 32 48000
+2367 32 72000
+2370 32 96000
+2334 32 120000
+2396 32 144000
+2375 32 168000
+2431 32 192000
+2428 32 216000
+2334 32 240000
+2261 32 264000
+2124 32 288000
+2152 32 312000
+2295 32 336000
+2183 32 360000
+2393 32 384000
+2400 32 408000
+2246 32 432000
+2289 32 456000
+2400 32 480000
+2335 32 504000
+2294 32 528000
+2260 32 552000
+2206 32 576000
+2185 32 600000
+2155 32 624000
+2118 32 648000
+2094 32 672000
+2050 32 696000
+2059 32 720000
+2030 32 744000
+2022 32 768000
+2078 32 792000
+2082 32 816000
+2094 32 840000
+2111 32 864000
+2043 32 888000
+2023 32 912000
+2024 32 936000
+2056 32 960000
+2108 32 984000
+2138 32 1008000
+2140 32 1032000
+2111 32 1056000
+2110 32 1080000
+2137 32 1104000
+2157 32 1128000
+2174 32 1152000
+2200 32 1176000
+2203 32 1200000
+2237 32 1224000
+2261 32 1248000
+2215 32 1272000
+2133 32 1296000
+2091 32 1320000
+2088 32 1344000
+2122 32 1368000
+2139 32 1392000
+2146 32 1416000
+2231 32 1440000
+2282 32 1464000
+2273 32 1488000
+2304 32 1512000
+2292 32 1536000
+2255 32 1560000
+2181 32 1584000
+2081 32 1608000
+2012 32 1632000
+2011 32 1656000
+2066 32 1680000
+2069 32 1704000
+2120 32 1728000
+2141 32 1752000
+2148 32 1776000
+2181 32 1800000
+2176 32 1824000
+2240 32 1848000
+2297 32 1872000
+2325 32 1896000
+2336 32 1920000
+2329 32 1944000
+2299 32 1968000
+2322 32 1992000
+2347 32 2016000
+2287 32 2040000
+2286 32 2064000
+2269 32 2088000
+2320 32 2112000
+2305 32 2136000
+2384 32 2160000
+2429 32 2184000
+2370 32 2208000
+2365 32 2232000
+2361 32 2256000
+2370 32 2280000
+2393 32 2304000
+2342 32 2328000
+2325 32 2352000
+2334 32 2376000
+2316 32 2400000
+2317 32 2424000
+2305 32 2448000
+2360 32 2472000
+2331 32 2496000
+2332 32 2520000
+2361 32 2544000
+2417 32 2568000
+2438 32 2592000
+2403 32 2616000
+2386 32 2640000
+2382 32 2664000
+2350 32 2688000
+2355 32 2712000
+2383 32 2736000
+2384 32 2760000
+2383 32 2784000
+2373 32 2808000
+2374 32 2832000
+2347 32 2856000
+2353 32 2880000
+2381 32 2904000
+2401 32 2928000
+2401 32 2952000
+2385 32 2976000
+2382 32 3000000
+2328 32 3024000
+2303 32 3048000
+2272 32 3072000
+2270 32 3096000
+2312 32 3120000
+2273 32 3144000
+2330 32 3168000
+2339 32 3192000
+2296 32 3216000
+2317 32 3240000
+2440 32 3264000
+2353 32 3288000
+2346 32 3312000
+2303 32 3336000
+2308 32 3360000
+2287 32 3384000
+2316 32 3408000
+2367 32 3432000
+2335 32 3456000
+2350 32 3480000
+2395 32 3504000
+2408 32 3528000
+2413 32 3552000
+2415 32 3576000
+2468 32 3600000
+2437 32 3624000
+2372 32 3648000
+2371 32 3672000
+2341 32 3696000
+2328 32 3720000
+2273 32 3744000
+2244 32 3768000
+2233 32 3792000
+2229 32 3816000
+2252 32 3840000
+2236 32 3864000
+2217 32 3888000
+2179 32 3912000
+2251 32 3936000
+2192 32 3960000
+2199 32 3984000
+2212 32 4008000
+2190 32 4032000
+2102 32 4056000
+2120 32 4080000
+2167 32 4104000
+2024 32 4128000
+2010 32 4152000
+2067 32 4176000
+2035 32 4200000
+2051 32 4224000
+2012 32 4248000
+2066 32 4272000
+2025 32 4296000
+1987 32 4320000
+1972 32 4344000
+1966 32 4368000
+1999 32 4392000
+1987 32 4416000
+1922 32 4440000
+2020 32 4464000
+2072 32 4488000
+2021 32 4512000
+2017 32 4536000
+2099 32 4560000
+2064 32 4584000
+2109 32 4608000
+2093 32 4632000
+2090 32 4656000
+2148 32 4680000
+2184 32 4704000
+2179 32 4728000
+2152 32 4752000
+2143 32 4776000
+2159 32 4800000
+2123 32 4824000
+2129 32 4848000
+2147 32 4872000
+2192 32 4896000
+2051 32 4920000
+2116 32 4944000
+2124 32 4968000
+2088 32 4992000
+2073 32 5016000
+2146 32 5040000
+2133 32 5064000
+2073 32 5088000
+2059 32 5112000
+2044 32 5136000
+2012 32 5160000
+2034 32 5184000
+2053 32 5208000
+2013 32 5232000
+1981 32 5256000
+2094 32 5280000
+2076 32 5304000
+1968 32 5328000
+2028 32 5352000
+2031 32 5376000
+2020 32 5400000
+2019 32 5424000
+2030 32 5448000
+2015 32 5472000
+1962 32 5496000
+2070 32 5520000
+2087 32 5544000
+1964 32 5568000
+2069 32 5592000
+2034 32 5616000
+1994 32 5640000
+1985 32 5664000
+2030 32 5688000
+2066 32 5712000
+1954 32 5736000
+1733 32 5760000
+1649 32 5784000
+1652 32 5808000
+1631 32 5832000
+1656 32 5856000
+1672 32 5880000
+1667 32 5904000
+1696 32 5928000
+1672 32 5952000
+1701 32 5976000
+1651 32 6000000
+1674 32 6024000
+1695 32 6048000
+1702 32 6072000
+1707 32 6096000
+1694 32 6120000
+1727 32 6144000
+1730 32 6168000
+1708 32 6192000
+1704 32 6216000
+1735 32 6240000
+1758 32 6264000
+1753 32 6288000
+1748 32 6312000
+1763 32 6336000
+1737 32 6360000
+1783 32 6384000
+1839 32 6408000
+1861 32 6432000
+1832 32 6456000
+1947 32 6480000
+1939 32 6504000
+1926 32 6528000
+1896 32 6552000
+1909 32 6576000
+1869 32 6600000
+1900 32 6624000
+1896 32 6648000
+1883 32 6672000
+1903 32 6696000
+1895 32 6720000
+1865 32 6744000
+1878 32 6768000
+1881 32 6792000
+1861 32 6816000
+1791 32 6840000
+1787 32 6864000
+1798 32 6888000
+1811 32 6912000
+1824 32 6936000
+1895 32 6960000
+2079 32 6984000
+2034 32 7008000
+2038 32 7032000
+2018 32 7056000
+2030 32 7080000
+2067 32 7104000
+1982 32 7128000
+1911 32 7152000
+1904 32 7176000
+1874 32 7200000
+1876 32 7224000
+1944 32 7248000
+1977 32 7272000
+1977 32 7296000
+1979 32 7320000
+2012 32 7344000
+1961 32 7368000
+1773 32 7392000
+1780 32 7416000
+1801 32 7440000
+1892 32 7464000
+1869 32 7488000
+1936 32 7512000
+2154 32 7536000
+2226 32 7560000
+2159 32 7584000
+2253 32 7608000
+2286 32 7632000
+2214 32 7656000
+2111 32 7680000
+2027 32 7704000
+1994 32 7728000
+1882 32 7752000
+1887 32 7776000
+1993 32 7800000
+1962 32 7824000
+1982 32 7848000
+1966 32 7872000
+1962 32 7896000
+1928 32 7920000
+1878 32 7944000
+1857 32 7968000
+1885 32 7992000
+1919 32 8016000
+1904 32 8040000
+1909 32 8064000
+1909 32 8088000
+1933 32 8112000
+1824 32 8136000
+1756 32 8160000
+1733 32 8184000
+1705 32 8208000
+1755 32 8232000
+1756 32 8256000
+1725 32 8280000
+1761 32 8304000
+1736 32 8328000
+1706 32 8352000
+1662 32 8376000
+1604 32 8400000
+1613 32 8424000
+1692 32 8448000
+1736 32 8472000
+1779 32 8496000
+1768 32 8520000
+1758 32 8544000
+1708 32 8568000
+1642 32 8592000
+1645 32 8616000
+1581 32 8640000
+1651 32 8664000
+1731 32 8688000
+1743 32 8712000
+1717 32 8736000
+1715 32 8760000
+1646 32 8784000
+1551 32 8808000
+1563 32 8832000
+1649 32 8856000
+1742 32 8880000
+1724 32 8904000
+1676 32 8928000
+1664 32 8952000
+1587 32 8976000
+1497 32 9000000
+1503 32 9024000
+1644 32 9048000
+1658 32 9072000
+1680 32 9096000
+1611 32 9120000
+1694 32 9144000
+1668 32 9168000
+1677 32 9192000
+1604 32 9216000
+1567 32 9240000
+1639 32 9264000
+1552 32 9288000
+1486 32 9312000
+1494 32 9336000
+1480 32 9360000
+1509 32 9384000
+1457 32 9408000
+1423 32 9432000
+1459 32 9456000
+1444 32 9480000
+1424 32 9504000
+1413 32 9528000
+1498 32 9552000
+1455 32 9576000
+1393 32 9600000
+1638 32 9624000
+1919 32 9648000
+1979 32 9672000
+1894 32 9696000
+2002 32 9720000
+2062 32 9744000
+2098 32 9768000
+1919 32 9792000
+1738 32 9816000
+1890 32 9840000
+1971 32 9864000
+2429 32 9888000
+1861 32 9912000
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
diff --git a/media/res/bbb_hevc_176x144_176kbps_60fps.hevc b/media/res/bbb_hevc_176x144_176kbps_60fps.hevc
new file mode 100644 (file)
index 0000000..f82236f
Binary files /dev/null and b/media/res/bbb_hevc_176x144_176kbps_60fps.hevc differ
diff --git a/media/res/bbb_hevc_176x144_176kbps_60fps.info b/media/res/bbb_hevc_176x144_176kbps_60fps.info
new file mode 100644 (file)
index 0000000..702b853
--- /dev/null
@@ -0,0 +1,61 @@
+1695 128 0
+1938 32 33333
+471 0 83333
+153 0 66666
+99 0 50000
+657 0 150000
+260 0 116666
+115 0 100000
+99 0 133333
+622 0 216666
+211 0 183333
+79 0 166666
+95 0 200000
+597 0 283333
+288 0 250000
+145 0 233333
+147 0 266666
+676 0 350000
+284 0 316666
+144 0 300000
+131 0 333333
+658 0 416666
+270 0 383333
+101 0 366666
+151 0 400000
+529 0 483333
+257 0 450000
+98 0 433333
+160 0 466666
+664 0 566666
+186 0 533333
+147 0 500000
+67 0 516666
+78 0 550000
+575 0 633333
+230 0 600000
+134 0 583333
+114 0 616666
+629 0 700000
+224 0 666666
+138 0 650000
+129 0 683333
+645 0 750000
+264 0 733333
+145 0 716666
+705 0 816666
+365 0 783333
+156 0 766666
+160 0 800000
+725 0 883333
+330 0 850000
+138 0 833333
+162 0 866666
+638 0 950000
+337 0 916666
+170 0 900000
+133 0 933333
+432 0 1016666
+287 0 983333
+130 0 966666
+136 0 1000000
diff --git a/media/res/bbb_mpeg2_352x288_1mbps_60fps.info b/media/res/bbb_mpeg2_352x288_1mbps_60fps.info
new file mode 100644 (file)
index 0000000..d5290d7
--- /dev/null
@@ -0,0 +1,60 @@
+16680 32 16666
+17017 0 33333
+10534 0 50000
+10289 0 66666
+3698 0 83333
+2776 0 100000
+1936 0 116666
+1493 0 133333
+1217 0 150000
+993 0 166666
+805 0 183333
+857 0 200000
+5082 32 216666
+812 0 233333
+718 0 250000
+746 0 266666
+762 0 283333
+865 0 300000
+782 0 316666
+833 0 333333
+750 0 350000
+819 0 366666
+826 0 383333
+846 0 400000
+4522 32 416666
+678 0 433333
+718 0 450000
+803 0 466666
+769 0 483333
+762 0 500000
+587 0 516666
+635 0 533333
+658 0 550000
+714 0 566666
+677 0 583333
+699 0 600000
+4616 32 616666
+800 0 633333
+831 0 650000
+928 0 666666
+869 0 683333
+931 0 700000
+930 0 716666
+974 0 733333
+978 0 750000
+932 0 766666
+918 0 783333
+978 0 800000
+4655 32 816666
+897 0 833333
+896 0 850000
+883 0 866666
+949 0 883333
+965 0 900000
+951 0 916666
+901 0 933333
+965 0 950000
+955 0 966666
+948 0 983333
+968 0 1000000
diff --git a/media/res/bbb_mpeg2_352x288_1mbps_60fps.m2v b/media/res/bbb_mpeg2_352x288_1mbps_60fps.m2v
new file mode 100644 (file)
index 0000000..2f67c2b
Binary files /dev/null and b/media/res/bbb_mpeg2_352x288_1mbps_60fps.m2v differ
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
diff --git a/media/res/bbb_vp8_176x144_240kbps_60fps.info b/media/res/bbb_vp8_176x144_240kbps_60fps.info
new file mode 100644 (file)
index 0000000..559f425
--- /dev/null
@@ -0,0 +1,60 @@
+10271 32 0
+106 0 17000
+134 0 33000
+149 0 50000
+152 0 67000
+159 0 83000
+114 0 100000
+723 0 117000
+175 0 133000
+186 0 150000
+201 0 167000
+270 0 183000
+383 0 200000
+255 0 217000
+286 0 233000
+273 0 250000
+1224 0 267000
+220 0 283000
+231 0 300000
+192 0 317000
+182 0 333000
+289 0 350000
+204 0 367000
+237 0 383000
+187 0 400000
+898 0 417000
+231 0 433000
+266 0 450000
+278 0 467000
+205 0 483000
+255 0 500000
+169 0 517000
+233 0 533000
+1011 0 550000
+202 0 567000
+251 0 583000
+223 0 600000
+283 0 617000
+362 0 633000
+217 0 650000
+245 0 667000
+960 0 683000
+233 0 700000
+286 0 717000
+272 0 733000
+254 0 750000
+331 0 767000
+218 0 783000
+261 0 800000
+981 0 817000
+226 0 833000
+226 0 850000
+279 0 867000
+225 0 883000
+295 0 900000
+175 0 917000
+249 0 933000
+996 0 950000
+169 0 967000
+224 0 983000
diff --git a/media/res/bbb_vp8_176x144_240kbps_60fps.vp8 b/media/res/bbb_vp8_176x144_240kbps_60fps.vp8
new file mode 100644 (file)
index 0000000..6eba56c
Binary files /dev/null and b/media/res/bbb_vp8_176x144_240kbps_60fps.vp8 differ
diff --git a/media/res/bbb_vp9_176x144_285kbps_60fps.info b/media/res/bbb_vp9_176x144_285kbps_60fps.info
new file mode 100644 (file)
index 0000000..2f7d35b
--- /dev/null
@@ -0,0 +1,60 @@
+6939 32 0
+6818 0 17000
+310 0 33000
+273 0 50000
+267 0 67000
+239 0 83000
+232 0 100000
+222 0 117000
+186 0 133000
+194 0 150000
+189 0 167000
+18 0 183000
+2014 0 200000
+297 0 217000
+287 0 233000
+237 0 250000
+263 0 267000
+238 0 283000
+257 0 300000
+229 0 317000
+187 0 333000
+191 0 350000
+18 0 367000
+2203 0 383000
+265 0 400000
+224 0 417000
+254 0 433000
+252 0 450000
+273 0 467000
+208 0 483000
+154 0 500000
+182 0 517000
+138 0 533000
+18 0 550000
+2502 0 567000
+286 0 583000
+304 0 600000
+341 0 617000
+259 0 633000
+275 0 650000
+222 0 667000
+254 0 683000
+253 0 700000
+225 0 717000
+18 0 733000
+2501 0 750000
+282 0 767000
+298 0 783000
+252 0 800000
+242 0 817000
+250 0 833000
+260 0 850000
+218 0 867000
+213 0 883000
+144 0 900000
+18 0 917000
+233 0 933000
+254 0 950000
+229 0 967000
+239 0 983000
diff --git a/media/res/bbb_vp9_176x144_285kbps_60fps.vp9 b/media/res/bbb_vp9_176x144_285kbps_60fps.vp9
new file mode 100644 (file)
index 0000000..2633c8a
Binary files /dev/null and b/media/res/bbb_vp9_176x144_285kbps_60fps.vp9 differ
index 6f6e16d..4df2c1d 100644 (file)
@@ -39,13 +39,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.memtrack@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.memtrack@1.0_genc++"],
     generated_headers: ["android.hardware.memtrack@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.memtrack@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index 71e6111..2d833e7 100644 (file)
 
 cc_test {
     name: "VtsHalMemtrackV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalMemtrackV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhardware",
-        "libhidlbase",
-        "libutils",
-        "android.hardware.memtrack@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ]
+    static_libs: ["android.hardware.memtrack@1.0"],
 }
diff --git a/minijail/Android.mk b/minijail/Android.mk
new file mode 100644 (file)
index 0000000..272bb0e
--- /dev/null
@@ -0,0 +1,14 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libhwminijail
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_SRC_FILES := HardwareMinijail.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+    libbase \
+    libminijail_vendor
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/minijail/HardwareMinijail.cpp b/minijail/HardwareMinijail.cpp
new file mode 100644 (file)
index 0000000..e6b1144
--- /dev/null
@@ -0,0 +1,45 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <android-base/logging.h>
+#include <libminijail.h>
+
+#include <hwminijail/HardwareMinijail.h>
+
+namespace android {
+namespace hardware {
+
+void SetupMinijail(const std::string& seccomp_policy_path) {
+    if (access(seccomp_policy_path.c_str(), R_OK) == -1) {
+        LOG(WARNING) << "Could not find seccomp policy file at: " << seccomp_policy_path;
+        return;
+    }
+
+    struct minijail* jail = minijail_new();
+    if (jail == NULL) {
+        LOG(FATAL) << "Failed to create minijail.";
+    }
+
+    minijail_no_new_privs(jail);
+    minijail_log_seccomp_filter_failures(jail);
+    minijail_use_seccomp_filter(jail);
+    minijail_parse_seccomp_filters(jail, seccomp_policy_path.c_str());
+    minijail_enter(jail);
+    minijail_destroy(jail);
+}
+
+}  // namespace hardware
+}  // namespace android
diff --git a/minijail/include/hwminijail/HardwareMinijail.h b/minijail/include/hwminijail/HardwareMinijail.h
new file mode 100644 (file)
index 0000000..8fcf007
--- /dev/null
@@ -0,0 +1,30 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef ANDROID_HARDWARE_CONFIGSTORE_MINIJAIL_H
+#define ANDROID_HARDWARE_CONFIGSTORE_MINIJAIL_H
+
+#include <string>
+
+namespace android {
+namespace hardware {
+
+void SetupMinijail(const std::string& seccomp_policy_path);
+
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_CONFIGSTORE_UTILS_H
diff --git a/neuralnetworks/1.0/Android.bp b/neuralnetworks/1.0/Android.bp
new file mode 100644 (file)
index 0000000..ba32d0c
--- /dev/null
@@ -0,0 +1,87 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+filegroup {
+    name: "android.hardware.neuralnetworks@1.0_hal",
+    srcs: [
+        "types.hal",
+        "IDevice.hal",
+        "IExecutionCallback.hal",
+        "IPreparedModel.hal",
+        "IPreparedModelCallback.hal",
+    ],
+}
+
+genrule {
+    name: "android.hardware.neuralnetworks@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.neuralnetworks@1.0",
+    srcs: [
+        ":android.hardware.neuralnetworks@1.0_hal",
+    ],
+    out: [
+        "android/hardware/neuralnetworks/1.0/types.cpp",
+        "android/hardware/neuralnetworks/1.0/DeviceAll.cpp",
+        "android/hardware/neuralnetworks/1.0/ExecutionCallbackAll.cpp",
+        "android/hardware/neuralnetworks/1.0/PreparedModelAll.cpp",
+        "android/hardware/neuralnetworks/1.0/PreparedModelCallbackAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.neuralnetworks@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.neuralnetworks@1.0",
+    srcs: [
+        ":android.hardware.neuralnetworks@1.0_hal",
+    ],
+    out: [
+        "android/hardware/neuralnetworks/1.0/types.h",
+        "android/hardware/neuralnetworks/1.0/hwtypes.h",
+        "android/hardware/neuralnetworks/1.0/IDevice.h",
+        "android/hardware/neuralnetworks/1.0/IHwDevice.h",
+        "android/hardware/neuralnetworks/1.0/BnHwDevice.h",
+        "android/hardware/neuralnetworks/1.0/BpHwDevice.h",
+        "android/hardware/neuralnetworks/1.0/BsDevice.h",
+        "android/hardware/neuralnetworks/1.0/IExecutionCallback.h",
+        "android/hardware/neuralnetworks/1.0/IHwExecutionCallback.h",
+        "android/hardware/neuralnetworks/1.0/BnHwExecutionCallback.h",
+        "android/hardware/neuralnetworks/1.0/BpHwExecutionCallback.h",
+        "android/hardware/neuralnetworks/1.0/BsExecutionCallback.h",
+        "android/hardware/neuralnetworks/1.0/IPreparedModel.h",
+        "android/hardware/neuralnetworks/1.0/IHwPreparedModel.h",
+        "android/hardware/neuralnetworks/1.0/BnHwPreparedModel.h",
+        "android/hardware/neuralnetworks/1.0/BpHwPreparedModel.h",
+        "android/hardware/neuralnetworks/1.0/BsPreparedModel.h",
+        "android/hardware/neuralnetworks/1.0/IPreparedModelCallback.h",
+        "android/hardware/neuralnetworks/1.0/IHwPreparedModelCallback.h",
+        "android/hardware/neuralnetworks/1.0/BnHwPreparedModelCallback.h",
+        "android/hardware/neuralnetworks/1.0/BpHwPreparedModelCallback.h",
+        "android/hardware/neuralnetworks/1.0/BsPreparedModelCallback.h",
+    ],
+}
+
+cc_library {
+    name: "android.hardware.neuralnetworks@1.0",
+    defaults: ["hidl-module-defaults"],
+    generated_sources: ["android.hardware.neuralnetworks@1.0_genc++"],
+    generated_headers: ["android.hardware.neuralnetworks@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.neuralnetworks@1.0_genc++_headers"],
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+    ],
+}
diff --git a/neuralnetworks/1.0/IDevice.hal b/neuralnetworks/1.0/IDevice.hal
new file mode 100644 (file)
index 0000000..49c2967
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.neuralnetworks@1.0;
+
+import IPreparedModelCallback;
+
+/**
+ * This interface represents a device driver.
+ */
+interface IDevice {
+    /**
+     * 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() generates (ErrorStatus status, Capabilities capabilities);
+
+    /**
+     * Gets the supported operations in a model.
+     *
+     * getSupportedSubgraph 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(Model model)
+                generates (ErrorStatus status, vec<bool> supportedOperations);
+
+    /**
+     * Creates a prepared model for execution.
+     *
+     * prepareModel is used to make any necessary transformations or alternative
+     * representations to a model for execution, possiblly 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 can only be finished when it is paired with a set of
+     * inputs to the model. Note that the same prepared model object can be
+     * used with different shapes of inputs on different (possibly concurrent)
+     * executions.
+     *
+     * Multiple threads can call prepareModel on the same model concurrently.
+     *
+     * @param model The model to be prepared for execution.
+     * @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(Model model, IPreparedModelCallback callback)
+      generates (ErrorStatus status);
+
+    /**
+     * Returns the current status of a driver.
+     *
+     * @return status Status of the driver, one of:
+     *                - DeviceStatus::AVAILABLE
+     *                - DeviceStatus::BUSY
+     *                - DeviceStatus::OFFLINE
+     *                - DeviceStatus::UNKNOWN
+     */
+    getStatus() generates (DeviceStatus status);
+};
diff --git a/neuralnetworks/1.0/IExecutionCallback.hal b/neuralnetworks/1.0/IExecutionCallback.hal
new file mode 100644 (file)
index 0000000..ef0f454
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.neuralnetworks@1.0;
+
+/**
+ * IExecutionCallback must be used to return the error status result from an
+ * execution asynchronously launched from IPreparedModel::execute.
+ */
+interface IExecutionCallback {
+
+    /**
+     * notify must be invoked immediately after the asynchronous task has
+     * finished performing the execution. notify must be provided with the
+     * ErrorStatus resulting from the execution. If the asynchronous task
+     * is not launched, notify must be invoked with the appropriate error.
+     *
+     * @return param Error status returned from launching the asynchronous task
+     *               (if the launch fails) or from the asynchronous task itself
+     *               (if the launch succeeds). Must be:
+     *               - NONE if the asynchronous execution was successful
+     *               - DEVICE_UNAVAILABLE if driver is offline or busy
+     *               - GENERAL_FAILURE if the asynchronous task resulted in an
+     *                 unspecified error
+     *               - OUTPUT_INSUFFICIENT_SIZE if provided output buffer is
+     *                 not large enough to store the resultant values
+     *               - INVALID_ARGUMENT if one of the input arguments to
+     *                 prepareModel is invalid
+     */
+    oneway notify(ErrorStatus status);
+};
diff --git a/neuralnetworks/1.0/IPreparedModel.hal b/neuralnetworks/1.0/IPreparedModel.hal
new file mode 100644 (file)
index 0000000..ee406fb
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.neuralnetworks@1.0;
+
+import IExecutionCallback;
+
+/**
+ * IPreparedModel describes a model that has been prepared for execution and
+ * is used to launch executions.
+ */
+interface IPreparedModel {
+    /**
+     * Launches an asynchronous execution on a prepared model.
+     *
+     * The execution is performed asynchronously with respect to the caller.
+     * execute must verify the inputs to the function are correct. If there is
+     * an error, execute must immediately invoke the callback with the
+     * appropriate ErrorStatus value, then return with the same ErrorStatus. If
+     * the inputs to the function are valid and there is no error, execute must
+     * launch an asynchronous task to perform the execution in the background,
+     * and immediately return with ErrorStatus::NONE. If the asynchronous task
+     * fails to launch, execute must immediately invoke the callback with
+     * ErrorStatus::GENERAL_FAILURE, then return with
+     * ErrorStatus::GENERAL_FAILURE.
+     *
+     * When the asynchronous task has finished its execution, it must
+     * immediately invoke the callback object provided as an input to the
+     * execute function. This callback must be provided with the ErrorStatus of
+     * the execution.
+     *
+     * Multiple threads can call the execute function on the same IPreparedModel
+     * object concurrently with different requests.
+     *
+     * @param request The input and output information on which the prepared
+     *                model is to be executed.
+     * @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
+     *                 unsuccessful.
+     * @return status Error status of the call, must be:
+     *                - NONE if task is successfully launched
+     *                - DEVICE_UNAVAILABLE if driver is offline or busy
+     *                - GENERAL_FAILURE if there is an unspecified error
+     *                - OUTPUT_INSUFFICIENT_SIZE if provided output buffer is
+     *                  not large enough to store the resultant values
+     *                - INVALID_ARGUMENT if one of the input arguments is
+     *                  invalid
+     */
+    execute(Request request, IExecutionCallback callback)
+        generates (ErrorStatus status);
+};
diff --git a/neuralnetworks/1.0/IPreparedModelCallback.hal b/neuralnetworks/1.0/IPreparedModelCallback.hal
new file mode 100644 (file)
index 0000000..fa1bf9d
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.neuralnetworks@1.0;
+
+import IPreparedModel;
+
+/**
+ * IPreparedModelCallback must be used to return a prepared model produced by an
+ * asynchronous task launched from IDevice::prepareModel.
+ */
+interface IPreparedModelCallback {
+
+    /**
+     * notify must be invoked immediately after the asynchronous task holding
+     * this callback has finished preparing the model. If the model was
+     * successfully prepared, notify must be invoked with ErrorStatus::NONE and
+     * the prepared model. If the model was not able to be successfully
+     * prepared, notify must be invoked with the appropriate ErrorStatus and
+     * nullptr as the IPreparedModel. If the asynchronous task holding this
+     * callback fails to launch or if the model provided to
+     * IDevice::prepareModel is invalid, notify must be invoked with the
+     * appropriate error as well as nullptr for the IPreparedModel.
+     *
+     * @param status Error status returned from the asynchronous model
+     *               preparation task; must be:
+     *               - NONE if the asynchronous task successfully prepared the
+     *                 model
+     *               - DEVICE_UNAVAILABLE if driver is offline or busy
+     *               - GENERAL_FAILURE if the asynchronous task resulted in an
+     *                 unspecified error
+     *               - INVALID_ARGUMENT if one of the input arguments to
+     *                 prepareModel is invalid
+     * @param preparedModel A model that has been asynchronously prepared for
+     *                      execution. If the model was unable to be prepared
+     *                      due to an error, nullptr must be passed in place of
+     *                      the IPreparedModel object.
+     */
+    oneway notify(ErrorStatus status, IPreparedModel preparedModel);
+};
diff --git a/neuralnetworks/1.0/types.hal b/neuralnetworks/1.0/types.hal
new file mode 100644 (file)
index 0000000..8779723
--- /dev/null
@@ -0,0 +1,1267 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.neuralnetworks@1.0;
+
+/**
+ * Operand types.
+ *
+ * The type of an operand in a model.
+ *
+ * Types prefaced with TENSOR_* must be used for tensor data (i.e., tensors
+ * with at least one dimension). Types not prefaced by TENSOR_* represent
+ * scalar values and must have no dimensions.
+ */
+enum OperandType : int32_t {
+    /**
+     * The following entries are used to declare scalars.
+     */
+    FLOAT32             = 0,
+    INT32               = 1,
+    UINT32              = 2,
+
+    /**
+     * The following entries are used to declare tensors.
+     */
+    TENSOR_FLOAT32      = 3,
+    TENSOR_INT32        = 4,
+
+    /**
+     * A tensor of 8 bit integers that represent real numbers.
+     *
+     * Attached to this tensor are two numbers that can be used to convert the
+     * 8 bit integer to the real value and vice versa. These two numbers are:
+     * - scale: a 32 bit floating point value
+     * - zero_value: a 32 bit integer
+     *
+     * The formula is:
+     * real_value = (integer_value - zero_value) * scale.
+     */
+    TENSOR_QUANT8_ASYMM = 5,
+
+    /**
+     * The following entries are OEM specific operand types.
+     */
+    OEM                 = 10000,
+    TENSOR_OEM_BYTE     = 10001,
+};
+
+/**
+ * Operation types.
+ *
+ * The type of an operation in a model.
+ */
+enum OperationType : int32_t {
+    /**
+     * Adds two tensors, elment-wise.
+     *
+     * Takes two input tensors of identical type 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 types: {@link OperandType::TENSOR_FLOAT32}
+     * Supported tensor rank: up to 4
+     *
+     * Inputs:
+     * 0: A tensor.
+     * 1: A tensor of the same type, and compatible dimensions as input0.
+     * 2: An INT32 value, and has to be one of the {@link FusedActivationFunc} values.
+     *    Specifies the activation to invoke on the result of each addition.
+     *
+     * Ouputs:
+     * 0: The sum, a tensor of the same type as input0.
+     */
+    ADD = 0,
+
+    /**
+     * Performs a 2-D average pooling operation.
+     *
+     * The output dimensions are functions of the filter dimensions, stride, and padding.
+     *
+     * The values in output Tensor is computed as:
+     *     output[batch, row, col, channel] =
+     *         sum_{i, j}(input[batch, row + i, col + j, channel]) / sum(1)
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: 4, with "NHWC" data layout.
+     *
+     * Inputs:
+     * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying the input.
+     * 1: An INT32 value, specifying the padding on the left, in the ‘width’ dimension.
+     * 2: An INT32 value, specifying the padding on the right,in the ‘width’ dimension.
+     * 3: An INT32 value, specifying the padding on the top, in the ‘height’ dimension.
+     * 4: An INT32 value, specifying the padding on the bottom, in the ‘height’ dimension.
+     * 5: An INT32 value, specifying the output stride in the ‘width’ dimension.
+     * 6: An INT32 value, specifying the output stride in the ‘height’ dimension.
+     * 7: An INT32 value, specifying the filter width.
+     * 8: An INT32 value, specifying the filter height.
+     * 9: An INT32 value, and has to be one of the {@link FusedActivationFunc} values.
+     *    Specifies the activation to invoke on the result of each addition.
+     *
+     * Ouputs:
+     * 0: The output 4-D tensor, of shape [batches, out_height, out_width, depth].
+     */
+    AVERAGE_POOL_2D = 1,
+
+    /**
+     * Concatenates the input tensors along the given dimension.
+     *
+     * The input tensors must have identical type and the same dimensions except the
+     * dimension along the concatenation axis.
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: up to 4
+     *
+     * Inputs:
+     * 0 ~ n: The list on n input tensors, of shape [D0, D1, ..., Daxis(i), ..., Dm]
+     * n+1: An INT32 value, specifying the concatenation axis.
+     * n+2: An INT32 value, and has to be one of the {@link FusedActivationFunc} values.
+     *    Specifies the activation to invoke on the result of each addition.
+     *
+     * Ouputs:
+     * 0: The output, a tensor of the same type as the input tensors.
+          The output shape is [D0, D1, ..., sum(Daxis(i)), ..., Dm].
+     */
+    CONCATENATION = 2,
+
+    /**
+     * 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 output Tensor is computed as:
+     *     output[batch, row, col, channel] =
+     *         sum_{i, j} (
+     *             input[batch, row + i, col + j, k] *
+     *             filter[channel, row + i, col + j, k] +
+     *             bias[channel]
+     *         )
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: 4, with "NHWC" data layout.
+     *
+     * Inputs:
+     * 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 {@link OperandType::TENSOR_FLOAT32} type, the bias should
+     *    also be of {@link OperandType::TENSOR_FLOAT32}.
+     *    For input tensor of {@link OperandType::TENSOR_QUANT8_ASYMM} type, the bias
+     *    should be of {@link OperandType::TENSOR_INT32}.
+     * 3: An INT32 value, specifying the padding on the left, in the ‘width’ dimension.
+     * 4: An INT32 value, specifying the padding on the right,in the ‘width’ dimension.
+     * 5: An INT32 value, specifying the padding on the top, in the ‘height’ dimension.
+     * 6: An INT32 value, specifying the padding on the bottom, in the ‘height’ dimension.
+     * 7: An INT32 value, specifying the output stride in the ‘width’ dimension.
+     * 8: An INT32 value, specifying the output stride in the ‘height’ dimension.
+     * 9: An INT32 value, and has to be one of the {@link FusedActivationFunc} values.
+     *    Specifies the activation to invoke on the result of each addition.
+     *
+     * Ouputs:
+     * 0: The output 4-D tensor, of shape [batches, out_height, out_width, depth_out].
+     */
+    CONV_2D = 3,
+
+    /**
+     * Performs an depthwise 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_in] containing
+     * in_channels 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 output Tensor is 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[di, dj, k, q]
+     *         )
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: 4, with "NHWC" data layout.
+     *
+     * Inputs:
+     * 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 {@link OperandType::TENSOR_FLOAT32} type, the bias should
+     *    also be of {@link OperandType::TENSOR_FLOAT32}.
+     *    For input tensor of {@link OperandType::TENSOR_QUANT8_ASYMM} type, the bias
+     *    should be of {@link OperandType::TENSOR_INT32}.
+     * 3: An INT32 value, specifying the padding on the left, in the ‘width’ dimension.
+     * 4: An INT32 value, specifying the padding on the right,in the ‘width’ dimension.
+     * 5: An INT32 value, specifying the padding on the top, in the ‘height’ dimension.
+     * 6: An INT32 value, specifying the padding on the bottom, in the ‘height’ dimension.
+     * 7: An INT32 value, specifying the output stride in the ‘width’ dimension.
+     * 8: An INT32 value, specifying the output stride in the ‘height’ dimension.
+     * 9: An INT32 value, specifying the depthwise multiplier.
+     * 10: An INT32 value, and has to be one of the {@link FusedActivationFunc} values.
+     *    Specifies the activation to invoke on the result of each addition.
+     *
+     * Ouputs:
+     * 0: The output 4-D tensor, of shape [batches, out_height, out_width, depth_out].
+     */
+    DEPTHWISE_CONV_2D = 4,
+
+    /**
+     * 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 types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: 4, with "NHWC" data layout.
+     *
+     * Inputs:
+     * 0: A 4-D tensor, of shape [batches, height, width, depth_in], specifying the input.
+     * 1: An INT32 value, specifying the block_size. block_size must be >=1 and
+     *    block_size * block_size must be a divisor of the input depth.
+     *
+     * Ouputs:
+     * 0: The output 4-D tensor, of shape [batch, height*block_size, width*block_size,
+     *    depth/(block_size*block_size)].
+     */
+    DEPTH_TO_SPACE = 5,
+
+    /**
+     * Dequantizes the input tensor.
+     *
+     * The formula is:
+     *     output = (input - zero_value) * scale.
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: up to 4
+     *
+     * Inputs:
+     * 0: A tensor of type {@link OperandType::TENSOR_QUANT8_ASYMM}.
+     *
+     * Ouputs:
+     * 0: The output tensor of same shape as input0, but with type
+          {@link OperandType::TENSOR_FLOAT32}.
+     */
+    DEQUANTIZE = 6,
+
+    /**
+     * Looks up items from a given tensor.
+     *
+     * Each item in the output is a raw copy of the corresponding item in
+     * the input “values”. If the the given “lookup” indices are out of bounds,
+     * the op will fail and an error will be reported.
+     *
+     * Inputs:
+     * * 0: Values. An n-D tensor of any type X (where n >= 2). E.g., if n is 2,
+     *      then the shape would be [lookup_dimension, values_dimension], where
+     *      “lookup_dimension” corresponds to the indexing dimension in the lookup
+     *      table, and “values_dimension” to the contents.
+     * * 1: Lookups. An 1-D tensor of type T, of shape [lookup_size], where
+     *      “lookup_size” is the number of elements to look for, and each entry
+     *      corresponds to the first dimension of the “values” tensor.
+     *
+     * Output:
+     * * 0: A n-D tensor of type X and the same rank and shape as the “values”
+     *      tensor, except for the first dimension which has size “lookup_size”.
+     */
+    EMBEDDING_LOOKUP = 7,
+
+    /**
+     * Computes element-wise floor() on the input tensor.
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     * Supported tensor rank: up to 4
+     *
+     * Inputs:
+     * 0: A tensor.
+     *
+     * Ouputs:
+     * 0: The output, a tensor of the same type and dimensions as input0.
+     */
+    FLOOR = 8,
+
+    /**
+     * 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 types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: up to 4.
+     *
+     * Inputs:
+     * 0: A tensor, specifying the input. If rank is greater than 2, then it gets flattened to
+     *    a 2-D Tensor. The 2-D Tensor is handled as if dimensions corresponded to shape
+     *    [batch_size, input_size], where “batch_size” corresponds to the batching dimension,
+     *    and “input_size” is the size of the input.
+     * 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} type, the bias should
+     *    also be of {@link OperandType::TENSOR_FLOAT32}.
+     *    For input tensor of {@link OperandType::TENSOR_QUANT8_ASYMM} type, the bias
+     *    should be of {@link OperandType::TENSOR_INT32}.
+     * 3: An INT32 value, and has to be one of the {@link FusedActivationFunc} values.
+     *    Specifies the activation to invoke on the result of each addition.
+     *
+     * Ouputs:
+     * 0: The output tensor, of shape [batch_size, num_units].
+     */
+    FULLY_CONNECTED = 9,
+
+    /**
+     * Looks up values of a hash table with given keys.
+     *
+     * Inputs:
+     * * 0: Lookups. A 1-D int32 tensor with shape [ k ].
+     * * 1: Keys. A 1-D int32 tensor with shape [ n ], *MUST* be sorted in
+     *      ascending order.
+     * * 2: Values. A tensor with shape [ n … ].
+     *
+     * Outputs:
+     * * 0: Output. A tensor with shape [ k …].
+     * * 1: Hits. A uint8 tensor with shape [ k ] indicates whether the lookup
+     *      hits or not.
+     */
+    HASHTABLE_LOOKUP = 10,
+
+    /**
+     * Applies L2 normalization along a the depth dimension.
+     *
+     * The values in output Tensor is computed as:
+     *     output[batch, row, col, channel] =
+     *         input[batch, row, col, channel] /
+     *         sqrt(sum_{c} pow(input[batch, row, col, c], 2))
+     *
+     * For x with more dimensions, independently normalizes each 1-D slice along dimension dim.
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     * Supported tensor rank: 4, with "NHWC" data layout.
+     *
+     * Inputs:
+     * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying the input.
+     *
+     * Ouputs:
+     * 0: The output 4-D tensor, of shape [batches, out_height, out_width, depth].
+     */
+    L2_NORMALIZATION = 11,
+
+    /**
+     * Performs an 2-D L2 pooling operation.
+     *
+     * The output dimensions are functions of the filter dimensions, stride, and padding.
+     *
+     * The values in output Tensor is computed as:
+     *     output[batch, row, col, channel] =
+     *         sqrt(sum_{i, j} pow(input[batch, row + i, col + j, channel], 2) / sum(1))
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     * Supported tensor rank: 4, with "NHWC" data layout.
+     *
+     * Inputs:
+     * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying the input.
+     * 1: An INT32 value, specifying the padding on the left, in the ‘width’ dimension.
+     * 2: An INT32 value, specifying the padding on the right,in the ‘width’ dimension.
+     * 3: An INT32 value, specifying the padding on the top, in the ‘height’ dimension.
+     * 4: An INT32 value, specifying the padding on the bottom, in the ‘height’ dimension.
+     * 5: An INT32 value, specifying the output stride in the ‘width’ dimension.
+     * 6: An INT32 value, specifying the output stride in the ‘height’ dimension.
+     * 7: An INT32 value, specifying the filter width.
+     * 8: An INT32 value, specifying the filter height.
+     * 9: An INT32 value, and has to be one of the {@link FusedActivationFunc} values.
+     *    Specifies the activation to invoke on the result of each addition.
+     *
+     * Ouputs:
+     * 0: The output 4-D tensor, of shape [batches, out_height, out_width, depth].
+     */
+    L2_POOL_2D = 12,
+
+    /**
+     * 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.
+     *
+     * In details:
+     *     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)
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     * Supported tensor rank: 4, with "NHWC" data layout.
+     *
+     * Inputs:
+     * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying the input.
+     * 1: An INT32 value, specifying the radius of the normalization window.
+     * 2: A FLOAT32 value, specifying the bias, must not be zero.
+     * 3: A FLOAT32 value, specifying the scale factor, alpha.
+     * 4: A FLOAT32 value, specifying the exponent, beta.
+     *
+     * Ouputs:
+     * 0: The output tensor of same shape as input0.
+     */
+    LOCAL_RESPONSE_NORMALIZATION = 13,
+
+    /**
+     * Computes sigmoid activation on the input tensor element-wise.
+     *
+     * In details:
+     *     output = 1 / (1 + exp(-input))
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: up to 4.
+     *
+     * Inputs:
+     * 0: A tensor, specifying the input.
+     *
+     * Ouputs:
+     * 0: The output tensor of same shape as input0.
+     */
+    LOGISTIC = 14,
+
+    /**
+     * Projects an input to a bit vector via locality senstive hashing.
+     *
+     * Inputs:
+     * * 0: Hash functions. Dim.size == 2, DataType: Float.
+     *            Tensor[0].Dim[0]: Number of hash functions.
+     *            Tensor[0].Dim[1]: Number of seeds per hash functions.
+     *            Tensor[0].Dim[1] <= 32 in sparse case.
+     *
+     * * 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(=1).
+     *          Computed bit vector is considered to be sparse.
+     *          Each output element is an int32 made up of multiple bits computed from
+     *          hash functions.
+     *
+     *        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.
+     */
+    LSH_PROJECTION = 15,
+
+    /**
+     * Long short-term memory unit (LSTM) recurrent network layer.
+     *
+     * The default non-peephole implementation is based on:
+     * http://deeplearning.cs.cmu.edu/pdfs/Hochreiter97_lstm.pdf
+     * S. Hochreiter and J. Schmidhuber. "Long Short-Term Memory". Neural
+     * Computation, 9(8):1735-1780, 1997.
+     *
+     * The peephole implementation 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.
+     *
+     * 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 class has the following independently optional inputs:
+     * * If input gate (if CIFG): “input_to_forget_weights”,
+     *   “recurrent_to_input_weights”, “cell_to_input_weights”, “input_gate_bias”.
+     * * If no peephole connections: “cell_to_input_weights”,
+     *   “cell_to_forget_weights”, “cell_to_output_weights”.
+     * * If no projection layer: “projection_weights” and “projection_bias”.
+     * * If no projection bias: “projection_bias”.
+     *
+     * Supported tensor types:
+     * * {@link OperandType::TENSOR_FLOAT32}
+     *
+     * Inputs:
+     * * 0: Input.
+     *      A 2-D tensor of type T, of shape [batch_size, input_size], where
+     *      “batch_size” corresponds to the batching dimension, and “input_size”
+     *      is the size of the input.
+     * * 1: input_to_input_weights.
+     *      A 2-D tensor of type T, of shape [num_units, input_size], where
+     *      “num_units” corresponds to the number of cell units.
+     * * 2: input_to_forget_weights.
+     *      A 2-D tensor of type T, of shape [num_units, input_size].
+     * * 3: input_to_cell_weights.
+     *      A 2-D tensor of type T, of shape [num_units, input_size].
+     * * 4: input_to_output_weights.
+     *      A 2-D tensor of type T, of shape [num_units, input_size].
+     * * 5: recurrent_to_input_weights.
+     *      A 2-D tensor of type T, 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: recurrent_to_forget_weights.
+     *      A 2-D tensor of type T, of shape [num_units, output_size].
+     * * 7: recurrent_to_cell_weights.
+     *      A 2-D tensor of type T, of shape [num_units, output_size].
+     * * 8: recurrent_to_output_weights.
+     *      A 2-D tensor of type T, of shape [num_units, output_size].
+     * * 9: cell_to_input_weights.
+     *      A 1-D tensor of type T, of shape [num_units].
+     * * 10:cell_to_forget_weights.
+     *      A 1-D tensor of type T, of shape [num_units].
+     * * 11:cell_to_output_weights.
+     *      A 1-D tensor of type T, of shape [num_units].
+     * * 12:input_gate_bias.
+     *      A 1-D tensor of type T, of shape [num_units].
+     * * 13:forget_gate_bias.
+     *      A 1-D tensor of type T, of shape [num_units].
+     * * 14:cell_bias.
+     *      A 1-D tensor of type T, of shape [num_units].
+     * * 15:output_gate_bias.
+     *      A 1-D tensor of type T, of shape [num_units].
+     * * 16:projection_weights.
+     *      A 2-D tensor of type T, of shape [output_size, num_units].
+     * * 17:projection_bias.
+     *      A 1-D tensor of type T, of shape [output_size].
+     *
+     * Parameters:
+     * * 18:fused_activation_function.
+     *      An (optional) ActivationFunctionType indicating the activation
+     *      function.
+     *      If “NONE” is specified then it results in a linear activation.
+     * * 19:cell_clip.
+     *      A 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.
+     * * 20:proj_clip.
+     *      A 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.
+     *
+     * Outputs:
+     * * 0: scratch_buffer.
+     *      A 3-D tensor of type T, of shape [batch_size, num_cell, 4].
+     * * 1: output_state.
+     *      A 2-D tensor of type T, of shape [batch_size, output_size].
+     * * 2: cell_state.
+     *      A 2-D tensor of type T, of shape [batch_size, num_units].
+     * * 3: output.
+     *      A 2-D tensor of type T, of shape [batch_size, output_size]. This is
+     *      effectively the same as the current “output_state” value.
+     */
+    LSTM = 16,
+
+    /**
+     * Performs an 2-D max pooling operation.
+     *
+     * The output dimensions are functions of the filter dimensions, stride, and padding.
+     *
+     * The values in output Tensor is computed as:
+     *     output[batch, row, col, channel] =
+     *         max_{i, j} (input[batch, row + i, col + j, channel])
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: 4, with "NHWC" data layout.
+     *
+     * Inputs:
+     * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying the input.
+     * 1: An INT32 value, specifying the padding on the left, in the ‘width’ dimension.
+     * 2: An INT32 value, specifying the padding on the right,in the ‘width’ dimension.
+     * 3: An INT32 value, specifying the padding on the top, in the ‘height’ dimension.
+     * 4: An INT32 value, specifying the padding on the bottom, in the ‘height’ dimension.
+     * 5: An INT32 value, specifying the output stride in the ‘width’ dimension.
+     * 6: An INT32 value, specifying the output stride in the ‘height’ dimension.
+     * 7: An INT32 value, specifying the filter width.
+     * 8: An INT32 value, specifying the filter height.
+     * 9: An INT32 value, and has to be one of the {@link FusedActivationFunc} values.
+     *    Specifies the activation to invoke on the result of each addition.
+     *
+     * Ouputs:
+     * 0: The output 4-D tensor, of shape [batches, out_height, out_width, depth].
+     */
+    MAX_POOL_2D = 17,
+
+    /**
+     * Multiplies two tensors, elment-wise.
+     *
+     * Takes two input tensors of identical type 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 types: {@link OperandType::TENSOR_FLOAT32}
+     * Supported tensor rank: up to 4
+     *
+     * Inputs:
+     * 0: A tensor.
+     * 1: A tensor of the same type, and compatible dimensions as input0.
+     * 2: An INT32 value, and has to be one of the {@link FusedActivationFunc} values.
+     *    Specifies the activation to invoke on the result of each addition.
+     *
+     * Ouputs:
+     * 0: The product, a tensor of the same type as input0.
+     */
+    MUL = 18,
+
+    /**
+     * Computes rectified linear activation on the input tensor element-wise.
+     *
+     * In details:
+     *     output = max(0, input)
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: up to 4.
+     *
+     * Inputs:
+     * 0: A tensor, specifying the input.
+     *
+     * Ouputs:
+     * 0: The output tensor of same shape as input0.
+     */
+    RELU = 19,
+
+    /**
+     * Computes rectified linear 1 activation on the input tensor element-wise.
+     *
+     * In details:
+     *     output = min(1.f, max(-1.f, input))
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: up to 4.
+     *
+     * Inputs:
+     * 0: A tensor, specifying the input.
+     *
+     * Ouputs:
+     * 0: The output tensor of same shape as input0.
+     */
+    RELU1 = 20,
+
+    /**
+     * Computes rectified linear 6 activation on the input tensor element-wise.
+     *
+     * In details:
+     *     output = min(6, max(0, input))
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: up to 4.
+     *
+     * Inputs:
+     * 0: A tensor, specifying the input.
+     *
+     * Ouputs:
+     * 0: The output tensor of same shape as input0.
+     */
+    RELU6 = 21,
+
+    /**
+     * 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 types: {@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 type {@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.
+     *
+     * Ouputs:
+     * 0: The output tensor, of shape specified by the input shape.
+     */
+    RESHAPE = 22,
+
+    /**
+     * Resizes images to given size using the bilinear interpretation.
+     *
+     * Resized images will be distorted if their original aspect ratio is not the same as input.
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     * Supported tensor rank: 4, with "NHWC" data layout.
+     *
+     * Inputs:
+     * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying the input.
+     * 1: An INT32 value, specifying the output width of the output tensor.
+     * 2: An INT32 value, specifying the output height of the output tensor.
+     *
+     * Ouputs:
+     * 0: The output 4-D tensor, of shape [batches, new_height, new_width, depth].
+     */
+    RESIZE_BILINEAR = 23,
+
+    /**
+     * 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 types:
+     * * {@link OperandType::TENSOR_FLOAT32}
+     *
+     * Inputs:
+     * * 0: input.
+     *      A 2-D tensor of type T, 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 type T, of shape [num_units, input_size], where
+     *      “num_units” corresponds to the number of units.
+     * * 2: recurrent_weights.
+     *      A 2-D tensor of type T, of shape [num_units, num_units], with columns
+     *      corresponding to the weights from each unit.
+     * * 3: bias.
+     *      A 1-D tensor of type T, of shape [num_units].
+     *
+     *    For FLOAT32 input tensor, bias must also be FLOAT32.
+     *    For UINT8 input tensor, bias must be INT32.
+     *
+     * Parameters
+     * * 4: fused_activation_function.
+     *      An (optional) ActivationFunctionType indicating the activation
+     *      function. If “NONE” is specified then it results in a linear
+     *      activation.
+     *
+     * * 5: Hidden state.
+     *      A 2-D tensor of type T, of shape [batch_size, num_units].
+     *
+     * Outputs:
+     * * 0: output.
+     *      A 2-D tensor of type T, of shape [batch_size, num_units]. This is
+     *      effectively the same as the current state value.
+     */
+    RNN = 24,
+
+    /**
+     * Computes the softmax activation on the input tensor element-wise, per batch, by
+     * normalizing the input vector so the maximum coefficient is zero.
+     *
+     * In details:
+     *     output[batch, i] =
+     *         exp((input[batch, i] - max(input[batch, :])) * beta) /
+     *         sum_{k}{exp((input[batch, k] - max(input[batch, :])) * beta)}
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: 2 or 4.
+     *
+     * Inputs:
+     * 0: A 2-D or 4-D tensor, specifying the tensor to be reshaped.
+     * 1: A FLOAT32 value, specifying the scaling factor for the exponent, beta.
+     *
+     * Ouputs:
+     * 0: The output tensor of same shape as input0.
+     */
+    SOFTMAX = 25,
+
+    /**
+     * 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 types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: 4, with "NHWC" data layout.
+     *
+     * Inputs:
+     * 0: A 4-D tensor, of shape [batches, height, width, depth_in], specifying the input.
+     * 1: An INT32 value, specifying the block_size. block_size must be >=1 and
+     *    block_size must be a divisor of both the input height and width.
+     *
+     * Ouputs:
+     * 0: The output 4-D tensor, of shape [batch, height/block_size, width/block_size,
+     *    depth*block_size*block_size].
+     */
+    SPACE_TO_DEPTH = 26,
+
+    /**
+     * 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, "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 types:
+     * * {@link OperandType::TENSOR_FLOAT32}
+     *
+     * Inputs:
+     * * 0: input.
+     *      A 2-D tensor of type T, 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 type T, of shape [num_units, input_size], where
+     *      “num_units” corresponds to the number of units.
+     * * 2: weights_time.
+     *      A 2-D tensor of type T, of shape [num_units, memory_size], where
+     *      “memory_size” corresponds to the fixed-size of the memory.
+     * * 3: bias.
+     *      A optional 1-D tensor of type T, of shape [num_units].
+     *
+     *    For FLOAT32 input tensor, bias must also be FLOAT32.
+     *    For UINT8 input tensor, bias must be INT32.
+     *
+     * Parameters:
+     * * 4: rank.
+     *      The rank of the SVD approximation.
+     * * 5: fused_activation_function.
+     *      An (optional) ActivationFunctionType indicating the activation function.
+     *      If “NONE” is specified then it results in a linear activation.
+     *
+     * Outputs:
+     * * 0: state.
+     *      A 2-D tensor of type T, of shape [batch_size, (memory_size - 1) * num_units * rank].
+     * * 1: output.
+     *      A 2-D tensor of type T, of shape [batch_size, num_units].
+     */
+    SVDF = 27,
+
+    /**
+     * Computes hyperbolic tangent of input tensor element-wise.
+     *
+     * In details:
+     *     output = tanh(input)
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     * Supported tensor rank: up to 4.
+     *
+     * Inputs:
+     * 0: A tensor, specifying the input.
+     *
+     * Ouputs:
+     * 0: The output tensor of same shape as input0.
+     */
+    TANH = 28,
+
+    /**
+     * OEM specific operation.
+     *
+     * This operation is OEM specific. It should only be used for OEM applications.
+     */
+    OEM_OPERATION = 10000,
+};
+
+/**
+ * Fused activation function types.
+ */
+enum FusedActivationFunc : int32_t {
+    NONE  = 0,
+    RELU  = 1,
+    RELU1 = 2,
+    RELU6 = 3,
+};
+
+/**
+ * How an operand is used.
+ */
+enum OperandLifeTime : int32_t {
+    /**
+     * The operand is internal to the model.  It's created by an operation
+     * and consumed by other operations.
+     */
+    TEMPORARY_VARIABLE,
+
+    /**
+     * The operand is an input of the model. An operand can't be both
+     * input and output of a model.
+     */
+    MODEL_INPUT,
+
+    /**
+     * The operand is an output of the model.
+     */
+    MODEL_OUTPUT,
+
+    /**
+     * The operand is a constant found in Model.operandValues.
+     */
+    CONSTANT_COPY,
+
+    /**
+     * The operand is a constant that was specified via a Memory object.
+     */
+    CONSTANT_REFERENCE,
+
+    /**
+     * The operand does not have a value. This is valid only for optional arguments
+     * of operations.
+     */
+    NO_VALUE,
+};
+
+/**
+ * Status of a device.
+ */
+enum DeviceStatus : int32_t {
+    AVAILABLE,
+    BUSY,
+    OFFLINE,
+    UNKNOWN,
+};
+
+/**
+ * Performance information for the reference workload.
+ *
+ * Used by a driver to report its performance characteristics.
+ */
+struct PerformanceInfo {
+    /**
+     * Ratio of the time taken by the driver to execute the
+     * workload compared to the time the CPU would take for the
+     * same workload. A lower number is better.
+     */
+    float execTime;
+
+    /**
+     * Ratio of the energy used by the driver compared to what
+     * the CPU would use for doing the same workload. A lower number
+     * is better.
+     */
+    float powerUsage;
+};
+
+/**
+ * The capabilities of a driver.
+ */
+struct Capabilities {
+    /**
+     * Driver performance when operating on float32 data.
+     */
+    PerformanceInfo float32Performance;
+
+    /**
+     * Driver performance when operating on asymmetric 8-bit quantized data.
+     */
+    PerformanceInfo quantized8Performance;
+};
+
+/**
+ * Describes the location of a data object.
+ */
+struct DataLocation {
+    /**
+     * The index of the memory pool where this location is found.
+     */
+    uint32_t poolIndex;
+
+    /**
+     * Offset in bytes from the start of the pool.
+     */
+    uint32_t offset;
+
+    /**
+     * The length of the data in bytes.
+     */
+    uint32_t length;
+};
+
+/**
+ * Describes one operand of the model's graph.
+ */
+struct Operand {
+    /**
+     * Data type of the operand.
+     */
+    OperandType type;
+
+    /**
+     * Dimensions of the operand.
+     */
+    vec<uint32_t> dimensions;
+
+    /**
+     * The number of operations that use this operand as input.
+     */
+    uint32_t numberOfConsumers;
+
+    /**
+     * Quantized scale of the operand.
+     *
+     * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM or
+     * TENSOR_INT32.
+     */
+    float scale;
+
+    /**
+     * Quantized zero-point offset of the operand.
+     *
+     * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM.
+     */
+    int32_t zeroPoint;
+
+    /**
+     * How the operand is used.
+     */
+    OperandLifeTime lifetime;
+
+    /**
+     * Where to find the data for this operand.
+     * If the lifetime is TEMPORARY_VARIABLE, MODEL_INPUT, MODEL_OUTPUT, or NO_VALUE:
+     * - All the fields will be 0.
+     * If the lifetime is CONSTANT_COPY:
+     * - location.poolIndex is 0.
+     * - location.offset is the offset in bytes into Model.operandValues.
+     * - location.length is set.
+     * If the lifetime is CONSTANT_REFERENCE:
+     * - location.poolIndex is set.
+     * - location.offset is the offset in bytes into the specified pool.
+     * - location.length is set.
+     */
+    DataLocation location;
+};
+
+/**
+ * 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<uint32_t> inputs;
+
+    /**
+     * Describes the table that contains the indexes of the outputs of the
+     * operation. The offset is the index in the operandIndexes table.
+     */
+    vec<uint32_t> 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
+ * might not be known is the shape of the input tensors.
+ */
+struct Model {
+    /**
+     * All operands included in the model.
+     */
+    vec<Operand> operands;
+
+    /**
+     * All operations included in the model.
+     *
+     * The operations are sorted into execution order.
+     */
+    vec<Operation> operations;
+
+    /**
+     * Input indexes of the model.
+     *
+     * Each value corresponds to the index of the operand in "operands".
+     */
+    vec<uint32_t> inputIndexes;
+
+    /**
+     * Output indexes of the model.
+     *
+     * Each value corresponds to the index of the operand in "operands".
+     */
+    vec<uint32_t> 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<uint8_t> operandValues;
+
+    /**
+     * A collection of shared memory pools containing operand data that were
+     * registered by the model.
+     *
+     * An operand's value must be located here if and only if Operand::lifetime
+     * equals OperandLifeTime::CONSTANT_REFERENCE.
+     */
+    vec<memory> pools;
+};
+
+/**
+ * Metadata information specifying the location of the input or output data and
+ * any updates to the input or output operand.
+ */
+struct RequestArgument {
+    /**
+     * 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 and
+     * the dimensions vector is left empty.
+     */
+    bool hasNoValue;
+
+    /**
+     * The location within one of the memory pools passed in the Request.
+     */
+    DataLocation location;
+
+    /**
+     * Updated dimension information.
+     *
+     * If dimensions.size() > 0, dimension information was provided along with the
+     * argument.  This can be the case for models that accept inputs of varying size.
+     * This can't change the rank, just the value of the dimensions that were
+     * unspecified in the model.
+     */
+    vec<uint32_t> dimensions;
+};
+
+/**
+ * Inputs to be sent to and outputs to be retrieved from a prepared model.
+ *
+ * A Request serves two primary tasks:
+ * 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.
+ */
+struct Request {
+    /**
+     * Input data and information to be used in the execution of a prepared
+     * model.
+     *
+     * The index of the input corresponds to the index in Model.inputIndexes.
+     *   E.g., input[i] corresponds to Model.inputIndexes[i].
+     */
+    vec<RequestArgument> inputs;
+
+    /**
+     * Output data and information to be used in the execution of a prepared
+     * model.
+     *
+     * The index of the output corresponds to the index in Model.outputIndexes.
+     *   E.g., output[i] corresponds to Model.outputIndexes[i].
+     */
+    vec<RequestArgument> outputs;
+
+    /**
+     * A collection of shared memory pools containing operand data for both the
+     * inputs and the outputs to a model.
+     */
+    vec<memory> pools;
+};
+
+/**
+ * Return status of a function.
+ */
+enum ErrorStatus : int32_t {
+    NONE,
+    DEVICE_UNAVAILABLE,
+    GENERAL_FAILURE,
+    OUTPUT_INSUFFICIENT_SIZE,
+    INVALID_ARGUMENT,
+};
diff --git a/neuralnetworks/1.0/vts/OWNERS b/neuralnetworks/1.0/vts/OWNERS
new file mode 100644 (file)
index 0000000..59e7c28
--- /dev/null
@@ -0,0 +1,11 @@
+# Neuralnetworks team
+butlermichael@google.com
+dgross@google.com
+ijsung@google.com
+jeanluc@google.com
+miaowang@google.com
+yangni@google.com
+
+# VTS team
+yim@google.com
+yuexima@google.com
diff --git a/neuralnetworks/1.0/vts/functional/Android.bp b/neuralnetworks/1.0/vts/functional/Android.bp
new file mode 100644 (file)
index 0000000..e33ee77
--- /dev/null
@@ -0,0 +1,36 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+    name: "VtsHalNeuralnetworksV1_0TargetTest",
+    srcs: [
+        "Callbacks.cpp",
+        "GeneratedTestHarness.cpp",
+        "Models.cpp",
+        "VtsHalNeuralnetworksV1_0TargetTest.cpp",
+    ],
+    defaults: ["VtsHalTargetTestDefaults"],
+    static_libs: [
+        "android.hardware.neuralnetworks@1.0",
+        "android.hidl.allocator@1.0",
+        "android.hidl.memory@1.0",
+        "libhidlmemory",
+    ],
+    header_libs: [
+        "libneuralnetworks_generated_test_harness_headers",
+        "libneuralnetworks_generated_tests",
+    ],
+}
diff --git a/neuralnetworks/1.0/vts/functional/Callbacks.cpp b/neuralnetworks/1.0/vts/functional/Callbacks.cpp
new file mode 100644 (file)
index 0000000..46bf243
--- /dev/null
@@ -0,0 +1,127 @@
+#include "Callbacks.h"
+#include <android-base/logging.h>
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_0 {
+namespace implementation {
+
+CallbackBase::CallbackBase() : mNotified(false) {}
+
+CallbackBase::~CallbackBase() {
+    // Note that we cannot call CallbackBase::join_thread from here:
+    // CallbackBase is intended to be reference counted, and it is possible that
+    // the reference count drops to zero in the bound thread, causing the
+    // bound thread to call this destructor. If a thread tries to join
+    // itself, it throws an exception, producing a message like the
+    // following:
+    //
+    //     terminating with uncaught exception of type std::__1::system_error:
+    //     thread::join failed: Resource deadlock would occur
+}
+
+void CallbackBase::wait() {
+    std::unique_lock<std::mutex> lock(mMutex);
+    mCondition.wait(lock, [this]{return mNotified;});
+    join_thread_locked();
+}
+
+bool CallbackBase::on_finish(std::function<bool(void)> post_work) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    if (mPostWork != nullptr) {
+        LOG(ERROR) << "CallbackBase::on_finish -- a post-work function has already been bound to "
+                   "this callback object";
+        return false;
+    }
+    if (post_work == nullptr) {
+        LOG(ERROR) << "CallbackBase::on_finish -- the new post-work function is invalid";
+        return false;
+    }
+    mPostWork = std::move(post_work);
+    return true;
+}
+
+bool CallbackBase::bind_thread(std::thread&& asyncThread) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    if (mThread.joinable()) {
+        LOG(ERROR) << "CallbackBase::bind_thread -- a thread has already been bound to this "
+                   "callback object";
+        return false;
+    }
+    if (!asyncThread.joinable()) {
+        LOG(ERROR) << "CallbackBase::bind_thread -- the new thread is not joinable";
+        return false;
+    }
+    mThread = std::move(asyncThread);
+    return true;
+}
+
+void CallbackBase::join_thread() {
+    std::lock_guard<std::mutex> lock(mMutex);
+    join_thread_locked();
+}
+
+void CallbackBase::notify() {
+    {
+        std::lock_guard<std::mutex> lock(mMutex);
+        mNotified = true;
+        if (mPostWork != nullptr) {
+            bool success = mPostWork();
+            if (!success) {
+                LOG(ERROR) << "CallbackBase::notify -- post work failed";
+            }
+        }
+    }
+    mCondition.notify_all();
+}
+
+void CallbackBase::join_thread_locked() {
+    if (mThread.joinable()) {
+        mThread.join();
+    }
+}
+
+PreparedModelCallback::PreparedModelCallback() :
+        mErrorStatus(ErrorStatus::GENERAL_FAILURE), mPreparedModel(nullptr) {}
+
+PreparedModelCallback::~PreparedModelCallback() {}
+
+Return<void> PreparedModelCallback::notify(ErrorStatus errorStatus,
+                                           const sp<IPreparedModel>& preparedModel) {
+    mErrorStatus = errorStatus;
+    mPreparedModel = preparedModel;
+    CallbackBase::notify();
+    return Void();
+}
+
+ErrorStatus PreparedModelCallback::getStatus() {
+    wait();
+    return mErrorStatus;
+}
+
+sp<IPreparedModel> PreparedModelCallback::getPreparedModel() {
+    wait();
+    return mPreparedModel;
+}
+
+ExecutionCallback::ExecutionCallback() : mErrorStatus(ErrorStatus::GENERAL_FAILURE) {}
+
+ExecutionCallback::~ExecutionCallback() {}
+
+Return<void> ExecutionCallback::notify(ErrorStatus errorStatus) {
+    mErrorStatus = errorStatus;
+    CallbackBase::notify();
+    return Void();
+}
+
+ErrorStatus ExecutionCallback::getStatus() {
+    wait();
+    return mErrorStatus;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.0/vts/functional/Callbacks.h b/neuralnetworks/1.0/vts/functional/Callbacks.h
new file mode 100644 (file)
index 0000000..0e2ffb3
--- /dev/null
@@ -0,0 +1,319 @@
+#ifndef ANDROID_HARDWARE_NEURALNETWORKS_V1_0_CALLBACKS_H
+#define ANDROID_HARDWARE_NEURALNETWORKS_V1_0_CALLBACKS_H
+
+#include <android/hardware/neuralnetworks/1.0/IExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.0/IPreparedModelCallback.h>
+#include <chrono>
+#include <condition_variable>
+#include <functional>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <mutex>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+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;
+
+/**
+ * The CallbackBase class is used internally by the NeuralNetworks runtime to
+ * synchronize between different threads. An asynchronous task is launched
+ * paired with a callback object. When a client thread requires the output being
+ * generated by the asynchronous task, the client thread can wait for the result
+ * and be blocked until it has completed or a timeout condition has been
+ * reached. Any wait* may safely be called concurrently, even on the same
+ * callback object. When the asynchronous task has finished its workload, it
+ * must immediately call "notify". If the asynchronous task has failed to launch,
+ * the function that tried to launch the asynchronous task must immediately call
+ * "notify". This "notify" call awakens any client threads waiting on the
+ * callback object.
+ *
+ * callback object. When the asynchronous task has finished its workload or has
+ * failed to launch, it must immediately call "notify", awakening any client
+ * threads waiting on the callback object.
+ *
+ * The CallbackBase class implements some of the base synchronization common to
+ * both PrepareModelCallback and ExecutionCallback. For consistency, any HIDL
+ * callback class must inherit from CallbackBase as well as the HIDL callback
+ * interface it implements.
+ *
+ * This class exists to enable synchronization across HIDL. When synchronization
+ * is only required in the same process, consider using std::future, std::mutex,
+ * std::condition_variable, or std::experimental::latch instead.
+ */
+class CallbackBase {
+ public:
+    CallbackBase();
+    ~CallbackBase();
+
+    /**
+     * CallbackBase::wait blocks until notify has been called on the callback
+     * object.
+     */
+    void wait();
+
+    /**
+     * CallbackBase::wait_for blocks until notify has been called on the
+     * callback object or the time duration from the time the wait_for function
+     * was called has expired, whichever comes first.
+     *
+     * @return Status std::cv_status::no_timeout if the callback was notified
+     *                before the time duration expired, std::cv_status::timeout
+     *                otherwise.
+     */
+    template<class Rep, class Period>
+    std::cv_status wait_for(const std::chrono::duration<Rep,Period>& timeout_duration);
+
+    /**
+     * CallbackBase::on_finish binds a function to the callback object. This
+     * bound function will be executed when CallbackBase::notify is called,
+     * before any calls to wait* return. (Note that CallbackBase::wait_for can
+     * return std::cv_status::timeout before CallbackBase::notify is called for
+     * the first time, and hence before the bound function is executed.)
+     *
+     * The bound function must not synchronize with or otherwise access the
+     * callback object it is bound to, as this could cause a deadlock.
+     *
+     * CallbackBase::on_finish can be called at most once on a given callback
+     * object, and the call to CallbackBase::on_finish must finish before
+     * CallbackBase::notify is called.
+     *
+     * @param post_work Function to be invoked the first time
+     *                  CallbackBase::notify is called. Must have a target --
+     *                  i.e., must not compare equal to nullptr. post_work
+     *                  returns true if it successfully completes, false if it
+     *                  fails.
+     * @return bool True if the function was successfully bound, false if
+     *              unsuccessful.
+     *
+     * TODO: Why does the return value of the callback matter?
+     */
+    bool on_finish(std::function<bool(void)> post_work);
+
+    /**
+     * CallbackBase::bind_thread binds a thread to the event for later use by
+     * CallbackBase::join_thread.
+     *
+     * The thread must be passed using std::move.
+     *
+     * Once a thread is bound with CallbackBase::bind_thread, the client code
+     * should ensure that one of the following occurs before the event is
+     * destroyed:
+     * - CallbackBase::join_thread has been called.
+     * - CallbackBase::wait has been called.
+     * - CallbackBase::wait_for has been called and returned other than
+     *   std::cv_status::no_timeout.
+     *
+     * The bound thread shall not call any CallbackBase method with the
+     * exception of CallbackBase::notify, which it must call when the thread has
+     * finished its computation.
+     *
+     * CallbackBase::bind_thread can be called at most once on a given callback
+     * object.
+     *
+     * @param asyncThread Thread to be bound to the callback object. The thread
+     *                    object must represent a thread of execution -- i.e.,
+     *                    asyncThread.joinable() must be true.
+     * @return bool True if successful, false if thread was not properly bound.
+     */
+    bool bind_thread(std::thread&& asyncThread);
+
+    /**
+     * CallbackBase::join_thread ensures that the thread (if any) bound to this
+     * event with CallbackBase::bind_thread has fully finished and cleaned its
+     * resources. It is legal to call this function multiple times, concurrently
+     * or sequentially.
+     */
+    void join_thread();
+
+ protected:
+    /**
+     * CallbackBase::notify enables all prior and future wait* calls on the
+     * callback object to proceed. The call to CallbackBase::notify happens
+     * before any wait* calls on this callback object return (except in the case
+     * of wait_for timing out). The asynchronous call the callback object is
+     * paired with must ensure that any update to state that should be visible
+     * to the caller of wait* happens before the call to CallbackBase::notify.
+     *
+     * CallbackBase::notify must be called exactly once on a given callback
+     * object.
+     */
+    void notify();
+
+ private:
+    // Same as CallbackBase::join_thread but assumes we already hold a lock on
+    // mMutex.
+    void join_thread_locked();
+
+    bool                      mNotified;
+    std::mutex                mMutex;
+    std::condition_variable   mCondition;
+    std::function<bool(void)> mPostWork;
+    std::thread               mThread;
+};
+
+/**
+ * The PreparedModelCallback class is used to receive the error status of
+ * preparing a model as well as the prepared model from a task executing
+ * asynchronously with respect to the runtime. If a calling thread calls wait*
+ * or get* on a PreparedModelCallback object and the corresponding asynchronous
+ * task has not finished preparing the model, the calling thread will block
+ * until the asynchronous task has called notify. For more information on the
+ * synchronization behavior, refer to the CallbackBase class.
+ *
+ * This class inherits the basic blocking and signaling calls from
+ * CallbackBase, and implements the HIDL notify call from
+ * IPreparedModelCallback. This callback object is passed as an argument to
+ * IDevice::prepareModel.
+ */
+class PreparedModelCallback : public CallbackBase, public IPreparedModelCallback {
+ public:
+    PreparedModelCallback();
+    ~PreparedModelCallback() override;
+
+    /**
+     * IPreparedModelCallback::notify marks the callback object with the return
+     * status of the asynchronous model preparation along with the prepared
+     * model, and calls CallbackBase::notify, enabling all prior and future
+     * wait* calls on the PreparedModelCallback object to proceed. For more
+     * information on the synchronization behavior, refer to the CallbackBase
+     * class.
+     *
+     * IPreparedModelCallback::notify must be called exactly once on a given
+     * PreparedModelCallback object.
+     *
+     * @param status Error status returned from asynchronously preparing the
+     *               model; will be:
+     *               - NONE if the asynchronous preparation was successful
+     *               - DEVICE_UNAVAILABLE if driver is offline or busy
+     *               - GENERAL_FAILURE if there is an unspecified error
+     *               - INVALID_ARGUMENT if the input model is invalid
+     * @param preparedModel Returned model that has been prepared for execution,
+     *                      nullptr if the model was unable to be prepared.
+     */
+    Return<void> notify(ErrorStatus status, const sp<IPreparedModel>& preparedModel) override;
+
+    /**
+     * Retrieves the error status returned from the asynchronous task launched
+     * by IDevice::prepareModel. If IDevice::prepareModel has not finished
+     * asynchronously preparing the model, this call will block until the
+     * asynchronous task notifies the object.
+     *
+     * @return status Error status returned from asynchronously preparing the
+     *                model; will be:
+     *                - NONE if the asynchronous preparation was successful
+     *                - DEVICE_UNAVAILABLE if driver is offline or busy
+     *                - GENERAL_FAILURE if there is an unspecified error
+     *                - INVALID_ARGUMENT if the input model is invalid
+     */
+    ErrorStatus getStatus();
+
+    /**
+     * Retrieves the model that has been prepared for execution from the
+     * asynchronous task launched by IDevice::prepareModel. If
+     * IDevice::prepareModel has not finished asynchronously preparing the
+     * model, this call will block until the asynchronous task notifies the
+     * object.
+     *
+     * @return preparedModel Returned model that has been prepared for
+     *                       execution, nullptr if the model was unable to be
+     *                       prepared.
+     */
+    sp<IPreparedModel> getPreparedModel();
+
+ private:
+    ErrorStatus        mErrorStatus;
+    sp<IPreparedModel> mPreparedModel;
+};
+
+/**
+ * The ExecutionCallback class is used to receive the error status of the
+ * execution from a task executing asynchronously with respect to the runtime.
+ * If a calling thread calls wait* or get* on a PreparedModelCallback object and
+ * the corresponding asynchronous task has not finished the execution, the
+ * calling thread will block until the asynchronous task has called notify. For
+ * more information on the synchronization behavior, refer to the CallbackBase
+ * class.
+ *
+ * This class inherits the basic blocking and signaling calls from
+ * CallbackBase, and implements the HIDL notify call from
+ * IExecutionCallback. This callback object is passed as an argument to
+ * IPreparedModel::execute.
+ */
+class ExecutionCallback : public CallbackBase,  public IExecutionCallback {
+ public:
+    ExecutionCallback();
+    ~ExecutionCallback() override;
+
+    /**
+     * IExecutionCallback::notify marks the callback object with the return
+     * status of the asynchronous execution that held this callback and enables
+     * all prior and future wait* calls on the ExecutionCallback object to
+     * proceed. For more information on the synchronization behavior, refer to
+     * the CallbackBase class.
+     *
+     * IExecutionCallback::notify must be called exactly once on a given
+     * ExecutionCallback object.
+     *
+     * @param status Error status returned from asynchronously preparing the
+     *               model; will be:
+     *               - NONE if the asynchronous execution was successful
+     *               - DEVICE_UNAVAILABLE if driver is offline or busy
+     *               - GENERAL_FAILURE if there is an unspecified error
+     *               - OUTPUT_INSUFFICIENT_SIZE if provided output buffer is
+     *                 not large enough to store the resultant values
+     *               - INVALID_ARGUMENT if the input request is invalid
+     */
+    Return<void> notify(ErrorStatus status) override;
+
+    /**
+     * Retrieves the error status returned from the asynchronous task launched
+     * by IPreparedModel::execute. If IPreparedModel::execute has not finished
+     * asynchronously executing, this call will block until the asynchronous task
+     * notifies the object.
+     *
+     * @return status Error status returned from asynchronously preparing the
+     *                model; will be:
+     *                - NONE if the asynchronous execution was successful
+     *                - DEVICE_UNAVAILABLE if driver is offline or busy
+     *                - GENERAL_FAILURE if there is an unspecified error
+     *                - OUTPUT_INSUFFICIENT_SIZE if provided output buffer is
+     *                  not large enough to store the resultant values
+     *                - INVALID_ARGUMENT if the input request is invalid
+     */
+    ErrorStatus getStatus();
+
+ private:
+    ErrorStatus mErrorStatus;
+};
+
+
+// template function implementation(s) below this point
+
+template<class Rep, class Period>
+std::cv_status CallbackBase::wait_for(const std::chrono::duration<Rep,Period>& timeout_duration) {
+    std::unique_lock<std::mutex> lock(mMutex);
+    std::cv_status status = mCondition.wait_for(lock, timeout_duration, [this]{return mNotified;});
+    if (status != std::cv_status::timeout) {
+        join_thread_locked();
+    }
+    return status;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_NEURALNETWORKS_V1_0_CALLBACKS_H
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
new file mode 100644 (file)
index 0000000..d740b5f
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * 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 "Callbacks.h"
+#include "TestHarness.h"
+#include "VtsHalNeuralnetworksV1_0TargetTest.h"
+
+#include <android-base/logging.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <hidlmemory/mapping.h>
+#include <iostream>
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_0 {
+namespace vts {
+namespace functional {
+// allocator helper
+hidl_memory allocateSharedMemory(int64_t size, const std::string& type = "ashmem");
+
+namespace generated_tests {
+using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+using ::generated_tests::filter;
+using ::generated_tests::for_all;
+using ::generated_tests::for_each;
+using ::generated_tests::resize_accordingly;
+using ::generated_tests::MixedTyped;
+using ::generated_tests::MixedTypedExampleType;
+using ::generated_tests::Float32Operands;
+using ::generated_tests::Int32Operands;
+using ::generated_tests::Quant8Operands;
+using ::generated_tests::compare;
+
+template <typename T>
+void copy_back_(MixedTyped* dst, const std::vector<RequestArgument>& ra, char* src) {
+    MixedTyped& test = *dst;
+    for_each<T>(test, [&ra, src](int index, std::vector<T>& m) {
+        ASSERT_EQ(m.size(), ra[index].location.length / sizeof(T));
+        char* begin = src + ra[index].location.offset;
+        memcpy(m.data(), begin, ra[index].location.length);
+    });
+}
+
+void copy_back(MixedTyped* dst, const std::vector<RequestArgument>& ra, char* src) {
+    copy_back_<float>(dst, ra, src);
+    copy_back_<int32_t>(dst, ra, src);
+    copy_back_<uint8_t>(dst, ra, src);
+}
+
+// Top level driver for models and examples generated by test_generator.py
+// Test driver for those generated from ml/nn/runtime/test/spec
+void Execute(const sp<IDevice>& device, std::function<Model(void)> create_model,
+             std::function<bool(int)> is_ignored,
+             const std::vector<MixedTypedExampleType>& examples) {
+    const uint32_t INPUT = 0;
+    const uint32_t OUTPUT = 1;
+    Model model = create_model();
+
+    // see if service can handle model
+    ErrorStatus supportedStatus;
+    bool fullySupportsModel = false;
+    Return<void> supportedCall = device->getSupportedOperations(
+        model, [&](ErrorStatus status, const hidl_vec<bool>& supported) {
+            supportedStatus = status;
+            ASSERT_NE(0ul, supported.size());
+            fullySupportsModel =
+                std::all_of(supported.begin(), supported.end(), [](bool valid) { return valid; });
+        });
+    ASSERT_TRUE(supportedCall.isOk());
+    ASSERT_EQ(ErrorStatus::NONE, supportedStatus);
+
+    // launch prepare model
+    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
+    ASSERT_NE(nullptr, preparedModelCallback.get());
+    Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback);
+    ASSERT_TRUE(prepareLaunchStatus.isOk());
+
+    // retrieve prepared model
+    preparedModelCallback->wait();
+    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
+    sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
+    if (fullySupportsModel) {
+        EXPECT_EQ(ErrorStatus::NONE, prepareReturnStatus);
+    } else {
+        EXPECT_TRUE(prepareReturnStatus == ErrorStatus::NONE ||
+                    prepareReturnStatus == ErrorStatus::GENERAL_FAILURE);
+    }
+
+    // early termination if vendor service cannot fully prepare model
+    if (!fullySupportsModel && prepareReturnStatus == ErrorStatus::GENERAL_FAILURE) {
+        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;
+    }
+    ASSERT_NE(nullptr, preparedModel.get());
+
+    int example_no = 1;
+    for (auto& example : examples) {
+        SCOPED_TRACE(example_no++);
+
+        const MixedTyped& inputs = example.first;
+        const MixedTyped& golden = example.second;
+
+        std::vector<RequestArgument> 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<size_t>(index)) inputs_info.resize(index + 1);
+            RequestArgument arg = {
+                .location = {.poolIndex = INPUT, .offset = 0, .length = static_cast<uint32_t>(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;
+            }
+        }
+
+        MixedTyped test;  // holding test results
+
+        // Go through all outputs, initialize RequestArgument descriptors
+        resize_accordingly(golden, test);
+        for_all(golden, [&outputs_info, &outputSize](int index, auto, auto s) {
+            if (outputs_info.size() <= static_cast<size_t>(index)) outputs_info.resize(index + 1);
+            RequestArgument arg = {
+                .location = {.poolIndex = OUTPUT, .offset = 0, .length = static_cast<uint32_t>(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<hidl_memory> pools = {allocateSharedMemory(inputSize),
+                                          allocateSharedMemory(outputSize)};
+        ASSERT_NE(0ull, pools[INPUT].size());
+        ASSERT_NE(0ull, pools[OUTPUT].size());
+
+        // load data
+        sp<IMemory> inputMemory = mapMemory(pools[INPUT]);
+        sp<IMemory> outputMemory = mapMemory(pools[OUTPUT]);
+        ASSERT_NE(nullptr, inputMemory.get());
+        ASSERT_NE(nullptr, outputMemory.get());
+        char* inputPtr = reinterpret_cast<char*>(static_cast<void*>(inputMemory->getPointer()));
+        char* outputPtr = reinterpret_cast<char*>(static_cast<void*>(outputMemory->getPointer()));
+        ASSERT_NE(nullptr, inputPtr);
+        ASSERT_NE(nullptr, outputPtr);
+        inputMemory->update();
+        outputMemory->update();
+
+        // Go through all inputs, copy the values
+        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();
+        outputMemory->commit();
+
+        // launch execution
+        sp<ExecutionCallback> executionCallback = new ExecutionCallback();
+        ASSERT_NE(nullptr, executionCallback.get());
+        Return<ErrorStatus> executionLaunchStatus = preparedModel->execute(
+            {.inputs = inputs_info, .outputs = outputs_info, .pools = pools}, executionCallback);
+        ASSERT_TRUE(executionLaunchStatus.isOk());
+        EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(executionLaunchStatus));
+
+        // retrieve execution status
+        executionCallback->wait();
+        ErrorStatus executionReturnStatus = executionCallback->getStatus();
+        EXPECT_EQ(ErrorStatus::NONE, executionReturnStatus);
+
+        // validate results
+        outputMemory->read();
+        copy_back(&test, outputs_info, outputPtr);
+        outputMemory->commit();
+        // Filter out don't cares
+        MixedTyped filtered_golden = filter(golden, is_ignored);
+        MixedTyped filtered_test = filter(test, is_ignored);
+
+        // We want "close-enough" results for float
+        compare(filtered_golden, filtered_test);
+    }
+}
+
+}  // namespace generated_tests
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_0
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.0/vts/functional/Models.cpp b/neuralnetworks/1.0/vts/functional/Models.cpp
new file mode 100644 (file)
index 0000000..8ce4f25
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * 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 "neuralnetworks_hidl_hal_test"
+
+#include "Models.h"
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <hidlmemory/mapping.h>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_0 {
+namespace vts {
+namespace functional {
+
+// create a valid model
+Model createValidTestModel() {
+    const std::vector<float> operand2Data = {5.0f, 6.0f, 7.0f, 8.0f};
+    const uint32_t size = operand2Data.size() * sizeof(float);
+
+    const uint32_t operand1 = 0;
+    const uint32_t operand2 = 1;
+    const uint32_t operand3 = 2;
+    const uint32_t operand4 = 3;
+
+    const std::vector<Operand> operands = {
+        {
+            .type = OperandType::TENSOR_FLOAT32,
+            .dimensions = {1, 2, 2, 1},
+            .numberOfConsumers = 1,
+            .scale = 0.0f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::MODEL_INPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        },
+        {
+            .type = OperandType::TENSOR_FLOAT32,
+            .dimensions = {1, 2, 2, 1},
+            .numberOfConsumers = 1,
+            .scale = 0.0f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::CONSTANT_COPY,
+            .location = {.poolIndex = 0, .offset = 0, .length = size},
+        },
+        {
+            .type = OperandType::INT32,
+            .dimensions = {},
+            .numberOfConsumers = 1,
+            .scale = 0.0f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::CONSTANT_COPY,
+            .location = {.poolIndex = 0, .offset = size, .length = sizeof(int32_t)},
+        },
+        {
+            .type = OperandType::TENSOR_FLOAT32,
+            .dimensions = {1, 2, 2, 1},
+            .numberOfConsumers = 0,
+            .scale = 0.0f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::MODEL_OUTPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        },
+    };
+
+    const std::vector<Operation> operations = {{
+        .type = OperationType::ADD, .inputs = {operand1, operand2, operand3}, .outputs = {operand4},
+    }};
+
+    const std::vector<uint32_t> inputIndexes = {operand1};
+    const std::vector<uint32_t> outputIndexes = {operand4};
+    std::vector<uint8_t> operandValues(
+        reinterpret_cast<const uint8_t*>(operand2Data.data()),
+        reinterpret_cast<const uint8_t*>(operand2Data.data()) + size);
+    int32_t activation[1] = {static_cast<int32_t>(FusedActivationFunc::NONE)};
+    operandValues.insert(operandValues.end(), reinterpret_cast<const uint8_t*>(&activation[0]),
+                         reinterpret_cast<const uint8_t*>(&activation[1]));
+
+    const std::vector<hidl_memory> pools = {};
+
+    return {
+        .operands = operands,
+        .operations = operations,
+        .inputIndexes = inputIndexes,
+        .outputIndexes = outputIndexes,
+        .operandValues = operandValues,
+        .pools = pools,
+    };
+}
+
+// create first invalid model
+Model createInvalidTestModel1() {
+    Model model = createValidTestModel();
+    model.operations[0].type = static_cast<OperationType>(0xDEADBEEF); /* INVALID */
+    return model;
+}
+
+// create second invalid model
+Model createInvalidTestModel2() {
+    Model model = createValidTestModel();
+    const uint32_t operand1 = 0;
+    const uint32_t operand5 = 4;  // INVALID OPERAND
+    model.inputIndexes = std::vector<uint32_t>({operand1, operand5 /* INVALID OPERAND */});
+    return model;
+}
+
+// allocator helper
+hidl_memory allocateSharedMemory(int64_t size, const std::string& type = "ashmem") {
+    hidl_memory memory;
+
+    sp<IAllocator> allocator = IAllocator::getService(type);
+    if (!allocator.get()) {
+        return {};
+    }
+
+    Return<void> ret = allocator->allocate(size, [&](bool success, const hidl_memory& mem) {
+        ASSERT_TRUE(success);
+        memory = mem;
+    });
+    if (!ret.isOk()) {
+        return {};
+    }
+
+    return memory;
+}
+
+// create a valid request
+Request createValidTestRequest() {
+    std::vector<float> inputData = {1.0f, 2.0f, 3.0f, 4.0f};
+    std::vector<float> outputData = {-1.0f, -1.0f, -1.0f, -1.0f};
+    const uint32_t INPUT = 0;
+    const uint32_t OUTPUT = 1;
+
+    // prepare inputs
+    uint32_t inputSize = static_cast<uint32_t>(inputData.size() * sizeof(float));
+    uint32_t outputSize = static_cast<uint32_t>(outputData.size() * sizeof(float));
+    std::vector<RequestArgument> inputs = {{
+        .location = {.poolIndex = INPUT, .offset = 0, .length = inputSize}, .dimensions = {},
+    }};
+    std::vector<RequestArgument> outputs = {{
+        .location = {.poolIndex = OUTPUT, .offset = 0, .length = outputSize}, .dimensions = {},
+    }};
+    std::vector<hidl_memory> pools = {allocateSharedMemory(inputSize),
+                                      allocateSharedMemory(outputSize)};
+    if (pools[INPUT].size() == 0 || pools[OUTPUT].size() == 0) {
+        return {};
+    }
+
+    // load data
+    sp<IMemory> inputMemory = mapMemory(pools[INPUT]);
+    sp<IMemory> outputMemory = mapMemory(pools[OUTPUT]);
+    if (inputMemory.get() == nullptr || outputMemory.get() == nullptr) {
+        return {};
+    }
+    float* inputPtr = reinterpret_cast<float*>(static_cast<void*>(inputMemory->getPointer()));
+    float* outputPtr = reinterpret_cast<float*>(static_cast<void*>(outputMemory->getPointer()));
+    if (inputPtr == nullptr || outputPtr == nullptr) {
+        return {};
+    }
+    inputMemory->update();
+    outputMemory->update();
+    std::copy(inputData.begin(), inputData.end(), inputPtr);
+    std::copy(outputData.begin(), outputData.end(), outputPtr);
+    inputMemory->commit();
+    outputMemory->commit();
+
+    return {.inputs = inputs, .outputs = outputs, .pools = pools};
+}
+
+// create first invalid request
+Request createInvalidTestRequest1() {
+    Request request = createValidTestRequest();
+    const uint32_t INVALID = 2;
+    std::vector<float> inputData = {1.0f, 2.0f, 3.0f, 4.0f};
+    uint32_t inputSize = static_cast<uint32_t>(inputData.size() * sizeof(float));
+    request.inputs[0].location = {
+        .poolIndex = INVALID /* INVALID */, .offset = 0, .length = inputSize};
+    return request;
+}
+
+// create second invalid request
+Request createInvalidTestRequest2() {
+    Request request = createValidTestRequest();
+    request.inputs[0].dimensions = std::vector<uint32_t>({1, 2, 3, 4, 5, 6, 7, 8} /* INVALID */);
+    return request;
+}
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_0
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.0/vts/functional/Models.h b/neuralnetworks/1.0/vts/functional/Models.h
new file mode 100644 (file)
index 0000000..e0d57d5
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * 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 "neuralnetworks_hidl_hal_test"
+
+#include "VtsHalNeuralnetworksV1_0TargetTest.h"
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_0 {
+namespace vts {
+namespace functional {
+
+// create the model
+Model createValidTestModel();
+Model createInvalidTestModel1();
+Model createInvalidTestModel2();
+
+// create the request
+Request createValidTestRequest();
+Request createInvalidTestRequest1();
+Request createInvalidTestRequest2();
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_0
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.cpp b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.cpp
new file mode 100644 (file)
index 0000000..b99e20e
--- /dev/null
@@ -0,0 +1,296 @@
+/*
+ * 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 "neuralnetworks_hidl_hal_test"
+
+#include "VtsHalNeuralnetworksV1_0TargetTest.h"
+
+#include "Callbacks.h"
+#include "Models.h"
+#include "TestHarness.h"
+
+#include <android-base/logging.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <hidlmemory/mapping.h>
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_0 {
+namespace vts {
+namespace functional {
+
+using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+using ::generated_tests::MixedTypedExampleType;
+
+namespace generated_tests {
+extern void Execute(const sp<IDevice>&, std::function<Model(void)>, std::function<bool(int)>,
+                    const std::vector<MixedTypedExampleType>&);
+}
+
+// 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<IDevice>();
+}
+
+// The main test class for NEURALNETWORK HIDL HAL.
+NeuralnetworksHidlTest::~NeuralnetworksHidlTest() {}
+
+void NeuralnetworksHidlTest::SetUp() {
+    device = ::testing::VtsHalHidlTargetTestBase::getService<IDevice>(
+        NeuralnetworksHidlEnvironment::getInstance());
+    ASSERT_NE(nullptr, device.get());
+}
+
+void NeuralnetworksHidlTest::TearDown() {}
+
+sp<IPreparedModel> NeuralnetworksHidlTest::doPrepareModelShortcut() {
+    Model model = createValidTestModel();
+
+    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
+    if (preparedModelCallback == nullptr) {
+        return nullptr;
+    }
+    Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback);
+    if (!prepareLaunchStatus.isOk() || prepareLaunchStatus != ErrorStatus::NONE) {
+        return nullptr;
+    }
+
+    preparedModelCallback->wait();
+    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
+    sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
+    if (prepareReturnStatus != ErrorStatus::NONE || preparedModel == nullptr) {
+        return nullptr;
+    }
+
+    return preparedModel;
+}
+
+// create device test
+TEST_F(NeuralnetworksHidlTest, CreateDevice) {}
+
+// status test
+TEST_F(NeuralnetworksHidlTest, StatusTest) {
+    Return<DeviceStatus> status = device->getStatus();
+    ASSERT_TRUE(status.isOk());
+    EXPECT_EQ(DeviceStatus::AVAILABLE, static_cast<DeviceStatus>(status));
+}
+
+// initialization
+TEST_F(NeuralnetworksHidlTest, GetCapabilitiesTest) {
+    Return<void> ret =
+        device->getCapabilities([](ErrorStatus status, const Capabilities& capabilities) {
+            EXPECT_EQ(ErrorStatus::NONE, status);
+            EXPECT_LT(0.0f, capabilities.float32Performance.execTime);
+            EXPECT_LT(0.0f, capabilities.float32Performance.powerUsage);
+            EXPECT_LT(0.0f, capabilities.quantized8Performance.execTime);
+            EXPECT_LT(0.0f, capabilities.quantized8Performance.powerUsage);
+        });
+    EXPECT_TRUE(ret.isOk());
+}
+
+// supported operations positive test
+TEST_F(NeuralnetworksHidlTest, SupportedOperationsPositiveTest) {
+    Model model = createValidTestModel();
+    Return<void> ret = device->getSupportedOperations(
+        model, [&](ErrorStatus status, const hidl_vec<bool>& supported) {
+            EXPECT_EQ(ErrorStatus::NONE, status);
+            EXPECT_EQ(model.operations.size(), supported.size());
+        });
+    EXPECT_TRUE(ret.isOk());
+}
+
+// supported operations negative test 1
+TEST_F(NeuralnetworksHidlTest, SupportedOperationsNegativeTest1) {
+    Model model = createInvalidTestModel1();
+    Return<void> ret = device->getSupportedOperations(
+        model, [&](ErrorStatus status, const hidl_vec<bool>& supported) {
+            EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
+            (void)supported;
+        });
+    EXPECT_TRUE(ret.isOk());
+}
+
+// supported operations negative test 2
+TEST_F(NeuralnetworksHidlTest, SupportedOperationsNegativeTest2) {
+    Model model = createInvalidTestModel2();
+    Return<void> ret = device->getSupportedOperations(
+        model, [&](ErrorStatus status, const hidl_vec<bool>& supported) {
+            EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
+            (void)supported;
+        });
+    EXPECT_TRUE(ret.isOk());
+}
+
+// prepare simple model positive test
+TEST_F(NeuralnetworksHidlTest, SimplePrepareModelPositiveTest) {
+    Model model = createValidTestModel();
+    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
+    ASSERT_NE(nullptr, preparedModelCallback.get());
+    Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback);
+    ASSERT_TRUE(prepareLaunchStatus.isOk());
+    EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(prepareLaunchStatus));
+
+    preparedModelCallback->wait();
+    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
+    EXPECT_EQ(ErrorStatus::NONE, prepareReturnStatus);
+    sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
+    EXPECT_NE(nullptr, preparedModel.get());
+}
+
+// prepare simple model negative test 1
+TEST_F(NeuralnetworksHidlTest, SimplePrepareModelNegativeTest1) {
+    Model model = createInvalidTestModel1();
+    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
+    ASSERT_NE(nullptr, preparedModelCallback.get());
+    Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback);
+    ASSERT_TRUE(prepareLaunchStatus.isOk());
+    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(prepareLaunchStatus));
+
+    preparedModelCallback->wait();
+    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
+    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, prepareReturnStatus);
+    sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
+    EXPECT_EQ(nullptr, preparedModel.get());
+}
+
+// prepare simple model negative test 2
+TEST_F(NeuralnetworksHidlTest, SimplePrepareModelNegativeTest2) {
+    Model model = createInvalidTestModel2();
+    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
+    ASSERT_NE(nullptr, preparedModelCallback.get());
+    Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback);
+    ASSERT_TRUE(prepareLaunchStatus.isOk());
+    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(prepareLaunchStatus));
+
+    preparedModelCallback->wait();
+    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
+    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, prepareReturnStatus);
+    sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
+    EXPECT_EQ(nullptr, preparedModel.get());
+}
+
+// execute simple graph positive test
+TEST_F(NeuralnetworksHidlTest, SimpleExecuteGraphPositiveTest) {
+    std::vector<float> outputData = {-1.0f, -1.0f, -1.0f, -1.0f};
+    std::vector<float> expectedData = {6.0f, 8.0f, 10.0f, 12.0f};
+    const uint32_t OUTPUT = 1;
+
+    sp<IPreparedModel> preparedModel = doPrepareModelShortcut();
+    ASSERT_NE(nullptr, preparedModel.get());
+    Request request = createValidTestRequest();
+
+    auto postWork = [&] {
+        sp<IMemory> outputMemory = mapMemory(request.pools[OUTPUT]);
+        if (outputMemory == nullptr) {
+            return false;
+        }
+        float* outputPtr = reinterpret_cast<float*>(static_cast<void*>(outputMemory->getPointer()));
+        if (outputPtr == nullptr) {
+            return false;
+        }
+        outputMemory->read();
+        std::copy(outputPtr, outputPtr + outputData.size(), outputData.begin());
+        outputMemory->commit();
+        return true;
+    };
+
+    sp<ExecutionCallback> executionCallback = new ExecutionCallback();
+    ASSERT_NE(nullptr, executionCallback.get());
+    executionCallback->on_finish(postWork);
+    Return<ErrorStatus> executeLaunchStatus = preparedModel->execute(request, executionCallback);
+    ASSERT_TRUE(executeLaunchStatus.isOk());
+    EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(executeLaunchStatus));
+
+    executionCallback->wait();
+    ErrorStatus executionReturnStatus = executionCallback->getStatus();
+    EXPECT_EQ(ErrorStatus::NONE, executionReturnStatus);
+    EXPECT_EQ(expectedData, outputData);
+}
+
+// execute simple graph negative test 1
+TEST_F(NeuralnetworksHidlTest, SimpleExecuteGraphNegativeTest1) {
+    sp<IPreparedModel> preparedModel = doPrepareModelShortcut();
+    ASSERT_NE(nullptr, preparedModel.get());
+    Request request = createInvalidTestRequest1();
+
+    sp<ExecutionCallback> executionCallback = new ExecutionCallback();
+    ASSERT_NE(nullptr, executionCallback.get());
+    Return<ErrorStatus> executeLaunchStatus = preparedModel->execute(request, executionCallback);
+    ASSERT_TRUE(executeLaunchStatus.isOk());
+    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(executeLaunchStatus));
+
+    executionCallback->wait();
+    ErrorStatus executionReturnStatus = executionCallback->getStatus();
+    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, executionReturnStatus);
+}
+
+// execute simple graph negative test 2
+TEST_F(NeuralnetworksHidlTest, SimpleExecuteGraphNegativeTest2) {
+    sp<IPreparedModel> preparedModel = doPrepareModelShortcut();
+    ASSERT_NE(nullptr, preparedModel.get());
+    Request request = createInvalidTestRequest2();
+
+    sp<ExecutionCallback> executionCallback = new ExecutionCallback();
+    ASSERT_NE(nullptr, executionCallback.get());
+    Return<ErrorStatus> executeLaunchStatus = preparedModel->execute(request, executionCallback);
+    ASSERT_TRUE(executeLaunchStatus.isOk());
+    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(executeLaunchStatus));
+
+    executionCallback->wait();
+    ErrorStatus executionReturnStatus = executionCallback->getStatus();
+    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, executionReturnStatus);
+}
+
+// Mixed-typed examples
+typedef MixedTypedExampleType MixedTypedExample;
+
+// in frameworks/ml/nn/runtime/tests/generated/
+#include "all_generated_vts_tests.cpp"
+
+// TODO: Add tests for execution failure, or wait_for/wait_until timeout.
+//       Discussion:
+//       https://googleplex-android-review.git.corp.google.com/#/c/platform/hardware/interfaces/+/2654636/5/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.cpp@222
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_0
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
+
+using android::hardware::neuralnetworks::V1_0::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.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.h b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.h
new file mode 100644 (file)
index 0000000..5cd209a
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * 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 VTS_HAL_NEURALNETWORKS_V1_0_TARGET_TESTS_H
+#define VTS_HAL_NEURALNETWORKS_V1_0_TARGET_TESTS_H
+
+#include <android/hardware/neuralnetworks/1.0/IDevice.h>
+#include <android/hardware/neuralnetworks/1.0/IExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.0/IPreparedModel.h>
+#include <android/hardware/neuralnetworks/1.0/IPreparedModelCallback.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hidl/allocator/1.0/IAllocator.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+#include <gtest/gtest.h>
+#include <string>
+
+using ::android::hardware::neuralnetworks::V1_0::IDevice;
+using ::android::hardware::neuralnetworks::V1_0::IPreparedModel;
+using ::android::hardware::neuralnetworks::V1_0::Capabilities;
+using ::android::hardware::neuralnetworks::V1_0::DeviceStatus;
+using ::android::hardware::neuralnetworks::V1_0::FusedActivationFunc;
+using ::android::hardware::neuralnetworks::V1_0::Model;
+using ::android::hardware::neuralnetworks::V1_0::OperationType;
+using ::android::hardware::neuralnetworks::V1_0::PerformanceInfo;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hidl::allocator::V1_0::IAllocator;
+using ::android::hidl::memory::V1_0::IMemory;
+using ::android::sp;
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_0 {
+namespace vts {
+namespace functional {
+
+// A class for test environment setup
+class NeuralnetworksHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+    NeuralnetworksHidlEnvironment();
+    NeuralnetworksHidlEnvironment(const NeuralnetworksHidlEnvironment&) = delete;
+    NeuralnetworksHidlEnvironment(NeuralnetworksHidlEnvironment&&) = delete;
+    NeuralnetworksHidlEnvironment& operator=(const NeuralnetworksHidlEnvironment&) = delete;
+    NeuralnetworksHidlEnvironment& operator=(NeuralnetworksHidlEnvironment&&) = delete;
+
+   public:
+    ~NeuralnetworksHidlEnvironment() override;
+    static NeuralnetworksHidlEnvironment* getInstance();
+    void registerTestServices() override;
+};
+
+// The main test class for NEURALNETWORKS HIDL HAL.
+class NeuralnetworksHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    ~NeuralnetworksHidlTest() override;
+    void SetUp() override;
+    void TearDown() override;
+
+    sp<IPreparedModel> doPrepareModelShortcut();
+
+    sp<IDevice> device;
+};
+
+}  // namespace functional
+}  // namespace vts
+
+// pretty-print values for error messages
+
+template<typename CharT, typename Traits>
+::std::basic_ostream<CharT, Traits>& operator<<(::std::basic_ostream<CharT, Traits>& os,
+                                                ErrorStatus errorStatus) {
+    return os << toString(errorStatus);
+}
+
+template<typename CharT, typename Traits>
+::std::basic_ostream<CharT, Traits>& operator<<(::std::basic_ostream<CharT, Traits>& os,
+                                                DeviceStatus deviceStatus) {
+    return os << toString(deviceStatus);
+}
+
+}  // namespace V1_0
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
+
+#endif  // VTS_HAL_NEURALNETWORKS_V1_0_TARGET_TESTS_H
diff --git a/neuralnetworks/Android.bp b/neuralnetworks/Android.bp
new file mode 100644 (file)
index 0000000..33f70eb
--- /dev/null
@@ -0,0 +1,5 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "1.0",
+    "1.0/vts/functional",
+]
index 7c9a66e..4adb32c 100644 (file)
@@ -46,13 +46,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.nfc@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.nfc@1.0_genc++"],
     generated_headers: ["android.hardware.nfc@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.nfc@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index d9ba702..3861bd4 100644 (file)
 
 cc_test {
     name: "VtsHalNfcV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalNfcV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
+    static_libs: [
         "android.hardware.nfc@1.0",
     ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
 }
index 21e7271..742061d 100644 (file)
@@ -39,13 +39,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.oemlock@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.oemlock@1.0_genc++"],
     generated_headers: ["android.hardware.oemlock@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.oemlock@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index a13b3dc..20737a1 100644 (file)
 
 cc_test {
     name: "VtsHalOemLockV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalOemLockV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
-        "android.hardware.oemlock@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
+    static_libs: ["android.hardware.oemlock@1.0"],
 }
index 1d967fd..bc886cb 100644 (file)
@@ -39,13 +39,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.power@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.power@1.0_genc++"],
     generated_headers: ["android.hardware.power@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.power@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index 5ab1eb4..45f74fc 100644 (file)
 
 cc_test {
     name: "VtsHalPowerV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalPowerV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
-        "android.hardware.power@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ]
+    static_libs: ["android.hardware.power@1.0"],
 }
index bfc140f..fb10aba 100644 (file)
@@ -39,13 +39,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.power@1.1",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.power@1.1_genc++"],
     generated_headers: ["android.hardware.power@1.1_genc++_headers"],
     export_generated_headers: ["android.hardware.power@1.1_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/power/1.1/default/Power.cpp b/power/1.1/default/Power.cpp
deleted file mode 100644 (file)
index b5d0c84..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "android.hardware.power@1.1-impl"
-
-#include <log/log.h>
-
-#include <hardware/hardware.h>
-#include <hardware/power.h>
-
-#include "Power.h"
-
-namespace android {
-namespace hardware {
-namespace power {
-namespace V1_1 {
-namespace implementation {
-
-using ::android::hardware::power::V1_0::Feature;
-using ::android::hardware::power::V1_0::PowerHint;
-using ::android::hardware::power::V1_0::PowerStatePlatformSleepState;
-using ::android::hardware::power::V1_0::Status;
-using ::android::hardware::power::V1_1::PowerStateSubsystem;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-
-Power::Power(power_module_t *module) : mModule(module) {
-    if (mModule)
-        mModule->init(mModule);
-}
-
-Power::~Power() {
-    delete(mModule);
-}
-
-// Methods from ::android::hardware::power::V1_0::IPower follow.
-Return<void> Power::setInteractive(bool interactive)  {
-    if (mModule->setInteractive)
-        mModule->setInteractive(mModule, interactive ? 1 : 0);
-    return Void();
-}
-
-Return<void> Power::powerHint(PowerHint hint, int32_t data)  {
-    int32_t param = data;
-    if (mModule->powerHint) {
-        if (data)
-            mModule->powerHint(mModule, static_cast<power_hint_t>(hint), &param);
-        else
-            mModule->powerHint(mModule, static_cast<power_hint_t>(hint), NULL);
-    }
-    return Void();
-}
-
-Return<void> Power::setFeature(Feature feature, bool activate)  {
-    if (mModule->setFeature)
-        mModule->setFeature(mModule, static_cast<feature_t>(feature),
-                activate ? 1 : 0);
-    return Void();
-}
-
-Return<void> Power::getPlatformLowPowerStats(getPlatformLowPowerStats_cb _hidl_cb)  {
-    hidl_vec<PowerStatePlatformSleepState> states;
-    ssize_t number_platform_modes;
-    size_t *voters = nullptr;
-    power_state_platform_sleep_state_t *legacy_states = nullptr;
-    int ret;
-
-    if (mModule->get_number_of_platform_modes == nullptr ||
-            mModule->get_voter_list == nullptr ||
-            mModule->get_platform_low_power_stats == nullptr)
-    {
-        _hidl_cb(states, Status::SUCCESS);
-        return Void();
-    }
-
-    number_platform_modes = mModule->get_number_of_platform_modes(mModule);
-    if (number_platform_modes)
-    {
-       if ((ssize_t) (SIZE_MAX / sizeof(size_t)) <= number_platform_modes)  // overflow
-           goto done;
-       voters = new (std::nothrow) size_t [number_platform_modes];
-       if (voters == nullptr)
-           goto done;
-
-       ret = mModule->get_voter_list(mModule, voters);
-       if (ret != 0)
-           goto done;
-
-       if ((ssize_t) (SIZE_MAX / sizeof(power_state_platform_sleep_state_t))
-           <= number_platform_modes)  // overflow
-           goto done;
-       legacy_states = new (std::nothrow)
-           power_state_platform_sleep_state_t [number_platform_modes];
-       if (legacy_states == nullptr)
-           goto done;
-
-       for (int i = 0; i < number_platform_modes; i++)
-       {
-          legacy_states[i].voters = nullptr;
-          legacy_states[i].voters = new power_state_voter_t [voters[i]];
-          if (legacy_states[i].voters == nullptr)
-              goto done;
-       }
-
-       ret = mModule->get_platform_low_power_stats(mModule, legacy_states);
-       if (ret != 0)
-           goto done;
-
-       states.resize(number_platform_modes);
-       for (int i = 0; i < number_platform_modes; i++)
-       {
-          power_state_platform_sleep_state_t& legacy_state = legacy_states[i];
-          PowerStatePlatformSleepState& state = states[i];
-          state.name = legacy_state.name;
-          state.residencyInMsecSinceBoot = legacy_state.residency_in_msec_since_boot;
-          state.totalTransitions = legacy_state.total_transitions;
-          state.supportedOnlyInSuspend = legacy_state.supported_only_in_suspend;
-          state.voters.resize(voters[i]);
-          for(size_t j = 0; j < voters[i]; j++)
-          {
-              state.voters[j].name = legacy_state.voters[j].name;
-              state.voters[j].totalTimeInMsecVotedForSinceBoot = legacy_state.voters[j].total_time_in_msec_voted_for_since_boot;
-              state.voters[j].totalNumberOfTimesVotedSinceBoot = legacy_state.voters[j].total_number_of_times_voted_since_boot;
-          }
-       }
-    }
-done:
-    if (legacy_states)
-    {
-        for (int i = 0; i < number_platform_modes; i++)
-        {
-            if(legacy_states[i].voters)
-                delete(legacy_states[i].voters);
-        }
-    }
-    delete[] legacy_states;
-    delete[] voters;
-    _hidl_cb(states, Status::SUCCESS);
-    return Void();
-}
-
-// Methods from ::android::hardware::power::V1_1::IPower follow.
-Return<void> Power::getSubsystemLowPowerStats(getSubsystemLowPowerStats_cb _hidl_cb) {
-    hidl_vec<PowerStateSubsystem> subsystems;
-    ssize_t number_subsystems = 0;
-
-    //This API will report zero subsystems to support older devices
-    //For devices that support this API, they will have their own implementation
-    subsystems.resize(number_subsystems);
-    _hidl_cb(subsystems, Status::SUCCESS);
-    return Void();
-}
-
-Return<void> Power::powerHintAsync(PowerHint hint, int32_t data) {
-    // just call the normal power hint in this oneway function
-    return powerHint(hint, data);
-}
-
-} // namespace implementation
-}  // namespace V1_1
-}  // namespace power
-}  // namespace hardware
-}  // namespace android
diff --git a/power/1.1/default/Power.h b/power/1.1/default/Power.h
deleted file mode 100644 (file)
index e779d64..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_POWER_V1_1_POWER_H
-#define ANDROID_HARDWARE_POWER_V1_1_POWER_H
-
-#include <android/hardware/power/1.1/IPower.h>
-#include <hidl/MQDescriptor.h>
-#include <hidl/Status.h>
-#include <hardware/power.h>
-
-namespace android {
-namespace hardware {
-namespace power {
-namespace V1_1 {
-namespace implementation {
-
-using ::android::hardware::power::V1_0::Feature;
-using ::android::hardware::power::V1_0::PowerHint;
-using ::android::hardware::power::V1_1::IPower;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-
-struct Power : public IPower {
-    Power(power_module_t* module);
-    ~Power();
-
-    // Methods from ::android::hardware::power::V1_0::IPower follow
-    Return<void> setInteractive(bool interactive) override;
-    Return<void> powerHint(PowerHint hint, int32_t data) override;
-    Return<void> setFeature(Feature feature, bool activate) override;
-    Return<void> getPlatformLowPowerStats(getPlatformLowPowerStats_cb _hidl_cb) override;
-
-    // Methods from ::android::hardware::power::V1_1::IPower follow.
-    Return<void> getSubsystemLowPowerStats(getSubsystemLowPowerStats_cb _hidl_cb) override;
-    Return<void> powerHintAsync(PowerHint hint, int32_t data) override;
-
-    // Methods from ::android::hidl::base::V1_0::IBase follow.
-
-  private:
-    power_module_t* mModule;
-};
-
-}  // namespace implementation
-}  // namespace V1_1
-}  // namespace power
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_POWER_V1_1_POWER_H
diff --git a/power/1.1/default/android.hardware.power@1.1-service.rc b/power/1.1/default/android.hardware.power@1.1-service.rc
deleted file mode 100644 (file)
index f2512f1..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-service power-hal-1-1 /vendor/bin/hw/android.hardware.power@1.1-service
-    class hal
-    user system
-    group system
diff --git a/power/1.1/default/service.cpp b/power/1.1/default/service.cpp
deleted file mode 100644 (file)
index 571db2f..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "android.hardware.power@1.1-service"
-
-#include <android/log.h>
-#include <hidl/HidlTransportSupport.h>
-#include <android/hardware/power/1.1/IPower.h>
-#include <hardware/power.h>
-#include "Power.h"
-
-using android::sp;
-using android::status_t;
-using android::OK;
-
-// libhwbinder:
-using android::hardware::configureRpcThreadpool;
-using android::hardware::joinRpcThreadpool;
-
-// Generated HIDL files
-using android::hardware::power::V1_1::IPower;
-using android::hardware::power::V1_1::implementation::Power;
-
-int main() {
-
-    status_t status;
-    android::sp<IPower> service = nullptr;
-    const hw_module_t* hw_module = nullptr;
-    power_module_t* power_module = nullptr;
-    int err;
-
-    ALOGI("Power HAL Service 1.1 (Default) is starting.");
-
-    err = hw_get_module(POWER_HARDWARE_MODULE_ID, &hw_module);
-    if (err) {
-        ALOGE("hw_get_module %s failed: %d", POWER_HARDWARE_MODULE_ID, err);
-        goto shutdown;
-    }
-
-    if (!hw_module->methods || !hw_module->methods->open) {
-        power_module = reinterpret_cast<power_module_t*>(
-            const_cast<hw_module_t*>(hw_module));
-    } else {
-        err = hw_module->methods->open(hw_module, POWER_HARDWARE_MODULE_ID,
-                                           reinterpret_cast<hw_device_t**>(&power_module));
-        if (err) {
-            ALOGE("Passthrough failed to load legacy HAL.");
-            goto shutdown;
-        }
-    }
-
-    service = new Power(power_module);
-    if (service == nullptr) {
-        ALOGE("Can not create an instance of Power HAL Iface, exiting.");
-
-        goto shutdown;
-    }
-
-    configureRpcThreadpool(1, true /*callerWillJoin*/);
-
-    status = service->registerAsService();
-    if (status != OK) {
-        ALOGE("Could not register service for Power HAL Iface (%d).", status);
-        goto shutdown;
-    }
-
-    ALOGI("Power Service is ready");
-    joinRpcThreadpool();
-    //Should not pass this line
-
-shutdown:
-    // In normal operation, we don't expect the thread pool to exit
-
-    ALOGE("Power Service is shutting down");
-    return 1;
-}
index f886bd2..604cd36 100644 (file)
 
 cc_test {
     name: "VtsHalPowerV1_1TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalPowerV1_1TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libhidlbase",
-        "libhidltransport",
-        "libutils",
+    static_libs: [
+        "android.hardware.power@1.0",
         "android.hardware.power@1.1",
     ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ]
 }
index 7a315fa..a5415df 100644 (file)
@@ -4,6 +4,5 @@ subdirs = [
     "1.0/default",
     "1.0/vts/functional",
     "1.1",
-    "1.1/default",
     "1.1/vts/functional",
 ]
index 988f5d2..093ceac 100644 (file)
@@ -67,13 +67,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.radio@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.radio@1.0_genc++"],
     generated_headers: ["android.hardware.radio@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.radio@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index a94aac3..94b304a 100644 (file)
@@ -161,6 +161,7 @@ interface IRadioResponse {
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
      *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:SIM_ABSENT
      */
     oneway supplyNetworkDepersonalizationResponse(RadioResponseInfo info, int32_t remainingRetries);
 
@@ -544,6 +545,7 @@ interface IRadioResponse {
      *   RadioError:OPERATION_NOT_ALLOWED
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
+     *   RadioError:SIM_ABSENT
      */
     oneway sendSmsResponse(RadioResponseInfo info, SendSmsResult sms);
 
@@ -574,6 +576,7 @@ interface IRadioResponse {
      *   RadioError:OPERATION_NOT_ALLOWED
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
+     *   RadioError:SIM_ABSENT
      */
     oneway sendSMSExpectMoreResponse(RadioResponseInfo info, SendSmsResult sms);
 
@@ -594,6 +597,7 @@ interface IRadioResponse {
      *   RadioError:NO_MEMORY
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
+     *   RadioError:SIM_ABSENT
      */
     oneway setupDataCallResponse(RadioResponseInfo info, SetupDataCallResult dcResponse);
 
@@ -860,6 +864,7 @@ interface IRadioResponse {
      *   RadioError:NO_MEMORY
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
+     *   RadioError:SIM_ABSENT
      */
     oneway deactivateDataCallResponse(RadioResponseInfo info);
 
@@ -1166,6 +1171,7 @@ interface IRadioResponse {
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
      *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:SIM_ABSENT
      */
     oneway getDataCallListResponse(RadioResponseInfo info, vec<SetupDataCallResult> dcResponse);
 
@@ -1210,6 +1216,7 @@ interface IRadioResponse {
      *   RadioError:REQUEST_NOT_SUPPORTED
      *   RadioError:CANCELLED
      *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:SIM_ABSENT
      */
     oneway writeSmsToSimResponse(RadioResponseInfo info, int32_t index);
 
@@ -1231,6 +1238,7 @@ interface IRadioResponse {
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
      *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:SIM_ABSENT
      */
     oneway deleteSmsOnSimResponse(RadioResponseInfo info);
 
@@ -1615,6 +1623,7 @@ interface IRadioResponse {
      *   RadioError:ENCODING_ERR
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
+     *   RadioError:SIM_ABSENT
      */
     oneway sendCdmaSmsResponse(RadioResponseInfo info, SendSmsResult sms);
 
@@ -1819,6 +1828,7 @@ interface IRadioResponse {
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
      *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:SIM_ABSENT
      */
     oneway writeSmsToRuimResponse(RadioResponseInfo info, uint32_t index);
 
@@ -1839,6 +1849,8 @@ interface IRadioResponse {
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
      *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:SIM_ABSENT
      */
     oneway deleteSmsOnRuimResponse(RadioResponseInfo info);
 
@@ -1906,6 +1918,7 @@ interface IRadioResponse {
      *   RadioError:OPERATION_NOT_ALLOWED
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
+     *   RadioError:SIM_ABSENT
      */
     oneway getSmscAddressResponse(RadioResponseInfo info, string smsc);
 
@@ -1927,6 +1940,7 @@ interface IRadioResponse {
      *   RadioError:OPERATION_NOT_ALLOWED
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
+     *   RadioError:SIM_ABSENT
      */
     oneway setSmscAddressResponse(RadioResponseInfo info);
 
@@ -1946,6 +1960,7 @@ interface IRadioResponse {
      *   RadioError:REQUEST_NOT_SUPPORTED
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
+     *   RadioError:SIM_ABSENT
      */
     oneway reportSmsMemoryStatusResponse(RadioResponseInfo info);
 
@@ -2024,6 +2039,7 @@ interface IRadioResponse {
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
      *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:SIM_ABSENT
      */
     oneway sendEnvelopeWithStatusResponse(RadioResponseInfo info, IccIoResult iccIo);
 
@@ -2328,6 +2344,7 @@ interface IRadioResponse {
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
      *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:SIM_ABSENT
      */
     oneway setDataProfileResponse(RadioResponseInfo info);
 
@@ -2414,6 +2431,7 @@ interface IRadioResponse {
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
      *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:SIM_ABSENT
      */
     oneway stopLceServiceResponse(RadioResponseInfo info, LceStatusInfo statusInfo);
 
@@ -2430,6 +2448,7 @@ interface IRadioResponse {
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
      *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:SIM_ABSENT
      */
     oneway pullLceDataResponse(RadioResponseInfo info, LceDataInfo lceInfo);
 
index c5d7f8a..4d22bc0 100644 (file)
@@ -1507,8 +1507,8 @@ struct CellIdentityGsm {
     int32_t lac;                          // 16-bit Location Area Code, 0..65535, INT_MAX if unknown
     int32_t cid;                          // 16-bit GSM Cell Identity described in
                                           // TS 27.007, 0..65535, INT_MAX if unknown
-    int32_t arfcn;                        // 16-bit GSM Absolute RF channel number, INT_MAX if
-                                          // unknown
+    int32_t arfcn;                        // 16-bit GSM Absolute RF channel number; this value must
+                                          // be valid
     uint8_t bsic;                         // 6-bit Base Station Identity Code, 0xFF if unknown
 };
 
@@ -1520,9 +1520,9 @@ struct CellIdentityWcdma {
     int32_t cid;                          // 28-bit UMTS Cell Identity described in
                                           // TS 25.331, 0..268435455, INT_MAX if unknown
     int32_t psc;                          // 9-bit UMTS Primary Scrambling Code described in
-                                          // TS 25.331, 0..511, INT_MAX if unknown
-    int32_t uarfcn;                       // 16-bit UMTS Absolute RF Channel Number, INT_MAX if
-                                          // unknown
+                                          // TS 25.331, 0..511; this value must be valid
+    int32_t uarfcn;                       // 16-bit UMTS Absolute RF Channel Number; this value must
+                                          // be valid
 };
 
 struct CellIdentityCdma {
@@ -1547,10 +1547,10 @@ struct CellIdentityLte {
                                           // unknown
     int32_t ci;                           // 28-bit Cell Identity described in TS TS 27.007, INT_MAX
                                           // if unknown
-    int32_t pci;                          // physical cell id 0..503, INT_MAX if unknown
+    int32_t pci;                          // physical cell id 0..503; this value must be valid
     int32_t tac;                          // 16-bit tracking area code, INT_MAX if unknown
-    int32_t earfcn;                       // 18-bit LTE Absolute RC Channel Number, INT_MAX if
-                                          // unknown
+    int32_t earfcn;                       // 18-bit LTE Absolute RF Channel Number; this value must
+                                          // be valid
 };
 
 struct CellIdentityTdscdma {
diff --git a/radio/1.0/vts/OWNERS b/radio/1.0/vts/OWNERS
new file mode 100644 (file)
index 0000000..2384317
--- /dev/null
@@ -0,0 +1,8 @@
+# Telephony team
+amitmahajan@google.com
+sanketpadawe@google.com
+shuoq@google.com
+
+# VTS team
+yuexima@google.com
+yim@google.com
index eb11b54..82a8a72 100644 (file)
@@ -16,7 +16,7 @@
 
 cc_test {
     name: "VtsHalRadioV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["radio_hidl_hal_cell_broadcast.cpp",
            "radio_hidl_hal_data.cpp",
            "radio_hidl_hal_icc.cpp",
@@ -30,46 +30,22 @@ cc_test {
            "radio_response.cpp",
            "VtsHalRadioV1_0TargetTest.cpp",
            "vts_test_util.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
+    static_libs: [
         "android.hardware.radio@1.0",
     ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
 }
 
 cc_test {
     name: "VtsHalSapV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["sap_callback.cpp",
            "sap_hidl_hal_api.cpp",
            "sap_hidl_hal_test.cpp",
            "VtsHalSapV1_0TargetTest.cpp",
            "vts_test_util.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
+    static_libs: [
         "android.hardware.radio@1.0",
     ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
 }
 
 cc_library_static {
@@ -82,4 +58,4 @@ cc_library_static {
 cc_library_headers {
     name: "radio.util.header@1.0",
     export_include_dirs: ["."],
-}
\ No newline at end of file
+}
index d93b176..795af86 100644 (file)
@@ -70,7 +70,7 @@ TEST_F(RadioHidlTest, getOperator) {
 TEST_F(RadioHidlTest, setRadioPower) {
     int serial = GetRandomSerialNumber();
 
-    radio->setRadioPower(serial, 0);
+    radio->setRadioPower(serial, 1);
     EXPECT_EQ(std::cv_status::no_timeout, wait());
     EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
index 8d6e200..1d2f199 100644 (file)
@@ -366,6 +366,7 @@ TEST_F(RadioHidlTest, sendCDMAFeatureCode) {
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
+        std::cout << static_cast<int>(radioRsp->rspInfo.error) << std::endl;
         ASSERT_TRUE(CheckGeneralError() ||
                     radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
                     radioRsp->rspInfo.error == RadioError::NONE ||
index 3a3f639..156cf99 100644 (file)
@@ -60,13 +60,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.radio@1.1",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.radio@1.1_genc++"],
     generated_headers: ["android.hardware.radio@1.1_genc++_headers"],
     export_generated_headers: ["android.hardware.radio@1.1_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index 4e7bf43..759602b 100644 (file)
@@ -16,6 +16,7 @@
 
 package android.hardware.radio@1.1;
 
+import @1.0::RadioResponseInfo;
 import @1.0::IRadioResponse;
 
 /**
diff --git a/radio/1.1/vts/OWNERS b/radio/1.1/vts/OWNERS
new file mode 100644 (file)
index 0000000..2384317
--- /dev/null
@@ -0,0 +1,8 @@
+# Telephony team
+amitmahajan@google.com
+sanketpadawe@google.com
+shuoq@google.com
+
+# VTS team
+yuexima@google.com
+yim@google.com
index 9000eb2..e7195ee 100644 (file)
 
 cc_test {
     name: "VtsHalRadioV1_1TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["radio_hidl_hal_api.cpp",
            "radio_hidl_hal_test.cpp",
            "radio_indication.cpp",
            "radio_response.cpp",
            "VtsHalRadioV1_1TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
+    static_libs: [
+        "RadioVtsTestUtilBase",
         "android.hardware.radio@1.1",
         "android.hardware.radio@1.0",
     ],
-    static_libs: ["VtsHalHidlTargetTestBase",
-                  "RadioVtsTestUtilBase"],
     header_libs: [
         "radio.util.header@1.0",
     ],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
 }
index e45ecc3..e63ed28 100644 (file)
@@ -49,13 +49,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.radio.deprecated@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.radio.deprecated@1.0_genc++"],
     generated_headers: ["android.hardware.radio.deprecated@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.radio.deprecated@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index d599315..0f62652 100644 (file)
@@ -46,13 +46,17 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.renderscript@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.renderscript@1.0_genc++"],
     generated_headers: ["android.hardware.renderscript@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.renderscript@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+        support_system_process: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index 3aae060..4831a8b 100644 (file)
@@ -1,6 +1,9 @@
 #include "Context.h"
 #include "Device.h"
 
+#include <android/dlext.h>
+#include <dlfcn.h>
+
 namespace android {
 namespace hardware {
 namespace renderscript {
@@ -39,7 +42,25 @@ dispatchTable loadHAL() {
     static_assert(sizeof(size_t) <= sizeof(uint64_t), "RenderScript HIDL Error: sizeof(size_t) > sizeof(uint64_t)");
 
     const char* filename = "libRS_internal.so";
-    void* handle = dlopen(filename, RTLD_LAZY | RTLD_LOCAL);
+    // Try to load libRS_internal.so from the "rs" namespace directly.
+    typedef struct android_namespace_t* (*GetExportedNamespaceFnPtr)(const char*);
+    GetExportedNamespaceFnPtr getExportedNamespace =
+        (GetExportedNamespaceFnPtr)dlsym(RTLD_DEFAULT, "android_get_exported_namespace");
+    void* handle = nullptr;
+    if (getExportedNamespace != nullptr) {
+        android_namespace_t* rs_namespace = getExportedNamespace("rs");
+        if (rs_namespace != nullptr) {
+            const android_dlextinfo dlextinfo = {
+                .flags = ANDROID_DLEXT_USE_NAMESPACE, .library_namespace = rs_namespace,
+            };
+            handle = android_dlopen_ext(filename, RTLD_LAZY | RTLD_LOCAL, &dlextinfo);
+        }
+    }
+    if (handle == nullptr) {
+        // if there is no "rs" namespace (in case when this HAL impl is loaded
+        // into a vendor process), then use the plain dlopen.
+        handle = dlopen(filename, RTLD_LAZY | RTLD_LOCAL);
+    }
 
     dispatchTable dispatchHal = {
         .SetNativeLibDir = (SetNativeLibDirFnPtr) nullptr,
index 5256c1f..bf011e6 100644 (file)
@@ -23,21 +23,9 @@ cc_test {
         "VtsScriptTests.cpp",
         "bitcode.cpp",
     ],
-    defaults: ["hidl_defaults"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
-        "libnativewindow",
+    defaults: ["VtsHalTargetTestDefaults"],
+    static_libs: [
         "android.hardware.renderscript@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
+        "libnativewindow",
     ],
 }
index 2670b8d..c6eecd6 100644 (file)
@@ -28,8 +28,10 @@ void RenderscriptHidlTest::SetUp() {
 }
 
 void RenderscriptHidlTest::TearDown() {
-    context->contextFinish();
-    context->contextDestroy();
+    if (context.get() != nullptr) {
+        context->contextFinish();
+        context->contextDestroy();
+    }
 }
 
 // A class for test environment setup (kept since this file is a template).
index f6cf4a7..b2cda05 100644 (file)
@@ -39,13 +39,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.sensors@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.sensors@1.0_genc++"],
     generated_headers: ["android.hardware.sensors@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.sensors@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index 8144590..4bbafa6 100644 (file)
@@ -38,6 +38,9 @@ cc_library_static {
         "android.hardware.sensors@1.0",
     ],
     local_include_dirs: ["include/sensors"],
+    export_shared_lib_headers: [
+        "libhardware",
+    ],
 }
 
 
index 059e5db..6e78082 100644 (file)
@@ -1,5 +1,5 @@
 service sensors-hal-1-0 /vendor/bin/hw/android.hardware.sensors@1.0-service
     class hal
     user system
-    group system
-    capabilities SYS_NICE
+    group system wakelock
+    capabilities BLOCK_SUSPEND SYS_NICE
index af149ba..a49307d 100644 (file)
 
 cc_test {
     name: "VtsHalSensorsV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalSensorsV1_0TargetTest.cpp"],
-    shared_libs: [
-        "android.hardware.sensors@1.0",
-        "libcutils",
-        "libhidlbase",
-        "liblog",
-        "libutils",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
+    static_libs: ["android.hardware.sensors@1.0"],
 }
 
index 8259776..f45c4e2 100644 (file)
@@ -46,13 +46,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.soundtrigger@2.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.soundtrigger@2.0_genc++"],
     generated_headers: ["android.hardware.soundtrigger@2.0_genc++_headers"],
     export_generated_headers: ["android.hardware.soundtrigger@2.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/soundtrigger/2.0/default/OWNERS b/soundtrigger/2.0/default/OWNERS
new file mode 100644 (file)
index 0000000..6fdc97c
--- /dev/null
@@ -0,0 +1,3 @@
+elaurent@google.com
+krocard@google.com
+mnaganov@google.com
index 8f0cc4e..be6b3a8 100644 (file)
 
 cc_test {
     name: "VtsHalSoundtriggerV2_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalSoundtriggerV2_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
-        "android.hardware.soundtrigger@2.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
+    static_libs: ["android.hardware.soundtrigger@2.0"],
 }
index ddf300b..9583bfd 100644 (file)
@@ -20,6 +20,8 @@ subdirs = [
     "memory/1.0/default",
     "msgq/1.0",
     "msgq/1.0/default",
+    "multithread/1.0",
+    "multithread/1.0/default",
     "pointer/1.0",
     "pointer/1.0/default",
     "pointer/1.0/default/lib",
diff --git a/tests/bar/1.0/.hidl_for_test b/tests/bar/1.0/.hidl_for_test
new file mode 100644 (file)
index 0000000..e69de29
index 4c76014..b6ee042 100644 (file)
@@ -67,7 +67,7 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.tests.bar@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.bar@1.0_genc++"],
diff --git a/tests/baz/1.0/.hidl_for_test b/tests/baz/1.0/.hidl_for_test
new file mode 100644 (file)
index 0000000..e69de29
index 1445b11..ef68149 100644 (file)
@@ -60,7 +60,7 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.tests.baz@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.baz@1.0_genc++"],
diff --git a/tests/expression/1.0/.hidl_for_test b/tests/expression/1.0/.hidl_for_test
new file mode 100644 (file)
index 0000000..e69de29
index 0cfe47d..bc389b0 100644 (file)
@@ -42,7 +42,7 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.tests.expression@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.expression@1.0_genc++"],
diff --git a/tests/extension/light/2.0/.hidl_for_test b/tests/extension/light/2.0/.hidl_for_test
new file mode 100644 (file)
index 0000000..e69de29
index 6469b45..c5987a7 100644 (file)
@@ -39,7 +39,7 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.tests.extension.light@2.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.extension.light@2.0_genc++"],
diff --git a/tests/foo/1.0/.hidl_for_test b/tests/foo/1.0/.hidl_for_test
new file mode 100644 (file)
index 0000000..e69de29
index b698847..6387950 100644 (file)
@@ -67,7 +67,7 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.tests.foo@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.foo@1.0_genc++"],
diff --git a/tests/hash/1.0/.hidl_for_test b/tests/hash/1.0/.hidl_for_test
new file mode 100644 (file)
index 0000000..e69de29
index 617ddec..505a4ad 100644 (file)
@@ -35,7 +35,7 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.tests.hash@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.hash@1.0_genc++"],
diff --git a/tests/inheritance/1.0/.hidl_for_test b/tests/inheritance/1.0/.hidl_for_test
new file mode 100644 (file)
index 0000000..e69de29
index 4dbcf4b..5d8d53d 100644 (file)
@@ -56,7 +56,7 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.tests.inheritance@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.inheritance@1.0_genc++"],
diff --git a/tests/libhwbinder/1.0/.hidl_for_test b/tests/libhwbinder/1.0/.hidl_for_test
new file mode 100644 (file)
index 0000000..e69de29
index f254bad..338a72b 100644 (file)
@@ -42,7 +42,7 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.tests.libhwbinder@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.libhwbinder@1.0_genc++"],
index af4caec..13f9c18 100644 (file)
@@ -1,7 +1,6 @@
 cc_library_shared {
     name: "android.hardware.tests.libhwbinder@1.0-impl",
     relative_install_path: "hw",
-    proprietary: true,
     srcs: [
         "Benchmark.cpp",
         "ScheduleTest.cpp",
diff --git a/tests/libhwbinder/aidl/.hidl_for_test b/tests/libhwbinder/aidl/.hidl_for_test
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/memory/1.0/.hidl_for_test b/tests/memory/1.0/.hidl_for_test
new file mode 100644 (file)
index 0000000..e69de29
index 5a62896..a753824 100644 (file)
@@ -35,7 +35,7 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.tests.memory@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.memory@1.0_genc++"],
diff --git a/tests/msgq/1.0/.hidl_for_test b/tests/msgq/1.0/.hidl_for_test
new file mode 100644 (file)
index 0000000..e69de29
index 19ff89c..0937545 100644 (file)
@@ -42,7 +42,7 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.tests.msgq@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.msgq@1.0_genc++"],
diff --git a/tests/multithread/1.0/.hidl_for_test b/tests/multithread/1.0/.hidl_for_test
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/multithread/1.0/Android.bp b/tests/multithread/1.0/Android.bp
new file mode 100644 (file)
index 0000000..5f4c44c
--- /dev/null
@@ -0,0 +1,59 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+filegroup {
+    name: "android.hardware.tests.multithread@1.0_hal",
+    srcs: [
+        "IMultithread.hal",
+    ],
+}
+
+genrule {
+    name: "android.hardware.tests.multithread@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tests.multithread@1.0",
+    srcs: [
+        ":android.hardware.tests.multithread@1.0_hal",
+    ],
+    out: [
+        "android/hardware/tests/multithread/1.0/MultithreadAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.tests.multithread@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tests.multithread@1.0",
+    srcs: [
+        ":android.hardware.tests.multithread@1.0_hal",
+    ],
+    out: [
+        "android/hardware/tests/multithread/1.0/IMultithread.h",
+        "android/hardware/tests/multithread/1.0/IHwMultithread.h",
+        "android/hardware/tests/multithread/1.0/BnHwMultithread.h",
+        "android/hardware/tests/multithread/1.0/BpHwMultithread.h",
+        "android/hardware/tests/multithread/1.0/BsMultithread.h",
+    ],
+}
+
+cc_library {
+    name: "android.hardware.tests.multithread@1.0",
+    defaults: ["hidl-module-defaults"],
+    generated_sources: ["android.hardware.tests.multithread@1.0_genc++"],
+    generated_headers: ["android.hardware.tests.multithread@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.tests.multithread@1.0_genc++_headers"],
+    vendor_available: true,
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+    ],
+}
diff --git a/tests/multithread/1.0/Android.mk b/tests/multithread/1.0/Android.mk
new file mode 100644 (file)
index 0000000..f63381d
--- /dev/null
@@ -0,0 +1,76 @@
+# This file is autogenerated by hidl-gen. Do not edit manually.
+
+LOCAL_PATH := $(call my-dir)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.tests.multithread-V1.0-java
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(call local-generated-sources-dir, COMMON)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_JAVA_LIBRARIES := \
+    android.hidl.base-V1.0-java \
+
+
+#
+# Build IMultithread.hal
+#
+GEN := $(intermediates)/android/hardware/tests/multithread/V1_0/IMultithread.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IMultithread.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tests.multithread@1.0::IMultithread
+
+$(GEN): $(LOCAL_PATH)/IMultithread.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_JAVA_LIBRARY)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.tests.multithread-V1.0-java-static
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(call local-generated-sources-dir, COMMON)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android.hidl.base-V1.0-java-static \
+
+
+#
+# Build IMultithread.hal
+#
+GEN := $(intermediates)/android/hardware/tests/multithread/V1_0/IMultithread.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IMultithread.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tests.multithread@1.0::IMultithread
+
+$(GEN): $(LOCAL_PATH)/IMultithread.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/multithread/1.0/IMultithread.hal b/tests/multithread/1.0/IMultithread.hal
new file mode 100644 (file)
index 0000000..19dc4f6
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tests.multithread@1.0;
+
+/**
+ * IMultithread tests configureRpcThreadpool
+ *
+ * Makes calls finish only when specific number of them are running in parallel
+ */
+interface IMultithread {
+    /**
+     * Sets up controller
+     * Must be called for each test
+     * @param maxThreads arg passed to configureRpcThreadpool
+     * Could not be decremented by future calls
+     * @param numThreads number of calls in parallel to finish
+     */
+    setNumThreads(int32_t maxThreads, int32_t numThreads);
+
+    /**
+     * Makes a new call
+     * @return noTimeout numThreads appeared in parallel before timeout
+     * Shall return the same value for one setNumThreads call
+     */
+    runNewThread() generates (bool noTimeout);
+};
diff --git a/tests/multithread/1.0/default/Android.bp b/tests/multithread/1.0/default/Android.bp
new file mode 100644 (file)
index 0000000..a7a750a
--- /dev/null
@@ -0,0 +1,16 @@
+cc_library_shared {
+    name: "android.hardware.tests.multithread@1.0-impl",
+    defaults: ["hidl_defaults"],
+    relative_install_path: "hw",
+    srcs: [
+        "Multithread.cpp",
+    ],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libutils",
+        "android.hardware.tests.multithread@1.0",
+    ],
+}
diff --git a/tests/multithread/1.0/default/Multithread.cpp b/tests/multithread/1.0/default/Multithread.cpp
new file mode 100644 (file)
index 0000000..1fb267c
--- /dev/null
@@ -0,0 +1,63 @@
+#define LOG_TAG "hidl_test"
+
+#include <android-base/logging.h>
+#include "Multithread.h"
+#include <inttypes.h>
+#include <thread>
+
+#include <hidl/HidlTransportSupport.h>
+
+namespace android {
+namespace hardware {
+namespace tests {
+namespace multithread {
+namespace V1_0 {
+namespace implementation {
+
+// Methods from ::android::hardware::tests::multithread::V1_0::IMultithread follow.
+Return<void> Multithread::setNumThreads(int32_t maxThreads, int32_t numThreads) {
+    LOG(INFO) << "SERVER(Multithread) setNumThreads("
+              << maxThreads << ", " << numThreads << ")";
+
+    LOG(INFO) << "SERVER(Multithread) call configureRpcThreadpool("
+              << maxThreads << ")";
+    ::android::hardware::configureRpcThreadpool(maxThreads, /*willjoin*/ false);
+
+    mNumThreads = numThreads;
+    mNoTimeout = true;
+
+    return Void();
+}
+
+Return<bool> Multithread::runNewThread() {
+    LOG(INFO) << "SERVER(Multithread) runNewThread()";
+
+    std::unique_lock<std::mutex> lk(mCvMutex);
+    --mNumThreads;
+
+    LOG(INFO) << "SERVER(Multithread) runNewThread()";
+    LOG(INFO) << mNumThreads << "threads left";
+
+    mCv.notify_all();
+    bool noTimeout = mCv.wait_for(lk, kTimeoutDuration,
+        [&] { return mNumThreads <= 0 || !mNoTimeout; });
+
+    if (!noTimeout) {
+        mNoTimeout = false;
+        mCv.notify_all();
+    }
+    return mNoTimeout;
+}
+
+IMultithread* HIDL_FETCH_IMultithread(const char* /* name */) {
+    return new Multithread();
+}
+
+decltype(Multithread::kTimeoutDuration) Multithread::kTimeoutDuration;
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace multithread
+}  // namespace tests
+}  // namespace hardware
+}  // namespace android
diff --git a/tests/multithread/1.0/default/Multithread.h b/tests/multithread/1.0/default/Multithread.h
new file mode 100644 (file)
index 0000000..0d4a007
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef ANDROID_HARDWARE_TESTS_MULTITHREAD_V1_0_MULTITHREAD_H
+#define ANDROID_HARDWARE_TESTS_MULTITHREAD_V1_0_MULTITHREAD_H
+
+#include <android/hardware/tests/multithread/1.0/IMultithread.h>
+#include <hidl/Status.h>
+
+#include <chrono>
+#include <condition_variable>
+#include <mutex>
+
+namespace android {
+namespace hardware {
+namespace tests {
+namespace multithread {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::tests::multithread::V1_0::IMultithread;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+using namespace std::chrono_literals;
+
+struct Multithread : public IMultithread {
+    // Methods from ::android::hardware::tests::multithread::V1_0::IMultithread follow.
+    virtual Return<void> setNumThreads(int32_t maxThreads, int32_t numThreads) override;
+    virtual Return<bool> runNewThread() override;
+
+   private:
+    int32_t mNumThreads;
+    bool mNoTimeout;
+
+    std::condition_variable mCv;
+    std::mutex mCvMutex;
+
+    static constexpr auto kTimeoutDuration = 100ms;
+};
+
+extern "C" IMultithread* HIDL_FETCH_IMultithread(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace multithread
+}  // namespace tests
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_TESTS_MULTITHREAD_V1_0_MULTITHREAD_H
diff --git a/tests/pointer/1.0/.hidl_for_test b/tests/pointer/1.0/.hidl_for_test
new file mode 100644 (file)
index 0000000..e69de29
index 37fea94..a765ae7 100644 (file)
@@ -42,7 +42,7 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.tests.pointer@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.pointer@1.0_genc++"],
index 7beefbf..2d62f16 100644 (file)
@@ -35,13 +35,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.tetheroffload.config@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tetheroffload.config@1.0_genc++"],
     generated_headers: ["android.hardware.tetheroffload.config@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.tetheroffload.config@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index 2e720c6..dc95eaa 100644 (file)
 
 cc_test {
     name: "VtsHalTetheroffloadConfigV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalTetheroffloadConfigV1_0TargetTest.cpp"],
-    shared_libs: [
-        "android.hardware.tetheroffload.config@1.0",
-        "libbase",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "liblog",
-        "libutils",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
+    static_libs: ["android.hardware.tetheroffload.config@1.0"],
 }
index fc61e1c..2cbe479 100644 (file)
@@ -91,35 +91,42 @@ class OffloadConfigHidlTest : public testing::VtsHalHidlTargetTestBase {
 
 // Ensure handles can be set with correct socket options.
 TEST_F(OffloadConfigHidlTest, TestSetHandles) {
-    unique_fd fd1(netlinkSocket(kFd1Groups));
-    if (fd1.get() < 0) {
-        ALOGE("Unable to create conntrack handles: %d/%s", errno, strerror(errno));
-        FAIL();
-    }
-    native_handle_t* const nativeHandle1 = native_handle_create(1, 0);
-    nativeHandle1->data[0] = fd1.release();
-    const hidl_handle h1 = hidl_handle(nativeHandle1);
-
-    unique_fd fd2(netlinkSocket(kFd2Groups));
-    if (fd2.get() < 0) {
-        ALOGE("Unable to create conntrack handles: %d/%s", errno, strerror(errno));
-        FAIL();
+    // Try multiple times in a row to see if it provokes file descriptor leaks.
+    for (int i = 0; i < 1024; i++) {
+        unique_fd fd1(netlinkSocket(kFd1Groups));
+        if (fd1.get() < 0) {
+            ALOGE("Unable to create conntrack handles: %d/%s", errno, strerror(errno));
+            FAIL();
+        }
+        native_handle_t* const nativeHandle1 = native_handle_create(1, 0);
+        nativeHandle1->data[0] = fd1.release();
+        hidl_handle h1;
+        h1.setTo(nativeHandle1, true);
+
+        unique_fd fd2(netlinkSocket(kFd2Groups));
+        if (fd2.get() < 0) {
+            ALOGE("Unable to create conntrack handles: %d/%s", errno, strerror(errno));
+            FAIL();
+        }
+        native_handle_t* const nativeHandle2 = native_handle_create(1, 0);
+        nativeHandle2->data[0] = fd2.release();
+        hidl_handle h2;
+        h2.setTo(nativeHandle2, true);
+
+        const Return<void> ret = config->setHandles(h1, h2, ASSERT_TRUE_CALLBACK);
+        ASSERT_TRUE(ret.isOk());
     }
-    native_handle_t* const nativeHandle2 = native_handle_create(1, 0);
-    nativeHandle2->data[0] = fd2.release();
-    const hidl_handle h2 = hidl_handle(nativeHandle2);
-
-    const Return<void> ret = config->setHandles(h1, h2, ASSERT_TRUE_CALLBACK);
-    ASSERT_TRUE(ret.isOk());
 }
 
 // Passing a handle without an associated file descriptor should return an error
 // (e.g. "Failed Input Checks"). Check that this occurs when both FDs are empty.
 TEST_F(OffloadConfigHidlTest, TestSetHandleNone) {
     native_handle_t* const nativeHandle1 = native_handle_create(0, 0);
-    const hidl_handle h1 = hidl_handle(nativeHandle1);
+    hidl_handle h1;
+    h1.setTo(nativeHandle1, true);
     native_handle_t* const nativeHandle2 = native_handle_create(0, 0);
-    const hidl_handle h2 = hidl_handle(nativeHandle2);
+    hidl_handle h2;
+    h2.setTo(nativeHandle2, true);
 
     const Return<void> ret = config->setHandles(h1, h2, ASSERT_FALSE_CALLBACK);
     ASSERT_TRUE(ret.isOk());
@@ -135,10 +142,12 @@ TEST_F(OffloadConfigHidlTest, TestSetHandle1Only) {
     }
     native_handle_t* const nativeHandle1 = native_handle_create(1, 0);
     nativeHandle1->data[0] = fd1.release();
-    const hidl_handle h1 = hidl_handle(nativeHandle1);
+    hidl_handle h1;
+    h1.setTo(nativeHandle1, true);
 
     native_handle_t* const nativeHandle2 = native_handle_create(0, 0);
-    const hidl_handle h2 = hidl_handle(nativeHandle2);
+    hidl_handle h2;
+    h2.setTo(nativeHandle2, true);
 
     const Return<void> ret = config->setHandles(h1, h2, ASSERT_FALSE_CALLBACK);
     ASSERT_TRUE(ret.isOk());
@@ -148,7 +157,8 @@ TEST_F(OffloadConfigHidlTest, TestSetHandle1Only) {
 // (e.g. "Failed Input Checks"). Check that this occurs when FD1 is empty.
 TEST_F(OffloadConfigHidlTest, TestSetHandle2OnlyNotOk) {
     native_handle_t* const nativeHandle1 = native_handle_create(0, 0);
-    const hidl_handle h1 = hidl_handle(nativeHandle1);
+    hidl_handle h1;
+    h1.setTo(nativeHandle1, true);
 
     unique_fd fd2(netlinkSocket(kFd2Groups));
     if (fd2.get() < 0) {
@@ -157,7 +167,8 @@ TEST_F(OffloadConfigHidlTest, TestSetHandle2OnlyNotOk) {
     }
     native_handle_t* const nativeHandle2 = native_handle_create(1, 0);
     nativeHandle2->data[0] = fd2.release();
-    const hidl_handle h2 = hidl_handle(nativeHandle2);
+    hidl_handle h2;
+    h2.setTo(nativeHandle2, true);
 
     const Return<void> ret = config->setHandles(h1, h2, ASSERT_FALSE_CALLBACK);
     ASSERT_TRUE(ret.isOk());
index d351edb..72f410e 100644 (file)
@@ -46,13 +46,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.tetheroffload.control@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tetheroffload.control@1.0_genc++"],
     generated_headers: ["android.hardware.tetheroffload.control@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.tetheroffload.control@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index 69fac6e..c6216a2 100644 (file)
 
 cc_test {
     name: "VtsHalTetheroffloadControlV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalTetheroffloadControlV1_0TargetTest.cpp"],
-    shared_libs: [
+    static_libs: [
         "android.hardware.tetheroffload.config@1.0",
         "android.hardware.tetheroffload.control@1.0",
-        "libbase",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "liblog",
-        "libutils",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
     ],
 }
index 3059eac..52dd026 100644 (file)
@@ -46,6 +46,12 @@ using android::hardware::tetheroffload::control::V1_0::NetworkProtocol;
 using android::hardware::Void;
 using android::sp;
 
+enum class ExpectBoolean {
+    Ignored = -1,
+    False = 0,
+    True = 1,
+};
+
 // We use #defines here so as to get local lamba captures and error message line numbers
 #define ASSERT_TRUE_CALLBACK                            \
     [&](bool success, std::string errMsg) {             \
@@ -112,7 +118,12 @@ class OffloadControlHidlTestBase : public testing::VtsHalHidlTargetTestBase {
         prepareControlHal();
     }
 
-    virtual void TearDown() override { stopOffload(false); }
+    virtual void TearDown() override {
+        // For good measure, we should try stopOffload() once more. Since we
+        // don't know where we are in HAL call test cycle we don't know what
+        // return code to actually expect, so we just ignore it.
+        stopOffload(ExpectBoolean::Ignored);
+    }
 
     // The IOffloadConfig HAL is tested more thoroughly elsewhere. He we just
     // setup everything correctly and verify basic readiness.
@@ -127,7 +138,8 @@ class OffloadControlHidlTestBase : public testing::VtsHalHidlTargetTestBase {
         }
         native_handle_t* const nativeHandle1 = native_handle_create(1, 0);
         nativeHandle1->data[0] = fd1.release();
-        hidl_handle h1 = hidl_handle(nativeHandle1);
+        hidl_handle h1;
+        h1.setTo(nativeHandle1, true);
 
         unique_fd fd2(conntrackSocket(NFNLGRP_CONNTRACK_UPDATE | NFNLGRP_CONNTRACK_DESTROY));
         if (fd2.get() < 0) {
@@ -136,7 +148,8 @@ class OffloadControlHidlTestBase : public testing::VtsHalHidlTargetTestBase {
         }
         native_handle_t* const nativeHandle2 = native_handle_create(1, 0);
         nativeHandle2->data[0] = fd2.release();
-        hidl_handle h2 = hidl_handle(nativeHandle2);
+        hidl_handle h2;
+        h2.setTo(nativeHandle2, true);
 
         const Return<void> ret = config->setHandles(h1, h2, ASSERT_TRUE_CALLBACK);
         ASSERT_TRUE(ret.isOk());
@@ -166,12 +179,21 @@ class OffloadControlHidlTestBase : public testing::VtsHalHidlTargetTestBase {
         initOffload(true);
     }
 
-    void stopOffload(const bool expected_result) {
+    void stopOffload(const ExpectBoolean value) {
         auto cb = [&](bool success, const hidl_string& errMsg) {
             if (!success) {
                 ALOGI("Error message: %s", errMsg.c_str());
             }
-            ASSERT_EQ(expected_result, success);
+            switch (value) {
+                case ExpectBoolean::False:
+                    ASSERT_EQ(false, success);
+                    break;
+                case ExpectBoolean::True:
+                    ASSERT_EQ(true, success);
+                    break;
+                case ExpectBoolean::Ignored:
+                    break;
+            }
         };
         const Return<void> ret = control->stopOffload(cb);
         ASSERT_TRUE(ret.isOk());
@@ -209,22 +231,22 @@ TEST_F(OffloadControlHidlTestBase, AdditionalInitsWithoutStopReturnFalse) {
     initOffload(false);
     initOffload(false);
     initOffload(false);
-    stopOffload(true);  // balance out initOffload(true)
+    stopOffload(ExpectBoolean::True);  // balance out initOffload(true)
 }
 
 // Check that calling stopOffload() without first having called initOffload() returns false.
 TEST_F(OffloadControlHidlTestBase, MultipleStopsWithoutInitReturnFalse) {
-    stopOffload(false);
-    stopOffload(false);
-    stopOffload(false);
+    stopOffload(ExpectBoolean::False);
+    stopOffload(ExpectBoolean::False);
+    stopOffload(ExpectBoolean::False);
 }
 
 // Check that calling stopOffload() after a complete init/stop cycle returns false.
 TEST_F(OffloadControlHidlTestBase, AdditionalStopsWithInitReturnFalse) {
     initOffload(true);
-    stopOffload(true);  // balance out initOffload(true)
-    stopOffload(false);
-    stopOffload(false);
+    stopOffload(ExpectBoolean::True);  // balance out initOffload(true)
+    stopOffload(ExpectBoolean::False);
+    stopOffload(ExpectBoolean::False);
 }
 
 // Check that calling setLocalPrefixes() without first having called initOffload() returns false.
@@ -305,7 +327,12 @@ class OffloadControlHidlTest : public OffloadControlHidlTestBase {
         setupControlHal();
     }
 
-    virtual void TearDown() override { stopOffload(true); }
+    virtual void TearDown() override {
+        // For good measure, we should try stopOffload() once more. Since we
+        // don't know where we are in HAL call test cycle we don't know what
+        // return code to actually expect, so we just ignore it.
+        stopOffload(ExpectBoolean::Ignored);
+    }
 };
 
 /*
@@ -575,16 +602,24 @@ TEST_F(OffloadControlHidlTest, AddDownstreamBogusPrefixFails) {
 TEST_F(OffloadControlHidlTest, RemoveDownstreamIPv4) {
     const hidl_string iface("dummy0");
     const hidl_string prefix("192.0.2.0/24");
-    const Return<void> ret = control->removeDownstream(iface, prefix, ASSERT_TRUE_CALLBACK);
-    EXPECT_TRUE(ret.isOk());
+    // First add the downstream, otherwise removeDownstream logic can reasonably
+    // return false for downstreams not previously added.
+    const Return<void> add = control->addDownstream(iface, prefix, ASSERT_TRUE_CALLBACK);
+    EXPECT_TRUE(add.isOk());
+    const Return<void> del = control->removeDownstream(iface, prefix, ASSERT_TRUE_CALLBACK);
+    EXPECT_TRUE(del.isOk());
 }
 
 // Test removeDownstream() works given an IPv6 prefix.
 TEST_F(OffloadControlHidlTest, RemoveDownstreamIPv6) {
     const hidl_string iface("dummy0");
     const hidl_string prefix("2001:db8::/64");
-    const Return<void> ret = control->removeDownstream(iface, prefix, ASSERT_TRUE_CALLBACK);
-    EXPECT_TRUE(ret.isOk());
+    // First add the downstream, otherwise removeDownstream logic can reasonably
+    // return false for downstreams not previously added.
+    const Return<void> add = control->addDownstream(iface, prefix, ASSERT_TRUE_CALLBACK);
+    EXPECT_TRUE(add.isOk());
+    const Return<void> del = control->removeDownstream(iface, prefix, ASSERT_TRUE_CALLBACK);
+    EXPECT_TRUE(del.isOk());
 }
 
 // Test removeDownstream() fails given all empty parameters.
index 6a9f9c7..aa97175 100644 (file)
@@ -39,13 +39,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.thermal@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.thermal@1.0_genc++"],
     generated_headers: ["android.hardware.thermal@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.thermal@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index 9046882..f661f1e 100644 (file)
 
 cc_test {
     name: "VtsHalThermalV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalThermalV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
-        "android.hardware.thermal@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
+    static_libs: ["android.hardware.thermal@1.0"],
 }
 
diff --git a/thermal/1.1/Android.bp b/thermal/1.1/Android.bp
new file mode 100644 (file)
index 0000000..0985d94
--- /dev/null
@@ -0,0 +1,71 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+filegroup {
+    name: "android.hardware.thermal@1.1_hal",
+    srcs: [
+        "IThermal.hal",
+        "IThermalCallback.hal",
+    ],
+}
+
+genrule {
+    name: "android.hardware.thermal@1.1_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.thermal@1.1",
+    srcs: [
+        ":android.hardware.thermal@1.1_hal",
+    ],
+    out: [
+        "android/hardware/thermal/1.1/ThermalAll.cpp",
+        "android/hardware/thermal/1.1/ThermalCallbackAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.thermal@1.1_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.thermal@1.1",
+    srcs: [
+        ":android.hardware.thermal@1.1_hal",
+    ],
+    out: [
+        "android/hardware/thermal/1.1/IThermal.h",
+        "android/hardware/thermal/1.1/IHwThermal.h",
+        "android/hardware/thermal/1.1/BnHwThermal.h",
+        "android/hardware/thermal/1.1/BpHwThermal.h",
+        "android/hardware/thermal/1.1/BsThermal.h",
+        "android/hardware/thermal/1.1/IThermalCallback.h",
+        "android/hardware/thermal/1.1/IHwThermalCallback.h",
+        "android/hardware/thermal/1.1/BnHwThermalCallback.h",
+        "android/hardware/thermal/1.1/BpHwThermalCallback.h",
+        "android/hardware/thermal/1.1/BsThermalCallback.h",
+    ],
+}
+
+cc_library {
+    name: "android.hardware.thermal@1.1",
+    defaults: ["hidl-module-defaults"],
+    generated_sources: ["android.hardware.thermal@1.1_genc++"],
+    generated_headers: ["android.hardware.thermal@1.1_genc++_headers"],
+    export_generated_headers: ["android.hardware.thermal@1.1_genc++_headers"],
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hardware.thermal@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hardware.thermal@1.0",
+    ],
+}
diff --git a/thermal/1.1/Android.mk b/thermal/1.1/Android.mk
new file mode 100644 (file)
index 0000000..082d65b
--- /dev/null
@@ -0,0 +1,120 @@
+# This file is autogenerated by hidl-gen. Do not edit manually.
+
+LOCAL_PATH := $(call my-dir)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.thermal-V1.1-java
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(call local-generated-sources-dir, COMMON)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_JAVA_LIBRARIES := \
+    android.hardware.thermal-V1.0-java \
+    android.hidl.base-V1.0-java \
+
+
+#
+# Build IThermal.hal
+#
+GEN := $(intermediates)/android/hardware/thermal/V1_1/IThermal.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IThermal.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IThermalCallback.hal
+$(GEN): $(LOCAL_PATH)/IThermalCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.thermal@1.1::IThermal
+
+$(GEN): $(LOCAL_PATH)/IThermal.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IThermalCallback.hal
+#
+GEN := $(intermediates)/android/hardware/thermal/V1_1/IThermalCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IThermalCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.thermal@1.1::IThermalCallback
+
+$(GEN): $(LOCAL_PATH)/IThermalCallback.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_JAVA_LIBRARY)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.thermal-V1.1-java-static
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(call local-generated-sources-dir, COMMON)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android.hardware.thermal-V1.0-java-static \
+    android.hidl.base-V1.0-java-static \
+
+
+#
+# Build IThermal.hal
+#
+GEN := $(intermediates)/android/hardware/thermal/V1_1/IThermal.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IThermal.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IThermalCallback.hal
+$(GEN): $(LOCAL_PATH)/IThermalCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.thermal@1.1::IThermal
+
+$(GEN): $(LOCAL_PATH)/IThermal.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IThermalCallback.hal
+#
+GEN := $(intermediates)/android/hardware/thermal/V1_1/IThermalCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IThermalCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.thermal@1.1::IThermalCallback
+
+$(GEN): $(LOCAL_PATH)/IThermalCallback.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/thermal/1.1/IThermal.hal b/thermal/1.1/IThermal.hal
new file mode 100644 (file)
index 0000000..14f35ba
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.thermal@1.1;
+
+import android.hardware.thermal@1.0::IThermal;
+import IThermalCallback;
+
+interface IThermal extends @1.0::IThermal {
+   /**
+    * Register an IThermalCallback, used by the Thermal HAL
+    * to send thermal events to the framework thermal service.
+    *
+    * @param callback the IThermalCallback to use for sending
+    *        thermal events, or nullptr to set no callback
+    */
+    registerThermalCallback(IThermalCallback callback);
+};
diff --git a/thermal/1.1/IThermalCallback.hal b/thermal/1.1/IThermalCallback.hal
new file mode 100644 (file)
index 0000000..f418ec3
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.thermal@1.1;
+
+import android.hardware.thermal@1.0::Temperature;
+
+/**
+ * IThermalCallback connects vendor code to the framework binder ThermalService.
+ */
+interface IThermalCallback {
+    /**
+     * Send a thermal throttling start/stop event to all ThermalService
+     * thermal event listeners.
+     * @param isThrottling true if device is currently throttling
+     * @param temperature The temperature associated with the throttling
+     *        start/stop event
+     */
+    oneway notifyThrottling(bool isThrottling, Temperature temperature);
+};
diff --git a/thermal/1.1/vts/functional/Android.bp b/thermal/1.1/vts/functional/Android.bp
new file mode 100644 (file)
index 0000000..f5f01fa
--- /dev/null
@@ -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.
+//
+
+cc_test {
+    name: "VtsHalThermalV1_1TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalThermalV1_1TargetTest.cpp"],
+    static_libs: [
+        "android.hardware.thermal@1.0",
+        "android.hardware.thermal@1.1",
+    ],
+}
+
diff --git a/thermal/1.1/vts/functional/VtsHalThermalV1_1TargetTest.cpp b/thermal/1.1/vts/functional/VtsHalThermalV1_1TargetTest.cpp
new file mode 100644 (file)
index 0000000..6c1599b
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/hardware/thermal/1.1/IThermal.h>
+#include <android/hardware/thermal/1.1/IThermalCallback.h>
+#include <android/hardware/thermal/1.0/types.h>
+
+#include <VtsHalHidlTargetCallbackBase.h>
+#include <VtsHalHidlTargetTestBase.h>
+
+using ::android::hardware::thermal::V1_0::Temperature;
+using ::android::hardware::thermal::V1_0::TemperatureType;
+using ::android::hardware::thermal::V1_1::IThermal;
+using ::android::hardware::thermal::V1_1::IThermalCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+constexpr char kCallbackNameNotifyThrottling[] = "notifyThrottling";
+static const Temperature kThrottleTemp = {
+    .type = TemperatureType::CPU,
+    .name = "test temperature sensor",
+    .currentValue = 98.6,
+    .throttlingThreshold = 58,
+    .shutdownThreshold = 60,
+    .vrThrottlingThreshold = 59,
+};
+
+class ThermalCallbackArgs {
+   public:
+     bool isThrottling;
+     Temperature temperature;
+};
+
+// Callback class for receiving thermal event notifications from main class
+class ThermalCallback
+    : public ::testing::VtsHalHidlTargetCallbackBase<ThermalCallbackArgs>,
+      public IThermalCallback {
+   public:
+    virtual ~ThermalCallback() = default;
+
+    Return<void> notifyThrottling(bool isThrottling,
+                                  const Temperature& temperature) override {
+        ThermalCallbackArgs args;
+        args.isThrottling = isThrottling;
+        args.temperature = temperature;
+        NotifyFromCallback(kCallbackNameNotifyThrottling, args);
+        return Void();
+    }
+};
+
+// The main test class for THERMAL HIDL HAL 1.1.
+class ThermalHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    virtual void SetUp() override {
+        mThermal = ::testing::VtsHalHidlTargetTestBase::getService<IThermal>();
+        ASSERT_NE(mThermal, nullptr);
+        mThermalCallback = new(std::nothrow) ThermalCallback();
+        ASSERT_NE(mThermalCallback, nullptr);
+        auto ret = mThermal->registerThermalCallback(mThermalCallback);
+        ASSERT_TRUE(ret.isOk());
+    }
+
+    virtual void TearDown() override {
+        auto ret = mThermal->registerThermalCallback(nullptr);
+        ASSERT_TRUE(ret.isOk());
+    }
+
+   protected:
+    sp<IThermal> mThermal;
+    sp<ThermalCallback> mThermalCallback;
+}; // class ThermalHidlTest
+
+// Test ThermalCallback::notifyThrottling().
+// This just calls into and back from our local ThermalCallback impl.
+// Note: a real thermal throttling event from the Thermal HAL could be
+// inadvertently received here.
+TEST_F(ThermalHidlTest, NotifyThrottlingTest) {
+    auto ret = mThermalCallback->notifyThrottling(true, kThrottleTemp);
+    ASSERT_TRUE(ret.isOk());
+    auto res = mThermalCallback->WaitForCallback(kCallbackNameNotifyThrottling);
+    EXPECT_TRUE(res.no_timeout);
+    ASSERT_TRUE(res.args);
+    EXPECT_EQ(true, res.args->isThrottling);
+    EXPECT_EQ(kThrottleTemp, res.args->temperature);
+}
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    cout << "Test result = " << status << std::endl;
+    return status;
+}
index ed19a37..a5415df 100644 (file)
@@ -3,4 +3,6 @@ subdirs = [
     "1.0",
     "1.0/default",
     "1.0/vts/functional",
+    "1.1",
+    "1.1/vts/functional",
 ]
index bf3ffe2..c9da737 100644 (file)
@@ -46,13 +46,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.tv.cec@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tv.cec@1.0_genc++"],
     generated_headers: ["android.hardware.tv.cec@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.tv.cec@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index a3f8c94..22ea1d8 100644 (file)
@@ -46,13 +46,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.tv.input@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tv.input@1.0_genc++"],
     generated_headers: ["android.hardware.tv.input@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.tv.input@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index c862429..978830c 100644 (file)
 
 cc_test {
     name: "VtsHalTvInputV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalTvInputV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
-        "android.hardware.tv.input@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ]
+    static_libs: ["android.hardware.tv.input@1.0"],
 }
 
index b03f75b..afe1931 100644 (file)
@@ -46,13 +46,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.usb@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.usb@1.0_genc++"],
     generated_headers: ["android.hardware.usb@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.usb@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index 7438bc7..96d3c0e 100644 (file)
 
 cc_test {
     name: "VtsHalUsbV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalUsbV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
-        "android.hardware.usb@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
+    static_libs: ["android.hardware.usb@1.0"],
 }
index f067606..5466001 100644 (file)
@@ -46,13 +46,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.usb@1.1",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.usb@1.1_genc++"],
     generated_headers: ["android.hardware.usb@1.1_genc++_headers"],
     export_generated_headers: ["android.hardware.usb@1.1_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index 820f794..4bb3203 100644 (file)
 
 cc_test {
     name: "VtsHalUsbV1_1TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalUsbV1_1TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
+    static_libs: [
         "android.hardware.usb@1.0",
         "android.hardware.usb@1.1",
     ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
 }
 
index 0beff68..354b83f 100644 (file)
@@ -39,13 +39,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.vibrator@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.vibrator@1.0_genc++"],
     generated_headers: ["android.hardware.vibrator@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.vibrator@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index 9e25def..016d627 100644 (file)
 
 cc_test {
     name: "VtsHalVibratorV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalVibratorV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "libhidlbase",
-        "liblog",
-        "libutils",
-        "android.hardware.vibrator@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
+    static_libs: ["android.hardware.vibrator@1.0"],
 }
 
index ee81d83..a47f37c 100644 (file)
@@ -39,13 +39,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.vibrator@1.1",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.vibrator@1.1_genc++"],
     generated_headers: ["android.hardware.vibrator@1.1_genc++_headers"],
     export_generated_headers: ["android.hardware.vibrator@1.1_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index 5baa8ed..4f6454b 100644 (file)
 
 cc_test {
     name: "VtsHalVibratorV1_1TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalVibratorV1_1TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "libhidlbase",
-        "liblog",
-        "libutils",
+    static_libs: [
+        "android.hardware.vibrator@1.0",
         "android.hardware.vibrator@1.1",
     ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
 }
 
index d6949c5..cb9e2af 100644 (file)
@@ -35,13 +35,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.vr@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.vr@1.0_genc++"],
     generated_headers: ["android.hardware.vr@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.vr@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index 5d5a99a..4029137 100644 (file)
 
 cc_test {
     name: "VtsHalVrV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalVrV1_0TargetTest.cpp"],
-    shared_libs: [
-        "liblog",
-        "libhidlbase",
-        "libutils",
-        "android.hardware.vr@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-       "-O0",
-        "-g",
-    ]
+    static_libs: ["android.hardware.vr@1.0"],
 }
index b64391c..cdc59c9 100644 (file)
@@ -39,13 +39,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.weaver@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.weaver@1.0_genc++"],
     generated_headers: ["android.hardware.weaver@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.weaver@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index 9b0ff6d..0089d89 100644 (file)
 
 cc_test {
     name: "VtsHalWeaverV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalWeaverV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
-        "android.hardware.weaver@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
+    static_libs: ["android.hardware.weaver@1.0"],
 }
index c8b694c..d7db770 100644 (file)
@@ -123,13 +123,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.wifi@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.wifi@1.0_genc++"],
     generated_headers: ["android.hardware.wifi@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.wifi@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/wifi/1.0/README-NAN.md b/wifi/1.0/README-NAN.md
new file mode 100644 (file)
index 0000000..f4b3320
--- /dev/null
@@ -0,0 +1,221 @@
+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.
+
+# Wi-Fi Aware (NAN) HAL API Usage
+
+The Wi-Fi Aware (NAN) HAL API is defined in (<i>hardware/interfaces/wifi/\<version\>/</i>):
+
+* IWifiNanIface.hal
+* IWifiNanIfaceEventCallback.hal
+* types.hal (structure definitions)
+
+The Wi-Fi Aware (NAN) HAL API surface is very large - only a subset is used from the framework.
+
+Understanding of the HAL API subset which is actively used by the Android framework can be deduced
+by reviewing framework code, specifically (<i>frameworks/opt/net/wif/</i>):
+
+* WifiAwareNativeApi.java
+* WifiAwareNativeCallback.java
+
+The above framework files determine the API usage - and should be consulted as the authoritative
+reference. Please consult the primary HAL file for documentation - they will not be replicated
+in this document. APIs which are in the HAL but are not listed in this README file are not used by
+the framework.
+
+Note: the HAL API is translated to the legacy HAL API (<i>wifi_nan.h</i>). This README file covers
+the new HAL API only. To understand the mapping between new and legacy HALs please consult
+<i>hardware/interfaces/wifi/\<version\>/default/hidl_struct_util.cpp</i>.
+
+## IWifiNanIface
+
+Format:
+* Hard-coded values are in <b>bold</b>, e.g. <b>true</b> or <b>5</b>
+* Assigned but not fixed value are specified using the <i>variable</i> keyword, possibly with some
+details/constraints
+* Unassigned values are specified using the <i>N/A</i> keyword. Unassigned usually means initialized
+to 0.
+
+APIs:
+
+* registerEventCallback(IWifiNanIfaceEventCallback callback)
+* getCapabilitiesRequest
+* enableRequest
+  * NanEnableRequest
+    * bool[2] operateInBand
+        * Index [NanBandIndex.NAN_BAND_24GHZ] = <b>true</b>
+        * Index [NanBandIndex.NAN_BAND_5GHZ] = <i>variable</i>
+    * uint8_t hopCountMax = <b>2</b>
+    * NanConfigRequest configParams
+        * uint8_t masterPref = <i>variable</i>
+        * bool disableDiscoveryAddressChangeIndication = <i>variable</i>
+        * bool disableStartedClusterIndication = <i>variable</i>
+        * bool disableJoinedClusterIndication = <i>variable</i>
+        * bool includePublishServiceIdsInBeacon = <b>true</b>
+        * uint8_t numberOfPublishServiceIdsInBeacon = <b>0</b>
+        * bool includeSubscribeServiceIdsInBeacon = <b>true</b>
+        * uint8_t numberOfSubscribeServiceIdsInBeacon = <b>0</b>
+        * uint16_t rssiWindowSize = <b>8</b>
+        * uint32_t macAddressRandomizationIntervalSec = <i>variable</i>
+            * Normal run-time: set to <b>1800</b> (30 minutes)
+            * Tests: set to <b>120</b> (2 minutes)
+        * NanBandSpecificConfig[2] bandSpecificConfig
+            * Index [NanBandIndex.NAN_BAND_24GHZ]
+                * uint8_t rssiClose = <b>60</b>
+                * uint8_t rssiMiddle = <b>70</b>
+                * uint8_t rssiCloseProximity = <b>60</b>
+                * uint8_t dwellTimeMs = <b>200</b>
+                * uint16_t scanPeriodSec = <b>20</b>
+                * bool validDiscoveryWindowIntervalVal = <i>variable</i>
+                * uint8_t discoveryWindowIntervalVal = <i>variable</i>
+            * Index [NanBandIndex.NAN_BAND_5GHZ]
+                * uint8_t rssiClose = <b>60</b>
+                * uint8_t rssiMiddle = <b>75</b>
+                * uint8_t rssiCloseProximity = <b>60</b>
+                * uint8_t dwellTimeMs = <b>200</b>
+                * uint16_t scanPeriodSec = <b>20</b>
+                * bool validDiscoveryWindowIntervalVal = <i>variable</i>
+                * uint8_t discoveryWindowIntervalVal = <i>variable</i>
+    * NanDebugConfig debugConfigs
+        * bool validClusterIdVals = <b>true</b>
+        * uint16_t clusterIdBottomRangeVal = <i>variable</i>
+        * uint16_t clusterIdTopRangeVal = <i>variable</i>
+        * bool validIntfAddrVal = <b>false</b>
+        * MacAddress intfAddrVal = <i>N/A</i>
+        * bool validOuiVal = <b>false</b>
+        * uint32_t ouiVal = <i>N/A</i>
+        * bool validRandomFactorForceVal = <b>false</b>
+        * uint8_t randomFactorForceVal = <i>N/A</i>
+        * bool validHopCountForceVal = <b>false</b>
+        * uint8_t hopCountForceVal = <i>N/A</i>
+        * bool validDiscoveryChannelVal = <b>false</b>
+        * WifiChannelInMhz[2] discoveryChannelMhzVal = <i>N/A</i>
+        * bool validUseBeaconsInBandVal = <b>false</b>
+        * bool[2] useBeaconsInBandVal = <i>N/A</i>
+        * bool validUseSdfInBandVal = <b>false</b>
+        * bool[2] useSdfInBandVal = <i>N/A</i>
+* configRequest
+    * NanConfigRequest: same as for <i>enableRequest</i>
+* disableRequest
+* startPublishRequest
+    * NanPublishRequest
+        * NanDiscoveryCommonConfig baseConfigs
+            * uint8_t sessionId = <i>variable</i>
+            * uint16_t ttlSec = <i>variable</i>
+            * uint16_t discoveryWindowPeriod = <b>1</b>
+            * uint8_t discoveryCount = <b>0</b>
+            * vec<uint8_t> serviceName = <i>variable</i>
+            * NanMatchAlg discoveryMatchIndicator = <b>NanMatchAlg.MATCH_NEVER</b>
+            * vec<uint8_t> serviceSpecificInfo = <i>variable</i>
+            * vec<uint8_t> extendedServiceSpecificInfo = <i>N/A</i>
+            * vec<uint8_t> rxMatchFilter = <i>variable</i>
+            * vec<uint8_t> txMatchFilter = <i>variable</i>
+            * bool useRssiThreshold = <b>false</b>
+            * bool disableDiscoveryTerminationIndication = <i>variable</i>
+            * bool disableMatchExpirationIndication = <b>true</b>
+            * bool disableFollowupReceivedIndication = <b>false</b>
+            * NanDataPathSecurityConfig securityConfig = <b>NanDataPathSecurityType.OPEN</b>
+            * bool rangingRequired = <b>false</b>
+            * uint32_t rangingIntervalMsec = <i>N/A</i>
+            * bitfield<NanRangingIndication> configRangingIndications = <i>N/A</i>
+            * uint16_t distanceIngressCm = <i>N/A</i>
+            * uint16_t distanceEgressCm = <i>N/A</i>
+        * NanPublishType publishType = <i>variable</i>
+        * NanTxType txType = <b>NanTxType.BROADCAST</b>
+        * bool autoAcceptDataPathRequests = <b>false</b>
+* stopPublishRequest
+* startSubscribeRequest
+    * NanSubscribeRequest
+        * NanDiscoveryCommonConfig baseConfigs
+            * Mostly same as <i>publish</i> above except:
+            * NanMatchAlg discoveryMatchIndicator = <b>NanMatchAlg.MATCH_ONCE</b>
+        * NanSubscribeType subscribeType = <i>variable</i>
+        * NanSrfType srfType = <i>N/A</i>
+        * bool srfRespondIfInAddressSet = <i>N/A</i>
+        * bool shouldUseSrf = <i>N/A</i>
+        * bool isSsiRequiredForMatch = <i>N/A</i>
+        * vec<MacAddress> intfAddr = <i>N/A</i>
+* stopSubscribeRequest
+* transmitFollowupRequest
+    * NanTransmitFollowupRequest
+        * uint8_t discoverySessionId = <i>variable</i>
+        * uint32_t peerId = <i>variable</i>
+        * MacAddress addr = <i>variable</i>
+        * bool isHighPriority = <b>false</b>
+        * bool shouldUseDiscoveryWindow = <b>true</b>
+        * vec<uint8_t> serviceSpecificInfo = <i>variable</i>
+        * vec<uint8_t> extendedServiceSpecificInfo = <i>N/A</i>
+        * bool disableFollowupResultIndication = <b>false</b>
+* createDataInterfaceRequest
+* deleteDataInterfaceRequest
+* initiateDataPathRequest
+    * NanInitiateDataPathRequest
+        * uint32_t peerId = <i>variable</i>
+        * MacAddress peerDiscMacAddr = <i>variable</i>
+        * NanDataPathChannelCfg channelRequestType =
+        <i>NanDataPathChannelCfg.CHANNEL_NOT_REQUESTED</i>
+        * WifiChannelInMhz channel = <b>2437</b> (note that should be ignored though -
+        CHANNEL_NOT_REQUESTED!)
+        * string ifaceName = <i>variable</i>
+        * NanDataPathSecurityConfig securityConfig = <i>variable</i>
+        * vec<uint8_t> appInfo = <i>N/A</i>
+        * vec<uint8_t> serviceNameOutOfBand = <i>variable</i>
+* respondToDataPathIndicationRequest
+    * NanRespondToDataPathIndicationRequest
+        * bool acceptRequest = <i>variable</i>
+        * uint32_t ndpInstanceId = <i>variable</i>
+        * string ifaceName = <i>variable</i>
+        * NanDataPathSecurityConfig securityConfig = <i>variable</i>
+        * vec<uint8_t> appInfo = <i>N/A</i>
+        * vec<uint8_t> serviceNameOutOfBand = <i>variable</i>
+* terminateDataPathRequest
+
+## IWifiNanIfaceEventCallback
+
+Format:
+* Parameters whose values are <i>ignored</i> will be flagged, otherwise the parameter value is used
+by the framework.
+
+API:
+
+* notifyXxxResponse: all callbacks are used by framework
+* eventClusterEvent
+* eventDisabled
+* eventPublishTerminated
+* eventSubscribeTerminated
+* eventMatch
+    * NanMatchInd (all parameters are used except those listed below)
+        * vec<uint8_t> extendedServiceSpecificInfo: <i>ignored</i>
+        * bool matchOccuredInBeaconFlag: <i>ignored</i>
+        * bool outOfResourceFlag: <i>ignored</i>
+        * uint8_t rssiValue: <i>ignored</i>
+        * NanCipherSuiteType peerCipherType: <i>ignored</i>
+        * bool peerRequiresSecurityEnabledInNdp: <i>ignored</i>
+        * bool peerRequiresRanging: <i>ignored</i>
+        * uint32_t rangingMeasurementInCm: <i>ignored</i>
+        * bitfield<NanRangingIndication> rangingIndicationType: <i>ignored</i>
+* eventMatchExpired: <i>ignored</i>
+* eventFollowupReceived
+    * NanFollowupReceivedInd (all parameters are used except those listed below)
+        * bool receivedInFaw: <i>ignored</i>
+        * vec<uint8_t> extendedServiceSpecificInfo: <i>ignored</i>
+* eventTransmitFollowup
+* eventDataPathRequest
+    * NanDataPathRequestInd (all parameters are used except those listed below)
+        * bool securityRequired: <i>ignored</i>
+        * vec<uint8_t> appInfo: <i>ignored</i>
+* eventDataPathConfirm
+    * NanDataPathConfirmInd (all parameters are used except those listed below)
+        * vec<uint8_t> appInfo: <i>ignored</i>
+* eventDataPathTerminated
+
index 1b5f8f7..b9fb0bd 100644 (file)
@@ -1355,8 +1355,8 @@ struct NanCapabilities {
    */
   uint32_t maxNdiInterfaces;
   /**
-   * Maximum number of data paths (NDP) which can be created concurrently on each individual
-   * data interface (NDI).
+   * Maximum number of data paths (NDP) which can be created concurrently on the device, across all
+   * data interfaces (NDI).
    */
   uint32_t maxNdpSessions;
   /**
index 2d6679f..0cebbfc 100644 (file)
@@ -38,50 +38,30 @@ cc_library_static {
 
 cc_test {
     name: "VtsHalWifiV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: [
         "VtsHalWifiV1_0TargetTest.cpp",
         "wifi_ap_iface_hidl_test.cpp",
         "wifi_chip_hidl_test.cpp",
         "wifi_p2p_iface_hidl_test.cpp",
         "wifi_rtt_controller_hidl_test.cpp",
-        "wifi_sta_iface_hidl_test.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
-        "android.hardware.wifi@1.0",
+        "wifi_sta_iface_hidl_test.cpp",
     ],
-    static_libs: ["VtsHalWifiV1_0TargetTestUtil", "VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
+    static_libs: [
+        "VtsHalWifiV1_0TargetTestUtil",
+        "android.hardware.wifi@1.0",
     ],
 }
 
 cc_test {
     name: "VtsHalWifiNanV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: [
         "VtsHalWifiV1_0TargetTest.cpp",
-        "wifi_nan_iface_hidl_test.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
-        "android.hardware.wifi@1.0",
+        "wifi_nan_iface_hidl_test.cpp",
     ],
-    static_libs: ["VtsHalWifiV1_0TargetTestUtil", "VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
+    static_libs: [
+        "VtsHalWifiV1_0TargetTestUtil",
+        "android.hardware.wifi@1.0",
     ],
 }
index f991fa5..aa6e937 100644 (file)
@@ -42,13 +42,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.wifi@1.1",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.wifi@1.1_genc++"],
     generated_headers: ["android.hardware.wifi@1.1_genc++_headers"],
     export_generated_headers: ["android.hardware.wifi@1.1_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/wifi/1.1/default/OWNERS b/wifi/1.1/default/OWNERS
new file mode 100644 (file)
index 0000000..2878acc
--- /dev/null
@@ -0,0 +1,2 @@
+rpius@google.com
+quiche@google.com
index 2f95c23..f36c8bd 100644 (file)
@@ -55,6 +55,25 @@ Return<void> validateAndCall(
   return Void();
 }
 
+// Use for HIDL methods which return only an instance of WifiStatus.
+// This version passes the global lock acquired to the body of the method.
+// Note: Only used by IWifi::stop() currently.
+template <typename ObjT, typename WorkFuncT, typename... Args>
+Return<void> validateAndCallWithLock(
+    ObjT* obj,
+    WifiStatusCode status_code_if_invalid,
+    WorkFuncT&& work,
+    const std::function<void(const WifiStatus&)>& hidl_cb,
+    Args&&... args) {
+  auto lock = hidl_sync_util::acquireGlobalLock();
+  if (obj->isValid()) {
+    hidl_cb((obj->*work)(&lock, std::forward<Args>(args)...));
+  } else {
+    hidl_cb(createWifiStatus(status_code_if_invalid));
+  }
+  return Void();
+}
+
 // Use for HIDL methods which return instance of WifiStatus and a single return
 // value.
 template <typename ObjT, typename WorkFuncT, typename ReturnT, typename... Args>
index 8456b90..c46ef95 100644 (file)
@@ -31,6 +31,7 @@ namespace wifi {
 namespace V1_1 {
 namespace implementation {
 using hidl_return_util::validateAndCall;
+using hidl_return_util::validateAndCallWithLock;
 
 Wifi::Wifi()
     : legacy_hal_(new legacy_hal::WifiLegacyHal()),
@@ -64,8 +65,8 @@ Return<void> Wifi::start(start_cb hidl_status_cb) {
 }
 
 Return<void> Wifi::stop(stop_cb hidl_status_cb) {
-  return validateAndCall(
-      this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::stopInternal, hidl_status_cb);
+  return validateAndCallWithLock(this, WifiStatusCode::ERROR_UNKNOWN,
+                                 &Wifi::stopInternal, hidl_status_cb);
 }
 
 Return<void> Wifi::getChipIds(getChipIds_cb hidl_status_cb) {
@@ -120,7 +121,8 @@ WifiStatus Wifi::startInternal() {
   return wifi_status;
 }
 
-WifiStatus Wifi::stopInternal() {
+WifiStatus Wifi::stopInternal(
+    /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock) {
   if (run_state_ == RunState::STOPPED) {
     return createWifiStatus(WifiStatusCode::SUCCESS);
   } else if (run_state_ == RunState::STOPPING) {
@@ -133,7 +135,7 @@ WifiStatus Wifi::stopInternal() {
     chip_->invalidate();
     chip_.clear();
   }
-  WifiStatus wifi_status = stopLegacyHalAndDeinitializeModeController();
+  WifiStatus wifi_status = stopLegacyHalAndDeinitializeModeController(lock);
   if (wifi_status.code == WifiStatusCode::SUCCESS) {
     for (const auto& callback : event_cb_handler_.getCallbacks()) {
       if (!callback->onStop().isOk()) {
@@ -180,11 +182,11 @@ WifiStatus Wifi::initializeLegacyHal() {
   return createWifiStatus(WifiStatusCode::SUCCESS);
 }
 
-WifiStatus Wifi::stopLegacyHalAndDeinitializeModeController() {
+WifiStatus Wifi::stopLegacyHalAndDeinitializeModeController(
+    /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock) {
   run_state_ = RunState::STOPPING;
-  const auto on_complete_callback_ = [&]() { run_state_ = RunState::STOPPED; };
   legacy_hal::wifi_error legacy_status =
-      legacy_hal_->stop(on_complete_callback_);
+      legacy_hal_->stop(lock, [&]() { run_state_ = RunState::STOPPED; });
   if (legacy_status != legacy_hal::WIFI_SUCCESS) {
     LOG(ERROR) << "Failed to stop legacy HAL: "
                << legacyErrorToString(legacy_status);
index 1ade2d8..3a64cbd 100644 (file)
@@ -61,12 +61,13 @@ class Wifi : public V1_1::IWifi {
   WifiStatus registerEventCallbackInternal(
       const sp<IWifiEventCallback>& event_callback);
   WifiStatus startInternal();
-  WifiStatus stopInternal();
+  WifiStatus stopInternal(std::unique_lock<std::recursive_mutex>* lock);
   std::pair<WifiStatus, std::vector<ChipId>> getChipIdsInternal();
   std::pair<WifiStatus, sp<IWifiChip>> getChipInternal(ChipId chip_id);
 
   WifiStatus initializeLegacyHal();
-  WifiStatus stopLegacyHalAndDeinitializeModeController();
+  WifiStatus stopLegacyHalAndDeinitializeModeController(
+      std::unique_lock<std::recursive_mutex>* lock);
 
   // Instance is created in this root level |IWifi| HIDL interface object
   // and shared with all the child HIDL interface objects.
index 7d683d3..36da6e5 100644 (file)
@@ -15,6 +15,7 @@
  */
 
 #include <array>
+#include <chrono>
 
 #include <android-base/logging.h>
 #include <cutils/properties.h>
@@ -34,6 +35,7 @@ static constexpr uint32_t kMaxGscanFrequenciesForBand = 64;
 static constexpr uint32_t kLinkLayerStatsDataMpduSizeThreshold = 128;
 static constexpr uint32_t kMaxWakeReasonStatsArraySize = 32;
 static constexpr uint32_t kMaxRingBuffers = 10;
+static constexpr uint32_t kMaxStopCompleteWaitMs = 100;
 
 // Helper function to create a non-const char* for legacy Hal API's.
 std::vector<char> makeCharVec(const std::string& str) {
@@ -53,7 +55,8 @@ namespace legacy_hal {
 // Legacy HAL functions accept "C" style function pointers, so use global
 // functions to pass to the legacy HAL function and store the corresponding
 // std::function methods to be invoked.
-// Callback to be invoked once |stop| is complete.
+//
+// Callback to be invoked once |stop| is complete
 std::function<void(wifi_handle handle)> on_stop_complete_internal_callback;
 void onAsyncStopComplete(wifi_handle handle) {
   const auto lock = hidl_sync_util::acquireGlobalLock();
@@ -369,6 +372,7 @@ wifi_error WifiLegacyHal::start() {
 }
 
 wifi_error WifiLegacyHal::stop(
+    /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,
     const std::function<void()>& on_stop_complete_user_callback) {
   if (!is_started_) {
     LOG(DEBUG) << "Legacy HAL already stopped";
@@ -376,19 +380,27 @@ wifi_error WifiLegacyHal::stop(
     return WIFI_SUCCESS;
   }
   LOG(DEBUG) << "Stopping legacy HAL";
-  on_stop_complete_internal_callback = [on_stop_complete_user_callback,
-                                        this](wifi_handle handle) {
+  on_stop_complete_internal_callback =
+      [on_stop_complete_user_callback, this](wifi_handle handle) {
     CHECK_EQ(global_handle_, handle) << "Handle mismatch";
+    LOG(INFO) << "Legacy HAL stop complete callback received";
     // Invalidate all the internal pointers now that the HAL is
     // stopped.
     invalidate();
     iface_tool_.SetWifiUpState(false);
     on_stop_complete_user_callback();
+    is_started_ = false;
   };
   awaiting_event_loop_termination_ = true;
   global_func_table_.wifi_cleanup(global_handle_, onAsyncStopComplete);
+  const auto status = stop_wait_cv_.wait_for(
+      *lock, std::chrono::milliseconds(kMaxStopCompleteWaitMs),
+      [this] { return !awaiting_event_loop_termination_; });
+  if (!status) {
+    LOG(ERROR) << "Legacy HAL stop failed or timed out";
+    return WIFI_ERROR_UNKNOWN;
+  }
   LOG(DEBUG) << "Legacy HAL stop complete";
-  is_started_ = false;
   return WIFI_SUCCESS;
 }
 
@@ -1257,11 +1269,13 @@ wifi_error WifiLegacyHal::retrieveWlanInterfaceHandle() {
 void WifiLegacyHal::runEventLoop() {
   LOG(DEBUG) << "Starting legacy HAL event loop";
   global_func_table_.wifi_event_loop(global_handle_);
+  const auto lock = hidl_sync_util::acquireGlobalLock();
   if (!awaiting_event_loop_termination_) {
     LOG(FATAL) << "Legacy HAL event loop terminated, but HAL was not stopping";
   }
   LOG(DEBUG) << "Legacy HAL event loop terminated";
   awaiting_event_loop_termination_ = false;
+  stop_wait_cv_.notify_one();
 }
 
 std::pair<wifi_error, std::vector<wifi_cached_scan_results>>
@@ -1284,7 +1298,7 @@ WifiLegacyHal::getGscanCachedResults() {
     for (int i = 0; i < num_scan_results; i++) {
       auto& scan_result = cached_scan_result.results[i];
       if (scan_result.ie_length > 0) {
-        LOG(ERROR) << "Cached scan result has non-zero IE length "
+        LOG(DEBUG) << "Cached scan result has non-zero IE length "
                    << scan_result.ie_length;
         scan_result.ie_length = 0;
       }
index caa1bd5..5498803 100644 (file)
@@ -20,6 +20,7 @@
 #include <functional>
 #include <thread>
 #include <vector>
+#include <condition_variable>
 
 #include <wifi_system/interface_tool.h>
 
@@ -149,8 +150,10 @@ class WifiLegacyHal {
   wifi_error initialize();
   // Start the legacy HAL and the event looper thread.
   wifi_error start();
-  // Deinitialize the legacy HAL and stop the event looper thread.
-  wifi_error stop(const std::function<void()>& on_complete_callback);
+  // Deinitialize the legacy HAL and wait for the event loop thread to exit
+  // using a predefined timeout.
+  wifi_error stop(std::unique_lock<std::recursive_mutex>* lock,
+                  const std::function<void()>& on_complete_callback);
   // Wrappers for all the functions in the legacy HAL function table.
   std::pair<wifi_error, std::string> getDriverVersion();
   std::pair<wifi_error, std::string> getFirmwareVersion();
@@ -293,6 +296,7 @@ class WifiLegacyHal {
   wifi_interface_handle wlan_interface_handle_;
   // Flag to indicate if we have initiated the cleanup of legacy HAL.
   std::atomic<bool> awaiting_event_loop_termination_;
+  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_;
index 6b0baf7..1b0c12d 100644 (file)
 
 cc_test {
     name: "VtsHalWifiV1_1TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: [
         "VtsHalWifiV1_1TargetTest.cpp",
         "wifi_chip_hidl_test.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
+    static_libs: [
+        "VtsHalWifiV1_0TargetTestUtil",
         "android.hardware.wifi@1.0",
         "android.hardware.wifi@1.1",
     ],
-    static_libs: ["VtsHalWifiV1_0TargetTestUtil", "VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
 }
diff --git a/wifi/1.1/vts/functional/OWNERS b/wifi/1.1/vts/functional/OWNERS
new file mode 100644 (file)
index 0000000..2878acc
--- /dev/null
@@ -0,0 +1,2 @@
+rpius@google.com
+quiche@google.com
index b4ab98f..1153b0c 100644 (file)
@@ -7,4 +7,5 @@ subdirs = [
     "offload/1.0",
     "offload/1.0/vts/functional",
     "supplicant/1.0",
+    "supplicant/1.0/vts/functional",
 ]
index 28e8e6a..5b7fcad 100644 (file)
@@ -46,13 +46,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.wifi.offload@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.wifi.offload@1.0_genc++"],
     generated_headers: ["android.hardware.wifi.offload@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.wifi.offload@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
index f907a89..140e45e 100644 (file)
 
 cc_test {
     name: "VtsHalWifiOffloadV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalWifiOffloadV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
-        "android.hardware.wifi.offload@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
+    static_libs: ["android.hardware.wifi.offload@1.0"],
 }
index 9242fb6..978192d 100644 (file)
@@ -116,13 +116,16 @@ genrule {
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.wifi.supplicant@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.wifi.supplicant@1.0_genc++"],
     generated_headers: ["android.hardware.wifi.supplicant@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.wifi.supplicant@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/wifi/supplicant/1.0/vts/functional/Android.bp b/wifi/supplicant/1.0/vts/functional/Android.bp
new file mode 100644 (file)
index 0000000..24b9f6f
--- /dev/null
@@ -0,0 +1,37 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+    name: "VtsHalWifiSupplicantV1_0TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "VtsHalWifiSupplicantV1_0TargetTest.cpp",
+        "supplicant_hidl_test.cpp",
+        "supplicant_hidl_test_utils.cpp",
+        "supplicant_p2p_iface_hidl_test.cpp",
+        "supplicant_sta_iface_hidl_test.cpp",
+        "supplicant_sta_network_hidl_test.cpp",
+    ],
+    static_libs: [
+        "VtsHalWifiV1_0TargetTestUtil",
+        "android.hardware.wifi.supplicant@1.0",
+        "android.hardware.wifi@1.0",
+        "libcrypto",
+        "libgmock",
+        "libwifi-system",
+        "libwifi-system-iface",
+    ],
+}
diff --git a/wifi/supplicant/1.0/vts/functional/Android.mk b/wifi/supplicant/1.0/vts/functional/Android.mk
deleted file mode 100644 (file)
index c6e3950..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-#
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := VtsHalWifiSupplicantV1_0TargetTest
-LOCAL_CPPFLAGS := -Wall -Werror -Wextra
-LOCAL_SRC_FILES := \
-    VtsHalWifiSupplicantV1_0TargetTest.cpp \
-    supplicant_hidl_test.cpp \
-    supplicant_hidl_test_utils.cpp \
-    supplicant_p2p_iface_hidl_test.cpp \
-    supplicant_sta_iface_hidl_test.cpp \
-    supplicant_sta_network_hidl_test.cpp
-LOCAL_SHARED_LIBRARIES := \
-    android.hardware.wifi.supplicant@1.0 \
-    android.hardware.wifi@1.0 \
-    libbase \
-    libcutils \
-    libhidlbase \
-    libhidltransport \
-    liblog \
-    libutils \
-    libwifi-system \
-    libwifi-system-iface
-LOCAL_STATIC_LIBRARIES := \
-    libgmock \
-    VtsHalHidlTargetTestBase \
-    VtsHalWifiV1_0TargetTestUtil
-include $(BUILD_NATIVE_TEST)
-