summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXin Li <delphij@google.com>2017-11-14 12:08:38 -0800
committerXin Li <delphij@google.com>2017-11-14 12:08:38 -0800
commitbb9e38fef95b7bc932ebcad18508e03228f9f7d3 (patch)
tree29e859e08879c87f591507de0f370abd1ec66fe2
parentb86b2d2881d53219c59a5eb85a3d73cb45942661 (diff)
parent1a06284b24f5eb7bb9c1fea0817da8898b3b1bff (diff)
downloadplatform_hardware_interfaces-bb9e38fef95b7bc932ebcad18508e03228f9f7d3.tar.gz
platform_hardware_interfaces-bb9e38fef95b7bc932ebcad18508e03228f9f7d3.tar.bz2
platform_hardware_interfaces-bb9e38fef95b7bc932ebcad18508e03228f9f7d3.zip
Merge commit '1a06284b24f5eb7bb9c1fea0817da8898b3b1bff' from
oc-mr1-dev-plus-aosp into stage-aosp-master Change-Id: I2a044eb8c9981d0a8198ffe2df55559afbd76341 Merged-In: I4fb9f18884f7ef21162015a0032c4431444f7025
-rw-r--r--CleanSpec.mk7
-rw-r--r--audio/2.0/config/audio_policy_configuration.xsd8
-rw-r--r--audio/2.0/default/Android.mk4
-rw-r--r--audio/2.0/default/OWNERS3
-rw-r--r--audio/2.0/default/Stream.h7
-rw-r--r--audio/2.0/default/StreamIn.cpp12
-rw-r--r--audio/2.0/default/StreamOut.cpp11
-rw-r--r--audio/2.0/default/service.cpp19
-rw-r--r--audio/2.0/vts/functional/Android.bp29
-rw-r--r--audio/2.0/vts/functional/ValidateAudioConfiguration.cpp16
-rw-r--r--audio/common/2.0/default/Android.bp3
-rw-r--r--audio/common/2.0/default/OWNERS3
-rw-r--r--audio/common/test/utility/OWNERS3
-rw-r--r--audio/effect/2.0/default/OWNERS3
-rw-r--r--audio/effect/2.0/vts/functional/Android.bp24
-rw-r--r--audio/effect/2.0/vts/functional/ValidateAudioEffectsConfiguration.cpp30
-rw-r--r--audio/effect/2.0/xml/audio_effects_conf_V2_0.xsd249
-rw-r--r--automotive/Android.bp4
-rw-r--r--automotive/evs/1.0/default/Android.bp31
-rw-r--r--automotive/evs/1.0/default/Android.mk29
-rw-r--r--automotive/evs/1.0/vts/functional/Android.bp5
-rw-r--r--automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp (renamed from automotive/evs/1.0/vts/functional/VtsEvsV1_0TargetTest.cpp)11
-rw-r--r--automotive/vehicle/2.0/Android.mk608
-rw-r--r--automotive/vehicle/2.0/default/Android.bp117
-rw-r--r--automotive/vehicle/2.0/default/Android.mk194
-rw-r--r--automotive/vehicle/2.0/default/common/include/vhal_v2_0/Obd2SensorStore.h (renamed from automotive/vehicle/2.1/default/common/include/vhal_v2_1/Obd2SensorStore.h)31
-rw-r--r--automotive/vehicle/2.0/default/common/src/Obd2SensorStore.cpp (renamed from automotive/vehicle/2.1/default/common/src/Obd2SensorStore.cpp)51
-rw-r--r--automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h74
-rw-r--r--automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp217
-rw-r--r--automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h11
-rw-r--r--automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/Android.bp27
-rw-r--r--automotive/vehicle/2.0/types.hal1475
-rw-r--r--automotive/vehicle/2.1/Android.bp68
-rw-r--r--automotive/vehicle/2.1/Android.mk648
-rw-r--r--automotive/vehicle/2.1/IVehicle.hal31
-rw-r--r--automotive/vehicle/2.1/default/Android.mk121
-rw-r--r--automotive/vehicle/2.1/default/android.hardware.automotive.vehicle@2.1-service.rc4
-rw-r--r--automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultConfig.h90
-rw-r--r--automotive/vehicle/2.1/default/impl/vhal_v2_1/EmulatedVehicleHal.cpp263
-rw-r--r--automotive/vehicle/2.1/default/impl/vhal_v2_1/EmulatedVehicleHal.h77
-rw-r--r--automotive/vehicle/2.1/default/service.cpp104
-rw-r--r--automotive/vehicle/2.1/default/tests/Obd2SensorStore_test.cpp285
-rw-r--r--automotive/vehicle/2.1/types.hal653
-rw-r--r--biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp2
-rw-r--r--biometrics/fingerprint/2.1/default/BiometricsFingerprint.h1
-rw-r--r--bluetooth/1.0/default/async_fd_watcher.cc2
-rw-r--r--bluetooth/1.0/default/bluetooth_address.cc1
-rw-r--r--bluetooth/1.0/default/h4_protocol.cc1
-rw-r--r--bluetooth/1.0/default/hci_packetizer.cc1
-rw-r--r--bluetooth/1.0/default/hci_protocol.cc1
-rw-r--r--broadcastradio/1.0/default/OWNERS4
-rw-r--r--broadcastradio/1.0/types.hal33
-rw-r--r--broadcastradio/1.1/IBroadcastRadio.hal34
-rw-r--r--broadcastradio/1.1/IBroadcastRadioFactory.hal6
-rw-r--r--broadcastradio/1.1/ITuner.hal80
-rw-r--r--broadcastradio/1.1/ITunerCallback.hal40
-rw-r--r--broadcastradio/1.1/WARNING1
-rw-r--r--broadcastradio/1.1/default/Android.bp21
-rw-r--r--broadcastradio/1.1/default/BroadcastRadio.cpp232
-rw-r--r--broadcastradio/1.1/default/BroadcastRadio.h68
-rw-r--r--broadcastradio/1.1/default/BroadcastRadioFactory.cpp42
-rw-r--r--broadcastradio/1.1/default/BroadcastRadioFactory.h14
-rw-r--r--broadcastradio/1.1/default/OWNERS4
-rw-r--r--broadcastradio/1.1/default/Tuner.cpp449
-rw-r--r--broadcastradio/1.1/default/Tuner.h66
-rw-r--r--broadcastradio/1.1/default/Utils.cpp299
-rw-r--r--broadcastradio/1.1/default/Utils.h58
-rw-r--r--broadcastradio/1.1/default/VirtualProgram.cpp106
-rw-r--r--broadcastradio/1.1/default/VirtualProgram.h55
-rw-r--r--broadcastradio/1.1/default/VirtualRadio.cpp105
-rw-r--r--broadcastradio/1.1/default/VirtualRadio.h80
-rw-r--r--broadcastradio/1.1/default/android.hardware.broadcastradio@1.1-service.rc4
-rw-r--r--broadcastradio/1.1/default/resources.h46
-rw-r--r--broadcastradio/1.1/default/service.cpp36
-rw-r--r--broadcastradio/1.1/tests/Android.bp29
-rw-r--r--broadcastradio/1.1/tests/OWNERS8
-rw-r--r--broadcastradio/1.1/tests/WorkerThread_test.cpp138
-rw-r--r--broadcastradio/1.1/types.hal246
-rw-r--r--broadcastradio/1.1/utils/Android.bp (renamed from power/1.1/default/Android.bp)33
-rw-r--r--broadcastradio/1.1/utils/OWNERS4
-rw-r--r--broadcastradio/1.1/utils/Utils.cpp234
-rw-r--r--broadcastradio/1.1/utils/WorkerThread.cpp89
-rw-r--r--broadcastradio/1.1/utils/include/broadcastradio-utils/Utils.h89
-rw-r--r--broadcastradio/1.1/utils/include/broadcastradio-utils/WorkerThread.h51
-rw-r--r--broadcastradio/1.1/vts/OWNERS8
-rw-r--r--broadcastradio/1.1/vts/functional/Android.bp19
-rw-r--r--broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp790
-rw-r--r--broadcastradio/1.1/vts/utils/Android.bp28
-rw-r--r--broadcastradio/1.1/vts/utils/call-barrier.cpp45
-rw-r--r--broadcastradio/1.1/vts/utils/include/broadcastradio-vts-utils/call-barrier.h59
-rw-r--r--broadcastradio/1.1/vts/utils/include/broadcastradio-vts-utils/mock-timeout.h111
-rw-r--r--broadcastradio/Android.bp3
-rw-r--r--camera/Android.bp2
-rw-r--r--camera/common/1.0/default/CameraParameters.cpp1
-rw-r--r--camera/device/1.0/default/Android.bp3
-rw-r--r--camera/device/1.0/default/OWNERS6
-rw-r--r--camera/device/3.2/default/CameraDevice.cpp25
-rw-r--r--camera/device/3.2/default/CameraDeviceSession.cpp21
-rw-r--r--camera/device/3.2/default/CameraDeviceSession.h82
-rw-r--r--camera/device/3.2/default/CameraDevice_3_2.h8
-rw-r--r--camera/device/3.2/default/OWNERS6
-rw-r--r--camera/device/3.3/Android.bp72
-rw-r--r--camera/device/3.3/ICameraDeviceSession.hal50
-rw-r--r--camera/device/3.3/default/Android.bp30
-rw-r--r--camera/device/3.3/default/CameraDevice.cpp67
-rw-r--r--camera/device/3.3/default/CameraDeviceSession.cpp178
-rw-r--r--camera/device/3.3/default/CameraDeviceSession.h138
-rw-r--r--camera/device/3.3/default/CameraDevice_3_3.h75
-rw-r--r--camera/device/3.3/default/OWNERS6
-rw-r--r--camera/device/3.3/default/convert.cpp65
-rw-r--r--camera/device/3.3/default/include/convert.h49
-rw-r--r--camera/device/3.3/types.hal57
-rw-r--r--camera/device/README.md13
-rw-r--r--camera/provider/2.4/default/Android.bp3
-rw-r--r--camera/provider/2.4/default/CameraProvider.cpp83
-rw-r--r--camera/provider/2.4/default/CameraProvider.h8
-rw-r--r--camera/provider/2.4/default/OWNERS6
-rw-r--r--camera/provider/2.4/vts/OWNERS11
-rw-r--r--camera/provider/2.4/vts/functional/Android.bp32
-rw-r--r--camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp3138
-rw-r--r--cas/1.0/Android.bp87
-rw-r--r--cas/1.0/CasHal.mk192
-rw-r--r--cas/1.0/ICas.hal122
-rw-r--r--cas/1.0/ICasListener.hal28
-rw-r--r--cas/1.0/IDescramblerBase.hal49
-rw-r--r--cas/1.0/IMediaCasService.hal68
-rw-r--r--cas/1.0/default/Android.bp39
-rw-r--r--cas/1.0/default/CasImpl.cpp205
-rw-r--r--cas/1.0/default/CasImpl.h103
-rw-r--r--cas/1.0/default/DescramblerImpl.cpp127
-rw-r--r--cas/1.0/default/DescramblerImpl.h69
-rw-r--r--cas/1.0/default/FactoryLoader.h229
-rw-r--r--cas/1.0/default/MediaCasService.cpp112
-rw-r--r--cas/1.0/default/MediaCasService.h64
-rw-r--r--cas/1.0/default/SharedLibrary.cpp65
-rw-r--r--cas/1.0/default/SharedLibrary.h50
-rw-r--r--cas/1.0/default/TypeConvert.cpp95
-rw-r--r--cas/1.0/default/TypeConvert.h41
-rw-r--r--cas/1.0/default/android.hardware.cas@1.0-service.rc6
-rw-r--r--cas/1.0/default/service.cpp50
-rw-r--r--cas/1.0/types.hal124
-rw-r--r--cas/1.0/vts/functional/Android.bp (renamed from configstore/1.1/vts/functional/Android.bp)24
-rw-r--r--cas/1.0/vts/functional/VtsHalCasV1_0TargetTest.cpp623
-rw-r--r--cas/Android.bp7
-rw-r--r--cas/native/1.0/Android.bp68
-rw-r--r--cas/native/1.0/IDescrambler.hal46
-rw-r--r--cas/native/1.0/types.hal88
-rw-r--r--compatibility_matrix.26.xml67
-rw-r--r--compatibility_matrix.27.xml370
-rw-r--r--compatibility_matrix.current.xml59
-rw-r--r--compatibility_matrix.legacy.xml67
-rw-r--r--configstore/1.0/default/Android.mk34
-rw-r--r--configstore/1.0/default/SurfaceFlingerConfigs.cpp (renamed from configstore/1.1/default/SurfaceFlingerConfigs.cpp)7
-rw-r--r--configstore/1.0/default/SurfaceFlingerConfigs.h (renamed from configstore/1.1/default/SurfaceFlingerConfigs.h)17
-rw-r--r--configstore/1.0/default/android.hardware.configstore@1.0-service.rc4
-rw-r--r--configstore/1.0/default/seccomp_policy/configstore@1.0-arm64.policy51
-rw-r--r--configstore/1.0/default/service.cpp (renamed from configstore/1.1/default/service.cpp)13
-rw-r--r--configstore/1.0/default/surfaceflinger.mk (renamed from configstore/1.1/default/surfaceflinger.mk)0
-rw-r--r--configstore/1.1/Android.bp170
-rw-r--r--configstore/1.1/ISurfaceFlingerConfigs.hal25
-rw-r--r--configstore/1.1/default/Android.mk23
-rw-r--r--configstore/1.1/default/android.hardware.configstore@1.1-service.rc4
-rw-r--r--configstore/1.1/vts/functional/VtsHalConfigstoreV1_1TargetTest.cpp55
-rw-r--r--configstore/Android.bp2
-rw-r--r--contexthub/1.0/default/Contexthub.cpp17
-rw-r--r--current.txt35
-rw-r--r--drm/1.0/default/Android.mk3
-rw-r--r--drm/1.0/default/CryptoFactory.h1
-rw-r--r--drm/1.0/default/CryptoPlugin.cpp15
-rw-r--r--drm/1.0/default/DrmFactory.h1
-rw-r--r--drm/1.0/vts/functional/Android.bp20
-rw-r--r--drm/1.0/vts/functional/drm_hal_clearkey_test.cpp109
-rw-r--r--drm/1.0/vts/functional/drm_hal_vendor_test.cpp22
-rw-r--r--dumpstate/1.0/vts/functional/Android.bp15
-rw-r--r--gnss/1.0/default/GnssMeasurement.cpp3
-rw-r--r--gnss/1.0/default/OWNERS3
-rw-r--r--gnss/1.0/vts/OWNERS7
-rw-r--r--graphics/composer/2.1/default/Hwc.cpp2
-rw-r--r--graphics/composer/2.1/default/IComposerCommandBuffer.h17
-rw-r--r--graphics/composer/2.1/vts/functional/Android.bp28
-rw-r--r--graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp51
-rw-r--r--graphics/mapper/2.0/vts/functional/Android.bp22
-rw-r--r--health/1.0/default/Android.bp20
-rw-r--r--health/1.0/default/Android.mk18
-rw-r--r--health/1.0/default/libhealthd/Android.bp10
-rw-r--r--health/1.0/default/libhealthd/Android.mk10
-rw-r--r--health/Android.bp2
-rw-r--r--keymaster/3.0/vts/functional/Android.bp32
-rw-r--r--keymaster/3.0/vts/functional/Android.mk39
-rw-r--r--keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp6
-rw-r--r--keymaster/Android.bp1
-rw-r--r--media/omx/1.0/IOmxStore.hal6
-rw-r--r--media/omx/1.0/vts/functional/audio/Android.bp62
-rw-r--r--media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioDecTest.cpp372
-rw-r--r--media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioEncTest.cpp114
-rw-r--r--media/omx/1.0/vts/functional/audio/media_audio_hidl_test_common.cpp4
-rw-r--r--media/omx/1.0/vts/functional/audio/media_audio_hidl_test_common.h5
-rw-r--r--[-rwxr-xr-x]media/omx/1.0/vts/functional/common/Android.bp39
-rw-r--r--[-rwxr-xr-x]media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp263
-rw-r--r--media/omx/1.0/vts/functional/common/media_hidl_test_common.h57
-rw-r--r--media/omx/1.0/vts/functional/component/Android.bp27
-rw-r--r--media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp507
-rw-r--r--media/omx/1.0/vts/functional/master/Android.bp24
-rw-r--r--media/omx/1.0/vts/functional/master/VtsHalMediaOmxV1_0TargetMasterTest.cpp7
-rw-r--r--media/omx/1.0/vts/functional/video/Android.bp69
-rw-r--r--media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp864
-rw-r--r--media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp259
-rw-r--r--media/omx/1.0/vts/functional/video/media_video_hidl_test_common.cpp1
-rw-r--r--media/omx/1.0/vts/functional/video/media_video_hidl_test_common.h6
-rw-r--r--[-rwxr-xr-x]media/res/bbb_aac_stereo_128kbps_48000hz.aacbin159216 -> 159216 bytes
-rw-r--r--[-rwxr-xr-x]media/res/bbb_aac_stereo_128kbps_48000hz.info0
-rw-r--r--[-rwxr-xr-x]media/res/bbb_amrwb_1ch_14kbps_16000hz.amrwbbin20254 -> 20254 bytes
-rw-r--r--[-rwxr-xr-x]media/res/bbb_amrwb_1ch_14kbps_16000hz.info0
-rw-r--r--media/res/bbb_avc_176x144_300kbps_60fps.h264bin0 -> 37899 bytes
-rw-r--r--media/res/bbb_avc_176x144_300kbps_60fps.info62
-rw-r--r--media/res/bbb_flac_stereo_680kbps_48000hz.flacbin0 -> 840775 bytes
-rw-r--r--media/res/bbb_flac_stereo_680kbps_48000hz.info415
-rw-r--r--[-rwxr-xr-x]media/res/bbb_g711alaw_1ch_8khz.info0
-rw-r--r--[-rwxr-xr-x]media/res/bbb_g711alaw_1ch_8khz.raw0
-rw-r--r--[-rwxr-xr-x]media/res/bbb_g711mulaw_1ch_8khz.info0
-rw-r--r--[-rwxr-xr-x]media/res/bbb_g711mulaw_1ch_8khz.raw0
-rw-r--r--[-rwxr-xr-x]media/res/bbb_gsm_1ch_8khz_13kbps.info0
-rw-r--r--[-rwxr-xr-x]media/res/bbb_gsm_1ch_8khz_13kbps.rawbin16120 -> 16120 bytes
-rw-r--r--media/res/bbb_hevc_176x144_176kbps_60fps.hevcbin0 -> 20503 bytes
-rw-r--r--media/res/bbb_hevc_176x144_176kbps_60fps.info61
-rw-r--r--media/res/bbb_mpeg2_352x288_1mbps_60fps.info60
-rw-r--r--media/res/bbb_mpeg2_352x288_1mbps_60fps.m2vbin0 -> 123976 bytes
-rw-r--r--[-rwxr-xr-x]media/res/bbb_opus_stereo_128kbps_48000hz.info0
-rw-r--r--[-rwxr-xr-x]media/res/bbb_opus_stereo_128kbps_48000hz.opusbin163743 -> 163743 bytes
-rw-r--r--[-rwxr-xr-x]media/res/bbb_raw_1ch_8khz_s32le.info0
-rw-r--r--[-rwxr-xr-x]media/res/bbb_raw_1ch_8khz_s32le.rawbin158380 -> 158380 bytes
-rw-r--r--[-rwxr-xr-x]media/res/bbb_vorbis_stereo_128kbps_48000hz.info0
-rw-r--r--[-rwxr-xr-x]media/res/bbb_vorbis_stereo_128kbps_48000hz.vorbisbin147450 -> 147450 bytes
-rw-r--r--media/res/bbb_vp8_176x144_240kbps_60fps.info60
-rw-r--r--media/res/bbb_vp8_176x144_240kbps_60fps.vp8bin0 -> 28992 bytes
-rw-r--r--media/res/bbb_vp9_176x144_285kbps_60fps.info60
-rw-r--r--media/res/bbb_vp9_176x144_285kbps_60fps.vp9bin0 -> 34848 bytes
-rw-r--r--neuralnetworks/1.0/Android.bp87
-rw-r--r--neuralnetworks/1.0/IDevice.hal126
-rw-r--r--neuralnetworks/1.0/IExecutionCallback.hal44
-rw-r--r--neuralnetworks/1.0/IPreparedModel.hal65
-rw-r--r--neuralnetworks/1.0/IPreparedModelCallback.hal53
-rw-r--r--neuralnetworks/1.0/types.hal1267
-rw-r--r--neuralnetworks/1.0/vts/OWNERS11
-rw-r--r--neuralnetworks/1.0/vts/functional/Android.bp36
-rw-r--r--neuralnetworks/1.0/vts/functional/Callbacks.cpp127
-rw-r--r--neuralnetworks/1.0/vts/functional/Callbacks.h319
-rw-r--r--neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp231
-rw-r--r--neuralnetworks/1.0/vts/functional/Models.cpp207
-rw-r--r--neuralnetworks/1.0/vts/functional/Models.h43
-rw-r--r--neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.cpp296
-rw-r--r--neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.h104
-rw-r--r--neuralnetworks/Android.bp5
-rw-r--r--oemlock/1.0/vts/functional/Android.bp18
-rw-r--r--power/1.1/default/Power.cpp177
-rw-r--r--power/1.1/default/Power.h63
-rw-r--r--power/1.1/default/android.hardware.power@1.1-service.rc4
-rw-r--r--power/1.1/default/service.cpp89
-rw-r--r--power/1.1/vts/functional/Android.bp15
-rw-r--r--power/Android.bp1
-rw-r--r--radio/1.0/IRadioResponse.hal30
-rw-r--r--radio/1.0/vts/functional/radio_hidl_hal_icc.cpp3
-rw-r--r--radio/1.0/vts/functional/radio_hidl_hal_ims.cpp5
-rw-r--r--radio/1.0/vts/functional/radio_hidl_hal_misc.cpp23
-rw-r--r--radio/1.0/vts/functional/radio_hidl_hal_stk.cpp9
-rw-r--r--radio/1.0/vts/functional/radio_hidl_hal_voice.cpp1
-rw-r--r--radio/1.1/IRadioResponse.hal1
-rw-r--r--renderscript/1.0/vts/functional/Android.bp18
-rw-r--r--sensors/1.0/default/Android.bp3
-rw-r--r--soundtrigger/2.0/default/OWNERS3
-rw-r--r--tetheroffload/config/1.0/vts/functional/Android.bp17
-rw-r--r--tetheroffload/config/1.0/vts/functional/VtsHalTetheroffloadConfigV1_0TargetTest.cpp61
-rw-r--r--tetheroffload/control/1.0/vts/functional/Android.bp15
-rw-r--r--tetheroffload/control/1.0/vts/functional/VtsHalTetheroffloadControlV1_0TargetTest.cpp76
-rw-r--r--thermal/1.1/Android.bp71
-rw-r--r--thermal/1.1/Android.mk65
-rw-r--r--thermal/1.1/IThermal.hal31
-rw-r--r--thermal/1.1/IThermalCallback.hal33
-rw-r--r--thermal/1.1/vts/functional/Android.bp26
-rw-r--r--thermal/1.1/vts/functional/VtsHalThermalV1_1TargetTest.cpp106
-rw-r--r--thermal/Android.bp2
-rw-r--r--usb/1.1/vts/functional/Android.bp16
-rw-r--r--vibrator/1.1/vts/functional/Android.bp14
-rw-r--r--weaver/1.0/vts/functional/Android.bp18
-rw-r--r--wifi/1.0/README-NAN.md221
-rw-r--r--wifi/1.0/types.hal4
-rw-r--r--wifi/1.1/default/OWNERS2
-rw-r--r--wifi/1.1/default/hidl_return_util.h19
-rw-r--r--wifi/1.1/default/wifi.cpp16
-rw-r--r--wifi/1.1/default/wifi.h5
-rw-r--r--wifi/1.1/default/wifi_legacy_hal.cpp24
-rw-r--r--wifi/1.1/default/wifi_legacy_hal.h8
-rw-r--r--wifi/1.1/vts/functional/Android.bp17
-rw-r--r--wifi/1.1/vts/functional/OWNERS2
-rw-r--r--wifi/Android.bp1
-rw-r--r--wifi/offload/1.0/vts/functional/Android.bp18
-rw-r--r--wifi/supplicant/1.0/vts/functional/Android.bp37
-rw-r--r--wifi/supplicant/1.0/vts/functional/Android.mk44
298 files changed, 17865 insertions, 8021 deletions
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 42399a6664..3788bc6baa 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -56,3 +56,10 @@ $(call add-clean-step, rm -rf $(OUT_DIR)/soong/.intermediates/)
$(call add-clean-step, rm -rf $(OUT_DIR)/soong/.intermediates/hardware/interfaces/)
$(call add-clean-step, rm -rf $(OUT_DIR)/soong/.intermediates/hardware/interfaces/)
$(call add-clean-step, find $(PRODUCT_OUT)/system $(PRODUCT_OUT)/vendor -type f -name "android\.hardware\.configstore*" -print0 | xargs -0 rm -f)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/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/audio/2.0/config/audio_policy_configuration.xsd b/audio/2.0/config/audio_policy_configuration.xsd
index c94da80bfa..eb59152c91 100644
--- a/audio/2.0/config/audio_policy_configuration.xsd
+++ b/audio/2.0/config/audio_policy_configuration.xsd
@@ -365,10 +365,10 @@
</xs:restriction>
</xs:simpleType>
<xs:complexType name="profile">
- <xs:attribute name="name" type="xs:token" use="required"/>
- <xs:attribute name="format" type="audioFormat" use="required"/>
- <xs:attribute name="samplingRates" type="samplingRates" use="required"/>
- <xs:attribute name="channelMasks" type="channelMask" use="required"/>
+ <xs:attribute name="name" type="xs:token" use="optional"/>
+ <xs:attribute name="format" type="audioFormat" use="optional"/>
+ <xs:attribute name="samplingRates" type="samplingRates" use="optional"/>
+ <xs:attribute name="channelMasks" type="channelMask" use="optional"/>
</xs:complexType>
<xs:simpleType name="gainMode">
<xs:restriction base="xs:string">
diff --git a/audio/2.0/default/Android.mk b/audio/2.0/default/Android.mk
index 621853cb0e..8dec48209c 100644
--- a/audio/2.0/default/Android.mk
+++ b/audio/2.0/default/Android.mk
@@ -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
index 0000000000..6fdc97ca29
--- /dev/null
+++ b/audio/2.0/default/OWNERS
@@ -0,0 +1,3 @@
+elaurent@google.com
+krocard@google.com
+mnaganov@google.com
diff --git a/audio/2.0/default/Stream.h b/audio/2.0/default/Stream.h
index 82f05a77b4..e29af53184 100644
--- a/audio/2.0/default/Stream.h
+++ b/audio/2.0/default/Stream.h
@@ -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;
diff --git a/audio/2.0/default/StreamIn.cpp b/audio/2.0/default/StreamIn.cpp
index b81cbb924f..9c933a9201 100644
--- a/audio/2.0/default/StreamIn.cpp
+++ b/audio/2.0/default/StreamIn.cpp
@@ -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();
}
diff --git a/audio/2.0/default/StreamOut.cpp b/audio/2.0/default/StreamOut.cpp
index 290d0b103c..22dcd0c994 100644
--- a/audio/2.0/default/StreamOut.cpp
+++ b/audio/2.0/default/StreamOut.cpp
@@ -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();
}
diff --git a/audio/2.0/default/service.cpp b/audio/2.0/default/service.cpp
index 7f28d7df84..a215108e95 100644
--- a/audio/2.0/default/service.cpp
+++ b/audio/2.0/default/service.cpp
@@ -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;
}
diff --git a/audio/2.0/vts/functional/Android.bp b/audio/2.0/vts/functional/Android.bp
index b289709fda..f3b2ca72cd 100644
--- a/audio/2.0/vts/functional/Android.bp
+++ b/audio/2.0/vts/functional/Android.bp
@@ -16,29 +16,18 @@
cc_test {
name: "VtsHalAudioV2_0TargetTest",
- defaults: ["hidl_defaults"],
- srcs: ["AudioPrimaryHidlHalTest.cpp",
- "ValidateAudioConfiguration.cpp"],
- shared_libs: [
- "libbase",
- "liblog",
- "libhidlbase",
- "libhidltransport",
- "libutils",
- "libcutils",
- "libxml2",
- "android.hardware.audio@2.0",
- "android.hardware.audio.common@2.0",
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: [
+ "AudioPrimaryHidlHalTest.cpp",
+ "ValidateAudioConfiguration.cpp"
],
static_libs: [
- "VtsHalHidlTargetTestBase",
"android.hardware.audio.common.test.utility",
+ "android.hardware.audio@2.0",
+ "android.hardware.audio.common@2.0",
+ "libxml2",
],
- cflags: [
- "-O0",
- "-g",
- "-Wall",
- "-Wextra",
- "-Werror",
+ shared_libs: [
+ "libicuuc",
],
}
diff --git a/audio/2.0/vts/functional/ValidateAudioConfiguration.cpp b/audio/2.0/vts/functional/ValidateAudioConfiguration.cpp
index 01324c87d3..ec3259a1e3 100644
--- a/audio/2.0/vts/functional/ValidateAudioConfiguration.cpp
+++ b/audio/2.0/vts/functional/ValidateAudioConfiguration.cpp
@@ -14,9 +14,21 @@
* limitations under the License.
*/
+#include <string>
+#include <unistd.h>
+
#include "utility/ValidateXml.h"
TEST(CheckConfig, audioPolicyConfigurationValidation) {
- ASSERT_VALID_XML("/vendor/etc/audio_policy_configuration.xml",
- "/data/local/tmp/audio_policy_configuration.xsd");
+ const char* configName = "audio_policy_configuration.xml";
+ const char* possibleConfigLocations[] = {"/odm/etc", "/vendor/etc", "/system/etc"};
+ const char* configSchemaPath = "/data/local/tmp/audio_policy_configuration.xsd";
+
+ for (std::string folder : possibleConfigLocations) {
+ const auto configPath = folder + '/' + configName;
+ if (access(configPath.c_str(), R_OK) == 0) {
+ ASSERT_VALID_XML(configPath.c_str(), configSchemaPath);
+ return; // The framework does not read past the first config file found
+ }
+ }
}
diff --git a/audio/common/2.0/default/Android.bp b/audio/common/2.0/default/Android.bp
index 7fab220fcf..82b38c0877 100644
--- a/audio/common/2.0/default/Android.bp
+++ b/audio/common/2.0/default/Android.bp
@@ -17,6 +17,9 @@ cc_library_shared {
name: "android.hardware.audio.common@2.0-util",
defaults: ["hidl_defaults"],
vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
srcs: [
"EffectMap.cpp",
"HidlUtils.cpp",
diff --git a/audio/common/2.0/default/OWNERS b/audio/common/2.0/default/OWNERS
new file mode 100644
index 0000000000..6fdc97ca29
--- /dev/null
+++ b/audio/common/2.0/default/OWNERS
@@ -0,0 +1,3 @@
+elaurent@google.com
+krocard@google.com
+mnaganov@google.com
diff --git a/audio/common/test/utility/OWNERS b/audio/common/test/utility/OWNERS
new file mode 100644
index 0000000000..6fdc97ca29
--- /dev/null
+++ b/audio/common/test/utility/OWNERS
@@ -0,0 +1,3 @@
+elaurent@google.com
+krocard@google.com
+mnaganov@google.com
diff --git a/audio/effect/2.0/default/OWNERS b/audio/effect/2.0/default/OWNERS
new file mode 100644
index 0000000000..6fdc97ca29
--- /dev/null
+++ b/audio/effect/2.0/default/OWNERS
@@ -0,0 +1,3 @@
+elaurent@google.com
+krocard@google.com
+mnaganov@google.com
diff --git a/audio/effect/2.0/vts/functional/Android.bp b/audio/effect/2.0/vts/functional/Android.bp
index 8a370cd12d..7b421cb7e7 100644
--- a/audio/effect/2.0/vts/functional/Android.bp
+++ b/audio/effect/2.0/vts/functional/Android.bp
@@ -16,24 +16,20 @@
cc_test {
name: "VtsHalAudioEffectV2_0TargetTest",
- defaults: ["hidl_defaults"],
- srcs: ["VtsHalAudioEffectV2_0TargetTest.cpp"],
- shared_libs: [
- "libbase",
- "liblog",
- "libcutils",
- "libhidlbase",
- "libhidltransport",
- "libnativehelper",
- "libutils",
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: [
+ "VtsHalAudioEffectV2_0TargetTest.cpp",
+ "ValidateAudioEffectsConfiguration.cpp"
+ ],
+ static_libs: [
+ "android.hardware.audio.common.test.utility",
"android.hardware.audio.common@2.0",
"android.hardware.audio.effect@2.0",
"android.hidl.allocator@1.0",
"android.hidl.memory@1.0",
+ "libxml2",
],
- static_libs: ["VtsHalHidlTargetTestBase"],
- cflags: [
- "-O0",
- "-g",
+ shared_libs: [
+ "libicuuc",
],
}
diff --git a/audio/effect/2.0/vts/functional/ValidateAudioEffectsConfiguration.cpp b/audio/effect/2.0/vts/functional/ValidateAudioEffectsConfiguration.cpp
new file mode 100644
index 0000000000..fdc1347497
--- /dev/null
+++ b/audio/effect/2.0/vts/functional/ValidateAudioEffectsConfiguration.cpp
@@ -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
index 0000000000..ca6a7dc65b
--- /dev/null
+++ b/audio/effect/2.0/xml/audio_effects_conf_V2_0.xsd
@@ -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>
diff --git a/automotive/Android.bp b/automotive/Android.bp
index be588299e3..8cde817d03 100644
--- a/automotive/Android.bp
+++ b/automotive/Android.bp
@@ -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",
]
diff --git a/automotive/evs/1.0/default/Android.bp b/automotive/evs/1.0/default/Android.bp
new file mode 100644
index 0000000000..2574e860b2
--- /dev/null
+++ b/automotive/evs/1.0/default/Android.bp
@@ -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
index 0ee70711d1..0000000000
--- a/automotive/evs/1.0/default/Android.mk
+++ /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)
diff --git a/automotive/evs/1.0/vts/functional/Android.bp b/automotive/evs/1.0/vts/functional/Android.bp
index e86e9bcdd8..555ff5bc42 100644
--- a/automotive/evs/1.0/vts/functional/Android.bp
+++ b/automotive/evs/1.0/vts/functional/Android.bp
@@ -15,10 +15,10 @@
//
cc_test {
- name: "VtsEvsV1_0Target",
+ name: "VtsHalEvsV1_0Target",
srcs: [
- "VtsEvsV1_0TargetTest.cpp",
+ "VtsHalEvsV1_0TargetTest.cpp",
"FrameHandler.cpp",
"FormatConvert.cpp"
],
@@ -43,4 +43,3 @@ cc_test {
"-g",
],
}
-
diff --git a/automotive/evs/1.0/vts/functional/VtsEvsV1_0TargetTest.cpp b/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
index 2e80afe8fe..57050d7516 100644
--- a/automotive/evs/1.0/vts/functional/VtsEvsV1_0TargetTest.cpp
+++ b/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
@@ -17,8 +17,13 @@
#define LOG_TAG "VtsHalEvsTest"
-// TODO: How should we configure these values to target appropriate hardware?
-const static char kEnumeratorName[] = "EvsEnumeratorHw-Mock";
+// Note: We have't got a great way to indicate which target
+// should be tested, so we'll leave the interface served by the
+// default (mock) EVS driver here for easy reference. All
+// actual EVS drivers should serve on the EvsEnumeratorHw name,
+// however, so the code is checked in that way.
+//const static char kEnumeratorName[] = "EvsEnumeratorHw-Mock";
+const static char kEnumeratorName[] = "EvsEnumeratorHw";
// These values are called out in the EVS design doc (as of Mar 8, 2017)
@@ -474,4 +479,4 @@ TEST_F(EvsHidlTest, CameraToDisplayRoundTrip) {
// Explicitly release the display
pEnumerator->closeDisplay(pDisplay);
-} \ No newline at end of file
+}
diff --git a/automotive/vehicle/2.0/Android.mk b/automotive/vehicle/2.0/Android.mk
index eb05f35eca..5919487471 100644
--- a/automotive/vehicle/2.0/Android.mk
+++ b/automotive/vehicle/2.0/Android.mk
@@ -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
index 0000000000..1690163d2a
--- /dev/null
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -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
index 72e1364fc6..0000000000
--- a/automotive/vehicle/2.0/default/Android.mk
+++ /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)
diff --git a/automotive/vehicle/2.1/default/common/include/vhal_v2_1/Obd2SensorStore.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/Obd2SensorStore.h
index 6c44626d12..191a565c61 100644
--- a/automotive/vehicle/2.1/default/common/include/vhal_v2_1/Obd2SensorStore.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/Obd2SensorStore.h
@@ -14,38 +14,37 @@
* limitations under the License.
*/
-#ifndef android_hardware_automotive_vehicle_V2_1_Obd2SensorStore_H_
-#define android_hardware_automotive_vehicle_V2_1_Obd2SensorStore_H_
+#ifndef android_hardware_automotive_vehicle_V2_0_Obd2SensorStore_H_
+#define android_hardware_automotive_vehicle_V2_0_Obd2SensorStore_H_
#include <vector>
-#include <android/hardware/automotive/vehicle/2.1/types.h>
+#include <android/hardware/automotive/vehicle/2.0/types.h>
namespace android {
namespace hardware {
namespace automotive {
namespace vehicle {
-namespace V2_1 {
+namespace V2_0 {
// This class wraps all the logic required to create an OBD2 frame.
// It allows storing sensor values, setting appropriate bitmasks as needed,
// and returning appropriately laid out storage of sensor values suitable
// for being returned via a VehicleHal implementation.
class Obd2SensorStore {
-public:
+ public:
// Creates a sensor storage with a given number of vendor-specific sensors.
- Obd2SensorStore(size_t numVendorIntegerSensors,
- size_t numVendorFloatSensors);
+ Obd2SensorStore(size_t numVendorIntegerSensors, size_t numVendorFloatSensors);
// Stores an integer-valued sensor.
- V2_0::StatusCode setIntegerSensor(Obd2IntegerSensorIndex index, int32_t value);
+ StatusCode setIntegerSensor(DiagnosticIntegerSensorIndex index, int32_t value);
// Stores an integer-valued sensor.
- V2_0::StatusCode setIntegerSensor(size_t index, int32_t value);
+ StatusCode setIntegerSensor(size_t index, int32_t value);
// Stores a float-valued sensor.
- V2_0::StatusCode setFloatSensor(Obd2FloatSensorIndex index, float value);
+ StatusCode setFloatSensor(DiagnosticFloatSensorIndex index, float value);
// Stores a float-valued sensor.
- V2_0::StatusCode setFloatSensor(size_t index, float value);
+ StatusCode setFloatSensor(size_t index, float value);
// Returns a vector that contains all integer sensors stored.
const std::vector<int32_t>& getIntegerSensors() const;
@@ -55,11 +54,11 @@ public:
const std::vector<uint8_t>& getSensorsBitmask() const;
// Given a stringValue, fill in a VehiclePropValue
- void fillPropValue(const std::string& dtc, V2_0::VehiclePropValue *propValue) const;
+ void fillPropValue(const std::string& dtc, VehiclePropValue* propValue) const;
-private:
+ private:
class BitmaskInVector {
- public:
+ public:
BitmaskInVector(size_t numBits = 0);
void resize(size_t numBits);
bool get(size_t index) const;
@@ -67,7 +66,7 @@ private:
const std::vector<uint8_t>& getBitmask() const;
- private:
+ private:
std::vector<uint8_t> mStorage;
};
@@ -76,7 +75,7 @@ private:
BitmaskInVector mSensorsBitmask;
};
-} // namespace V2_1
+} // namespace V2_0
} // namespace vehicle
} // namespace automotive
} // namespace hardware
diff --git a/automotive/vehicle/2.1/default/common/src/Obd2SensorStore.cpp b/automotive/vehicle/2.0/default/common/src/Obd2SensorStore.cpp
index f4c63a9544..65174f7a00 100644
--- a/automotive/vehicle/2.1/default/common/src/Obd2SensorStore.cpp
+++ b/automotive/vehicle/2.0/default/common/src/Obd2SensorStore.cpp
@@ -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
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index fb63e3645e..08d3d79446 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -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
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
index fe34a3f610..6bc0522403 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
@@ -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
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
index c25e0838c5..99d7edbc78 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
@@ -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
index 0000000000..ec352000c6
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/Android.bp
@@ -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"]
+}
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index f1fb6bf2b9..7c08b4a036 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -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
index 447c08e336..0000000000
--- a/automotive/vehicle/2.1/Android.bp
+++ /dev/null
@@ -1,68 +0,0 @@
-// This file is autogenerated by hidl-gen. Do not edit manually.
-
-filegroup {
- name: "android.hardware.automotive.vehicle@2.1_hal",
- srcs: [
- "types.hal",
- "IVehicle.hal",
- ],
-}
-
-genrule {
- name: "android.hardware.automotive.vehicle@2.1_genc++",
- tools: ["hidl-gen"],
- cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.automotive.vehicle@2.1",
- srcs: [
- ":android.hardware.automotive.vehicle@2.1_hal",
- ],
- out: [
- "android/hardware/automotive/vehicle/2.1/types.cpp",
- "android/hardware/automotive/vehicle/2.1/VehicleAll.cpp",
- ],
-}
-
-genrule {
- name: "android.hardware.automotive.vehicle@2.1_genc++_headers",
- tools: ["hidl-gen"],
- cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.automotive.vehicle@2.1",
- srcs: [
- ":android.hardware.automotive.vehicle@2.1_hal",
- ],
- out: [
- "android/hardware/automotive/vehicle/2.1/types.h",
- "android/hardware/automotive/vehicle/2.1/hwtypes.h",
- "android/hardware/automotive/vehicle/2.1/IVehicle.h",
- "android/hardware/automotive/vehicle/2.1/IHwVehicle.h",
- "android/hardware/automotive/vehicle/2.1/BnHwVehicle.h",
- "android/hardware/automotive/vehicle/2.1/BpHwVehicle.h",
- "android/hardware/automotive/vehicle/2.1/BsVehicle.h",
- ],
-}
-
-cc_library {
- name: "android.hardware.automotive.vehicle@2.1",
- defaults: ["hidl-module-defaults"],
- generated_sources: ["android.hardware.automotive.vehicle@2.1_genc++"],
- generated_headers: ["android.hardware.automotive.vehicle@2.1_genc++_headers"],
- export_generated_headers: ["android.hardware.automotive.vehicle@2.1_genc++_headers"],
- vendor_available: true,
- vndk: {
- enabled: true,
- },
- shared_libs: [
- "libhidlbase",
- "libhidltransport",
- "libhwbinder",
- "liblog",
- "libutils",
- "libcutils",
- "android.hardware.automotive.vehicle@2.0",
- ],
- export_shared_lib_headers: [
- "libhidlbase",
- "libhidltransport",
- "libhwbinder",
- "libutils",
- "android.hardware.automotive.vehicle@2.0",
- ],
-}
diff --git a/automotive/vehicle/2.1/Android.mk b/automotive/vehicle/2.1/Android.mk
deleted file mode 100644
index 8e1c0dd321..0000000000
--- a/automotive/vehicle/2.1/Android.mk
+++ /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
index a22d1e685c..0000000000
--- a/automotive/vehicle/2.1/IVehicle.hal
+++ /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
index f19263c7d1..0000000000
--- a/automotive/vehicle/2.1/default/Android.mk
+++ /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
index 8929d25668..0000000000
--- a/automotive/vehicle/2.1/default/android.hardware.automotive.vehicle@2.1-service.rc
+++ /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
index 0f10086d70..0000000000
--- a/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultConfig.h
+++ /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
index 46e062b86b..0000000000
--- a/automotive/vehicle/2.1/default/impl/vhal_v2_1/EmulatedVehicleHal.cpp
+++ /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
index 7cc3b79679..0000000000
--- a/automotive/vehicle/2.1/default/impl/vhal_v2_1/EmulatedVehicleHal.h
+++ /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
index bae64fde9f..0000000000
--- a/automotive/vehicle/2.1/default/service.cpp
+++ /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
index a01c0f498c..0000000000
--- a/automotive/vehicle/2.1/default/tests/Obd2SensorStore_test.cpp
+++ /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
index 7be611c55b..0000000000
--- a/automotive/vehicle/2.1/types.hal
+++ /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,
-};
diff --git a/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp b/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp
index c6774ca222..f68795955a 100644
--- a/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp
+++ b/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp
@@ -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;
diff --git a/biometrics/fingerprint/2.1/default/BiometricsFingerprint.h b/biometrics/fingerprint/2.1/default/BiometricsFingerprint.h
index 5923c849c8..6d64e3d38d 100644
--- a/biometrics/fingerprint/2.1/default/BiometricsFingerprint.h
+++ b/biometrics/fingerprint/2.1/default/BiometricsFingerprint.h
@@ -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;
};
diff --git a/bluetooth/1.0/default/async_fd_watcher.cc b/bluetooth/1.0/default/async_fd_watcher.cc
index d8714f5b5b..7c74643871 100644
--- a/bluetooth/1.0/default/async_fd_watcher.cc
+++ b/bluetooth/1.0/default/async_fd_watcher.cc
@@ -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"
diff --git a/bluetooth/1.0/default/bluetooth_address.cc b/bluetooth/1.0/default/bluetooth_address.cc
index 34df752b3c..93a5469958 100644
--- a/bluetooth/1.0/default/bluetooth_address.cc
+++ b/bluetooth/1.0/default/bluetooth_address.cc
@@ -19,6 +19,7 @@
#include <cutils/properties.h>
#include <errno.h>
#include <fcntl.h>
+#include <unistd.h>
#include <utils/Log.h>
namespace android {
diff --git a/bluetooth/1.0/default/h4_protocol.cc b/bluetooth/1.0/default/h4_protocol.cc
index 5a89557e39..163cc333c4 100644
--- a/bluetooth/1.0/default/h4_protocol.cc
+++ b/bluetooth/1.0/default/h4_protocol.cc
@@ -22,6 +22,7 @@
#include <fcntl.h>
#include <log/log.h>
#include <sys/uio.h>
+#include <unistd.h>
namespace android {
namespace hardware {
diff --git a/bluetooth/1.0/default/hci_packetizer.cc b/bluetooth/1.0/default/hci_packetizer.cc
index 2da1254531..fde08ac1cb 100644
--- a/bluetooth/1.0/default/hci_packetizer.cc
+++ b/bluetooth/1.0/default/hci_packetizer.cc
@@ -21,6 +21,7 @@
#include <dlfcn.h>
#include <errno.h>
#include <fcntl.h>
+#include <unistd.h>
#include <utils/Log.h>
namespace {
diff --git a/bluetooth/1.0/default/hci_protocol.cc b/bluetooth/1.0/default/hci_protocol.cc
index 5d6f1d1396..bf94dfe884 100644
--- a/bluetooth/1.0/default/hci_protocol.cc
+++ b/bluetooth/1.0/default/hci_protocol.cc
@@ -20,6 +20,7 @@
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
+#include <unistd.h>
#include <log/log.h>
namespace android {
diff --git a/broadcastradio/1.0/default/OWNERS b/broadcastradio/1.0/default/OWNERS
new file mode 100644
index 0000000000..b159083944
--- /dev/null
+++ b/broadcastradio/1.0/default/OWNERS
@@ -0,0 +1,4 @@
+elaurent@google.com
+krocard@google.com
+mnaganov@google.com
+twasilczyk@google.com
diff --git a/broadcastradio/1.0/types.hal b/broadcastradio/1.0/types.hal
index 045231d495..8c3ec119d3 100644
--- a/broadcastradio/1.0/types.hal
+++ b/broadcastradio/1.0/types.hal
@@ -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. */
};
diff --git a/broadcastradio/1.1/IBroadcastRadio.hal b/broadcastradio/1.1/IBroadcastRadio.hal
index dd37d4942c..dadba2accb 100644
--- a/broadcastradio/1.1/IBroadcastRadio.hal
+++ b/broadcastradio/1.1/IBroadcastRadio.hal
@@ -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);
};
diff --git a/broadcastradio/1.1/IBroadcastRadioFactory.hal b/broadcastradio/1.1/IBroadcastRadioFactory.hal
index fce1cc0c72..edf78ff09a 100644
--- a/broadcastradio/1.1/IBroadcastRadioFactory.hal
+++ b/broadcastradio/1.1/IBroadcastRadioFactory.hal
@@ -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 {
diff --git a/broadcastradio/1.1/ITuner.hal b/broadcastradio/1.1/ITuner.hal
index 751162966f..b20c5f4fba 100644
--- a/broadcastradio/1.1/ITuner.hal
+++ b/broadcastradio/1.1/ITuner.hal
@@ -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);
};
diff --git a/broadcastradio/1.1/ITunerCallback.hal b/broadcastradio/1.1/ITunerCallback.hal
index 158e2170b1..8bf5b7f120 100644
--- a/broadcastradio/1.1/ITunerCallback.hal
+++ b/broadcastradio/1.1/ITunerCallback.hal
@@ -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
index e867cfa362..0000000000
--- a/broadcastradio/1.1/WARNING
+++ /dev/null
@@ -1 +0,0 @@
-This is experimental interface, do not use it yet.
diff --git a/broadcastradio/1.1/default/Android.bp b/broadcastradio/1.1/default/Android.bp
index 759eb09118..6d26b11bd8 100644
--- a/broadcastradio/1.1/default/Android.bp
+++ b/broadcastradio/1.1/default/Android.bp
@@ -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",
],
}
diff --git a/broadcastradio/1.1/default/BroadcastRadio.cpp b/broadcastradio/1.1/default/BroadcastRadio.cpp
index 68c9b93870..1bcfd824f7 100644
--- a/broadcastradio/1.1/default/BroadcastRadio.cpp
+++ b/broadcastradio/1.1/default/BroadcastRadio.cpp
@@ -13,14 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#define LOG_TAG "BroadcastRadio"
-//#define LOG_NDEBUG 0
+#define LOG_TAG "BroadcastRadioDefault.module"
+#define LOG_NDEBUG 0
+
+#include "BroadcastRadio.h"
#include <log/log.h>
-#include "BroadcastRadio.h"
-#include "Tuner.h"
-#include "Utils.h"
+#include "resources.h"
namespace android {
namespace hardware {
@@ -28,117 +28,163 @@ namespace broadcastradio {
namespace V1_1 {
namespace implementation {
-using ::android::sp;
+using V1_0::Band;
+using V1_0::BandConfig;
+using V1_0::Class;
+using V1_0::Deemphasis;
+using V1_0::Rds;
+
+using std::lock_guard;
+using std::map;
+using std::mutex;
+using std::vector;
+
+// clang-format off
+static const map<Class, ModuleConfig> gModuleConfigs{
+ {Class::AM_FM, ModuleConfig({
+ "Digital radio mock",
+ { // amFmBands
+ AmFmBandConfig({
+ Band::AM,
+ 153, // lowerLimit
+ 26100, // upperLimit
+ {5, 9, 10}, // spacings
+ }),
+ AmFmBandConfig({
+ Band::FM,
+ 65800, // lowerLimit
+ 108000, // upperLimit
+ {10, 100, 200}, // spacings
+ }),
+ AmFmBandConfig({
+ Band::AM_HD,
+ 153, // lowerLimit
+ 26100, // upperLimit
+ {5, 9, 10}, // spacings
+ }),
+ AmFmBandConfig({
+ Band::FM_HD,
+ 87700, // lowerLimit
+ 107900, // upperLimit
+ {200}, // spacings
+ }),
+ },
+ })},
+
+ {Class::SAT, ModuleConfig({
+ "Satellite radio mock",
+ {}, // amFmBands
+ })},
+};
+// clang-format on
BroadcastRadio::BroadcastRadio(Class classId)
- : mStatus(Result::NOT_INITIALIZED), mClassId(classId), mHwDevice(NULL)
-{
+ : mClassId(classId), mConfig(gModuleConfigs.at(classId)) {}
+
+bool BroadcastRadio::isSupported(Class classId) {
+ return gModuleConfigs.find(classId) != gModuleConfigs.end();
}
-BroadcastRadio::~BroadcastRadio()
-{
- if (mHwDevice != NULL) {
- radio_hw_device_close(mHwDevice);
- }
+Return<void> BroadcastRadio::getProperties(getProperties_cb _hidl_cb) {
+ ALOGV("%s", __func__);
+ return getProperties_1_1(
+ [&](const Properties& properties) { _hidl_cb(Result::OK, properties.base); });
}
-void BroadcastRadio::onFirstRef()
-{
- const hw_module_t *mod;
- int rc;
- ALOGI("%s mClassId %d", __FUNCTION__, mClassId);
-
- 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
diff --git a/broadcastradio/1.1/default/BroadcastRadio.h b/broadcastradio/1.1/default/BroadcastRadio.h
index 7de31a07cb..a96a2ab933 100644
--- a/broadcastradio/1.1/default/BroadcastRadio.h
+++ b/broadcastradio/1.1/default/BroadcastRadio.h
@@ -16,9 +16,10 @@
#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_BROADCASTRADIO_H
#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_BROADCASTRADIO_H
+#include "Tuner.h"
+
#include <android/hardware/broadcastradio/1.1/IBroadcastRadio.h>
#include <android/hardware/broadcastradio/1.1/types.h>
-#include <hardware/radio.h>
namespace android {
namespace hardware {
@@ -26,42 +27,49 @@ namespace broadcastradio {
namespace V1_1 {
namespace implementation {
-using V1_0::Class;
-using V1_0::BandConfig;
-using V1_0::Properties;
+struct AmFmBandConfig {
+ V1_0::Band type;
+ uint32_t lowerLimit; // kHz
+ uint32_t upperLimit; // kHz
+ std::vector<uint32_t> spacings; // kHz
+};
+
+struct ModuleConfig {
+ std::string productName;
+ std::vector<AmFmBandConfig> amFmBands;
+};
struct BroadcastRadio : public V1_1::IBroadcastRadio {
+ /**
+ * Constructs new broadcast radio module.
+ *
+ * Before calling a constructor with a given classId, it must be checked with isSupported
+ * method first. Otherwise it results in undefined behaviour.
+ *
+ * @param classId type of a radio.
+ */
+ BroadcastRadio(V1_0::Class classId);
- BroadcastRadio(Class classId);
+ /**
+ * Checks, if a given radio type is supported.
+ *
+ * @param classId type of a radio.
+ */
+ static bool isSupported(V1_0::Class classId);
- // Methods from ::android::hardware::broadcastradio::V1_1::IBroadcastRadio follow.
+ // V1_1::IBroadcastRadio methods
Return<void> getProperties(getProperties_cb _hidl_cb) override;
Return<void> getProperties_1_1(getProperties_1_1_cb _hidl_cb) override;
- Return<void> openTuner(const BandConfig& config, bool audio,
- const sp<V1_0::ITunerCallback>& callback, openTuner_cb _hidl_cb) override;
-
- // 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
diff --git a/broadcastradio/1.1/default/BroadcastRadioFactory.cpp b/broadcastradio/1.1/default/BroadcastRadioFactory.cpp
index c8b6c39f54..f57bc79feb 100644
--- a/broadcastradio/1.1/default/BroadcastRadioFactory.cpp
+++ b/broadcastradio/1.1/default/BroadcastRadioFactory.cpp
@@ -13,29 +13,51 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#define LOG_TAG "BroadcastRadioDefault.factory"
+#define LOG_NDEBUG 0
+
#include "BroadcastRadioFactory.h"
+
#include "BroadcastRadio.h"
+#include <log/log.h>
+
namespace android {
namespace hardware {
namespace broadcastradio {
namespace V1_1 {
namespace implementation {
-// Methods from ::android::hardware::broadcastradio::V1_0::IBroadcastRadioFactory follow.
-Return<void> BroadcastRadioFactory::connectModule(Class classId, connectModule_cb _hidl_cb) {
- sp<BroadcastRadio> impl = new BroadcastRadio(classId);
- Result retval = Result::NOT_INITIALIZED;
- if (impl != 0) {
- retval = impl->initCheck();
+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
diff --git a/broadcastradio/1.1/default/BroadcastRadioFactory.h b/broadcastradio/1.1/default/BroadcastRadioFactory.h
index 8eb851485a..8b67ac3637 100644
--- a/broadcastradio/1.1/default/BroadcastRadioFactory.h
+++ b/broadcastradio/1.1/default/BroadcastRadioFactory.h
@@ -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
index 0000000000..0c27b71865
--- /dev/null
+++ b/broadcastradio/1.1/default/OWNERS
@@ -0,0 +1,4 @@
+# Automotive team
+egranata@google.com
+keunyoung@google.com
+twasilczyk@google.com
diff --git a/broadcastradio/1.1/default/Tuner.cpp b/broadcastradio/1.1/default/Tuner.cpp
index ae5848cec7..9a34cb128c 100644
--- a/broadcastradio/1.1/default/Tuner.cpp
+++ b/broadcastradio/1.1/default/Tuner.cpp
@@ -14,15 +14,14 @@
* limitations under the License.
*/
-#define LOG_TAG "Tuner"
-//#define LOG_NDEBUG 0
-
-#include <log/log.h>
+#define LOG_TAG "BroadcastRadioDefault.tuner"
+#define LOG_NDEBUG 0
#include "BroadcastRadio.h"
#include "Tuner.h"
-#include "Utils.h"
-#include <system/RadioMetadataWrapper.h>
+
+#include <broadcastradio-utils/Utils.h>
+#include <log/log.h>
namespace android {
namespace hardware {
@@ -30,199 +29,351 @@ namespace broadcastradio {
namespace V1_1 {
namespace implementation {
-void Tuner::onCallback(radio_hal_event_t *halEvent)
-{
- BandConfig config;
- ProgramInfo info;
- hidl_vec<MetaData> metadata;
-
- 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
diff --git a/broadcastradio/1.1/default/Tuner.h b/broadcastradio/1.1/default/Tuner.h
index 57eafd3d7c..07d31898a7 100644
--- a/broadcastradio/1.1/default/Tuner.h
+++ b/broadcastradio/1.1/default/Tuner.h
@@ -16,8 +16,11 @@
#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_TUNER_H
#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_TUNER_H
+#include "VirtualRadio.h"
+
#include <android/hardware/broadcastradio/1.1/ITuner.h>
#include <android/hardware/broadcastradio/1.1/ITunerCallback.h>
+#include <broadcastradio-utils/WorkerThread.h>
namespace android {
namespace hardware {
@@ -25,43 +28,48 @@ namespace broadcastradio {
namespace V1_1 {
namespace implementation {
-using V1_0::Direction;
-
-struct BroadcastRadio;
-
struct Tuner : public ITuner {
+ Tuner(V1_0::Class classId, const sp<V1_0::ITunerCallback>& callback);
- Tuner(const sp<V1_0::ITunerCallback>& callback, const wp<BroadcastRadio>& mParentDevice);
-
- // 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
index e21344ede2..0000000000
--- a/broadcastradio/1.1/default/Utils.cpp
+++ /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
index 22902ba513..0000000000
--- a/broadcastradio/1.1/default/Utils.h
+++ /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
index 0000000000..7977391cdd
--- /dev/null
+++ b/broadcastradio/1.1/default/VirtualProgram.cpp
@@ -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
index 0000000000..a14830d77a
--- /dev/null
+++ b/broadcastradio/1.1/default/VirtualProgram.h
@@ -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
index 0000000000..36d47a92e7
--- /dev/null
+++ b/broadcastradio/1.1/default/VirtualRadio.cpp
@@ -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
index 0000000000..3c7ae5c193
--- /dev/null
+++ b/broadcastradio/1.1/default/VirtualRadio.h
@@ -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
index 0000000000..7c57135fc2
--- /dev/null
+++ b/broadcastradio/1.1/default/android.hardware.broadcastradio@1.1-service.rc
@@ -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
index 0000000000..b7e709f955
--- /dev/null
+++ b/broadcastradio/1.1/default/resources.h
@@ -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
index 0000000000..f8af0b78cb
--- /dev/null
+++ b/broadcastradio/1.1/default/service.cpp
@@ -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
index 0000000000..fa1fd94409
--- /dev/null
+++ b/broadcastradio/1.1/tests/Android.bp
@@ -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
index 0000000000..aa5ce82e16
--- /dev/null
+++ b/broadcastradio/1.1/tests/OWNERS
@@ -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
index 0000000000..ed36de3e85
--- /dev/null
+++ b/broadcastradio/1.1/tests/WorkerThread_test.cpp
@@ -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
diff --git a/broadcastradio/1.1/types.hal b/broadcastradio/1.1/types.hal
index 5577ea02da..8b8fc6fdde 100644
--- a/broadcastradio/1.1/types.hal
+++ b/broadcastradio/1.1/types.hal
@@ -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;
};
diff --git a/power/1.1/default/Android.bp b/broadcastradio/1.1/utils/Android.bp
index 0b3598bbf5..e80d133dca 100644
--- a/power/1.1/default/Android.bp
+++ b/broadcastradio/1.1/utils/Android.bp
@@ -1,4 +1,5 @@
-// Copyright (C) 2016 The Android Open Source Project
+//
+// Copyright (C) 2017 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -11,23 +12,23 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
+//
-cc_binary {
- proprietary: true,
- defaults: ["hidl_defaults"],
+cc_library_static {
+ name: "android.hardware.broadcastradio@1.1-utils-lib",
+ vendor_available: true,
relative_install_path: "hw",
- name: "android.hardware.power@1.1-service",
- init_rc: ["android.hardware.power@1.1-service.rc"],
- srcs: ["service.cpp" , "Power.cpp"],
-
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ ],
+ srcs: [
+ "Utils.cpp",
+ "WorkerThread.cpp",
+ ],
+ export_include_dirs: ["include"],
shared_libs: [
- "liblog",
- "libdl",
- "libutils",
- "libhardware",
- "libhidlbase",
- "libhidltransport",
- "android.hardware.power@1.0",
- "android.hardware.power@1.1",
+ "android.hardware.broadcastradio@1.1",
],
}
diff --git a/broadcastradio/1.1/utils/OWNERS b/broadcastradio/1.1/utils/OWNERS
new file mode 100644
index 0000000000..0c27b71865
--- /dev/null
+++ b/broadcastradio/1.1/utils/OWNERS
@@ -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
index 0000000000..4dd6b139c4
--- /dev/null
+++ b/broadcastradio/1.1/utils/Utils.cpp
@@ -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
index 0000000000..bfcbb390e8
--- /dev/null
+++ b/broadcastradio/1.1/utils/WorkerThread.cpp
@@ -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
index 0000000000..24c60ee460
--- /dev/null
+++ b/broadcastradio/1.1/utils/include/broadcastradio-utils/Utils.h
@@ -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
index 0000000000..635876fbcb
--- /dev/null
+++ b/broadcastradio/1.1/utils/include/broadcastradio-utils/WorkerThread.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_WORKERTHREAD_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_WORKERTHREAD_H
+
+#include <chrono>
+#include <queue>
+#include <thread>
+
+namespace android {
+
+class WorkerThread {
+ public:
+ WorkerThread();
+ virtual ~WorkerThread();
+
+ void schedule(std::function<void()> task, std::chrono::milliseconds delay);
+ void cancelAll();
+
+ private:
+ struct Task {
+ std::chrono::time_point<std::chrono::steady_clock> when;
+ std::function<void()> what;
+ };
+ friend bool operator<(const Task& lhs, const Task& rhs);
+
+ std::atomic<bool> mIsTerminating;
+ std::mutex mMut;
+ std::condition_variable mCond;
+ std::thread mThread;
+ std::priority_queue<Task> mTasks;
+
+ void threadLoop();
+};
+
+} // namespace android
+
+#endif // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_WORKERTHREAD_H
diff --git a/broadcastradio/1.1/vts/OWNERS b/broadcastradio/1.1/vts/OWNERS
new file mode 100644
index 0000000000..aa5ce82e16
--- /dev/null
+++ b/broadcastradio/1.1/vts/OWNERS
@@ -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/vts/functional/Android.bp b/broadcastradio/1.1/vts/functional/Android.bp
index a4c0849cf2..4b93cbcf1f 100644
--- a/broadcastradio/1.1/vts/functional/Android.bp
+++ b/broadcastradio/1.1/vts/functional/Android.bp
@@ -16,22 +16,13 @@
cc_test {
name: "VtsHalBroadcastradioV1_1TargetTest",
- defaults: ["hidl_defaults"],
+ defaults: ["VtsHalTargetTestDefaults"],
srcs: ["VtsHalBroadcastradioV1_1TargetTest.cpp"],
- shared_libs: [
- "libbase",
- "liblog",
- "libcutils",
- "libhidlbase",
- "libhidltransport",
- "libnativehelper",
- "libutils",
+ static_libs: [
"android.hardware.broadcastradio@1.0",
"android.hardware.broadcastradio@1.1",
- ],
- static_libs: ["VtsHalHidlTargetTestBase"],
- cflags: [
- "-O0",
- "-g",
+ "android.hardware.broadcastradio@1.1-utils-lib",
+ "android.hardware.broadcastradio@1.1-vts-utils-lib",
+ "libgmock",
],
}
diff --git a/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp b/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp
index aa5ab548f6..a46378ee6a 100644
--- a/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp
+++ b/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp
@@ -14,463 +14,527 @@
* 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
index 0000000000..0c7e2a4433
--- /dev/null
+++ b/broadcastradio/1.1/vts/utils/Android.bp
@@ -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
index 0000000000..d8c47162ed
--- /dev/null
+++ b/broadcastradio/1.1/vts/utils/call-barrier.cpp
@@ -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
index 0000000000..462396a55b
--- /dev/null
+++ b/broadcastradio/1.1/vts/utils/include/broadcastradio-vts-utils/call-barrier.h
@@ -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
index 0000000000..b0ce08806d
--- /dev/null
+++ b/broadcastradio/1.1/vts/utils/include/broadcastradio-vts-utils/mock-timeout.h
@@ -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
diff --git a/broadcastradio/Android.bp b/broadcastradio/Android.bp
index 7a315faab3..8c65bf6013 100644
--- a/broadcastradio/Android.bp
+++ b/broadcastradio/Android.bp
@@ -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",
]
diff --git a/camera/Android.bp b/camera/Android.bp
index 3869766db5..0240751c5a 100644
--- a/camera/Android.bp
+++ b/camera/Android.bp
@@ -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",
diff --git a/camera/common/1.0/default/CameraParameters.cpp b/camera/common/1.0/default/CameraParameters.cpp
index d224483c75..e707b0855a 100644
--- a/camera/common/1.0/default/CameraParameters.cpp
+++ b/camera/common/1.0/default/CameraParameters.cpp
@@ -20,6 +20,7 @@
#include <string.h>
#include <stdlib.h>
+#include <unistd.h>
#include "CameraParameters.h"
#include <system/graphics.h>
diff --git a/camera/device/1.0/default/Android.bp b/camera/device/1.0/default/Android.bp
index 1a349d6a3e..e0b31f0a48 100644
--- a/camera/device/1.0/default/Android.bp
+++ b/camera/device/1.0/default/Android.bp
@@ -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"
],
diff --git a/camera/device/1.0/default/OWNERS b/camera/device/1.0/default/OWNERS
new file mode 100644
index 0000000000..18acfee145
--- /dev/null
+++ b/camera/device/1.0/default/OWNERS
@@ -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.2/default/CameraDevice.cpp b/camera/device/3.2/default/CameraDevice.cpp
index 637a1e6616..295ee32865 100644
--- a/camera/device/3.2/default/CameraDevice.cpp
+++ b/camera/device/3.2/default/CameraDevice.cpp
@@ -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
diff --git a/camera/device/3.2/default/CameraDeviceSession.cpp b/camera/device/3.2/default/CameraDeviceSession.cpp
index fcd134f45e..d6a04bc56b 100644
--- a/camera/device/3.2/default/CameraDeviceSession.cpp
+++ b/camera/device/3.2/default/CameraDeviceSession.cpp
@@ -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;
diff --git a/camera/device/3.2/default/CameraDeviceSession.h b/camera/device/3.2/default/CameraDeviceSession.h
index 2fe189fde1..69e2e2c802 100644
--- a/camera/device/3.2/default/CameraDeviceSession.h
+++ b/camera/device/3.2/default/CameraDeviceSession.h
@@ -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
diff --git a/camera/device/3.2/default/CameraDevice_3_2.h b/camera/device/3.2/default/CameraDevice_3_2.h
index 4e8606757c..9534707bd0 100644
--- a/camera/device/3.2/default/CameraDevice_3_2.h
+++ b/camera/device/3.2/default/CameraDevice_3_2.h
@@ -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
index 0000000000..18acfee145
--- /dev/null
+++ b/camera/device/3.2/default/OWNERS
@@ -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
index 0000000000..2a1999165c
--- /dev/null
+++ b/camera/device/3.3/Android.bp
@@ -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
index 0000000000..764392f1cf
--- /dev/null
+++ b/camera/device/3.3/ICameraDeviceSession.hal
@@ -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
index 0000000000..b1e9b46d8f
--- /dev/null
+++ b/camera/device/3.3/default/Android.bp
@@ -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
index 0000000000..ce5e1de239
--- /dev/null
+++ b/camera/device/3.3/default/CameraDevice.cpp
@@ -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
index 0000000000..f877895ebb
--- /dev/null
+++ b/camera/device/3.3/default/CameraDeviceSession.cpp
@@ -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
index 0000000000..dd52b35b8e
--- /dev/null
+++ b/camera/device/3.3/default/CameraDeviceSession.h
@@ -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
index 0000000000..18b3fe8e81
--- /dev/null
+++ b/camera/device/3.3/default/CameraDevice_3_3.h
@@ -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
index 0000000000..18acfee145
--- /dev/null
+++ b/camera/device/3.3/default/OWNERS
@@ -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
index 0000000000..dae190b03c
--- /dev/null
+++ b/camera/device/3.3/default/convert.cpp
@@ -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
index 0000000000..23bb79796c
--- /dev/null
+++ b/camera/device/3.3/default/include/convert.h
@@ -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
index 0000000000..b4ad702292
--- /dev/null
+++ b/camera/device/3.3/types.hal
@@ -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;
+};
diff --git a/camera/device/README.md b/camera/device/README.md
index 6e5703a578..9f607816d8 100644
--- a/camera/device/README.md
+++ b/camera/device/README.md
@@ -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.
diff --git a/camera/provider/2.4/default/Android.bp b/camera/provider/2.4/default/Android.bp
index f2a2d2e71e..c0b35912f7 100644
--- a/camera/provider/2.4/default/Android.bp
+++ b/camera/provider/2.4/default/Android.bp
@@ -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",
],
diff --git a/camera/provider/2.4/default/CameraProvider.cpp b/camera/provider/2.4/default/CameraProvider.cpp
index 19f7bdd7b2..d50168a20b 100644
--- a/camera/provider/2.4/default/CameraProvider.cpp
+++ b/camera/provider/2.4/default/CameraProvider.cpp
@@ -15,11 +15,13 @@
*/
#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();
}
diff --git a/camera/provider/2.4/default/CameraProvider.h b/camera/provider/2.4/default/CameraProvider.h
index 75971fa3a0..4980711bcf 100644
--- a/camera/provider/2.4/default/CameraProvider.h
+++ b/camera/provider/2.4/default/CameraProvider.h
@@ -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
index 0000000000..18acfee145
--- /dev/null
+++ b/camera/provider/2.4/default/OWNERS
@@ -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
index 0000000000..003fe71fa8
--- /dev/null
+++ b/camera/provider/2.4/vts/OWNERS
@@ -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
diff --git a/camera/provider/2.4/vts/functional/Android.bp b/camera/provider/2.4/vts/functional/Android.bp
index 439fe3dd67..81d3de1566 100644
--- a/camera/provider/2.4/vts/functional/Android.bp
+++ b/camera/provider/2.4/vts/functional/Android.bp
@@ -16,30 +16,28 @@
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",
],
}
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 6f04efc598..e4cf9af273 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -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_t* staticMeta;
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_t* staticMeta;
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_t* staticMeta;
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 (auto& inputIter : 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_t* staticMeta;
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_t* staticMeta;
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_t* staticMeta;
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
index 0000000000..6d94793b7e
--- /dev/null
+++ b/cas/1.0/Android.bp
@@ -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
index 0000000000..3cae6bf416
--- /dev/null
+++ b/cas/1.0/CasHal.mk
@@ -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
index 0000000000..08a92da19e
--- /dev/null
+++ b/cas/1.0/ICas.hal
@@ -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
index 0000000000..8ae6014d1c
--- /dev/null
+++ b/cas/1.0/ICasListener.hal
@@ -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
index 0000000000..a126084b33
--- /dev/null
+++ b/cas/1.0/IDescramblerBase.hal
@@ -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
index 0000000000..cfeafad2a1
--- /dev/null
+++ b/cas/1.0/IMediaCasService.hal
@@ -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
index 0000000000..6da5cc442c
--- /dev/null
+++ b/cas/1.0/default/Android.bp
@@ -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
index 0000000000..9d1f4a3268
--- /dev/null
+++ b/cas/1.0/default/CasImpl.cpp
@@ -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
index 0000000000..841d64e038
--- /dev/null
+++ b/cas/1.0/default/CasImpl.h
@@ -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
index 0000000000..3d90809cd0
--- /dev/null
+++ b/cas/1.0/default/DescramblerImpl.cpp
@@ -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
index 0000000000..d3b146ecc7
--- /dev/null
+++ b/cas/1.0/default/DescramblerImpl.h
@@ -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
index 0000000000..18c2186dcb
--- /dev/null
+++ b/cas/1.0/default/FactoryLoader.h
@@ -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
index 0000000000..ca4322461e
--- /dev/null
+++ b/cas/1.0/default/MediaCasService.cpp
@@ -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
index 0000000000..77ddac6032
--- /dev/null
+++ b/cas/1.0/default/MediaCasService.h
@@ -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
index 0000000000..9c7f38554a
--- /dev/null
+++ b/cas/1.0/default/SharedLibrary.cpp
@@ -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
index 0000000000..18130a5441
--- /dev/null
+++ b/cas/1.0/default/SharedLibrary.h
@@ -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
index 0000000000..cd0efdbc2a
--- /dev/null
+++ b/cas/1.0/default/TypeConvert.cpp
@@ -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
index 0000000000..7c3ddeddbb
--- /dev/null
+++ b/cas/1.0/default/TypeConvert.h
@@ -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
index 0000000000..93de79444e
--- /dev/null
+++ b/cas/1.0/default/android.hardware.cas@1.0-service.rc
@@ -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
index 0000000000..3f1df5a511
--- /dev/null
+++ b/cas/1.0/default/service.cpp
@@ -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
index 0000000000..7337f0014e
--- /dev/null
+++ b/cas/1.0/types.hal
@@ -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/configstore/1.1/vts/functional/Android.bp b/cas/1.0/vts/functional/Android.bp
index 5cfa4839d9..e1e09e9ce8 100644
--- a/configstore/1.1/vts/functional/Android.bp
+++ b/cas/1.0/vts/functional/Android.bp
@@ -15,20 +15,18 @@
//
cc_test {
- name: "VtsHalConfigstoreV1_1TargetTest",
- defaults: ["hidl_defaults"],
- srcs: ["VtsHalConfigstoreV1_1TargetTest.cpp"],
+ 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: [
- "libbase",
- "libhidlbase",
- "liblog",
- "libutils",
- "android.hardware.configstore@1.1",
+ "libbinder",
],
- static_libs: ["VtsHalHidlTargetTestBase"],
- cflags: [
- "-O0",
- "-g",
- ]
}
diff --git a/cas/1.0/vts/functional/VtsHalCasV1_0TargetTest.cpp b/cas/1.0/vts/functional/VtsHalCasV1_0TargetTest.cpp
new file mode 100644
index 0000000000..d3b0f1da3b
--- /dev/null
+++ b/cas/1.0/vts/functional/VtsHalCasV1_0TargetTest.cpp
@@ -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
index 0000000000..8208d3d51e
--- /dev/null
+++ b/cas/Android.bp
@@ -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
index 0000000000..e39cab1f7b
--- /dev/null
+++ b/cas/native/1.0/Android.bp
@@ -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
index 0000000000..4822111d2f
--- /dev/null
+++ b/cas/native/1.0/IDescrambler.hal
@@ -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
index 0000000000..d75338b588
--- /dev/null
+++ b/cas/native/1.0/types.hal
@@ -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;
+};
diff --git a/compatibility_matrix.26.xml b/compatibility_matrix.26.xml
index 9aa54188ad..5c81f26616 100644
--- a/compatibility_matrix.26.xml
+++ b/compatibility_matrix.26.xml
@@ -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>
@@ -71,9 +71,17 @@
<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-1</version>
+ <version>1.0</version>
<interface>
<name>ISurfaceFlingerConfigs</name>
<instance>default</instance>
@@ -204,16 +212,24 @@
</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>
@@ -256,9 +272,25 @@
</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>
@@ -281,7 +313,7 @@
</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>
@@ -289,7 +321,7 @@
</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>
@@ -304,14 +336,30 @@
</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>
@@ -319,7 +367,4 @@
<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
index 0000000000..5c81f26616
--- /dev/null
+++ b/compatibility_matrix.27.xml
@@ -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>
diff --git a/compatibility_matrix.current.xml b/compatibility_matrix.current.xml
index 9603bd6e15..5c81f26616 100644
--- a/compatibility_matrix.current.xml
+++ b/compatibility_matrix.current.xml
@@ -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>
@@ -71,9 +71,17 @@
<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-1</version>
+ <version>1.0</version>
<interface>
<name>ISurfaceFlingerConfigs</name>
<instance>default</instance>
@@ -206,10 +214,14 @@
<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>
@@ -217,7 +229,7 @@
</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>
@@ -260,9 +272,25 @@
</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>
@@ -285,7 +313,7 @@
</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>
@@ -293,7 +321,7 @@
</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>
@@ -310,16 +338,28 @@
<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>
@@ -327,7 +367,4 @@
<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.legacy.xml b/compatibility_matrix.legacy.xml
index 6167f25eb6..5655fb97d5 100644
--- a/compatibility_matrix.legacy.xml
+++ b/compatibility_matrix.legacy.xml
@@ -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>
@@ -71,9 +71,17 @@
<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-1</version>
+ <version>1.0</version>
<interface>
<name>ISurfaceFlingerConfigs</name>
<instance>default</instance>
@@ -204,16 +212,24 @@
</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>
@@ -256,9 +272,25 @@
</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>
@@ -281,7 +313,7 @@
</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>
@@ -289,7 +321,7 @@
</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>
@@ -304,14 +336,30 @@
</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>
@@ -319,7 +367,4 @@
<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/configstore/1.0/default/Android.mk b/configstore/1.0/default/Android.mk
new file mode 100644
index 0000000000..8b24031f4c
--- /dev/null
+++ b/configstore/1.0/default/Android.mk
@@ -0,0 +1,34 @@
+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
+LOCAL_INIT_RC := android.hardware.configstore@1.0-service.rc
+LOCAL_SRC_FILES:= service.cpp
+
+include $(LOCAL_PATH)/surfaceflinger.mk
+
+LOCAL_SHARED_LIBRARIES := \
+ android.hardware.configstore@1.0 \
+ 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.1/default/SurfaceFlingerConfigs.cpp b/configstore/1.0/default/SurfaceFlingerConfigs.cpp
index 5a040f2a89..3239274f9f 100644
--- a/configstore/1.1/default/SurfaceFlingerConfigs.cpp
+++ b/configstore/1.0/default/SurfaceFlingerConfigs.cpp
@@ -19,7 +19,7 @@
namespace android {
namespace hardware {
namespace configstore {
-namespace V1_1 {
+namespace V1_0 {
namespace implementation {
// Methods from ::android::hardware::configstore::V1_0::ISurfaceFlingerConfigs
@@ -139,13 +139,10 @@ Return<void> SurfaceFlingerConfigs::startGraphicsAllocatorService(
return Void();
}
-// Methods from ::android::hardware::configstore::V1_1::ISurfaceFlingerConfigs
-// follow.
-
// Methods from ::android::hidl::base::V1_0::IBase follow.
} // namespace implementation
-} // namespace V1_1
+} // namespace V1_0
} // namespace configstore
} // namespace hardware
} // namespace android
diff --git a/configstore/1.1/default/SurfaceFlingerConfigs.h b/configstore/1.0/default/SurfaceFlingerConfigs.h
index 53e8ae8714..32e5fc3928 100644
--- a/configstore/1.1/default/SurfaceFlingerConfigs.h
+++ b/configstore/1.0/default/SurfaceFlingerConfigs.h
@@ -1,17 +1,17 @@
-#ifndef ANDROID_HARDWARE_CONFIGSTORE_V1_1_SURFACEFLINGERCONFIGS_H
-#define ANDROID_HARDWARE_CONFIGSTORE_V1_1_SURFACEFLINGERCONFIGS_H
+#ifndef ANDROID_HARDWARE_CONFIGSTORE_V1_0_SURFACEFLINGERCONFIGS_H
+#define ANDROID_HARDWARE_CONFIGSTORE_V1_0_SURFACEFLINGERCONFIGS_H
-#include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
+#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
namespace android {
namespace hardware {
namespace configstore {
-namespace V1_1 {
+namespace V1_0 {
namespace implementation {
-using ::android::hardware::configstore::V1_1::ISurfaceFlingerConfigs;
+using ::android::hardware::configstore::V1_0::ISurfaceFlingerConfigs;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::sp;
@@ -32,16 +32,13 @@ struct SurfaceFlingerConfigs : public ISurfaceFlingerConfigs {
Return<void> maxFrameBufferAcquiredBuffers(maxFrameBufferAcquiredBuffers_cb _hidl_cb) override;
Return<void> startGraphicsAllocatorService(startGraphicsAllocatorService_cb _hidl_cb) override;
- // Methods from
- // ::android::hardware::configstore::V1_1::ISurfaceFlingerConfigs follow.
-
// Methods from ::android::hidl::base::V1_0::IBase follow.
};
} // namespace implementation
-} // namespace V1_1
+} // namespace V1_0
} // namespace configstore
} // namespace hardware
} // namespace android
-#endif // ANDROID_HARDWARE_CONFIGSTORE_V1_1_SURFACEFLINGERCONFIGS_H
+#endif // ANDROID_HARDWARE_CONFIGSTORE_V1_0_SURFACEFLINGERCONFIGS_H
diff --git a/configstore/1.0/default/android.hardware.configstore@1.0-service.rc b/configstore/1.0/default/android.hardware.configstore@1.0-service.rc
new file mode 100644
index 0000000000..563d8541c3
--- /dev/null
+++ b/configstore/1.0/default/android.hardware.configstore@1.0-service.rc
@@ -0,0 +1,4 @@
+service configstore-hal-1-0 /vendor/bin/hw/android.hardware.configstore@1.0-service
+ class hal animation
+ user system
+ group system
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
index 0000000000..43bf1fac3c
--- /dev/null
+++ b/configstore/1.0/default/seccomp_policy/configstore@1.0-arm64.policy
@@ -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
diff --git a/configstore/1.1/default/service.cpp b/configstore/1.0/default/service.cpp
index 3a4cd3fd67..c9c81a07f5 100644
--- a/configstore/1.1/default/service.cpp
+++ b/configstore/1.0/default/service.cpp
@@ -14,25 +14,28 @@
* limitations under the License.
*/
-#define LOG_TAG "android.hardware.configstore@1.1-service"
+#define LOG_TAG "android.hardware.configstore@1.0-service"
-#include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
+#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
#include <hidl/HidlTransportSupport.h>
+#include <hwminijail/HardwareMinijail.h>
#include "SurfaceFlingerConfigs.h"
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
-using android::hardware::configstore::V1_1::ISurfaceFlingerConfigs;
-using android::hardware::configstore::V1_1::implementation::SurfaceFlingerConfigs;
+using android::hardware::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");
diff --git a/configstore/1.1/default/surfaceflinger.mk b/configstore/1.0/default/surfaceflinger.mk
index 3ce768a63e..3ce768a63e 100644
--- a/configstore/1.1/default/surfaceflinger.mk
+++ b/configstore/1.0/default/surfaceflinger.mk
diff --git a/configstore/1.1/Android.bp b/configstore/1.1/Android.bp
deleted file mode 100644
index 3f8d580153..0000000000
--- a/configstore/1.1/Android.bp
+++ /dev/null
@@ -1,170 +0,0 @@
-// This file is autogenerated by hidl-gen. Do not edit manually.
-
-filegroup {
- name: "android.hardware.configstore@1.1_hal",
- srcs: [
- "ISurfaceFlingerConfigs.hal",
- ],
-}
-
-genrule {
- name: "android.hardware.configstore@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.configstore@1.1",
- srcs: [
- ":android.hardware.configstore@1.1_hal",
- ],
- out: [
- "android/hardware/configstore/1.1/SurfaceFlingerConfigsAll.cpp",
- ],
-}
-
-genrule {
- name: "android.hardware.configstore@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.configstore@1.1",
- srcs: [
- ":android.hardware.configstore@1.1_hal",
- ],
- out: [
- "android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h",
- "android/hardware/configstore/1.1/IHwSurfaceFlingerConfigs.h",
- "android/hardware/configstore/1.1/BnHwSurfaceFlingerConfigs.h",
- "android/hardware/configstore/1.1/BpHwSurfaceFlingerConfigs.h",
- "android/hardware/configstore/1.1/BsSurfaceFlingerConfigs.h",
- ],
-}
-
-cc_library {
- name: "android.hardware.configstore@1.1",
- defaults: ["hidl-module-defaults"],
- generated_sources: ["android.hardware.configstore@1.1_genc++"],
- generated_headers: ["android.hardware.configstore@1.1_genc++_headers"],
- export_generated_headers: ["android.hardware.configstore@1.1_genc++_headers"],
- vendor_available: true,
- vndk: {
- enabled: true,
- },
- shared_libs: [
- "libhidlbase",
- "libhidltransport",
- "libhwbinder",
- "liblog",
- "libutils",
- "libcutils",
- "android.hardware.configstore@1.0",
- ],
- export_shared_lib_headers: [
- "libhidlbase",
- "libhidltransport",
- "libhwbinder",
- "libutils",
- "android.hardware.configstore@1.0",
- ],
-}
-
-genrule {
- name: "android.hardware.configstore-V1.1-java_gen_java",
- tools: ["hidl-gen"],
- cmd: "$(location hidl-gen) -o $(genDir) -Ljava -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.configstore@1.1",
- srcs: [
- ":android.hardware.configstore@1.1_hal",
- ],
- out: [
- "android/hardware/configstore/V1_1/ISurfaceFlingerConfigs.java",
- ],
-}
-
-java_library {
- name: "android.hardware.configstore-V1.1-java",
- no_framework_libs: true,
- defaults: ["hidl-java-module-defaults"],
- srcs: [":android.hardware.configstore-V1.1-java_gen_java"],
- libs: [
- "hwbinder",
- "android.hardware.configstore-V1.0-java",
- "android.hidl.base-V1.0-java",
- ]
-}
-
-// This package does not export any types. Not creating java constants export.
-
-
-genrule {
- name: "android.hardware.configstore@1.1-adapter-helper_genc++",
- tools: ["hidl-gen"],
- cmd: "$(location hidl-gen) -o $(genDir) -Lc++-adapter-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.configstore@1.1",
- srcs: [
- ":android.hardware.configstore@1.1_hal",
- ],
- out: [
- "android/hardware/configstore/1.1/ASurfaceFlingerConfigs.cpp",
- ],
-}
-
-genrule {
- name: "android.hardware.configstore@1.1-adapter-helper_genc++_headers",
- tools: ["hidl-gen"],
- cmd: "$(location hidl-gen) -o $(genDir) -Lc++-adapter-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.configstore@1.1",
- srcs: [
- ":android.hardware.configstore@1.1_hal",
- ],
- out: [
- "android/hardware/configstore/1.1/ASurfaceFlingerConfigs.h",
- ],
-}
-
-cc_library {
- name: "android.hardware.configstore@1.1-adapter-helper",
- defaults: ["hidl-module-defaults"],
- generated_sources: ["android.hardware.configstore@1.1-adapter-helper_genc++"],
- generated_headers: ["android.hardware.configstore@1.1-adapter-helper_genc++_headers"],
- export_generated_headers: ["android.hardware.configstore@1.1-adapter-helper_genc++_headers"],
- vendor_available: true,
- shared_libs: [
- "libhidlbase",
- "libhidltransport",
- "libhwbinder",
- "liblog",
- "libutils",
- "libcutils",
- "libhidladapter",
- "android.hardware.configstore@1.0",
- "android.hardware.configstore@1.1",
- "android.hardware.configstore@1.0-adapter-helper",
- "android.hidl.base@1.0-adapter-helper",
- ],
- export_shared_lib_headers: [
- "libhidlbase",
- "libhidltransport",
- "libhwbinder",
- "libutils",
- "libhidladapter",
- "android.hardware.configstore@1.0",
- "android.hardware.configstore@1.1",
- "android.hardware.configstore@1.0-adapter-helper",
- "android.hidl.base@1.0-adapter-helper",
- ],
-}
-
-genrule {
- name: "android.hardware.configstore@1.1-adapter_genc++",
- tools: ["hidl-gen"],
- cmd: "$(location hidl-gen) -o $(genDir) -Lc++-adapter-main -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.configstore@1.1",
- out: ["main.cpp"]
-}
-
-cc_test {
- name: "android.hardware.configstore@1.1-adapter",
- defaults: ["hidl-module-defaults"],
- shared_libs: [
- "libhidladapter",
- "libhidlbase",
- "libhidltransport",
- "libutils",
- "android.hardware.configstore@1.0",
- "android.hardware.configstore@1.1",
- "android.hardware.configstore@1.1-adapter-helper",
- ],
- generated_sources: ["android.hardware.configstore@1.1-adapter_genc++"],
-}
diff --git a/configstore/1.1/ISurfaceFlingerConfigs.hal b/configstore/1.1/ISurfaceFlingerConfigs.hal
deleted file mode 100644
index 5eacbe00ac..0000000000
--- a/configstore/1.1/ISurfaceFlingerConfigs.hal
+++ /dev/null
@@ -1,25 +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.configstore@1.1;
-
-import @1.0::ISurfaceFlingerConfigs;
-
-/**
- * New revision of ISurfaceFlingerConfigs
- */
-
-interface ISurfaceFlingerConfigs extends @1.0::ISurfaceFlingerConfigs {
-};
diff --git a/configstore/1.1/default/Android.mk b/configstore/1.1/default/Android.mk
deleted file mode 100644
index a3a1041223..0000000000
--- a/configstore/1.1/default/Android.mk
+++ /dev/null
@@ -1,23 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-################################################################################
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hardware.configstore@1.1-service
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_MODULE_CLASS := EXECUTABLES
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_INIT_RC := android.hardware.configstore@1.1-service.rc
-LOCAL_SRC_FILES:= service.cpp
-
-include $(LOCAL_PATH)/surfaceflinger.mk
-
-LOCAL_SHARED_LIBRARIES := \
- libhidlbase \
- libhidltransport \
- libbase \
- liblog \
- libutils \
- android.hardware.configstore@1.0 \
- android.hardware.configstore@1.1
-
-include $(BUILD_EXECUTABLE)
diff --git a/configstore/1.1/default/android.hardware.configstore@1.1-service.rc b/configstore/1.1/default/android.hardware.configstore@1.1-service.rc
deleted file mode 100644
index 018ef102d0..0000000000
--- a/configstore/1.1/default/android.hardware.configstore@1.1-service.rc
+++ /dev/null
@@ -1,4 +0,0 @@
-service configstore-hal /vendor/bin/hw/android.hardware.configstore@1.1-service
- class hal animation
- user system
- group system
diff --git a/configstore/1.1/vts/functional/VtsHalConfigstoreV1_1TargetTest.cpp b/configstore/1.1/vts/functional/VtsHalConfigstoreV1_1TargetTest.cpp
deleted file mode 100644
index bd3da4c433..0000000000
--- a/configstore/1.1/vts/functional/VtsHalConfigstoreV1_1TargetTest.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "ConfigstoreHidlHalTest"
-
-#include <VtsHalHidlTargetTestBase.h>
-#include <android-base/logging.h>
-#include <android/hardware/configstore/1.0/types.h>
-#include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
-#include <unistd.h>
-
-using ::android::hardware::configstore::V1_1::ISurfaceFlingerConfigs;
-using ::android::sp;
-
-#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
-#define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk())
-
-class ConfigstoreHidlTest : public ::testing::VtsHalHidlTargetTestBase {
- public:
- sp<ISurfaceFlingerConfigs> sfConfigs;
-
- virtual void SetUp() override {
- sfConfigs = ::testing::VtsHalHidlTargetTestBase::getService<ISurfaceFlingerConfigs>();
- ASSERT_NE(sfConfigs, nullptr);
- }
-
- virtual void TearDown() override {}
-};
-
-/**
- * Placeholder testcase.
- */
-TEST_F(ConfigstoreHidlTest, Test) {
- ASSERT_TRUE(true);
-}
-
-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/configstore/Android.bp b/configstore/Android.bp
index 4a783c3d7e..ba3e62e29b 100644
--- a/configstore/Android.bp
+++ b/configstore/Android.bp
@@ -2,7 +2,5 @@
subdirs = [
"1.0",
"1.0/vts/functional",
- "1.1",
- "1.1/vts/functional",
"utils",
]
diff --git a/contexthub/1.0/default/Contexthub.cpp b/contexthub/1.0/default/Contexthub.cpp
index bf459005b4..3626a0948f 100644
--- a/contexthub/1.0/default/Contexthub.cpp
+++ b/contexthub/1.0/default/Contexthub.cpp
@@ -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);
diff --git a/current.txt b/current.txt
index a3ff61e8f2..db34c37bd9 100644
--- a/current.txt
+++ b/current.txt
@@ -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
@@ -221,5 +226,31 @@ b18caefefcc765092412285d776234fcf213b73bdf07ae1b67a5f71b2d2464e3 android.hardwar
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)
+2d833aeed0cd1d59437aca210be590a953cf32bcb6683cd63d089762a643fb49 android.hardware.radio@1.0::IRadioResponse
+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
diff --git a/drm/1.0/default/Android.mk b/drm/1.0/default/Android.mk
index 0cc6e71b2d..99773be385 100644
--- a/drm/1.0/default/Android.mk
+++ b/drm/1.0/default/Android.mk
@@ -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
diff --git a/drm/1.0/default/CryptoFactory.h b/drm/1.0/default/CryptoFactory.h
index 6b1d1ffce8..86130dc367 100644
--- a/drm/1.0/default/CryptoFactory.h
+++ b/drm/1.0/default/CryptoFactory.h
@@ -20,7 +20,6 @@
#include <hidl/Status.h>
#include <media/hardware/CryptoAPI.h>
#include <PluginLoader.h>
-#include <media/SharedLibrary.h>
namespace android {
namespace hardware {
diff --git a/drm/1.0/default/CryptoPlugin.cpp b/drm/1.0/default/CryptoPlugin.cpp
index 591861aeec..fd75dbd3f9 100644
--- a/drm/1.0/default/CryptoPlugin.cpp
+++ b/drm/1.0/default/CryptoPlugin.cpp
@@ -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();
diff --git a/drm/1.0/default/DrmFactory.h b/drm/1.0/default/DrmFactory.h
index 726bf97185..32e192db80 100644
--- a/drm/1.0/default/DrmFactory.h
+++ b/drm/1.0/default/DrmFactory.h
@@ -20,7 +20,6 @@
#include <hidl/Status.h>
#include <media/drm/DrmAPI.h>
#include <PluginLoader.h>
-#include <media/SharedLibrary.h>
namespace android {
namespace hardware {
diff --git a/drm/1.0/vts/functional/Android.bp b/drm/1.0/vts/functional/Android.bp
index 18aebee4a9..57678fb46c 100644
--- a/drm/1.0/vts/functional/Android.bp
+++ b/drm/1.0/vts/functional/Android.bp
@@ -21,29 +21,15 @@ cc_test {
"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",
],
}
diff --git a/drm/1.0/vts/functional/drm_hal_clearkey_test.cpp b/drm/1.0/vts/functional/drm_hal_clearkey_test.cpp
index 84ee5dfc49..4652c76d5d 100644
--- a/drm/1.0/vts/functional/drm_hal_clearkey_test.cpp
+++ b/drm/1.0/vts/functional/drm_hal_clearkey_test.cpp
@@ -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;
}
@@ -1078,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);
}
diff --git a/drm/1.0/vts/functional/drm_hal_vendor_test.cpp b/drm/1.0/vts/functional/drm_hal_vendor_test.cpp
index 2e080b3050..47c6950cd7 100644
--- a/drm/1.0/vts/functional/drm_hal_vendor_test.cpp
+++ b/drm/1.0/vts/functional/drm_hal_vendor_test.cpp
@@ -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;
diff --git a/dumpstate/1.0/vts/functional/Android.bp b/dumpstate/1.0/vts/functional/Android.bp
index a1c735b1e4..1ab530fec4 100644
--- a/dumpstate/1.0/vts/functional/Android.bp
+++ b/dumpstate/1.0/vts/functional/Android.bp
@@ -15,18 +15,7 @@
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"],
}
diff --git a/gnss/1.0/default/GnssMeasurement.cpp b/gnss/1.0/default/GnssMeasurement.cpp
index 6c9b838b8d..d81f829bcd 100644
--- a/gnss/1.0/default/GnssMeasurement.cpp
+++ b/gnss/1.0/default/GnssMeasurement.cpp
@@ -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
index 0000000000..6c25bd7c22
--- /dev/null
+++ b/gnss/1.0/default/OWNERS
@@ -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
index 0000000000..937d70aa67
--- /dev/null
+++ b/gnss/1.0/vts/OWNERS
@@ -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
diff --git a/graphics/composer/2.1/default/Hwc.cpp b/graphics/composer/2.1/default/Hwc.cpp
index fdb4af88c2..80ec1cdc3f 100644
--- a/graphics/composer/2.1/default/Hwc.cpp
+++ b/graphics/composer/2.1/default/Hwc.cpp
@@ -30,6 +30,8 @@
using namespace std::chrono_literals;
+using namespace std::chrono_literals;
+
namespace android {
namespace hardware {
namespace graphics {
diff --git a/graphics/composer/2.1/default/IComposerCommandBuffer.h b/graphics/composer/2.1/default/IComposerCommandBuffer.h
index 9ee5f4f88d..058709c5ed 100644
--- a/graphics/composer/2.1/default/IComposerCommandBuffer.h
+++ b/graphics/composer/2.1/default/IComposerCommandBuffer.h
@@ -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)) {
diff --git a/graphics/composer/2.1/vts/functional/Android.bp b/graphics/composer/2.1/vts/functional/Android.bp
index 2e87144dbb..1ba7c9a1b2 100644
--- a/graphics/composer/2.1/vts/functional/Android.bp
+++ b/graphics/composer/2.1/vts/functional/Android.bp
@@ -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",
- ]
}
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
index 0f03546558..9a749d7837 100644
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
+++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
@@ -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;
}
diff --git a/graphics/mapper/2.0/vts/functional/Android.bp b/graphics/mapper/2.0/vts/functional/Android.bp
index 1c0e4c5a32..ac6cb47a68 100644
--- a/graphics/mapper/2.0/vts/functional/Android.bp
+++ b/graphics/mapper/2.0/vts/functional/Android.bp
@@ -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",
- ]
}
diff --git a/health/1.0/default/Android.bp b/health/1.0/default/Android.bp
new file mode 100644
index 0000000000..cb2e87d16e
--- /dev/null
+++ b/health/1.0/default/Android.bp
@@ -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",
+ ],
+
+}
+
diff --git a/health/1.0/default/Android.mk b/health/1.0/default/Android.mk
index 96ff91fe7b..199ab4120d 100644
--- a/health/1.0/default/Android.mk
+++ b/health/1.0/default/Android.mk
@@ -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
index 0000000000..ce02e28cc2
--- /dev/null
+++ b/health/1.0/default/libhealthd/Android.bp
@@ -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
index a5f4445edc..0000000000
--- a/health/1.0/default/libhealthd/Android.mk
+++ /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)
diff --git a/health/Android.bp b/health/Android.bp
index 31e042a982..2c931e591b 100644
--- a/health/Android.bp
+++ b/health/Android.bp
@@ -1,6 +1,8 @@
// This is an autogenerated file, do not edit.
subdirs = [
"1.0",
+ "1.0/default",
+ "1.0/default/libhealthd",
"1.0/vts/functional",
"2.0",
]
diff --git a/keymaster/3.0/vts/functional/Android.bp b/keymaster/3.0/vts/functional/Android.bp
new file mode 100644
index 0000000000..7d96704f2e
--- /dev/null
+++ b/keymaster/3.0/vts/functional/Android.bp
@@ -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
index 40986640d4..0000000000
--- a/keymaster/3.0/vts/functional/Android.mk
+++ /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)
diff --git a/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp
index 78353eaf25..3d78f45069 100644
--- a/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -1774,7 +1774,7 @@ TEST_F(SigningOperationsTest, EcdsaNoDigestHugeData) {
.Authorization(TAG_NO_AUTH_REQUIRED)
.EcdsaSigningKey(224)
.Digest(Digest::NONE)));
- string message(64 * 1024, 'a');
+ string message(2 * 1024, 'a');
SignMessage(message, AuthorizationSetBuilder().Digest(Digest::NONE));
}
@@ -2607,7 +2607,7 @@ TEST_F(EncryptionOperationsTest, RsaNoPaddingTooLong) {
}
/*
- * EncryptionOperationsTest.RsaNoPaddingTooLong
+ * EncryptionOperationsTest.RsaNoPaddingTooLarge
*
* Verifies that raw RSA encryption of too-large (numerically) messages fails in the expected way.
*/
@@ -3907,7 +3907,7 @@ TEST_F(AddEntropyTest, AddEmptyEntropy) {
* Verifies that the addRngEntropy method doesn't blow up when given a largish amount of data.
*/
TEST_F(AddEntropyTest, AddLargeEntropy) {
- EXPECT_EQ(ErrorCode::OK, keymaster().addRngEntropy(HidlBuf(string(16 * 1024, 'a'))));
+ EXPECT_EQ(ErrorCode::OK, keymaster().addRngEntropy(HidlBuf(string(2 * 1024, 'a'))));
}
typedef KeymasterHidlTest AttestationTest;
diff --git a/keymaster/Android.bp b/keymaster/Android.bp
index 09b8cb28d3..90a01955f3 100644
--- a/keymaster/Android.bp
+++ b/keymaster/Android.bp
@@ -1,4 +1,5 @@
// This is an autogenerated file, do not edit.
subdirs = [
"3.0",
+ "3.0/vts/functional",
]
diff --git a/media/omx/1.0/IOmxStore.hal b/media/omx/1.0/IOmxStore.hal
index a224b0e16f..3ec053578a 100644
--- a/media/omx/1.0/IOmxStore.hal
+++ b/media/omx/1.0/IOmxStore.hal
@@ -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>
diff --git a/media/omx/1.0/vts/functional/audio/Android.bp b/media/omx/1.0/vts/functional/audio/Android.bp
index 66fd20be2c..f517fa1d90 100644
--- a/media/omx/1.0/vts/functional/audio/Android.bp
+++ b/media/omx/1.0/vts/functional/audio/Android.bp
@@ -16,65 +16,19 @@
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"
],
}
diff --git a/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioDecTest.cpp b/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioDecTest.cpp
index 336cab4832..38cdcd6508 100644
--- a/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioDecTest.cpp
+++ b/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioDecTest.cpp
@@ -15,6 +15,10 @@
*/
#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,11 +225,15 @@ 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 {
if (omxNode != nullptr) {
+ // If you have encountered a fatal failure, it is possible that
+ // freeNode() will not go through. Instead of hanging the app.
+ // let it pass through and report errors
+ if (::testing::Test::HasFatalFailure()) return;
EXPECT_TRUE((omxNode->freeNode()).isOk());
omxNode = nullptr;
}
@@ -263,9 +273,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 +310,7 @@ class AudioDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
g711mlaw,
gsm,
raw,
+ flac,
unknown_comp,
};
@@ -418,6 +428,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 +444,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 +495,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 +556,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 +571,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 +583,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 +594,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 +614,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 +639,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 +656,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 +687,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 +728,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;
@@ -766,13 +777,13 @@ TEST_F(AudioDecHidlTest, DecodeTest) {
int bytesCount = 0;
uint32_t flags = 0;
uint32_t timestamp = 0;
- timestampDevTest = true;
+ timestampDevTest = false;
while (1) {
if (!(eleInfo >> bytesCount)) break;
eleInfo >> flags;
eleInfo >> timestamp;
Info.push_back({bytesCount, flags, timestamp});
- if (flags != OMX_BUFFERFLAG_CODECCONFIG)
+ if (timestampDevTest && (flags != OMX_BUFFERFLAG_CODECCONFIG))
timestampUslist.push_back(timestamp);
}
eleInfo.close();
@@ -784,8 +795,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 +809,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);
- EXPECT_EQ(timestampUslist.empty(), true);
+ 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 +861,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 +875,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 +945,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 +959,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 +971,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 +991,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 +1059,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 +1073,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 +1151,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 +1165,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 +1177,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 +1198,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) {
diff --git a/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioEncTest.cpp b/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioEncTest.cpp
index ae79e82621..953dc7507b 100644
--- a/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioEncTest.cpp
+++ b/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioEncTest.cpp
@@ -15,6 +15,10 @@
*/
#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,11 +211,15 @@ 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 {
if (omxNode != nullptr) {
+ // If you have encountered a fatal failure, it is possible that
+ // freeNode() will not go through. Instead of hanging the app.
+ // let it pass through and report errors
+ if (::testing::Test::HasFatalFailure()) return;
EXPECT_TRUE((omxNode->freeNode()).isOk());
omxNode = nullptr;
}
@@ -342,13 +351,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 +370,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 +386,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 +412,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 +447,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 +523,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) {
diff --git a/media/omx/1.0/vts/functional/audio/media_audio_hidl_test_common.cpp b/media/omx/1.0/vts/functional/audio/media_audio_hidl_test_common.cpp
index 4c68219b47..9500094d6f 100644
--- a/media/omx/1.0/vts/functional/audio/media_audio_hidl_test_common.cpp
+++ b/media/omx/1.0/vts/functional/audio/media_audio_hidl_test_common.cpp
@@ -15,6 +15,10 @@
*/
#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>
diff --git a/media/omx/1.0/vts/functional/audio/media_audio_hidl_test_common.h b/media/omx/1.0/vts/functional/audio/media_audio_hidl_test_common.h
index 08b3d9cd58..b187d28415 100644
--- a/media/omx/1.0/vts/functional/audio/media_audio_hidl_test_common.h
+++ b/media/omx/1.0/vts/functional/audio/media_audio_hidl_test_common.h
@@ -20,11 +20,6 @@
#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,
diff --git a/media/omx/1.0/vts/functional/common/Android.bp b/media/omx/1.0/vts/functional/common/Android.bp
index 93251fe89b..cdc52fb477 100755..100644
--- a/media/omx/1.0/vts/functional/common/Android.bp
+++ b/media/omx/1.0/vts/functional/common/Android.bp
@@ -16,18 +16,43 @@
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",
],
}
diff --git a/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp b/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
index 1f67e2b6a5..34a96a0ce7 100755..100644
--- a/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
+++ b/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
@@ -15,13 +15,15 @@
*/
#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>
@@ -29,7 +31,10 @@
#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;
diff --git a/media/omx/1.0/vts/functional/common/media_hidl_test_common.h b/media/omx/1.0/vts/functional/common/media_hidl_test_common.h
index 0adea14e80..bec733dc93 100644
--- a/media/omx/1.0/vts/functional/common/media_hidl_test_common.h
+++ b/media/omx/1.0/vts/functional/common/media_hidl_test_common.h
@@ -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.
@@ -33,8 +33,21 @@
#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,
diff --git a/media/omx/1.0/vts/functional/component/Android.bp b/media/omx/1.0/vts/functional/component/Android.bp
index fd3210fb91..f76b6e94fa 100644
--- a/media/omx/1.0/vts/functional/component/Android.bp
+++ b/media/omx/1.0/vts/functional/component/Android.bp
@@ -16,32 +16,7 @@
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",
- ],
}
diff --git a/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp b/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp
index 2d91e8275d..d66136d212 100644
--- a/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp
+++ b/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp
@@ -15,6 +15,10 @@
*/
#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,11 +186,15 @@ 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 {
if (omxNode != nullptr) {
+ // If you have encountered a fatal failure, it is possible that
+ // freeNode() will not go through. Instead of hanging the app.
+ // let it pass through and report errors
+ if (::testing::Test::HasFatalFailure()) return;
EXPECT_TRUE((omxNode->freeNode()).isOk());
omxNode = nullptr;
}
@@ -213,9 +222,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 +238,6 @@ void initPortMode(PortMode* pm, bool isSecure,
break;
}
}
- return;
}
// test dispatch message API call
@@ -293,7 +298,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 +379,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 +405,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 +440,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 +507,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 +524,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 +567,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 +638,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 +936,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 +946,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 +958,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 +1047,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 +1102,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 +1117,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 +1152,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 +1218,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 +1232,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
diff --git a/media/omx/1.0/vts/functional/master/Android.bp b/media/omx/1.0/vts/functional/master/Android.bp
index e24b79b8a9..4a45e6923c 100644
--- a/media/omx/1.0/vts/functional/master/Android.bp
+++ b/media/omx/1.0/vts/functional/master/Android.bp
@@ -16,29 +16,7 @@
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",
- ],
}
diff --git a/media/omx/1.0/vts/functional/master/VtsHalMediaOmxV1_0TargetMasterTest.cpp b/media/omx/1.0/vts/functional/master/VtsHalMediaOmxV1_0TargetMasterTest.cpp
index e8f5f77dfd..5a31d691c9 100644
--- a/media/omx/1.0/vts/functional/master/VtsHalMediaOmxV1_0TargetMasterTest.cpp
+++ b/media/omx/1.0/vts/functional/master/VtsHalMediaOmxV1_0TargetMasterTest.cpp
@@ -15,6 +15,10 @@
*/
#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()
diff --git a/media/omx/1.0/vts/functional/video/Android.bp b/media/omx/1.0/vts/functional/video/Android.bp
index 4e94f3b35b..f0da2b39d0 100644
--- a/media/omx/1.0/vts/functional/video/Android.bp
+++ b/media/omx/1.0/vts/functional/video/Android.bp
@@ -16,70 +16,21 @@
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",
],
}
diff --git a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp
index 438dd7071e..9b74a339c0 100644
--- a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp
+++ b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp
@@ -15,11 +15,12 @@
*/
#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>
@@ -28,8 +29,6 @@
#include <android/hidl/memory/1.0/IMapper.h>
#include <android/hidl/memory/1.0/IMemory.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;
@@ -47,6 +46,7 @@ using ::android::sp;
#include <VtsHalHidlTargetTestBase.h>
#include <getopt.h>
+#include <media/hardware/HardwareAPI.h>
#include <media_hidl_test_common.h>
#include <media_video_hidl_test_common.h>
#include <fstream>
@@ -166,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 {
@@ -217,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 =
@@ -225,11 +227,15 @@ 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 {
if (omxNode != nullptr) {
+ // If you have encountered a fatal failure, it is possible that
+ // freeNode() will not go through. Instead of hanging the app.
+ // let it pass through and report errors
+ if (::testing::Test::HasFatalFailure()) return;
EXPECT_TRUE((omxNode->freeNode()).isOk());
omxNode = nullptr;
}
@@ -269,9 +275,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";
}
}
}
@@ -293,6 +298,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;
+ }
+ }
}
}
@@ -320,6 +332,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) {
@@ -367,119 +380,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, 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 = PixelFormat::RGBA_8888;
- 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);
- 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 =
- (*buffArray)[i].id;
- }
- });
-}
-
// port settings reconfiguration during runtime. reconfigures frame dimensions
void portReconfiguration(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
android::Vector<BufferInfo>* iBuffer,
@@ -493,6 +448,21 @@ void portReconfiguration(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
ASSERT_EQ(msg.data.eventData.data1, kPortIndexOutput);
if (msg.data.eventData.data2 == OMX_IndexParamPortDefinition ||
msg.data.eventData.data2 == 0) {
+ // Components can send various kinds of port settings changed events
+ // all at once. Before committing to a full port reconfiguration,
+ // defer any events waiting in the queue to be addressed to a later
+ // point.
+ android::List<Message> msgQueueDefer;
+ while (1) {
+ status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
+ iBuffer, oBuffer);
+ if (status !=
+ android::hardware::media::omx::V1_0::Status::TIMED_OUT) {
+ msgQueueDefer.push_back(msg);
+ continue;
+ } else
+ break;
+ }
status = omxNode->sendCommand(
toRawCommandType(OMX_CommandPortDisable), kPortIndexOutput);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
@@ -521,17 +491,19 @@ void portReconfiguration(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
// set Port Params
uint32_t nFrameWidth, nFrameHeight, xFramerate;
- OMX_COLOR_FORMATTYPE eColorFormat =
- OMX_COLOR_FormatYUV420Planar;
getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth,
&nFrameHeight, &xFramerate);
+ // get configured color format
+ OMX_PARAM_PORTDEFINITIONTYPE portDef;
+ status = getPortParam(omxNode, OMX_IndexParamPortDefinition,
+ kPortIndexOutput, &portDef);
setDefaultPortParam(omxNode, kPortIndexOutput,
- OMX_VIDEO_CodingUnused, eColorFormat,
+ OMX_VIDEO_CodingUnused,
+ portDef.format.video.eColorFormat,
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,
@@ -544,22 +516,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.nBufferCountActual);
- }
+ ASSERT_NO_FATAL_FAILURE(allocatePortBuffers(
+ omxNode, oBuffer, kPortIndexOutput, oPortMode, true));
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
iBuffer, oBuffer);
ASSERT_EQ(status,
@@ -568,25 +526,36 @@ void portReconfiguration(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortEnable);
ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput);
+ // Push back deferred messages to the list
+ android::List<Message>::iterator it = msgQueueDefer.begin();
+ while (it != msgQueueDefer.end()) {
+ status = omxNode->dispatchMessage(*it);
+ ASSERT_EQ(
+ status,
+ ::android::hardware::media::omx::V1_0::Status::OK);
+ it++;
+ }
+
// 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);
@@ -601,17 +570,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
@@ -624,9 +593,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--;
}
}
@@ -640,50 +610,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()));
@@ -692,29 +639,146 @@ 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";
+ ASSERT_TRUE(false) << "Wait on Input/Output is found indefinite";
+ }
+ }
+}
+
+// DescribeColorFormatParams Copy Constructor (Borrowed from OMXUtils.cpp)
+android::DescribeColorFormatParams::DescribeColorFormatParams(
+ const android::DescribeColorFormat2Params& params) {
+ eColorFormat = params.eColorFormat;
+ nFrameWidth = params.nFrameWidth;
+ nFrameHeight = params.nFrameHeight;
+ nStride = params.nStride;
+ nSliceHeight = params.nSliceHeight;
+ bUsingNativeBuffers = params.bUsingNativeBuffers;
+};
+
+bool isColorFormatFlexibleYUV(sp<IOmxNode> omxNode,
+ OMX_COLOR_FORMATTYPE eColorFormat) {
+ android::hardware::media::omx::V1_0::Status status;
+ unsigned int index = OMX_IndexMax, index2 = OMX_IndexMax;
+ omxNode->getExtensionIndex(
+ "OMX.google.android.index.describeColorFormat",
+ [&index](android::hardware::media::omx::V1_0::Status _s,
+ unsigned int _nl) {
+ if (_s == ::android::hardware::media::omx::V1_0::Status::OK)
+ index = _nl;
+ });
+ omxNode->getExtensionIndex(
+ "OMX.google.android.index.describeColorFormat2",
+ [&index2](android::hardware::media::omx::V1_0::Status _s,
+ unsigned int _nl) {
+ if (_s == ::android::hardware::media::omx::V1_0::Status::OK)
+ index2 = _nl;
+ });
+
+ android::DescribeColorFormat2Params describeParams;
+ describeParams.eColorFormat = eColorFormat;
+ describeParams.nFrameWidth = 128;
+ describeParams.nFrameHeight = 128;
+ describeParams.nStride = 128;
+ describeParams.nSliceHeight = 128;
+ describeParams.bUsingNativeBuffers = OMX_FALSE;
+ if (index != OMX_IndexMax) {
+ android::DescribeColorFormatParams describeParamsV1(describeParams);
+ status = getParam(omxNode, static_cast<OMX_INDEXTYPE>(index),
+ &describeParamsV1);
+ if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
+ android::MediaImage& img = describeParamsV1.sMediaImage;
+ if (img.mType == android::MediaImage::MEDIA_IMAGE_TYPE_YUV) {
+ if (img.mNumPlanes == 3 &&
+ img.mPlane[img.Y].mHorizSubsampling == 1 &&
+ img.mPlane[img.Y].mVertSubsampling == 1) {
+ if (img.mPlane[img.U].mHorizSubsampling == 2 &&
+ img.mPlane[img.U].mVertSubsampling == 2 &&
+ img.mPlane[img.V].mHorizSubsampling == 2 &&
+ img.mPlane[img.V].mVertSubsampling == 2) {
+ if (img.mBitDepth <= 8) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ } else if (index2 != OMX_IndexMax) {
+ status = getParam(omxNode, static_cast<OMX_INDEXTYPE>(index2),
+ &describeParams);
+ android::MediaImage2& img = describeParams.sMediaImage;
+ if (img.mType == android::MediaImage2::MEDIA_IMAGE_TYPE_YUV) {
+ if (img.mNumPlanes == 3 &&
+ img.mPlane[img.Y].mHorizSubsampling == 1 &&
+ img.mPlane[img.Y].mVertSubsampling == 1) {
+ if (img.mPlane[img.U].mHorizSubsampling == 2 &&
+ img.mPlane[img.U].mVertSubsampling == 2 &&
+ img.mPlane[img.V].mHorizSubsampling == 2 &&
+ img.mPlane[img.V].mVertSubsampling == 2) {
+ if (img.mBitDepth <= 8) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+}
+
+// get default color format for output port
+void getDefaultColorFormat(sp<IOmxNode> omxNode, OMX_U32 kPortIndexOutput,
+ PortMode oPortMode,
+ OMX_COLOR_FORMATTYPE* eColorFormat) {
+ android::hardware::media::omx::V1_0::Status status;
+ OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat;
+ *eColorFormat = OMX_COLOR_FormatUnused;
+ portFormat.nIndex = 0;
+ while (portFormat.nIndex < 512) {
+ status = getPortParam(omxNode, OMX_IndexParamVideoPortFormat,
+ kPortIndexOutput, &portFormat);
+ if (status != ::android::hardware::media::omx::V1_0::Status::OK) break;
+ EXPECT_EQ(portFormat.eCompressionFormat, OMX_VIDEO_CodingUnused);
+ if (oPortMode != PortMode::PRESET_BYTE_BUFFER) {
+ *eColorFormat = portFormat.eColorFormat;
+ break;
+ }
+ if (isColorFormatFlexibleYUV(omxNode, portFormat.eColorFormat)) {
+ *eColorFormat = portFormat.eColorFormat;
+ break;
+ }
+ if (OMX_COLOR_FormatYUV420SemiPlanar == portFormat.eColorFormat ||
+ OMX_COLOR_FormatYUV420Planar == portFormat.eColorFormat ||
+ OMX_COLOR_FormatYUV420PackedPlanar == portFormat.eColorFormat ||
+ OMX_COLOR_FormatYUV420PackedSemiPlanar == portFormat.eColorFormat) {
+ *eColorFormat = portFormat.eColorFormat;
break;
}
+ portFormat.nIndex++;
}
}
@@ -788,7 +852,7 @@ TEST_F(VideoDecHidlTest, DecodeTest) {
eleInfo >> flags;
eleInfo >> timestamp;
Info.push_back({bytesCount, flags, timestamp});
- if (flags != OMX_BUFFERFLAG_CODECCONFIG)
+ if (timestampDevTest && (flags != OMX_BUFFERFLAG_CODECCONFIG))
timestampUslist.push_back(timestamp);
if (maxBytesCount < bytesCount) maxBytesCount = bytesCount;
}
@@ -813,58 +877,59 @@ TEST_F(VideoDecHidlTest, DecodeTest) {
// set Port Params
uint32_t nFrameWidth, nFrameHeight, xFramerate;
- OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatYUV420Planar;
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);
- // 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.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);
- EXPECT_EQ(timestampUslist.empty(), true);
+ 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
- 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
-TEST_F(VideoDecHidlTest, EOSTest_M) {
- description("Test End of stream monkeying");
+// 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());
@@ -877,44 +942,199 @@ TEST_F(VideoDecHidlTest, EOSTest_M) {
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;
- OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatYUV420Planar;
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
+ ASSERT_NO_FATAL_FAILURE(
+ changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
+ // set state to executing
+ ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
+ &oBuffer, kPortIndexInput,
+ kPortIndexOutput));
+}
+
+// end of sequence test
+TEST_F(VideoDecHidlTest, EOSTest_M) {
+ description("Test End of stream monkeying");
+ if (disableTest) 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 portMode[2];
- portMode[0] = portMode[1] = PortMode::PRESET_BYTE_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);
+ // 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
- 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
@@ -967,67 +1187,75 @@ TEST_F(VideoDecHidlTest, ThumbnailTest) {
// set Port Params
uint32_t nFrameWidth, nFrameHeight, xFramerate;
- OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatYUV420Planar;
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);
- // set port mode
- PortMode portMode[2];
- portMode[0] = portMode[1] = PortMode::PRESET_BYTE_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);
-
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
@@ -1073,56 +1301,68 @@ 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;
- OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatYUV420Planar;
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);
- // set port mode
- PortMode portMode[2];
- portMode[0] = portMode[1] = PortMode::PRESET_BYTE_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);
-
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
@@ -1175,27 +1415,28 @@ TEST_F(VideoDecHidlTest, FlushTest) {
// set Port Params
uint32_t nFrameWidth, nFrameHeight, xFramerate;
- OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatYUV420Planar;
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);
- // set port mode
- PortMode portMode[2];
- portMode[0] = portMode[1] = PortMode::PRESET_BYTE_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);
-
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
@@ -1203,12 +1444,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
@@ -1225,21 +1465,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) {
diff --git a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp
index 7f9486d953..099658f8ae 100644
--- a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp
+++ b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp
@@ -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,11 +238,15 @@ 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 {
if (omxNode != nullptr) {
+ // If you have encountered a fatal failure, it is possible that
+ // freeNode() will not go through. Instead of hanging the app.
+ // let it pass through and report errors
+ if (::testing::Test::HasFatalFailure()) return;
EXPECT_TRUE((omxNode->freeNode()).isOk());
omxNode = nullptr;
}
@@ -278,9 +283,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 +446,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 +457,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 +469,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 +483,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 +509,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 +519,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 +528,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 +536,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 +616,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 +639,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 +988,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 +1014,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 +1030,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 +1052,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 +1147,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 +1161,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 +1228,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 +1247,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 +1266,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);
- EXPECT_EQ(timestampUslist.empty(), true);
+ 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 +1318,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 +1429,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 +1548,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);
diff --git a/media/omx/1.0/vts/functional/video/media_video_hidl_test_common.cpp b/media/omx/1.0/vts/functional/video/media_video_hidl_test_common.cpp
index 91aecf22e6..e1b6022f9d 100644
--- a/media/omx/1.0/vts/functional/video/media_video_hidl_test_common.cpp
+++ b/media/omx/1.0/vts/functional/video/media_video_hidl_test_common.cpp
@@ -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
diff --git a/media/omx/1.0/vts/functional/video/media_video_hidl_test_common.h b/media/omx/1.0/vts/functional/video/media_video_hidl_test_common.h
index c1d7aeae55..55de125877 100644
--- a/media/omx/1.0/vts/functional/video/media_video_hidl_test_common.h
+++ b/media/omx/1.0/vts/functional/video/media_video_hidl_test_common.h
@@ -18,14 +18,8 @@
#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);
diff --git a/media/res/bbb_aac_stereo_128kbps_48000hz.aac b/media/res/bbb_aac_stereo_128kbps_48000hz.aac
index 831102d223..831102d223 100755..100644
--- a/media/res/bbb_aac_stereo_128kbps_48000hz.aac
+++ b/media/res/bbb_aac_stereo_128kbps_48000hz.aac
Binary files differ
diff --git a/media/res/bbb_aac_stereo_128kbps_48000hz.info b/media/res/bbb_aac_stereo_128kbps_48000hz.info
index d124f30dda..d124f30dda 100755..100644
--- a/media/res/bbb_aac_stereo_128kbps_48000hz.info
+++ b/media/res/bbb_aac_stereo_128kbps_48000hz.info
diff --git a/media/res/bbb_amrwb_1ch_14kbps_16000hz.amrwb b/media/res/bbb_amrwb_1ch_14kbps_16000hz.amrwb
index 0d8259378f..0d8259378f 100755..100644
--- a/media/res/bbb_amrwb_1ch_14kbps_16000hz.amrwb
+++ b/media/res/bbb_amrwb_1ch_14kbps_16000hz.amrwb
Binary files differ
diff --git a/media/res/bbb_amrwb_1ch_14kbps_16000hz.info b/media/res/bbb_amrwb_1ch_14kbps_16000hz.info
index 71cffefea8..71cffefea8 100755..100644
--- a/media/res/bbb_amrwb_1ch_14kbps_16000hz.info
+++ b/media/res/bbb_amrwb_1ch_14kbps_16000hz.info
diff --git a/media/res/bbb_avc_176x144_300kbps_60fps.h264 b/media/res/bbb_avc_176x144_300kbps_60fps.h264
new file mode 100644
index 0000000000..da1e75dcd1
--- /dev/null
+++ b/media/res/bbb_avc_176x144_300kbps_60fps.h264
Binary files 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
index 0000000000..d88b540ef4
--- /dev/null
+++ b/media/res/bbb_avc_176x144_300kbps_60fps.info
@@ -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
index 0000000000..db94d8eb04
--- /dev/null
+++ b/media/res/bbb_flac_stereo_680kbps_48000hz.flac
Binary files 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
index 0000000000..c57243079d
--- /dev/null
+++ b/media/res/bbb_flac_stereo_680kbps_48000hz.info
@@ -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
diff --git a/media/res/bbb_g711alaw_1ch_8khz.info b/media/res/bbb_g711alaw_1ch_8khz.info
index 2ffe358eb4..2ffe358eb4 100755..100644
--- a/media/res/bbb_g711alaw_1ch_8khz.info
+++ b/media/res/bbb_g711alaw_1ch_8khz.info
diff --git a/media/res/bbb_g711alaw_1ch_8khz.raw b/media/res/bbb_g711alaw_1ch_8khz.raw
index cfc4a11cfe..cfc4a11cfe 100755..100644
--- a/media/res/bbb_g711alaw_1ch_8khz.raw
+++ b/media/res/bbb_g711alaw_1ch_8khz.raw
diff --git a/media/res/bbb_g711mulaw_1ch_8khz.info b/media/res/bbb_g711mulaw_1ch_8khz.info
index 5162a17f0b..5162a17f0b 100755..100644
--- a/media/res/bbb_g711mulaw_1ch_8khz.info
+++ b/media/res/bbb_g711mulaw_1ch_8khz.info
diff --git a/media/res/bbb_g711mulaw_1ch_8khz.raw b/media/res/bbb_g711mulaw_1ch_8khz.raw
index f38f1cae63..f38f1cae63 100755..100644
--- a/media/res/bbb_g711mulaw_1ch_8khz.raw
+++ b/media/res/bbb_g711mulaw_1ch_8khz.raw
diff --git a/media/res/bbb_gsm_1ch_8khz_13kbps.info b/media/res/bbb_gsm_1ch_8khz_13kbps.info
index b15b296a27..b15b296a27 100755..100644
--- a/media/res/bbb_gsm_1ch_8khz_13kbps.info
+++ b/media/res/bbb_gsm_1ch_8khz_13kbps.info
diff --git a/media/res/bbb_gsm_1ch_8khz_13kbps.raw b/media/res/bbb_gsm_1ch_8khz_13kbps.raw
index df903a8d6e..df903a8d6e 100755..100644
--- a/media/res/bbb_gsm_1ch_8khz_13kbps.raw
+++ b/media/res/bbb_gsm_1ch_8khz_13kbps.raw
Binary files differ
diff --git a/media/res/bbb_hevc_176x144_176kbps_60fps.hevc b/media/res/bbb_hevc_176x144_176kbps_60fps.hevc
new file mode 100644
index 0000000000..f82236f3a0
--- /dev/null
+++ b/media/res/bbb_hevc_176x144_176kbps_60fps.hevc
Binary files 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
index 0000000000..702b853697
--- /dev/null
+++ b/media/res/bbb_hevc_176x144_176kbps_60fps.info
@@ -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
index 0000000000..d5290d70d3
--- /dev/null
+++ b/media/res/bbb_mpeg2_352x288_1mbps_60fps.info
@@ -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
index 0000000000..2f67c2b382
--- /dev/null
+++ b/media/res/bbb_mpeg2_352x288_1mbps_60fps.m2v
Binary files differ
diff --git a/media/res/bbb_opus_stereo_128kbps_48000hz.info b/media/res/bbb_opus_stereo_128kbps_48000hz.info
index 12a6b99652..12a6b99652 100755..100644
--- a/media/res/bbb_opus_stereo_128kbps_48000hz.info
+++ b/media/res/bbb_opus_stereo_128kbps_48000hz.info
diff --git a/media/res/bbb_opus_stereo_128kbps_48000hz.opus b/media/res/bbb_opus_stereo_128kbps_48000hz.opus
index 7b763b2c15..7b763b2c15 100755..100644
--- a/media/res/bbb_opus_stereo_128kbps_48000hz.opus
+++ b/media/res/bbb_opus_stereo_128kbps_48000hz.opus
Binary files differ
diff --git a/media/res/bbb_raw_1ch_8khz_s32le.info b/media/res/bbb_raw_1ch_8khz_s32le.info
index 933925beae..933925beae 100755..100644
--- a/media/res/bbb_raw_1ch_8khz_s32le.info
+++ b/media/res/bbb_raw_1ch_8khz_s32le.info
diff --git a/media/res/bbb_raw_1ch_8khz_s32le.raw b/media/res/bbb_raw_1ch_8khz_s32le.raw
index fd91b46219..fd91b46219 100755..100644
--- a/media/res/bbb_raw_1ch_8khz_s32le.raw
+++ b/media/res/bbb_raw_1ch_8khz_s32le.raw
Binary files differ
diff --git a/media/res/bbb_vorbis_stereo_128kbps_48000hz.info b/media/res/bbb_vorbis_stereo_128kbps_48000hz.info
index 0716643c50..0716643c50 100755..100644
--- a/media/res/bbb_vorbis_stereo_128kbps_48000hz.info
+++ b/media/res/bbb_vorbis_stereo_128kbps_48000hz.info
diff --git a/media/res/bbb_vorbis_stereo_128kbps_48000hz.vorbis b/media/res/bbb_vorbis_stereo_128kbps_48000hz.vorbis
index 404c5f8151..404c5f8151 100755..100644
--- a/media/res/bbb_vorbis_stereo_128kbps_48000hz.vorbis
+++ b/media/res/bbb_vorbis_stereo_128kbps_48000hz.vorbis
Binary files differ
diff --git a/media/res/bbb_vp8_176x144_240kbps_60fps.info b/media/res/bbb_vp8_176x144_240kbps_60fps.info
new file mode 100644
index 0000000000..559f42580b
--- /dev/null
+++ b/media/res/bbb_vp8_176x144_240kbps_60fps.info
@@ -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
index 0000000000..6eba56ccad
--- /dev/null
+++ b/media/res/bbb_vp8_176x144_240kbps_60fps.vp8
Binary files 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
index 0000000000..2f7d35bed2
--- /dev/null
+++ b/media/res/bbb_vp9_176x144_285kbps_60fps.info
@@ -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
index 0000000000..2633c8a6c4
--- /dev/null
+++ b/media/res/bbb_vp9_176x144_285kbps_60fps.vp9
Binary files differ
diff --git a/neuralnetworks/1.0/Android.bp b/neuralnetworks/1.0/Android.bp
new file mode 100644
index 0000000000..ba32d0c396
--- /dev/null
+++ b/neuralnetworks/1.0/Android.bp
@@ -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
index 0000000000..49c29674ee
--- /dev/null
+++ b/neuralnetworks/1.0/IDevice.hal
@@ -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
index 0000000000..ef0f4549dd
--- /dev/null
+++ b/neuralnetworks/1.0/IExecutionCallback.hal
@@ -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
index 0000000000..ee406fb79b
--- /dev/null
+++ b/neuralnetworks/1.0/IPreparedModel.hal
@@ -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
index 0000000000..fa1bf9d508
--- /dev/null
+++ b/neuralnetworks/1.0/IPreparedModelCallback.hal
@@ -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
index 0000000000..8779723d2f
--- /dev/null
+++ b/neuralnetworks/1.0/types.hal
@@ -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
index 0000000000..59e7c28b64
--- /dev/null
+++ b/neuralnetworks/1.0/vts/OWNERS
@@ -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
index 0000000000..e33ee77f12
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/Android.bp
@@ -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
index 0000000000..46bf24350f
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/Callbacks.cpp
@@ -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
index 0000000000..0e2ffb324a
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/Callbacks.h
@@ -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
index 0000000000..d740b5f53c
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
@@ -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
index 0000000000..8ce4f25938
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/Models.cpp
@@ -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
index 0000000000..e0d57d533b
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/Models.h
@@ -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
index 0000000000..b99e20e3b4
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.cpp
@@ -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
index 0000000000..5cd209ae62
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.h
@@ -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
index 0000000000..33f70ebae2
--- /dev/null
+++ b/neuralnetworks/Android.bp
@@ -0,0 +1,5 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+ "1.0",
+ "1.0/vts/functional",
+]
diff --git a/oemlock/1.0/vts/functional/Android.bp b/oemlock/1.0/vts/functional/Android.bp
index a13b3dc71d..20737a1808 100644
--- a/oemlock/1.0/vts/functional/Android.bp
+++ b/oemlock/1.0/vts/functional/Android.bp
@@ -16,21 +16,7 @@
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"],
}
diff --git a/power/1.1/default/Power.cpp b/power/1.1/default/Power.cpp
deleted file mode 100644
index b5d0c84bcc..0000000000
--- a/power/1.1/default/Power.cpp
+++ /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
index e779d64d37..0000000000
--- a/power/1.1/default/Power.h
+++ /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
index f2512f1b53..0000000000
--- a/power/1.1/default/android.hardware.power@1.1-service.rc
+++ /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
index 571db2f31c..0000000000
--- a/power/1.1/default/service.cpp
+++ /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;
-}
diff --git a/power/1.1/vts/functional/Android.bp b/power/1.1/vts/functional/Android.bp
index f886bd2c08..604cd36eef 100644
--- a/power/1.1/vts/functional/Android.bp
+++ b/power/1.1/vts/functional/Android.bp
@@ -16,19 +16,10 @@
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",
- ]
}
diff --git a/power/Android.bp b/power/Android.bp
index 7a315faab3..a5415df348 100644
--- a/power/Android.bp
+++ b/power/Android.bp
@@ -4,6 +4,5 @@ subdirs = [
"1.0/default",
"1.0/vts/functional",
"1.1",
- "1.1/default",
"1.1/vts/functional",
]
diff --git a/radio/1.0/IRadioResponse.hal b/radio/1.0/IRadioResponse.hal
index a94aac3352..27945cb07f 100644
--- a/radio/1.0/IRadioResponse.hal
+++ b/radio/1.0/IRadioResponse.hal
@@ -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);
@@ -1184,6 +1190,7 @@ interface IRadioResponse {
* RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
+ * RadioError:SIM_ABSENT
*/
oneway setSuppServiceNotificationsResponse(RadioResponseInfo info);
@@ -1210,6 +1217,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 +1239,7 @@ interface IRadioResponse {
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:INVALID_MODEM_STATE
+ * RadioError:SIM_ABSENT
*/
oneway deleteSmsOnSimResponse(RadioResponseInfo info);
@@ -1287,6 +1296,7 @@ interface IRadioResponse {
* RadioError:INVALID_ARGUMENTS
* RadioError:MODEM_ERR
* RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:SIM_ABSENT
*/
oneway sendEnvelopeResponse(RadioResponseInfo info, string commandResponse);
@@ -1304,6 +1314,7 @@ interface IRadioResponse {
* RadioError:CANCELLED
* RadioError:INVALID_MODEM_STATE
* RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:SIM_ABSENT
*/
oneway sendTerminalResponseToSimResponse(RadioResponseInfo info);
@@ -1321,6 +1332,7 @@ interface IRadioResponse {
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:SIM_ABSENT
*/
oneway handleStkCallSetupRequestFromSimResponse(RadioResponseInfo info);
@@ -1417,6 +1429,7 @@ interface IRadioResponse {
* RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
+ * RadioError:SIM_ABSENT
*/
oneway setLocationUpdatesResponse(RadioResponseInfo info);
@@ -1451,6 +1464,7 @@ interface IRadioResponse {
* RadioError:OPERATION_NOT_ALLOWED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
+ * RadioError:SIM_ABSENT
*/
oneway setCdmaRoamingPreferenceResponse(RadioResponseInfo info);
@@ -1469,6 +1483,7 @@ interface IRadioResponse {
* RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
+ * RadioError:SIM_ABSENT
*/
oneway getCdmaRoamingPreferenceResponse(RadioResponseInfo info, CdmaRoamingType type);
@@ -1615,6 +1630,7 @@ interface IRadioResponse {
* RadioError:ENCODING_ERR
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
+ * RadioError:SIM_ABSENT
*/
oneway sendCdmaSmsResponse(RadioResponseInfo info, SendSmsResult sms);
@@ -1792,6 +1808,7 @@ interface IRadioResponse {
* RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
+ * RadioError:SIM_ABSENT
*/
oneway getCDMASubscriptionResponse(RadioResponseInfo info, string mdn, string hSid,
string hNid, string min, string prl);
@@ -1819,6 +1836,7 @@ interface IRadioResponse {
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:INVALID_MODEM_STATE
+ * RadioError:SIM_ABSENT
*/
oneway writeSmsToRuimResponse(RadioResponseInfo info, uint32_t index);
@@ -1839,6 +1857,8 @@ interface IRadioResponse {
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:INVALID_MODEM_STATE
+ * RadioError:OPERATION_NOT_ALLOWED
+ * RadioError:SIM_ABSENT
*/
oneway deleteSmsOnRuimResponse(RadioResponseInfo info);
@@ -1884,6 +1904,7 @@ interface IRadioResponse {
* RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
+ * RadioError:SIM_ABSENT
*/
oneway exitEmergencyCallbackModeResponse(RadioResponseInfo info);
@@ -1906,6 +1927,7 @@ interface IRadioResponse {
* RadioError:OPERATION_NOT_ALLOWED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
+ * RadioError:SIM_ABSENT
*/
oneway getSmscAddressResponse(RadioResponseInfo info, string smsc);
@@ -1927,6 +1949,7 @@ interface IRadioResponse {
* RadioError:OPERATION_NOT_ALLOWED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
+ * RadioError:SIM_ABSENT
*/
oneway setSmscAddressResponse(RadioResponseInfo info);
@@ -1946,6 +1969,7 @@ interface IRadioResponse {
* RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
+ * RadioError:SIM_ABSENT
*/
oneway reportSmsMemoryStatusResponse(RadioResponseInfo info);
@@ -1976,6 +2000,7 @@ interface IRadioResponse {
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:SIM_ABSENT
*/
oneway getCdmaSubscriptionSourceResponse(RadioResponseInfo info, CdmaSubscriptionSource source);
@@ -1993,6 +2018,7 @@ interface IRadioResponse {
* RadioError:INVALID_MODEM_STATE
* RadioError:INVALID_ARGUMENTS
* RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:SIM_ABSENT
*/
oneway requestIsimAuthenticationResponse(RadioResponseInfo info, string response);
@@ -2024,6 +2050,7 @@ interface IRadioResponse {
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:SIM_ABSENT
*/
oneway sendEnvelopeWithStatusResponse(RadioResponseInfo info, IccIoResult iccIo);
@@ -2328,6 +2355,7 @@ interface IRadioResponse {
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:SIM_ABSENT
*/
oneway setDataProfileResponse(RadioResponseInfo info);
@@ -2414,6 +2442,7 @@ interface IRadioResponse {
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:SIM_ABSENT
*/
oneway stopLceServiceResponse(RadioResponseInfo info, LceStatusInfo statusInfo);
@@ -2430,6 +2459,7 @@ interface IRadioResponse {
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:SIM_ABSENT
*/
oneway pullLceDataResponse(RadioResponseInfo info, LceDataInfo lceInfo);
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_icc.cpp b/radio/1.0/vts/functional/radio_hidl_hal_icc.cpp
index 9e003e2d77..130064aa52 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_icc.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_icc.cpp
@@ -317,6 +317,7 @@ TEST_F(RadioHidlTest, getIccCardStatus) {
radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
radioRsp->rspInfo.error == RadioError::INVALID_SIM_STATE ||
radioRsp->rspInfo.error == RadioError::PASSWORD_INCORRECT ||
- radioRsp->rspInfo.error == RadioError::INTERNAL_ERR);
+ radioRsp->rspInfo.error == RadioError::INTERNAL_ERR ||
+ radioRsp->rspInfo.error == RadioError::SIM_ABSENT);
}
}
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_ims.cpp b/radio/1.0/vts/functional/radio_hidl_hal_ims.cpp
index c1834c5692..aa9d9871c9 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_ims.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_ims.cpp
@@ -155,7 +155,8 @@ TEST_F(RadioHidlTest, setSuppServiceNotifications) {
EXPECT_EQ(serial, radioRsp->rspInfo.serial);
if (cardStatus.cardState == CardState::ABSENT) {
- EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
+ ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE ||
+ radioRsp->rspInfo.error == RadioError::SIM_ABSENT);
}
}
@@ -173,7 +174,7 @@ TEST_F(RadioHidlTest, requestIsimAuthentication) {
EXPECT_EQ(serial, radioRsp->rspInfo.serial);
if (cardStatus.cardState == CardState::ABSENT) {
- ASSERT_TRUE(CheckGeneralError());
+ ASSERT_TRUE(CheckGeneralError() || radioRsp->rspInfo.error == RadioError::SIM_ABSENT);
}
}
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp b/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp
index 0507cc98f5..631dff3d1e 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp
@@ -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);
@@ -265,7 +265,8 @@ TEST_F(RadioHidlTest, setLocationUpdates) {
EXPECT_EQ(serial, radioRsp->rspInfo.serial);
if (cardStatus.cardState == CardState::ABSENT) {
- ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE);
+ ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE ||
+ radioRsp->rspInfo.error == RadioError::SIM_ABSENT);
}
}
@@ -282,7 +283,8 @@ TEST_F(RadioHidlTest, setCdmaRoamingPreference) {
if (cardStatus.cardState == CardState::ABSENT) {
ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE ||
- radioRsp->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+ radioRsp->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED ||
+ radioRsp->rspInfo.error == RadioError::SIM_ABSENT);
}
}
@@ -299,7 +301,8 @@ TEST_F(RadioHidlTest, getCdmaRoamingPreference) {
if (cardStatus.cardState == CardState::ABSENT) {
ASSERT_TRUE(CheckGeneralError() || radioRsp->rspInfo.error == RadioError::NONE ||
- radioRsp->rspInfo.error == RadioError::MODEM_ERR);
+ radioRsp->rspInfo.error == RadioError::MODEM_ERR ||
+ radioRsp->rspInfo.error == RadioError::SIM_ABSENT);
}
}
@@ -381,7 +384,9 @@ TEST_F(RadioHidlTest, getCDMASubscription) {
EXPECT_EQ(serial, radioRsp->rspInfo.serial);
if (cardStatus.cardState == CardState::ABSENT) {
- ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE);
+ ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE ||
+ radioRsp->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED ||
+ radioRsp->rspInfo.error == RadioError::SIM_ABSENT);
}
}
@@ -414,7 +419,9 @@ TEST_F(RadioHidlTest, exitEmergencyCallbackMode) {
EXPECT_EQ(serial, radioRsp->rspInfo.serial);
if (cardStatus.cardState == CardState::ABSENT) {
- ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE);
+ ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE ||
+ radioRsp->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED ||
+ radioRsp->rspInfo.error == RadioError::SIM_ABSENT);
}
}
@@ -430,7 +437,9 @@ TEST_F(RadioHidlTest, getCdmaSubscriptionSource) {
EXPECT_EQ(serial, radioRsp->rspInfo.serial);
if (cardStatus.cardState == CardState::ABSENT) {
- ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE);
+ ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE ||
+ radioRsp->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED ||
+ radioRsp->rspInfo.error == RadioError::SIM_ABSENT);
}
}
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_stk.cpp b/radio/1.0/vts/functional/radio_hidl_hal_stk.cpp
index f97f5febd6..c3f7549666 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_stk.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_stk.cpp
@@ -38,7 +38,8 @@ TEST_F(RadioHidlTest, sendEnvelope) {
ASSERT_TRUE(CheckGeneralError() ||
radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
radioRsp->rspInfo.error == RadioError::NONE ||
- radioRsp->rspInfo.error == RadioError::MODEM_ERR);
+ radioRsp->rspInfo.error == RadioError::MODEM_ERR ||
+ radioRsp->rspInfo.error == RadioError::SIM_ABSENT);
}
}
@@ -61,7 +62,8 @@ TEST_F(RadioHidlTest, sendTerminalResponseToSim) {
std::cout << static_cast<int>(radioRsp->rspInfo.error) << std::endl;
ASSERT_TRUE(CheckGeneralError() ||
radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
- radioRsp->rspInfo.error == RadioError::NONE);
+ radioRsp->rspInfo.error == RadioError::NONE ||
+ radioRsp->rspInfo.error == RadioError::SIM_ABSENT);
}
}
@@ -81,7 +83,8 @@ TEST_F(RadioHidlTest, handleStkCallSetupRequestFromSim) {
if (cardStatus.cardState == CardState::ABSENT) {
ASSERT_TRUE(CheckGeneralError() || radioRsp->rspInfo.error == RadioError::NONE ||
radioRsp->rspInfo.error == RadioError::MODEM_ERR ||
- radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS);
+ radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
+ radioRsp->rspInfo.error == RadioError::SIM_ABSENT);
}
}
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_voice.cpp b/radio/1.0/vts/functional/radio_hidl_hal_voice.cpp
index 8d6e200f27..1d2f199de0 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_voice.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_voice.cpp
@@ -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 ||
diff --git a/radio/1.1/IRadioResponse.hal b/radio/1.1/IRadioResponse.hal
index 4e7bf43dec..759602b004 100644
--- a/radio/1.1/IRadioResponse.hal
+++ b/radio/1.1/IRadioResponse.hal
@@ -16,6 +16,7 @@
package android.hardware.radio@1.1;
+import @1.0::RadioResponseInfo;
import @1.0::IRadioResponse;
/**
diff --git a/renderscript/1.0/vts/functional/Android.bp b/renderscript/1.0/vts/functional/Android.bp
index 5256c1f9da..bf011e6c17 100644
--- a/renderscript/1.0/vts/functional/Android.bp
+++ b/renderscript/1.0/vts/functional/Android.bp
@@ -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",
],
}
diff --git a/sensors/1.0/default/Android.bp b/sensors/1.0/default/Android.bp
index 75fe3df7e4..2485b058fb 100644
--- a/sensors/1.0/default/Android.bp
+++ b/sensors/1.0/default/Android.bp
@@ -38,6 +38,9 @@ cc_library_static {
"android.hardware.sensors@1.0",
],
local_include_dirs: ["include/sensors"],
+ export_shared_lib_headers: [
+ "libhardware",
+ ],
}
cc_binary {
diff --git a/soundtrigger/2.0/default/OWNERS b/soundtrigger/2.0/default/OWNERS
new file mode 100644
index 0000000000..6fdc97ca29
--- /dev/null
+++ b/soundtrigger/2.0/default/OWNERS
@@ -0,0 +1,3 @@
+elaurent@google.com
+krocard@google.com
+mnaganov@google.com
diff --git a/tetheroffload/config/1.0/vts/functional/Android.bp b/tetheroffload/config/1.0/vts/functional/Android.bp
index 2e720c6855..dc95eaa28d 100644
--- a/tetheroffload/config/1.0/vts/functional/Android.bp
+++ b/tetheroffload/config/1.0/vts/functional/Android.bp
@@ -14,20 +14,7 @@
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"],
}
diff --git a/tetheroffload/config/1.0/vts/functional/VtsHalTetheroffloadConfigV1_0TargetTest.cpp b/tetheroffload/config/1.0/vts/functional/VtsHalTetheroffloadConfigV1_0TargetTest.cpp
index fc61e1c1c0..2cbe479dc9 100644
--- a/tetheroffload/config/1.0/vts/functional/VtsHalTetheroffloadConfigV1_0TargetTest.cpp
+++ b/tetheroffload/config/1.0/vts/functional/VtsHalTetheroffloadConfigV1_0TargetTest.cpp
@@ -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());
diff --git a/tetheroffload/control/1.0/vts/functional/Android.bp b/tetheroffload/control/1.0/vts/functional/Android.bp
index 69fac6e57f..c6216a2f97 100644
--- a/tetheroffload/control/1.0/vts/functional/Android.bp
+++ b/tetheroffload/control/1.0/vts/functional/Android.bp
@@ -14,21 +14,10 @@
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",
],
}
diff --git a/tetheroffload/control/1.0/vts/functional/VtsHalTetheroffloadControlV1_0TargetTest.cpp b/tetheroffload/control/1.0/vts/functional/VtsHalTetheroffloadControlV1_0TargetTest.cpp
index 3059eac0c2..c009af5d91 100644
--- a/tetheroffload/control/1.0/vts/functional/VtsHalTetheroffloadControlV1_0TargetTest.cpp
+++ b/tetheroffload/control/1.0/vts/functional/VtsHalTetheroffloadControlV1_0TargetTest.cpp
@@ -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,29 @@ TEST_F(OffloadControlHidlTestBase, AdditionalInitsWithoutStopReturnFalse) {
initOffload(false);
initOffload(false);
initOffload(false);
- stopOffload(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);
+ // Call setUpstreamParameters() so that "offload" can be reasonably said
+ // to be both requested and operational.
+ const hidl_string v4Addr("192.0.0.2");
+ const hidl_string v4Gw("192.0.0.1");
+ const vector<hidl_string> v6Gws{hidl_string("fe80::db8:1"), hidl_string("fe80::db8:2")};
+ const Return<void> upstream =
+ control->setUpstreamParameters("rmnet_data0", v4Addr, v4Gw, v6Gws, ASSERT_TRUE_CALLBACK);
+ EXPECT_TRUE(upstream.isOk());
+ 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 +334,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 +609,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.
diff --git a/thermal/1.1/Android.bp b/thermal/1.1/Android.bp
new file mode 100644
index 0000000000..0985d947b6
--- /dev/null
+++ b/thermal/1.1/Android.bp
@@ -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
index 0000000000..059ac8bde7
--- /dev/null
+++ b/thermal/1.1/Android.mk
@@ -0,0 +1,65 @@
+# 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 \
+
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_JAVA_LIBRARIES += core-oj hwbinder
+
+#
+# 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 $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/thermal/1.1/IThermal.hal b/thermal/1.1/IThermal.hal
new file mode 100644
index 0000000000..14f35baa00
--- /dev/null
+++ b/thermal/1.1/IThermal.hal
@@ -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
index 0000000000..f418ec3dd4
--- /dev/null
+++ b/thermal/1.1/IThermalCallback.hal
@@ -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
index 0000000000..f5f01faf2c
--- /dev/null
+++ b/thermal/1.1/vts/functional/Android.bp
@@ -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
index 0000000000..6c1599bdb2
--- /dev/null
+++ b/thermal/1.1/vts/functional/VtsHalThermalV1_1TargetTest.cpp
@@ -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;
+}
diff --git a/thermal/Android.bp b/thermal/Android.bp
index ed19a37034..a5415df348 100644
--- a/thermal/Android.bp
+++ b/thermal/Android.bp
@@ -3,4 +3,6 @@ subdirs = [
"1.0",
"1.0/default",
"1.0/vts/functional",
+ "1.1",
+ "1.1/vts/functional",
]
diff --git a/usb/1.1/vts/functional/Android.bp b/usb/1.1/vts/functional/Android.bp
index 820f794bfc..4bb3203695 100644
--- a/usb/1.1/vts/functional/Android.bp
+++ b/usb/1.1/vts/functional/Android.bp
@@ -16,23 +16,11 @@
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",
- ],
}
diff --git a/vibrator/1.1/vts/functional/Android.bp b/vibrator/1.1/vts/functional/Android.bp
index 5baa8ed74a..4f6454b6c1 100644
--- a/vibrator/1.1/vts/functional/Android.bp
+++ b/vibrator/1.1/vts/functional/Android.bp
@@ -16,19 +16,11 @@
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",
- ],
}
diff --git a/weaver/1.0/vts/functional/Android.bp b/weaver/1.0/vts/functional/Android.bp
index 9b0ff6df31..0089d89053 100644
--- a/weaver/1.0/vts/functional/Android.bp
+++ b/weaver/1.0/vts/functional/Android.bp
@@ -16,21 +16,7 @@
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"],
}
diff --git a/wifi/1.0/README-NAN.md b/wifi/1.0/README-NAN.md
new file mode 100644
index 0000000000..f4b3320e33
--- /dev/null
+++ b/wifi/1.0/README-NAN.md
@@ -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
+
diff --git a/wifi/1.0/types.hal b/wifi/1.0/types.hal
index 1b5f8f7dad..b9fb0bded9 100644
--- a/wifi/1.0/types.hal
+++ b/wifi/1.0/types.hal
@@ -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;
/**
diff --git a/wifi/1.1/default/OWNERS b/wifi/1.1/default/OWNERS
new file mode 100644
index 0000000000..2878acc7fd
--- /dev/null
+++ b/wifi/1.1/default/OWNERS
@@ -0,0 +1,2 @@
+rpius@google.com
+quiche@google.com
diff --git a/wifi/1.1/default/hidl_return_util.h b/wifi/1.1/default/hidl_return_util.h
index 2f95c23d7e..f36c8bda8a 100644
--- a/wifi/1.1/default/hidl_return_util.h
+++ b/wifi/1.1/default/hidl_return_util.h
@@ -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>
diff --git a/wifi/1.1/default/wifi.cpp b/wifi/1.1/default/wifi.cpp
index 8456b90e9f..c46ef950e9 100644
--- a/wifi/1.1/default/wifi.cpp
+++ b/wifi/1.1/default/wifi.cpp
@@ -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);
diff --git a/wifi/1.1/default/wifi.h b/wifi/1.1/default/wifi.h
index 1ade2d8b9b..3a64cbd490 100644
--- a/wifi/1.1/default/wifi.h
+++ b/wifi/1.1/default/wifi.h
@@ -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.
diff --git a/wifi/1.1/default/wifi_legacy_hal.cpp b/wifi/1.1/default/wifi_legacy_hal.cpp
index 7d683d3fe9..36da6e5351 100644
--- a/wifi/1.1/default/wifi_legacy_hal.cpp
+++ b/wifi/1.1/default/wifi_legacy_hal.cpp
@@ -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;
}
diff --git a/wifi/1.1/default/wifi_legacy_hal.h b/wifi/1.1/default/wifi_legacy_hal.h
index caa1bd50fc..549880398f 100644
--- a/wifi/1.1/default/wifi_legacy_hal.h
+++ b/wifi/1.1/default/wifi_legacy_hal.h
@@ -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_;
diff --git a/wifi/1.1/vts/functional/Android.bp b/wifi/1.1/vts/functional/Android.bp
index 6b0baf7851..1b0c12d68b 100644
--- a/wifi/1.1/vts/functional/Android.bp
+++ b/wifi/1.1/vts/functional/Android.bp
@@ -16,24 +16,13 @@
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
index 0000000000..2878acc7fd
--- /dev/null
+++ b/wifi/1.1/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+rpius@google.com
+quiche@google.com
diff --git a/wifi/Android.bp b/wifi/Android.bp
index b4ab98ffef..1153b0c628 100644
--- a/wifi/Android.bp
+++ b/wifi/Android.bp
@@ -7,4 +7,5 @@ subdirs = [
"offload/1.0",
"offload/1.0/vts/functional",
"supplicant/1.0",
+ "supplicant/1.0/vts/functional",
]
diff --git a/wifi/offload/1.0/vts/functional/Android.bp b/wifi/offload/1.0/vts/functional/Android.bp
index f907a89559..140e45e2d3 100644
--- a/wifi/offload/1.0/vts/functional/Android.bp
+++ b/wifi/offload/1.0/vts/functional/Android.bp
@@ -16,21 +16,7 @@
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"],
}
diff --git a/wifi/supplicant/1.0/vts/functional/Android.bp b/wifi/supplicant/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000000..24b9f6f71f
--- /dev/null
+++ b/wifi/supplicant/1.0/vts/functional/Android.bp
@@ -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
index c6e39503d4..0000000000
--- a/wifi/supplicant/1.0/vts/functional/Android.mk
+++ /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)
-