diff --git a/audio/7.0/IStreamOut.hal b/audio/7.0/IStreamOut.hal index 359dce4ca13e683afa2912a462825ee1419b3705..6e8498e30695c284074ae287e2f0012d4402b1cb 100644 --- a/audio/7.0/IStreamOut.hal +++ b/audio/7.0/IStreamOut.hal @@ -286,8 +286,6 @@ interface IStreamOut extends IStream { * timestamp must correspond to N rather than N+M. The terms 'recent' and * 'small' are not defined. They reflect the quality of the implementation. * - * Optional method - * * @return retval operation completion status. * @return frames count of presented audio frames. * @return timeStamp associated clock time. diff --git a/audio/7.0/config/api/current.txt b/audio/7.0/config/api/current.txt index c2585bd8b0bc6808166b64200bdce8426931e2a5..3716cf0ea0052a2d7023beefd701e28cf9445d1a 100644 --- a/audio/7.0/config/api/current.txt +++ b/audio/7.0/config/api/current.txt @@ -276,6 +276,7 @@ package android.audio.policy.configuration.V7_0 { enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_DIRECT; enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_DIRECT_PCM; enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_FAST; + enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD; enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_HW_AV_SYNC; enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO; enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_INCALL_MUSIC; diff --git a/audio/7.0/config/audio_policy_configuration.xsd b/audio/7.0/config/audio_policy_configuration.xsd index e0df3599c7be1a694d809c9e8b3d83f4a35cff2f..7f7fb61f4dd42d5d8f5e80b6774930c2a1727a6a 100644 --- a/audio/7.0/config/audio_policy_configuration.xsd +++ b/audio/7.0/config/audio_policy_configuration.xsd @@ -177,6 +177,7 @@ + diff --git a/audio/core/all-versions/default/Android.bp b/audio/core/all-versions/default/Android.bp index 27ec17cd23b06031bc356408173f58478f770f63..8fb7111fbf4fab17f93178b854ed6e3ea0f023ad 100644 --- a/audio/core/all-versions/default/Android.bp +++ b/audio/core/all-versions/default/Android.bp @@ -59,6 +59,7 @@ cc_defaults { "libaudio_system_headers", "libhardware_headers", "libmedia_headers", + "libmediautils_headers", ], export_header_lib_headers: [ diff --git a/audio/core/all-versions/default/StreamIn.cpp b/audio/core/all-versions/default/StreamIn.cpp index 17621a9acf4e6e5c4f02ae50e5b1484e486a96a9..2aeee43c59a7f30f99aaaaf0b051893605c5d629 100644 --- a/audio/core/all-versions/default/StreamIn.cpp +++ b/audio/core/all-versions/default/StreamIn.cpp @@ -412,9 +412,9 @@ Return StreamIn::prepareForReading(uint32_t frameSize, uint32_t framesCoun } // Create and launch the thread. - sp tempReadThread = - new ReadThread(&mStopReadThread, mStream, tempCommandMQ.get(), tempDataMQ.get(), - tempStatusMQ.get(), tempElfGroup.get()); + auto tempReadThread = + sp::make(&mStopReadThread, mStream, tempCommandMQ.get(), tempDataMQ.get(), + tempStatusMQ.get(), tempElfGroup.get()); if (!tempReadThread->init()) { ALOGW("failed to start reader thread: %s", strerror(-status)); sendError(Result::INVALID_ARGUMENTS); diff --git a/audio/core/all-versions/default/StreamOut.cpp b/audio/core/all-versions/default/StreamOut.cpp index c23922dbb631c325f06aeaa2765b548f791dfda8..d027231f118099ac0eb8f19a90fc696b497aac73 100644 --- a/audio/core/all-versions/default/StreamOut.cpp +++ b/audio/core/all-versions/default/StreamOut.cpp @@ -164,7 +164,7 @@ StreamOut::~StreamOut() { status_t status = EventFlag::deleteEventFlag(&mEfGroup); ALOGE_IF(status, "write MQ event flag deletion error: %s", strerror(-status)); } - mCallback.clear(); + mCallback = nullptr; #if MAJOR_VERSION <= 5 mDevice->closeOutputStream(mStream); // Closing the output stream in the HAL waits for the callback to finish, @@ -398,9 +398,9 @@ Return StreamOut::prepareForWriting(uint32_t frameSize, uint32_t framesCou } // Create and launch the thread. - sp tempWriteThread = - new WriteThread(&mStopWriteThread, mStream, tempCommandMQ.get(), tempDataMQ.get(), - tempStatusMQ.get(), tempElfGroup.get()); + auto tempWriteThread = + sp::make(&mStopWriteThread, mStream, tempCommandMQ.get(), tempDataMQ.get(), + tempStatusMQ.get(), tempElfGroup.get()); if (!tempWriteThread->init()) { ALOGW("failed to start writer thread: %s", strerror(-status)); sendError(Result::INVALID_ARGUMENTS); @@ -463,7 +463,7 @@ Return StreamOut::setCallback(const sp& callback) { Return StreamOut::clearCallback() { if (mStream->set_callback == NULL) return Result::NOT_SUPPORTED; - mCallback.clear(); + mCallback = nullptr; return Result::OK; } @@ -478,7 +478,7 @@ int StreamOut::asyncCallback(stream_callback_event_t event, void*, void* cookie) // It's correct to hold an sp<> to callback because the reference // in the StreamOut instance can be cleared in the meantime. There is // no difference on which thread to run IStreamOutCallback's destructor. - sp callback = self->mCallback; + sp callback = self->mCallback.load(); if (callback.get() == nullptr) return 0; ALOGV("asyncCallback() event %d", event); Return result; @@ -736,7 +736,7 @@ Return StreamOut::setEventCallback(const sp& ca // static int StreamOut::asyncEventCallback(stream_event_callback_type_t event, void* param, void* cookie) { StreamOut* self = reinterpret_cast(cookie); - sp eventCallback = self->mEventCallback; + sp eventCallback = self->mEventCallback.load(); if (eventCallback.get() == nullptr) return 0; ALOGV("%s event %d", __func__, event); Return result; diff --git a/audio/core/all-versions/default/include/core/default/StreamOut.h b/audio/core/all-versions/default/include/core/default/StreamOut.h index ccc1c1a3f81b0644d975d4c3559de1ad63491d4c..0b07972810c3e8b550d92707f5c9fdd661a96cdb 100644 --- a/audio/core/all-versions/default/include/core/default/StreamOut.h +++ b/audio/core/all-versions/default/include/core/default/StreamOut.h @@ -29,6 +29,7 @@ #include #include #include +#include #include namespace android { @@ -158,9 +159,9 @@ struct StreamOut : public IStreamOut { audio_stream_out_t* mStream; const sp mStreamCommon; const sp> mStreamMmap; - sp mCallback; // Callback for non-blocking write and drain + mediautils::atomic_sp mCallback; // for non-blocking write and drain #if MAJOR_VERSION >= 6 - sp mEventCallback; + mediautils::atomic_sp mEventCallback; #endif std::unique_ptr mCommandMQ; std::unique_ptr mDataMQ; diff --git a/audio/core/all-versions/default/util/CoreUtils.cpp b/audio/core/all-versions/default/util/CoreUtils.cpp index 14f76f3c65ecf67e02bb8ddb3c6a6f004537e9c9..773be21962aa0064985834be2d3d44c4ab340dfe 100644 --- a/audio/core/all-versions/default/util/CoreUtils.cpp +++ b/audio/core/all-versions/default/util/CoreUtils.cpp @@ -66,13 +66,13 @@ status_t CoreUtils::microphoneInfoFromHal( CONVERT_CHECKED( deviceAddressFromHal(halMicInfo.device, halMicInfo.address, &micInfo->deviceAddress), result); - size_t chCount; - for (chCount = 0; chCount < AUDIO_CHANNEL_COUNT_MAX; ++chCount) { - if (halMicInfo.channel_mapping[chCount] == AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED) { + int chCount; + for (chCount = AUDIO_CHANNEL_COUNT_MAX - 1; chCount >= 0; --chCount) { + if (halMicInfo.channel_mapping[chCount] != AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED) { break; } } - micInfo->channelMapping.resize(chCount); + micInfo->channelMapping.resize(chCount + 1); for (size_t ch = 0; ch < micInfo->channelMapping.size(); ch++) { micInfo->channelMapping[ch] = AudioMicrophoneChannelMapping(halMicInfo.channel_mapping[ch]); } diff --git a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp index 28bcd0b7138103486a5ac7b0947ea71dfac3299b..787654bdd3fc741031ac987fc91517c3f92b473d 100644 --- a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp +++ b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp @@ -332,18 +332,21 @@ TEST_P(AudioPrimaryHidlTest, setMode) { #endif for (int mode : {-2, -1, maxMode + 1}) { - ASSERT_RESULT(Result::INVALID_ARGUMENTS, getDevice()->setMode(AudioMode(mode))) + EXPECT_RESULT(Result::INVALID_ARGUMENTS, getDevice()->setMode(AudioMode(mode))) << "mode=" << mode; } - // Test valid values - for (AudioMode mode : {AudioMode::IN_CALL, AudioMode::IN_COMMUNICATION, AudioMode::RINGTONE, - AudioMode::NORMAL /* Make sure to leave the test in normal mode */}) { - ASSERT_OK(getDevice()->setMode(mode)) << "mode=" << toString(mode); - } + // AudioMode::CALL_SCREEN as support is optional #if MAJOR_VERSION >= 6 - ASSERT_RESULT(okOrNotSupportedOrInvalidArgs, getDevice()->setMode(AudioMode::CALL_SCREEN)); + EXPECT_RESULT(okOrNotSupportedOrInvalidArgs, getDevice()->setMode(AudioMode::CALL_SCREEN)); #endif + // Test valid values + for (AudioMode mode : {AudioMode::IN_CALL, AudioMode::IN_COMMUNICATION, AudioMode::RINGTONE, + AudioMode::NORMAL}) { + EXPECT_OK(getDevice()->setMode(mode)) << "mode=" << toString(mode); + } + // Make sure to leave the test in normal mode + getDevice()->setMode(AudioMode::NORMAL); } TEST_P(AudioPrimaryHidlTest, setBtHfpSampleRate) { diff --git a/audio/core/all-versions/vts/functional/Android.bp b/audio/core/all-versions/vts/functional/Android.bp index 91831912dd72c98fb1ef26b7e5355d332944321d..e446a7f2cf68cf6c81eae1f43e9742a995211745 100644 --- a/audio/core/all-versions/vts/functional/Android.bp +++ b/audio/core/all-versions/vts/functional/Android.bp @@ -28,11 +28,13 @@ cc_defaults { defaults: ["VtsHalTargetTestDefaults"], static_libs: [ "android.hardware.audio.common.test.utility", - "libxml2", + "audioclient-types-aidl-cpp", + "libaudioclient_aidl_conversion", ], shared_libs: [ "libbinder", "libfmq", + "libxml2", ], header_libs: [ "android.hardware.audio.common.util@all-versions", diff --git a/authsecret/aidl/Android.bp b/authsecret/aidl/Android.bp index 8fe9f27d7e601b96ce6c75980436bb183afc616d..432c1b97c3fae733dc97f861799b01b5cbfb1d29 100644 --- a/authsecret/aidl/Android.bp +++ b/authsecret/aidl/Android.bp @@ -22,4 +22,5 @@ aidl_interface { }, }, }, + versions: ["1"], } diff --git a/authsecret/aidl/aidl_api/android.hardware.authsecret/1/.hash b/authsecret/aidl/aidl_api/android.hardware.authsecret/1/.hash new file mode 100644 index 0000000000000000000000000000000000000000..4a5c24a154c8ef97b6f70c35f2b94695dcbebe5f --- /dev/null +++ b/authsecret/aidl/aidl_api/android.hardware.authsecret/1/.hash @@ -0,0 +1 @@ +729cca96cb4732246b6ed1b3d15e2cbe63413afd diff --git a/authsecret/aidl/aidl_api/android.hardware.authsecret/1/android/hardware/authsecret/IAuthSecret.aidl b/authsecret/aidl/aidl_api/android.hardware.authsecret/1/android/hardware/authsecret/IAuthSecret.aidl new file mode 100644 index 0000000000000000000000000000000000000000..76b96f284da4acdbc99c3bdebd28e41d59b9d100 --- /dev/null +++ b/authsecret/aidl/aidl_api/android.hardware.authsecret/1/android/hardware/authsecret/IAuthSecret.aidl @@ -0,0 +1,38 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.authsecret; +@VintfStability +interface IAuthSecret { + oneway void setPrimaryUserCredential(in byte[] secret); +} diff --git a/automotive/OWNERS b/automotive/OWNERS index fb3e3d63bf584729d1c9bcb872793412b9215fc6..43c5f3e30e8f83629ba1058dd3b619e9f5ccce82 100644 --- a/automotive/OWNERS +++ b/automotive/OWNERS @@ -1,6 +1,6 @@ pirozzoj@google.com twasilczyk@google.com -pfg@google.com +krachuri@google.com gurunagarajan@google.com keunyoung@google.com felipeal@google.com diff --git a/automotive/audiocontrol/1.0/vts/functional/VtsHalAudioControlV1_0TargetTest.cpp b/automotive/audiocontrol/1.0/vts/functional/VtsHalAudioControlV1_0TargetTest.cpp index de1ec020729a80e927647ecce528335d19befb00..982cf2c358ded3eadca0a0fb511a7d009d84c0ca 100644 --- a/automotive/audiocontrol/1.0/vts/functional/VtsHalAudioControlV1_0TargetTest.cpp +++ b/automotive/audiocontrol/1.0/vts/functional/VtsHalAudioControlV1_0TargetTest.cpp @@ -140,6 +140,7 @@ TEST_P(CarAudioControlHidlTest, ContextMapping) { EXPECT_EQ(bus, -1); } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CarAudioControlHidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, CarAudioControlHidlTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames(IAudioControl::descriptor)), diff --git a/automotive/audiocontrol/2.0/vts/functional/VtsHalAudioControlV2_0TargetTest.cpp b/automotive/audiocontrol/2.0/vts/functional/VtsHalAudioControlV2_0TargetTest.cpp index 0c106647c579f1be5d3611cda75b18315b653649..fa351430e30d37f3b922a1286bc011ea683f568a 100644 --- a/automotive/audiocontrol/2.0/vts/functional/VtsHalAudioControlV2_0TargetTest.cpp +++ b/automotive/audiocontrol/2.0/vts/functional/VtsHalAudioControlV2_0TargetTest.cpp @@ -149,6 +149,7 @@ TEST_P(CarAudioControlHidlTest, FocusChangeExercise) { AudioFocusChange::GAIN_TRANSIENT | 0); }; +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CarAudioControlHidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, CarAudioControlHidlTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames(IAudioControl::descriptor)), diff --git a/automotive/audiocontrol/aidl/Android.bp b/automotive/audiocontrol/aidl/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..4acfd82d6a8f8b3846e403c740810b8a272f8023 --- /dev/null +++ b/automotive/audiocontrol/aidl/Android.bp @@ -0,0 +1,23 @@ +// This is the expected build file, but it may not be right in all cases + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +aidl_interface { + name: "android.hardware.automotive.audiocontrol", + vendor_available: true, + srcs: ["android/hardware/automotive/audiocontrol/*.aidl"], + stability: "vintf", + backend: { + java: { + sdk_version: "module_current", + }, + }, + versions: ["1"], +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/1/.hash b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/1/.hash new file mode 100644 index 0000000000000000000000000000000000000000..c4bb36b470ce456f21abaf74ec19c46b9ecba67c --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/1/.hash @@ -0,0 +1 @@ +ba2a7caca61683385b3b100e4faab1b4139fc547 diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/1/android/hardware/automotive/audiocontrol/AudioFocusChange.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/1/android/hardware/automotive/audiocontrol/AudioFocusChange.aidl new file mode 100644 index 0000000000000000000000000000000000000000..58a36673cdec15b46f0c2234f8f53ee3cc67ad9f --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/1/android/hardware/automotive/audiocontrol/AudioFocusChange.aidl @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@Backing(type="int") @VintfStability +enum AudioFocusChange { + NONE = 0, + GAIN = 1, + GAIN_TRANSIENT = 2, + GAIN_TRANSIENT_MAY_DUCK = 3, + GAIN_TRANSIENT_EXCLUSIVE = 4, + LOSS = -1, + LOSS_TRANSIENT = -2, + LOSS_TRANSIENT_CAN_DUCK = -3, +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/1/android/hardware/automotive/audiocontrol/DuckingInfo.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/1/android/hardware/automotive/audiocontrol/DuckingInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..a0f7db97ad70f2c98a41290056aff11227c6a624 --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/1/android/hardware/automotive/audiocontrol/DuckingInfo.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@VintfStability +parcelable DuckingInfo { + int zoneId; + String[] deviceAddressesToDuck; + String[] deviceAddressesToUnduck; + String[] usagesHoldingFocus; +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/1/android/hardware/automotive/audiocontrol/IAudioControl.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/1/android/hardware/automotive/audiocontrol/IAudioControl.aidl new file mode 100644 index 0000000000000000000000000000000000000000..c10713d0ec52f1f23268f42eef6b86f15be8f3cf --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/1/android/hardware/automotive/audiocontrol/IAudioControl.aidl @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@VintfStability +interface IAudioControl { + oneway void onAudioFocusChange(in String usage, in int zoneId, in android.hardware.automotive.audiocontrol.AudioFocusChange focusChange); + oneway void onDevicesToDuckChange(in android.hardware.automotive.audiocontrol.DuckingInfo[] duckingInfos); + oneway void onDevicesToMuteChange(in android.hardware.automotive.audiocontrol.MutingInfo[] mutingInfos); + oneway void registerFocusListener(in android.hardware.automotive.audiocontrol.IFocusListener listener); + oneway void setBalanceTowardRight(in float value); + oneway void setFadeTowardFront(in float value); +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/1/android/hardware/automotive/audiocontrol/IFocusListener.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/1/android/hardware/automotive/audiocontrol/IFocusListener.aidl new file mode 100644 index 0000000000000000000000000000000000000000..046c19d930023ffc6f2e3e093722445afa6eeca0 --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/1/android/hardware/automotive/audiocontrol/IFocusListener.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@VintfStability +interface IFocusListener { + oneway void abandonAudioFocus(in String usage, in int zoneId); + oneway void requestAudioFocus(in String usage, in int zoneId, in android.hardware.automotive.audiocontrol.AudioFocusChange focusGain); +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/1/android/hardware/automotive/audiocontrol/MutingInfo.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/1/android/hardware/automotive/audiocontrol/MutingInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..b25ed0f1e92e6daba4e8ee50967b221e117cc124 --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/1/android/hardware/automotive/audiocontrol/MutingInfo.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@VintfStability +parcelable MutingInfo { + int zoneId; + String[] deviceAddressesToMute; + String[] deviceAddressesToUnmute; +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioFocusChange.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioFocusChange.aidl new file mode 100644 index 0000000000000000000000000000000000000000..3dc393a5805e8f04eade7c6f89b02e9ae17ff945 --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioFocusChange.aidl @@ -0,0 +1,29 @@ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL interface (or parcelable). Do not try to +// edit this file. It looks like you are doing that because you have modified +// an AIDL interface in a backward-incompatible way, e.g., deleting a function +// from an interface or a field from a parcelable and it broke the build. That +// breakage is intended. +// +// You must not make a backward incompatible changes to the AIDL files built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@Backing(type="int") @VintfStability +enum AudioFocusChange { + NONE = 0, + GAIN = 1, + GAIN_TRANSIENT = 2, + GAIN_TRANSIENT_MAY_DUCK = 3, + GAIN_TRANSIENT_EXCLUSIVE = 4, + LOSS = -1, + LOSS_TRANSIENT = -2, + LOSS_TRANSIENT_CAN_DUCK = -3, +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/DuckingInfo.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/DuckingInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..6d729e22058319e6c236a327af5d0deccc97c193 --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/DuckingInfo.aidl @@ -0,0 +1,25 @@ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL interface (or parcelable). Do not try to +// edit this file. It looks like you are doing that because you have modified +// an AIDL interface in a backward-incompatible way, e.g., deleting a function +// from an interface or a field from a parcelable and it broke the build. That +// breakage is intended. +// +// You must not make a backward incompatible changes to the AIDL files built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@VintfStability +parcelable DuckingInfo { + int zoneId; + String[] deviceAddressesToDuck; + String[] deviceAddressesToUnduck; + String[] usagesHoldingFocus; +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IAudioControl.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IAudioControl.aidl new file mode 100644 index 0000000000000000000000000000000000000000..bc4162bc8bc8d8e149f341d93cbc0db3ba874133 --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IAudioControl.aidl @@ -0,0 +1,27 @@ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL interface (or parcelable). Do not try to +// edit this file. It looks like you are doing that because you have modified +// an AIDL interface in a backward-incompatible way, e.g., deleting a function +// from an interface or a field from a parcelable and it broke the build. That +// breakage is intended. +// +// You must not make a backward incompatible changes to the AIDL files built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@VintfStability +interface IAudioControl { + oneway void onAudioFocusChange(in String usage, in int zoneId, in android.hardware.automotive.audiocontrol.AudioFocusChange focusChange); + oneway void onDevicesToDuckChange(in android.hardware.automotive.audiocontrol.DuckingInfo[] duckingInfos); + oneway void onDevicesToMuteChange(in android.hardware.automotive.audiocontrol.MutingInfo[] mutingInfos); + oneway void registerFocusListener(in android.hardware.automotive.audiocontrol.IFocusListener listener); + oneway void setBalanceTowardRight(in float value); + oneway void setFadeTowardFront(in float value); +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IFocusListener.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IFocusListener.aidl new file mode 100644 index 0000000000000000000000000000000000000000..f00f042a0217530d8d08061d4364e513b3d7f762 --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IFocusListener.aidl @@ -0,0 +1,23 @@ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL interface (or parcelable). Do not try to +// edit this file. It looks like you are doing that because you have modified +// an AIDL interface in a backward-incompatible way, e.g., deleting a function +// from an interface or a field from a parcelable and it broke the build. That +// breakage is intended. +// +// You must not make a backward incompatible changes to the AIDL files built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@VintfStability +interface IFocusListener { + oneway void abandonAudioFocus(in String usage, in int zoneId); + oneway void requestAudioFocus(in String usage, in int zoneId, in android.hardware.automotive.audiocontrol.AudioFocusChange focusGain); +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/MutingInfo.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/MutingInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..ab902ec97199390188481044af0c04979840a79a --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/MutingInfo.aidl @@ -0,0 +1,24 @@ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL interface (or parcelable). Do not try to +// edit this file. It looks like you are doing that because you have modified +// an AIDL interface in a backward-incompatible way, e.g., deleting a function +// from an interface or a field from a parcelable and it broke the build. That +// breakage is intended. +// +// You must not make a backward incompatible changes to the AIDL files built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@VintfStability +parcelable MutingInfo { + int zoneId; + String[] deviceAddressesToMute; + String[] deviceAddressesToUnmute; +} diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioFocusChange.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioFocusChange.aidl new file mode 100644 index 0000000000000000000000000000000000000000..98fa4e83e3eb972741c326f7704dc94bd431ba4f --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioFocusChange.aidl @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.automotive.audiocontrol; + +/** + * Changes in audio focus that can be experienced + */ +@VintfStability +@Backing(type="int") +enum AudioFocusChange { + NONE = 0, + GAIN = 1, + GAIN_TRANSIENT = 2, + GAIN_TRANSIENT_MAY_DUCK = 3, + GAIN_TRANSIENT_EXCLUSIVE = 4, + LOSS = -1 * GAIN, + LOSS_TRANSIENT = -1 * GAIN_TRANSIENT, + LOSS_TRANSIENT_CAN_DUCK = -1 * GAIN_TRANSIENT_MAY_DUCK, +} \ No newline at end of file diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/DuckingInfo.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/DuckingInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..e95fe9bb2e7c8c97ef9d299d0c780c53d5faf6a2 --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/DuckingInfo.aidl @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + package android.hardware.automotive.audiocontrol; + + /** + * The current ducking information for a single audio zone. + * + *

This includes devices to duck, as well as unduck based on the contents of a previous + * {@link DuckingInfo}. Additionally, the current usages holding focus in the specified zone are + * included, which were used to determine which addresses to duck. + */ + @VintfStability + parcelable DuckingInfo { + /** + * ID of the associated audio zone + */ + int zoneId; + + /** + * List of addresses for audio output devices that should be ducked. + * + *

The provided address strings are defined in audio_policy_configuration.xml. + */ + String[] deviceAddressesToDuck; + + /** + * List of addresses for audio output devices that were previously be ducked and should now be + * unducked. + * + *

The provided address strings are defined in audio_policy_configuration.xml. + */ + String[] deviceAddressesToUnduck; + + /** + * List of usages currently holding focus for this audio zone. + * + *

See {@code audioUsage} in audio_policy_configuration.xsd for the list of allowed values. + */ + String[] usagesHoldingFocus; + } \ No newline at end of file diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IAudioControl.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IAudioControl.aidl new file mode 100644 index 0000000000000000000000000000000000000000..3a0224557ff79d27364e241bea075dc41846fede --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IAudioControl.aidl @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.automotive.audiocontrol; + +import android.hardware.automotive.audiocontrol.AudioFocusChange; +import android.hardware.automotive.audiocontrol.DuckingInfo; +import android.hardware.automotive.audiocontrol.MutingInfo; +import android.hardware.automotive.audiocontrol.IFocusListener; + +/** + * Interacts with the car's audio subsystem to manage audio sources and volumes + */ +@VintfStability +interface IAudioControl { + /** + * Notifies HAL of changes in audio focus status for focuses requested or abandoned by the HAL. + * + * This will be called in response to IFocusListener's requestAudioFocus and + * abandonAudioFocus, as well as part of any change in focus being held by the HAL due focus + * request from other activities or services. + * + * The HAL is not required to wait for an callback of AUDIOFOCUS_GAIN before playing audio, nor + * is it required to stop playing audio in the event of a AUDIOFOCUS_LOSS callback is received. + * + * @param usage The audio usage associated with the focus change {@code AttributeUsage}. See + * {@code audioUsage} in audio_policy_configuration.xsd for the list of allowed values. + * @param zoneId The identifier for the audio zone that the HAL is playing the stream in + * @param focusChange the AudioFocusChange that has occurred. + */ + oneway void onAudioFocusChange(in String usage, in int zoneId, in AudioFocusChange focusChange); + + /** + * Notifies HAL of changes in output devices that the HAL should apply ducking to. + * + * This will be called in response to changes in audio focus, and will include a + * {@link DuckingInfo} object per audio zone that experienced a change in audo focus. + * + * @param duckingInfos an array of {@link DuckingInfo} objects for the audio zones where audio + * focus has changed. + */ + oneway void onDevicesToDuckChange(in DuckingInfo[] duckingInfos); + + /** + * Notifies HAL of changes in output devices that the HAL should apply muting to. + * + * This will be called in response to changes in audio mute state for each volume group + * and will include a {@link MutingInfo} object per audio zone that experienced a mute state + * event. + * + * @param mutingInfos an array of {@link MutingInfo} objects for the audio zones where audio + * mute state has changed. + */ + oneway void onDevicesToMuteChange(in MutingInfo[] mutingInfos); + + /** + * Registers focus listener to be used by HAL for requesting and abandoning audio focus. + * + * It is expected that there will only ever be a single focus listener registered. If the + * observer dies, the HAL implementation must unregister observer automatically. If called when + * a listener is already registered, the existing one should be unregistered and replaced with + * the new listener. + * + * @param listener the listener interface. + */ + oneway void registerFocusListener(in IFocusListener listener); + + /** + * Control the right/left balance setting of the car speakers. + * + * This is intended to shift the speaker volume toward the right (+) or left (-) side of + * the car. 0.0 means "centered". +1.0 means fully right. -1.0 means fully left. + * + * A value outside the range -1 to 1 must be clamped by the implementation to the -1 to 1 + * range. + */ + oneway void setBalanceTowardRight(in float value); + + /** + * Control the fore/aft fade setting of the car speakers. + * + * This is intended to shift the speaker volume toward the front (+) or back (-) of the car. + * 0.0 means "centered". +1.0 means fully forward. -1.0 means fully rearward. + * + * A value outside the range -1 to 1 must be clamped by the implementation to the -1 to 1 + * range. + */ + oneway void setFadeTowardFront(in float value); +} \ No newline at end of file diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IFocusListener.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IFocusListener.aidl new file mode 100644 index 0000000000000000000000000000000000000000..b79295a6da9b07718dcd968fd2a9bf4d07267cac --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IFocusListener.aidl @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.automotive.audiocontrol; + +import android.hardware.automotive.audiocontrol.AudioFocusChange; + +/** + * Callback interface for audio focus listener. + * + * For typical configuration, the listener the car audio service. + */ +@VintfStability +interface IFocusListener { + /** + * Called whenever HAL is abandoning focus as it is finished playing audio of a given usage in a + * specific zone. + * + * In response, IAudioControl#onAudioFocusChange will be called with focusChange status. This + * interaction is oneway to avoid blocking HAL so that it is not required to wait for a response + * before stopping audio playback. + * + * @param usage The audio usage for which the HAL is abandoning focus {@code AttributeUsage}. + * See {@code audioUsage} in audio_policy_configuration.xsd for the list of allowed values. + * @param zoneId The identifier for the audio zone that the HAL abandoning focus + */ + oneway void abandonAudioFocus(in String usage, in int zoneId); + + /** + * Called whenever HAL is requesting focus as it is starting to play audio of a given usage in a + * specified zone. + * + * In response, IAudioControl#onAudioFocusChange will be called with focusChange status. This + * interaction is oneway to avoid blocking HAL so that it is not required to wait for a response + * before playing audio. + * + * @param usage The audio usage associated with the focus request {@code AttributeUsage}. See + * {@code audioUsage} in audio_policy_configuration.xsd for the list of allowed values. + * @param zoneId The identifier for the audio zone where the HAL is requesting focus + * @param focusGain The AudioFocusChange associated with this request. Should be one of the + * following: GAIN, GAIN_TRANSIENT, GAIN_TRANSIENT_MAY_DUCK, GAIN_TRANSIENT_EXCLUSIVE. + */ + oneway void requestAudioFocus(in String usage, in int zoneId, in AudioFocusChange focusGain); +} \ No newline at end of file diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/MutingInfo.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/MutingInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..783640fcfe1a1bd599bacde6b5ebfe73745b353e --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/MutingInfo.aidl @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + package android.hardware.automotive.audiocontrol; + + /** + * The current muting information for a single audio zone. + * + *

This includes devices to mute, as well as mute based on the contents of a previous + * {@link MutingInfo}. + */ + @VintfStability + parcelable MutingInfo { + /** + * ID of the associated audio zone + */ + int zoneId; + + /** + * List of addresses for audio output devices that should be muted. + * + *

The provided address strings are defined in audio_policy_configuration.xml. + */ + String[] deviceAddressesToMute; + + /** + * List of addresses for audio output devices that were previously be muted and should now be + * unmuted. + * + *

The provided address strings are defined in audio_policy_configuration.xml. + */ + String[] deviceAddressesToUnmute; + } \ No newline at end of file diff --git a/automotive/audiocontrol/aidl/default/Android.bp b/automotive/audiocontrol/aidl/default/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..1439cce60686dbac89dd9a1124ee0e61c69a4df5 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/Android.bp @@ -0,0 +1,45 @@ +// Copyright (C) 2020 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_binary { + name: "android.hardware.automotive.audiocontrol-service.example", + relative_install_path: "hw", + init_rc: ["audiocontrol-default.rc"], + vintf_fragments: ["audiocontrol-default.xml"], + vendor: true, + shared_libs: [ + "android.hardware.audio.common@7.0-enums", + "android.frameworks.automotive.powerpolicy-V1-ndk", + "android.hardware.automotive.audiocontrol-V1-ndk", + "libbase", + "libbinder_ndk", + "libcutils", + "liblog", + "libpowerpolicyclient", + ], + srcs: [ + "AudioControl.cpp", + "main.cpp", + "PowerPolicyClient.cpp", + ], +} diff --git a/automotive/audiocontrol/aidl/default/AudioControl.cpp b/automotive/audiocontrol/aidl/default/AudioControl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c0bc796cdf46db37bb43c6d52e5b7637d7339b67 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/AudioControl.cpp @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "AudioControl" +// #define LOG_NDEBUG 0 + +#include "AudioControl.h" + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +namespace aidl::android::hardware::automotive::audiocontrol { + +using ::android::base::EqualsIgnoreCase; +using ::android::base::ParseInt; +using ::std::shared_ptr; +using ::std::string; + +namespace xsd { +using namespace ::android::audio::policy::configuration::V7_0; +} + +namespace { +const float kLowerBound = -1.0f; +const float kUpperBound = 1.0f; +bool checkCallerHasWritePermissions(int fd) { + // Double check that's only called by root - it should be be blocked at debug() level, + // but it doesn't hurt to make sure... + if (AIBinder_getCallingUid() != AID_ROOT) { + dprintf(fd, "Must be root\n"); + return false; + } + return true; +} + +bool isValidValue(float value) { + return (value >= kLowerBound) && (value <= kUpperBound); +} + +bool safelyParseInt(string s, int* out) { + if (!ParseInt(s, out)) { + return false; + } + return true; +} +} // namespace + +ndk::ScopedAStatus AudioControl::registerFocusListener( + const shared_ptr& in_listener) { + LOG(DEBUG) << "registering focus listener"; + + if (in_listener) { + std::atomic_store(&mFocusListener, in_listener); + } else { + LOG(ERROR) << "Unexpected nullptr for listener resulting in no-op."; + } + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus AudioControl::setBalanceTowardRight(float value) { + if (isValidValue(value)) { + // Just log in this default mock implementation + LOG(INFO) << "Balance set to " << value; + return ndk::ScopedAStatus::ok(); + } + + LOG(ERROR) << "Balance value out of range -1 to 1 at " << value; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus AudioControl::setFadeTowardFront(float value) { + if (isValidValue(value)) { + // Just log in this default mock implementation + LOG(INFO) << "Fader set to " << value; + return ndk::ScopedAStatus::ok(); + } + + LOG(ERROR) << "Fader value out of range -1 to 1 at " << value; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus AudioControl::onAudioFocusChange(const string& in_usage, int32_t in_zoneId, + AudioFocusChange in_focusChange) { + LOG(INFO) << "Focus changed: " << toString(in_focusChange).c_str() << " for usage " + << in_usage.c_str() << " in zone " << in_zoneId; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus AudioControl::onDevicesToDuckChange( + const std::vector& in_duckingInfos) { + LOG(INFO) << "AudioControl::onDevicesToDuckChange"; + for (const DuckingInfo& duckingInfo : in_duckingInfos) { + LOG(INFO) << "zone: " << duckingInfo.zoneId; + LOG(INFO) << "Devices to duck:"; + for (const auto& addressToDuck : duckingInfo.deviceAddressesToDuck) { + LOG(INFO) << addressToDuck; + } + LOG(INFO) << "Devices to unduck:"; + for (const auto& addressToUnduck : duckingInfo.deviceAddressesToUnduck) { + LOG(INFO) << addressToUnduck; + } + LOG(INFO) << "Usages holding focus:"; + for (const auto& usage : duckingInfo.usagesHoldingFocus) { + LOG(INFO) << usage; + } + } + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus AudioControl::onDevicesToMuteChange( + const std::vector& in_mutingInfos) { + LOG(INFO) << "AudioControl::onDevicesToMuteChange"; + for (const MutingInfo& mutingInfo : in_mutingInfos) { + LOG(INFO) << "zone: " << mutingInfo.zoneId; + LOG(INFO) << "Devices to mute:"; + for (const auto& addressToMute : mutingInfo.deviceAddressesToMute) { + LOG(INFO) << addressToMute; + } + LOG(INFO) << "Devices to unmute:"; + for (const auto& addressToUnmute : mutingInfo.deviceAddressesToUnmute) { + LOG(INFO) << addressToUnmute; + } + } + return ndk::ScopedAStatus::ok(); +} + +binder_status_t AudioControl::dump(int fd, const char** args, uint32_t numArgs) { + if (numArgs == 0) { + return dumpsys(fd); + } + + string option = string(args[0]); + if (EqualsIgnoreCase(option, "--help")) { + return cmdHelp(fd); + } else if (EqualsIgnoreCase(option, "--request")) { + return cmdRequestFocus(fd, args, numArgs); + } else if (EqualsIgnoreCase(option, "--abandon")) { + return cmdAbandonFocus(fd, args, numArgs); + } else { + dprintf(fd, "Invalid option: %s\n", option.c_str()); + return STATUS_BAD_VALUE; + } +} + +binder_status_t AudioControl::dumpsys(int fd) { + if (mFocusListener == nullptr) { + dprintf(fd, "No focus listener registered\n"); + } else { + dprintf(fd, "Focus listener registered\n"); + } + return STATUS_OK; +} + +binder_status_t AudioControl::cmdHelp(int fd) const { + dprintf(fd, "Usage: \n\n"); + dprintf(fd, "[no args]: dumps focus listener status\n"); + dprintf(fd, "--help: shows this help\n"); + dprintf(fd, + "--request : requests audio focus for specified " + "usage (string), audio zone ID (int), and focus gain type (int)\n"); + dprintf(fd, + "--abandon : abandons audio focus for specified usage (string) and " + "audio zone ID (int)\n"); + dprintf(fd, "See audio_policy_configuration.xsd for valid AudioUsage values.\n"); + return STATUS_OK; +} + +binder_status_t AudioControl::cmdRequestFocus(int fd, const char** args, uint32_t numArgs) { + if (!checkCallerHasWritePermissions(fd)) { + return STATUS_PERMISSION_DENIED; + } + if (numArgs != 4) { + dprintf(fd, + "Invalid number of arguments: please provide --request " + "\n"); + return STATUS_BAD_VALUE; + } + + string usage = string(args[1]); + if (xsd::isUnknownAudioUsage(usage)) { + dprintf(fd, + "Unknown usage provided: %s. Please see audio_policy_configuration.xsd V7_0 " + "for supported values\n", + usage.c_str()); + return STATUS_BAD_VALUE; + } + + int zoneId; + if (!safelyParseInt(string(args[2]), &zoneId)) { + dprintf(fd, "Non-integer zoneId provided with request: %s\n", string(args[2]).c_str()); + return STATUS_BAD_VALUE; + } + + int focusGainValue; + if (!safelyParseInt(string(args[3]), &focusGainValue)) { + dprintf(fd, "Non-integer focusGain provided with request: %s\n", string(args[3]).c_str()); + return STATUS_BAD_VALUE; + } + AudioFocusChange focusGain = AudioFocusChange(focusGainValue); + + if (mFocusListener == nullptr) { + dprintf(fd, "Unable to request focus - no focus listener registered\n"); + return STATUS_BAD_VALUE; + } + + mFocusListener->requestAudioFocus(usage, zoneId, focusGain); + dprintf(fd, "Requested focus for usage %s, zoneId %d, and focusGain %d\n", usage.c_str(), + zoneId, focusGain); + return STATUS_OK; +} + +binder_status_t AudioControl::cmdAbandonFocus(int fd, const char** args, uint32_t numArgs) { + if (!checkCallerHasWritePermissions(fd)) { + return STATUS_PERMISSION_DENIED; + } + if (numArgs != 3) { + dprintf(fd, "Invalid number of arguments: please provide --abandon \n"); + return STATUS_BAD_VALUE; + } + + string usage = string(args[1]); + if (xsd::isUnknownAudioUsage(usage)) { + dprintf(fd, + "Unknown usage provided: %s. Please see audio_policy_configuration.xsd V7_0 " + "for supported values\n", + usage.c_str()); + return STATUS_BAD_VALUE; + } + + int zoneId; + if (!safelyParseInt(string(args[2]), &zoneId)) { + dprintf(fd, "Non-integer zoneId provided with abandon: %s\n", string(args[2]).c_str()); + return STATUS_BAD_VALUE; + } + + if (mFocusListener == nullptr) { + dprintf(fd, "Unable to abandon focus - no focus listener registered\n"); + return STATUS_BAD_VALUE; + } + + mFocusListener->abandonAudioFocus(usage, zoneId); + dprintf(fd, "Abandoned focus for usage %s and zoneId %d\n", usage.c_str(), zoneId); + return STATUS_OK; +} + +} // namespace aidl::android::hardware::automotive::audiocontrol diff --git a/automotive/audiocontrol/aidl/default/AudioControl.h b/automotive/audiocontrol/aidl/default/AudioControl.h new file mode 100644 index 0000000000000000000000000000000000000000..cca9c44004476aff52459af23c7776464ce67450 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/AudioControl.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_AUDIOCONTROL_H +#define ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_AUDIOCONTROL_H + +#include +#include +#include +#include + +namespace aidl::android::hardware::automotive::audiocontrol { + +class AudioControl : public BnAudioControl { + public: + ndk::ScopedAStatus onAudioFocusChange(const std::string& in_usage, int32_t in_zoneId, + AudioFocusChange in_focusChange) override; + ndk::ScopedAStatus onDevicesToDuckChange( + const std::vector& in_duckingInfos) override; + ndk::ScopedAStatus onDevicesToMuteChange( + const std::vector& in_mutingInfos) override; + ndk::ScopedAStatus registerFocusListener( + const std::shared_ptr& in_listener) override; + ndk::ScopedAStatus setBalanceTowardRight(float in_value) override; + ndk::ScopedAStatus setFadeTowardFront(float in_value) override; + binder_status_t dump(int fd, const char** args, uint32_t numArgs) override; + + private: + // This focus listener will only be used by this HAL instance to communicate with + // a single instance of CarAudioService. As such, it doesn't have explicit serialization. + // If a different AudioControl implementation were to have multiple threads leveraging this + // listener, then it should also include mutexes or make the listener atomic. + std::shared_ptr mFocusListener; + + binder_status_t cmdHelp(int fd) const; + binder_status_t cmdRequestFocus(int fd, const char** args, uint32_t numArgs); + binder_status_t cmdAbandonFocus(int fd, const char** args, uint32_t numArgs); + binder_status_t dumpsys(int fd); +}; + +} // namespace aidl::android::hardware::automotive::audiocontrol + +#endif // ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_AUDIOCONTROL_H diff --git a/automotive/audiocontrol/aidl/default/PowerPolicyClient.cpp b/automotive/audiocontrol/aidl/default/PowerPolicyClient.cpp new file mode 100644 index 0000000000000000000000000000000000000000..765733716b2ed1855e3280b081e75c32e2031e8f --- /dev/null +++ b/automotive/audiocontrol/aidl/default/PowerPolicyClient.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "PowerPolicyClient.h" +#include "AudioControl.h" + +#include + +namespace aidl { +namespace android { +namespace hardware { +namespace automotive { +namespace audiocontrol { + +namespace aafap = aidl::android::frameworks::automotive::powerpolicy; + +using aafap::CarPowerPolicy; +using aafap::CarPowerPolicyFilter; +using aafap::PowerComponent; +using ::android::frameworks::automotive::powerpolicy::hasComponent; +using ::ndk::ScopedAStatus; + +namespace { + +constexpr PowerComponent kAudioComponent = PowerComponent::AUDIO; + +} // namespace + +PowerPolicyClient::PowerPolicyClient(std::shared_ptr audioControl) + : mAudioControl(audioControl) {} + +void PowerPolicyClient::onInitFailed() { + LOG(ERROR) << "Initializing power policy client failed"; +} + +std::vector PowerPolicyClient::getComponentsOfInterest() { + std::vector components{kAudioComponent}; + return components; +} + +ScopedAStatus PowerPolicyClient::onPolicyChanged(const CarPowerPolicy& powerPolicy) { + if (hasComponent(powerPolicy.enabledComponents, kAudioComponent)) { + LOG(DEBUG) << "Power policy: Audio component is enabled"; + // TODO(b/173719953): Do something when AUDIO is enabled. + } else if (hasComponent(powerPolicy.disabledComponents, kAudioComponent)) { + LOG(DEBUG) << "Power policy: Audio component is disabled"; + // TODO(b/173719953): Do something when AUDIO is disabled. + } + return ScopedAStatus::ok(); +} + +} // namespace audiocontrol +} // namespace automotive +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/automotive/audiocontrol/aidl/default/PowerPolicyClient.h b/automotive/audiocontrol/aidl/default/PowerPolicyClient.h new file mode 100644 index 0000000000000000000000000000000000000000..0b4d5b6c0a18252d811133c7887fbb9316deb0a7 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/PowerPolicyClient.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AUTOMOTIVE_AUDIOCONTROL_AIDL_DEFAULT_POWERPOLICYCLIENT_H_ +#define AUTOMOTIVE_AUDIOCONTROL_AIDL_DEFAULT_POWERPOLICYCLIENT_H_ + +#include "PowerPolicyClientBase.h" + +#include + +namespace aidl::android::hardware::automotive::audiocontrol { + +class AudioControl; + +class PowerPolicyClient + : public ::android::frameworks::automotive::powerpolicy::PowerPolicyClientBase { + public: + explicit PowerPolicyClient(std::shared_ptr audioControl); + + void onInitFailed(); + std::vector<::aidl::android::frameworks::automotive::powerpolicy::PowerComponent> + getComponentsOfInterest() override; + ::ndk::ScopedAStatus onPolicyChanged( + const ::aidl::android::frameworks::automotive::powerpolicy::CarPowerPolicy&) override; + + private: + std::shared_ptr mAudioControl; +}; + +} // namespace aidl::android::hardware::automotive::audiocontrol + +#endif // AUTOMOTIVE_AUDIOCONTROL_AIDL_DEFAULT_POWERPOLICYCLIENT_H_ diff --git a/automotive/audiocontrol/aidl/default/audiocontrol-default.rc b/automotive/audiocontrol/aidl/default/audiocontrol-default.rc new file mode 100644 index 0000000000000000000000000000000000000000..88d180dbd1d55b626bdd69b7329e67ae6234d7d2 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/audiocontrol-default.rc @@ -0,0 +1,4 @@ +service vendor.audiocontrol-default /vendor/bin/hw/android.hardware.automotive.audiocontrol-service.example + class hal + user audioserver + group system diff --git a/automotive/audiocontrol/aidl/default/audiocontrol-default.xml b/automotive/audiocontrol/aidl/default/audiocontrol-default.xml new file mode 100644 index 0000000000000000000000000000000000000000..f95d05fe7779353a24a941f7df027c5196a261db --- /dev/null +++ b/automotive/audiocontrol/aidl/default/audiocontrol-default.xml @@ -0,0 +1,6 @@ + + + android.hardware.automotive.audiocontrol + IAudioControl/default + + diff --git a/automotive/audiocontrol/aidl/default/main.cpp b/automotive/audiocontrol/aidl/default/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9b259fca0a005ea8aad989387d812a4f6a9f54fb --- /dev/null +++ b/automotive/audiocontrol/aidl/default/main.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "AudioControl.h" +#include "PowerPolicyClient.h" + +#include +#include +#include + +using aidl::android::hardware::automotive::audiocontrol::AudioControl; +using aidl::android::hardware::automotive::audiocontrol::PowerPolicyClient; + +int main() { + ABinderProcess_setThreadPoolMaxThreadCount(0); + std::shared_ptr audioControl = ::ndk::SharedRefBase::make(); + + const std::string instance = std::string() + AudioControl::descriptor + "/default"; + binder_status_t status = + AServiceManager_addService(audioControl->asBinder().get(), instance.c_str()); + CHECK(status == STATUS_OK); + + std::shared_ptr powerPolicyClient = + ::ndk::SharedRefBase::make(audioControl); + powerPolicyClient->init(); + + ABinderProcess_joinThreadPool(); + return EXIT_FAILURE; // should not reach +} diff --git a/automotive/audiocontrol/aidl/vts/Android.bp b/automotive/audiocontrol/aidl/vts/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..6856b91d2b1418adee80afd83f36021f2b4596b0 --- /dev/null +++ b/automotive/audiocontrol/aidl/vts/Android.bp @@ -0,0 +1,47 @@ +// Copyright (C) 2020 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_test { + name: "VtsAidlHalAudioControlTest", + defaults: [ + "VtsHalTargetTestDefaults", + "use_libaidlvintf_gtest_helper_static", + ], + generated_headers: ["audio_policy_configuration_V7_0"], + generated_sources: ["audio_policy_configuration_V7_0"], + header_libs: ["libxsdc-utils"], + srcs: ["VtsHalAudioControlTargetTest.cpp"], + shared_libs: [ + "libbinder", + "libbase", + "libxml2", + ], + static_libs: [ + "android.hardware.automotive.audiocontrol-V1-cpp", + "libgmock", + ], + test_suites: [ + "general-tests", + "vts", + ], +} diff --git a/automotive/audiocontrol/aidl/vts/VtsHalAudioControlTargetTest.cpp b/automotive/audiocontrol/aidl/vts/VtsHalAudioControlTargetTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ae53c685285b693c69b91cf1c9b3ad5aba12afb8 --- /dev/null +++ b/automotive/audiocontrol/aidl/vts/VtsHalAudioControlTargetTest.cpp @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define LOG_TAG "VtsAidlHalAudioControlTest" + +#include +#include +#include + +#include +#include +#include +#include +#include + +using android::ProcessState; +using android::sp; +using android::String16; +using android::binder::Status; +using android::hardware::automotive::audiocontrol::AudioFocusChange; +using android::hardware::automotive::audiocontrol::BnFocusListener; +using android::hardware::automotive::audiocontrol::DuckingInfo; +using android::hardware::automotive::audiocontrol::IAudioControl; +using android::hardware::automotive::audiocontrol::MutingInfo; + +#include "android_audio_policy_configuration_V7_0.h" + +namespace xsd { +using namespace android::audio::policy::configuration::V7_0; +} + +class AudioControlAidl : public testing::TestWithParam { + public: + virtual void SetUp() override { + audioControl = android::waitForDeclaredService(String16(GetParam().c_str())); + ASSERT_NE(audioControl, nullptr); + } + + sp audioControl; + int32_t capabilities; +}; + +TEST_P(AudioControlAidl, OnSetFadeTowardsFront) { + ALOGI("Fader exercise test (silent)"); + + // Set the fader all the way to the back + ASSERT_TRUE(audioControl->setFadeTowardFront(-1.0f).isOk()); + + // Set the fader all the way to the front + ASSERT_TRUE(audioControl->setFadeTowardFront(1.0f).isOk()); + + // Set the fader part way toward the back + ASSERT_TRUE(audioControl->setFadeTowardFront(-0.333f).isOk()); + + // Set the fader to a out of bounds value (driver should clamp) + ASSERT_TRUE(audioControl->setFadeTowardFront(99999.9f).isOk()); + + // Set the fader to a negative out of bounds value (driver should clamp) + ASSERT_TRUE(audioControl->setFadeTowardFront(-99999.9f).isOk()); + + // Set the fader back to the middle + ASSERT_TRUE(audioControl->setFadeTowardFront(0.0f).isOk()); +} + +TEST_P(AudioControlAidl, OnSetBalanceTowardsRight) { + ALOGI("Balance exercise test (silent)"); + + // Set the balance all the way to the left + ASSERT_TRUE(audioControl->setBalanceTowardRight(-1.0f).isOk()); + + // Set the balance all the way to the right + ASSERT_TRUE(audioControl->setBalanceTowardRight(1.0f).isOk()); + + // Set the balance part way toward the left + ASSERT_TRUE(audioControl->setBalanceTowardRight(-0.333f).isOk()); + + // Set the balance to a out of bounds value (driver should clamp) + ASSERT_TRUE(audioControl->setBalanceTowardRight(99999.9f).isOk()); + + // Set the balance to a negative out of bounds value (driver should clamp) + ASSERT_TRUE(audioControl->setBalanceTowardRight(-99999.9f).isOk()); + + // Set the balance back to the middle + ASSERT_TRUE(audioControl->setBalanceTowardRight(0.0f).isOk()); + + // Set the balance back to the middle + audioControl->setBalanceTowardRight(0.0f).isOk(); +} + +struct FocusListenerMock : BnFocusListener { + MOCK_METHOD(Status, requestAudioFocus, + (const String16& usage, int32_t zoneId, AudioFocusChange focusGain)); + MOCK_METHOD(Status, abandonAudioFocus, (const String16& usage, int32_t zoneId)); +}; + +/* + * Test focus listener registration. + * + * Verifies that: + * - registerFocusListener succeeds; + * - registering a second listener succeeds in replacing the first; + * - closing handle does not crash; + */ +TEST_P(AudioControlAidl, FocusListenerRegistration) { + ALOGI("Focus listener test"); + + sp listener = new FocusListenerMock(); + ASSERT_TRUE(audioControl->registerFocusListener(listener).isOk()); + + sp listener2 = new FocusListenerMock(); + ASSERT_TRUE(audioControl->registerFocusListener(listener2).isOk()); +}; + +TEST_P(AudioControlAidl, FocusChangeExercise) { + ALOGI("Focus Change test"); + + String16 usage = String16(xsd::toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA).c_str()); + ASSERT_TRUE( + audioControl->onAudioFocusChange(usage, 0, AudioFocusChange::GAIN_TRANSIENT).isOk()); +}; + +TEST_P(AudioControlAidl, MuteChangeExercise) { + ALOGI("Mute change test"); + + MutingInfo mutingInfo; + mutingInfo.zoneId = 0; + mutingInfo.deviceAddressesToMute = {String16("address 1"), String16("address 2")}; + mutingInfo.deviceAddressesToUnmute = {String16("address 3"), String16("address 4")}; + std::vector mutingInfos = {mutingInfo}; + ALOGI("Mute change test start"); + ASSERT_TRUE(audioControl->onDevicesToMuteChange(mutingInfos).isOk()); +} + +TEST_P(AudioControlAidl, DuckChangeExercise) { + ALOGI("Duck change test"); + + DuckingInfo duckingInfo; + duckingInfo.zoneId = 0; + duckingInfo.deviceAddressesToDuck = {String16("address 1"), String16("address 2")}; + duckingInfo.deviceAddressesToUnduck = {String16("address 3"), String16("address 4")}; + duckingInfo.usagesHoldingFocus = { + String16(xsd::toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA).c_str()), + String16(xsd::toString(xsd::AudioUsage::AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE) + .c_str())}; + std::vector duckingInfos = {duckingInfo}; + ALOGI("Duck change test start"); + ASSERT_TRUE(audioControl->onDevicesToDuckChange(duckingInfos).isOk()); +} + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioControlAidl); +INSTANTIATE_TEST_SUITE_P( + Audiocontrol, AudioControlAidl, + testing::ValuesIn(android::getAidlHalInstanceNames(IAudioControl::descriptor)), + android::PrintInstanceNameToString); + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + ProcessState::self()->setThreadPoolMaxThreadCount(1); + ProcessState::self()->startThreadPool(); + return RUN_ALL_TESTS(); +} diff --git a/automotive/can/1.0/default/Android.bp b/automotive/can/1.0/default/Android.bp index 879decc4e771b9671dd82f8e1461b1bcdd13360e..c0c17e27f537c4bd2ad30aec5319de8544976ad6 100644 --- a/automotive/can/1.0/default/Android.bp +++ b/automotive/can/1.0/default/Android.bp @@ -62,5 +62,6 @@ cc_binary { static_libs: [ "android.hardware.automotive.can@libnetdevice", "android.hardware.automotive@libc++fs", + "libnl++", ], } diff --git a/automotive/can/1.0/default/CanBus.cpp b/automotive/can/1.0/default/CanBus.cpp index 8b98e5ee2bd9b33f62874800518ca9d459f4bf47..2efe0547eaadf4d81aa7875d7d591b69d5fffaf8 100644 --- a/automotive/can/1.0/default/CanBus.cpp +++ b/automotive/can/1.0/default/CanBus.cpp @@ -254,7 +254,7 @@ static bool match(const hidl_vec& filter, CanMessageId id, boo satisfiesFilterFlag(rule.extendedFormat, isExtendedId); if (rule.exclude) { - // Any excluded (blacklist) rule not being satisfied invalidates the whole filter set. + // Any exclude rule being satisfied invalidates the whole filter set. if (satisfied) return false; } else { anyNonExcludeRulePresent = true; diff --git a/automotive/can/1.0/default/libnetdevice/Android.bp b/automotive/can/1.0/default/libnetdevice/Android.bp index 757d8e606399049e251be93a4bec0383a0192706..653e77324094a5532d051a2796125932e2536c02 100644 --- a/automotive/can/1.0/default/libnetdevice/Android.bp +++ b/automotive/can/1.0/default/libnetdevice/Android.bp @@ -27,13 +27,16 @@ cc_library_static { name: "android.hardware.automotive.can@libnetdevice", defaults: ["android.hardware.automotive.can@defaults"], vendor_available: true, - relative_install_path: "hw", srcs: [ - "NetlinkRequest.cpp", - "NetlinkSocket.cpp", "can.cpp", "common.cpp", + "ethtool.cpp", + "ifreqs.cpp", "libnetdevice.cpp", + "vlan.cpp", ], export_include_dirs: ["include"], + static_libs: [ + "libnl++", + ], } diff --git a/automotive/can/1.0/default/libnetdevice/NetlinkRequest.cpp b/automotive/can/1.0/default/libnetdevice/NetlinkRequest.cpp deleted file mode 100644 index 556debfc0911aa452d7af504083ca13eb45aacb0..0000000000000000000000000000000000000000 --- a/automotive/can/1.0/default/libnetdevice/NetlinkRequest.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "NetlinkRequest.h" - -#include - -namespace android::netdevice::impl { - -static struct rtattr* nlmsg_tail(struct nlmsghdr* n) { - return reinterpret_cast( // - reinterpret_cast(n) + NLMSG_ALIGN(n->nlmsg_len)); -} - -struct rtattr* addattr_l(struct nlmsghdr* n, size_t maxLen, rtattrtype_t type, const void* data, - size_t dataLen) { - size_t newLen = NLMSG_ALIGN(n->nlmsg_len) + RTA_SPACE(dataLen); - if (newLen > maxLen) { - LOG(ERROR) << "addattr_l failed - exceeded maxLen: " << newLen << " > " << maxLen; - return nullptr; - } - - auto attr = nlmsg_tail(n); - attr->rta_len = RTA_SPACE(dataLen); - attr->rta_type = type; - if (dataLen > 0) memcpy(RTA_DATA(attr), data, dataLen); - - n->nlmsg_len = newLen; - return attr; -} - -struct rtattr* addattr_nest(struct nlmsghdr* n, size_t maxLen, rtattrtype_t type) { - return addattr_l(n, maxLen, type, nullptr, 0); -} - -void addattr_nest_end(struct nlmsghdr* n, struct rtattr* nest) { - size_t nestLen = reinterpret_cast(nlmsg_tail(n)) - reinterpret_cast(nest); - nest->rta_len = nestLen; -} - -} // namespace android::netdevice::impl diff --git a/automotive/can/1.0/default/libnetdevice/NetlinkRequest.h b/automotive/can/1.0/default/libnetdevice/NetlinkRequest.h deleted file mode 100644 index 3e28d78485cc4be3a0488ef8d053b872e3e737f2..0000000000000000000000000000000000000000 --- a/automotive/can/1.0/default/libnetdevice/NetlinkRequest.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include -#include - -#include - -namespace android::netdevice { - -typedef unsigned short rtattrtype_t; // as in rtnetlink.h -typedef __u16 nlmsgtype_t; // as in netlink.h - -/** Implementation details, do not use outside NetlinkRequest template. */ -namespace impl { - -struct rtattr* addattr_l(struct nlmsghdr* n, size_t maxLen, rtattrtype_t type, const void* data, - size_t dataLen); -struct rtattr* addattr_nest(struct nlmsghdr* n, size_t maxLen, rtattrtype_t type); -void addattr_nest_end(struct nlmsghdr* n, struct rtattr* nest); - -} // namespace impl - -/** - * Wrapper around NETLINK_ROUTE messages, to build them in C++ style. - * - * \param T specific message header (such as struct ifinfomsg) - * \param BUFSIZE how much space to reserve for payload (not counting the header size) - */ -template -struct NetlinkRequest { - /** - * Create empty message. - * - * \param type Message type (such as RTM_NEWLINK) - * \param flags Message flags (such as NLM_F_REQUEST) - */ - NetlinkRequest(nlmsgtype_t type, uint16_t flags) { - mRequest.nlmsg.nlmsg_len = NLMSG_LENGTH(sizeof(mRequest.data)); - mRequest.nlmsg.nlmsg_type = type; - mRequest.nlmsg.nlmsg_flags = flags; - } - - /** \return pointer to raw netlink message header. */ - struct nlmsghdr* header() { - return &mRequest.nlmsg; - } - /** Reference to message-specific header. */ - T& data() { return mRequest.data; } - - /** - * Adds an attribute of a simple type. - * - * If this method fails (i.e. due to insufficient space), the message will be marked - * as bad (\see isGood). - * - * \param type attribute type (such as IFLA_IFNAME) - * \param attr attribute data - */ - template - void addattr(rtattrtype_t type, const A& attr) { - if (!mIsGood) return; - auto ap = impl::addattr_l(&mRequest.nlmsg, sizeof(mRequest), type, &attr, sizeof(attr)); - if (ap == nullptr) mIsGood = false; - } - - template <> - void addattr(rtattrtype_t type, const std::string& s) { - if (!mIsGood) return; - auto ap = impl::addattr_l(&mRequest.nlmsg, sizeof(mRequest), type, s.c_str(), s.size() + 1); - if (ap == nullptr) mIsGood = false; - } - - /** Guard class to frame nested attributes. See nest(int). */ - struct Nest { - Nest(NetlinkRequest& req, rtattrtype_t type) : mReq(req), mAttr(req.nestStart(type)) {} - ~Nest() { mReq.nestEnd(mAttr); } - - private: - NetlinkRequest& mReq; - struct rtattr* mAttr; - - DISALLOW_COPY_AND_ASSIGN(Nest); - }; - - /** - * Add nested attribute. - * - * The returned object is a guard for auto-nesting children inside the argument attribute. - * When the Nest object goes out of scope, the nesting attribute is closed. - * - * Example usage nesting IFLA_CAN_BITTIMING inside IFLA_INFO_DATA, which is nested - * inside IFLA_LINKINFO: - * NetlinkRequest req(RTM_NEWLINK, NLM_F_REQUEST); - * { - * auto linkinfo = req.nest(IFLA_LINKINFO); - * req.addattr(IFLA_INFO_KIND, "can"); - * { - * auto infodata = req.nest(IFLA_INFO_DATA); - * req.addattr(IFLA_CAN_BITTIMING, bitTimingStruct); - * } - * } - * // use req - * - * \param type attribute type (such as IFLA_LINKINFO) - */ - Nest nest(int type) { return Nest(*this, type); } - - /** - * Indicates, whether the message is in a good state. - * - * The bad state is usually a result of payload buffer being too small. - * You can modify BUFSIZE template parameter to fix this. - */ - bool isGood() const { return mIsGood; } - - private: - bool mIsGood = true; - - struct { - struct nlmsghdr nlmsg; - T data; - char buf[BUFSIZE]; - } mRequest = {}; - - struct rtattr* nestStart(rtattrtype_t type) { - if (!mIsGood) return nullptr; - auto attr = impl::addattr_nest(&mRequest.nlmsg, sizeof(mRequest), type); - if (attr == nullptr) mIsGood = false; - return attr; - } - - void nestEnd(struct rtattr* nest) { - if (mIsGood && nest != nullptr) impl::addattr_nest_end(&mRequest.nlmsg, nest); - } -}; - -} // namespace android::netdevice diff --git a/automotive/can/1.0/default/libnetdevice/NetlinkSocket.cpp b/automotive/can/1.0/default/libnetdevice/NetlinkSocket.cpp deleted file mode 100644 index 7817169876ea474869cd928a517e36c9f491c0b0..0000000000000000000000000000000000000000 --- a/automotive/can/1.0/default/libnetdevice/NetlinkSocket.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "NetlinkSocket.h" - -#include - -namespace android::netdevice { - -NetlinkSocket::NetlinkSocket(int protocol) { - mFd.reset(socket(AF_NETLINK, SOCK_RAW, protocol)); - if (!mFd.ok()) { - PLOG(ERROR) << "Can't open Netlink socket"; - mFailed = true; - return; - } - - struct sockaddr_nl sa = {}; - sa.nl_family = AF_NETLINK; - - if (bind(mFd.get(), reinterpret_cast(&sa), sizeof(sa)) < 0) { - PLOG(ERROR) << "Can't bind Netlink socket"; - mFd.reset(); - mFailed = true; - } -} - -bool NetlinkSocket::send(struct nlmsghdr* nlmsg) { - if (mFailed) return false; - - nlmsg->nlmsg_pid = 0; // kernel - nlmsg->nlmsg_seq = mSeq++; - nlmsg->nlmsg_flags |= NLM_F_ACK; - - struct iovec iov = {nlmsg, nlmsg->nlmsg_len}; - - struct sockaddr_nl sa = {}; - sa.nl_family = AF_NETLINK; - - struct msghdr msg = {}; - msg.msg_name = &sa; - msg.msg_namelen = sizeof(sa); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - - if (sendmsg(mFd.get(), &msg, 0) < 0) { - PLOG(ERROR) << "Can't send Netlink message"; - return false; - } - return true; -} - -bool NetlinkSocket::receiveAck() { - if (mFailed) return false; - - char buf[8192]; - - struct sockaddr_nl sa; - struct iovec iov = {buf, sizeof(buf)}; - - struct msghdr msg = {}; - msg.msg_name = &sa; - msg.msg_namelen = sizeof(sa); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - - const ssize_t status = recvmsg(mFd.get(), &msg, 0); - if (status < 0) { - PLOG(ERROR) << "Failed to receive Netlink message"; - return false; - } - size_t remainingLen = status; - - if (msg.msg_flags & MSG_TRUNC) { - LOG(ERROR) << "Failed to receive Netlink message: truncated"; - return false; - } - - for (auto nlmsg = reinterpret_cast(buf); NLMSG_OK(nlmsg, remainingLen); - nlmsg = NLMSG_NEXT(nlmsg, remainingLen)) { - // We're looking for error/ack message only, ignoring others. - if (nlmsg->nlmsg_type != NLMSG_ERROR) { - LOG(WARNING) << "Received unexpected Netlink message (ignored): " << nlmsg->nlmsg_type; - continue; - } - - // Found error/ack message, return status. - auto nlerr = reinterpret_cast(NLMSG_DATA(nlmsg)); - if (nlerr->error != 0) { - LOG(ERROR) << "Received Netlink error message: " << nlerr->error; - return false; - } - return true; - } - // Couldn't find any error/ack messages. - return false; -} - -} // namespace android::netdevice diff --git a/automotive/can/1.0/default/libnetdevice/NetlinkSocket.h b/automotive/can/1.0/default/libnetdevice/NetlinkSocket.h deleted file mode 100644 index 2b40ea20c0bd0aaea07995e0fe9fbf8820f7691c..0000000000000000000000000000000000000000 --- a/automotive/can/1.0/default/libnetdevice/NetlinkSocket.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include "NetlinkRequest.h" - -#include -#include - -#include - -namespace android::netdevice { - -/** - * A wrapper around AF_NETLINK sockets. - * - * This class is not thread safe to use a single instance between multiple threads, but it's fine to - * use multiple instances over multiple threads. - */ -struct NetlinkSocket { - NetlinkSocket(int protocol); - - /** - * Send Netlink message to Kernel. - * - * \param msg Message to send, nlmsg_seq will be set to next sequence number - * \return true, if succeeded - */ - template - bool send(NetlinkRequest& req) { - if (!req.isGood()) return false; - return send(req.header()); - } - - /** - * Receive Netlink ACK message from Kernel. - * - * \return true if received ACK message, false in case of error - */ - bool receiveAck(); - - private: - uint32_t mSeq = 0; - base::unique_fd mFd; - bool mFailed = false; - - bool send(struct nlmsghdr* msg); - - DISALLOW_COPY_AND_ASSIGN(NetlinkSocket); -}; - -} // namespace android::netdevice diff --git a/automotive/can/1.0/default/libnetdevice/can.cpp b/automotive/can/1.0/default/libnetdevice/can.cpp index a2a85dcae8a08107d3f270c34269216f264f5eee..083f4f002870d6b456ecbf8b44e71cb5bb219713 100644 --- a/automotive/can/1.0/default/libnetdevice/can.cpp +++ b/automotive/can/1.0/default/libnetdevice/can.cpp @@ -14,26 +14,27 @@ * limitations under the License. */ -#include +#include -#include "NetlinkRequest.h" -#include "NetlinkSocket.h" #include "common.h" #include #include +#include +#include #include #include #include #include +#include namespace android::netdevice::can { static constexpr can_err_mask_t kErrMask = CAN_ERR_MASK; base::unique_fd socket(const std::string& ifname) { - struct sockaddr_can addr = {}; + sockaddr_can addr = {}; addr.can_family = AF_CAN; addr.can_ifindex = nametoindex(ifname); if (addr.can_ifindex == 0) { @@ -57,7 +58,7 @@ base::unique_fd socket(const std::string& ifname) { return {}; } - if (0 != bind(sock.get(), reinterpret_cast(&addr), sizeof(addr))) { + if (0 != bind(sock.get(), reinterpret_cast(&addr), sizeof(addr))) { LOG(ERROR) << "Can't bind to CAN interface " << ifname; return {}; } @@ -66,31 +67,30 @@ base::unique_fd socket(const std::string& ifname) { } bool setBitrate(std::string ifname, uint32_t bitrate) { - struct can_bittiming bt = {}; + can_bittiming bt = {}; bt.bitrate = bitrate; - NetlinkRequest req(RTM_NEWLINK, NLM_F_REQUEST); + nl::MessageFactory req(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_ACK); - const auto ifidx = nametoindex(ifname); - if (ifidx == 0) { + req->ifi_index = nametoindex(ifname); + if (req->ifi_index == 0) { LOG(ERROR) << "Can't find interface " << ifname; return false; } - req.data().ifi_index = ifidx; { - auto linkinfo = req.nest(IFLA_LINKINFO); - req.addattr(IFLA_INFO_KIND, "can"); + auto linkinfo = req.addNested(IFLA_LINKINFO); + req.add(IFLA_INFO_KIND, "can"); { - auto infodata = req.nest(IFLA_INFO_DATA); + auto infodata = req.addNested(IFLA_INFO_DATA); /* For CAN FD, it would require to add IFLA_CAN_DATA_BITTIMING * and IFLA_CAN_CTRLMODE as well. */ - req.addattr(IFLA_CAN_BITTIMING, bt); + req.add(IFLA_CAN_BITTIMING, bt); } } - NetlinkSocket sock(NETLINK_ROUTE); - return sock.send(req) && sock.receiveAck(); + nl::Socket sock(NETLINK_ROUTE); + return sock.send(req) && sock.receiveAck(req); } } // namespace android::netdevice::can diff --git a/automotive/can/1.0/default/libnetdevice/common.cpp b/automotive/can/1.0/default/libnetdevice/common.cpp index 5c624439cd068c097fe68aed1cf8324c46d4f7c7..28e50af60ab504819e5be3e30c0137304b0332e5 100644 --- a/automotive/can/1.0/default/libnetdevice/common.cpp +++ b/automotive/can/1.0/default/libnetdevice/common.cpp @@ -26,9 +26,8 @@ unsigned int nametoindex(const std::string& ifname) { const auto ifidx = if_nametoindex(ifname.c_str()); if (ifidx != 0) return ifidx; - const auto err = errno; - if (err != ENODEV) { - LOG(ERROR) << "if_nametoindex(" << ifname << ") failed: " << err; + if (errno != ENODEV) { + PLOG(ERROR) << "if_nametoindex(" << ifname << ") failed"; } return 0; } diff --git a/automotive/can/1.0/default/libnetdevice/common.h b/automotive/can/1.0/default/libnetdevice/common.h index 8097f374adc4b54e82dbff0cd5a4ee33cc745aeb..661e3f80f2d33aac9e188c9e320d861f1990e9b5 100644 --- a/automotive/can/1.0/default/libnetdevice/common.h +++ b/automotive/can/1.0/default/libnetdevice/common.h @@ -16,6 +16,9 @@ #pragma once +#include +#include + #include namespace android::netdevice { diff --git a/automotive/can/1.0/default/libnetdevice/ethtool.cpp b/automotive/can/1.0/default/libnetdevice/ethtool.cpp new file mode 100644 index 0000000000000000000000000000000000000000..762ef5cc884f09867134ce3055175da136bf41a4 --- /dev/null +++ b/automotive/can/1.0/default/libnetdevice/ethtool.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ifreqs.h" + +#include + +namespace android::netdevice::ethtool { + +std::optional getValue(const std::string& ifname, uint32_t command) { + struct ethtool_value valueop = {}; + valueop.cmd = command; + + auto ifr = ifreqs::fromName(ifname); + ifr.ifr_data = &valueop; + + if (!ifreqs::send(SIOCETHTOOL, ifr)) return std::nullopt; + return valueop.data; +} + +bool setValue(const std::string& ifname, uint32_t command, uint32_t value) { + struct ethtool_value valueop = {}; + valueop.cmd = command; + valueop.data = value; + + auto ifr = ifreqs::fromName(ifname); + ifr.ifr_data = &valueop; + + return ifreqs::send(SIOCETHTOOL, ifr); +} + +} // namespace android::netdevice::ethtool diff --git a/automotive/can/1.0/default/libnetdevice/ifreqs.cpp b/automotive/can/1.0/default/libnetdevice/ifreqs.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8df64347967da716f5fd115f36c5ad5bfb08581a --- /dev/null +++ b/automotive/can/1.0/default/libnetdevice/ifreqs.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ifreqs.h" + +#include "common.h" + +#include +#include + +#include + +namespace android::netdevice::ifreqs { + +static constexpr int defaultSocketDomain = AF_INET; +std::atomic_int socketDomain = defaultSocketDomain; + +struct SocketParams { + int domain; + int type; + int protocol; +}; + +static const std::map socketParams = { + {AF_INET, {AF_INET, SOCK_DGRAM, 0}}, + {AF_CAN, {AF_CAN, SOCK_RAW, CAN_RAW}}, +}; + +static SocketParams getSocketParams(int domain) { + if (socketParams.count(domain)) return socketParams.find(domain)->second; + + auto params = socketParams.find(defaultSocketDomain)->second; + params.domain = domain; + return params; +} + +bool send(unsigned long request, struct ifreq& ifr) { + const auto sp = getSocketParams(socketDomain); + base::unique_fd sock(socket(sp.domain, sp.type, sp.protocol)); + if (!sock.ok()) { + LOG(ERROR) << "Can't create socket"; + return false; + } + + if (ioctl(sock.get(), request, &ifr) < 0) { + PLOG(ERROR) << "ioctl(" << std::hex << request << std::dec << ") failed"; + return false; + } + + return true; +} + +struct ifreq fromName(const std::string& ifname) { + struct ifreq ifr = {}; + strlcpy(ifr.ifr_name, ifname.c_str(), IF_NAMESIZE); + return ifr; +} + +} // namespace android::netdevice::ifreqs diff --git a/automotive/can/1.0/default/libnetdevice/ifreqs.h b/automotive/can/1.0/default/libnetdevice/ifreqs.h new file mode 100644 index 0000000000000000000000000000000000000000..74e58775b690fffa5016d170dd1ac32100406230 --- /dev/null +++ b/automotive/can/1.0/default/libnetdevice/ifreqs.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include + +namespace android::netdevice::ifreqs { + +/** + * \see useSocketDomain() + */ +extern std::atomic_int socketDomain; + +/** + * Sends ioctl interface request. + * + * \param request Request type (such as SIOCGIFFLAGS) + * \param ifr Request data (both input and output) + * \return true if the call succeeded, false otherwise + */ +bool send(unsigned long request, struct ifreq& ifr); + +/** + * Initializes interface request with interface name. + * + * \param ifname Interface to initialize request with + * \return Interface request with ifr_name field set to ifname + */ +struct ifreq fromName(const std::string& ifname); + +} // namespace android::netdevice::ifreqs diff --git a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/ethtool.h b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/ethtool.h new file mode 100644 index 0000000000000000000000000000000000000000..26bfdce00caf1e619897cee73d89a7f63a979e73 --- /dev/null +++ b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/ethtool.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +namespace android::netdevice::ethtool { + +/** + * Fetch a single value with ethtool_value. + * + * \see linux/ethtool.h + * \param ifname Interface to fetch data for + * \param command Fetch command (ETHTOOL_G*) + * \return value, or nullopt if fetch failed + */ +std::optional getValue(const std::string& ifname, uint32_t command); + +/** + * Set a single value with ethtool_value. + * + * \see linux/ethtool.h + * \param ifname Interface to set data for + * \param command Set command (ETHTOOL_S*) + * \param value New value + * \return true if succeeded, false otherwise + */ +bool setValue(const std::string& ifname, uint32_t command, uint32_t value); + +} // namespace android::netdevice::ethtool diff --git a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/libnetdevice.h b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/libnetdevice.h index 3818a31c4cb8d6a5fb7df331e6d6feff976fafb1..70cb6889331b85c5e9a749bb5af38331d7933019 100644 --- a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/libnetdevice.h +++ b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/libnetdevice.h @@ -16,11 +16,27 @@ #pragma once +#include + +#include #include +#include #include namespace android::netdevice { +typedef std::array hwaddr_t; + +/** + * Configures libnetdevice to use other socket domain than AF_INET, + * what requires less permissive SEPolicy rules for a given process. + * + * In such case, the process would only be able to control interfaces of a given kind. + + * \param domain Socket domain to use (e.g. AF_CAN), see socket(2) for details + */ +void useSocketDomain(int domain); + /** * Checks, if the network interface exists. * @@ -37,6 +53,36 @@ bool exists(std::string ifname); */ std::optional isUp(std::string ifname); +/** + * Interface condition to wait for. + */ +enum class WaitCondition { + /** + * Interface is present (but not necessarily up). + */ + PRESENT, + + /** + * Interface is up. + */ + PRESENT_AND_UP, + + /** + * Interface is down or not present (disconnected) at all. + */ + DOWN_OR_GONE, +}; + +/** + * Listens for interface changes until anticipated condition takes place. + * + * \param ifnames List of interfaces to watch for. + * \param cnd Awaited condition. + * \param allOf true if all interfaces need to satisfy the condition, false if only one satistying + * interface should stop the wait. + */ +void waitFor(std::set ifnames, WaitCondition cnd, bool allOf = true); + /** * Brings network interface up. * @@ -70,4 +116,22 @@ bool add(std::string dev, std::string type); */ bool del(std::string dev); +/** + * Fetches interface's hardware address. + * + * \param ifname Interface name + * \return Hardware address (MAC address) or nullopt if the lookup failed + */ +std::optional getHwAddr(const std::string& ifname); + +/** + * Changes interface's hardware address. + * + * \param ifname Interface name + * \param hwaddr New hardware address to set + */ +bool setHwAddr(const std::string& ifname, hwaddr_t hwaddr); + } // namespace android::netdevice + +bool operator==(const android::netdevice::hwaddr_t lhs, const unsigned char rhs[ETH_ALEN]); diff --git a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/vlan.h b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/vlan.h new file mode 100644 index 0000000000000000000000000000000000000000..3e1b736ebd2c1e9f9a6143e36f7e44de9b2db033 --- /dev/null +++ b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/vlan.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +namespace android::netdevice::vlan { + +bool add(const std::string& eth, const std::string& vlan, uint16_t id); + +} // namespace android::netdevice::vlan diff --git a/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp b/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp index b05144209e4d4a67a542b03dccdb837677a27f09..4c5b30928fee1f935361225544ce347895231d97 100644 --- a/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp +++ b/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp @@ -16,83 +16,178 @@ #include -#include "NetlinkRequest.h" -#include "NetlinkSocket.h" #include "common.h" +#include "ifreqs.h" #include +#include +#include #include +#include #include +#include + namespace android::netdevice { +void useSocketDomain(int domain) { + ifreqs::socketDomain = domain; +} + bool exists(std::string ifname) { return nametoindex(ifname) != 0; } -static bool sendIfreq(unsigned long request, struct ifreq& ifr) { - /* For general interfaces it would be socket(AF_INET, SOCK_DGRAM, 0), - * but SEPolicy forces us to limit our flexibility here. */ - base::unique_fd sock(socket(PF_CAN, SOCK_RAW, CAN_RAW)); - if (!sock.ok()) { - LOG(ERROR) << "Can't create socket"; - return false; - } +bool up(std::string ifname) { + auto ifr = ifreqs::fromName(ifname); + if (!ifreqs::send(SIOCGIFFLAGS, ifr)) return false; + ifr.ifr_flags |= IFF_UP; + return ifreqs::send(SIOCSIFFLAGS, ifr); +} - if (ioctl(sock.get(), request, &ifr) < 0) { - PLOG(ERROR) << "ioctl(" << std::hex << request << std::dec << ") failed"; - return false; +bool down(std::string ifname) { + auto ifr = ifreqs::fromName(ifname); + if (!ifreqs::send(SIOCGIFFLAGS, ifr)) return false; + ifr.ifr_flags &= ~IFF_UP; + return ifreqs::send(SIOCSIFFLAGS, ifr); +} + +bool add(std::string dev, std::string type) { + nl::MessageFactory req(RTM_NEWLINK, + NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK); + req.add(IFLA_IFNAME, dev); + + { + auto linkinfo = req.addNested(IFLA_LINKINFO); + req.add(IFLA_INFO_KIND, type); } - return true; + nl::Socket sock(NETLINK_ROUTE); + return sock.send(req) && sock.receiveAck(req); } -static struct ifreq ifreqFromName(const std::string& ifname) { - struct ifreq ifr = {}; - strlcpy(ifr.ifr_name, ifname.c_str(), IF_NAMESIZE); - return ifr; +bool del(std::string dev) { + nl::MessageFactory req(RTM_DELLINK, NLM_F_REQUEST | NLM_F_ACK); + req.add(IFLA_IFNAME, dev); + + nl::Socket sock(NETLINK_ROUTE); + return sock.send(req) && sock.receiveAck(req); +} + +std::optional getHwAddr(const std::string& ifname) { + auto ifr = ifreqs::fromName(ifname); + if (!ifreqs::send(SIOCGIFHWADDR, ifr)) return std::nullopt; + + hwaddr_t hwaddr; + memcpy(hwaddr.data(), ifr.ifr_hwaddr.sa_data, hwaddr.size()); + return hwaddr; +} + +bool setHwAddr(const std::string& ifname, hwaddr_t hwaddr) { + auto ifr = ifreqs::fromName(ifname); + + // fetch sa_family + if (!ifreqs::send(SIOCGIFHWADDR, ifr)) return false; + + memcpy(ifr.ifr_hwaddr.sa_data, hwaddr.data(), hwaddr.size()); + return ifreqs::send(SIOCSIFHWADDR, ifr); } std::optional isUp(std::string ifname) { - struct ifreq ifr = ifreqFromName(ifname); - if (!sendIfreq(SIOCGIFFLAGS, ifr)) return std::nullopt; + auto ifr = ifreqs::fromName(ifname); + if (!ifreqs::send(SIOCGIFFLAGS, ifr)) return std::nullopt; return ifr.ifr_flags & IFF_UP; } -bool up(std::string ifname) { - struct ifreq ifr = ifreqFromName(ifname); - if (!sendIfreq(SIOCGIFFLAGS, ifr)) return false; - ifr.ifr_flags |= IFF_UP; - return sendIfreq(SIOCSIFFLAGS, ifr); +struct WaitState { + bool present; + bool up; + + bool satisfied(WaitCondition cnd) const { + switch (cnd) { + case WaitCondition::PRESENT: + if (present) return true; + break; + case WaitCondition::PRESENT_AND_UP: + if (present && up) return true; + break; + case WaitCondition::DOWN_OR_GONE: + if (!present || !up) return true; + break; + } + return false; + } +}; + +static std::string toString(WaitCondition cnd) { + switch (cnd) { + case WaitCondition::PRESENT: + return "become present"; + case WaitCondition::PRESENT_AND_UP: + return "come up"; + case WaitCondition::DOWN_OR_GONE: + return "go down"; + } } -bool down(std::string ifname) { - struct ifreq ifr = ifreqFromName(ifname); - if (!sendIfreq(SIOCGIFFLAGS, ifr)) return false; - ifr.ifr_flags &= ~IFF_UP; - return sendIfreq(SIOCSIFFLAGS, ifr); +static std::string toString(const std::set& ifnames) { + std::stringstream ss; + std::copy(ifnames.begin(), ifnames.end(), std::ostream_iterator(ss, ",")); + auto str = ss.str(); + str.pop_back(); + return str; } -bool add(std::string dev, std::string type) { - NetlinkRequest req(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL); - req.addattr(IFLA_IFNAME, dev); +void waitFor(std::set ifnames, WaitCondition cnd, bool allOf) { + nl::Socket sock(NETLINK_ROUTE, 0, RTMGRP_LINK); - { - auto linkinfo = req.nest(IFLA_LINKINFO); - req.addattr(IFLA_INFO_KIND, type); + using StatesMap = std::map; + StatesMap states = {}; + for (const auto ifname : ifnames) { + const auto present = exists(ifname); + const auto up = present && isUp(ifname).value_or(false); + states[ifname] = {present, up}; } - NetlinkSocket sock(NETLINK_ROUTE); - return sock.send(req) && sock.receiveAck(); + const auto mapConditionChecker = [cnd](const StatesMap::iterator::value_type& it) { + return it.second.satisfied(cnd); + }; + const auto isFullySatisfied = [&states, allOf, mapConditionChecker]() { + if (allOf) { + return std::all_of(states.begin(), states.end(), mapConditionChecker); + } else { + return std::any_of(states.begin(), states.end(), mapConditionChecker); + } + }; + + if (isFullySatisfied()) return; + + LOG(DEBUG) << "Waiting for " << (allOf ? "" : "any of ") << toString(ifnames) << " to " + << toString(cnd); + for (const auto rawMsg : sock) { + const auto msg = nl::Message::parse(rawMsg, {RTM_NEWLINK, RTM_DELLINK}); + if (!msg.has_value()) continue; + + const auto ifname = msg->attributes.get(IFLA_IFNAME); + if (ifnames.count(ifname) == 0) continue; + + const bool present = (msg->header.nlmsg_type != RTM_DELLINK); + const bool up = present && (msg->data.ifi_flags & IFF_UP) != 0; + states[ifname] = {present, up}; + + if (isFullySatisfied()) { + LOG(DEBUG) << "Finished waiting for " << (allOf ? "" : "some of ") << toString(ifnames) + << " to " << toString(cnd); + return; + } + } + LOG(FATAL) << "Can't read Netlink socket"; } -bool del(std::string dev) { - NetlinkRequest req(RTM_DELLINK, NLM_F_REQUEST); - req.addattr(IFLA_IFNAME, dev); +} // namespace android::netdevice - NetlinkSocket sock(NETLINK_ROUTE); - return sock.send(req) && sock.receiveAck(); +bool operator==(const android::netdevice::hwaddr_t lhs, const unsigned char rhs[ETH_ALEN]) { + static_assert(lhs.size() == ETH_ALEN); + return 0 == memcmp(lhs.data(), rhs, lhs.size()); } - -} // namespace android::netdevice diff --git a/automotive/can/1.0/default/libnetdevice/vlan.cpp b/automotive/can/1.0/default/libnetdevice/vlan.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ee02f7b58ab943016184dea6f89b8940d8fbc78c --- /dev/null +++ b/automotive/can/1.0/default/libnetdevice/vlan.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "common.h" + +#include +#include +#include + +#include + +namespace android::netdevice::vlan { + +bool add(const std::string& eth, const std::string& vlan, uint16_t id) { + const auto ethidx = nametoindex(eth); + if (ethidx == 0) { + LOG(ERROR) << "Ethernet interface " << eth << " doesn't exist"; + return false; + } + + nl::MessageFactory req(RTM_NEWLINK, + NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK); + req.add(IFLA_IFNAME, vlan); + req.add(IFLA_LINK, ethidx); + + { + auto linkinfo = req.addNested(IFLA_LINKINFO); + req.add(IFLA_INFO_KIND, "vlan"); + + { + auto linkinfo = req.addNested(IFLA_INFO_DATA); + req.add(IFLA_VLAN_ID, id); + } + } + + nl::Socket sock(NETLINK_ROUTE); + return sock.send(req) && sock.receiveAck(req); +} + +} // namespace android::netdevice::vlan diff --git a/automotive/can/1.0/default/libnl++/Android.bp b/automotive/can/1.0/default/libnl++/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..790adcd073a759c0a17f1b4075f942b39d6832c4 --- /dev/null +++ b/automotive/can/1.0/default/libnl++/Android.bp @@ -0,0 +1,53 @@ +// +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_library_static { + name: "libnl++", + defaults: ["android.hardware.automotive.can@defaults"], + vendor_available: true, + srcs: [ + "protocols/common/Empty.cpp", + "protocols/common/Error.cpp", + "protocols/generic/Ctrl.cpp", + "protocols/generic/FamilyTracker.cpp", + "protocols/generic/Generic.cpp", + "protocols/generic/GenericMessageBase.cpp", + "protocols/generic/Unknown.cpp", + "protocols/generic/families/Nl80211.cpp", + "protocols/route/Link.cpp", + "protocols/route/Route.cpp", + "protocols/route/structs.cpp", + "protocols/MessageDefinition.cpp", + "protocols/NetlinkProtocol.cpp", + "protocols/all.cpp", + "Attributes.cpp", + "MessageFactory.cpp", + "MessageMutator.cpp", + "Socket.cpp", + "common.cpp", + "printer.cpp", + ], + export_include_dirs: ["include"], +} diff --git a/automotive/can/1.0/default/libnl++/Attributes.cpp b/automotive/can/1.0/default/libnl++/Attributes.cpp new file mode 100644 index 0000000000000000000000000000000000000000..620f57b2f625402048f7eca8d352c62211b65105 --- /dev/null +++ b/automotive/can/1.0/default/libnl++/Attributes.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace android::nl { + +Attributes::Attributes() {} + +Attributes::Attributes(Buffer buffer) : Buffer(buffer) {} + +const Attributes::Index& Attributes::index() const { + if (mIndex.has_value()) return *mIndex; + + mIndex = Index(); + auto& index = *mIndex; + + for (auto attr : static_cast>(*this)) { + index.emplace(attr->nla_type, attr); + } + + return index; +} + +bool Attributes::contains(nlattrtype_t attrtype) const { + return index().count(attrtype) > 0; +} + +/* Parser specializations for selected types (more to come if necessary). */ + +template <> +Attributes Attributes::parse(Buffer buf) { + return buf.data(); +} + +template <> +std::string Attributes::parse(Buffer buf) { + const auto rawString = buf.data().getRaw(); + std::string str(rawString.ptr(), rawString.len()); + + str.erase(std::find(str.begin(), str.end(), '\0'), str.end()); + + return str; +} + +template +static T parseUnsigned(Buffer buf) { + return buf.data().copyFirst(); +} + +template <> +uint8_t Attributes::parse(Buffer buf) { + return parseUnsigned(buf); +} + +template <> +uint16_t Attributes::parse(Buffer buf) { + return parseUnsigned(buf); +} + +template <> +uint32_t Attributes::parse(Buffer buf) { + return parseUnsigned(buf); +} + +template <> +uint64_t Attributes::parse(Buffer buf) { + return parseUnsigned(buf); +} + +} // namespace android::nl diff --git a/automotive/can/1.0/default/libnl++/MessageFactory.cpp b/automotive/can/1.0/default/libnl++/MessageFactory.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6f35897e322ee79149bc0285e59636157117ee1a --- /dev/null +++ b/automotive/can/1.0/default/libnl++/MessageFactory.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include + +namespace android::nl { + +static nlattr* tail(nlmsghdr* msg) { + return reinterpret_cast(uintptr_t(msg) + impl::align(msg->nlmsg_len)); +} + +nlattr* MessageFactoryBase::add(nlmsghdr* msg, size_t maxLen, nlattrtype_t type, const void* data, + size_t dataLen) { + const auto totalAttrLen = impl::space(dataLen); + const auto newLen = impl::align(msg->nlmsg_len) + totalAttrLen; + if (newLen > maxLen) { + LOG(ERROR) << "Can't add attribute of size " << dataLen // + << " - exceeded maxLen: " << newLen << " > " << maxLen; + return nullptr; + } + + auto attr = tail(msg); + attr->nla_len = totalAttrLen; + attr->nla_type = type; + if (dataLen > 0) memcpy(impl::data(attr), data, dataLen); + + msg->nlmsg_len = newLen; + return attr; +} + +void MessageFactoryBase::closeNested(nlmsghdr* msg, nlattr* nested) { + if (nested == nullptr) return; + nested->nla_len = uintptr_t(tail(msg)) - uintptr_t(nested); +} + +} // namespace android::nl diff --git a/automotive/can/1.0/default/libnl++/MessageMutator.cpp b/automotive/can/1.0/default/libnl++/MessageMutator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..00b48a66ae19d37526e9a36e0ec4cbda184f21c2 --- /dev/null +++ b/automotive/can/1.0/default/libnl++/MessageMutator.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace android::nl { + +MessageMutator::MessageMutator(nlmsghdr* buffer, size_t totalLen) + : mConstBuffer(buffer, totalLen), mMutableBuffer(buffer) { + CHECK(totalLen >= sizeof(nlmsghdr)); +} + +nlmsghdr* MessageMutator::operator->() const { + return mMutableBuffer; +} + +MessageMutator::operator Buffer() const { + return mConstBuffer; +} + +uint64_t MessageMutator::read(Buffer attr) const { + return attr.data().copyFirst(); +} + +void MessageMutator::write(Buffer attr, uint64_t val) const { + const auto attrData = attr.data(); + const auto offset = mConstBuffer.getOffset(attrData); + CHECK(offset.has_value()) << "Trying to write attribute that's not a member of this message"; + + const auto writeableBuffer = reinterpret_cast(mMutableBuffer) + *offset; + const auto attrSize = attrData.getRaw().len(); + + if (attrSize > sizeof(val)) memset(writeableBuffer, 0, attrSize); + memcpy(writeableBuffer, &val, std::min(sizeof(val), attrSize)); +} + +} // namespace android::nl diff --git a/automotive/can/1.0/default/libnl++/Socket.cpp b/automotive/can/1.0/default/libnl++/Socket.cpp new file mode 100644 index 0000000000000000000000000000000000000000..514d9bb1b9238d75778bdd66e5183aff0d1a798a --- /dev/null +++ b/automotive/can/1.0/default/libnl++/Socket.cpp @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +#include + +namespace android::nl { + +/** + * Print all outbound/inbound Netlink messages. + */ +static constexpr bool kSuperVerbose = false; + +Socket::Socket(int protocol, unsigned pid, uint32_t groups) : mProtocol(protocol) { + mFd.reset(socket(AF_NETLINK, SOCK_RAW, protocol)); + if (!mFd.ok()) { + PLOG(ERROR) << "Can't open Netlink socket"; + mFailed = true; + return; + } + + sockaddr_nl sa = {}; + sa.nl_family = AF_NETLINK; + sa.nl_pid = pid; + sa.nl_groups = groups; + + if (bind(mFd.get(), reinterpret_cast(&sa), sizeof(sa)) < 0) { + PLOG(ERROR) << "Can't bind Netlink socket"; + mFd.reset(); + mFailed = true; + } +} + +bool Socket::send(const Buffer& msg, const sockaddr_nl& sa) { + if constexpr (kSuperVerbose) { + LOG(VERBOSE) << (mFailed ? "(not) " : "") << "sending to " << sa.nl_pid << ": " + << toString(msg, mProtocol); + } + if (mFailed) return false; + + mSeq = msg->nlmsg_seq; + const auto rawMsg = msg.getRaw(); + const auto bytesSent = sendto(mFd.get(), rawMsg.ptr(), rawMsg.len(), 0, + reinterpret_cast(&sa), sizeof(sa)); + if (bytesSent < 0) { + PLOG(ERROR) << "Can't send Netlink message"; + return false; + } else if (size_t(bytesSent) != rawMsg.len()) { + LOG(ERROR) << "Can't send Netlink message: truncated message"; + return false; + } + return true; +} + +bool Socket::increaseReceiveBuffer(size_t maxSize) { + if (maxSize == 0) { + LOG(ERROR) << "Maximum receive size should not be zero"; + return false; + } + + if (mReceiveBuffer.size() < maxSize) mReceiveBuffer.resize(maxSize); + return true; +} + +std::optional> Socket::receive(size_t maxSize) { + return receiveFrom(maxSize).first; +} + +std::pair>, sockaddr_nl> Socket::receiveFrom(size_t maxSize) { + if (mFailed) return {std::nullopt, {}}; + + if (!increaseReceiveBuffer(maxSize)) return {std::nullopt, {}}; + + sockaddr_nl sa = {}; + socklen_t saLen = sizeof(sa); + const auto bytesReceived = recvfrom(mFd.get(), mReceiveBuffer.data(), maxSize, MSG_TRUNC, + reinterpret_cast(&sa), &saLen); + + if (bytesReceived <= 0) { + PLOG(ERROR) << "Failed to receive Netlink message"; + return {std::nullopt, {}}; + } else if (size_t(bytesReceived) > maxSize) { + PLOG(ERROR) << "Received data larger than maximum receive size: " // + << bytesReceived << " > " << maxSize; + return {std::nullopt, {}}; + } + + Buffer msg(reinterpret_cast(mReceiveBuffer.data()), bytesReceived); + if constexpr (kSuperVerbose) { + LOG(VERBOSE) << "received from " << sa.nl_pid << ": " << toString(msg, mProtocol); + } + return {msg, sa}; +} + +bool Socket::receiveAck(uint32_t seq) { + const auto nlerr = receive({NLMSG_ERROR}); + if (!nlerr.has_value()) return false; + + if (nlerr->data.msg.nlmsg_seq != seq) { + LOG(ERROR) << "Received ACK for a different message (" << nlerr->data.msg.nlmsg_seq + << ", expected " << seq << "). Multi-message tracking is not implemented."; + return false; + } + + if (nlerr->data.error == 0) return true; + + LOG(WARNING) << "Received Netlink error message: " << strerror(-nlerr->data.error); + return false; +} + +std::optional> Socket::receive(const std::set& msgtypes, + size_t maxSize) { + if (mFailed || !increaseReceiveBuffer(maxSize)) return std::nullopt; + + for (const auto rawMsg : *this) { + if (msgtypes.count(rawMsg->nlmsg_type) == 0) { + LOG(WARNING) << "Received (and ignored) unexpected Netlink message of type " + << rawMsg->nlmsg_type; + continue; + } + + return rawMsg; + } + + return std::nullopt; +} + +std::optional Socket::getPid() { + if (mFailed) return std::nullopt; + + sockaddr_nl sa = {}; + socklen_t sasize = sizeof(sa); + if (getsockname(mFd.get(), reinterpret_cast(&sa), &sasize) < 0) { + PLOG(ERROR) << "Failed to get PID of Netlink socket"; + return std::nullopt; + } + return sa.nl_pid; +} + +pollfd Socket::preparePoll(short events) { + return {mFd.get(), events, 0}; +} + +Socket::receive_iterator::receive_iterator(Socket& socket, bool end) + : mSocket(socket), mIsEnd(end) { + if (!end) receive(); +} + +Socket::receive_iterator Socket::receive_iterator::operator++() { + CHECK(!mIsEnd) << "Trying to increment end iterator"; + ++mCurrent; + if (mCurrent.isEnd()) receive(); + return *this; +} + +bool Socket::receive_iterator::operator==(const receive_iterator& other) const { + if (mIsEnd != other.mIsEnd) return false; + if (mIsEnd && other.mIsEnd) return true; + return mCurrent == other.mCurrent; +} + +const Buffer& Socket::receive_iterator::operator*() const { + CHECK(!mIsEnd) << "Trying to dereference end iterator"; + return *mCurrent; +} + +void Socket::receive_iterator::receive() { + CHECK(!mIsEnd) << "Trying to receive on end iterator"; + CHECK(mCurrent.isEnd()) << "Trying to receive without draining previous read"; + + const auto buf = mSocket.receive(); + if (buf.has_value()) { + mCurrent = buf->begin(); + } else { + mIsEnd = true; + } +} + +Socket::receive_iterator Socket::begin() { + return {*this, false}; +} + +Socket::receive_iterator Socket::end() { + return {*this, true}; +} + +} // namespace android::nl diff --git a/automotive/can/1.0/default/libnl++/common.cpp b/automotive/can/1.0/default/libnl++/common.cpp new file mode 100644 index 0000000000000000000000000000000000000000..23c2d94a6d97a0a65db4ecee1af12477b69284c9 --- /dev/null +++ b/automotive/can/1.0/default/libnl++/common.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#include + +#include + +namespace android::nl { + +unsigned int nametoindex(const std::string& ifname) { + const auto ifidx = if_nametoindex(ifname.c_str()); + if (ifidx != 0) return ifidx; + + if (errno != ENODEV) { + PLOG(ERROR) << "if_nametoindex(" << ifname << ") failed"; + } + return 0; +} + +std::string printableOnly(std::string str) { + const auto isInvalid = [](char c) { return !isprint(c); }; + std::replace_if(str.begin(), str.end(), isInvalid, '?'); + + return str; +} + +uint16_t crc16(const Buffer data, uint16_t crc) { + for (const auto byte : data.getRaw()) { + crc ^= byte; + for (unsigned i = 0; i < 8; i++) { + if (crc & 1) { + crc = (crc >> 1) ^ 0xA001; + } else { + crc >>= 1; + } + } + } + return crc; +} + +} // namespace android::nl diff --git a/automotive/can/1.0/default/libnl++/common.h b/automotive/can/1.0/default/libnl++/common.h new file mode 100644 index 0000000000000000000000000000000000000000..38263c5173ee06ec804d5f837042ddf0fa129346 --- /dev/null +++ b/automotive/can/1.0/default/libnl++/common.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include +#include + +#include + +namespace android::nl { + +/** + * Returns the index of a given network interface. + * + * If the syscall to check the index fails with other error than ENODEV, it gets logged and the + * return value indicates the interface doesn't exists. + * + * \param ifname Interface to check + * \return Interface index, or 0 if the interface doesn't exist + */ +unsigned int nametoindex(const std::string& ifname); + +/** + * Filter a string against non-printable characters. + * + * Replaces all non-printable characters with '?'. + * + * \param str String to filter. + * \return Filtered string. + */ +std::string printableOnly(std::string str); + +/** + * Calculates a (optionally running) CRC16 checksum. + * + * CRC16 isn't a strong checksum, but is good for quick comparison purposes. + * One benefit (and also a drawback too) is that all-zero payloads with any length will + * always have a checksum of 0x0000. + * + * \param data Buffer to calculate checksum for + * \param crc Previous CRC16 value to continue calculating running checksum + * \return CRC16 checksum + */ +uint16_t crc16(const Buffer data, uint16_t crc = 0); + +} // namespace android::nl diff --git a/automotive/can/1.0/default/libnl++/include/libnl++/Attributes.h b/automotive/can/1.0/default/libnl++/include/libnl++/Attributes.h new file mode 100644 index 0000000000000000000000000000000000000000..a438a69932ca1a55be3e9074ae0726fd6f12b74e --- /dev/null +++ b/automotive/can/1.0/default/libnl++/include/libnl++/Attributes.h @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +#include + +#include + +namespace android::nl { + +/** + * Netlink attribute map. + * + * This is a C++-style, memory safe(r) implementation of linux/netlink.h macros accessing Netlink + * message attributes. The class doesn't own the underlying data, so the instance is valid as long + * as the source buffer is allocated and unmodified. + * + * WARNING: this class is NOT thread-safe (it's safe to be used in multithreaded application, but + * a single instance can only be used by a single thread - the one owning the underlying buffer). + */ +class Attributes : private Buffer { + public: + /** + * Constructs empty attribute map. + */ + Attributes(); + + /** + * Construct attribute map from underlying buffer. + * + * \param buffer Source buffer pointing at the first attribute. + */ + Attributes(Buffer buffer); + + /** + * Checks, if the map contains given attribute type (key). + * + * \param attrtype Attribute type (such as IFLA_IFNAME). + * \return true if attribute is in the map, false otherwise. + */ + bool contains(nlattrtype_t attrtype) const; + + /** + * Fetches attribute of a given type by copying it. + * + * While this is quite efficient for simple types, fetching nested attribute creates a new copy + * of child attribute map. This may be costly if you calculate the index for child maps multiple + * times. Examples below. + * + * BAD: + * ``` + * const auto flags = msg->attributes. + * get(IFLA_AF_SPEC). + * get(AF_INET6). // IFLA_AF_SPEC index lazy-calculated + * get(IFLA_INET6_FLAGS); // AF_INET6 index lazy-calculated + * const auto& cacheinfo = msg->attributes. + * get(IFLA_AF_SPEC). // new instance of IFLA_AF_SPEC index + * get(AF_INET6). // IFLA_AF_SPEC index calculated again + * getStruct(IFLA_INET6_CACHEINFO); // AF_INET6 calculated again + * ``` + * + * GOOD: + * ``` + * const auto inet6 = msg->attributes. + * get(IFLA_AF_SPEC). + * get(AF_INET6); + * const auto flags = inet6.get(IFLA_INET6_FLAGS); // AF_INET6 index lazy-calculated + * const auto& cache = inet6.getStruct(IFLA_INET6_CACHEINFO); // index reused + * ``` + * + * If the attribute doesn't exists, default value of a given type is returned and warning + * spawned into the log. To check for attribute existence, \see contains(nlattrtype_t). + * + * \param attrtype Attribute to fetch. + * \return Attribute value. + */ + template + T get(nlattrtype_t attrtype) const { + const auto buffer = getBuffer(attrtype); + if (!buffer.has_value()) { + LOG(WARNING) << "Netlink attribute is missing: " << attrtype; + return T{}; + } + + return parse(*buffer); + } + + /** + * Fetches underlying buffer of a given attribute. + * + * This is a low-level access method unlikely to be useful in most cases. Please consider + * using #get instead. + * + * \param attrtype Attribute to fetch + * \return Attribute buffer. + */ + std::optional> getBuffer(nlattrtype_t attrtype) const { + const auto& ind = index(); + const auto it = ind.find(attrtype); + if (it == ind.end()) return std::nullopt; + return it->second; + } + + /** + * Fetches a reference to a given attribute's data. + * + * This method is intended for arbitrary structures not specialized with get(nlattrtype_t) + * template and slightly more efficient for larger payloads due to not copying its data. + * + * If the attribute doesn't exists, a reference to empty value of a given type is returned and + * warning spawned into the log. To check for attribute existence, \see contains(nlattrtype_t). + * + * \param attrtype Attribute to fetch. + * \return Reference to the attribute's data. + */ + template + const T& getStruct(nlattrtype_t attrtype) const { + const auto& ind = index(); + const auto it = ind.find(attrtype); + if (it == ind.end()) { + LOG(WARNING) << "Netlink attribute is missing: " << attrtype; + static const T empty = {}; + return empty; + } + + const auto& [ok, val] = it->second.data().getFirst(); + if (!ok) LOG(WARNING) << "Can't fetch structure of size " << sizeof(T); + return val; + } + + private: + using Index = std::map>; + + /** + * Attribute index. + * + * Since this field is not protected by mutex, the use of \see index() dependent methods + * (such as \see get(nlattrtype_t)) is not thread-safe. This is a compromise made based on the + * following assumptions: + * + * 1. Most (or even all) use-cases involve attribute parsing in the same thread as where the + * buffer was allocated. This is partly forced by a dependence of nlmsg lifecycle on the + * underlying data buffer. + * + * 2. Index calculation and access would come with performance penalty never justified in most + * or all use cases (see the previous point). Since Index is not a trivially assignable data + * structure, it's not possible to use it with atomic types only and avoid mutexes. + */ + mutable std::optional mIndex; + + /** + * Lazy-calculate and cache index. + * + * \return Attribute index. + */ + const Index& index() const; + + /** + * Parse attribute data into a specific type. + * + * \param buf Raw attribute data. + * \return Parsed data. + */ + template + static T parse(Buffer buf); +}; + +} // namespace android::nl diff --git a/automotive/can/1.0/default/libnl++/include/libnl++/Buffer.h b/automotive/can/1.0/default/libnl++/include/libnl++/Buffer.h new file mode 100644 index 0000000000000000000000000000000000000000..d759a0a570b44c9ca6b8a97c3382816b79e27fdd --- /dev/null +++ b/automotive/can/1.0/default/libnl++/include/libnl++/Buffer.h @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +#include + +#include + +namespace android::nl { + +/** + * Buffer wrapper containing netlink structure (e.g. nlmsghdr, nlattr). + * + * This is a C++-style, memory safe(r) and generic implementation of linux/netlink.h macros. + * + * While netlink structures contain information about their total length (with payload), they can + * not be trusted - the value may either be larger than the buffer message is allocated in or + * smaller than the header itself (so it couldn't even fit itself). + * + * As a solution, Buffer<> keeps track of two lengths (both attribute for header with payload): + * - buffer length - how much memory was allocated to a given structure + * - declared length - what nlmsg_len or nla_len says how long the structure is + * + * In most cases buffer length would be larger than declared length (or equal - modulo alignment - + * for continuous data). If that's not the case, there is a potential of ouf-of-bounds read which + * this template attempts to protect against. + */ +template +class Buffer { + public: + /** + * Constructs empty buffer of size 0. + */ + Buffer() : mData(nullptr), mBufferEnd(nullptr) {} + + /** + * Buffer constructor. + * + * \param data A pointer to the data the Buffer wraps. + * \param bufLen Length of the buffer. + */ + Buffer(const T* data, size_t bufLen) : mData(data), mBufferEnd(pointerAdd(data, bufLen)) {} + + const T* operator->() const { + CHECK(firstOk()) << "buffer can't fit the first element's header"; + return mData; + } + + std::pair getFirst() const { + if (!ok()) { + static const T empty = {}; + return {false, empty}; + } + return {true, *mData}; + } + + /** + * Copy the first element of the buffer. + * + * This is a memory-safe cast operation, useful for reading e.g. uint32_t values + * from 1-byte buffer. If the buffer is smaller than the copied type, the rest is + * padded with default constructor output (usually zeros). + */ + T copyFirst() const { + T val = {}; + memcpy(&val, mData, std::min(sizeof(val), remainingLength())); + return val; + } + + bool firstOk() const { return sizeof(T) <= remainingLength(); } + + template + const Buffer data(size_t offset = 0) const { + return {impl::data(mData, offset), dataEnd()}; + } + + template + std::optional getOffset(Buffer inner) const { + const auto selfStart = uintptr_t(mData); + const auto selfEnd = uintptr_t(mBufferEnd); + const auto innerStart = uintptr_t(inner.mData); + const auto innerEnd = uintptr_t(inner.mBufferEnd); + + if (innerStart < selfStart || innerEnd > selfEnd) return std::nullopt; + + return innerStart - selfStart; + } + + class iterator { + public: + iterator() : mCurrent(nullptr, size_t(0)) { + CHECK(isEnd()) << "end() iterator should indicate it's beyond end"; + } + iterator(const Buffer& buf) : mCurrent(buf) {} + + iterator operator++() { + // mBufferEnd stays the same + mCurrent.mData = reinterpret_cast( // + uintptr_t(mCurrent.mData) + impl::align(mCurrent.declaredLength())); + + return *this; + } + + bool operator==(const iterator& other) const { + // all iterators beyond end are the same + if (isEnd() && other.isEnd()) return true; + + return uintptr_t(other.mCurrent.mData) == uintptr_t(mCurrent.mData); + } + + const Buffer& operator*() const { return mCurrent; } + + bool isEnd() const { return !mCurrent.ok(); } + + protected: + Buffer mCurrent; + }; + iterator begin() const { return {*this}; } + iterator end() const { return {}; } + + class raw_iterator : public iterator { + public: + iterator operator++() { + this->mCurrent.mData++; // ignore alignment + return *this; + } + const T& operator*() const { return *this->mCurrent.mData; } + }; + + class raw_view { + public: + raw_view(const Buffer& buffer) : mBuffer(buffer) {} + raw_iterator begin() const { return {mBuffer}; } + raw_iterator end() const { return {}; } + + const T* ptr() const { return mBuffer.mData; } + size_t len() const { return mBuffer.remainingLength(); } + + private: + const Buffer mBuffer; + }; + + raw_view getRaw() const { return {*this}; } + + private: + const T* mData; + const void* mBufferEnd; + + Buffer(const T* data, const void* bufferEnd) : mData(data), mBufferEnd(bufferEnd) {} + + bool ok() const { return declaredLength() <= remainingLength(); } + + // to be specialized individually for each T with payload after a header + inline size_t declaredLengthImpl() const { return sizeof(T); } + + size_t declaredLength() const { + // We can't even fit a header, so let's return some absurd high value to trip off + // buffer overflow checks. + static constexpr size_t badHeaderLength = std::numeric_limits::max() / 2; + + if (sizeof(T) > remainingLength()) return badHeaderLength; + const auto len = declaredLengthImpl(); + if (sizeof(T) > len) return badHeaderLength; + return len; + } + + size_t remainingLength() const { + auto len = intptr_t(mBufferEnd) - intptr_t(mData); + return (len >= 0) ? len : 0; + } + + const void* dataEnd() const { + auto declaredEnd = pointerAdd(mData, declaredLength()); + return std::min(declaredEnd, mBufferEnd); + } + + static const void* pointerAdd(const void* ptr, size_t len) { + return reinterpret_cast(uintptr_t(ptr) + len); + } + + template + friend class Buffer; // calling private constructor of data buffers +}; + +template <> +inline size_t Buffer::declaredLengthImpl() const { + return mData->nlmsg_len; +} + +template <> +inline size_t Buffer::declaredLengthImpl() const { + return mData->nla_len; +} + +} // namespace android::nl diff --git a/automotive/can/1.0/default/libnl++/include/libnl++/Message.h b/automotive/can/1.0/default/libnl++/include/libnl++/Message.h new file mode 100644 index 0000000000000000000000000000000000000000..50b3c4b05d4278cba0c324db0755c72eae1426dd --- /dev/null +++ b/automotive/can/1.0/default/libnl++/include/libnl++/Message.h @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +#include + +namespace android::nl { + +/** + * In-place Netlink message parser. + * + * This is a C++-style, memory safe(r) implementation of linux/netlink.h macros accessing Netlink + * message contents. The class doesn't own the underlying data, so the instance is valid as long as + * the source buffer is allocated and unmodified. + * + * WARNING: this class is NOT thread-safe (it's safe to be used in multithreaded application, but + * a single instance can only be used by a single thread - the one owning the underlying buffer). + */ +template +class Message { + public: + /** + * Validate buffer contents as a message carrying T data and create instance of parsed message. + * + * \param buf Buffer containing the message. + * \return Parsed message or nullopt, if the buffer data is invalid. + */ + static std::optional> parse(Buffer buf) { + const auto& [nlOk, nlHeader] = buf.getFirst(); + if (!nlOk) return std::nullopt; + + const auto& [dataOk, dataHeader] = buf.data().getFirst(); + if (!dataOk) return std::nullopt; + + const auto attributes = buf.data(sizeof(T)); + + return Message(nlHeader, dataHeader, attributes); + } + + /** + * Validate buffer contents as a message of a given type and create instance of parsed message. + * + * \param buf Buffer containing the message. + * \param msgtypes Acceptable message types (within a specific Netlink protocol) + * \return Parsed message or nullopt, if the buffer data is invalid or message type + * doesn't match. + */ + static std::optional> parse(Buffer buf, + const std::set& msgtypes) { + const auto& [nlOk, nlHeader] = buf.getFirst(); // we're doing it twice, but it's fine + if (!nlOk) return std::nullopt; + + if (msgtypes.count(nlHeader.nlmsg_type) == 0) return std::nullopt; + + return parse(buf); + } + + /** + * Netlink message header. + * + * This is a generic Netlink header containing information such as message flags. + */ + const nlmsghdr& header; + + /** + * Netlink message data. + * + * This is a payload specific to a given message type. + */ + const T& data; + + /** + * Netlink message attributes. + */ + const Attributes attributes; + + const T* operator->() const { return &data; } + + private: + Message(const nlmsghdr& nlHeader, const T& dataHeader, Attributes attributes) + : header(nlHeader), data(dataHeader), attributes(attributes) {} +}; + +} // namespace android::nl diff --git a/automotive/can/1.0/default/libnl++/include/libnl++/MessageFactory.h b/automotive/can/1.0/default/libnl++/include/libnl++/MessageFactory.h new file mode 100644 index 0000000000000000000000000000000000000000..c3d72c54e23f71c18361c158672158af453901a8 --- /dev/null +++ b/automotive/can/1.0/default/libnl++/include/libnl++/MessageFactory.h @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include + +#include + +#include + +namespace android::nl { + +class MessageFactoryBase { + protected: + static nlattr* add(nlmsghdr* msg, size_t maxLen, nlattrtype_t type, const void* data, + size_t dataLen); + static void closeNested(nlmsghdr* msg, nlattr* nested); +}; + +/** + * Wrapper around NETLINK_ROUTE messages, to build them in C++ style. + * + * \param T Message payload type (such as ifinfomsg). + * \param BUFSIZE how much space to reserve for attributes. + */ +template +class MessageFactory : private MessageFactoryBase { + struct alignas(NLMSG_ALIGNTO) Message { + nlmsghdr header; + T data; + uint8_t attributesBuffer[BUFSIZE]; + }; + + public: + /** + * Create empty message. + * + * \param type Message type (such as RTM_NEWLINK). + * \param flags Message flags (such as NLM_F_REQUEST). + */ + MessageFactory(nlmsgtype_t type, uint16_t flags) + : header(mMessage.header), data(mMessage.data) { + mMessage.header.nlmsg_len = offsetof(Message, attributesBuffer); + mMessage.header.nlmsg_type = type; + mMessage.header.nlmsg_flags = flags; + } + + /** + * Netlink message header. + * + * This is a generic Netlink header containing information such as message flags. + */ + nlmsghdr& header; + + /** + * Netlink message data. + * + * This is a payload specific to a given message type. + */ + T& data; + + T* operator->() { return &mMessage.data; } + + /** + * Build netlink message. + * + * In fact, this operation is almost a no-op, since the factory builds the message in a single + * buffer, using native data structures. + * + * A likely failure case is when the BUFSIZE template parameter is too small to acommodate + * added attributes. In such a case, please increase this parameter. + * + * \return Netlink message or std::nullopt in case of failure. + */ + std::optional> build() const { + if (!mIsGood) return std::nullopt; + return {{&mMessage.header, mMessage.header.nlmsg_len}}; + } + + /** + * Adds an attribute of a trivially copyable type. + * + * Template specializations may extend this function for other types, such as std::string. + * + * If this method fails (i.e. due to insufficient space), a warning will be printed to the log + * and the message will be marked as bad, causing later \see build call to fail. + * + * \param type attribute type (such as IFLA_IFNAME) + * \param attr attribute data + */ + template + void add(nlattrtype_t type, const A& attr) { + add(type, &attr, sizeof(attr)); + } + + template <> + void add(nlattrtype_t type, const std::string& s) { + add(type, s.c_str(), s.size() + 1); + } + + /** Guard class to frame nested attributes. \see addNested(nlattrtype_t). */ + class [[nodiscard]] NestedGuard { + public: + NestedGuard(MessageFactory & req, nlattrtype_t type) : mReq(req), mAttr(req.add(type)) {} + ~NestedGuard() { closeNested(&mReq.mMessage.header, mAttr); } + + private: + MessageFactory& mReq; + nlattr* mAttr; + + DISALLOW_COPY_AND_ASSIGN(NestedGuard); + }; + + /** + * Add nested attribute. + * + * The returned object is a guard for auto-nesting children inside the argument attribute. + * When the guard object goes out of scope, the nesting attribute is closed. + * + * Example usage nesting IFLA_CAN_BITTIMING inside IFLA_INFO_DATA, which is nested + * inside IFLA_LINKINFO: + * MessageFactory req(RTM_NEWLINK, NLM_F_REQUEST); + * { + * auto linkinfo = req.addNested(IFLA_LINKINFO); + * req.add(IFLA_INFO_KIND, "can"); + * { + * auto infodata = req.addNested(IFLA_INFO_DATA); + * req.add(IFLA_CAN_BITTIMING, bitTimingStruct); + * } + * } + * // use req + * + * \param type attribute type (such as IFLA_LINKINFO) + */ + NestedGuard addNested(nlattrtype_t type) { return {*this, type}; } + + private: + Message mMessage = {}; + bool mIsGood = true; + + nlattr* add(nlattrtype_t type, const void* data = nullptr, size_t len = 0) { + if (!mIsGood) return nullptr; + auto attr = MessageFactoryBase::add(&mMessage.header, sizeof(mMessage), type, data, len); + if (attr == nullptr) mIsGood = false; + return attr; + } +}; + +} // namespace android::nl diff --git a/automotive/can/1.0/default/libnl++/include/libnl++/MessageMutator.h b/automotive/can/1.0/default/libnl++/include/libnl++/MessageMutator.h new file mode 100644 index 0000000000000000000000000000000000000000..7d495e9a5b1f86bc1b780848ca0c9228c317cc8c --- /dev/null +++ b/automotive/can/1.0/default/libnl++/include/libnl++/MessageMutator.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +namespace android::nl { + +/** + * In-place message mutator. + * + * Useful for making small changes (such as adjusting const-sized attributes or struct fields) + * efficiently and in-place. However, if you need to rebuild the message (e.g. to modify variable + * sized attributes or add/remove them), you need to use MessageFactory instead. + */ +class MessageMutator { + public: + /** + * Construct message mutator object from editable buffer. + */ + MessageMutator(nlmsghdr* buffer, size_t totalLen); + + nlmsghdr* operator->() const; + operator Buffer() const; + + /** + * Read current attribute value. + * + * \param Read-only attribute buffer. + * \returns Attribute value. + */ + uint64_t read(Buffer attr) const; + + /** + * Write new attribute value. + * + * \param Read-only attribute buffer. + * \param val New value to set. + */ + void write(Buffer attr, uint64_t val) const; + + private: + const Buffer mConstBuffer; + nlmsghdr* mMutableBuffer; +}; + +} // namespace android::nl diff --git a/automotive/can/1.0/default/libnl++/include/libnl++/Socket.h b/automotive/can/1.0/default/libnl++/include/libnl++/Socket.h new file mode 100644 index 0000000000000000000000000000000000000000..8ea3575720fc56fbd6950dac8b319a82f29e7b8d --- /dev/null +++ b/automotive/can/1.0/default/libnl++/include/libnl++/Socket.h @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +namespace android::nl { + +/** + * A wrapper around AF_NETLINK sockets. + * + * This class is not thread safe to use a single instance between multiple threads, but it's fine to + * use multiple instances over multiple threads. + */ +class Socket { + public: + static constexpr size_t defaultReceiveSize = 8192; + + /** + * Socket constructor. + * + * \param protocol the Netlink protocol to use. + * \param pid port id. Default value of 0 allows the kernel to assign us a unique pid. + * (NOTE: this is NOT the same as process id). + * \param groups Netlink multicast groups to listen to. This is a 32-bit bitfield, where each + * bit is a different group. Default value of 0 means no groups are selected. + * See man netlink.7. + * for more details. + */ + Socket(int protocol, unsigned pid = 0, uint32_t groups = 0); + + /** + * Send Netlink message with incremented sequence number to the Kernel. + * + * \param msg Message to send. Its sequence number will be updated. + * \return true, if succeeded. + */ + template + bool send(MessageFactory& req) { + sockaddr_nl sa = {}; + sa.nl_family = AF_NETLINK; + sa.nl_pid = 0; // Kernel + return send(req, sa); + } + + /** + * Send Netlink message with incremented sequence number. + * + * \param msg Message to send. Its sequence number will be updated. + * \param sa Destination address. + * \return true, if succeeded. + */ + template + bool send(MessageFactory& req, const sockaddr_nl& sa) { + req.header.nlmsg_seq = mSeq + 1; + + const auto msg = req.build(); + if (!msg.has_value()) return false; + + return send(*msg, sa); + } + + /** + * Send Netlink message. + * + * \param msg Message to send. + * \param sa Destination address. + * \return true, if succeeded. + */ + bool send(const Buffer& msg, const sockaddr_nl& sa); + + /** + * Receive one or multiple Netlink messages. + * + * WARNING: the underlying buffer is owned by Socket class and the data is valid until the next + * call to the read function or until deallocation of Socket instance. + * + * \param maxSize Maximum total size of received messages + * \return Buffer view with message data, std::nullopt on error. + */ + std::optional> receive(size_t maxSize = defaultReceiveSize); + + /** + * Receive one or multiple Netlink messages and the sender process address. + * + * WARNING: the underlying buffer is owned by Socket class and the data is valid until the next + * call to the read function or until deallocation of Socket instance. + * + * \param maxSize Maximum total size of received messages. + * \return A pair (for use with structured binding) containing: + * - buffer view with message data, std::nullopt on error; + * - sender process address. + */ + std::pair>, sockaddr_nl> receiveFrom( + size_t maxSize = defaultReceiveSize); + + /** + * Receive matching Netlink message of a given payload type. + * + * This method should be used if the caller expects exactly one incoming message of exactly + * given type (such as ACK). If there is a use case to handle multiple types of messages, + * please use receive(size_t) directly and iterate through potential multipart messages. + * + * If this method is used in such an environment, it will only return the first matching message + * from multipart packet and will issue warnings on messages that do not match. + * + * \param msgtypes Expected message types (such as NLMSG_ERROR). + * \param maxSize Maximum total size of received messages. + * \return Parsed message or std::nullopt in case of error. + */ + template + std::optional> receive(const std::set& msgtypes, + size_t maxSize = defaultReceiveSize) { + const auto msg = receive(msgtypes, maxSize); + if (!msg.has_value()) return std::nullopt; + + const auto parsed = Message::parse(*msg); + if (!parsed.has_value()) { + LOG(WARNING) << "Received matching Netlink message, but couldn't parse it"; + return std::nullopt; + } + + return parsed; + } + + /** + * Receive Netlink ACK message. + * + * \param req Message to match sequence number against. + * \return true if received ACK message, false in case of error. + */ + template + bool receiveAck(MessageFactory& req) { + return receiveAck(req.header.nlmsg_seq); + } + + /** + * Receive Netlink ACK message. + * + * \param seq Sequence number of message to ACK. + * \return true if received ACK message, false in case of error. + */ + bool receiveAck(uint32_t seq); + + /** + * Fetches the socket PID. + * + * \return PID that socket is bound to or std::nullopt. + */ + std::optional getPid(); + + /** + * Creates a pollfd object for the socket. + * + * \param events Value for pollfd.events. + * \return A populated pollfd object. + */ + pollfd preparePoll(short events = 0); + + /** + * Live iterator continuously receiving messages from Netlink socket. + * + * Iteration ends when socket fails to receive a buffer. + * + * Example: + * ``` + * nl::Socket sock(NETLINK_ROUTE, 0, RTMGRP_LINK); + * for (const auto rawMsg : sock) { + * const auto msg = nl::Message::parse(rawMsg, {RTM_NEWLINK, RTM_DELLINK}); + * if (!msg.has_value()) continue; + * + * LOG(INFO) << msg->attributes.get(IFLA_IFNAME) + * << " is " << ((msg->data.ifi_flags & IFF_UP) ? "up" : "down"); + * } + * LOG(FATAL) << "Failed to read from Netlink socket"; + * ``` + */ + class receive_iterator { + public: + receive_iterator(Socket& socket, bool end); + + receive_iterator operator++(); + bool operator==(const receive_iterator& other) const; + const Buffer& operator*() const; + + private: + Socket& mSocket; + bool mIsEnd; + Buffer::iterator mCurrent; + + void receive(); + }; + receive_iterator begin(); + receive_iterator end(); + + private: + const int mProtocol; + base::unique_fd mFd; + std::vector mReceiveBuffer; + + bool mFailed = false; + uint32_t mSeq = 0; + + bool increaseReceiveBuffer(size_t maxSize); + std::optional> receive(const std::set& msgtypes, size_t maxSize); + + DISALLOW_COPY_AND_ASSIGN(Socket); +}; + +} // namespace android::nl diff --git a/automotive/can/1.0/default/libnl++/include/libnl++/bits.h b/automotive/can/1.0/default/libnl++/include/libnl++/bits.h new file mode 100644 index 0000000000000000000000000000000000000000..4c8f1aa9a1ea1122f4d3f15f15a4cd625a23060d --- /dev/null +++ b/automotive/can/1.0/default/libnl++/include/libnl++/bits.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +namespace android::nl::impl { + +// The following definitions are C++ equivalents of NLMSG_* macros from linux/netlink.h. + +/** + * Equivalent to NLMSG_ALIGNTO. + */ +constexpr size_t alignto = NLMSG_ALIGNTO; +static_assert(NLMSG_ALIGNTO == NLA_ALIGNTO); + +/** + * Equivalent to NLMSG_ALIGN(len). + */ +constexpr size_t align(size_t len) { + return (len + alignto - 1) & ~(alignto - 1); +} + +/** + * Equivalent to NLMSG_SPACE(len). + */ +template +constexpr size_t space(size_t len) { + return align(align(sizeof(H)) + len); +} + +/** + * Equivalent to NLMSG_DATA(hdr) + NLMSG_ALIGN(offset). + */ +template +constexpr D* data(H* header, size_t offset = 0) { + return reinterpret_cast(uintptr_t(header) + space(offset)); +} + +} // namespace android::nl::impl diff --git a/automotive/can/1.0/default/libnl++/include/libnl++/generic/FamilyTracker.h b/automotive/can/1.0/default/libnl++/include/libnl++/generic/FamilyTracker.h new file mode 100644 index 0000000000000000000000000000000000000000..253003527fb6d150c3c3b195f22ae5d9bd23cbeb --- /dev/null +++ b/automotive/can/1.0/default/libnl++/include/libnl++/generic/FamilyTracker.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +#include + +#include + +namespace android::nl::generic { + +/** + * Tracker of Netlink family ID registrations. + */ +class FamilyTracker { + public: + /** + * Try parsing NL80211 message. + * + * Proper parsing of NL80211 nessages requires prior parsing of control message for Generic + * Netlink protocol. + * + * \param msg Message to parse + * \returns Parsed NL80211 message or std::nullopt if it wasn't one + */ + std::optional> parseNl80211(Buffer msg); + + private: + /* For efficiency, we use a single hardcoded family ID. However, if we supported multiple family + * types, this should probably be a map. + */ + std::optional mNl80211FamilyId; + + /** + * Track Generic protocol messages. + * + * This method is looking for family registration messages. + * + * \param msg Message to track + * \returns True, if the message was a control message (regardless of carrying + * family info or not) + */ + bool track(const Buffer& msg); +}; + +} // namespace android::nl::generic diff --git a/automotive/can/1.0/default/libnl++/include/libnl++/printer.h b/automotive/can/1.0/default/libnl++/include/libnl++/printer.h new file mode 100644 index 0000000000000000000000000000000000000000..3570918e2df831ca38a494dd305b80425284f8d7 --- /dev/null +++ b/automotive/can/1.0/default/libnl++/include/libnl++/printer.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include + +#include + +namespace android::nl { + +/** + * Stringify a Netlink message. + * + * \param hdr Pointer to the message(s) to print. + * \param protocol Which Netlink protocol hdr uses. + * \param printPayload True will stringify message data, false will only stringify the header(s). + * \return Stringified message. + */ +std::string toString(const Buffer hdr, int protocol, bool printPayload = true); + +} // namespace android::nl diff --git a/automotive/can/1.0/default/libnl++/include/libnl++/types.h b/automotive/can/1.0/default/libnl++/include/libnl++/types.h new file mode 100644 index 0000000000000000000000000000000000000000..567590b4562287787f858971f18f079763633080 --- /dev/null +++ b/automotive/can/1.0/default/libnl++/include/libnl++/types.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +namespace android::nl { + +typedef decltype(nlmsghdr::nlmsg_type) nlmsgtype_t; +typedef decltype(nlattr::nla_type) nlattrtype_t; + +} // namespace android::nl diff --git a/automotive/can/1.0/default/libnl++/printer.cpp b/automotive/can/1.0/default/libnl++/printer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f08897e9514232a22937445baa399dfb206e8809 --- /dev/null +++ b/automotive/can/1.0/default/libnl++/printer.cpp @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "common.h" +#include "protocols/all.h" + +#include +#include + +#include +#include +#include + +namespace android::nl { + +static void flagsToStream(std::stringstream& ss, __u16 nlmsg_flags, protocols::MessageGenre genre) { + bool first = true; + auto printFlag = [&ss, &first, &nlmsg_flags](__u16 flag, const std::string& name) { + if ((nlmsg_flags & flag) != flag) return; + nlmsg_flags &= ~flag; + + if (first) { + first = false; + } else { + ss << '|'; + } + + ss << name; + }; + + printFlag(NLM_F_REQUEST, "REQUEST"); + printFlag(NLM_F_MULTI, "MULTI"); + printFlag(NLM_F_ACK, "ACK"); + printFlag(NLM_F_ECHO, "ECHO"); + printFlag(NLM_F_DUMP_INTR, "DUMP_INTR"); + printFlag(NLM_F_DUMP_FILTERED, "DUMP_FILTERED"); + + switch (genre) { + case protocols::MessageGenre::Unknown: + break; + case protocols::MessageGenre::Get: + printFlag(NLM_F_DUMP, "DUMP"); // ROOT | MATCH + printFlag(NLM_F_ROOT, "ROOT"); + printFlag(NLM_F_MATCH, "MATCH"); + printFlag(NLM_F_ATOMIC, "ATOMIC"); + break; + case protocols::MessageGenre::New: + printFlag(NLM_F_REPLACE, "REPLACE"); + printFlag(NLM_F_EXCL, "EXCL"); + printFlag(NLM_F_CREATE, "CREATE"); + printFlag(NLM_F_APPEND, "APPEND"); + break; + case protocols::MessageGenre::Delete: + printFlag(NLM_F_NONREC, "NONREC"); + break; + case protocols::MessageGenre::Ack: + printFlag(NLM_F_CAPPED, "CAPPED"); + printFlag(NLM_F_ACK_TLVS, "ACK_TLVS"); + break; + } + + if (nlmsg_flags != 0) { + if (!first) ss << '|'; + ss << std::hex << nlmsg_flags << std::dec; + } +} + +static void toStream(std::stringstream& ss, const Buffer data) { + const auto rawData = data.getRaw(); + const auto dataLen = rawData.len(); + ss << std::hex; + int i = 0; + for (const auto byte : rawData) { + if (i % 16 == 0 && dataLen > 16) { + ss << std::endl << ' ' << std::dec << std::setw(4) << i << std::hex; + } + if (i++ > 0 || dataLen > 16) ss << ' '; + ss << std::setw(2) << unsigned(byte); + } + ss << std::dec; + if (dataLen > 16) ss << std::endl; +} + +static void toStream(std::stringstream& ss, const Buffer attr, + const protocols::AttributeMap& attrMap) { + using DataType = protocols::AttributeDefinition::DataType; + using Flags = protocols::AttributeDefinition::Flags; + const auto attrtype = attrMap[attr->nla_type]; + + ss << attrtype.name; + + if (attrtype.dataType == DataType::Flag && attr.data().getRaw().len() == 0) return; + ss << ": "; + + if (attrtype.flags == Flags::Verbose) { + const auto raw = attr.data(); + ss << "{len=" << raw.getRaw().len(); + ss << ", crc=" << std::hex << std::setw(4) << crc16(raw) << std::dec; + ss << "}"; + return; + } + + switch (attrtype.dataType) { + case DataType::Raw: + case DataType::Flag: + toStream(ss, attr.data()); + break; + case DataType::Nested: { + ss << '{'; + bool first = true; + for (const auto childattr : attr.data()) { + if (!first) ss << ", "; + first = false; + toStream(ss, childattr, std::get(attrtype.ops)); + } + ss << '}'; + break; + } + case DataType::StringNul: + case DataType::String: { + const auto str = attr.data().getRaw(); + auto len = str.len(); + if (attrtype.dataType == DataType::StringNul && len > 0 && str.ptr()[len - 1] == '\0') { + len--; + } + + ss << '"' << printableOnly({str.ptr(), len}) << '"'; + break; + } + case DataType::Uint: + ss << attr.data().copyFirst(); + break; + case DataType::Struct: { + const auto structToStream = + std::get(attrtype.ops); + structToStream(ss, attr); + break; + } + } +} + +std::string toString(const Buffer hdr, int protocol, bool printPayload) { + if (!hdr.firstOk()) return "nlmsg{buffer overflow}"; + + std::stringstream ss; + ss << std::setfill('0'); + + auto protocolMaybe = protocols::get(protocol); + if (!protocolMaybe.has_value()) { + ss << "nlmsg{protocol=" << protocol << "}"; + return ss.str(); + } + protocols::NetlinkProtocol& protocolDescr = *protocolMaybe; + + auto msgDescMaybe = protocolDescr.getMessageDescriptor(hdr->nlmsg_type); + const auto msgDetails = + protocols::MessageDescriptor::getMessageDetails(msgDescMaybe, hdr->nlmsg_type); + + if (msgDescMaybe.has_value()) msgDescMaybe->get().track(hdr); + + ss << "nlmsg{" << protocolDescr.getName() << " "; + + ss << "hdr={"; + ss << "type=" << msgDetails.name; + if (hdr->nlmsg_flags != 0) { + ss << ", flags="; + flagsToStream(ss, hdr->nlmsg_flags, msgDetails.genre); + } + if (hdr->nlmsg_seq != 0) ss << ", seq=" << hdr->nlmsg_seq; + if (hdr->nlmsg_pid != 0) ss << ", pid=" << hdr->nlmsg_pid; + ss << ", len=" << hdr->nlmsg_len; + ss << ", crc=" << std::hex << std::setw(4) << crc16(hdr.data()) << std::dec; + ss << '}'; + + if (!printPayload) return ss.str(); + ss << ' '; + + if (!msgDescMaybe.has_value()) { + toStream(ss, hdr.data()); + } else { + const protocols::MessageDescriptor& msgDesc = *msgDescMaybe; + msgDesc.dataToStream(ss, hdr); + + bool first = true; + for (auto attr : hdr.data(msgDesc.getContentsSize())) { + if (first) { + ss << " attributes: {"; + first = false; + } else { + ss << ", "; + } + toStream(ss, attr, msgDesc.getAttributeMap()); + } + if (!first) ss << '}'; + } + + ss << "}"; + + return ss.str(); +} + +} // namespace android::nl diff --git a/automotive/can/1.0/default/libnl++/protocols/MessageDefinition.cpp b/automotive/can/1.0/default/libnl++/protocols/MessageDefinition.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aaf24a53aa1cd1e44b3d186f1b156f06c5004f27 --- /dev/null +++ b/automotive/can/1.0/default/libnl++/protocols/MessageDefinition.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "MessageDefinition.h" + +namespace android::nl::protocols { + +AttributeMap::AttributeMap(const std::initializer_list attrTypes) + : std::map, AttributeDefinition>(attrTypes) {} + +const AttributeDefinition AttributeMap::operator[](nlattrtype_t nla_type) const { + if (count(nla_type) == 0) { + if (count(std::nullopt) == 0) return {std::to_string(nla_type)}; + + auto definition = find(std::nullopt)->second; + definition.name += std::to_string(nla_type); + return definition; + } + return find(nla_type)->second; +} + +MessageDescriptor::MessageDescriptor(const std::string& name, + const MessageDetailsMap&& messageDetails, + const AttributeMap&& attrTypes, size_t contentsSize) + : mName(name), + mContentsSize(contentsSize), + mMessageDetails(messageDetails), + mAttributeMap(attrTypes) {} + +MessageDescriptor::~MessageDescriptor() {} + +size_t MessageDescriptor::getContentsSize() const { + return mContentsSize; +} + +const MessageDescriptor::MessageDetailsMap& MessageDescriptor::getMessageDetailsMap() const { + return mMessageDetails; +} + +const AttributeMap& MessageDescriptor::getAttributeMap() const { + return mAttributeMap; +} + +MessageDescriptor::MessageDetails MessageDescriptor::getMessageDetails(nlmsgtype_t msgtype) const { + const auto it = mMessageDetails.find(msgtype); + if (it == mMessageDetails.end()) return {std::to_string(msgtype), MessageGenre::Unknown}; + return it->second; +} + +MessageDescriptor::MessageDetails MessageDescriptor::getMessageDetails( + const std::optional>& msgDescMaybe, + nlmsgtype_t msgtype) { + if (msgDescMaybe.has_value()) return msgDescMaybe->get().getMessageDetails(msgtype); + return {std::to_string(msgtype), protocols::MessageGenre::Unknown}; +} + +void MessageDescriptor::track(const Buffer /* hdr */) {} + +} // namespace android::nl::protocols diff --git a/automotive/can/1.0/default/libnl++/protocols/MessageDefinition.h b/automotive/can/1.0/default/libnl++/protocols/MessageDefinition.h new file mode 100644 index 0000000000000000000000000000000000000000..8bed5e7a7e3d2ef00a2f8506af47bcb0d9f90bc8 --- /dev/null +++ b/automotive/can/1.0/default/libnl++/protocols/MessageDefinition.h @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +#include +#include +#include + +namespace android::nl::protocols { + +struct AttributeDefinition; + +/** + * Mapping between nlattrtype_t identifier and attribute definition. + * + * The map contains values for all nlattrtype_t identifiers - if some is missing, a generic + * definition with a identifier as its name will be generated. + * + * It's possible to define a default attribute to return instead of to_string of its identifier + * (useful for nested attribute lists). In such case, an entry with id=std::nullopt needs to be + * present in the map. + */ +class AttributeMap : private std::map, AttributeDefinition> { + public: + using std::map, AttributeDefinition>::value_type; + + AttributeMap(const std::initializer_list attrTypes); + + const AttributeDefinition operator[](nlattrtype_t nla_type) const; +}; + +/** + * Attribute definition. + * + * Describes the name and type (optionally sub types, in case of Nested attribute) + * for a given message attribute. + */ +struct AttributeDefinition { + enum class DataType : uint8_t { + /** + * Binary blob (or attribute of unknown type). + */ + Raw, + + /** + * Nested attribute (with or without NLA_F_NESTED). + */ + Nested, + + /** + * Non-null terminated string. + * + * The length of the string is determined by the size of an attribute. + */ + String, + + /** + * Null terminated string. + */ + StringNul, + + /** + * Unsigned integer of size 8, 16, 32 or 64 bits. + */ + Uint, + + /** + * Structure which printer is defined in ops ToStream variant. + */ + Struct, + + /** + * Flag attribute. + * + * The attribute doesn't have any contents. The flag is set when the attribute is present, + * it's not when it's absent from attribute list. + */ + Flag, + }; + enum class Flags : uint8_t { + Verbose = (1 << 0), + }; + using ToStream = std::function attr)>; + + std::string name; + DataType dataType = DataType::Raw; + std::variant ops = AttributeMap{}; + + /** + * Attribute flags. + * + * It's not really a bitmask flag set (since you are not supposed to compare enum class by + * bitmask), but std::set bumps compile time from 16s to 3m. Let's leave it as-is for + * now and revisit if we get some flags that can be used in pairs. When it happens, review all + * uses of the flags field to include the "&" operator and not "==". + */ + Flags flags = {}; +}; + +/** + * General message type's kind. + * + * For example, RTM_NEWLINK is a NEW kind. For details, please see "Flags values" + * section in linux/netlink.h. + */ +enum class MessageGenre { + Unknown, + Get, + New, + Delete, + Ack, +}; + +/** + * Message family descriptor. + * + * Describes the structure of all message types with the same header and attributes. + */ +class MessageDescriptor { + public: + struct MessageDetails { + std::string name; + MessageGenre genre; + }; + typedef std::map MessageDetailsMap; + + public: + virtual ~MessageDescriptor(); + + size_t getContentsSize() const; + const MessageDetailsMap& getMessageDetailsMap() const; + const AttributeMap& getAttributeMap() const; + MessageDetails getMessageDetails(nlmsgtype_t msgtype) const; + virtual void dataToStream(std::stringstream& ss, const Buffer hdr) const = 0; + + /** + * Message tracking for stateful protocols (such as NETLINK_GENERIC). + * + * \param hdr Message to track + */ + virtual void track(const Buffer hdr); + + static MessageDetails getMessageDetails( + const std::optional>& msgDescMaybe, + nlmsgtype_t msgtype); + + protected: + MessageDescriptor(const std::string& name, const MessageDetailsMap&& messageDetails, + const AttributeMap&& attrTypes, size_t contentsSize); + + private: + const std::string mName; + const size_t mContentsSize; + const MessageDetailsMap mMessageDetails; + const AttributeMap mAttributeMap; +}; + +/** + * Message definition template. + * + * A convenience initialization helper of a message descriptor. + */ +template +class MessageDefinition : public MessageDescriptor { + public: + MessageDefinition( // + const std::string& name, + const std::initializer_list msgDet, + const std::initializer_list attrTypes = {}) + : MessageDescriptor(name, msgDet, attrTypes, sizeof(T)) {} + + void dataToStream(std::stringstream& ss, const Buffer hdr) const override { + const auto& [ok, msg] = hdr.data().getFirst(); + if (!ok) { + ss << "{incomplete payload}"; + return; + } + + toStream(ss, msg); + } + + protected: + virtual void toStream(std::stringstream& ss, const T& data) const = 0; +}; + +} // namespace android::nl::protocols diff --git a/automotive/can/1.0/default/libnl++/protocols/NetlinkProtocol.cpp b/automotive/can/1.0/default/libnl++/protocols/NetlinkProtocol.cpp new file mode 100644 index 0000000000000000000000000000000000000000..16208aba1409e6f2988831a3ad427325b397ee57 --- /dev/null +++ b/automotive/can/1.0/default/libnl++/protocols/NetlinkProtocol.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "NetlinkProtocol.h" + +namespace android::nl::protocols { + +NetlinkProtocol::NetlinkProtocol(int protocol, const std::string& name, + const MessageDescriptorList&& messageDescrs) + : mProtocol(protocol), mName(name), mMessageDescrs(toMap(messageDescrs, protocol)) {} + +NetlinkProtocol::~NetlinkProtocol() {} + +int NetlinkProtocol::getProtocol() const { + return mProtocol; +} + +const std::string& NetlinkProtocol::getName() const { + return mName; +} + +const std::optional> +NetlinkProtocol::getMessageDescriptor(nlmsgtype_t nlmsg_type) { + if (mMessageDescrs.count(nlmsg_type) == 0) return std::nullopt; + return *mMessageDescrs.find(nlmsg_type)->second; +} + +NetlinkProtocol::MessageDescriptorMap NetlinkProtocol::toMap( + const NetlinkProtocol::MessageDescriptorList& descrs, int protocol) { + MessageDescriptorMap map; + for (auto& descr : descrs) { + for (const auto& [mtype, mdet] : descr->getMessageDetailsMap()) { + map.emplace(mtype, descr); + } + } + + const MessageDescriptorList baseDescriptors = { + std::make_shared(), + std::make_shared(protocol), + }; + + for (const auto& descr : baseDescriptors) { + for (const auto& [mtype, mdet] : descr->getMessageDetailsMap()) { + map.emplace(mtype, descr); + } + } + + return map; +} + +} // namespace android::nl::protocols diff --git a/automotive/can/1.0/default/libnl++/protocols/NetlinkProtocol.h b/automotive/can/1.0/default/libnl++/protocols/NetlinkProtocol.h new file mode 100644 index 0000000000000000000000000000000000000000..b173b912705bfaffc8063bc9ed2d7a3202f55f28 --- /dev/null +++ b/automotive/can/1.0/default/libnl++/protocols/NetlinkProtocol.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "MessageDefinition.h" +#include "common/Empty.h" +#include "common/Error.h" + +#include + +#include +#include + +namespace android::nl::protocols { + +/** + * Netlink-based protocol definition. + * + * Usually it's just an id/name and a list of supported messages. + */ +class NetlinkProtocol { + public: + virtual ~NetlinkProtocol(); + + int getProtocol() const; + + const std::string& getName() const; + + virtual const std::optional> getMessageDescriptor( + nlmsgtype_t nlmsg_type); + + protected: + typedef std::vector> MessageDescriptorList; + + NetlinkProtocol(int protocol, const std::string& name, + const MessageDescriptorList&& messageDescrs); + + private: + typedef std::map> MessageDescriptorMap; + + const int mProtocol; + const std::string mName; + const MessageDescriptorMap mMessageDescrs; + + static MessageDescriptorMap toMap(const MessageDescriptorList& descrs, int protocol); +}; + +} // namespace android::nl::protocols diff --git a/automotive/can/1.0/default/libnl++/protocols/README b/automotive/can/1.0/default/libnl++/protocols/README new file mode 100644 index 0000000000000000000000000000000000000000..45c95c40ea6dcd0f75e22bc363ff3ac6fe75452a --- /dev/null +++ b/automotive/can/1.0/default/libnl++/protocols/README @@ -0,0 +1,8 @@ +This folder contains message definitions for various protocols based on Netlink. + +The structure is as follows: +protocols/*.(cpp|h) - base definition classes and protocol definition lookup +protocols/common/ - common message types that apply to all protocols +protocols//.(cpp|h) - protocol definition (usually just a list of message types) +protocols//*.(cpp|h) - message definition that covers all message types with the same + header (T type in MessageDefinition template) and attributes diff --git a/automotive/can/1.0/default/libnl++/protocols/all.cpp b/automotive/can/1.0/default/libnl++/protocols/all.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a398dc8f1f27825f5b63e8c99dcb4abceb70a567 --- /dev/null +++ b/automotive/can/1.0/default/libnl++/protocols/all.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "all.h" + +#include "generic/Generic.h" +#include "route/Route.h" + +#include + +namespace android::nl::protocols { + +// This should be a map of unique_ptr, but it's not trivial to uniformly initialize such a map +static std::map> toMap( + std::initializer_list> l) { + std::map> map; + for (auto p : l) { + map[p->getProtocol()] = p; + } + return map; +} + +static auto all = toMap({ + std::make_unique(), + std::make_unique(), +}); + +std::optional> get(int protocol) { + if (all.count(protocol) == 0) return std::nullopt; + return *all.find(protocol)->second.get(); +} + +} // namespace android::nl::protocols diff --git a/automotive/can/1.0/default/libnl++/protocols/all.h b/automotive/can/1.0/default/libnl++/protocols/all.h new file mode 100644 index 0000000000000000000000000000000000000000..6d6ec1e76d6bdba74678cc3d0bb93c26ec8679ff --- /dev/null +++ b/automotive/can/1.0/default/libnl++/protocols/all.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "NetlinkProtocol.h" + +namespace android::nl::protocols { + +/** + * Protocol definition lookup. + * + * \param protocol Protocol identifier from linux/netlink.h + * \return Protocol definition or nullopt if it's not implemented + */ +std::optional> get(int protocol); + +} // namespace android::nl::protocols diff --git a/automotive/can/1.0/default/libnl++/protocols/common/Empty.cpp b/automotive/can/1.0/default/libnl++/protocols/common/Empty.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4b509c9069149caf3a7ba14a6650caf739bee0bf --- /dev/null +++ b/automotive/can/1.0/default/libnl++/protocols/common/Empty.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Empty.h" + +namespace android::nl::protocols::base { + +// clang-format off +Empty::Empty() : MessageDefinition("nlmsg", { + {NLMSG_NOOP, {"NOOP", MessageGenre::Unknown}}, + {NLMSG_DONE, {"DONE", MessageGenre::Unknown}}, + {NLMSG_OVERRUN, {"OVERRUN", MessageGenre::Unknown}}, +}) {} +// clang-format on + +void Empty::toStream(std::stringstream&, const char&) const {} + +} // namespace android::nl::protocols::base diff --git a/automotive/can/1.0/default/libnl++/protocols/common/Empty.h b/automotive/can/1.0/default/libnl++/protocols/common/Empty.h new file mode 100644 index 0000000000000000000000000000000000000000..79a0f46aa283702d1e3e238955457f1f2e900ae0 --- /dev/null +++ b/automotive/can/1.0/default/libnl++/protocols/common/Empty.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "../MessageDefinition.h" + +#include + +namespace android::nl::protocols::base { + +// no-payload (like NLMSG_NOOP) messages can't be defined with T=void, so let's use char +class Empty : public MessageDefinition { + public: + Empty(); + void toStream(std::stringstream&, const char&) const override; +}; + +} // namespace android::nl::protocols::base diff --git a/automotive/can/1.0/default/libnl++/protocols/common/Error.cpp b/automotive/can/1.0/default/libnl++/protocols/common/Error.cpp new file mode 100644 index 0000000000000000000000000000000000000000..77451edbeb8d44a9fafff6d47e2b32e7e637a025 --- /dev/null +++ b/automotive/can/1.0/default/libnl++/protocols/common/Error.cpp @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Error.h" + +#include "../MessageDefinition.h" + +#include + +#include + +namespace android::nl::protocols::base { + +using DataType = AttributeDefinition::DataType; + +// clang-format off +Error::Error(int protocol) : MessageDefinition("nlmsg", { + {NLMSG_ERROR, {"ERROR", MessageGenre::Ack}}, +}, { + {NLMSGERR_ATTR_MSG, {"MSG", DataType::String}}, + {NLMSGERR_ATTR_OFFS, {"OFFS", DataType::Uint}}, + {NLMSGERR_ATTR_COOKIE, {"COOKIE", DataType::Raw}}, +}), mProtocol(protocol) {} +// clang-format on + +std::map errnoNames{ + {EPERM, "EPERM"}, // Operation not permitted + {ENOENT, "ENOENT"}, // No such file or directory + {ESRCH, "ESRCH"}, // No such process + {EINTR, "EINTR"}, // Interrupted system call + {EIO, "EIO"}, // I/O error + {ENXIO, "ENXIO"}, // No such device or address + {E2BIG, "E2BIG"}, // Argument list too long + {ENOEXEC, "ENOEXEC"}, // Exec format error + {EBADF, "EBADF"}, // Bad file number + {ECHILD, "ECHILD"}, // No child processes + {EAGAIN, "EAGAIN"}, // Try again + {ENOMEM, "ENOMEM"}, // Out of memory + {EACCES, "EACCES"}, // Permission denied + {EFAULT, "EFAULT"}, // Bad address + {ENOTBLK, "ENOTBLK"}, // Block device required + {EBUSY, "EBUSY"}, // Device or resource busy + {EEXIST, "EEXIST"}, // File exists + {EXDEV, "EXDEV"}, // Cross-device link + {ENODEV, "ENODEV"}, // No such device + {ENOTDIR, "ENOTDIR"}, // Not a directory + {EISDIR, "EISDIR"}, // Is a directory + {EINVAL, "EINVAL"}, // Invalid argument + {ENFILE, "ENFILE"}, // File table overflow + {EMFILE, "EMFILE"}, // Too many open files + {ENOTTY, "ENOTTY"}, // Not a typewriter + {ETXTBSY, "ETXTBSY"}, // Text file busy + {EFBIG, "EFBIG"}, // File too large + {ENOSPC, "ENOSPC"}, // No space left on device + {ESPIPE, "ESPIPE"}, // Illegal seek + {EROFS, "EROFS"}, // Read-only file system + {EMLINK, "EMLINK"}, // Too many links + {EPIPE, "EPIPE"}, // Broken pipe + {EDOM, "EDOM"}, // Math argument out of domain of func + {ERANGE, "ERANGE"}, // Math result not representable + {EDEADLK, "EDEADLK"}, // Resource deadlock would occur + {ENAMETOOLONG, "ENAMETOOLONG"}, // File name too long + {ENOLCK, "ENOLCK"}, // No record locks available + {ENOSYS, "ENOSYS"}, // Invalid system call number + {ENOTEMPTY, "ENOTEMPTY"}, // Directory not empty + {ELOOP, "ELOOP"}, // Too many symbolic links encountered + {ENOMSG, "ENOMSG"}, // No message of desired type + {EIDRM, "EIDRM"}, // Identifier removed + {ECHRNG, "ECHRNG"}, // Channel number out of range + {EL2NSYNC, "EL2NSYNC"}, // Level 2 not synchronized + {EL3HLT, "EL3HLT"}, // Level 3 halted + {EL3RST, "EL3RST"}, // Level 3 reset + {ELNRNG, "ELNRNG"}, // Link number out of range + {EUNATCH, "EUNATCH"}, // Protocol driver not attached + {ENOCSI, "ENOCSI"}, // No CSI structure available + {EL2HLT, "EL2HLT"}, // Level 2 halted + {EBADE, "EBADE"}, // Invalid exchange + {EBADR, "EBADR"}, // Invalid request descriptor + {EXFULL, "EXFULL"}, // Exchange full + {ENOANO, "ENOANO"}, // No anode + {EBADRQC, "EBADRQC"}, // Invalid request code + {EBADSLT, "EBADSLT"}, // Invalid slot + {EBFONT, "EBFONT"}, // Bad font file format + {ENOSTR, "ENOSTR"}, // Device not a stream + {ENODATA, "ENODATA"}, // No data available + {ETIME, "ETIME"}, // Timer expired + {ENOSR, "ENOSR"}, // Out of streams resources + {ENONET, "ENONET"}, // Machine is not on the network + {ENOPKG, "ENOPKG"}, // Package not installed + {EREMOTE, "EREMOTE"}, // Object is remote + {ENOLINK, "ENOLINK"}, // Link has been severed + {EADV, "EADV"}, // Advertise error + {ESRMNT, "ESRMNT"}, // Srmount error + {ECOMM, "ECOMM"}, // Communication error on send + {EPROTO, "EPROTO"}, // Protocol error + {EMULTIHOP, "EMULTIHOP"}, // Multihop attempted + {EDOTDOT, "EDOTDOT"}, // RFS specific error + {EBADMSG, "EBADMSG"}, // Not a data message + {EOVERFLOW, "EOVERFLOW"}, // Value too large for defined data type + {ENOTUNIQ, "ENOTUNIQ"}, // Name not unique on network + {EBADFD, "EBADFD"}, // File descriptor in bad state + {EREMCHG, "EREMCHG"}, // Remote address changed + {ELIBACC, "ELIBACC"}, // Can not access a needed shared library + {ELIBBAD, "ELIBBAD"}, // Accessing a corrupted shared library + {ELIBSCN, "ELIBSCN"}, // .lib section in a.out corrupted + {ELIBMAX, "ELIBMAX"}, // Attempting to link in too many shared libraries + {ELIBEXEC, "ELIBEXEC"}, // Cannot exec a shared library directly + {EILSEQ, "EILSEQ"}, // Illegal byte sequence + {ERESTART, "ERESTART"}, // Interrupted system call should be restarted + {ESTRPIPE, "ESTRPIPE"}, // Streams pipe error + {EUSERS, "EUSERS"}, // Too many users + {ENOTSOCK, "ENOTSOCK"}, // Socket operation on non-socket + {EDESTADDRREQ, "EDESTADDRREQ"}, // Destination address required + {EMSGSIZE, "EMSGSIZE"}, // Message too long + {EPROTOTYPE, "EPROTOTYPE"}, // Protocol wrong type for socket + {ENOPROTOOPT, "ENOPROTOOPT"}, // Protocol not available + {EPROTONOSUPPORT, "EPROTONOSUPPORT"}, // Protocol not supported + {ESOCKTNOSUPPORT, "ESOCKTNOSUPPORT"}, // Socket type not supported + {EOPNOTSUPP, "EOPNOTSUPP"}, // Operation not supported on transport endpoint + {EPFNOSUPPORT, "EPFNOSUPPORT"}, // Protocol family not supported + {EAFNOSUPPORT, "EAFNOSUPPORT"}, // Address family not supported by protocol + {EADDRINUSE, "EADDRINUSE"}, // Address already in use + {EADDRNOTAVAIL, "EADDRNOTAVAIL"}, // Cannot assign requested address + {ENETDOWN, "ENETDOWN"}, // Network is down + {ENETUNREACH, "ENETUNREACH"}, // Network is unreachable + {ENETRESET, "ENETRESET"}, // Network dropped connection because of reset + {ECONNABORTED, "ECONNABORTED"}, // Software caused connection abort + {ECONNRESET, "ECONNRESET"}, // Connection reset by peer + {ENOBUFS, "ENOBUFS"}, // No buffer space available + {EISCONN, "EISCONN"}, // Transport endpoint is already connected + {ENOTCONN, "ENOTCONN"}, // Transport endpoint is not connected + {ESHUTDOWN, "ESHUTDOWN"}, // Cannot send after transport endpoint shutdown + {ETOOMANYREFS, "ETOOMANYREFS"}, // Too many references: cannot splice + {ETIMEDOUT, "ETIMEDOUT"}, // Connection timed out + {ECONNREFUSED, "ECONNREFUSED"}, // Connection refused + {EHOSTDOWN, "EHOSTDOWN"}, // Host is down + {EHOSTUNREACH, "EHOSTUNREACH"}, // No route to host + {EALREADY, "EALREADY"}, // Operation already in progress + {EINPROGRESS, "EINPROGRESS"}, // Operation now in progress + {ESTALE, "ESTALE"}, // Stale file handle + {EUCLEAN, "EUCLEAN"}, // Structure needs cleaning + {ENOTNAM, "ENOTNAM"}, // Not a XENIX named type file + {ENAVAIL, "ENAVAIL"}, // No XENIX semaphores available + {EISNAM, "EISNAM"}, // Is a named type file + {EREMOTEIO, "EREMOTEIO"}, // Remote I/O error + {EDQUOT, "EDQUOT"}, // Quota exceeded + {ENOMEDIUM, "ENOMEDIUM"}, // No medium found + {EMEDIUMTYPE, "EMEDIUMTYPE"}, // Wrong medium type + {ECANCELED, "ECANCELED"}, // Operation Canceled + {ENOKEY, "ENOKEY"}, // Required key not available + {EKEYEXPIRED, "EKEYEXPIRED"}, // Key has expired + {EKEYREVOKED, "EKEYREVOKED"}, // Key has been revoked + {EKEYREJECTED, "EKEYREJECTED"}, // Key was rejected by service + {EOWNERDEAD, "EOWNERDEAD"}, // Owner died + {ENOTRECOVERABLE, "ENOTRECOVERABLE"}, // State not recoverable + {ERFKILL, "ERFKILL"}, // Operation not possible due to RF-kill + {EHWPOISON, "EHWPOISON"}, // Memory page has hardware error + + // Duplicates: EWOULDBLOCK (Operation would block), EDEADLOCK +}; + +void Error::toStream(std::stringstream& ss, const nlmsgerr& data) const { + ss << "nlmsgerr{"; + if (data.error == 0) { + ss << "ACK"; + } else { + ss << "error="; + const auto nameIt = errnoNames.find(-data.error); + if (nameIt == errnoNames.end()) { + ss << data.error; + } else { + ss << nameIt->second; + } + } + ss << ", msg=" << toString({&data.msg, sizeof(data.msg)}, mProtocol, false) << "}"; +} + +} // namespace android::nl::protocols::base diff --git a/automotive/can/1.0/default/libnl++/protocols/common/Error.h b/automotive/can/1.0/default/libnl++/protocols/common/Error.h new file mode 100644 index 0000000000000000000000000000000000000000..782986b7a38de7775b2c3a83acbfe39607cbf9b5 --- /dev/null +++ b/automotive/can/1.0/default/libnl++/protocols/common/Error.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "../MessageDefinition.h" + +namespace android::nl::protocols::base { + +class Error : public MessageDefinition { + public: + Error(int protocol); + void toStream(std::stringstream& ss, const nlmsgerr& data) const override; + + private: + const int mProtocol; +}; + +} // namespace android::nl::protocols::base diff --git a/automotive/can/1.0/default/libnl++/protocols/generic/Ctrl.cpp b/automotive/can/1.0/default/libnl++/protocols/generic/Ctrl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1e1ad12c84cfc37e257b39fd09b748322b14b100 --- /dev/null +++ b/automotive/can/1.0/default/libnl++/protocols/generic/Ctrl.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Ctrl.h" + +#include "families/Nl80211.h" + +#include + +namespace android::nl::protocols::generic { + +using DataType = AttributeDefinition::DataType; +using Flags = AttributeDefinition::Flags; + +// clang-format off +Ctrl::Ctrl(Generic::FamilyRegister& familyRegister) + : GenericMessageBase(GENL_ID_CTRL, "ID_CTRL", +{ + {CTRL_CMD_NEWFAMILY, "NEWFAMILY"}, + {CTRL_CMD_DELFAMILY, "DELFAMILY"}, + {CTRL_CMD_GETFAMILY, "GETFAMILY"}, + {CTRL_CMD_NEWOPS, "NEWOPS"}, + {CTRL_CMD_DELOPS, "DELOPS"}, + {CTRL_CMD_GETOPS, "GETOPS"}, + {CTRL_CMD_NEWMCAST_GRP, "NEWMCAST_GRP"}, + {CTRL_CMD_DELMCAST_GRP, "DELMCAST_GRP"}, + {CTRL_CMD_GETMCAST_GRP, "GETMCAST_GRP"}, +}, { + {CTRL_ATTR_FAMILY_ID, {"FAMILY_ID", DataType::Uint}}, + {CTRL_ATTR_FAMILY_NAME, {"FAMILY_NAME", DataType::StringNul}}, + {CTRL_ATTR_VERSION, {"VERSION", DataType::Uint}}, + {CTRL_ATTR_HDRSIZE, {"HDRSIZE", DataType::Uint}}, + {CTRL_ATTR_MAXATTR, {"MAXATTR", DataType::Uint}}, + {CTRL_ATTR_OPS, {"OPS", DataType::Nested, AttributeMap{ + {std::nullopt, {"OP", DataType::Nested, AttributeMap{ + {CTRL_ATTR_OP_ID, {"ID", DataType::Uint}}, + {CTRL_ATTR_OP_FLAGS, {"FLAGS", DataType::Uint}}, + }}}, + }, Flags::Verbose}}, + {CTRL_ATTR_MCAST_GROUPS, {"MCAST_GROUPS", DataType::Nested, AttributeMap{ + {std::nullopt, {"GRP", DataType::Nested, AttributeMap{ + {CTRL_ATTR_MCAST_GRP_NAME, {"NAME", DataType::StringNul}}, + {CTRL_ATTR_MCAST_GRP_ID, {"ID", DataType::Uint}}, + }}}, + }}}, +}), mFamilyRegister(familyRegister) {} +// clang-format on + +void Ctrl::track(const Buffer hdr) { + const auto msgMaybe = Message::parse(hdr, {GENL_ID_CTRL}); + if (!msgMaybe.has_value()) return; + const auto msg = *msgMaybe; + + if (msg->cmd != CTRL_CMD_NEWFAMILY) return; + const auto familyId = msg.attributes.get(CTRL_ATTR_FAMILY_ID); + const auto familyName = msg.attributes.get(CTRL_ATTR_FAMILY_NAME); + + /* For now, we support just a single family. But if you add more, please define proper + * abstraction and not hardcode every name and class here. + */ + if (familyName == "nl80211") { + mFamilyRegister[familyId] = std::make_shared(familyId); + } +} + +} // namespace android::nl::protocols::generic diff --git a/automotive/can/1.0/default/libnl++/protocols/generic/Ctrl.h b/automotive/can/1.0/default/libnl++/protocols/generic/Ctrl.h new file mode 100644 index 0000000000000000000000000000000000000000..b13df0228276843c534fa1b062454d7e8f1af551 --- /dev/null +++ b/automotive/can/1.0/default/libnl++/protocols/generic/Ctrl.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "Generic.h" +#include "GenericMessageBase.h" + +namespace android::nl::protocols::generic { + +class Ctrl : public GenericMessageBase { + public: + Ctrl(Generic::FamilyRegister& familyRegister); + + void track(const Buffer hdr) override; + + private: + Generic::FamilyRegister& mFamilyRegister; +}; + +} // namespace android::nl::protocols::generic diff --git a/automotive/can/1.0/default/libnl++/protocols/generic/FamilyTracker.cpp b/automotive/can/1.0/default/libnl++/protocols/generic/FamilyTracker.cpp new file mode 100644 index 0000000000000000000000000000000000000000..900560e5b9721220dee94be6ff8f044e5764fa06 --- /dev/null +++ b/automotive/can/1.0/default/libnl++/protocols/generic/FamilyTracker.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +namespace android::nl::generic { + +bool FamilyTracker::track(const Buffer& buffer) { + const auto msgMaybe = nl::Message::parse(buffer, {GENL_ID_CTRL}); + if (!msgMaybe.has_value()) return false; + + const auto msg = *msgMaybe; + if (msg->cmd != CTRL_CMD_NEWFAMILY) return true; + + const auto familyName = msg.attributes.get(CTRL_ATTR_FAMILY_NAME); + const auto familyId = msg.attributes.get(CTRL_ATTR_FAMILY_ID); + + if (familyId < GENL_START_ALLOC) { + LOG(WARNING) << "Invalid family ID: " << familyId; + return true; + } + + if (familyName == "nl80211") mNl80211FamilyId = familyId; + + return true; +} + +std::optional> FamilyTracker::parseNl80211(Buffer msg) { + if (track(msg)) return std::nullopt; + if (!mNl80211FamilyId.has_value()) return std::nullopt; + + return nl::Message::parse(msg, {*mNl80211FamilyId}); +} + +} // namespace android::nl::generic diff --git a/automotive/can/1.0/default/libnl++/protocols/generic/Generic.cpp b/automotive/can/1.0/default/libnl++/protocols/generic/Generic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5e34a1fe5d9f7f2dd99a126371c39d208adabdf0 --- /dev/null +++ b/automotive/can/1.0/default/libnl++/protocols/generic/Generic.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Generic.h" + +#include "Ctrl.h" +#include "Unknown.h" + +namespace android::nl::protocols::generic { + +Generic::Generic() + : NetlinkProtocol(NETLINK_GENERIC, "GENERIC", {std::make_shared(mFamilyRegister)}) {} + +const std::optional> Generic::getMessageDescriptor( + nlmsgtype_t nlmsg_type) { + auto desc = NetlinkProtocol::getMessageDescriptor(nlmsg_type); + if (desc.has_value()) return desc; + + auto it = mFamilyRegister.find(nlmsg_type); + if (it != mFamilyRegister.end()) return *it->second; + return *(mFamilyRegister[nlmsg_type] = std::make_shared(nlmsg_type)); +} + +} // namespace android::nl::protocols::generic diff --git a/automotive/can/1.0/default/libnl++/protocols/generic/Generic.h b/automotive/can/1.0/default/libnl++/protocols/generic/Generic.h new file mode 100644 index 0000000000000000000000000000000000000000..2cdd584ef13e864e5d10e333e4e188e7f08bcd67 --- /dev/null +++ b/automotive/can/1.0/default/libnl++/protocols/generic/Generic.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "../NetlinkProtocol.h" + +namespace android::nl::protocols::generic { + +/** + * Definition of NETLINK_GENERIC protocol. + */ +class Generic : public NetlinkProtocol { + public: + typedef std::map> FamilyRegister; + + Generic(); + + const std::optional> getMessageDescriptor( + nlmsgtype_t nlmsg_type); + + private: + FamilyRegister mFamilyRegister; +}; + +} // namespace android::nl::protocols::generic diff --git a/automotive/can/1.0/default/libnl++/protocols/generic/GenericMessageBase.cpp b/automotive/can/1.0/default/libnl++/protocols/generic/GenericMessageBase.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b7b811b629a7f6a542a2bb5116987ec9349c696b --- /dev/null +++ b/automotive/can/1.0/default/libnl++/protocols/generic/GenericMessageBase.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "GenericMessageBase.h" + +namespace android::nl::protocols::generic { + +GenericMessageBase::GenericMessageBase( + nlmsgtype_t msgtype, const std::string&& msgname, + const std::initializer_list commandNames, + const std::initializer_list attrTypes) + : MessageDefinition(msgname, {{msgtype, {msgname, MessageGenre::Unknown}}}, + attrTypes), + mCommandNames(commandNames) {} + +void GenericMessageBase::toStream(std::stringstream& ss, const genlmsghdr& data) const { + const auto commandNameIt = mCommandNames.find(data.cmd); + const auto commandName = (commandNameIt == mCommandNames.end()) + ? std::nullopt + : std::optional(commandNameIt->second); + + if (commandName.has_value() && data.version == 1 && data.reserved == 0) { + // short version + ss << *commandName; + return; + } + + ss << "genlmsghdr{"; + if (commandName.has_value()) { + ss << "cmd=" << unsigned(data.cmd); + } else { + ss << "cmd=" << *commandName; + } + ss << ", version=" << unsigned(data.version); + if (data.reserved != 0) ss << ", reserved=" << data.reserved; + ss << "}"; +} + +} // namespace android::nl::protocols::generic diff --git a/automotive/can/1.0/default/libnl++/protocols/generic/GenericMessageBase.h b/automotive/can/1.0/default/libnl++/protocols/generic/GenericMessageBase.h new file mode 100644 index 0000000000000000000000000000000000000000..443f10c60a39cdf979d1cd79b3c93b51d5db5ffd --- /dev/null +++ b/automotive/can/1.0/default/libnl++/protocols/generic/GenericMessageBase.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "../MessageDefinition.h" + +#include + +namespace android::nl::protocols::generic { + +class GenericMessageBase : public MessageDefinition { + public: + typedef std::map GenericCommandNameMap; + + GenericMessageBase( + nlmsgtype_t msgtype, const std::string&& msgname, + const std::initializer_list commandNames = {}, + const std::initializer_list attrTypes = {}); + + void toStream(std::stringstream& ss, const genlmsghdr& data) const override; + + private: + const GenericCommandNameMap mCommandNames; +}; + +} // namespace android::nl::protocols::generic diff --git a/automotive/can/1.0/default/libnl++/protocols/generic/Unknown.cpp b/automotive/can/1.0/default/libnl++/protocols/generic/Unknown.cpp new file mode 100644 index 0000000000000000000000000000000000000000..17367f00297072d6bd539a48c54728f1b6abbf16 --- /dev/null +++ b/automotive/can/1.0/default/libnl++/protocols/generic/Unknown.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Unknown.h" + +namespace android::nl::protocols::generic { + +Unknown::Unknown(nlmsgtype_t msgtype) + : GenericMessageBase(msgtype, "Unknown(" + std::to_string(msgtype) + ")") {} + +} // namespace android::nl::protocols::generic diff --git a/automotive/can/1.0/default/libnl++/protocols/generic/Unknown.h b/automotive/can/1.0/default/libnl++/protocols/generic/Unknown.h new file mode 100644 index 0000000000000000000000000000000000000000..62ae19d7584c7f75b2be7ab9b43ce2e75ffaf663 --- /dev/null +++ b/automotive/can/1.0/default/libnl++/protocols/generic/Unknown.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "GenericMessageBase.h" + +namespace android::nl::protocols::generic { + +class Unknown : public GenericMessageBase { + public: + Unknown(nlmsgtype_t msgtype); +}; + +} // namespace android::nl::protocols::generic diff --git a/automotive/can/1.0/default/libnl++/protocols/generic/families/Nl80211.cpp b/automotive/can/1.0/default/libnl++/protocols/generic/families/Nl80211.cpp new file mode 100644 index 0000000000000000000000000000000000000000..23ec66f4d671ead63b10e1db8df79ec144e7d5c4 --- /dev/null +++ b/automotive/can/1.0/default/libnl++/protocols/generic/families/Nl80211.cpp @@ -0,0 +1,1009 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Nl80211.h" + +#include "../../structs.h" +#include "common.h" + +#include + +#include + +namespace android::nl::protocols::generic::families { + +/** + * Reduce verbosity of printed Information Elements. + */ +static constexpr bool kCompactIE = true; + +enum { + // broken compatibility in Aug 2020 + NL80211_ATTR_CNTDWN_OFFS_BEACON = NL80211_ATTR_CSA_C_OFF_BEACON, + NL80211_ATTR_CNTDWN_OFFS_PRESP = NL80211_ATTR_CSA_C_OFF_PRESP, + + // new fields not available in current Android + NL80211_ATTR_FILS_DISCOVERY = NL80211_ATTR_HE_6GHZ_CAPABILITY + 1, + NL80211_ATTR_UNSOL_BCAST_PROBE_RESP, + NL80211_ATTR_S1G_CAPABILITY, + NL80211_ATTR_S1G_CAPABILITY_MASK, + + NL80211_FREQUENCY_ATTR_1MHZ = NL80211_FREQUENCY_ATTR_OFFSET + 1, + NL80211_FREQUENCY_ATTR_2MHZ, + NL80211_FREQUENCY_ATTR_4MHZ, + NL80211_FREQUENCY_ATTR_8MHZ, + NL80211_FREQUENCY_ATTR_16MHZ, +}; + +enum ieee80211_eid { + WLAN_EID_SSID = 0, +}; + +using DataType = AttributeDefinition::DataType; +using Flags = AttributeDefinition::Flags; + +static void informationElementsToStream(std::stringstream& ss, const Buffer attr); +static void nl80211_pattern_supportToStream(std::stringstream& ss, const Buffer attr); + +static const AttributeMap iftypes{ + {NL80211_IFTYPE_UNSPECIFIED, {"UNSPECIFIED", DataType::Flag}}, + {NL80211_IFTYPE_ADHOC, {"ADHOC", DataType::Flag}}, + {NL80211_IFTYPE_STATION, {"STATION", DataType::Flag}}, + {NL80211_IFTYPE_AP, {"AP", DataType::Flag}}, + {NL80211_IFTYPE_AP_VLAN, {"AP_VLAN", DataType::Flag}}, + {NL80211_IFTYPE_WDS, {"WDS", DataType::Flag}}, + {NL80211_IFTYPE_MONITOR, {"MONITOR", DataType::Flag}}, + {NL80211_IFTYPE_MESH_POINT, {"MESH_POINT", DataType::Flag}}, + {NL80211_IFTYPE_P2P_CLIENT, {"P2P_CLIENT", DataType::Flag}}, + {NL80211_IFTYPE_P2P_GO, {"P2P_GO", DataType::Flag}}, + {NL80211_IFTYPE_P2P_DEVICE, {"P2P_DEVICE", DataType::Flag}}, + {NL80211_IFTYPE_OCB, {"OCB", DataType::Flag}}, + {NL80211_IFTYPE_NAN, {"NAN", DataType::Flag}}, +}; + +// clang-format off +Nl80211::Nl80211(nlmsgtype_t familyId) : GenericMessageBase(familyId, "nl80211", { + /* Script to generate the (initial) top-level list from linux/nl80211.h: + * sed -e 's/^ NL80211_CMD_\(.*\),$/ {NL80211_CMD_\1, "\1"},/g' + */ + {NL80211_CMD_UNSPEC, "UNSPEC"}, + + {NL80211_CMD_GET_WIPHY, "GET_WIPHY"}, + {NL80211_CMD_SET_WIPHY, "SET_WIPHY"}, + {NL80211_CMD_NEW_WIPHY, "NEW_WIPHY"}, + {NL80211_CMD_DEL_WIPHY, "DEL_WIPHY"}, + + {NL80211_CMD_GET_INTERFACE, "GET_INTERFACE"}, + {NL80211_CMD_SET_INTERFACE, "SET_INTERFACE"}, + {NL80211_CMD_NEW_INTERFACE, "NEW_INTERFACE"}, + {NL80211_CMD_DEL_INTERFACE, "DEL_INTERFACE"}, + + {NL80211_CMD_GET_KEY, "GET_KEY"}, + {NL80211_CMD_SET_KEY, "SET_KEY"}, + {NL80211_CMD_NEW_KEY, "NEW_KEY"}, + {NL80211_CMD_DEL_KEY, "DEL_KEY"}, + + {NL80211_CMD_GET_BEACON, "GET_BEACON"}, + {NL80211_CMD_SET_BEACON, "SET_BEACON"}, + {NL80211_CMD_START_AP, "START_AP"}, + {NL80211_CMD_STOP_AP, "STOP_AP"}, + + {NL80211_CMD_GET_STATION, "GET_STATION"}, + {NL80211_CMD_SET_STATION, "SET_STATION"}, + {NL80211_CMD_NEW_STATION, "NEW_STATION"}, + {NL80211_CMD_DEL_STATION, "DEL_STATION"}, + + {NL80211_CMD_GET_MPATH, "GET_MPATH"}, + {NL80211_CMD_SET_MPATH, "SET_MPATH"}, + {NL80211_CMD_NEW_MPATH, "NEW_MPATH"}, + {NL80211_CMD_DEL_MPATH, "DEL_MPATH"}, + + {NL80211_CMD_SET_BSS, "SET_BSS"}, + + {NL80211_CMD_SET_REG, "SET_REG"}, + {NL80211_CMD_REQ_SET_REG, "REQ_SET_REG"}, + + {NL80211_CMD_GET_MESH_CONFIG, "GET_MESH_CONFIG"}, + {NL80211_CMD_SET_MESH_CONFIG, "SET_MESH_CONFIG"}, + + {NL80211_CMD_SET_MGMT_EXTRA_IE, "SET_MGMT_EXTRA_IE"}, + + {NL80211_CMD_GET_REG, "GET_REG"}, + + {NL80211_CMD_GET_SCAN, "GET_SCAN"}, + {NL80211_CMD_TRIGGER_SCAN, "TRIGGER_SCAN"}, + {NL80211_CMD_NEW_SCAN_RESULTS, "NEW_SCAN_RESULTS"}, + {NL80211_CMD_SCAN_ABORTED, "SCAN_ABORTED"}, + + {NL80211_CMD_REG_CHANGE, "REG_CHANGE"}, + + {NL80211_CMD_AUTHENTICATE, "AUTHENTICATE"}, + {NL80211_CMD_ASSOCIATE, "ASSOCIATE"}, + {NL80211_CMD_DEAUTHENTICATE, "DEAUTHENTICATE"}, + {NL80211_CMD_DISASSOCIATE, "DISASSOCIATE"}, + + {NL80211_CMD_MICHAEL_MIC_FAILURE, "MICHAEL_MIC_FAILURE"}, + + {NL80211_CMD_REG_BEACON_HINT, "REG_BEACON_HINT"}, + + {NL80211_CMD_JOIN_IBSS, "JOIN_IBSS"}, + {NL80211_CMD_LEAVE_IBSS, "LEAVE_IBSS"}, + + {NL80211_CMD_TESTMODE, "TESTMODE"}, + + {NL80211_CMD_CONNECT, "CONNECT"}, + {NL80211_CMD_ROAM, "ROAM"}, + {NL80211_CMD_DISCONNECT, "DISCONNECT"}, + + {NL80211_CMD_SET_WIPHY_NETNS, "SET_WIPHY_NETNS"}, + + {NL80211_CMD_GET_SURVEY, "GET_SURVEY"}, + {NL80211_CMD_NEW_SURVEY_RESULTS, "NEW_SURVEY_RESULTS"}, + + {NL80211_CMD_SET_PMKSA, "SET_PMKSA"}, + {NL80211_CMD_DEL_PMKSA, "DEL_PMKSA"}, + {NL80211_CMD_FLUSH_PMKSA, "FLUSH_PMKSA"}, + + {NL80211_CMD_REMAIN_ON_CHANNEL, "REMAIN_ON_CHANNEL"}, + {NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL, "CANCEL_REMAIN_ON_CHANNEL"}, + + {NL80211_CMD_SET_TX_BITRATE_MASK, "SET_TX_BITRATE_MASK"}, + + {NL80211_CMD_REGISTER_FRAME, "REGISTER_FRAME"}, + {NL80211_CMD_FRAME, "FRAME"}, + {NL80211_CMD_FRAME_TX_STATUS, "FRAME_TX_STATUS"}, + + {NL80211_CMD_SET_POWER_SAVE, "SET_POWER_SAVE"}, + {NL80211_CMD_GET_POWER_SAVE, "GET_POWER_SAVE"}, + + {NL80211_CMD_SET_CQM, "SET_CQM"}, + {NL80211_CMD_NOTIFY_CQM, "NOTIFY_CQM"}, + + {NL80211_CMD_SET_CHANNEL, "SET_CHANNEL"}, + {NL80211_CMD_SET_WDS_PEER, "SET_WDS_PEER"}, + + {NL80211_CMD_FRAME_WAIT_CANCEL, "FRAME_WAIT_CANCEL"}, + + {NL80211_CMD_JOIN_MESH, "JOIN_MESH"}, + {NL80211_CMD_LEAVE_MESH, "LEAVE_MESH"}, + + {NL80211_CMD_UNPROT_DEAUTHENTICATE, "UNPROT_DEAUTHENTICATE"}, + {NL80211_CMD_UNPROT_DISASSOCIATE, "UNPROT_DISASSOCIATE"}, + + {NL80211_CMD_NEW_PEER_CANDIDATE, "NEW_PEER_CANDIDATE"}, + + {NL80211_CMD_GET_WOWLAN, "GET_WOWLAN"}, + {NL80211_CMD_SET_WOWLAN, "SET_WOWLAN"}, + + {NL80211_CMD_START_SCHED_SCAN, "START_SCHED_SCAN"}, + {NL80211_CMD_STOP_SCHED_SCAN, "STOP_SCHED_SCAN"}, + {NL80211_CMD_SCHED_SCAN_RESULTS, "SCHED_SCAN_RESULTS"}, + {NL80211_CMD_SCHED_SCAN_STOPPED, "SCHED_SCAN_STOPPED"}, + + {NL80211_CMD_SET_REKEY_OFFLOAD, "SET_REKEY_OFFLOAD"}, + + {NL80211_CMD_PMKSA_CANDIDATE, "PMKSA_CANDIDATE"}, + + {NL80211_CMD_TDLS_OPER, "TDLS_OPER"}, + {NL80211_CMD_TDLS_MGMT, "TDLS_MGMT"}, + + {NL80211_CMD_UNEXPECTED_FRAME, "UNEXPECTED_FRAME"}, + + {NL80211_CMD_PROBE_CLIENT, "PROBE_CLIENT"}, + + {NL80211_CMD_REGISTER_BEACONS, "REGISTER_BEACONS"}, + + {NL80211_CMD_UNEXPECTED_4ADDR_FRAME, "UNEXPECTED_4ADDR_FRAME"}, + + {NL80211_CMD_SET_NOACK_MAP, "SET_NOACK_MAP"}, + + {NL80211_CMD_CH_SWITCH_NOTIFY, "CH_SWITCH_NOTIFY"}, + + {NL80211_CMD_START_P2P_DEVICE, "START_P2P_DEVICE"}, + {NL80211_CMD_STOP_P2P_DEVICE, "STOP_P2P_DEVICE"}, + + {NL80211_CMD_CONN_FAILED, "CONN_FAILED"}, + + {NL80211_CMD_SET_MCAST_RATE, "SET_MCAST_RATE"}, + + {NL80211_CMD_SET_MAC_ACL, "SET_MAC_ACL"}, + + {NL80211_CMD_RADAR_DETECT, "RADAR_DETECT"}, + + {NL80211_CMD_GET_PROTOCOL_FEATURES, "GET_PROTOCOL_FEATURES"}, + + {NL80211_CMD_UPDATE_FT_IES, "UPDATE_FT_IES"}, + {NL80211_CMD_FT_EVENT, "FT_EVENT"}, + + {NL80211_CMD_CRIT_PROTOCOL_START, "CRIT_PROTOCOL_START"}, + {NL80211_CMD_CRIT_PROTOCOL_STOP, "CRIT_PROTOCOL_STOP"}, + + {NL80211_CMD_GET_COALESCE, "GET_COALESCE"}, + {NL80211_CMD_SET_COALESCE, "SET_COALESCE"}, + + {NL80211_CMD_CHANNEL_SWITCH, "CHANNEL_SWITCH"}, + + {NL80211_CMD_VENDOR, "VENDOR"}, + + {NL80211_CMD_SET_QOS_MAP, "SET_QOS_MAP"}, + + {NL80211_CMD_ADD_TX_TS, "ADD_TX_TS"}, + {NL80211_CMD_DEL_TX_TS, "DEL_TX_TS"}, + + {NL80211_CMD_GET_MPP, "GET_MPP"}, + + {NL80211_CMD_JOIN_OCB, "JOIN_OCB"}, + {NL80211_CMD_LEAVE_OCB, "LEAVE_OCB"}, + + {NL80211_CMD_CH_SWITCH_STARTED_NOTIFY, "CH_SWITCH_STARTED_NOTIFY"}, + + {NL80211_CMD_TDLS_CHANNEL_SWITCH, "TDLS_CHANNEL_SWITCH"}, + {NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH, "TDLS_CANCEL_CHANNEL_SWITCH"}, + + {NL80211_CMD_WIPHY_REG_CHANGE, "WIPHY_REG_CHANGE"}, + + {NL80211_CMD_ABORT_SCAN, "ABORT_SCAN"}, + + {NL80211_CMD_START_NAN, "START_NAN"}, + {NL80211_CMD_STOP_NAN, "STOP_NAN"}, + {NL80211_CMD_ADD_NAN_FUNCTION, "ADD_NAN_FUNCTION"}, + {NL80211_CMD_DEL_NAN_FUNCTION, "DEL_NAN_FUNCTION"}, + {NL80211_CMD_CHANGE_NAN_CONFIG, "CHANGE_NAN_CONFIG"}, + {NL80211_CMD_NAN_MATCH, "NAN_MATCH"}, + + {NL80211_CMD_SET_MULTICAST_TO_UNICAST, "SET_MULTICAST_TO_UNICAST"}, + + {NL80211_CMD_UPDATE_CONNECT_PARAMS, "UPDATE_CONNECT_PARAMS"}, + + {NL80211_CMD_SET_PMK, "SET_PMK"}, + {NL80211_CMD_DEL_PMK, "DEL_PMK"}, + + {NL80211_CMD_PORT_AUTHORIZED, "PORT_AUTHORIZED"}, + + {NL80211_CMD_RELOAD_REGDB, "RELOAD_REGDB"}, + + {NL80211_CMD_EXTERNAL_AUTH, "EXTERNAL_AUTH"}, + + {NL80211_CMD_STA_OPMODE_CHANGED, "STA_OPMODE_CHANGED"}, + + {NL80211_CMD_CONTROL_PORT_FRAME, "CONTROL_PORT_FRAME"}, + + {NL80211_CMD_GET_FTM_RESPONDER_STATS, "GET_FTM_RESPONDER_STATS"}, + + {NL80211_CMD_PEER_MEASUREMENT_START, "PEER_MEASUREMENT_START"}, + {NL80211_CMD_PEER_MEASUREMENT_RESULT, "PEER_MEASUREMENT_RESULT"}, + {NL80211_CMD_PEER_MEASUREMENT_COMPLETE, "PEER_MEASUREMENT_COMPLETE"}, + + {NL80211_CMD_NOTIFY_RADAR, "NOTIFY_RADAR"}, + + {NL80211_CMD_UPDATE_OWE_INFO, "UPDATE_OWE_INFO"}, + + {NL80211_CMD_PROBE_MESH_LINK, "PROBE_MESH_LINK"}, + + {NL80211_CMD_SET_TID_CONFIG, "SET_TID_CONFIG"}, + + {NL80211_CMD_UNPROT_BEACON, "UNPROT_BEACON"}, + + {NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS, "CONTROL_PORT_FRAME_TX_STATUS"}, +}, { + /* Script to generate the (initial) top-level list from linux/nl80211.h: + * sed -e 's/^\tNL80211_ATTR_\(.*\),$/ {NL80211_ATTR_\1, {"\1"}},/g' + */ + {NL80211_ATTR_UNSPEC, {"UNSPEC"}}, + + {NL80211_ATTR_WIPHY, {"WIPHY", DataType::Uint}}, + {NL80211_ATTR_WIPHY_NAME, {"WIPHY_NAME", DataType::StringNul}}, + + {NL80211_ATTR_IFINDEX, {"IFINDEX", DataType::Uint}}, + {NL80211_ATTR_IFNAME, {"IFNAME", DataType::StringNul}}, + {NL80211_ATTR_IFTYPE, {"IFTYPE", DataType::Uint}}, + + {NL80211_ATTR_MAC, {"MAC", DataType::Raw}}, + + {NL80211_ATTR_KEY_DATA, {"KEY_DATA"}}, + {NL80211_ATTR_KEY_IDX, {"KEY_IDX"}}, + {NL80211_ATTR_KEY_CIPHER, {"KEY_CIPHER"}}, + {NL80211_ATTR_KEY_SEQ, {"KEY_SEQ"}}, + {NL80211_ATTR_KEY_DEFAULT, {"KEY_DEFAULT"}}, + + {NL80211_ATTR_BEACON_INTERVAL, {"BEACON_INTERVAL"}}, + {NL80211_ATTR_DTIM_PERIOD, {"DTIM_PERIOD"}}, + {NL80211_ATTR_BEACON_HEAD, {"BEACON_HEAD"}}, + {NL80211_ATTR_BEACON_TAIL, {"BEACON_TAIL"}}, + + {NL80211_ATTR_STA_AID, {"STA_AID"}}, + {NL80211_ATTR_STA_FLAGS, {"STA_FLAGS"}}, + {NL80211_ATTR_STA_LISTEN_INTERVAL, {"STA_LISTEN_INTERVAL"}}, + {NL80211_ATTR_STA_SUPPORTED_RATES, {"STA_SUPPORTED_RATES"}}, + {NL80211_ATTR_STA_VLAN, {"STA_VLAN"}}, + {NL80211_ATTR_STA_INFO, {"STA_INFO"}}, + + {NL80211_ATTR_WIPHY_BANDS, {"WIPHY_BANDS", DataType::Nested, AttributeMap{ + {std::nullopt, {"BAND", DataType::Nested, AttributeMap{ + {NL80211_BAND_ATTR_FREQS, {"FREQS", DataType::Nested, AttributeMap{ + {std::nullopt, {"FQ", DataType::Nested, AttributeMap{ + {NL80211_FREQUENCY_ATTR_FREQ, {"FREQ", DataType::Uint}}, + {NL80211_FREQUENCY_ATTR_DISABLED, {"DISABLED", DataType::Flag}}, + {NL80211_FREQUENCY_ATTR_NO_IR, {"NO_IR", DataType::Flag}}, + {__NL80211_FREQUENCY_ATTR_NO_IBSS, {"_NO_IBSS", DataType::Flag}}, + {NL80211_FREQUENCY_ATTR_RADAR, {"RADAR", DataType::Flag}}, + {NL80211_FREQUENCY_ATTR_MAX_TX_POWER, {"MAX_TX_POWER", DataType::Uint}}, + {NL80211_FREQUENCY_ATTR_DFS_STATE, {"DFS_STATE", DataType::Uint}}, + {NL80211_FREQUENCY_ATTR_DFS_TIME, {"DFS_TIME", DataType::Uint}}, + {NL80211_FREQUENCY_ATTR_NO_HT40_MINUS, {"NO_HT40_MINUS", DataType::Flag}}, + {NL80211_FREQUENCY_ATTR_NO_HT40_PLUS, {"NO_HT40_PLUS", DataType::Flag}}, + {NL80211_FREQUENCY_ATTR_NO_80MHZ, {"NO_80MHZ", DataType::Flag}}, + {NL80211_FREQUENCY_ATTR_NO_160MHZ, {"NO_160MHZ", DataType::Flag}}, + {NL80211_FREQUENCY_ATTR_DFS_CAC_TIME, {"DFS_CAC_TIME", DataType::Uint}}, + {NL80211_FREQUENCY_ATTR_INDOOR_ONLY, {"INDOOR_ONLY", DataType::Flag}}, + {NL80211_FREQUENCY_ATTR_IR_CONCURRENT, {"IR_CONCURRENT", DataType::Flag}}, + {NL80211_FREQUENCY_ATTR_NO_20MHZ, {"NO_20MHZ", DataType::Flag}}, + {NL80211_FREQUENCY_ATTR_NO_10MHZ, {"NO_10MHZ", DataType::Flag}}, + {NL80211_FREQUENCY_ATTR_WMM, {"WMM"}}, + {NL80211_FREQUENCY_ATTR_NO_HE, {"NO_HE", DataType::Flag}}, + {NL80211_FREQUENCY_ATTR_OFFSET, {"OFFSET", DataType::Uint}}, + {NL80211_FREQUENCY_ATTR_1MHZ, {"1MHZ", DataType::Flag}}, + {NL80211_FREQUENCY_ATTR_2MHZ, {"2MHZ", DataType::Flag}}, + {NL80211_FREQUENCY_ATTR_4MHZ, {"4MHZ", DataType::Flag}}, + {NL80211_FREQUENCY_ATTR_8MHZ, {"8MHZ", DataType::Flag}}, + {NL80211_FREQUENCY_ATTR_16MHZ, {"16MHZ", DataType::Flag}}, + }}}, + }, Flags::Verbose}}, + {NL80211_BAND_ATTR_RATES, {"RATES", DataType::Nested, AttributeMap{ + {std::nullopt, {"RATE", DataType::Nested, AttributeMap{ + {NL80211_BITRATE_ATTR_RATE, {"RATE", DataType::Uint}}, + {NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE, + {"2GHZ_SHORTPREAMBLE", DataType::Flag}}, + }}}, + }}}, + + {NL80211_BAND_ATTR_HT_MCS_SET, {"HT_MCS_SET"}}, // struct ieee80211_mcs_info + {NL80211_BAND_ATTR_HT_CAPA, {"HT_CAPA", DataType::Uint}}, + {NL80211_BAND_ATTR_HT_AMPDU_FACTOR, {"HT_AMPDU_FACTOR", DataType::Uint}}, + {NL80211_BAND_ATTR_HT_AMPDU_DENSITY, {"HT_AMPDU_DENSITY", DataType::Uint}}, + + {NL80211_BAND_ATTR_VHT_MCS_SET, {"VHT_MCS_SET"}}, // struct ieee80211_vht_mcs_info + {NL80211_BAND_ATTR_VHT_CAPA, {"VHT_CAPA", DataType::Uint}}, + {NL80211_BAND_ATTR_IFTYPE_DATA, {"IFTYPE_DATA"}}, + + {NL80211_BAND_ATTR_EDMG_CHANNELS, {"EDMG_CHANNELS"}}, + {NL80211_BAND_ATTR_EDMG_BW_CONFIG, {"EDMG_BW_CONFIG"}}, + }}}, + }, Flags::Verbose}}, + + {NL80211_ATTR_MNTR_FLAGS, {"MNTR_FLAGS"}}, + + {NL80211_ATTR_MESH_ID, {"MESH_ID"}}, + {NL80211_ATTR_STA_PLINK_ACTION, {"STA_PLINK_ACTION"}}, + {NL80211_ATTR_MPATH_NEXT_HOP, {"MPATH_NEXT_HOP"}}, + {NL80211_ATTR_MPATH_INFO, {"MPATH_INFO"}}, + + {NL80211_ATTR_BSS_CTS_PROT, {"BSS_CTS_PROT"}}, + {NL80211_ATTR_BSS_SHORT_PREAMBLE, {"BSS_SHORT_PREAMBLE"}}, + {NL80211_ATTR_BSS_SHORT_SLOT_TIME, {"BSS_SHORT_SLOT_TIME"}}, + + {NL80211_ATTR_HT_CAPABILITY, {"HT_CAPABILITY"}}, + + {NL80211_ATTR_SUPPORTED_IFTYPES, {"SUPPORTED_IFTYPES", DataType::Nested, iftypes}}, + + {NL80211_ATTR_REG_ALPHA2, {"REG_ALPHA2"}}, + {NL80211_ATTR_REG_RULES, {"REG_RULES"}}, + + {NL80211_ATTR_MESH_CONFIG, {"MESH_CONFIG"}}, + + {NL80211_ATTR_BSS_BASIC_RATES, {"BSS_BASIC_RATES"}}, + + {NL80211_ATTR_WIPHY_TXQ_PARAMS, {"WIPHY_TXQ_PARAMS"}}, + {NL80211_ATTR_WIPHY_FREQ, {"WIPHY_FREQ"}}, + {NL80211_ATTR_WIPHY_CHANNEL_TYPE, {"WIPHY_CHANNEL_TYPE"}}, + + {NL80211_ATTR_KEY_DEFAULT_MGMT, {"KEY_DEFAULT_MGMT"}}, + + {NL80211_ATTR_MGMT_SUBTYPE, {"MGMT_SUBTYPE"}}, + {NL80211_ATTR_IE, {"IE"}}, + + {NL80211_ATTR_MAX_NUM_SCAN_SSIDS, {"MAX_NUM_SCAN_SSIDS", DataType::Uint}}, + + {NL80211_ATTR_SCAN_FREQUENCIES, {"SCAN_FREQUENCIES", DataType::Nested, AttributeMap{ + {std::nullopt, {"FQ", DataType::Uint}}, + }, Flags::Verbose}}, + {NL80211_ATTR_SCAN_SSIDS, {"SCAN_SSIDS", DataType::Nested, AttributeMap{ + {std::nullopt, {"SSID", DataType::String}}, + }}}, + {NL80211_ATTR_GENERATION, {"GENERATION", DataType::Uint}}, + {NL80211_ATTR_BSS, {"BSS", DataType::Nested, AttributeMap{ + {NL80211_BSS_BSSID, {"BSSID", DataType::Raw}}, + {NL80211_BSS_FREQUENCY, {"FREQUENCY", DataType::Uint}}, + {NL80211_BSS_TSF, {"TSF", DataType::Uint}}, + {NL80211_BSS_BEACON_INTERVAL, {"BEACON_INTERVAL", DataType::Uint}}, + {NL80211_BSS_CAPABILITY, {"CAPABILITY", DataType::Uint}}, + {NL80211_BSS_INFORMATION_ELEMENTS, {"INFORMATION_ELEMENTS", + DataType::Struct, informationElementsToStream}}, + {NL80211_BSS_SIGNAL_MBM, {"SIGNAL_MBM", DataType::Uint}}, + {NL80211_BSS_SIGNAL_UNSPEC, {"SIGNAL_UNSPEC", DataType::Uint}}, + {NL80211_BSS_STATUS, {"STATUS", DataType::Uint}}, // enum nl80211_bss_status + {NL80211_BSS_SEEN_MS_AGO, {"SEEN_MS_AGO", DataType::Uint}}, + {NL80211_BSS_BEACON_IES, {"BEACON_IES", DataType::Struct, informationElementsToStream}}, + {NL80211_BSS_CHAN_WIDTH, {"CHAN_WIDTH", DataType::Uint}}, + {NL80211_BSS_BEACON_TSF, {"BEACON_TSF", DataType::Uint}}, + {NL80211_BSS_PRESP_DATA, {"PRESP_DATA", DataType::Flag}}, + {NL80211_BSS_LAST_SEEN_BOOTTIME, {"LAST_SEEN_BOOTTIME", DataType::Uint}}, + {NL80211_BSS_PAD, {"PAD"}}, + {NL80211_BSS_PARENT_TSF, {"PARENT_TSF"}}, + {NL80211_BSS_PARENT_BSSID, {"PARENT_BSSID"}}, + {NL80211_BSS_CHAIN_SIGNAL, {"CHAIN_SIGNAL", DataType::Nested, AttributeMap{ + {std::nullopt, {"SIG", DataType::Uint}}, + }}}, + {NL80211_BSS_FREQUENCY_OFFSET, {"FREQUENCY_OFFSET"}}, + }}}, + + {NL80211_ATTR_REG_INITIATOR, {"REG_INITIATOR"}}, + {NL80211_ATTR_REG_TYPE, {"REG_TYPE"}}, + + {NL80211_ATTR_SUPPORTED_COMMANDS, {"SUPPORTED_COMMANDS", DataType::Nested,AttributeMap{ + {std::nullopt, {"CMD", DataType::Uint}}, // enum nl80211_commands + }}}, + + {NL80211_ATTR_FRAME, {"FRAME"}}, + {NL80211_ATTR_SSID, {"SSID"}}, + {NL80211_ATTR_AUTH_TYPE, {"AUTH_TYPE"}}, + {NL80211_ATTR_REASON_CODE, {"REASON_CODE"}}, + + {NL80211_ATTR_KEY_TYPE, {"KEY_TYPE"}}, + + {NL80211_ATTR_MAX_SCAN_IE_LEN, {"MAX_SCAN_IE_LEN", DataType::Uint}}, + {NL80211_ATTR_CIPHER_SUITES, {"CIPHER_SUITES", DataType::Struct, arrayToStream}}, + + {NL80211_ATTR_FREQ_BEFORE, {"FREQ_BEFORE"}}, + {NL80211_ATTR_FREQ_AFTER, {"FREQ_AFTER"}}, + + {NL80211_ATTR_FREQ_FIXED, {"FREQ_FIXED"}}, + + {NL80211_ATTR_WIPHY_RETRY_SHORT, {"WIPHY_RETRY_SHORT", DataType::Uint}}, + {NL80211_ATTR_WIPHY_RETRY_LONG, {"WIPHY_RETRY_LONG", DataType::Uint}}, + {NL80211_ATTR_WIPHY_FRAG_THRESHOLD, {"WIPHY_FRAG_THRESHOLD", DataType::Uint}}, + {NL80211_ATTR_WIPHY_RTS_THRESHOLD, {"WIPHY_RTS_THRESHOLD", DataType::Uint}}, + + {NL80211_ATTR_TIMED_OUT, {"TIMED_OUT"}}, + + {NL80211_ATTR_USE_MFP, {"USE_MFP"}}, + + {NL80211_ATTR_STA_FLAGS2, {"STA_FLAGS2"}}, + + {NL80211_ATTR_CONTROL_PORT, {"CONTROL_PORT"}}, + + {NL80211_ATTR_TESTDATA, {"TESTDATA"}}, + + {NL80211_ATTR_PRIVACY, {"PRIVACY"}}, + + {NL80211_ATTR_DISCONNECTED_BY_AP, {"DISCONNECTED_BY_AP"}}, + {NL80211_ATTR_STATUS_CODE, {"STATUS_CODE"}}, + + {NL80211_ATTR_CIPHER_SUITES_PAIRWISE, {"CIPHER_SUITES_PAIRWISE"}}, + {NL80211_ATTR_CIPHER_SUITE_GROUP, {"CIPHER_SUITE_GROUP"}}, + {NL80211_ATTR_WPA_VERSIONS, {"WPA_VERSIONS"}}, + {NL80211_ATTR_AKM_SUITES, {"AKM_SUITES"}}, + + {NL80211_ATTR_REQ_IE, {"REQ_IE"}}, + {NL80211_ATTR_RESP_IE, {"RESP_IE"}}, + + {NL80211_ATTR_PREV_BSSID, {"PREV_BSSID"}}, + + {NL80211_ATTR_KEY, {"KEY"}}, + {NL80211_ATTR_KEYS, {"KEYS"}}, + + {NL80211_ATTR_PID, {"PID"}}, + + {NL80211_ATTR_4ADDR, {"4ADDR"}}, + + {NL80211_ATTR_SURVEY_INFO, {"SURVEY_INFO"}}, + + {NL80211_ATTR_PMKID, {"PMKID"}}, + {NL80211_ATTR_MAX_NUM_PMKIDS, {"MAX_NUM_PMKIDS", DataType::Uint}}, + + {NL80211_ATTR_DURATION, {"DURATION"}}, + + {NL80211_ATTR_COOKIE, {"COOKIE"}}, + + {NL80211_ATTR_WIPHY_COVERAGE_CLASS, {"WIPHY_COVERAGE_CLASS", DataType::Uint}}, + + {NL80211_ATTR_TX_RATES, {"TX_RATES"}}, + + {NL80211_ATTR_FRAME_MATCH, {"FRAME_MATCH"}}, + + {NL80211_ATTR_ACK, {"ACK"}}, + + {NL80211_ATTR_PS_STATE, {"PS_STATE"}}, + + {NL80211_ATTR_CQM, {"CQM"}}, + + {NL80211_ATTR_LOCAL_STATE_CHANGE, {"LOCAL_STATE_CHANGE"}}, + + {NL80211_ATTR_AP_ISOLATE, {"AP_ISOLATE"}}, + + {NL80211_ATTR_WIPHY_TX_POWER_SETTING, {"WIPHY_TX_POWER_SETTING"}}, + {NL80211_ATTR_WIPHY_TX_POWER_LEVEL, {"WIPHY_TX_POWER_LEVEL"}}, + + {NL80211_ATTR_TX_FRAME_TYPES, {"TX_FRAME_TYPES", DataType::Nested, AttributeMap{ + {std::nullopt, {"TFT", DataType::Nested, AttributeMap{ + {NL80211_ATTR_FRAME_TYPE, {"FRAME_TYPE", DataType::Uint}}, + }}}, + }, Flags::Verbose}}, + {NL80211_ATTR_RX_FRAME_TYPES, {"RX_FRAME_TYPES", DataType::Nested, AttributeMap{ + {std::nullopt, {"RFT", DataType::Nested, AttributeMap{ + {NL80211_ATTR_FRAME_TYPE, {"FRAME_TYPE", DataType::Uint}}, + }}}, + }, Flags::Verbose}}, + + {NL80211_ATTR_FRAME_TYPE, {"FRAME_TYPE", DataType::Uint}}, + + {NL80211_ATTR_CONTROL_PORT_ETHERTYPE, {"CONTROL_PORT_ETHERTYPE"}}, + {NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT, {"CONTROL_PORT_NO_ENCRYPT"}}, + + {NL80211_ATTR_SUPPORT_IBSS_RSN, {"SUPPORT_IBSS_RSN"}}, + + {NL80211_ATTR_WIPHY_ANTENNA_TX, {"WIPHY_ANTENNA_TX"}}, + {NL80211_ATTR_WIPHY_ANTENNA_RX, {"WIPHY_ANTENNA_RX"}}, + + {NL80211_ATTR_MCAST_RATE, {"MCAST_RATE"}}, + + {NL80211_ATTR_OFFCHANNEL_TX_OK, {"OFFCHANNEL_TX_OK", DataType::Flag}}, + + {NL80211_ATTR_BSS_HT_OPMODE, {"BSS_HT_OPMODE"}}, + + {NL80211_ATTR_KEY_DEFAULT_TYPES, {"KEY_DEFAULT_TYPES"}}, + + {NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION, + {"MAX_REMAIN_ON_CHANNEL_DURATION", DataType::Uint}}, + + {NL80211_ATTR_MESH_SETUP, {"MESH_SETUP"}}, + + {NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX, {"WIPHY_ANTENNA_AVAIL_TX", DataType::Uint}}, + {NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX, {"WIPHY_ANTENNA_AVAIL_RX", DataType::Uint}}, + + {NL80211_ATTR_SUPPORT_MESH_AUTH, {"SUPPORT_MESH_AUTH"}}, + {NL80211_ATTR_STA_PLINK_STATE, {"STA_PLINK_STATE"}}, + + {NL80211_ATTR_WOWLAN_TRIGGERS, {"WOWLAN_TRIGGERS"}}, + {NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, + {"WOWLAN_TRIGGERS_SUPPORTED", DataType::Nested, AttributeMap{ + {NL80211_WOWLAN_TRIG_ANY, {"ANY", DataType::Flag}}, + {NL80211_WOWLAN_TRIG_DISCONNECT, {"DISCONNECT", DataType::Flag}}, + {NL80211_WOWLAN_TRIG_MAGIC_PKT, {"MAGIC_PKT", DataType::Flag}}, + {NL80211_WOWLAN_TRIG_PKT_PATTERN, + {"PKT_PATTERN", DataType::Struct, nl80211_pattern_supportToStream}}, + {NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED, {"GTK_REKEY_SUPPORTED", DataType::Flag}}, + {NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE, {"GTK_REKEY_FAILURE", DataType::Flag}}, + {NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST, {"EAP_IDENT_REQUEST", DataType::Flag}}, + {NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE, {"4WAY_HANDSHAKE", DataType::Flag}}, + {NL80211_WOWLAN_TRIG_RFKILL_RELEASE, {"RFKILL_RELEASE", DataType::Flag}}, + {NL80211_WOWLAN_TRIG_TCP_CONNECTION, {"TCP_CONNECTION", DataType::Nested, AttributeMap{ + {NL80211_WOWLAN_TCP_SRC_IPV4, {"SRC_IPV4"}}, + {NL80211_WOWLAN_TCP_DST_IPV4, {"DST_IPV4"}}, + {NL80211_WOWLAN_TCP_DST_MAC, {"DST_MAC"}}, + {NL80211_WOWLAN_TCP_SRC_PORT, {"SRC_PORT", DataType::Uint}}, + {NL80211_WOWLAN_TCP_DST_PORT, {"DST_PORT", DataType::Uint}}, + {NL80211_WOWLAN_TCP_DATA_PAYLOAD, {"DATA_PAYLOAD"}}, + {NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ, {"DATA_PAYLOAD_SEQ"}}, + {NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN, {"DATA_PAYLOAD_TOKEN"}}, + {NL80211_WOWLAN_TCP_DATA_INTERVAL, {"DATA_INTERVAL", DataType::Uint}}, + {NL80211_WOWLAN_TCP_WAKE_PAYLOAD, {"WAKE_PAYLOAD"}}, + {NL80211_WOWLAN_TCP_WAKE_MASK, {"WAKE_MASK"}}, + }}}, + {NL80211_WOWLAN_TRIG_NET_DETECT, {"NET_DETECT", DataType::Uint}}, + + /* Not in WOWLAN_TRIGGERS_SUPPORTED: + * - NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211 + * - NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN + * - NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023 + * - NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN + * - NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH + * - NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST + * - NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS + * - NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS + */ + }}}, + + {NL80211_ATTR_SCHED_SCAN_INTERVAL, {"SCHED_SCAN_INTERVAL"}}, + + {NL80211_ATTR_INTERFACE_COMBINATIONS, {"INTERFACE_COMBINATIONS", DataType::Nested, AttributeMap{ + {std::nullopt, {"IC", DataType::Nested, AttributeMap{ + {NL80211_IFACE_COMB_UNSPEC, {"UNSPEC"}}, + {NL80211_IFACE_COMB_LIMITS, {"LIMITS", DataType::Nested, AttributeMap{ + {std::nullopt, {"LT", DataType::Nested, AttributeMap{ + {NL80211_IFACE_LIMIT_UNSPEC, {"UNSPEC"}}, + {NL80211_IFACE_LIMIT_MAX, {"MAX", DataType::Uint}}, + {NL80211_IFACE_LIMIT_TYPES, {"TYPES", DataType::Nested, iftypes}}, + }}}, + }}}, + {NL80211_IFACE_COMB_MAXNUM, {"MAXNUM", DataType::Uint}}, + {NL80211_IFACE_COMB_STA_AP_BI_MATCH, {"STA_AP_BI_MATCH", DataType::Flag}}, + {NL80211_IFACE_COMB_NUM_CHANNELS, {"NUM_CHANNELS", DataType::Uint}}, + {NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS, {"RADAR_DETECT_WIDTHS", DataType::Uint}}, + {NL80211_IFACE_COMB_RADAR_DETECT_REGIONS, {"RADAR_DETECT_REGIONS", DataType::Uint}}, + {NL80211_IFACE_COMB_BI_MIN_GCD, {"BI_MIN_GCD"}}, + }}}, + }, Flags::Verbose}}, + {NL80211_ATTR_SOFTWARE_IFTYPES, {"SOFTWARE_IFTYPES", DataType::Nested, iftypes}}, + + {NL80211_ATTR_REKEY_DATA, {"REKEY_DATA"}}, + + {NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS, {"MAX_NUM_SCHED_SCAN_SSIDS", DataType::Uint}}, + {NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN, {"MAX_SCHED_SCAN_IE_LEN", DataType::Uint}}, + + {NL80211_ATTR_SCAN_SUPP_RATES, {"SCAN_SUPP_RATES"}}, + + {NL80211_ATTR_HIDDEN_SSID, {"HIDDEN_SSID"}}, + + {NL80211_ATTR_IE_PROBE_RESP, {"IE_PROBE_RESP"}}, + {NL80211_ATTR_IE_ASSOC_RESP, {"IE_ASSOC_RESP"}}, + + {NL80211_ATTR_STA_WME, {"STA_WME"}}, + {NL80211_ATTR_SUPPORT_AP_UAPSD, {"SUPPORT_AP_UAPSD"}}, + + {NL80211_ATTR_ROAM_SUPPORT, {"ROAM_SUPPORT", DataType::Flag}}, + + {NL80211_ATTR_SCHED_SCAN_MATCH, {"SCHED_SCAN_MATCH"}}, + {NL80211_ATTR_MAX_MATCH_SETS, {"MAX_MATCH_SETS", DataType::Uint}}, + + {NL80211_ATTR_PMKSA_CANDIDATE, {"PMKSA_CANDIDATE"}}, + + {NL80211_ATTR_TX_NO_CCK_RATE, {"TX_NO_CCK_RATE"}}, + + {NL80211_ATTR_TDLS_ACTION, {"TDLS_ACTION"}}, + {NL80211_ATTR_TDLS_DIALOG_TOKEN, {"TDLS_DIALOG_TOKEN"}}, + {NL80211_ATTR_TDLS_OPERATION, {"TDLS_OPERATION"}}, + {NL80211_ATTR_TDLS_SUPPORT, {"TDLS_SUPPORT", DataType::Flag}}, + {NL80211_ATTR_TDLS_EXTERNAL_SETUP, {"TDLS_EXTERNAL_SETUP", DataType::Flag}}, + + {NL80211_ATTR_DEVICE_AP_SME, {"DEVICE_AP_SME", DataType::Uint}}, + + {NL80211_ATTR_DONT_WAIT_FOR_ACK, {"DONT_WAIT_FOR_ACK"}}, + + {NL80211_ATTR_FEATURE_FLAGS, {"FEATURE_FLAGS", DataType::Uint}}, + + {NL80211_ATTR_PROBE_RESP_OFFLOAD, {"PROBE_RESP_OFFLOAD", DataType::Uint}}, + + {NL80211_ATTR_PROBE_RESP, {"PROBE_RESP"}}, + + {NL80211_ATTR_DFS_REGION, {"DFS_REGION"}}, + + {NL80211_ATTR_DISABLE_HT, {"DISABLE_HT"}}, + {NL80211_ATTR_HT_CAPABILITY_MASK, {"HT_CAPABILITY_MASK"}}, + + {NL80211_ATTR_NOACK_MAP, {"NOACK_MAP"}}, + + {NL80211_ATTR_INACTIVITY_TIMEOUT, {"INACTIVITY_TIMEOUT"}}, + + {NL80211_ATTR_RX_SIGNAL_DBM, {"RX_SIGNAL_DBM"}}, + + {NL80211_ATTR_BG_SCAN_PERIOD, {"BG_SCAN_PERIOD"}}, + + {NL80211_ATTR_WDEV, {"WDEV", DataType::Uint}}, + + {NL80211_ATTR_USER_REG_HINT_TYPE, {"USER_REG_HINT_TYPE"}}, + + {NL80211_ATTR_CONN_FAILED_REASON, {"CONN_FAILED_REASON"}}, + + {NL80211_ATTR_AUTH_DATA, {"AUTH_DATA"}}, + + {NL80211_ATTR_VHT_CAPABILITY, {"VHT_CAPABILITY"}}, + + {NL80211_ATTR_SCAN_FLAGS, {"SCAN_FLAGS", DataType::Uint}}, + + {NL80211_ATTR_CHANNEL_WIDTH, {"CHANNEL_WIDTH"}}, + {NL80211_ATTR_CENTER_FREQ1, {"CENTER_FREQ1"}}, + {NL80211_ATTR_CENTER_FREQ2, {"CENTER_FREQ2"}}, + + {NL80211_ATTR_P2P_CTWINDOW, {"P2P_CTWINDOW"}}, + {NL80211_ATTR_P2P_OPPPS, {"P2P_OPPPS"}}, + + {NL80211_ATTR_LOCAL_MESH_POWER_MODE, {"LOCAL_MESH_POWER_MODE"}}, + + {NL80211_ATTR_ACL_POLICY, {"ACL_POLICY"}}, + + {NL80211_ATTR_MAC_ADDRS, {"MAC_ADDRS"}}, + + {NL80211_ATTR_MAC_ACL_MAX, {"MAC_ACL_MAX", DataType::Uint}}, + + {NL80211_ATTR_RADAR_EVENT, {"RADAR_EVENT"}}, + + {NL80211_ATTR_EXT_CAPA, {"EXT_CAPA"}}, + {NL80211_ATTR_EXT_CAPA_MASK, {"EXT_CAPA_MASK"}}, + + {NL80211_ATTR_STA_CAPABILITY, {"STA_CAPABILITY"}}, + {NL80211_ATTR_STA_EXT_CAPABILITY, {"STA_EXT_CAPABILITY"}}, + + {NL80211_ATTR_PROTOCOL_FEATURES, {"PROTOCOL_FEATURES", DataType::Uint}}, + {NL80211_ATTR_SPLIT_WIPHY_DUMP, {"SPLIT_WIPHY_DUMP", DataType::Flag}}, + + {NL80211_ATTR_DISABLE_VHT, {"DISABLE_VHT", DataType::Flag}}, + {NL80211_ATTR_VHT_CAPABILITY_MASK, {"VHT_CAPABILITY_MASK"}}, + + {NL80211_ATTR_MDID, {"MDID"}}, + {NL80211_ATTR_IE_RIC, {"IE_RIC"}}, + + {NL80211_ATTR_CRIT_PROT_ID, {"CRIT_PROT_ID"}}, + {NL80211_ATTR_MAX_CRIT_PROT_DURATION, {"MAX_CRIT_PROT_DURATION"}}, + + {NL80211_ATTR_PEER_AID, {"PEER_AID"}}, + + {NL80211_ATTR_COALESCE_RULE, {"COALESCE_RULE"}}, + + {NL80211_ATTR_CH_SWITCH_COUNT, {"CH_SWITCH_COUNT"}}, + {NL80211_ATTR_CH_SWITCH_BLOCK_TX, {"CH_SWITCH_BLOCK_TX"}}, + {NL80211_ATTR_CSA_IES, {"CSA_IES"}}, + {NL80211_ATTR_CNTDWN_OFFS_BEACON, {"CNTDWN_OFFS_BEACON"}}, + {NL80211_ATTR_CNTDWN_OFFS_PRESP, {"CNTDWN_OFFS_PRESP"}}, + + {NL80211_ATTR_RXMGMT_FLAGS, {"RXMGMT_FLAGS"}}, + + {NL80211_ATTR_STA_SUPPORTED_CHANNELS, {"STA_SUPPORTED_CHANNELS"}}, + + {NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES, {"STA_SUPPORTED_OPER_CLASSES"}}, + + {NL80211_ATTR_HANDLE_DFS, {"HANDLE_DFS"}}, + + {NL80211_ATTR_SUPPORT_5_MHZ, {"SUPPORT_5_MHZ"}}, + {NL80211_ATTR_SUPPORT_10_MHZ, {"SUPPORT_10_MHZ"}}, + + {NL80211_ATTR_OPMODE_NOTIF, {"OPMODE_NOTIF"}}, + + {NL80211_ATTR_VENDOR_ID, {"VENDOR_ID"}}, + {NL80211_ATTR_VENDOR_SUBCMD, {"VENDOR_SUBCMD"}}, + {NL80211_ATTR_VENDOR_DATA, {"VENDOR_DATA", DataType::Raw, AttributeMap{}, Flags::Verbose}}, + {NL80211_ATTR_VENDOR_EVENTS, {"VENDOR_EVENTS", DataType::Nested, AttributeMap{}, + Flags::Verbose}}, + + {NL80211_ATTR_QOS_MAP, {"QOS_MAP"}}, + + {NL80211_ATTR_MAC_HINT, {"MAC_HINT"}}, + {NL80211_ATTR_WIPHY_FREQ_HINT, {"WIPHY_FREQ_HINT"}}, + + {NL80211_ATTR_MAX_AP_ASSOC_STA, {"MAX_AP_ASSOC_STA"}}, + + {NL80211_ATTR_TDLS_PEER_CAPABILITY, {"TDLS_PEER_CAPABILITY"}}, + + {NL80211_ATTR_SOCKET_OWNER, {"SOCKET_OWNER"}}, + + {NL80211_ATTR_CSA_C_OFFSETS_TX, {"CSA_C_OFFSETS_TX"}}, + {NL80211_ATTR_MAX_CSA_COUNTERS, {"MAX_CSA_COUNTERS"}}, + + {NL80211_ATTR_TDLS_INITIATOR, {"TDLS_INITIATOR"}}, + + {NL80211_ATTR_USE_RRM, {"USE_RRM"}}, + + {NL80211_ATTR_WIPHY_DYN_ACK, {"WIPHY_DYN_ACK"}}, + + {NL80211_ATTR_TSID, {"TSID"}}, + {NL80211_ATTR_USER_PRIO, {"USER_PRIO"}}, + {NL80211_ATTR_ADMITTED_TIME, {"ADMITTED_TIME"}}, + + {NL80211_ATTR_SMPS_MODE, {"SMPS_MODE"}}, + + {NL80211_ATTR_OPER_CLASS, {"OPER_CLASS"}}, + + {NL80211_ATTR_MAC_MASK, {"MAC_MASK"}}, + + {NL80211_ATTR_WIPHY_SELF_MANAGED_REG, {"WIPHY_SELF_MANAGED_REG"}}, + + {NL80211_ATTR_EXT_FEATURES, {"EXT_FEATURES"}}, + + {NL80211_ATTR_SURVEY_RADIO_STATS, {"SURVEY_RADIO_STATS"}}, + + {NL80211_ATTR_NETNS_FD, {"NETNS_FD"}}, + + {NL80211_ATTR_SCHED_SCAN_DELAY, {"SCHED_SCAN_DELAY"}}, + + {NL80211_ATTR_REG_INDOOR, {"REG_INDOOR"}}, + + {NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS, {"MAX_NUM_SCHED_SCAN_PLANS", DataType::Uint}}, + {NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL, {"MAX_SCAN_PLAN_INTERVAL", DataType::Uint}}, + {NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS, {"MAX_SCAN_PLAN_ITERATIONS", DataType::Uint}}, + {NL80211_ATTR_SCHED_SCAN_PLANS, {"SCHED_SCAN_PLANS"}}, + + {NL80211_ATTR_PBSS, {"PBSS"}}, + + {NL80211_ATTR_BSS_SELECT, {"BSS_SELECT"}}, + + {NL80211_ATTR_STA_SUPPORT_P2P_PS, {"STA_SUPPORT_P2P_PS"}}, + + {NL80211_ATTR_PAD, {"PAD"}}, + + {NL80211_ATTR_IFTYPE_EXT_CAPA, {"IFTYPE_EXT_CAPA"}}, + + {NL80211_ATTR_MU_MIMO_GROUP_DATA, {"MU_MIMO_GROUP_DATA"}}, + {NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR, {"MU_MIMO_FOLLOW_MAC_ADDR"}}, + + {NL80211_ATTR_SCAN_START_TIME_TSF, {"SCAN_START_TIME_TSF"}}, + {NL80211_ATTR_SCAN_START_TIME_TSF_BSSID, {"SCAN_START_TIME_TSF_BSSID"}}, + {NL80211_ATTR_MEASUREMENT_DURATION, {"MEASUREMENT_DURATION"}}, + {NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY, {"MEASUREMENT_DURATION_MANDATORY"}}, + + {NL80211_ATTR_MESH_PEER_AID, {"MESH_PEER_AID"}}, + + {NL80211_ATTR_NAN_MASTER_PREF, {"NAN_MASTER_PREF"}}, + {NL80211_ATTR_BANDS, {"BANDS"}}, + {NL80211_ATTR_NAN_FUNC, {"NAN_FUNC"}}, + {NL80211_ATTR_NAN_MATCH, {"NAN_MATCH"}}, + + {NL80211_ATTR_FILS_KEK, {"FILS_KEK"}}, + {NL80211_ATTR_FILS_NONCES, {"FILS_NONCES"}}, + + {NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED, {"MULTICAST_TO_UNICAST_ENABLED"}}, + + {NL80211_ATTR_BSSID, {"BSSID"}}, + + {NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI, {"SCHED_SCAN_RELATIVE_RSSI"}}, + {NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST, {"SCHED_SCAN_RSSI_ADJUST"}}, + + {NL80211_ATTR_TIMEOUT_REASON, {"TIMEOUT_REASON"}}, + + {NL80211_ATTR_FILS_ERP_USERNAME, {"FILS_ERP_USERNAME"}}, + {NL80211_ATTR_FILS_ERP_REALM, {"FILS_ERP_REALM"}}, + {NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM, {"FILS_ERP_NEXT_SEQ_NUM"}}, + {NL80211_ATTR_FILS_ERP_RRK, {"FILS_ERP_RRK"}}, + {NL80211_ATTR_FILS_CACHE_ID, {"FILS_CACHE_ID"}}, + + {NL80211_ATTR_PMK, {"PMK"}}, + + {NL80211_ATTR_SCHED_SCAN_MULTI, {"SCHED_SCAN_MULTI"}}, + {NL80211_ATTR_SCHED_SCAN_MAX_REQS, {"SCHED_SCAN_MAX_REQS"}}, + + {NL80211_ATTR_WANT_1X_4WAY_HS, {"WANT_1X_4WAY_HS"}}, + {NL80211_ATTR_PMKR0_NAME, {"PMKR0_NAME"}}, + {NL80211_ATTR_PORT_AUTHORIZED, {"PORT_AUTHORIZED"}}, + + {NL80211_ATTR_EXTERNAL_AUTH_ACTION, {"EXTERNAL_AUTH_ACTION"}}, + {NL80211_ATTR_EXTERNAL_AUTH_SUPPORT, {"EXTERNAL_AUTH_SUPPORT"}}, + + {NL80211_ATTR_NSS, {"NSS"}}, + {NL80211_ATTR_ACK_SIGNAL, {"ACK_SIGNAL"}}, + + {NL80211_ATTR_CONTROL_PORT_OVER_NL80211, {"CONTROL_PORT_OVER_NL80211"}}, + + {NL80211_ATTR_TXQ_STATS, {"TXQ_STATS"}}, + {NL80211_ATTR_TXQ_LIMIT, {"TXQ_LIMIT"}}, + {NL80211_ATTR_TXQ_MEMORY_LIMIT, {"TXQ_MEMORY_LIMIT"}}, + {NL80211_ATTR_TXQ_QUANTUM, {"TXQ_QUANTUM"}}, + + {NL80211_ATTR_HE_CAPABILITY, {"HE_CAPABILITY"}}, + + {NL80211_ATTR_FTM_RESPONDER, {"FTM_RESPONDER"}}, + + {NL80211_ATTR_FTM_RESPONDER_STATS, {"FTM_RESPONDER_STATS"}}, + + {NL80211_ATTR_TIMEOUT, {"TIMEOUT"}}, + + {NL80211_ATTR_PEER_MEASUREMENTS, {"PEER_MEASUREMENTS"}}, + + {NL80211_ATTR_AIRTIME_WEIGHT, {"AIRTIME_WEIGHT"}}, + {NL80211_ATTR_STA_TX_POWER_SETTING, {"STA_TX_POWER_SETTING"}}, + {NL80211_ATTR_STA_TX_POWER, {"STA_TX_POWER"}}, + + {NL80211_ATTR_SAE_PASSWORD, {"SAE_PASSWORD"}}, + + {NL80211_ATTR_TWT_RESPONDER, {"TWT_RESPONDER"}}, + + {NL80211_ATTR_HE_OBSS_PD, {"HE_OBSS_PD"}}, + + {NL80211_ATTR_WIPHY_EDMG_CHANNELS, {"WIPHY_EDMG_CHANNELS"}}, + {NL80211_ATTR_WIPHY_EDMG_BW_CONFIG, {"WIPHY_EDMG_BW_CONFIG"}}, + + {NL80211_ATTR_VLAN_ID, {"VLAN_ID"}}, + + {NL80211_ATTR_HE_BSS_COLOR, {"HE_BSS_COLOR"}}, + + {NL80211_ATTR_IFTYPE_AKM_SUITES, {"IFTYPE_AKM_SUITES"}}, + + {NL80211_ATTR_TID_CONFIG, {"TID_CONFIG"}}, + + {NL80211_ATTR_CONTROL_PORT_NO_PREAUTH, {"CONTROL_PORT_NO_PREAUTH"}}, + + {NL80211_ATTR_PMK_LIFETIME, {"PMK_LIFETIME"}}, + {NL80211_ATTR_PMK_REAUTH_THRESHOLD, {"PMK_REAUTH_THRESHOLD"}}, + + {NL80211_ATTR_RECEIVE_MULTICAST, {"RECEIVE_MULTICAST"}}, + {NL80211_ATTR_WIPHY_FREQ_OFFSET, {"WIPHY_FREQ_OFFSET"}}, + {NL80211_ATTR_CENTER_FREQ1_OFFSET, {"CENTER_FREQ1_OFFSET"}}, + {NL80211_ATTR_SCAN_FREQ_KHZ, {"SCAN_FREQ_KHZ"}}, + + {NL80211_ATTR_HE_6GHZ_CAPABILITY, {"HE_6GHZ_CAPABILITY"}}, + + {NL80211_ATTR_FILS_DISCOVERY, {"FILS_DISCOVERY"}}, + + {NL80211_ATTR_UNSOL_BCAST_PROBE_RESP, {"UNSOL_BCAST_PROBE_RESP"}}, + + {NL80211_ATTR_S1G_CAPABILITY, {"S1G_CAPABILITY"}}, + {NL80211_ATTR_S1G_CAPABILITY_MASK, {"S1G_CAPABILITY_MASK"}}, +}) {} +// clang-format on + +static void informationElementsToStream(std::stringstream& ss, const Buffer attr) { + struct IEHeader { + uint8_t elementId; + uint8_t length; + } __attribute__((packed)); + static_assert(sizeof(IEHeader) == 2); + + const auto alldata = attr.data(); + const auto bytes = alldata.getRaw(); + + ss << '{'; + + if constexpr (kCompactIE) { + ss << "len=" << bytes.len() << ", "; + ss << "crc=" << std::hex << std::setw(4) << crc16(alldata) << std::dec << ", "; + } + + bool first = true; + auto printComma = [&first, &ss]() { + // put separator at every but first entry + if (!first) ss << ", "; + first = false; + }; + + for (size_t offset = 0; offset < bytes.len();) { + const auto ptr = bytes.ptr() + offset; + const auto remainingLen = bytes.len() - offset; + + // can we fit one more header? + if (sizeof(IEHeader) > remainingLen) break; + IEHeader ieHeader; + memcpy(&ieHeader, ptr, sizeof(IEHeader)); + if (sizeof(IEHeader) + ieHeader.length > remainingLen) { + printComma(); + ss << "ERR"; + break; + } + offset += sizeof(IEHeader) + ieHeader.length; + + const Buffer data(ptr + sizeof(IEHeader), ieHeader.length); + + if (ieHeader.elementId == WLAN_EID_SSID) { + printComma(); + + const auto str = data.getRaw(); + const std::string ssid(reinterpret_cast(str.ptr()), str.len()); + ss << "SSID=\"" << printableOnly(ssid) << '"'; + + continue; + } + + if constexpr (kCompactIE) continue; + + // print entry ID:LENGTH/CRC16 + printComma(); + ss << (int)ieHeader.elementId << ':' << (int)ieHeader.length << '/'; + ss << std::hex << std::setw(4) << crc16(data) << std::dec; + } + ss << '}'; +} + +static void nl80211_pattern_supportToStream(std::stringstream& ss, const Buffer attr) { + const auto& [ok, data] = attr.data().getFirst(); + if (!ok) { + ss << "invalid structure"; + return; + } + ss << '{' // + << data.max_patterns << ',' // + << data.min_pattern_len << ',' // + << data.max_pattern_len << ',' // + << data.max_pkt_offset << '}'; +} + +} // namespace android::nl::protocols::generic::families diff --git a/automotive/can/1.0/default/libnl++/protocols/generic/families/Nl80211.h b/automotive/can/1.0/default/libnl++/protocols/generic/families/Nl80211.h new file mode 100644 index 0000000000000000000000000000000000000000..8a9608cde696a70d04af9bdcd11fd1aae071b550 --- /dev/null +++ b/automotive/can/1.0/default/libnl++/protocols/generic/families/Nl80211.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "../GenericMessageBase.h" + +namespace android::nl::protocols::generic::families { + +class Nl80211 : public GenericMessageBase { + public: + Nl80211(nlmsgtype_t familyId); +}; + +} // namespace android::nl::protocols::generic::families diff --git a/automotive/can/1.0/default/libnl++/protocols/route/Link.cpp b/automotive/can/1.0/default/libnl++/protocols/route/Link.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9cc05da027fd28ab765c42e5010f574250ba20a6 --- /dev/null +++ b/automotive/can/1.0/default/libnl++/protocols/route/Link.cpp @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Link.h" + +#include "../structs.h" +#include "structs.h" + +#include + +namespace android::nl::protocols::route { + +using DataType = AttributeDefinition::DataType; + +// clang-format off +Link::Link() : MessageDefinition("link", { + {RTM_NEWLINK, {"NEWLINK", MessageGenre::New}}, + {RTM_DELLINK, {"DELLINK", MessageGenre::Delete}}, + {RTM_GETLINK, {"GETLINK", MessageGenre::Get}}, +}, { + {IFLA_ADDRESS, {"ADDRESS"}}, + {IFLA_BROADCAST, {"BROADCAST"}}, + {IFLA_IFNAME, {"IFNAME", DataType::String}}, + {IFLA_MTU, {"MTU", DataType::Uint}}, + {IFLA_LINK, {"LINK", DataType::Uint}}, + {IFLA_QDISC, {"QDISC", DataType::String}}, + {IFLA_STATS, {"STATS", DataType::Struct, statsToStream}}, + {IFLA_COST, {"COST"}}, + {IFLA_PRIORITY, {"PRIORITY"}}, + {IFLA_MASTER, {"MASTER", DataType::Uint}}, + {IFLA_WIRELESS, {"WIRELESS"}}, + {IFLA_PROTINFO, {"PROTINFO"}}, + {IFLA_TXQLEN, {"TXQLEN", DataType::Uint}}, + {IFLA_MAP, {"MAP", DataType::Struct, mapToStream}}, + {IFLA_WEIGHT, {"WEIGHT", DataType::Uint}}, + {IFLA_OPERSTATE, {"OPERSTATE", DataType::Uint}}, + {IFLA_LINKMODE, {"LINKMODE", DataType::Uint}}, + {IFLA_LINKINFO, {"LINKINFO", DataType::Nested, AttributeMap{ + {IFLA_INFO_KIND, {"INFO_KIND", DataType::String}}, + {IFLA_INFO_DATA, {"INFO_DATA", DataType::Nested}}, + {IFLA_INFO_XSTATS, {"INFO_XSTATS"}}, + {IFLA_INFO_SLAVE_KIND, {"INFO_SLAVE_KIND", DataType::String}}, + {IFLA_INFO_SLAVE_DATA, {"INFO_SLAVE_DATA"}}, + }}}, + {IFLA_NET_NS_PID, {"NET_NS_PID", DataType::Uint}}, + {IFLA_IFALIAS, {"IFALIAS", DataType::String}}, + {IFLA_NUM_VF, {"NUM_VF", DataType::Uint}}, + {IFLA_VFINFO_LIST, {"VFINFO_LIST"}}, + {IFLA_STATS64, {"STATS64", DataType::Struct, statsToStream}}, + {IFLA_VF_PORTS, {"VF_PORTS"}}, + {IFLA_PORT_SELF, {"PORT_SELF"}}, + {IFLA_AF_SPEC, {"AF_SPEC", DataType::Nested, AttributeMap{ + {AF_INET, {"AF_INET", DataType::Nested, AttributeMap{ + {IFLA_INET_CONF, {"INET_CONF", DataType::Struct, arrayToStream}}, + }}}, + {AF_INET6, {"AF_INET6", DataType::Nested, AttributeMap{ + {IFLA_INET6_FLAGS, {"INET6_FLAGS", DataType::Uint}}, + {IFLA_INET6_CONF, {"INET6_CONF", DataType::Struct, arrayToStream}}, + {IFLA_INET6_STATS, {"INET6_STATS", DataType::Struct, arrayToStream}}, + {IFLA_INET6_MCAST, {"INET6_MCAST"}}, + {IFLA_INET6_CACHEINFO, {"INET6_CACHEINFO", DataType::Struct, ifla_cacheinfoToStream}}, + {IFLA_INET6_ICMP6STATS, {"INET6_ICMP6STATS", DataType::Struct, arrayToStream}}, + {IFLA_INET6_TOKEN, {"INET6_TOKEN"}}, + {IFLA_INET6_ADDR_GEN_MODE, {"INET6_ADDR_GEN_MODE", DataType::Uint}}, + }}}, + }}}, + {IFLA_GROUP, {"GROUP", DataType::Uint}}, + {IFLA_NET_NS_FD, {"NET_NS_FD", DataType::Uint}}, + {IFLA_EXT_MASK, {"EXT_MASK", DataType::Uint}}, + {IFLA_PROMISCUITY, {"PROMISCUITY", DataType::Uint}}, + {IFLA_NUM_TX_QUEUES, {"NUM_TX_QUEUES", DataType::Uint}}, + {IFLA_NUM_RX_QUEUES, {"NUM_RX_QUEUES", DataType::Uint}}, + {IFLA_CARRIER, {"CARRIER", DataType::Uint}}, + {IFLA_PHYS_PORT_ID, {"PHYS_PORT_ID"}}, + {IFLA_CARRIER_CHANGES, {"CARRIER_CHANGES", DataType::Uint}}, + {IFLA_PHYS_SWITCH_ID, {"PHYS_SWITCH_ID"}}, + {IFLA_LINK_NETNSID, {"LINK_NETNSID"}}, // NLA_S32 + {IFLA_PHYS_PORT_NAME, {"PHYS_PORT_NAME", DataType::String}}, + {IFLA_PROTO_DOWN, {"PROTO_DOWN", DataType::Uint}}, + {IFLA_GSO_MAX_SEGS, {"GSO_MAX_SEGS", DataType::Uint}}, + {IFLA_GSO_MAX_SIZE, {"GSO_MAX_SIZE", DataType::Uint}}, + {IFLA_PAD, {"PAD"}}, + {IFLA_XDP, {"XDP"}}, + {IFLA_EVENT, {"EVENT", DataType::Uint}}, + {IFLA_NEW_NETNSID, {"NEW_NETNSID"}}, // NLA_S32 + {IFLA_TARGET_NETNSID, {"TARGET_NETNSID"}}, // NLA_S32 + {IFLA_CARRIER_UP_COUNT, {"CARRIER_UP_COUNT", DataType::Uint}}, + {IFLA_CARRIER_DOWN_COUNT, {"CARRIER_DOWN_COUNT", DataType::Uint}}, + {IFLA_NEW_IFINDEX, {"NEW_IFINDEX"}}, // NLA_S32 + {IFLA_MIN_MTU, {"MIN_MTU", DataType::Uint}}, + {IFLA_MAX_MTU, {"MAX_MTU", DataType::Uint}}, + {IFLA_PROP_LIST, {"PROP_LIST"}}, + {IFLA_ALT_IFNAME, {"ALT_IFNAME", DataType::String}}, + {IFLA_PERM_ADDRESS, {"PERM_ADDRESS"}}, +}) {} +// clang-format off + +void Link::toStream(std::stringstream& ss, const ifinfomsg& data) const { + ss << "ifinfomsg{" + << "family=" << unsigned(data.ifi_family) << ", type=" << data.ifi_type + << ", index=" << data.ifi_index << ", flags=" << data.ifi_flags + << ", change=" << data.ifi_change << "}"; +} + +} // namespace android::nl::protocols::route diff --git a/automotive/can/1.0/default/libnl++/protocols/route/Link.h b/automotive/can/1.0/default/libnl++/protocols/route/Link.h new file mode 100644 index 0000000000000000000000000000000000000000..ecfefc928b411f28c17c6f725e31ef5c0308dffd --- /dev/null +++ b/automotive/can/1.0/default/libnl++/protocols/route/Link.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "../MessageDefinition.h" + +#include + +namespace android::nl::protocols::route { + +class Link : public MessageDefinition { + public: + Link(); + void toStream(std::stringstream& ss, const ifinfomsg& data) const override; +}; + +} // namespace android::nl::protocols::route diff --git a/automotive/can/1.0/default/libnl++/protocols/route/Route.cpp b/automotive/can/1.0/default/libnl++/protocols/route/Route.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c134911525faaa846750d3b01601ec7fa90d977b --- /dev/null +++ b/automotive/can/1.0/default/libnl++/protocols/route/Route.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Route.h" + +#include "Link.h" + +namespace android::nl::protocols::route { + +Route::Route() : NetlinkProtocol(NETLINK_ROUTE, "ROUTE", {std::make_shared()}) {} + +} // namespace android::nl::protocols::route diff --git a/automotive/can/1.0/default/libnl++/protocols/route/Route.h b/automotive/can/1.0/default/libnl++/protocols/route/Route.h new file mode 100644 index 0000000000000000000000000000000000000000..433e610101601e93ad441f317725a552a87dc213 --- /dev/null +++ b/automotive/can/1.0/default/libnl++/protocols/route/Route.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "../NetlinkProtocol.h" + +namespace android::nl::protocols::route { + +/** + * Definition of NETLINK_ROUTE protocol. + */ +class Route : public NetlinkProtocol { + public: + Route(); +}; + +} // namespace android::nl::protocols::route diff --git a/automotive/can/1.0/default/libnl++/protocols/route/structs.cpp b/automotive/can/1.0/default/libnl++/protocols/route/structs.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b62cec3c7ebd93831c3a3cd83c159fc19d80a4cb --- /dev/null +++ b/automotive/can/1.0/default/libnl++/protocols/route/structs.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "structs.h" + +namespace android::nl::protocols::route { + +void mapToStream(std::stringstream& ss, const Buffer attr) { + const auto& [ok, data] = attr.data().getFirst(); + if (!ok) { + ss << "invalid structure"; + return; + } + ss << '{' // + << data.mem_start << ',' // + << data.mem_end << ',' // + << data.base_addr << ',' // + << data.irq << ',' // + << unsigned(data.dma) << ',' // + << unsigned(data.port) << '}'; +} + +void ifla_cacheinfoToStream(std::stringstream& ss, const Buffer attr) { + const auto& [ok, data] = attr.data().getFirst(); + if (!ok) { + ss << "invalid structure"; + return; + } + ss << '{' // + << data.max_reasm_len << ',' // + << data.tstamp << ',' // + << data.reachable_time << ',' // + << data.retrans_time << '}'; +} + +} // namespace android::nl::protocols::route diff --git a/automotive/can/1.0/default/libnl++/protocols/route/structs.h b/automotive/can/1.0/default/libnl++/protocols/route/structs.h new file mode 100644 index 0000000000000000000000000000000000000000..fea2ce130c4acf991c74565a7ee1297c9f20da31 --- /dev/null +++ b/automotive/can/1.0/default/libnl++/protocols/route/structs.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include + +#include + +namespace android::nl::protocols::route { + +// rtnl_link_ifmap +void mapToStream(std::stringstream& ss, const Buffer attr); + +// ifla_cacheinfo +void ifla_cacheinfoToStream(std::stringstream& ss, const Buffer attr); + +// rtnl_link_stats or rtnl_link_stats64 +template +void statsToStream(std::stringstream& ss, const Buffer attr) { + const auto& [ok, data] = attr.data().getFirst(); + if (!ok) { + ss << "invalid structure"; + return; + } + ss << '{' // + << data.rx_packets << ',' // + << data.tx_packets << ',' // + << data.rx_bytes << ',' // + << data.tx_bytes << ',' // + << data.rx_errors << ',' // + << data.tx_errors << ',' // + << data.rx_dropped << ',' // + << data.tx_dropped << ',' // + << data.multicast << ',' // + << data.collisions << ',' // + << data.rx_length_errors << ',' // + << data.rx_over_errors << ',' // + << data.rx_crc_errors << ',' // + << data.rx_frame_errors << ',' // + << data.rx_fifo_errors << ',' // + << data.rx_missed_errors << ',' // + << data.tx_aborted_errors << ',' // + << data.tx_carrier_errors << ',' // + << data.tx_fifo_errors << ',' // + << data.tx_heartbeat_errors << ',' // + << data.tx_window_errors << ',' // + << data.rx_compressed << ',' // + << data.tx_compressed << ',' // + << data.rx_nohandler << '}'; +} + +} // namespace android::nl::protocols::route diff --git a/automotive/can/1.0/default/libnl++/protocols/structs.h b/automotive/can/1.0/default/libnl++/protocols/structs.h new file mode 100644 index 0000000000000000000000000000000000000000..44c17b84b9e18b4d79b3c2b9b6ca35b8c8c6bcfa --- /dev/null +++ b/automotive/can/1.0/default/libnl++/protocols/structs.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +namespace android::nl::protocols { + +template +void arrayToStream(std::stringstream& ss, const Buffer attr) { + ss << '{'; + for (const auto it : attr.data().getRaw()) { + ss << it << ','; + } + ss.seekp(-1, std::ios_base::cur); + ss << '}'; +} + +} // namespace android::nl::protocols diff --git a/automotive/can/1.0/default/service.cpp b/automotive/can/1.0/default/service.cpp index b52a54a5b7cc0311f8b4807dd656f1ec0e33763d..9a9d3226f0f331954948c410f95fba5d3ae6aba4 100644 --- a/automotive/can/1.0/default/service.cpp +++ b/automotive/can/1.0/default/service.cpp @@ -18,6 +18,7 @@ #include #include +#include namespace android::hardware::automotive::can::V1_0::implementation { @@ -27,6 +28,8 @@ static void canControllerService() { configureRpcThreadpool(16, true); LOG(DEBUG) << "CAN controller service starting..."; + netdevice::useSocketDomain(AF_CAN); + sp canController(new CanController); if (canController->registerAsService("socketcan") != OK) { LOG(FATAL) << "Failed to register CAN controller"; diff --git a/automotive/can/1.0/vts/functional/VtsHalCanBusV1_0TargetTest.cpp b/automotive/can/1.0/vts/functional/VtsHalCanBusV1_0TargetTest.cpp index a8e7c0b633fca02eccebe02a754701aae13b3045..d91d9f50359e1ae7a1ef3665528498c8760da255 100644 --- a/automotive/can/1.0/vts/functional/VtsHalCanBusV1_0TargetTest.cpp +++ b/automotive/can/1.0/vts/functional/VtsHalCanBusV1_0TargetTest.cpp @@ -176,8 +176,9 @@ TEST_P(CanBusHalTest, DontCloseErrorListener) { * adb shell /data/nativetest64/VtsHalCanBusV1_0TargetTest/VtsHalCanBusV1_0TargetTest\ * --gtest_filter=*_ */ -INSTANTIATE_TEST_SUITE_P( // - PerInstance, CanBusHalTest, testing::ValuesIn(getAllHalInstanceNames(ICanBus::descriptor)), - PrintInstanceNameToString); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CanBusHalTest); +INSTANTIATE_TEST_SUITE_P(PerInstance, CanBusHalTest, + testing::ValuesIn(getAllHalInstanceNames(ICanBus::descriptor)), + PrintInstanceNameToString); } // namespace android::hardware::automotive::can::V1_0::vts diff --git a/automotive/can/1.0/vts/functional/VtsHalCanBusVirtualV1_0TargetTest.cpp b/automotive/can/1.0/vts/functional/VtsHalCanBusVirtualV1_0TargetTest.cpp index 903943545808fd90750404b9ed5c85eb7bdc77e9..fc77579058573dbe03edf99dcfc8977d766153ba 100644 --- a/automotive/can/1.0/vts/functional/VtsHalCanBusVirtualV1_0TargetTest.cpp +++ b/automotive/can/1.0/vts/functional/VtsHalCanBusVirtualV1_0TargetTest.cpp @@ -86,7 +86,7 @@ struct Bus { EXPECT_EQ(ICanController::Result::OK, result); /* Not using ICanBus::getService here, since it ignores interfaces not in the manifest - * file -- this is a test, so we don't want to add dummy services to a device manifest. */ + * file -- this is a test, so we don't want to add fake services to a device manifest. */ auto manager = hidl::manager::V1_2::IServiceManager::getService(); auto service = manager->get(ICanBus::descriptor, config.name); mBus = ICanBus::castFrom(service); @@ -868,9 +868,9 @@ TEST_P(CanBusVirtualHalTest, FilterMixed) { * Example manual invocation: * adb shell /data/nativetest64/VtsHalCanBusVirtualV1_0TargetTest/VtsHalCanBusVirtualV1_0TargetTest */ -INSTANTIATE_TEST_SUITE_P( // - PerInstance, CanBusVirtualHalTest, - testing::ValuesIn(getAllHalInstanceNames(ICanController::descriptor)), - PrintInstanceNameToString); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CanBusVirtualHalTest); +INSTANTIATE_TEST_SUITE_P(PerInstance, CanBusVirtualHalTest, + testing::ValuesIn(getAllHalInstanceNames(ICanController::descriptor)), + PrintInstanceNameToString); } // namespace android::hardware::automotive::can::V1_0::vts diff --git a/automotive/can/1.0/vts/functional/VtsHalCanControllerV1_0TargetTest.cpp b/automotive/can/1.0/vts/functional/VtsHalCanControllerV1_0TargetTest.cpp index 8ef57589cd8b3868f6985bc6607fe0f33f3a15ab..294cd177584e054eec2d055a873380eb9ec01569 100644 --- a/automotive/can/1.0/vts/functional/VtsHalCanControllerV1_0TargetTest.cpp +++ b/automotive/can/1.0/vts/functional/VtsHalCanControllerV1_0TargetTest.cpp @@ -119,7 +119,7 @@ bool CanControllerHalTest::up(InterfaceType iftype, std::string srvname, std::st void CanControllerHalTest::assertRegistered(std::string srvname, bool expectRegistered) { /* Not using ICanBus::tryGetService here, since it ignores interfaces not in the manifest - * file -- this is a test, so we don't want to add dummy services to a device manifest. */ + * file -- this is a test, so we don't want to add fake services to a device manifest. */ auto manager = hidl::manager::V1_2::IServiceManager::getService(); auto busService = manager->get(ICanBus::descriptor, srvname); ASSERT_EQ(expectRegistered, busService.withDefault(nullptr) != nullptr) @@ -145,7 +145,7 @@ TEST_P(CanControllerHalTest, BringUpDown) { assertRegistered(name, false); } -TEST_P(CanControllerHalTest, DownDummy) { +TEST_P(CanControllerHalTest, DownFake) { const auto result = mCanController->downInterface("imnotup"); ASSERT_FALSE(result); } @@ -293,9 +293,9 @@ TEST_P(CanControllerHalTest, FailBadSlcanAddress) { * Example manual invocation: * adb shell /data/nativetest64/VtsHalCanControllerV1_0TargetTest/VtsHalCanControllerV1_0TargetTest */ -INSTANTIATE_TEST_SUITE_P( // - PerInstance, CanControllerHalTest, - testing::ValuesIn(getAllHalInstanceNames(ICanController::descriptor)), - PrintInstanceNameToString); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CanControllerHalTest); +INSTANTIATE_TEST_SUITE_P(PerInstance, CanControllerHalTest, + testing::ValuesIn(getAllHalInstanceNames(ICanController::descriptor)), + PrintInstanceNameToString); } // namespace android::hardware::automotive::can::V1_0::vts diff --git a/automotive/evs/1.0/default/EvsCamera.cpp b/automotive/evs/1.0/default/EvsCamera.cpp index e0782ec77995d4552336ad2641bbf2240123d012..0daea5a2951854d7764a64add1db1ed732488327 100644 --- a/automotive/evs/1.0/default/EvsCamera.cpp +++ b/automotive/evs/1.0/default/EvsCamera.cpp @@ -49,7 +49,7 @@ EvsCamera::EvsCamera(const char *id) : mDescription.cameraId = id; - // Set up dummy data for testing + // Set up mock data for testing if (mDescription.cameraId == kCameraName_Backup) { mWidth = 640; // full NTSC/VGA mHeight = 480; // full NTSC/VGA diff --git a/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp b/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp index 7fe7a3399b562c25fdc68afd57cc2c7b00f6a8e8..ad607d808753a91855577b36c847041f932781ea 100644 --- a/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp +++ b/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp @@ -369,7 +369,7 @@ TEST_P(EvsHidlTest, CameraStreamPerformance) { TEST_P(EvsHidlTest, CameraStreamBuffering) { ALOGI("Starting CameraStreamBuffering test"); - // Arbitrary constant (should be > 1 and less than crazy) + // Arbitrary constant (should be > 1 and not too big) static const unsigned int kBuffersToHold = 6; // Get the camera list @@ -381,7 +381,7 @@ TEST_P(EvsHidlTest, CameraStreamBuffering) { sp pCam = pEnumerator->openCamera(cam.cameraId); ASSERT_NE(pCam, nullptr); - // Ask for a crazy number of buffers in flight to ensure it errors correctly + // Ask for a very large number of buffers in flight to ensure it errors correctly Return badResult = pCam->setMaxFramesInFlight(0xFFFFFFFF); EXPECT_EQ(EvsResult::BUFFER_NOT_AVAILABLE, badResult); diff --git a/automotive/evs/1.1/default/ConfigManager.h b/automotive/evs/1.1/default/ConfigManager.h index 870af1caa95d0d441a3a93075282b725008b27b1..b0b2670fb6a30cc84aee50d7f6a27dfa9a2ed8c7 100644 --- a/automotive/evs/1.1/default/ConfigManager.h +++ b/automotive/evs/1.1/default/ConfigManager.h @@ -76,7 +76,7 @@ public: } /* - * List of supported controls that the master client can program. + * List of supported controls that the primary client can program. * Paraemters are stored with its valid range */ unordered_map windowService) { // Add ultrasonics array desc. sUltrasonicsArrayRecordList.emplace_back( - EvsUltrasonicsArray::GetDummyArrayDesc("front_array")); + EvsUltrasonicsArray::GetMockArrayDesc("front_array")); } diff --git a/automotive/evs/1.1/default/EvsUltrasonicsArray.cpp b/automotive/evs/1.1/default/EvsUltrasonicsArray.cpp index bc69aa41568fdb4a08df2763002ffe93f27a7f2d..ebd47c618bb78bd33b005f380b63c0a063ae533f 100644 --- a/automotive/evs/1.1/default/EvsUltrasonicsArray.cpp +++ b/automotive/evs/1.1/default/EvsUltrasonicsArray.cpp @@ -45,7 +45,7 @@ const int kTargetFrameRate = 10; namespace { -void fillDummyArrayDesc(UltrasonicsArrayDesc& arrayDesc) { +void fillMockArrayDesc(UltrasonicsArrayDesc& arrayDesc) { arrayDesc.maxReadingsPerSensorCount = kMaxReadingsPerSensor; arrayDesc.maxReceiversCount = kMaxReceiversCount; @@ -99,8 +99,8 @@ void SerializeWaveformData(const std::vector& waveformDataList, ui } } -// Fills dataFrameDesc with dummy data. -bool fillDummyDataFrame(UltrasonicsDataFrameDesc& dataFrameDesc, sp pIMemory) { +// Fills dataFrameDesc with mock data. +bool fillMockDataFrame(UltrasonicsDataFrameDesc& dataFrameDesc, sp pIMemory) { dataFrameDesc.timestampNs = elapsedRealtimeNano(); const std::vector transmittersIdList = {0}; @@ -137,9 +137,9 @@ EvsUltrasonicsArray::EvsUltrasonicsArray(const char* deviceName) : mFramesAllowed(0), mFramesInUse(0), mStreamState(STOPPED) { LOG(DEBUG) << "EvsUltrasonicsArray instantiated"; - // Set up dummy data for description. + // Set up mock data for description. mArrayDesc.ultrasonicsArrayId = deviceName; - fillDummyArrayDesc(mArrayDesc); + fillMockArrayDesc(mArrayDesc); // Assign allocator. mShmemAllocator = IAllocator::getService("ashmem"); @@ -182,10 +182,10 @@ void EvsUltrasonicsArray::forceShutdown() { mStreamState = DEAD; } -UltrasonicsArrayDesc EvsUltrasonicsArray::GetDummyArrayDesc(const char* deviceName) { +UltrasonicsArrayDesc EvsUltrasonicsArray::GetMockArrayDesc(const char* deviceName) { UltrasonicsArrayDesc ultrasonicsArrayDesc; ultrasonicsArrayDesc.ultrasonicsArrayId = deviceName; - fillDummyArrayDesc(ultrasonicsArrayDesc); + fillMockArrayDesc(ultrasonicsArrayDesc); return ultrasonicsArrayDesc; } @@ -497,17 +497,17 @@ void EvsUltrasonicsArray::generateDataFrames() { if (timeForFrame) { // Assemble the buffer description we'll transmit below - UltrasonicsDataFrameDesc dummyDataFrameDesc; - dummyDataFrameDesc.dataFrameId = idx; - dummyDataFrameDesc.waveformsData = mDataFrames[idx].sharedMemory.hidlMemory; + UltrasonicsDataFrameDesc mockDataFrameDesc; + mockDataFrameDesc.dataFrameId = idx; + mockDataFrameDesc.waveformsData = mDataFrames[idx].sharedMemory.hidlMemory; - // Fill dummy waveform data. - fillDummyDataFrame(dummyDataFrameDesc, mDataFrames[idx].sharedMemory.pIMemory); + // Fill mock waveform data. + fillMockDataFrame(mockDataFrameDesc, mDataFrames[idx].sharedMemory.pIMemory); // Issue the (asynchronous) callback to the client -- can't be holding the lock - auto result = mStream->deliverDataFrame(dummyDataFrameDesc); + auto result = mStream->deliverDataFrame(mockDataFrameDesc); if (result.isOk()) { - LOG(DEBUG) << "Delivered data frame id: " << dummyDataFrameDesc.dataFrameId; + LOG(DEBUG) << "Delivered data frame id: " << mockDataFrameDesc.dataFrameId; } else { // This can happen if the client dies and is likely unrecoverable. // To avoid consuming resources generating failing calls, we stop sending diff --git a/automotive/evs/1.1/default/EvsUltrasonicsArray.h b/automotive/evs/1.1/default/EvsUltrasonicsArray.h index 7a4101290e1c507f4124644602acb0cf0a32437c..88aa6003f66a6aa3616da47e8fa96fb10ada9706 100644 --- a/automotive/evs/1.1/default/EvsUltrasonicsArray.h +++ b/automotive/evs/1.1/default/EvsUltrasonicsArray.h @@ -58,7 +58,7 @@ class EvsUltrasonicsArray : public IEvsUltrasonicsArray { static sp Create(const char* deviceName); // Returns a ultrasonics array descriptor filled with sample data. - static UltrasonicsArrayDesc GetDummyArrayDesc(const char* id); + static UltrasonicsArrayDesc GetMockArrayDesc(const char* id); DISALLOW_COPY_AND_ASSIGN(EvsUltrasonicsArray); virtual ~EvsUltrasonicsArray() override; diff --git a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp index f1c8f9f6c738cf964da032be1437ec09808ce08d..8cc18822f2c19b752333282ef48805fd864711fb 100644 --- a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp +++ b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp @@ -41,14 +41,14 @@ static const float kNanoToSeconds = 0.000000001f; #include #include +#include #include #include -#include #include +#include #include -#include #include -#include +#include #include #include #include @@ -513,7 +513,7 @@ TEST_P(EvsHidlTest, CameraStreamPerformance) { TEST_P(EvsHidlTest, CameraStreamBuffering) { LOG(INFO) << "Starting CameraStreamBuffering test"; - // Arbitrary constant (should be > 1 and less than crazy) + // Arbitrary constant (should be > 1 and not too big) static const unsigned int kBuffersToHold = 6; // Get the camera list @@ -540,7 +540,7 @@ TEST_P(EvsHidlTest, CameraStreamBuffering) { // Store a camera handle for a clean-up activeCameras.push_back(pCam); - // Ask for a crazy number of buffers in flight to ensure it errors correctly + // Ask for a very large number of buffers in flight to ensure it errors correctly Return badResult = pCam->setMaxFramesInFlight(0xFFFFFFFF); EXPECT_EQ(EvsResult::BUFFER_NOT_AVAILABLE, badResult); @@ -622,7 +622,7 @@ TEST_P(EvsHidlTest, CameraToDisplayRoundTrip) { ASSERT_GT(config.size(), 0); ASSERT_GT(state.size(), 0); - android::DisplayConfig* pConfig = (android::DisplayConfig*)config.data(); + android::ui::DisplayMode* pConfig = (android::ui::DisplayMode*)config.data(); const auto width = pConfig->resolution.getWidth(); const auto height = pConfig->resolution.getHeight(); LOG(INFO) << " Resolution: " << width << "x" << height; @@ -946,12 +946,12 @@ TEST_P(EvsHidlTest, CameraParameter) { /* - * CameraMasterRelease - * Verify that non-master client gets notified when the master client either + * CameraPrimaryClientRelease + * Verify that non-primary client gets notified when the primary client either * terminates or releases a role. */ -TEST_P(EvsHidlTest, CameraMasterRelease) { - LOG(INFO) << "Starting CameraMasterRelease test"; +TEST_P(EvsHidlTest, CameraPrimaryClientRelease) { + LOG(INFO) << "Starting CameraPrimaryClientRelease test"; if (mIsHwModule) { // This test is not for HW module implementation. @@ -977,57 +977,57 @@ TEST_P(EvsHidlTest, CameraMasterRelease) { } // Create two camera clients. - sp pCamMaster = + sp pCamPrimary = IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg)) .withDefault(nullptr); - ASSERT_NE(pCamMaster, nullptr); + ASSERT_NE(pCamPrimary, nullptr); // Store a camera handle for a clean-up - activeCameras.push_back(pCamMaster); + activeCameras.push_back(pCamPrimary); - sp pCamNonMaster = + sp pCamSecondary = IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg)) .withDefault(nullptr); - ASSERT_NE(pCamNonMaster, nullptr); + ASSERT_NE(pCamSecondary, nullptr); // Store a camera handle for a clean-up - activeCameras.push_back(pCamNonMaster); + activeCameras.push_back(pCamSecondary); // Set up per-client frame receiver objects which will fire up its own thread - sp frameHandlerMaster = - new FrameHandler(pCamMaster, cam, + sp frameHandlerPrimary = + new FrameHandler(pCamPrimary, cam, nullptr, FrameHandler::eAutoReturn); - ASSERT_NE(frameHandlerMaster, nullptr); - sp frameHandlerNonMaster = - new FrameHandler(pCamNonMaster, cam, + ASSERT_NE(frameHandlerPrimary, nullptr); + sp frameHandlerSecondary = + new FrameHandler(pCamSecondary, cam, nullptr, FrameHandler::eAutoReturn); - ASSERT_NE(frameHandlerNonMaster, nullptr); + ASSERT_NE(frameHandlerSecondary, nullptr); - // Set one client as the master - EvsResult result = pCamMaster->setMaster(); + // Set one client as the primary client + EvsResult result = pCamPrimary->setMaster(); ASSERT_TRUE(result == EvsResult::OK); - // Try to set another client as the master. - result = pCamNonMaster->setMaster(); + // Try to set another client as the primary client. + result = pCamSecondary->setMaster(); ASSERT_TRUE(result == EvsResult::OWNERSHIP_LOST); - // Start the camera's video stream via a master client. - bool startResult = frameHandlerMaster->startStream(); + // Start the camera's video stream via a primary client client. + bool startResult = frameHandlerPrimary->startStream(); ASSERT_TRUE(startResult); // Ensure the stream starts - frameHandlerMaster->waitForFrameCount(1); + frameHandlerPrimary->waitForFrameCount(1); // Start the camera's video stream via another client - startResult = frameHandlerNonMaster->startStream(); + startResult = frameHandlerSecondary->startStream(); ASSERT_TRUE(startResult); // Ensure the stream starts - frameHandlerNonMaster->waitForFrameCount(1); + frameHandlerSecondary->waitForFrameCount(1); - // Non-master client expects to receive a master role relesed + // Non-primary client expects to receive a primary client role relesed // notification. EvsEventDesc aTargetEvent = {}; EvsEventDesc aNotification = {}; @@ -1036,14 +1036,14 @@ TEST_P(EvsHidlTest, CameraMasterRelease) { std::mutex eventLock; std::condition_variable eventCond; std::thread listener = std::thread( - [&aNotification, &frameHandlerNonMaster, &listening, &eventCond]() { + [&aNotification, &frameHandlerSecondary, &listening, &eventCond]() { // Notify that a listening thread is running. listening = true; eventCond.notify_all(); EvsEventDesc aTargetEvent; aTargetEvent.aType = EvsEventType::MASTER_RELEASED; - if (!frameHandlerNonMaster->waitForEvent(aTargetEvent, aNotification, true)) { + if (!frameHandlerSecondary->waitForEvent(aTargetEvent, aNotification, true)) { LOG(WARNING) << "A timer is expired before a target event is fired."; } @@ -1059,8 +1059,8 @@ TEST_P(EvsHidlTest, CameraMasterRelease) { } lock.unlock(); - // Release a master role. - pCamMaster->unsetMaster(); + // Release a primary client role. + pCamPrimary->unsetMaster(); // Join a listening thread. if (listener.joinable()) { @@ -1071,24 +1071,24 @@ TEST_P(EvsHidlTest, CameraMasterRelease) { ASSERT_EQ(EvsEventType::MASTER_RELEASED, static_cast(aNotification.aType)); - // Non-master becomes a master. - result = pCamNonMaster->setMaster(); + // Non-primary becomes a primary client. + result = pCamSecondary->setMaster(); ASSERT_TRUE(result == EvsResult::OK); - // Previous master client fails to become a master. - result = pCamMaster->setMaster(); + // Previous primary client fails to become a primary client. + result = pCamPrimary->setMaster(); ASSERT_TRUE(result == EvsResult::OWNERSHIP_LOST); listening = false; listener = std::thread( - [&aNotification, &frameHandlerMaster, &listening, &eventCond]() { + [&aNotification, &frameHandlerPrimary, &listening, &eventCond]() { // Notify that a listening thread is running. listening = true; eventCond.notify_all(); EvsEventDesc aTargetEvent; aTargetEvent.aType = EvsEventType::MASTER_RELEASED; - if (!frameHandlerMaster->waitForEvent(aTargetEvent, aNotification, true)) { + if (!frameHandlerPrimary->waitForEvent(aTargetEvent, aNotification, true)) { LOG(WARNING) << "A timer is expired before a target event is fired."; } @@ -1103,8 +1103,8 @@ TEST_P(EvsHidlTest, CameraMasterRelease) { } lock.unlock(); - // Closing current master client. - frameHandlerNonMaster->shutdown(); + // Closing current primary client. + frameHandlerSecondary->shutdown(); // Join a listening thread. if (listener.joinable()) { @@ -1116,11 +1116,11 @@ TEST_P(EvsHidlTest, CameraMasterRelease) { static_cast(aNotification.aType)); // Closing streams. - frameHandlerMaster->shutdown(); + frameHandlerPrimary->shutdown(); // Explicitly release the camera - pEnumerator->closeCamera(pCamMaster); - pEnumerator->closeCamera(pCamNonMaster); + pEnumerator->closeCamera(pCamPrimary); + pEnumerator->closeCamera(pCamSecondary); activeCameras.clear(); } } @@ -1128,7 +1128,7 @@ TEST_P(EvsHidlTest, CameraMasterRelease) { /* * MultiCameraParameter: - * Verify that master and non-master clients behave as expected when they try to adjust + * Verify that primary and non-primary clients behave as expected when they try to adjust * camera parameters. */ TEST_P(EvsHidlTest, MultiCameraParameter) { @@ -1158,88 +1158,88 @@ TEST_P(EvsHidlTest, MultiCameraParameter) { } // Create two camera clients. - sp pCamMaster = + sp pCamPrimary = IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg)) .withDefault(nullptr); - ASSERT_NE(pCamMaster, nullptr); + ASSERT_NE(pCamPrimary, nullptr); // Store a camera handle for a clean-up - activeCameras.push_back(pCamMaster); + activeCameras.push_back(pCamPrimary); - sp pCamNonMaster = + sp pCamSecondary = IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg)) .withDefault(nullptr); - ASSERT_NE(pCamNonMaster, nullptr); + ASSERT_NE(pCamSecondary, nullptr); // Store a camera handle for a clean-up - activeCameras.push_back(pCamNonMaster); + activeCameras.push_back(pCamSecondary); // Get the parameter list - std::vector camMasterCmds, camNonMasterCmds; - pCamMaster->getParameterList([&camMasterCmds](hidl_vec cmdList) { - camMasterCmds.reserve(cmdList.size()); + std::vector camPrimaryCmds, camSecondaryCmds; + pCamPrimary->getParameterList([&camPrimaryCmds](hidl_vec cmdList) { + camPrimaryCmds.reserve(cmdList.size()); for (auto &&cmd : cmdList) { - camMasterCmds.push_back(cmd); + camPrimaryCmds.push_back(cmd); } } ); - pCamNonMaster->getParameterList([&camNonMasterCmds](hidl_vec cmdList) { - camNonMasterCmds.reserve(cmdList.size()); + pCamSecondary->getParameterList([&camSecondaryCmds](hidl_vec cmdList) { + camSecondaryCmds.reserve(cmdList.size()); for (auto &&cmd : cmdList) { - camNonMasterCmds.push_back(cmd); + camSecondaryCmds.push_back(cmd); } } ); - if (camMasterCmds.size() < 1 || - camNonMasterCmds.size() < 1) { + if (camPrimaryCmds.size() < 1 || + camSecondaryCmds.size() < 1) { // Skip a camera device if it does not support any parameter. continue; } // Set up per-client frame receiver objects which will fire up its own thread - sp frameHandlerMaster = - new FrameHandler(pCamMaster, cam, + sp frameHandlerPrimary = + new FrameHandler(pCamPrimary, cam, nullptr, FrameHandler::eAutoReturn); - ASSERT_NE(frameHandlerMaster, nullptr); - sp frameHandlerNonMaster = - new FrameHandler(pCamNonMaster, cam, + ASSERT_NE(frameHandlerPrimary, nullptr); + sp frameHandlerSecondary = + new FrameHandler(pCamSecondary, cam, nullptr, FrameHandler::eAutoReturn); - ASSERT_NE(frameHandlerNonMaster, nullptr); + ASSERT_NE(frameHandlerSecondary, nullptr); - // Set one client as the master - EvsResult result = pCamMaster->setMaster(); + // Set one client as the primary client. + EvsResult result = pCamPrimary->setMaster(); ASSERT_EQ(EvsResult::OK, result); - // Try to set another client as the master. - result = pCamNonMaster->setMaster(); + // Try to set another client as the primary client. + result = pCamSecondary->setMaster(); ASSERT_EQ(EvsResult::OWNERSHIP_LOST, result); - // Start the camera's video stream via a master client. - bool startResult = frameHandlerMaster->startStream(); + // Start the camera's video stream via a primary client client. + bool startResult = frameHandlerPrimary->startStream(); ASSERT_TRUE(startResult); // Ensure the stream starts - frameHandlerMaster->waitForFrameCount(1); + frameHandlerPrimary->waitForFrameCount(1); // Start the camera's video stream via another client - startResult = frameHandlerNonMaster->startStream(); + startResult = frameHandlerSecondary->startStream(); ASSERT_TRUE(startResult); // Ensure the stream starts - frameHandlerNonMaster->waitForFrameCount(1); + frameHandlerSecondary->waitForFrameCount(1); int32_t val0 = 0; std::vector values; EvsEventDesc aNotification0 = {}; EvsEventDesc aNotification1 = {}; - for (auto &cmd : camMasterCmds) { + for (auto &cmd : camPrimaryCmds) { // Get a valid parameter value range int32_t minVal, maxVal, step; - pCamMaster->getIntParameterRange( + pCamPrimary->getIntParameterRange( cmd, [&minVal, &maxVal, &step](int32_t val0, int32_t val1, int32_t val2) { minVal = val0; @@ -1252,7 +1252,7 @@ TEST_P(EvsHidlTest, MultiCameraParameter) { if (cmd == CameraParam::ABSOLUTE_FOCUS) { // Try to turn off auto-focus values.clear(); - pCamMaster->setIntParameter(CameraParam::AUTO_FOCUS, 0, + pCamPrimary->setIntParameter(CameraParam::AUTO_FOCUS, 0, [&result, &values](auto status, auto effectiveValues) { result = status; if (status == EvsResult::OK) { @@ -1277,7 +1277,7 @@ TEST_P(EvsHidlTest, MultiCameraParameter) { std::condition_variable eventCond; std::thread listener0 = std::thread( [cmd, val0, - &aNotification0, &frameHandlerMaster, &listening0, &listening1, &eventCond]() { + &aNotification0, &frameHandlerPrimary, &listening0, &listening1, &eventCond]() { listening0 = true; if (listening1) { eventCond.notify_all(); @@ -1287,14 +1287,14 @@ TEST_P(EvsHidlTest, MultiCameraParameter) { aTargetEvent.aType = EvsEventType::PARAMETER_CHANGED; aTargetEvent.payload[0] = static_cast(cmd); aTargetEvent.payload[1] = val0; - if (!frameHandlerMaster->waitForEvent(aTargetEvent, aNotification0)) { + if (!frameHandlerPrimary->waitForEvent(aTargetEvent, aNotification0)) { LOG(WARNING) << "A timer is expired before a target event is fired."; } } ); std::thread listener1 = std::thread( [cmd, val0, - &aNotification1, &frameHandlerNonMaster, &listening0, &listening1, &eventCond]() { + &aNotification1, &frameHandlerSecondary, &listening0, &listening1, &eventCond]() { listening1 = true; if (listening0) { eventCond.notify_all(); @@ -1304,7 +1304,7 @@ TEST_P(EvsHidlTest, MultiCameraParameter) { aTargetEvent.aType = EvsEventType::PARAMETER_CHANGED; aTargetEvent.payload[0] = static_cast(cmd); aTargetEvent.payload[1] = val0; - if (!frameHandlerNonMaster->waitForEvent(aTargetEvent, aNotification1)) { + if (!frameHandlerSecondary->waitForEvent(aTargetEvent, aNotification1)) { LOG(WARNING) << "A timer is expired before a target event is fired."; } } @@ -1321,7 +1321,7 @@ TEST_P(EvsHidlTest, MultiCameraParameter) { // Try to program a parameter values.clear(); - pCamMaster->setIntParameter(cmd, val0, + pCamPrimary->setIntParameter(cmd, val0, [&result, &values](auto status, auto effectiveValues) { result = status; if (status == EvsResult::OK) { @@ -1361,9 +1361,9 @@ TEST_P(EvsHidlTest, MultiCameraParameter) { } // Clients expects to receive a parameter change notification - // whenever a master client adjusts it. + // whenever a primary client client adjusts it. values.clear(); - pCamMaster->getIntParameter(cmd, + pCamPrimary->getIntParameter(cmd, [&result, &values](auto status, auto readValues) { result = status; if (status == EvsResult::OK) { @@ -1378,9 +1378,9 @@ TEST_P(EvsHidlTest, MultiCameraParameter) { } } - // Try to adjust a parameter via non-master client + // Try to adjust a parameter via non-primary client values.clear(); - pCamNonMaster->setIntParameter(camNonMasterCmds[0], val0, + pCamSecondary->setIntParameter(camSecondaryCmds[0], val0, [&result, &values](auto status, auto effectiveValues) { result = status; if (status == EvsResult::OK) { @@ -1391,21 +1391,21 @@ TEST_P(EvsHidlTest, MultiCameraParameter) { }); ASSERT_EQ(EvsResult::INVALID_ARG, result); - // Non-master client attemps to be a master - result = pCamNonMaster->setMaster(); + // Non-primary client attempts to be a primary client + result = pCamSecondary->setMaster(); ASSERT_EQ(EvsResult::OWNERSHIP_LOST, result); - // Master client retires from a master role + // Primary client retires from a primary client role bool listening = false; std::condition_variable eventCond; std::thread listener = std::thread( - [&aNotification0, &frameHandlerNonMaster, &listening, &eventCond]() { + [&aNotification0, &frameHandlerSecondary, &listening, &eventCond]() { listening = true; eventCond.notify_all(); EvsEventDesc aTargetEvent; aTargetEvent.aType = EvsEventType::MASTER_RELEASED; - if (!frameHandlerNonMaster->waitForEvent(aTargetEvent, aNotification0, true)) { + if (!frameHandlerSecondary->waitForEvent(aTargetEvent, aNotification0, true)) { LOG(WARNING) << "A timer is expired before a target event is fired."; } } @@ -1419,7 +1419,7 @@ TEST_P(EvsHidlTest, MultiCameraParameter) { } lock.unlock(); - result = pCamMaster->unsetMaster(); + result = pCamPrimary->unsetMaster(); ASSERT_EQ(EvsResult::OK, result); if (listener.joinable()) { @@ -1430,7 +1430,7 @@ TEST_P(EvsHidlTest, MultiCameraParameter) { // Try to adjust a parameter after being retired values.clear(); - pCamMaster->setIntParameter(camMasterCmds[0], val0, + pCamPrimary->setIntParameter(camPrimaryCmds[0], val0, [&result, &values](auto status, auto effectiveValues) { result = status; if (status == EvsResult::OK) { @@ -1441,15 +1441,15 @@ TEST_P(EvsHidlTest, MultiCameraParameter) { }); ASSERT_EQ(EvsResult::INVALID_ARG, result); - // Non-master client becomes a master - result = pCamNonMaster->setMaster(); + // Non-primary client becomes a primary client + result = pCamSecondary->setMaster(); ASSERT_EQ(EvsResult::OK, result); - // Try to adjust a parameter via new master client - for (auto &cmd : camNonMasterCmds) { + // Try to adjust a parameter via new primary client + for (auto &cmd : camSecondaryCmds) { // Get a valid parameter value range int32_t minVal, maxVal, step; - pCamNonMaster->getIntParameterRange( + pCamSecondary->getIntParameterRange( cmd, [&minVal, &maxVal, &step](int32_t val0, int32_t val1, int32_t val2) { minVal = val0; @@ -1463,7 +1463,7 @@ TEST_P(EvsHidlTest, MultiCameraParameter) { if (cmd == CameraParam::ABSOLUTE_FOCUS) { // Try to turn off auto-focus values.clear(); - pCamNonMaster->setIntParameter(CameraParam::AUTO_FOCUS, 0, + pCamSecondary->setIntParameter(CameraParam::AUTO_FOCUS, 0, [&result, &values](auto status, auto effectiveValues) { result = status; if (status == EvsResult::OK) { @@ -1487,7 +1487,7 @@ TEST_P(EvsHidlTest, MultiCameraParameter) { bool listening1 = false; std::condition_variable eventCond; std::thread listener0 = std::thread( - [&cmd, &val0, &aNotification0, &frameHandlerMaster, &listening0, &listening1, &eventCond]() { + [&]() { listening0 = true; if (listening1) { eventCond.notify_all(); @@ -1497,13 +1497,13 @@ TEST_P(EvsHidlTest, MultiCameraParameter) { aTargetEvent.aType = EvsEventType::PARAMETER_CHANGED; aTargetEvent.payload[0] = static_cast(cmd); aTargetEvent.payload[1] = val0; - if (!frameHandlerMaster->waitForEvent(aTargetEvent, aNotification0)) { + if (!frameHandlerPrimary->waitForEvent(aTargetEvent, aNotification0)) { LOG(WARNING) << "A timer is expired before a target event is fired."; } } ); std::thread listener1 = std::thread( - [&cmd, &val0, &aNotification1, &frameHandlerNonMaster, &listening0, &listening1, &eventCond]() { + [&]() { listening1 = true; if (listening0) { eventCond.notify_all(); @@ -1513,7 +1513,7 @@ TEST_P(EvsHidlTest, MultiCameraParameter) { aTargetEvent.aType = EvsEventType::PARAMETER_CHANGED; aTargetEvent.payload[0] = static_cast(cmd); aTargetEvent.payload[1] = val0; - if (!frameHandlerNonMaster->waitForEvent(aTargetEvent, aNotification1)) { + if (!frameHandlerSecondary->waitForEvent(aTargetEvent, aNotification1)) { LOG(WARNING) << "A timer is expired before a target event is fired."; } } @@ -1530,7 +1530,7 @@ TEST_P(EvsHidlTest, MultiCameraParameter) { // Try to program a parameter values.clear(); - pCamNonMaster->setIntParameter(cmd, val0, + pCamSecondary->setIntParameter(cmd, val0, [&result, &values](auto status, auto effectiveValues) { result = status; if (status == EvsResult::OK) { @@ -1542,9 +1542,9 @@ TEST_P(EvsHidlTest, MultiCameraParameter) { ASSERT_EQ(EvsResult::OK, result); // Clients expects to receive a parameter change notification - // whenever a master client adjusts it. + // whenever a primary client client adjusts it. values.clear(); - pCamNonMaster->getIntParameter(cmd, + pCamSecondary->getIntParameter(cmd, [&result, &values](auto status, auto readValues) { result = status; if (status == EvsResult::OK) { @@ -1583,17 +1583,17 @@ TEST_P(EvsHidlTest, MultiCameraParameter) { } } - // New master retires from a master role - result = pCamNonMaster->unsetMaster(); + // New primary client retires from the role + result = pCamSecondary->unsetMaster(); ASSERT_EQ(EvsResult::OK, result); // Shutdown - frameHandlerMaster->shutdown(); - frameHandlerNonMaster->shutdown(); + frameHandlerPrimary->shutdown(); + frameHandlerSecondary->shutdown(); // Explicitly release the camera - pEnumerator->closeCamera(pCamMaster); - pEnumerator->closeCamera(pCamNonMaster); + pEnumerator->closeCamera(pCamPrimary); + pEnumerator->closeCamera(pCamSecondary); activeCameras.clear(); } } @@ -1602,7 +1602,7 @@ TEST_P(EvsHidlTest, MultiCameraParameter) { /* * HighPriorityCameraClient: * EVS client, which owns the display, is priortized and therefore can take over - * a master role from other EVS clients without the display. + * a primary client role from other EVS clients without the display. */ TEST_P(EvsHidlTest, HighPriorityCameraClient) { LOG(INFO) << "Starting HighPriorityCameraClient test"; @@ -1684,7 +1684,7 @@ TEST_P(EvsHidlTest, HighPriorityCameraClient) { frameHandler0->waitForFrameCount(1); frameHandler1->waitForFrameCount(1); - // Client 1 becomes a master and programs a parameter. + // Client 1 becomes a primary client and programs a parameter. EvsResult result = EvsResult::OK; // Get a valid parameter value range int32_t minVal, maxVal, step; @@ -1697,7 +1697,7 @@ TEST_P(EvsHidlTest, HighPriorityCameraClient) { } ); - // Client1 becomes a master + // Client1 becomes a primary client result = pCam1->setMaster(); ASSERT_EQ(EvsResult::OK, result); @@ -1836,7 +1836,7 @@ TEST_P(EvsHidlTest, HighPriorityCameraClient) { } lock.unlock(); - // Client 0 steals a master role + // Client 0 steals a primary client role ASSERT_EQ(EvsResult::OK, pCam0->forceMaster(pDisplay)); // Join a listener @@ -2257,7 +2257,7 @@ TEST_P(EvsHidlTest, LogicalCameraMetadata) { TEST_P(EvsHidlTest, CameraStreamExternalBuffering) { LOG(INFO) << "Starting CameraStreamExternalBuffering test"; - // Arbitrary constant (should be > 1 and less than crazy) + // Arbitrary constant (should be > 1 and not too big) static const unsigned int kBuffersToHold = 6; // Get the camera list @@ -2269,48 +2269,74 @@ TEST_P(EvsHidlTest, CameraStreamExternalBuffering) { // Acquire the graphics buffer allocator android::GraphicBufferAllocator& alloc(android::GraphicBufferAllocator::get()); - const auto usage = GRALLOC_USAGE_HW_TEXTURE | - GRALLOC_USAGE_SW_READ_RARELY | - GRALLOC_USAGE_SW_WRITE_OFTEN; + const auto usage = + GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_OFTEN; const auto format = HAL_PIXEL_FORMAT_RGBA_8888; - const auto width = 640; - const auto height = 360; - - // Allocate buffers to use - hidl_vec buffers; - buffers.resize(kBuffersToHold); - for (auto i = 0; i < kBuffersToHold; ++i) { - unsigned pixelsPerLine; - buffer_handle_t memHandle = nullptr; - android::status_t result = alloc.allocate(width, - height, - format, - 1, - usage, - &memHandle, - &pixelsPerLine, - 0, - "EvsApp"); - if (result != android::NO_ERROR) { - LOG(ERROR) << __FUNCTION__ << " failed to allocate memory."; - } else { - BufferDesc buf; - AHardwareBuffer_Desc* pDesc = - reinterpret_cast(&buf.buffer.description); - pDesc->width = width; - pDesc->height = height; - pDesc->layers = 1; - pDesc->format = format; - pDesc->usage = usage; - pDesc->stride = pixelsPerLine; - buf.buffer.nativeHandle = memHandle; - buf.bufferId = i; // Unique number to identify this buffer - buffers[i] = buf; - } - } + uint32_t width = 640; + uint32_t height = 360; + camera_metadata_entry_t streamCfgs; // Test each reported camera - for (auto&& cam: cameraInfo) { + for (auto&& cam : cameraInfo) { + bool foundCfg = false; + if (!find_camera_metadata_entry(reinterpret_cast(cam.metadata.data()), + ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, + &streamCfgs)) { + // Stream configurations are found in metadata + RawStreamConfig* ptr = reinterpret_cast(streamCfgs.data.i32); + + LOG(DEBUG) << __LINE__ << " start searching " << streamCfgs.count; + for (unsigned idx = 0; idx < streamCfgs.count; idx++) { + LOG(DEBUG) << "ptr->direction= " << ptr->direction + << " ptr->format= " << ptr->format; + if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT && + ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) { + width = ptr->width; + height = ptr->height; + foundCfg = true; + // Always use the 1st available configuration + break; + } + ++ptr; + } + } + + if (!foundCfg) { + LOG(INFO) << "No configuration found. Use default stream configurations."; + } + + // Allocate buffers to use + hidl_vec buffers; + buffers.resize(kBuffersToHold); + for (auto i = 0; i < kBuffersToHold; ++i) { + unsigned pixelsPerLine; + buffer_handle_t memHandle = nullptr; + android::status_t result = + alloc.allocate(width, height, format, 1, usage, &memHandle, &pixelsPerLine, 0, + "CameraStreamExternalBufferingTest"); + if (result != android::NO_ERROR) { + LOG(ERROR) << __FUNCTION__ << " failed to allocate memory."; + // Release previous allocated buffers + for (auto j = 0; j < i; j++) { + alloc.free(buffers[i].buffer.nativeHandle); + } + return; + } else { + BufferDesc buf; + AHardwareBuffer_Desc* pDesc = + reinterpret_cast(&buf.buffer.description); + pDesc->width = width; + pDesc->height = height; + pDesc->layers = 1; + pDesc->format = format; + pDesc->usage = usage; + pDesc->stride = pixelsPerLine; + buf.buffer.nativeHandle = memHandle; + buf.bufferId = i; // Unique number to identify this buffer + buffers[i] = buf; + } + } + bool isLogicalCam = false; getPhysicalCameraIds(cam.v1.cameraId, isLogicalCam); @@ -2374,13 +2400,12 @@ TEST_P(EvsHidlTest, CameraStreamExternalBuffering) { // Explicitly release the camera pEnumerator->closeCamera(pCam); activeCameras.clear(); + // Release buffers + for (auto& b : buffers) { + alloc.free(b.buffer.nativeHandle); + } + buffers.resize(0); } - - // Release buffers - for (auto& b : buffers) { - alloc.free(b.buffer.nativeHandle); - } - buffers.resize(0); } @@ -2487,7 +2512,7 @@ TEST_P(EvsHidlTest, UltrasonicsSetFramesInFlight) { } } - +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EvsHidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, EvsHidlTest, diff --git a/automotive/evs/OWNERS b/automotive/evs/OWNERS index fec2a3ad33231f42312a9a891aa8257fee3ba3ed..559a372e1ef841de82f9c1a26fe12c8e139e1f87 100644 --- a/automotive/evs/OWNERS +++ b/automotive/evs/OWNERS @@ -1,3 +1 @@ changyeon@google.com -haoxiangl@google.com -swan@google.com diff --git a/automotive/occupant_awareness/aidl/vts/functional/VtsHalOccupantAwarenessV1_0TargetTest.cpp b/automotive/occupant_awareness/aidl/vts/functional/VtsHalOccupantAwarenessV1_0TargetTest.cpp index c431f9d3b84c2a52ca8b3488aacfff6a75f73d0a..a1fd05aa177c6604ba672a57b4ecb9593c0180c8 100644 --- a/automotive/occupant_awareness/aidl/vts/functional/VtsHalOccupantAwarenessV1_0TargetTest.cpp +++ b/automotive/occupant_awareness/aidl/vts/functional/VtsHalOccupantAwarenessV1_0TargetTest.cpp @@ -190,6 +190,7 @@ TEST_P(OccupantAwarenessAidl, GetLatestDetectionTest) { ASSERT_LE(elapsed, kTimeout); } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(OccupantAwarenessAidl); INSTANTIATE_TEST_SUITE_P( InstantiationName, OccupantAwarenessAidl, testing::ValuesIn(android::getAidlHalInstanceNames(IOccupantAwareness::descriptor)), diff --git a/automotive/sv/1.0/vts/functional/VtsHalSurroundViewV1_0TargetTest.cpp b/automotive/sv/1.0/vts/functional/VtsHalSurroundViewV1_0TargetTest.cpp index b1b9d16bc21f7d55005d315003f351975fb7e318..059d152bcf7b6e9d4fbc6ca3b29866ac0b12557e 100644 --- a/automotive/sv/1.0/vts/functional/VtsHalSurroundViewV1_0TargetTest.cpp +++ b/automotive/sv/1.0/vts/functional/VtsHalSurroundViewV1_0TargetTest.cpp @@ -1127,6 +1127,7 @@ TEST_P(SurroundViewHidlTest, projectPointsInvalidPointsFail) { mSurroundViewService->stop3dSession(surroundView3dSession); } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SurroundViewHidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, SurroundViewHidlTest, diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp index b0e60efc6abce80dbd779175822f738a06d49354..869c0c9124ae2e4de6ee418a0d242efaa9054759 100644 --- a/automotive/vehicle/2.0/default/Android.bp +++ b/automotive/vehicle/2.0/default/Android.bp @@ -41,7 +41,7 @@ cc_defaults { defaults: ["vhal_v2_0_defaults"], shared_libs: [ "libbinder_ndk", - "carwatchdog_aidl_interface-V2-ndk", + "android.automotive.watchdog-V2-ndk", ], } @@ -78,6 +78,7 @@ cc_library_static { name: "android.hardware.automotive.vehicle@2.0-default-impl-lib", vendor: true, defaults: ["vhal_v2_0_target_defaults"], + cflags: ["-DENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING"], srcs: [ "impl/vhal_v2_0/CommConn.cpp", "impl/vhal_v2_0/EmulatedVehicleConnector.cpp", @@ -133,6 +134,7 @@ cc_library_static { srcs: [ "common/src/Obd2SensorStore.cpp", "common/src/VehicleObjectPool.cpp", + "common/src/VehiclePropertyStore.cpp", "common/src/VehicleUtils.cpp", ], } diff --git a/automotive/vehicle/2.0/default/VehicleService.cpp b/automotive/vehicle/2.0/default/VehicleService.cpp index ef29560588f286450877f26c9fe45fefb101ffd5..7e8deb6777545135fc3283733d78dfcc82ac45bf 100644 --- a/automotive/vehicle/2.0/default/VehicleService.cpp +++ b/automotive/vehicle/2.0/default/VehicleService.cpp @@ -20,13 +20,10 @@ #include -#include -#include #include #include #include #include -#include using namespace android; using namespace android::hardware; @@ -41,7 +38,7 @@ int main(int /* argc */, char* /* argv */ []) { auto service = std::make_unique(hal.get()); connector->setValuePool(hal->getValuePool()); - configureRpcThreadpool(4, false /* callerWillJoin */); + configureRpcThreadpool(4, true /* callerWillJoin */); ALOGI("Registering as service..."); status_t status = service->registerAsService(); @@ -51,22 +48,8 @@ int main(int /* argc */, char* /* argv */ []) { return 1; } - // Setup a binder thread pool to be a car watchdog client. - ABinderProcess_setThreadPoolMaxThreadCount(1); - ABinderProcess_startThreadPool(); - sp looper(Looper::prepare(0 /* opts */)); - std::shared_ptr watchdogClient = - ndk::SharedRefBase::make(looper, service.get()); - // The current health check is done in the main thread, so it falls short of capturing the real - // situation. Checking through HAL binder thread should be considered. - if (!watchdogClient->initialize()) { - ALOGE("Failed to initialize car watchdog client"); - return 1; - } ALOGI("Ready"); - while (true) { - looper->pollAll(-1 /* timeoutMillis */); - } + joinRpcThreadpool(); return 1; } diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehiclePropertyStore.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehiclePropertyStore.h index 0a243fe352ca3831bfc462ebcb0a8fd36aae7a76..6a02cf3cab0196ccd8d0ff6dbd4cc1e8f89ed47f 100644 --- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehiclePropertyStore.h +++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehiclePropertyStore.h @@ -19,10 +19,11 @@ #include #include +#include #include #include -#include +#include namespace android { namespace hardware { 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 dec2d8cb7858af1491ef6045da613a3c0192eec7..f09d75ba213c317d19691c389df9bd7cc38c80f9 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 @@ -17,8 +17,7 @@ #ifndef android_hardware_automotive_vehicle_V2_0_impl_DefaultConfig_H_ #define android_hardware_automotive_vehicle_V2_0_impl_DefaultConfig_H_ -#include -#include +#include "PropertyUtils.h" #include @@ -29,157 +28,6 @@ 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 AP_POWER_STATE_REQ = (int)VehicleProperty::AP_POWER_STATE_REQ; -constexpr int AP_POWER_STATE_REPORT = (int)VehicleProperty::AP_POWER_STATE_REPORT; -constexpr int DOOR_1_LEFT = (int)VehicleAreaDoor::ROW_1_LEFT; -constexpr int DOOR_1_RIGHT = (int)VehicleAreaDoor::ROW_1_RIGHT; -constexpr int DOOR_2_LEFT = (int)VehicleAreaDoor::ROW_2_LEFT; -constexpr int DOOR_2_RIGHT = (int)VehicleAreaDoor::ROW_2_RIGHT; -constexpr int DOOR_REAR = (int)VehicleAreaDoor::REAR; -constexpr int WINDOW_1_LEFT = (int)VehicleAreaWindow::ROW_1_LEFT; -constexpr int WINDOW_1_RIGHT = (int)VehicleAreaWindow::ROW_1_RIGHT; -constexpr int WINDOW_2_LEFT = (int)VehicleAreaWindow::ROW_2_LEFT; -constexpr int WINDOW_2_RIGHT = (int)VehicleAreaWindow::ROW_2_RIGHT; -constexpr int WINDOW_ROOF_TOP_1 = (int)VehicleAreaWindow::ROOF_TOP_1; -constexpr int FAN_DIRECTION_FACE = (int)VehicleHvacFanDirection::FACE; -constexpr int FAN_DIRECTION_FLOOR = (int)VehicleHvacFanDirection::FLOOR; -constexpr int OBD2_LIVE_FRAME = (int)VehicleProperty::OBD2_LIVE_FRAME; -constexpr int OBD2_FREEZE_FRAME = (int)VehicleProperty::OBD2_FREEZE_FRAME; -constexpr int OBD2_FREEZE_FRAME_INFO = (int)VehicleProperty::OBD2_FREEZE_FRAME_INFO; -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)(VehicleAreaWheel::LEFT_FRONT | VehicleAreaWheel::RIGHT_FRONT | - VehicleAreaWheel::LEFT_REAR | VehicleAreaWheel::RIGHT_REAR); -constexpr int SEAT_1_LEFT = (int)(VehicleAreaSeat::ROW_1_LEFT); -constexpr int SEAT_1_RIGHT = (int)(VehicleAreaSeat::ROW_1_RIGHT); -constexpr int HVAC_LEFT = (int)(VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_2_LEFT | - VehicleAreaSeat::ROW_2_CENTER); -constexpr int HVAC_RIGHT = (int)(VehicleAreaSeat::ROW_1_RIGHT | VehicleAreaSeat::ROW_2_RIGHT); -constexpr int HVAC_ALL = HVAC_LEFT | HVAC_RIGHT; -constexpr int VENDOR_EXTENSION_BOOLEAN_PROPERTY = - (int)(0x101 | VehiclePropertyGroup::VENDOR | VehiclePropertyType::BOOLEAN | VehicleArea::DOOR); -constexpr int VENDOR_EXTENSION_FLOAT_PROPERTY = - (int)(0x102 | VehiclePropertyGroup::VENDOR | VehiclePropertyType::FLOAT | VehicleArea::SEAT); -constexpr int VENDOR_EXTENSION_INT_PROPERTY = - (int)(0x103 | VehiclePropertyGroup::VENDOR | VehiclePropertyType::INT32 | VehicleArea::WINDOW); -constexpr int VENDOR_EXTENSION_STRING_PROPERTY = - (int)(0x104 | VehiclePropertyGroup::VENDOR | VehiclePropertyType::STRING | VehicleArea::GLOBAL); -constexpr int FUEL_DOOR_REAR_LEFT = (int)PortLocationType::REAR_LEFT; -constexpr int CHARGE_PORT_FRONT_LEFT = (int)PortLocationType::FRONT_LEFT; -constexpr int CHARGE_PORT_REAR_LEFT = (int)PortLocationType::REAR_LEFT; -constexpr int LIGHT_STATE_ON = (int)VehicleLightState::ON; -constexpr int LIGHT_SWITCH_AUTO = (int)VehicleLightSwitch::AUTOMATIC; -constexpr int WHEEL_FRONT_LEFT = (int)VehicleAreaWheel::LEFT_FRONT; -constexpr int WHEEL_FRONT_RIGHT = (int)VehicleAreaWheel::RIGHT_FRONT; -constexpr int WHEEL_REAR_LEFT = (int)VehicleAreaWheel::LEFT_REAR; -constexpr int WHEEL_REAR_RIGHT = (int)VehicleAreaWheel::RIGHT_REAR; - -/** - * This property is used for test purpose to generate fake events. Here is the test package that - * is referencing this property definition: packages/services/Car/tests/vehiclehal_test - */ -const int32_t kGenerateFakeDataControllingProperty = - 0x0666 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::MIXED; - -/** - * This property is used for test purpose to set properties' value from vehicle. - * For example: Mocking hard button press triggering a HVAC fan speed change. - * Android set kSetPropertyFromVehicleForTest with an array of integer {HVAC_FAN_SPEED, value of - * fan speed} and a long value indicates the timestamp of the events . - * It only works with integer type properties. - */ -const int32_t kSetIntPropertyFromVehicleForTest = - 0x1112 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::MIXED; -/** - * This property is used for test purpose to set properties' value from vehicle. - * It only works with float type properties. - */ -const int32_t kSetFloatPropertyFromVehicleForTest = - 0x1113 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::MIXED; -/** - * This property is used for test purpose to set properties' value from vehicle. - * It only works with boolean type properties. - */ -const int32_t kSetBooleanPropertyFromVehicleForTest = - 0x1114 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::MIXED; - -/** - * This property is used for test purpose. End to end tests use this property to test set and get - * method for MIXED type properties. - */ -const int32_t kMixedTypePropertyForTest = - 0x1111 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::MIXED; -/** - * FakeDataCommand enum defines the supported command type for kGenerateFakeDataControllingProperty. - * All those commands can be send independently with each other. And each will override the one sent - * previously. - * - * The controlling property has the following format: - * - * int32Values[0] - command enum defined in FakeDataCommand - * - * The format of the arguments is defined for each command type as below: - */ -enum class FakeDataCommand : int32_t { - /** - * Starts linear fake data generation. Caller must provide additional data: - * int32Values[1] - vehicle property to which command applies - * int64Values[0] - periodic interval in nanoseconds - * floatValues[0] - initial value - * floatValues[1] - dispersion defines the min/max value relative to initial value, where - * max = initial_value + dispersion, min = initial_value - dispersion. - * Dispersion should be non-negative, otherwise the behavior is undefined. - * floatValues[2] - increment, with every timer tick the value will be incremented by this - * amount. When reaching to max value, the current value will be set to - * min. It should be non-negative, otherwise the behavior is undefined. - */ - StartLinear = 0, - - /** Stops linear fake data generation that was triggered by StartLinear commands. - * int32Values[1] - vehicle property to which command applies. VHAL will stop the - * corresponding linear generation for that property. - */ - StopLinear = 1, - - /** - * Starts JSON-based fake data generation. It iterates through JSON-encoded VHAL events from a - * file and inject them to VHAL. The iteration can be repeated multiple times or infinitely. - * Caller must provide additional data: - * int32Values[1] - number of iterations. If it is not provided or -1. The iteration will be - * repeated infinite times. - * stringValue - path to the fake values JSON file - */ - StartJson = 2, - - /** - * Stops JSON-based fake data generation. As multiple JSON-based generation can happen at the - * same time. Caller must provide the path of fake value JSON file to stop the corresponding - * generation: - * stringValue - path to the fake values JSON file - */ - StopJson = 3, - - /** - * Injects key press event (HAL incorporates UP/DOWN acction and triggers 2 HAL events for every - * key-press). We set the enum with high number to leave space for future start/stop commands. - * Caller must provide the following data: - * int32Values[2] - Android key code - * int32Values[3] - target display (0 - for main display, 1 - for instrument cluster, see - * VehicleDisplay) - */ - KeyPress = 100, -}; - -const int32_t kHvacPowerProperties[] = { - toInt(VehicleProperty::HVAC_FAN_SPEED), - toInt(VehicleProperty::HVAC_FAN_DIRECTION), -}; struct ConfigDeclaration { VehiclePropConfig config; @@ -225,14 +73,6 @@ const ConfigDeclaration kVehicleProperties[]{ }, .initialValue = {.int32Values = {(int)EvConnectorType::IEC_TYPE_1_AC}}}, - {.config = - { - .prop = toInt(VehicleProperty::INFO_DRIVER_SEAT), - .access = VehiclePropertyAccess::READ, - .changeMode = VehiclePropertyChangeMode::STATIC, - }, - .initialValue = {.int32Values = {SEAT_1_LEFT}}}, - {.config = { .prop = toInt(VehicleProperty::INFO_FUEL_DOOR_LOCATION), @@ -284,7 +124,7 @@ const ConfigDeclaration kVehicleProperties[]{ .access = VehiclePropertyAccess::READ, .changeMode = VehiclePropertyChangeMode::STATIC, }, - .initialValue = {.floatValues = {1776, 4950, 2008, 2140, 2984, 1665, 1667, 11800}}}, + .initialValue = {.int32Values = {1776, 4950, 2008, 2140, 2984, 1665, 1667, 11800}}}, {.config = { .prop = toInt(VehicleProperty::PERF_VEHICLE_SPEED), @@ -306,6 +146,19 @@ const ConfigDeclaration kVehicleProperties[]{ }, .initialValue = {.int32Values = {(int)VehicleUnit::KILOMETERS_PER_HOUR}}}, + {.config = + { + .prop = toInt(VehicleProperty::SEAT_OCCUPANCY), + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + .areaConfigs = {VehicleAreaConfig{.areaId = (SEAT_1_LEFT)}, + VehicleAreaConfig{.areaId = (SEAT_1_RIGHT)}}, + }, + .initialAreaValues = {{SEAT_1_LEFT, + {.int32Values = {(int)VehicleSeatOccupancyState::VACANT}}}, + {SEAT_1_RIGHT, + {.int32Values = {(int)VehicleSeatOccupancyState::VACANT}}}}}, + {.config = { .prop = toInt(VehicleProperty::INFO_DRIVER_SEAT), @@ -321,7 +174,7 @@ const ConfigDeclaration kVehicleProperties[]{ .prop = toInt(VehicleProperty::PERF_ODOMETER), .access = VehiclePropertyAccess::READ, .changeMode = VehiclePropertyChangeMode::CONTINUOUS, - .minSampleRate = 0.0f, + .minSampleRate = 1.0f, .maxSampleRate = 10.0f, }, .initialValue = {.floatValues = {0.0f}}}, @@ -330,7 +183,7 @@ const ConfigDeclaration kVehicleProperties[]{ .prop = toInt(VehicleProperty::PERF_STEERING_ANGLE), .access = VehiclePropertyAccess::READ, .changeMode = VehiclePropertyChangeMode::CONTINUOUS, - .minSampleRate = 0.0f, + .minSampleRate = 1.0f, .maxSampleRate = 10.0f, }, .initialValue = {.floatValues = {0.0f}}}, @@ -339,7 +192,7 @@ const ConfigDeclaration kVehicleProperties[]{ .prop = toInt(VehicleProperty::PERF_REAR_STEERING_ANGLE), .access = VehiclePropertyAccess::READ, .changeMode = VehiclePropertyChangeMode::CONTINUOUS, - .minSampleRate = 0.0f, + .minSampleRate = 1.0f, .maxSampleRate = 10.0f, }, .initialValue = {.floatValues = {0.0f}}}, @@ -360,7 +213,7 @@ const ConfigDeclaration kVehicleProperties[]{ .prop = toInt(VehicleProperty::FUEL_LEVEL), .access = VehiclePropertyAccess::READ, .changeMode = VehiclePropertyChangeMode::CONTINUOUS, - .minSampleRate = 0.0f, + .minSampleRate = 1.0f, .maxSampleRate = 100.0f, }, .initialValue = {.floatValues = {15000.0f}}}, @@ -378,7 +231,7 @@ const ConfigDeclaration kVehicleProperties[]{ .prop = toInt(VehicleProperty::EV_BATTERY_LEVEL), .access = VehiclePropertyAccess::READ, .changeMode = VehiclePropertyChangeMode::CONTINUOUS, - .minSampleRate = 0.0f, + .minSampleRate = 1.0f, .maxSampleRate = 100.0f, }, .initialValue = {.floatValues = {150000.0f}}}, @@ -426,22 +279,22 @@ const ConfigDeclaration kVehicleProperties[]{ .changeMode = VehiclePropertyChangeMode::CONTINUOUS, .areaConfigs = {VehicleAreaConfig{ .areaId = WHEEL_FRONT_LEFT, - .minFloatValue = 100.0f, + .minFloatValue = 193.0f, .maxFloatValue = 300.0f, }, VehicleAreaConfig{ .areaId = WHEEL_FRONT_RIGHT, - .minFloatValue = 100.0f, + .minFloatValue = 193.0f, .maxFloatValue = 300.0f, }, VehicleAreaConfig{ .areaId = WHEEL_REAR_LEFT, - .minFloatValue = 100.0f, + .minFloatValue = 193.0f, .maxFloatValue = 300.0f, }, VehicleAreaConfig{ .areaId = WHEEL_REAR_RIGHT, - .minFloatValue = 100.0f, + .minFloatValue = 193.0f, .maxFloatValue = 300.0f, }}, .minSampleRate = 1.0f, @@ -449,6 +302,17 @@ const ConfigDeclaration kVehicleProperties[]{ }, .initialValue = {.floatValues = {200.0f}}}, // units in kPa + {.config = + { + .prop = toInt(VehicleProperty::CRITICALLY_LOW_TIRE_PRESSURE), + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::STATIC, + }, + .initialAreaValues = {{WHEEL_FRONT_LEFT, {.floatValues = {137.0f}}}, + {WHEEL_FRONT_RIGHT, {.floatValues = {137.0f}}}, + {WHEEL_REAR_RIGHT, {.floatValues = {137.0f}}}, + {WHEEL_REAR_LEFT, {.floatValues = {137.0f}}}}}, + {.config = { .prop = toInt(VehicleProperty::TIRE_PRESSURE_DISPLAY_UNITS), @@ -464,6 +328,11 @@ const ConfigDeclaration kVehicleProperties[]{ .prop = toInt(VehicleProperty::CURRENT_GEAR), .access = VehiclePropertyAccess::READ, .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + .configArray = {(int)VehicleGear::GEAR_PARK, + (int)VehicleGear::GEAR_NEUTRAL, + (int)VehicleGear::GEAR_REVERSE, (int)VehicleGear::GEAR_1, + (int)VehicleGear::GEAR_2, (int)VehicleGear::GEAR_3, + (int)VehicleGear::GEAR_4, (int)VehicleGear::GEAR_5}, }, .initialValue = {.int32Values = {toInt(VehicleGear::GEAR_PARK)}}}, @@ -475,6 +344,14 @@ const ConfigDeclaration kVehicleProperties[]{ }, .initialValue = {.int32Values = {1}}}, + {.config = + { + .prop = toInt(VehicleProperty::PARKING_BRAKE_AUTO_APPLY), + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + }, + .initialValue = {.int32Values = {1}}}, + {.config = { .prop = toInt(VehicleProperty::FUEL_LEVEL_LOW), @@ -499,6 +376,18 @@ const ConfigDeclaration kVehicleProperties[]{ }, .initialValue = {.int32Values = {0, 0, 0}}}, + {.config = + { + .prop = toInt(VehicleProperty::HW_CUSTOM_INPUT), + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + .configArray = {0, 0, 0, 3, 0, 0, 0, 0, 0}, + }, + .initialValue = + { + .int32Values = {0, 0, 0}, + }}, + {.config = {.prop = toInt(VehicleProperty::HVAC_POWER_ON), .access = VehiclePropertyAccess::READ_WRITE, .changeMode = VehiclePropertyChangeMode::ON_CHANGE, @@ -635,6 +524,7 @@ const ConfigDeclaration kVehicleProperties[]{ {.config = {.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET), .access = VehiclePropertyAccess::READ_WRITE, .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + .configArray = {160, 280, 5, 605, 825, 10}, .areaConfigs = {VehicleAreaConfig{ .areaId = HVAC_LEFT, .minFloatValue = 16, @@ -648,6 +538,14 @@ const ConfigDeclaration kVehicleProperties[]{ .initialAreaValues = {{HVAC_LEFT, {.floatValues = {16}}}, {HVAC_RIGHT, {.floatValues = {20}}}}}, + {.config = + { + .prop = toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION), + .access = VehiclePropertyAccess::READ_WRITE, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + }, + .initialValue = {.floatValues = {66.2f, (float)VehicleUnit::FAHRENHEIT, 19.0f, 66.5f}}}, + {.config = { .prop = toInt(VehicleProperty::ENV_OUTSIDE_TEMPERATURE), @@ -971,6 +869,15 @@ const ConfigDeclaration kVehicleProperties[]{ }, .initialValue = {.int32Values = {LIGHT_SWITCH_AUTO}}}, + {.config = + { + .prop = toInt(VehicleProperty::EVS_SERVICE_REQUEST), + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + }, + .initialValue = {.int32Values = {toInt(EvsServiceType::REARVIEW), + toInt(EvsServiceState::OFF)}}}, + {.config = {.prop = VEHICLE_MAP_SERVICE, .access = VehiclePropertyAccess::READ_WRITE, .changeMode = VehiclePropertyChangeMode::ON_CHANGE}}, @@ -1022,10 +929,20 @@ const ConfigDeclaration kVehicleProperties[]{ .changeMode = VehiclePropertyChangeMode::ON_CHANGE}, .initialValue = {.stringValue = "Vendor String Property"}}, + {.config = {.prop = toInt(VehicleProperty::ELECTRONIC_TOLL_COLLECTION_CARD_TYPE), + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE}, + .initialValue = {.int32Values = {0}}}, + + {.config = {.prop = toInt(VehicleProperty::ELECTRONIC_TOLL_COLLECTION_CARD_STATUS), + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE}, + .initialValue = {.int32Values = {0}}}, + {.config = { .prop = toInt(VehicleProperty::SUPPORT_CUSTOMIZE_VENDOR_PERMISSION), - .access = VehiclePropertyAccess::READ_WRITE, + .access = VehiclePropertyAccess::READ, .changeMode = VehiclePropertyChangeMode::ON_CHANGE, .configArray = {kMixedTypePropertyForTest, @@ -1080,6 +997,162 @@ const ConfigDeclaration kVehicleProperties[]{ .changeMode = VehiclePropertyChangeMode::ON_CHANGE, }, }, + { + .config = + { + .prop = toInt(VehicleProperty::POWER_POLICY_REQ), + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + }, + }, + { + .config = + { + .prop = toInt(VehicleProperty::POWER_POLICY_GROUP_REQ), + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + }, + }, + { + .config = + { + .prop = toInt(VehicleProperty::CURRENT_POWER_POLICY), + .access = VehiclePropertyAccess::READ_WRITE, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + }, + }, + { + .config = + { + .prop = toInt(VehicleProperty::EPOCH_TIME), + .access = VehiclePropertyAccess::READ_WRITE, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + }, + }, + { + .config = + { + .prop = toInt(VehicleProperty::STORAGE_ENCRYPTION_BINDING_SEED), + .access = VehiclePropertyAccess::READ_WRITE, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + }, + }, + { + .config = + { + .prop = toInt(VehicleProperty::WATCHDOG_ALIVE), + .access = VehiclePropertyAccess::WRITE, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + }, + }, + { + .config = + { + .prop = toInt(VehicleProperty::WATCHDOG_TERMINATED_PROCESS), + .access = VehiclePropertyAccess::WRITE, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + }, + }, + { + .config = + { + .prop = toInt(VehicleProperty::VHAL_HEARTBEAT), + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + }, + }, + { + .config = + { + .prop = toInt(VehicleProperty::CLUSTER_SWITCH_UI), + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + }, + .initialValue = {.int32Values = {0 /* ClusterHome */, -1 /* ClusterNone */}}, + }, + { + .config = + { + .prop = toInt(VehicleProperty::CLUSTER_DISPLAY_STATE), + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + }, + .initialValue = {.int32Values = {0 /* Off */, -1, -1, -1, -1 /* Bounds */, -1, -1, + -1, -1 /* Insets */}}, + }, + { + .config = + { + .prop = toInt(VehicleProperty::CLUSTER_REPORT_STATE), + .access = VehiclePropertyAccess::WRITE, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + .configArray = {0, 0, 0, 11, 0, 0, 0, 0, 16}, + }, + }, + { + .config = + { + .prop = toInt(VehicleProperty::CLUSTER_REQUEST_DISPLAY), + .access = VehiclePropertyAccess::WRITE, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + }, + }, + { + .config = + { + .prop = toInt(VehicleProperty::CLUSTER_NAVIGATION_STATE), + .access = VehiclePropertyAccess::WRITE, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + }, + }, +#ifdef ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING + // Vendor propetry for E2E ClusterHomeService testing. + { + .config = + { + .prop = VENDOR_CLUSTER_SWITCH_UI, + .access = VehiclePropertyAccess::WRITE, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + }, + }, + { + .config = + { + .prop = VENDOR_CLUSTER_DISPLAY_STATE, + .access = VehiclePropertyAccess::WRITE, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + }, + }, + { + .config = + { + .prop = VENDOR_CLUSTER_REPORT_STATE, + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + .configArray = {0, 0, 0, 11, 0, 0, 0, 0, 16}, + }, + .initialValue = {.int32Values = {0 /* Off */, -1, -1, -1, -1 /* Bounds */, -1, -1, + -1, -1 /* Insets */, 0 /* ClusterHome */, + -1 /* ClusterNone */}}, + }, + { + .config = + { + .prop = VENDOR_CLUSTER_REQUEST_DISPLAY, + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + }, + .initialValue = {.int32Values = {0 /* ClusterHome */}}, + }, + { + .config = + { + .prop = VENDOR_CLUSTER_NAVIGATION_STATE, + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + }, + }, +#endif // ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING }; } // impl diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp index ed3f4a2e8f1c2f84c80478c56a9ed2779f87541f..eae58d0759923cd9f8808a37a08831ceb1f6cbbf 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp @@ -21,7 +21,6 @@ #include #include -#include "DefaultConfig.h" #include "EmulatedVehicleConnector.h" #include "JsonFakeValueGenerator.h" #include "LinearFakeValueGenerator.h" @@ -39,6 +38,10 @@ EmulatedUserHal* EmulatedVehicleConnector::getEmulatedUserHal() { return &mEmulatedUserHal; } +void EmulatedVehicleConnector::triggerSendAllValues() { + sendAllValuesToClient(); +} + StatusCode EmulatedVehicleConnector::onSetProperty(const VehiclePropValue& value, bool updateStatus) { if (mEmulatedUserHal.isSupported(value.prop)) { diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h index 4c6c66150b3adceac60e5abe9d0888c0dccf38b9..31ac7d8fb518cd22b7b52c077bcf7e0bc33a3f8f 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h @@ -33,11 +33,13 @@ namespace impl { class EmulatedVehicleConnector : public IPassThroughConnector { public: - EmulatedVehicleConnector() {} + EmulatedVehicleConnector() = default; EmulatedUserHal* getEmulatedUserHal(); // Methods from VehicleHalServer + void triggerSendAllValues() override; + StatusCode onSetProperty(const VehiclePropValue& value, bool updateStatus) override; bool onDump(const hidl_handle& fd, const hidl_vec& options) override; 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 3ef42f1683bdb68c43a3c6322d3440e37f4c5020..e8b79dc3944389b72f193054986bd19c17a5be04 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 @@ -15,11 +15,13 @@ */ #define LOG_TAG "DefaultVehicleHal_v2_0" +#include #include #include #include #include #include +#include #include #include @@ -36,6 +38,8 @@ namespace V2_0 { namespace impl { +static constexpr std::chrono::nanoseconds kHeartBeatIntervalNs = 3s; + static std::unique_ptr fillDefaultObd2Frame(size_t numVendorIntegerSensors, size_t numVendorFloatSensors) { std::unique_ptr sensorStore( @@ -101,9 +105,6 @@ EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore, VehicleH mVehicleClient(client), mEmulatedUserHal(emulatedUserHal) { initStaticConfig(); - for (size_t i = 0; i < arraysize(kVehicleProperties); i++) { - mPropStore->registerProperty(kVehicleProperties[i].config); - } mVehicleClient->registerPropertyValueCallback(std::bind(&EmulatedVehicleHal::onPropertyValue, this, std::placeholders::_1, std::placeholders::_2)); @@ -176,7 +177,13 @@ VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::get( v = getValuePool()->obtain(*internalPropValue); } - *outStatus = v != nullptr ? StatusCode::OK : StatusCode::INVALID_ARG; + if (!v) { + *outStatus = StatusCode::INVALID_ARG; + } else if (v->status == VehiclePropertyStatus::AVAILABLE) { + *outStatus = StatusCode::OK; + } else { + *outStatus = StatusCode::TRY_AGAIN; + } break; } if (v.get()) { @@ -276,61 +283,47 @@ static bool isDiagnosticProperty(VehiclePropConfig propConfig) { void EmulatedVehicleHal::onCreate() { static constexpr bool shouldUpdateStatus = true; - for (auto& it : kVehicleProperties) { - VehiclePropConfig cfg = it.config; - int32_t numAreas = cfg.areaConfigs.size(); + auto configs = mVehicleClient->getAllPropertyConfig(); + for (const auto& cfg : configs) { 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 only a single area - if (isGlobalProp(cfg.prop)) { - numAreas = 1; - } + int32_t numAreas = isGlobalProp(cfg.prop) ? 0 : cfg.areaConfigs.size(); for (int i = 0; i < numAreas; i++) { - int32_t curArea; - - if (isGlobalProp(cfg.prop)) { - curArea = 0; - } else { - curArea = cfg.areaConfigs[i].areaId; - } + int32_t curArea = isGlobalProp(cfg.prop) ? 0 : cfg.areaConfigs[i].areaId; // Create a separate instance for each individual zone VehiclePropValue prop = { .areaId = curArea, .prop = cfg.prop, + .status = VehiclePropertyStatus::UNAVAILABLE, }; - if (it.initialAreaValues.size() > 0) { - auto valueForAreaIt = it.initialAreaValues.find(curArea); - if (valueForAreaIt != it.initialAreaValues.end()) { - prop.value = valueForAreaIt->second; - } else { - ALOGW("%s failed to get default value for prop 0x%x area 0x%x", - __func__, cfg.prop, curArea); - } - } else { - prop.value = it.initialValue; - if (mInitVhalValueOverride) { - for (auto& itOverride : mVehiclePropertiesOverride) { - if (itOverride.prop == cfg.prop) { - prop.value = itOverride.value; - } + if (mInitVhalValueOverride) { + for (auto& itOverride : mVehiclePropertiesOverride) { + if (itOverride.prop == cfg.prop) { + prop.status = VehiclePropertyStatus::AVAILABLE; + prop.value = itOverride.value; } } } mPropStore->writeValue(prop, shouldUpdateStatus); } } + + mVehicleClient->triggerSendAllValues(); + initObd2LiveFrame(*mPropStore->getConfigOrDie(OBD2_LIVE_FRAME)); initObd2FreezeFrame(*mPropStore->getConfigOrDie(OBD2_FREEZE_FRAME)); mInEmulator = isInEmulator(); ALOGD("mInEmulator=%s", mInEmulator ? "true" : "false"); + mRecurrentTimer.registerRecurrentEvent(kHeartBeatIntervalNs, + static_cast(VehicleProperty::VHAL_HEARTBEAT)); } std::vector EmulatedVehicleHal::listProperties() { @@ -348,6 +341,10 @@ void EmulatedVehicleHal::onContinuousPropertyTimer(const std::vector& p if (internalPropValue != nullptr) { v = pool.obtain(*internalPropValue); } + } else if (property == static_cast(VehicleProperty::VHAL_HEARTBEAT)) { + // VHAL_HEARTBEAT is not a continuous value, but it needs to be updated periodically. + // So, the update is done through onContinuousPropertyTimer. + v = doInternalHealthCheck(); } else { ALOGE("Unexpected onContinuousPropertyTimer for property: 0x%x", property); } @@ -404,8 +401,8 @@ void EmulatedVehicleHal::onPropertyValue(const VehiclePropValue& value, bool upd } void EmulatedVehicleHal::initStaticConfig() { - for (auto&& it = std::begin(kVehicleProperties); it != std::end(kVehicleProperties); ++it) { - const auto& cfg = it->config; + auto configs = mVehicleClient->getAllPropertyConfig(); + for (auto&& cfg : configs) { VehiclePropertyStore::TokenFunction tokenFunction = nullptr; switch (cfg.prop) { @@ -501,6 +498,31 @@ StatusCode EmulatedVehicleHal::fillObd2DtcInfo(VehiclePropValue* outValue) { return StatusCode::OK; } +VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::doInternalHealthCheck() { + VehicleHal::VehiclePropValuePtr v = nullptr; + + // This is an example of very simpe health checking. VHAL is considered healthy if we can read + // PERF_VEHICLE_SPEED. The more comprehensive health checking is required. + VehiclePropValue propValue = { + .prop = static_cast(VehicleProperty::PERF_VEHICLE_SPEED), + }; + auto internalPropValue = mPropStore->readValueOrNull(propValue); + if (internalPropValue != nullptr) { + v = createVhalHeartBeatProp(); + } else { + ALOGW("VHAL health check failed"); + } + return v; +} + +VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::createVhalHeartBeatProp() { + VehicleHal::VehiclePropValuePtr v = getValuePool()->obtainInt64(uptimeMillis()); + v->prop = static_cast(VehicleProperty::VHAL_HEARTBEAT); + v->areaId = 0; + v->status = VehiclePropertyStatus::AVAILABLE; + return v; +} + } // 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 eb38d7de89268414ec411ce088dc863bd7776812..7871c7b41a10f5929e1b81be5ea42a9ea0089cd8 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 @@ -29,10 +29,10 @@ #include #include "vhal_v2_0/VehiclePropertyStore.h" -#include "DefaultConfig.h" #include "EmulatedUserHal.h" #include "EmulatedVehicleConnector.h" #include "GeneratorHub.h" +#include "PropertyUtils.h" #include "VehicleEmulator.h" namespace android { @@ -82,6 +82,8 @@ private: VehiclePropValue* outValue); StatusCode fillObd2DtcInfo(VehiclePropValue* outValue); StatusCode clearObd2FreezeFrames(const VehiclePropValue& propValue); + VehicleHal::VehiclePropValuePtr doInternalHealthCheck(); + VehicleHal::VehiclePropValuePtr createVhalHeartBeatProp(); /* Private members */ VehiclePropertyStore* mPropStore; diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h new file mode 100644 index 0000000000000000000000000000000000000000..d5f6a1841e0b9f66b6086e1a410629f91de71aee --- /dev/null +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +namespace android::hardware::automotive::vehicle::V2_0::impl { + +// Some handy constants to avoid conversions from enum to int. +constexpr int ABS_ACTIVE = (int)VehicleProperty::ABS_ACTIVE; +constexpr int AP_POWER_STATE_REQ = (int)VehicleProperty::AP_POWER_STATE_REQ; +constexpr int AP_POWER_STATE_REPORT = (int)VehicleProperty::AP_POWER_STATE_REPORT; +constexpr int DOOR_1_LEFT = (int)VehicleAreaDoor::ROW_1_LEFT; +constexpr int DOOR_1_RIGHT = (int)VehicleAreaDoor::ROW_1_RIGHT; +constexpr int DOOR_2_LEFT = (int)VehicleAreaDoor::ROW_2_LEFT; +constexpr int DOOR_2_RIGHT = (int)VehicleAreaDoor::ROW_2_RIGHT; +constexpr int DOOR_REAR = (int)VehicleAreaDoor::REAR; +constexpr int WINDOW_1_LEFT = (int)VehicleAreaWindow::ROW_1_LEFT; +constexpr int WINDOW_1_RIGHT = (int)VehicleAreaWindow::ROW_1_RIGHT; +constexpr int WINDOW_2_LEFT = (int)VehicleAreaWindow::ROW_2_LEFT; +constexpr int WINDOW_2_RIGHT = (int)VehicleAreaWindow::ROW_2_RIGHT; +constexpr int WINDOW_ROOF_TOP_1 = (int)VehicleAreaWindow::ROOF_TOP_1; +constexpr int FAN_DIRECTION_FACE = (int)VehicleHvacFanDirection::FACE; +constexpr int FAN_DIRECTION_FLOOR = (int)VehicleHvacFanDirection::FLOOR; +constexpr int OBD2_LIVE_FRAME = (int)VehicleProperty::OBD2_LIVE_FRAME; +constexpr int OBD2_FREEZE_FRAME = (int)VehicleProperty::OBD2_FREEZE_FRAME; +constexpr int OBD2_FREEZE_FRAME_INFO = (int)VehicleProperty::OBD2_FREEZE_FRAME_INFO; +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)(VehicleAreaWheel::LEFT_FRONT | VehicleAreaWheel::RIGHT_FRONT | + VehicleAreaWheel::LEFT_REAR | VehicleAreaWheel::RIGHT_REAR); +constexpr int SEAT_1_LEFT = (int)(VehicleAreaSeat::ROW_1_LEFT); +constexpr int SEAT_1_RIGHT = (int)(VehicleAreaSeat::ROW_1_RIGHT); +constexpr int HVAC_LEFT = (int)(VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_2_LEFT | + VehicleAreaSeat::ROW_2_CENTER); +constexpr int HVAC_RIGHT = (int)(VehicleAreaSeat::ROW_1_RIGHT | VehicleAreaSeat::ROW_2_RIGHT); +constexpr int HVAC_ALL = HVAC_LEFT | HVAC_RIGHT; +constexpr int VENDOR_EXTENSION_BOOLEAN_PROPERTY = + (int)(0x101 | VehiclePropertyGroup::VENDOR | VehiclePropertyType::BOOLEAN | VehicleArea::DOOR); +constexpr int VENDOR_EXTENSION_FLOAT_PROPERTY = + (int)(0x102 | VehiclePropertyGroup::VENDOR | VehiclePropertyType::FLOAT | VehicleArea::SEAT); +constexpr int VENDOR_EXTENSION_INT_PROPERTY = + (int)(0x103 | VehiclePropertyGroup::VENDOR | VehiclePropertyType::INT32 | VehicleArea::WINDOW); +constexpr int VENDOR_EXTENSION_STRING_PROPERTY = + (int)(0x104 | VehiclePropertyGroup::VENDOR | VehiclePropertyType::STRING | VehicleArea::GLOBAL); +constexpr int FUEL_DOOR_REAR_LEFT = (int)PortLocationType::REAR_LEFT; +constexpr int CHARGE_PORT_FRONT_LEFT = (int)PortLocationType::FRONT_LEFT; +constexpr int CHARGE_PORT_REAR_LEFT = (int)PortLocationType::REAR_LEFT; +constexpr int LIGHT_STATE_ON = (int)VehicleLightState::ON; +constexpr int LIGHT_SWITCH_AUTO = (int)VehicleLightSwitch::AUTOMATIC; +constexpr int WHEEL_FRONT_LEFT = (int)VehicleAreaWheel::LEFT_FRONT; +constexpr int WHEEL_FRONT_RIGHT = (int)VehicleAreaWheel::RIGHT_FRONT; +constexpr int WHEEL_REAR_LEFT = (int)VehicleAreaWheel::LEFT_REAR; +constexpr int WHEEL_REAR_RIGHT = (int)VehicleAreaWheel::RIGHT_REAR; + +/** + * This property is used for test purpose to generate fake events. Here is the test package that + * is referencing this property definition: packages/services/Car/tests/vehiclehal_test + */ +const int32_t kGenerateFakeDataControllingProperty = + 0x0666 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::MIXED; + +/** + * This property is used for test purpose to set properties' value from vehicle. + * For example: Mocking hard button press triggering a HVAC fan speed change. + * Android set kSetPropertyFromVehicleForTest with an array of integer {HVAC_FAN_SPEED, value of + * fan speed} and a long value indicates the timestamp of the events . + * It only works with integer type properties. + */ +const int32_t kSetIntPropertyFromVehicleForTest = + 0x1112 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::MIXED; +/** + * This property is used for test purpose to set properties' value from vehicle. + * It only works with float type properties. + */ +const int32_t kSetFloatPropertyFromVehicleForTest = + 0x1113 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::MIXED; +/** + * This property is used for test purpose to set properties' value from vehicle. + * It only works with boolean type properties. + */ +const int32_t kSetBooleanPropertyFromVehicleForTest = + 0x1114 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::MIXED; + +/** + * This property is used for test purpose. End to end tests use this property to test set and get + * method for MIXED type properties. + */ +const int32_t kMixedTypePropertyForTest = + 0x1111 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::MIXED; + +#ifdef ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING +/** + * Converts the system property to the vendor property. + * WARNING: This is only for the end-to-end testing, Should NOT include in the + * user build */ +inline constexpr int32_t toVendor(VehicleProperty prop) { + return (toInt(prop) & ~toInt(VehiclePropertyGroup::MASK)) | VehiclePropertyGroup::VENDOR; +} + +/** + * These properties are used for the end-to-end testing of ClusterHomeService. + */ +constexpr int32_t VENDOR_CLUSTER_SWITCH_UI = toVendor(VehicleProperty::CLUSTER_SWITCH_UI); +constexpr int32_t VENDOR_CLUSTER_DISPLAY_STATE = toVendor(VehicleProperty::CLUSTER_DISPLAY_STATE); +constexpr int32_t VENDOR_CLUSTER_REPORT_STATE = toVendor(VehicleProperty::CLUSTER_REPORT_STATE); +constexpr int32_t VENDOR_CLUSTER_REQUEST_DISPLAY = + toVendor(VehicleProperty::CLUSTER_REQUEST_DISPLAY); +constexpr int32_t VENDOR_CLUSTER_NAVIGATION_STATE = + toVendor(VehicleProperty::CLUSTER_NAVIGATION_STATE); +#endif // ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING + +/** + * FakeDataCommand enum defines the supported command type for kGenerateFakeDataControllingProperty. + * All those commands can be send independently with each other. And each will override the one sent + * previously. + * + * The controlling property has the following format: + * + * int32Values[0] - command enum defined in FakeDataCommand + * + * The format of the arguments is defined for each command type as below: + */ +enum class FakeDataCommand : int32_t { + /** + * Starts linear fake data generation. Caller must provide additional data: + * int32Values[1] - vehicle property to which command applies + * int64Values[0] - periodic interval in nanoseconds + * floatValues[0] - initial value + * floatValues[1] - dispersion defines the min/max value relative to initial value, where + * max = initial_value + dispersion, min = initial_value - dispersion. + * Dispersion should be non-negative, otherwise the behavior is undefined. + * floatValues[2] - increment, with every timer tick the value will be incremented by this + * amount. When reaching to max value, the current value will be set to + * min. It should be non-negative, otherwise the behavior is undefined. + */ + StartLinear = 0, + + /** Stops linear fake data generation that was triggered by StartLinear commands. + * int32Values[1] - vehicle property to which command applies. VHAL will stop the + * corresponding linear generation for that property. + */ + StopLinear = 1, + + /** + * Starts JSON-based fake data generation. It iterates through JSON-encoded VHAL events from a + * file and inject them to VHAL. The iteration can be repeated multiple times or infinitely. + * Caller must provide additional data: + * int32Values[1] - number of iterations. If it is not provided or -1. The iteration will be + * repeated infinite times. + * stringValue - path to the fake values JSON file + */ + StartJson = 2, + + /** + * Stops JSON-based fake data generation. As multiple JSON-based generation can happen at the + * same time. Caller must provide the path of fake value JSON file to stop the corresponding + * generation: + * stringValue - path to the fake values JSON file + */ + StopJson = 3, + + /** + * Injects key press event (HAL incorporates UP/DOWN acction and triggers 2 HAL events for every + * key-press). We set the enum with high number to leave space for future start/stop commands. + * Caller must provide the following data: + * int32Values[2] - Android key code + * int32Values[3] - target display (0 - for main display, 1 - for instrument cluster, see + * VehicleDisplay) + */ + KeyPress = 100, +}; + +const int32_t kHvacPowerProperties[] = { + toInt(VehicleProperty::HVAC_FAN_SPEED), + toInt(VehicleProperty::HVAC_FAN_DIRECTION), +}; + +} // namespace android::hardware::automotive::vehicle::V2_0::impl diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.h index 6559e2aa8446619746c0728bb7d6d65a3f40dfd0..81dfca1b06fcbddacb1d9f98e467d0b92aaa79e8 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.h +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.h @@ -27,6 +27,10 @@ class VehicleHalClient : public IVehicleClient { // Type of callback function for handling the new property values using PropertyCallBackType = std::function; + // The server will call sendAllValuesToClient, onPropertyValue will be called when values are + // received. + virtual void triggerSendAllValues() = 0; + // Method from IVehicleClient void onPropertyValue(const VehiclePropValue& value, bool updateStatus) override; diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp index 0ee183596a0772cb13a7f7144de6edc752bc8a2e..57dd7d42155dacd13099d24b299f56c46e2d3388 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp @@ -30,6 +30,66 @@ namespace android::hardware::automotive::vehicle::V2_0::impl { +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; +} + +VehicleHalServer::VehicleHalServer() { + constexpr bool shouldUpdateStatus = true; + + for (auto& it : kVehicleProperties) { + VehiclePropConfig cfg = it.config; + + mServerSidePropStore.registerProperty(cfg); + + if (isDiagnosticProperty(cfg)) { + continue; + } + + // A global property will have only a single area + int32_t numAreas = isGlobalProp(cfg.prop) ? 1 : cfg.areaConfigs.size(); + + for (int i = 0; i < numAreas; i++) { + int32_t curArea = isGlobalProp(cfg.prop) ? 0 : cfg.areaConfigs[i].areaId; + + // Create a separate instance for each individual zone + VehiclePropValue prop = { + .areaId = curArea, + .prop = cfg.prop, + }; + + if (it.initialAreaValues.empty()) { + prop.value = it.initialValue; + } else if (auto valueForAreaIt = it.initialAreaValues.find(curArea); + valueForAreaIt != it.initialAreaValues.end()) { + prop.value = valueForAreaIt->second; + } else { + LOG(WARNING) << __func__ << " failed to get default value for" + << " prop 0x" << std::hex << cfg.prop << " area 0x" << std::hex + << curArea; + prop.status = VehiclePropertyStatus::UNAVAILABLE; + } + + mServerSidePropStore.writeValue(prop, shouldUpdateStatus); + } + } +} + +void VehicleHalServer::sendAllValuesToClient() { + constexpr bool update_status = true; + auto values = mServerSidePropStore.readAllValues(); + for (const auto& value : values) { + onPropertyValueFromCar(value, update_status); + } +} + GeneratorHub* VehicleHalServer::getGenerator() { return &mGeneratorHub; } @@ -55,19 +115,13 @@ void VehicleHalServer::onFakeValueGenerated(const VehiclePropValue& value) { if (updatedPropValue) { updatedPropValue->timestamp = value.timestamp; updatedPropValue->status = VehiclePropertyStatus::AVAILABLE; + mServerSidePropStore.writeValue(*updatedPropValue, updateStatus); onPropertyValueFromCar(*updatedPropValue, updateStatus); } } std::vector VehicleHalServer::onGetAllPropertyConfig() const { - std::vector vehiclePropConfigs; - constexpr size_t numOfVehiclePropConfigs = - sizeof(kVehicleProperties) / sizeof(kVehicleProperties[0]); - vehiclePropConfigs.reserve(numOfVehiclePropConfigs); - for (auto& it : kVehicleProperties) { - vehiclePropConfigs.emplace_back(it.config); - } - return vehiclePropConfigs; + return mServerSidePropStore.getAllConfigs(); } StatusCode VehicleHalServer::handleGenerateFakeDataRequest(const VehiclePropValue& request) { @@ -247,6 +301,28 @@ StatusCode VehicleHalServer::onSetProperty(const VehiclePropValue& value, bool u break; } break; + +#ifdef ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING + case toInt(VehicleProperty::CLUSTER_REPORT_STATE): + case toInt(VehicleProperty::CLUSTER_REQUEST_DISPLAY): + case toInt(VehicleProperty::CLUSTER_NAVIGATION_STATE): + case VENDOR_CLUSTER_SWITCH_UI: + case VENDOR_CLUSTER_DISPLAY_STATE: { + auto updatedPropValue = createVehiclePropValue(getPropType(value.prop), 0); + updatedPropValue->prop = value.prop & ~toInt(VehiclePropertyGroup::MASK); + if (isSystemProperty(value.prop)) { + updatedPropValue->prop |= toInt(VehiclePropertyGroup::VENDOR); + } else { + updatedPropValue->prop |= toInt(VehiclePropertyGroup::SYSTEM); + } + updatedPropValue->value = value.value; + updatedPropValue->timestamp = elapsedRealtimeNano(); + updatedPropValue->areaId = value.areaId; + onPropertyValueFromCar(*updatedPropValue, updateStatus); + return StatusCode::OK; + } +#endif // ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING + default: break; } @@ -256,6 +332,7 @@ StatusCode VehicleHalServer::onSetProperty(const VehiclePropValue& value, bool u auto updatedPropValue = getValuePool()->obtain(value); updatedPropValue->timestamp = elapsedRealtimeNano(); + mServerSidePropStore.writeValue(*updatedPropValue, updateStatus); onPropertyValueFromCar(*updatedPropValue, updateStatus); return StatusCode::OK; } diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h index 117eadb1e20e096ba9c22372e1706b96745115c6..be88cd94cd26b11bcc36fecb717743b46238b836 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h @@ -17,6 +17,7 @@ #pragma once #include +#include #include #include "GeneratorHub.h" @@ -28,6 +29,10 @@ namespace android::hardware::automotive::vehicle::V2_0::impl { // scenario, the server may be run on a different OS than Android. class VehicleHalServer : public IVehicleServer { public: + VehicleHalServer(); + + void sendAllValuesToClient(); + // Methods from IVehicleServer std::vector onGetAllPropertyConfig() const override; @@ -58,6 +63,7 @@ class VehicleHalServer : public IVehicleServer { std::bind(&VehicleHalServer::onFakeValueGenerated, this, std::placeholders::_1)}; VehiclePropValuePool* mValuePool{nullptr}; + VehiclePropertyStore mServerSidePropStore; }; } // namespace android::hardware::automotive::vehicle::V2_0::impl diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal index f7a42e959b14639cb5a486dc8803279e64719bbc..6bfda329830d71614f95c1440dae7cfb3674c6d4 100644 --- a/automotive/vehicle/2.0/types.hal +++ b/automotive/vehicle/2.0/types.hal @@ -354,6 +354,12 @@ enum VehicleProperty : int32_t { /** * Speed of the vehicle * + * The value must be positive when the vehicle is moving forward and negative when + * the vehicle is moving backward. This value is independent of gear value + * (CURRENT_GEAR or GEAR_SELECTION), for example, if GEAR_SELECTION is GEAR_NEUTRAL, + * PERF_VEHICLE_SPEED is positive when the vehicle is moving forward, negative when moving + * backward, and zero when not moving. + * * @change_mode VehiclePropertyChangeMode:CONTINUOUS * @access VehiclePropertyAccess:READ * @unit VehicleUnit:METER_PER_SEC @@ -634,6 +640,25 @@ enum VehicleProperty : int32_t { | VehiclePropertyType:FLOAT | VehicleArea:WHEEL), + /** + * Critically low tire pressure + * + * This property indicates the critically low pressure threshold for each tire. + * It indicates when it is time for tires to be replaced or fixed. The value + * must be less than or equal to minFloatValue in TIRE_PRESSURE. + * Minimum and maximum property values (that is, minFloatValue, maxFloatValue) + * are not applicable to this property. + * + * @change_mode VehiclePropertyChangeMode:STATIC + * @access VehiclePropertyAccess:READ + * @unit VehicleUnit:KILOPASCAL + */ + CRITICALLY_LOW_TIRE_PRESSURE = ( + 0x030A + | VehiclePropertyGroup:SYSTEM + | VehiclePropertyType:FLOAT + | VehicleArea:WHEEL), + /** * Currently selected gear * @@ -682,7 +707,7 @@ enum VehicleProperty : int32_t { * Parking brake state. * * @change_mode VehiclePropertyChangeMode:ON_CHANGE - * @access VehiclePropertyAccess:READ_WRITE + * @access VehiclePropertyAccess:READ */ PARKING_BRAKE_ON = ( 0x0402 @@ -694,7 +719,7 @@ enum VehicleProperty : int32_t { * Auto-apply parking brake. * * @change_mode VehiclePropertyChangeMode:ON_CHANGE - * @access VehiclePropertyAccess:READ_WRITE + * @access VehiclePropertyAccess:READ */ PARKING_BRAKE_AUTO_APPLY = ( 0x0403 @@ -875,6 +900,24 @@ enum VehicleProperty : int32_t { /** * HVAC, target temperature set. * + * The configArray is used to indicate the valid values for HVAC in Fahrenheit and Celsius. + * Android might use it in the HVAC app UI. + * The configArray is set as follows: + * configArray[0] = [the lower bound of the supported temperature in Celsius] * 10. + * configArray[1] = [the upper bound of the supported temperature in Celsius] * 10. + * configArray[2] = [the increment in Celsius] * 10. + * configArray[3] = [the lower bound of the supported temperature in Fahrenheit] * 10. + * configArray[4] = [the upper bound of the supported temperature in Fahrenheit] * 10. + * configArray[5] = [the increment in Fahrenheit] * 10. + * For example, if the vehicle supports temperature values as: + * [16.0, 16.5, 17.0 ,..., 28.0] in Celsius + * [60.5, 61.5, 62.5 ,..., 85.5] in Fahrenheit. + * The configArray should be configArray = {160, 280, 5, 605, 825, 10}. + * + * If the vehicle supports HVAC_TEMPERATURE_VALUE_SUGGESTION, the application can use + * that property to get the suggested value before setting HVAC_TEMPERATURE_SET. Otherwise, + * the application may choose the value in HVAC_TEMPERATURE_SET configArray by itself. + * * @change_mode VehiclePropertyChangeMode:ON_CHANGE * @access VehiclePropertyAccess:READ_WRITE * @unit VehicleUnit:CELSIUS @@ -1223,6 +1266,50 @@ enum VehicleProperty : int32_t { | VehiclePropertyType:BOOLEAN | VehicleArea:WINDOW), + /** + * Suggested values for setting HVAC temperature. + * + * Implement the property to help applications understand the closest supported temperature + * value in Celsius or Fahrenheit. + * + * floatValues[0] = the requested value that an application wants to set a temperature to. + * floatValues[1] = the unit for floatValues[0]. It should be one of + * {VehicleUnit:CELSIUS, VehicleUnit:FAHRENHEIT}. + * floatValues[2] = the value OEMs suggested in CELSIUS. This value is not included + * in the request. + * floatValues[3] = the value OEMs suggested in FAHRENHEIT. This value is not included + * in the request. + * + * An application calls set(VehiclePropValue propValue) with the requested value and unit for + * the value. OEMs need to return the suggested values in floatValues[2] and floatValues[3] by + * onPropertyEvent() callbacks. + * + * For example, when a user uses the voice assistant to set HVAC temperature to 66.2 in + * Fahrenheit. + * First, an application will set this property with the value + * [66.2, (float)VehicleUnit:FAHRENHEIT,0,0]. + * If OEMs suggest to set 19.0 in Celsius or 66.5 in Fahrenheit for user's request, then VHAL + * must generate a callback with property value + * [66.2, (float)VehicleUnit:FAHRENHEIT, 19.0, 66.5]. After the voice assistant gets the + * callback, it will inform the user and set HVAC temperature to the suggested value. + * + * Another example, an application receives 21 Celsius as the current temperature value by + * querying HVC_TEMPERATURE_SET. But the application wants to know what value is displayed on + * the car's UI in Fahrenheit. + * For this, the application sets the property to [21, (float)VehicleUnit:CELSIUS, 0, 0]. If + * the suggested value by the OEM for 21 Celsius is 70 Fahrenheit, then VHAL must generate a + * callback with property value [21, (float)VehicleUnit:CELSIUS, 21.0, 70.0]. + * In this case, the application can know that the value is 70.0 Fahrenheit in the car’s UI. + * + * @change_mode VehiclePropertyChangeMode:ON_CHANGE + * @access VehiclePropertyAccess:READ_WRITE + */ + HVAC_TEMPERATURE_VALUE_SUGGESTION = ( + 0x0515 + | VehiclePropertyGroup:SYSTEM + | VehiclePropertyType:FLOAT_VEC + | VehicleArea:GLOBAL), + /** * Distance units for display * @@ -1341,6 +1428,48 @@ enum VehicleProperty : int32_t { | VehiclePropertyType:INT32 | VehicleArea:GLOBAL), + /** + * Current date and time, encoded as Unix time (in milliseconds). + * This value denotes the number of milliseconds seconds that have + * elapsed since 1/1/1970 UTC. + * + * Reading this value will give you the system’s time. This can be + * useful to synchronize other vehicle systems (dash clock etc). + * + * Writing this value will update the ‘ExternalTimeSuggestion’ + * value (if enabled). This value may be consumed by the “Time + * Detector Service”, if other sources do not have a higher + * priority. For information on how to adjust time source + * priorities see Time Detector Service documentation. + * + * @change_mode VehiclePropertyChangeMode:ON_CHANGE + * @access VehiclePropertyAccess:READ_WRITE + * @unit VehicleUnit:MILLI_SECS + */ + EPOCH_TIME = ( + 0x0606 + | VehiclePropertyGroup:SYSTEM + | VehiclePropertyType:INT64 + | VehicleArea:GLOBAL), + + /** + * External encryption binding seed. + * + * This value is mixed with the local key storage encryption key. + * This property holds 16 bytes, and is expected to be persisted on an ECU separate from + * the IVI. The property is initially set by AAOS, who generates it using a CSRNG. + * AAOS will then read the property on subsequent boots. The binding seed is expected to be + * reliably persisted. Any loss of the seed results in a factory reset of the IVI. + * + * @change_mode VehiclePropertyChangeMode:ON_CHANGE + * @access VehiclePropertyAccess:READ_WRITE + */ + STORAGE_ENCRYPTION_BINDING_SEED = ( + 0x0607 + | VehiclePropertyGroup:SYSTEM + | VehiclePropertyType:BYTES + | VehicleArea:GLOBAL), + /** * Outside temperature * @@ -1480,6 +1609,33 @@ enum VehicleProperty : int32_t { | VehiclePropertyType:INT32_VEC | VehicleArea:GLOBAL), + /** + * Defines a custom OEM partner input event. + * + * This input event must be used by OEM partners who wish to propagate events not supported + * by Android. It is composed by an array of int32 values only. + * + * The Android properties are: + * + * int32Values[0] : Input code identifying the function representing this event. Valid event + * types are defined by CustomInputType.CUSTOM_EVENT_F1 up to + * CustomInputType.CUSTOM_EVENT_F10. They represent the custom event to be + * defined by OEM partners. + * int32Values[1] : target display type defined in VehicleDisplay. Events not tied to specific + * display must be sent to VehicleDisplay#MAIN. + * int32Values[2] : repeat counter, if 0 then event is not repeated. Values 1 or above means + * how many times this event repeated. + * + * @change_mode VehiclePropertyChangeMode:ON_CHANGE + * @data_enum CustomInputType + * @access VehiclePropertyAccess:READ + */ + HW_CUSTOM_INPUT = ( + 0X0A30 + | VehiclePropertyGroup:SYSTEM + | VehiclePropertyType:INT32_VEC + | VehicleArea:GLOBAL), + /*************************************************************************** * Most Car Cabin properties have both a POSition and MOVE parameter. These * are used to control the various movements for seats, doors, and windows @@ -2746,7 +2902,7 @@ enum VehicleProperty : int32_t { * * int32[0]: 42 // request id * int32[1]: 11 // Android id of the created user - * int32[2]: 3 // Android flags (ephemeral guest) of the created user + * int32[2]: 6 // Android flags (ephemeral guest) of the created user * int32[3]: 10 // current user * int32[4]: 0 // current user flags (none) * int32[5]: 3 // number of users @@ -2755,7 +2911,7 @@ enum VehicleProperty : int32_t { * int32[8]: 10 // 2nd user (user 10) * int32[9]: 0 // 2nd user flags (none) * int32[19]: 11 // 3rd user (user 11) - * int32[11]: 3 // 3rd user flags (ephemeral guest) + * int32[11]: 6 // 3rd user flags (ephemeral guest) * string: "ElGuesto" // name of the new user * * Then if the request succeeded, the HAL would return: @@ -2892,6 +3048,314 @@ enum VehicleProperty : int32_t { | VehiclePropertyGroup:SYSTEM | VehiclePropertyType:MIXED | VehicleArea:GLOBAL), + + /** + * Enable/request an EVS service. + * + * The property provides a generalized way to trigger EVS services. VHAL + * should use this property to request Android to start or stop EVS service. + * + * int32Values[0] = a type of the EVS service. The value must be one of enums in + * EvsServiceType. + * int32Values[1] = the state of the EVS service. The value must be one of enums in + * EvsServiceState. + * + * For example, to enable rear view EVS service, android side can set the property value as + * [EvsServiceType::REAR_VIEW, EvsServiceState::ON]. + * + * @change_mode VehiclePropertyChangeMode:ON_CHANGE + * @access VehiclePropertyAccess:READ + */ + EVS_SERVICE_REQUEST = ( + 0x0F10 + | VehiclePropertyGroup:SYSTEM + | VehiclePropertyType:INT32_VEC + | VehicleArea:GLOBAL), + + /** + * Defines a request to apply power policy. + * + * VHAL sets this property to change car power policy. Car power policy service subscribes to + * this property and actually changes the power policy. + * The request is made by setting the VehiclePropValue with the ID of a power policy which is + * defined at /vendor/etc/power_policy.xml. If the given ID is not defined, car power policy + * service ignores the request and the current power policy is maintained. + * + * string: "sample_policy_id" // power policy ID + * + * @change_mode VehiclePropertyChangeMode:ON_CHANGE + * @access VehiclePropertyAccess:READ + */ + POWER_POLICY_REQ = ( + 0x0F21 + | VehiclePropertyGroup:SYSTEM + | VehiclePropertyType:STRING + | VehicleArea:GLOBAL), + + /** + * Defines a request to set the power polic group used to decide a default power policy per + * power status transition. + * + * VHAL sets this property with the ID of a power policy group in order to set the default power + * policy applied at power status transition. Power policy groups are defined at + * /vendor/etc/power_policy.xml. If the given ID is not defined, car power policy service + * ignores the request. + * Car power policy service subscribes to this property and sets the power policy group. + * The actual application of power policy takes place when the system power status changes and + * there is a valid mapped power policy for the new power status. + * + * string: "sample_policy_group_id" // power policy group ID + * + * @change_mode VehiclePropertyChangeMode:ON_CHANGE + * @access VehiclePropertyAccess:READ + */ + POWER_POLICY_GROUP_REQ = ( + 0x0F22 + | VehiclePropertyGroup:SYSTEM + | VehiclePropertyType:STRING + | VehicleArea:GLOBAL), + + /** + * Notifies the current power policy to VHAL layer. + * + * Car power policy service sets this property when the current power policy is changed. + * + * string: "sample_policy_id" // power policy ID + * + * @change_mode VehiclePropertyChangeMode:ON_CHANGE + * @access VehiclePropertyAccess:READ_WRITE + */ + CURRENT_POWER_POLICY = ( + 0x0F23 + | VehiclePropertyGroup:SYSTEM + | VehiclePropertyType:STRING + | VehicleArea:GLOBAL), + + /** + * Defines an event that car watchdog updates to tell it's alive. + * + * Car watchdog sets this property to system uptime in milliseconds at every 3 second. + * During the boot, the update may take longer time. + * + * @change_mode VehiclePropertyChangeMode:ON_CHANGE + * @access VehiclePropertyAccess:WRITE + */ + WATCHDOG_ALIVE = ( + 0xF31 + | VehiclePropertyGroup:SYSTEM + | VehiclePropertyType:INT64 + | VehicleArea:GLOBAL), + + /** + * Defines a process terminated by car watchdog and the reason of termination. + * + * int32Values[0]: 1 // ProcessTerminationReason showing why a process is terminated. + * string: "/system/bin/log" // Process execution command. + * + * @change_mode VehiclePropertyChangeMode:ON_CHANGE + * @access VehiclePropertyAccess:WRITE + */ + WATCHDOG_TERMINATED_PROCESS = ( + 0x0F32 + | VehiclePropertyGroup:SYSTEM + | VehiclePropertyType:MIXED + | VehicleArea:GLOBAL), + + /** + * Defines an event that VHAL signals to car watchdog as a heartbeat. + * + * If VHAL supports this property, VHAL should write system uptime to this property at every 3 + * second. Car watchdog subscribes to this property and checks if the property is updated at + * every 3 second. With the buffer time of 3 second, car watchdog waits for a heart beat to be + * signaled up to 6 seconds from the last heart beat. If it isn’t, car watchdog considers + * VHAL unhealthy and terminates it. + * If this property is not supported by VHAL, car watchdog doesn't check VHAL health status. + * + * @change_mode VehiclePropertyChangeMode:ON_CHANGE + * @access VehiclePropertyAccess:READ + */ + VHAL_HEARTBEAT = ( + 0x0F33 + | VehiclePropertyGroup:SYSTEM + | VehiclePropertyType:INT64 + | VehicleArea:GLOBAL), + + /** + * Starts the ClusterUI in cluster display. + * + * int32: the type of ClusterUI to show + * 0 indicates ClusterHome, that is a home screen of cluster display, and provides + * the default UI and a kind of launcher functionality for cluster display. + * the other values are followed by OEM's definition. + * + * @change_mode VehiclePropertyChangeMode:ON_CHANGE + * @access VehiclePropertyAccess:READ + */ + CLUSTER_SWITCH_UI = ( + 0x0F34 + | VehiclePropertyGroup:SYSTEM + | VehiclePropertyType:INT32 + | VehicleArea:GLOBAL), + + /** + * Changes the state of the cluster display. + * + * Bounds: the area to render the cluster Activity. + * Inset: the area which Activity should avoid from placing any important + * information. + * + * int32[0]: on/off: 0 - off, 1 - on, -1 - don't care + * int32[1]: Bounds - left: positive number - left position in pixels + -1 - don't care (should set all Bounds fields) + * int32[2]: Bounds - top: same format with 'left' + * int32[3]: Bounds - right: same format with 'left' + * int32[4]: Bounds - bottom: same format with 'left' + * int32[5]: Inset - left: positive number - actual left inset value in pixels + -1 - don't care (should set "don't care" all Inset fields) + * int32[6]: Inset - top: same format with 'left' + * int32[7]: Inset - right: same format with 'left' + * int32[8]: Inset - bottom: same format with 'left' + * + * @change_mode VehiclePropertyChangeMode:ON_CHANGE + * @access VehiclePropertyAccess:READ + */ + CLUSTER_DISPLAY_STATE = ( + 0x0F35 + | VehiclePropertyGroup:SYSTEM + | VehiclePropertyType:INT32_VEC + | VehicleArea:GLOBAL), + + /** + * Reports the current display state and ClusterUI state. + * + * ClusterHome will send this message when it handles CLUSTER_SWITCH_UI, CLUSTER_DISPLAY_STATE. + * + * In addition, ClusterHome should send this message when it starts for the first time. + * When ClusterOS receives this message and if the internal expectation is different with the + * received message, then it should send CLUSTER_SWITCH_UI, CLUSTER_DISPLAY_STATE again to + * match the state. + * + * int32[0]: on/off: 0 - off, 1 - on + * int32[1]: Bounds - left + * int32[2]: Bounds - top + * int32[3]: Bounds - right + * int32[4]: Bounds - bottom + * int32[5]: Inset - left + * int32[6]: Inset - top + * int32[7]: Inset - right + * int32[8]: Inset - bottom + * int32[9]: the type of ClusterUI in the fullscreen or main screen. + * 0 indicates ClusterHome. + * the other values are followed by OEM's definition. + * int32[10]: the type of ClusterUI in sub screen if the currently two UIs are shown. + * -1 indicates the area isn't used any more. + * bytes: the array to represent the availability of ClusterUI. + * 0 indicates non-available and 1 indicates available. + * For example, let's assume a car supports 3 OEM defined ClusterUI like HOME, MAPS, CALL, + * and it only supports CALL UI only when the cellular network is available. Then, if the + * nework is avaibale, it'll send [1 1 1], and if it's out of network, it'll send [1 1 0]. + * + * @change_mode VehiclePropertyChangeMode:ON_CHANGE + * @access VehiclePropertyAccess:WRITE + */ + CLUSTER_REPORT_STATE = ( + 0x0F36 + | VehiclePropertyGroup:SYSTEM + | VehiclePropertyType:MIXED + | VehicleArea:GLOBAL), + + /** + * Requests to change the cluster display state to show some ClusterUI. + * + * When the current display state is off and ClusterHome sends this message to ClusterOS to + * request to turn the display on to show some specific ClusterUI. + * ClusterOS should response this with CLUSTER_DISPLAY_STATE. + * + * int32: the type of ClusterUI to show + * + * @change_mode VehiclePropertyChangeMode:ON_CHANGE + * @access VehiclePropertyAccess:WRITE + */ + CLUSTER_REQUEST_DISPLAY = ( + 0x0F37 + | VehiclePropertyGroup:SYSTEM + | VehiclePropertyType:INT32 + | VehicleArea:GLOBAL), + + /** + * Informs the current navigation state. + * + * bytes: the serialized message of NavigationStateProto. + * + * @change_mode VehiclePropertyChangeMode:ON_CHANGE + * @access VehiclePropertyAccess:WRITE + */ + CLUSTER_NAVIGATION_STATE = ( + 0x0F38 + | VehiclePropertyGroup:SYSTEM + | VehiclePropertyType:BYTES + | VehicleArea:GLOBAL), + + /** + * Electronic Toll Collection card type. + * + * This property indicates the type of ETC card in this vehicle. + * If the head unit is aware of an ETC card attached to the vehicle, this property should + * return the type of card attached; otherwise, this property should be UNAVAILABLE. + * + * @change_mode VehiclePropertyChangeMode:ON_CHANGE + * @access VehiclePropertyAccess:READ + * @data_enum ElectronicTollCollectionCardType + */ + ELECTRONIC_TOLL_COLLECTION_CARD_TYPE = ( + 0x0F39 + | VehiclePropertyGroup:SYSTEM + | VehiclePropertyType:INT32 + | VehicleArea:GLOBAL), + + /** + * Electronic Toll Collection card status. + * + * This property indicates the status of ETC card in this vehicle. + * If the head unit is aware of an ETC card attached to the vehicle, + * ELECTRONIC_TOLL_COLLECTION_CARD_TYPE gives that status of the card; otherwise, + * this property should be UNAVAILABLE. + * + * @change_mode VehiclePropertyChangeMode:ON_CHANGE + * @access VehiclePropertyAccess:READ + * @data_enum ElectronicTollCollectionCardStatus + */ + ELECTRONIC_TOLL_COLLECTION_CARD_STATUS = ( + 0x0F3A + | VehiclePropertyGroup:SYSTEM + | VehiclePropertyType:INT32 + | VehicleArea:GLOBAL), +}; + +/** + * Used by ELECTRONIC_TOLL_COLLECTION_CARD_TYPE. + */ +enum ElectronicTollCollectionCardType : int32_t { + // Type is unknown or not in the list below. + UNKNOWN = 0, + // A Japanese ETC card reader that does not support ETC 2.0. + JP_ELECTRONIC_TOLL_COLLECTION_CARD = 1, + // A Japanese ETC 2.0 card reader. + JP_ELECTRONIC_TOLL_COLLECTION_CARD_V2 = 2, +}; + +/** + * Used by ELECTRONIC_TOLL_COLLECTION_CARD_STATUS. + */ +enum ElectronicTollCollectionCardStatus : int32_t { + // Status could not be determined + UNKNOWN = 0, + // A valid ETC card is present + ELECTRONIC_TOLL_COLLECTION_CARD_VALID = 1, + // An ETC card is present, but it is expired or otherwise invalid + ELECTRONIC_TOLL_COLLECTION_CARD_INVALID = 2, + // No ETC card is inserted in the reader. + ELECTRONIC_TOLL_COLLECTION_CARD_NOT_INSERTED = 3, }; /** @@ -2962,6 +3426,33 @@ enum VehicleSeatOccupancyState : int32_t { OCCUPIED = 2 }; +/** + * Used by EVS_SERVICE_REQUEST to enumerate the service's type. + */ +enum EvsServiceType : int32_t { + + REARVIEW = 0, + SURROUNDVIEW = 1, +}; + +/** + * Used by EVS_SERVICE_REQUEST to enumerate the service's state. + */ +enum EvsServiceState : int32_t { + + OFF = 0, + ON = 1, +}; + +/** + * Index in int32VAlues for VehicleProperty#EVS_SERVICE_REQUEST property. + */ +enum EvsServiceRequestIndex : int32_t { + + TYPE = 0, + STATE = 1, +}; + /** * Used by lights state properties to enumerate the current state of the lights. * @@ -3323,6 +3814,7 @@ enum VehicleUnit : int32_t { US_GALLON = 0x42, IMPERIAL_GALLON = 0x43, NANO_SECS = 0x50, + MILLI_SECS = 0x51, SECS = 0x53, YEAR = 0x59, @@ -3556,7 +4048,10 @@ struct VehiclePropConfig { * events. */ struct VehiclePropValue { - /** Time is elapsed nanoseconds since boot */ + /** + * Time is elapsed nanoseconds since boot. It's equivalent to + * {@code SystemClock.elapsedRealtimeNano()}. + */ int64_t timestamp; /** @@ -4790,3 +5285,46 @@ enum RotaryInputType : int32_t { ROTARY_INPUT_TYPE_AUDIO_VOLUME = 1, }; +/** + * The reason why a process is terminated by car watchdog. + * This is used with WATCHDOG_TERMINATED_PROCESS property. + */ +enum ProcessTerminationReason : int32_t { + /** + * A process doesn't respond to car watchdog within the timeout. + */ + NOT_RESPONDING = 1, + + /** + * A process uses more IO operations than what is allowed. + */ + IO_OVERUSE = 2, + + /** + * A process uses more memory space than what is allowed. + */ + MEMORY_OVERUSE = 3, +}; + +/** + * Input code values for HW_CUSTOM_INPUT. + */ +enum CustomInputType : int32_t { + /** + * Ten functions representing the custom input code to be defined and implemented by OEM + * partners. + * + * OEMs need to formally contact Android team if more than 10 functions are required. + */ + CUSTOM_EVENT_F1 = 1001, + CUSTOM_EVENT_F2 = 1002, + CUSTOM_EVENT_F3 = 1003, + CUSTOM_EVENT_F4 = 1004, + CUSTOM_EVENT_F5 = 1005, + CUSTOM_EVENT_F6 = 1006, + CUSTOM_EVENT_F7 = 1007, + CUSTOM_EVENT_F8 = 1008, + CUSTOM_EVENT_F9 = 1009, + CUSTOM_EVENT_F10 = 1010, +}; + diff --git a/automotive/vehicle/2.0/vts/functional/Android.bp b/automotive/vehicle/2.0/vts/functional/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..e64e942a0ebc9cbf8137565e5fb3d7c83c8f40c2 --- /dev/null +++ b/automotive/vehicle/2.0/vts/functional/Android.bp @@ -0,0 +1,30 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_test { + name: "VtsHalAutomotiveVehicleV2_0TargetTest", + defaults: [ + "VtsHalTargetTestDefaults", + ], + srcs: [ + "VtsHalAutomotiveVehicleV2_0TargetTest.cpp", + ], + shared_libs: [ + "libbase", + "libhidlbase", + "liblog", + ], + static_libs: [ + "android.hardware.automotive.vehicle@2.0", + ], + test_suites: [ + "vts", + "general-tests", + ], +} diff --git a/automotive/vehicle/2.0/vts/functional/VtsHalAutomotiveVehicleV2_0TargetTest.cpp b/automotive/vehicle/2.0/vts/functional/VtsHalAutomotiveVehicleV2_0TargetTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8adec8486f2b99ac3c2d77b39aa1f5ec6a155078 --- /dev/null +++ b/automotive/vehicle/2.0/vts/functional/VtsHalAutomotiveVehicleV2_0TargetTest.cpp @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "VtsHalAutomotiveVehicle" + +#include +#include +#include + +#include +#include +#include + +using namespace android::hardware::automotive::vehicle::V2_0; +using ::android::sp; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; + +constexpr auto kTimeout = std::chrono::milliseconds(500); +constexpr auto kInvalidProp = 0x31600207; + +class VtsVehicleCallback : public IVehicleCallback { + private: + using MutexGuard = std::lock_guard; + using HidlVecOfValues = hidl_vec; + std::mutex mLock; + std::condition_variable mEventCond; + std::vector mReceivedEvents; + + public: + Return onPropertyEvent(const hidl_vec& values) override { + { + MutexGuard guard(mLock); + mReceivedEvents.push_back(values); + } + mEventCond.notify_one(); + return Return(); + } + + Return onPropertySet(const VehiclePropValue& /* value */) override { + return Return(); + } + Return onPropertySetError(StatusCode /* errorCode */, int32_t /* propId */, + int32_t /* areaId */) override { + return Return(); + } + + bool waitForExpectedEvents(size_t expectedEvents) { + std::unique_lock g(mLock); + + if (expectedEvents == 0 && mReceivedEvents.size() == 0) { + return mEventCond.wait_for(g, kTimeout) == std::cv_status::timeout; + } + + while (expectedEvents != mReceivedEvents.size()) { + if (mEventCond.wait_for(g, kTimeout) == std::cv_status::timeout) { + return false; + } + } + return true; + } + + void reset() { mReceivedEvents.clear(); } +}; + +class VehicleHalHidlTest : public testing::TestWithParam { + public: + virtual void SetUp() override { + mVehicle = IVehicle::getService(GetParam()); + ASSERT_NE(mVehicle.get(), nullptr); + } + virtual void TearDown() override {} + + sp mVehicle; + + bool isBooleanGlobalProp(int32_t property) { + return (property & (int)VehiclePropertyType::MASK) == (int)VehiclePropertyType::BOOLEAN && + (property & (int)VehicleArea::MASK) == (int)VehicleArea::GLOBAL; + } + + void invokeGet(int32_t property, int32_t areaId) { + VehiclePropValue requestedValue{}; + requestedValue.prop = property; + requestedValue.areaId = areaId; + + invokeGet(requestedValue); + } + + void invokeGet(const VehiclePropValue& requestedPropValue) { + mActualValue = VehiclePropValue{}; // reset previous values + + StatusCode refStatus; + VehiclePropValue refValue; + bool isCalled = false; + mVehicle->get(requestedPropValue, + [&refStatus, &refValue, &isCalled](StatusCode status, + const VehiclePropValue& value) { + refStatus = status; + refValue = value; + isCalled = true; + }); + ASSERT_TRUE(isCalled) << "callback wasn't called for property: " << requestedPropValue.prop; + + mActualValue = refValue; + mActualStatusCode = refStatus; + } + + VehiclePropValue mActualValue; + StatusCode mActualStatusCode; +}; + +// Test getAllPropConfig() returns at least 4 property configs. +TEST_P(VehicleHalHidlTest, getAllPropConfigs) { + ALOGD("VehicleHalHidlTest::getAllPropConfigs"); + bool isCalled = false; + hidl_vec propConfigs; + mVehicle->getAllPropConfigs([&isCalled, &propConfigs](const hidl_vec& cfgs) { + propConfigs = cfgs; + isCalled = true; + }); + ASSERT_TRUE(isCalled); + ASSERT_GE(propConfigs.size(), 4); +} + +// Test getPropConfig() can query all properties listed in CDD. +TEST_P(VehicleHalHidlTest, getPropConfigs) { + ALOGD("VehicleHalHidlTest::getPropConfigs"); + // Check the properties listed in CDD + hidl_vec properties = { + (int)VehicleProperty::GEAR_SELECTION, (int)VehicleProperty::NIGHT_MODE, + (int)VehicleProperty::PARKING_BRAKE_ON, (int)VehicleProperty::PERF_VEHICLE_SPEED}; + bool isCalled = false; + mVehicle->getPropConfigs( + properties, [&isCalled](StatusCode status, const hidl_vec& cfgs) { + ASSERT_EQ(StatusCode::OK, status); + ASSERT_EQ(4u, cfgs.size()); + isCalled = true; + }); + ASSERT_TRUE(isCalled); +} + +// Test getPropConfig() with an invalid propertyId returns an error code. +TEST_P(VehicleHalHidlTest, getPropConfigsWithInvalidProp) { + ALOGD("VehicleHalHidlTest::getPropConfigsWithInvalidProp"); + hidl_vec properties = {kInvalidProp}; + bool isCalled = false; + mVehicle->getPropConfigs( + properties, [&isCalled](StatusCode status, const hidl_vec& cfgs) { + ASSERT_NE(StatusCode::OK, status); + ASSERT_EQ(0, cfgs.size()); + isCalled = true; + }); + ASSERT_TRUE(isCalled); +} + +// Test get() return current value for properties. +TEST_P(VehicleHalHidlTest, get) { + ALOGD("VehicleHalHidlTest::get"); + invokeGet((int)VehicleProperty::PERF_VEHICLE_SPEED, 0); + ASSERT_EQ(StatusCode::OK, mActualStatusCode); +} + +// Test get() with an invalid propertyId return an error codes. +TEST_P(VehicleHalHidlTest, getInvalidProp) { + ALOGD("VehicleHalHidlTest::getInvalidProp"); + + invokeGet(kInvalidProp, 0); + ASSERT_NE(StatusCode::OK, mActualStatusCode); +} + +// Test set() on read_write properties. +TEST_P(VehicleHalHidlTest, setProp) { + ALOGD("VehicleHalHidlTest::setProp"); + hidl_vec propConfigs; + // skip hvac related properties + std::unordered_set hvacProps = {(int)VehicleProperty::HVAC_DEFROSTER, + (int)VehicleProperty::HVAC_AC_ON, + (int)VehicleProperty::HVAC_MAX_AC_ON, + (int)VehicleProperty::HVAC_MAX_DEFROST_ON, + (int)VehicleProperty::HVAC_RECIRC_ON, + (int)VehicleProperty::HVAC_DUAL_ON, + (int)VehicleProperty::HVAC_AUTO_ON, + (int)VehicleProperty::HVAC_POWER_ON, + (int)VehicleProperty::HVAC_AUTO_RECIRC_ON, + (int)VehicleProperty::HVAC_ELECTRIC_DEFROSTER_ON}; + mVehicle->getAllPropConfigs( + [&propConfigs](const hidl_vec& cfgs) { propConfigs = cfgs; }); + for (const VehiclePropConfig& cfg : propConfigs) { + // test on boolean and writable property + if (cfg.access == VehiclePropertyAccess::READ_WRITE && isBooleanGlobalProp(cfg.prop) && + !hvacProps.count(cfg.prop)) { + invokeGet(cfg.prop, 0); + int setValue = mActualValue.value.int32Values[0] == 1 ? 0 : 1; + VehiclePropValue propToSet = mActualValue; + propToSet.value.int32Values[0] = setValue; + ASSERT_EQ(StatusCode::OK, mVehicle->set(propToSet)) + << "Invalid status code for setting property: " << cfg.prop; + // check set success + invokeGet(cfg.prop, 0); + ASSERT_EQ(StatusCode::OK, mActualStatusCode); + ASSERT_EQ(setValue, mActualValue.value.int32Values[0]) + << "Failed to set value for property: " << cfg.prop; + } + } +} + +// Test set() on an read_only property. +TEST_P(VehicleHalHidlTest, setNotWritableProp) { + ALOGD("VehicleHalHidlTest::setNotWritableProp"); + invokeGet(static_cast(VehicleProperty::PERF_VEHICLE_SPEED), 0); + ASSERT_EQ(StatusCode::OK, mActualStatusCode); + VehiclePropValue vehicleSpeed = mActualValue; + + ASSERT_EQ(StatusCode::ACCESS_DENIED, mVehicle->set(vehicleSpeed)); +} + +// Test subscribe() and unsubscribe(). +TEST_P(VehicleHalHidlTest, subscribeAndUnsubscribe) { + ALOGD("VehicleHalHidlTest::subscribeAndUnsubscribe"); + const auto prop = static_cast(VehicleProperty::PERF_VEHICLE_SPEED); + sp cb = new VtsVehicleCallback(); + + hidl_vec options = { + SubscribeOptions{.propId = prop, 100.0, .flags = SubscribeFlags::EVENTS_FROM_CAR}}; + + ASSERT_EQ(StatusCode::OK, mVehicle->subscribe(cb, options)); + ASSERT_TRUE(cb->waitForExpectedEvents(10)); + + ASSERT_EQ(StatusCode::OK, mVehicle->unsubscribe(cb, prop)); + cb->reset(); + ASSERT_FALSE(cb->waitForExpectedEvents(10)); +} + +// Test subscribe() with an invalid property. +TEST_P(VehicleHalHidlTest, subscribeInvalidProp) { + ALOGD("VehicleHalHidlTest::subscribeInvalidProp"); + + sp cb = new VtsVehicleCallback(); + + hidl_vec options = {SubscribeOptions{ + .propId = kInvalidProp, 10.0, .flags = SubscribeFlags::EVENTS_FROM_CAR}}; + + ASSERT_NE(StatusCode::OK, mVehicle->subscribe(cb, options)); +} + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VehicleHalHidlTest); +INSTANTIATE_TEST_SUITE_P( + PerInstance, VehicleHalHidlTest, + testing::ValuesIn(android::hardware::getAllHalInstanceNames(IVehicle::descriptor)), + android::hardware::PrintInstanceNameToString); diff --git a/biometrics/README.md b/biometrics/README.md new file mode 100644 index 0000000000000000000000000000000000000000..8ae1ad646099bfad127f8aae93f05781d6f32f78 --- /dev/null +++ b/biometrics/README.md @@ -0,0 +1,12 @@ +## Biometric HALs ## +--- + +## Overview: ## + +The interfaces within the biometrics.* HAL tree are used by the Android Biometric Services +(e.g. FingerprintService, FaceService) to discover and operate biometric sensors on the device. + +More details and versioning information can be found within each particular HAL. + +More complete information about the Android Biometric HALs and subsystem can be found at +[source.android.com](https://source.android.com/security/biometric). \ No newline at end of file diff --git a/biometrics/common/aidl/Android.bp b/biometrics/common/aidl/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..05028c4e5053e69ed3fc668553e0605c18f6f584 --- /dev/null +++ b/biometrics/common/aidl/Android.bp @@ -0,0 +1,26 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +aidl_interface { + name: "android.hardware.biometrics.common", + vendor_available: true, + srcs: [ + "android/hardware/biometrics/common/*.aidl", + ], + stability: "vintf", + backend: { + java: { + platform_apis: true, + }, + cpp: { + enabled: false, + }, + }, + versions: ["1"], +} diff --git a/biometrics/common/aidl/OWNERS b/biometrics/common/aidl/OWNERS new file mode 100644 index 0000000000000000000000000000000000000000..36d726136fb188baf8f3dfc2180e8986c9f568fe --- /dev/null +++ b/biometrics/common/aidl/OWNERS @@ -0,0 +1,2 @@ +ilyamaty@google.com +kchyn@google.com diff --git a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/1/.hash b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/1/.hash new file mode 100644 index 0000000000000000000000000000000000000000..e7609fbc86aeba50c4f57b94799e3c351d720227 --- /dev/null +++ b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/1/.hash @@ -0,0 +1 @@ +9ad0b938db247283c4a8c1bf7e4218a420019024 diff --git a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/1/android/hardware/biometrics/common/CommonProps.aidl b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/1/android/hardware/biometrics/common/CommonProps.aidl new file mode 100644 index 0000000000000000000000000000000000000000..d4433c5bdeaceaf497141d6ca038ac39cd6b3951 --- /dev/null +++ b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/1/android/hardware/biometrics/common/CommonProps.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.common; +@VintfStability +parcelable CommonProps { + int sensorId; + android.hardware.biometrics.common.SensorStrength sensorStrength = android.hardware.biometrics.common.SensorStrength.CONVENIENCE; + int maxEnrollmentsPerUser; + android.hardware.biometrics.common.ComponentInfo[] componentInfo; +} diff --git a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/1/android/hardware/biometrics/common/ComponentInfo.aidl b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/1/android/hardware/biometrics/common/ComponentInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..ad11ddaa6d471924f138536e30ff7b532ec6e79b --- /dev/null +++ b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/1/android/hardware/biometrics/common/ComponentInfo.aidl @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.common; +@VintfStability +parcelable ComponentInfo { + String componentId; + String hardwareVersion; + String firmwareVersion; + String serialNumber; + String softwareVersion; +} diff --git a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/1/android/hardware/biometrics/common/ICancellationSignal.aidl b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/1/android/hardware/biometrics/common/ICancellationSignal.aidl new file mode 100644 index 0000000000000000000000000000000000000000..2bc6a6df05d554536affd38619a47a0d69c1220b --- /dev/null +++ b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/1/android/hardware/biometrics/common/ICancellationSignal.aidl @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.common; +@VintfStability +interface ICancellationSignal { + oneway void cancel(); +} diff --git a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/1/android/hardware/biometrics/common/SensorStrength.aidl b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/1/android/hardware/biometrics/common/SensorStrength.aidl new file mode 100644 index 0000000000000000000000000000000000000000..6675d091e5462d392f517f87e35ac89b4ae476d5 --- /dev/null +++ b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/1/android/hardware/biometrics/common/SensorStrength.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.common; +@Backing(type="byte") @VintfStability +enum SensorStrength { + CONVENIENCE = 0, + WEAK = 1, + STRONG = 2, +} diff --git a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/CommonProps.aidl b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/CommonProps.aidl new file mode 100644 index 0000000000000000000000000000000000000000..d4433c5bdeaceaf497141d6ca038ac39cd6b3951 --- /dev/null +++ b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/CommonProps.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.common; +@VintfStability +parcelable CommonProps { + int sensorId; + android.hardware.biometrics.common.SensorStrength sensorStrength = android.hardware.biometrics.common.SensorStrength.CONVENIENCE; + int maxEnrollmentsPerUser; + android.hardware.biometrics.common.ComponentInfo[] componentInfo; +} diff --git a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/ComponentInfo.aidl b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/ComponentInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..ad11ddaa6d471924f138536e30ff7b532ec6e79b --- /dev/null +++ b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/ComponentInfo.aidl @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.common; +@VintfStability +parcelable ComponentInfo { + String componentId; + String hardwareVersion; + String firmwareVersion; + String serialNumber; + String softwareVersion; +} diff --git a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/ICancellationSignal.aidl b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/ICancellationSignal.aidl new file mode 100644 index 0000000000000000000000000000000000000000..2bc6a6df05d554536affd38619a47a0d69c1220b --- /dev/null +++ b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/ICancellationSignal.aidl @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.common; +@VintfStability +interface ICancellationSignal { + oneway void cancel(); +} diff --git a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/SensorStrength.aidl b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/SensorStrength.aidl new file mode 100644 index 0000000000000000000000000000000000000000..6675d091e5462d392f517f87e35ac89b4ae476d5 --- /dev/null +++ b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/SensorStrength.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.common; +@Backing(type="byte") @VintfStability +enum SensorStrength { + CONVENIENCE = 0, + WEAK = 1, + STRONG = 2, +} diff --git a/biometrics/common/aidl/android/hardware/biometrics/common/CommonProps.aidl b/biometrics/common/aidl/android/hardware/biometrics/common/CommonProps.aidl new file mode 100644 index 0000000000000000000000000000000000000000..2f5af5dbc91219a89fc4b2752314a558ac6d6af1 --- /dev/null +++ b/biometrics/common/aidl/android/hardware/biometrics/common/CommonProps.aidl @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics.common; + +import android.hardware.biometrics.common.ComponentInfo; +import android.hardware.biometrics.common.SensorStrength; + +@VintfStability +parcelable CommonProps { + /** + * A statically configured unique ID that identifies a single biometric sensor. IDs must start + * at zero and increment by one for each unique sensor. Note that ID allocations are shared + * between all biometric modalities (e.g. fingerprint, face, iris), and a single ID must never + * be claimed by more than a single sensor. + */ + int sensorId; + + /** + * A statically configured strength for this sensor. See the SensorStrength interface for more + * information. + */ + SensorStrength sensorStrength = SensorStrength.CONVENIENCE; + + /** + * The maximum number of enrollments that a single user can have. Statically configured. + */ + int maxEnrollmentsPerUser; + + /** + * A list of component information for subsystems that pertain to this biometric sensor. + */ + ComponentInfo[] componentInfo; +} diff --git a/biometrics/common/aidl/android/hardware/biometrics/common/ComponentInfo.aidl b/biometrics/common/aidl/android/hardware/biometrics/common/ComponentInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..b268eef976096327f56420f6509d8182300c3be3 --- /dev/null +++ b/biometrics/common/aidl/android/hardware/biometrics/common/ComponentInfo.aidl @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics.common; + +@VintfStability +parcelable ComponentInfo { + /** + * An identifier uniquely identifying a subsystem. + * It must not be an empty string. + */ + String componentId; + + /** + * The hardware version. For example, //. + * If there's no hardware version for this component, it must be empty. + */ + String hardwareVersion; + + /** + * The firmware version. + * If there's no firmware version for this component, it must be empty. + */ + String firmwareVersion; + + /** + * The sensor's serial number. + * If there's no serial number for this component, it must be empty. + */ + String serialNumber; + + /** + * The software version. For example, //. + * If there's no software version for this component, it must be empty. + */ + String softwareVersion; +} diff --git a/biometrics/common/aidl/android/hardware/biometrics/common/ICancellationSignal.aidl b/biometrics/common/aidl/android/hardware/biometrics/common/ICancellationSignal.aidl new file mode 100644 index 0000000000000000000000000000000000000000..10102561b5a956637e6c577b98af87eb74a798f5 --- /dev/null +++ b/biometrics/common/aidl/android/hardware/biometrics/common/ICancellationSignal.aidl @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics.common; + +@VintfStability +oneway interface ICancellationSignal { + void cancel(); +} + diff --git a/biometrics/common/aidl/android/hardware/biometrics/common/SensorStrength.aidl b/biometrics/common/aidl/android/hardware/biometrics/common/SensorStrength.aidl new file mode 100644 index 0000000000000000000000000000000000000000..790691cbfc1f1d0ba53a7338dbe32725ecc804ed --- /dev/null +++ b/biometrics/common/aidl/android/hardware/biometrics/common/SensorStrength.aidl @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics.common; + +@VintfStability +@Backing(type="byte") +enum SensorStrength { + /** + * A sensor that meets the requirements for Class 1 biometrics as defined in the CDD. This does + * not correspond to a public BiometricManager.Authenticators constant. Sensors of this strength + * are not available to applications via the public API surface. + */ + CONVENIENCE, + + /** + * A sensor that meets the requirements for Class 2 biometrics as defined in the CDD. + * Corresponds to BiometricManager.Authenticators.BIOMETRIC_WEAK. + */ + WEAK, + + /** + * A sensor that meets the requirements for Class 3 biometrics as defined in the CDD. + * Corresponds to BiometricManager.Authenticators.BIOMETRIC_STRONG. + * + * Notably, this is the only strength that allows generation/verification of + * HardwareAuthToken(s). + */ + STRONG, +} \ No newline at end of file diff --git a/biometrics/face/1.0/default/BiometricsFace.cpp b/biometrics/face/1.0/default/BiometricsFace.cpp index 2dd64764bb1d1b40fda2ea282bb7cd81c58409b8..97dc4690befe8fc82cceff866fc3ce03e2e56dc4 100644 --- a/biometrics/face/1.0/default/BiometricsFace.cpp +++ b/biometrics/face/1.0/default/BiometricsFace.cpp @@ -24,8 +24,8 @@ using android::hardware::biometrics::face::V1_0::OptionalUint64; constexpr uint64_t kDeviceId = 123; // Arbitrary value. constexpr uint64_t kAuthenticatorId = 987; -// Arbitrary value. -constexpr uint64_t kLockoutDuration = 555; +// Not locked out. +constexpr uint64_t kLockoutDuration = 0; BiometricsFace::BiometricsFace() : mRandom(std::mt19937::default_seed) {} diff --git a/biometrics/face/aidl/Android.bp b/biometrics/face/aidl/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..54d3ecd1e1e9db846999262dee86af092a93cee6 --- /dev/null +++ b/biometrics/face/aidl/Android.bp @@ -0,0 +1,31 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +aidl_interface { + name: "android.hardware.biometrics.face", + vendor_available: true, + srcs: [ + "android/hardware/biometrics/face/**/*.aidl", + ], + imports: [ + "android.hardware.biometrics.common", + "android.hardware.common", + "android.hardware.keymaster", + ], + stability: "vintf", + backend: { + java: { + platform_apis: true, + }, + cpp: { + enabled: false, + }, + }, + versions: ["1"], +} diff --git a/biometrics/face/aidl/OWNERS b/biometrics/face/aidl/OWNERS new file mode 100644 index 0000000000000000000000000000000000000000..36d726136fb188baf8f3dfc2180e8986c9f568fe --- /dev/null +++ b/biometrics/face/aidl/OWNERS @@ -0,0 +1,2 @@ +ilyamaty@google.com +kchyn@google.com diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/.hash b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/.hash new file mode 100644 index 0000000000000000000000000000000000000000..f5ad87fca7649c203de6d15b59dc955df864aa4f --- /dev/null +++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/.hash @@ -0,0 +1 @@ +3b10f5094c5af9fe551093597fab007d1e148256 diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/AcquiredInfo.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/AcquiredInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..eaa43f3f9e0ad776d09f74ad5422a84c4c118989 --- /dev/null +++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/AcquiredInfo.aidl @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.face; +@Backing(type="byte") @VintfStability +enum AcquiredInfo { + UNKNOWN = 0, + GOOD = 1, + INSUFFICIENT = 2, + TOO_BRIGHT = 3, + TOO_DARK = 4, + TOO_CLOSE = 5, + TOO_FAR = 6, + FACE_TOO_HIGH = 7, + FACE_TOO_LOW = 8, + FACE_TOO_RIGHT = 9, + FACE_TOO_LEFT = 10, + POOR_GAZE = 11, + NOT_DETECTED = 12, + TOO_MUCH_MOTION = 13, + RECALIBRATE = 14, + TOO_DIFFERENT = 15, + TOO_SIMILAR = 16, + PAN_TOO_EXTREME = 17, + TILT_TOO_EXTREME = 18, + ROLL_TOO_EXTREME = 19, + FACE_OBSCURED = 20, + START = 21, + SENSOR_DIRTY = 22, + VENDOR = 23, + FIRST_FRAME_RECEIVED = 24, + DARK_GLASSES_DETECTED = 25, + MOUTH_COVERING_DETECTED = 26, +} diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/AuthenticationFrame.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/AuthenticationFrame.aidl new file mode 100644 index 0000000000000000000000000000000000000000..20bc76779bae4770bb02f9fa0d576d09f1bf9e35 --- /dev/null +++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/AuthenticationFrame.aidl @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.face; +@VintfStability +parcelable AuthenticationFrame { + android.hardware.biometrics.face.BaseFrame data; +} diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/BaseFrame.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/BaseFrame.aidl new file mode 100644 index 0000000000000000000000000000000000000000..67b5cf41692df6234e13d7e724fd360b25e45dfc --- /dev/null +++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/BaseFrame.aidl @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.face; +@VintfStability +parcelable BaseFrame { + android.hardware.biometrics.face.AcquiredInfo acquiredInfo = android.hardware.biometrics.face.AcquiredInfo.UNKNOWN; + int vendorCode; + float pan; + float tilt; + float distance; + boolean isCancellable; +} diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/Cell.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/Cell.aidl new file mode 100644 index 0000000000000000000000000000000000000000..6be8c8e97518d1605c251ddb3679a51288999c09 --- /dev/null +++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/Cell.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.face; +@VintfStability +parcelable Cell { + int x; + int y; + int z; +} diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/EnrollmentFrame.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/EnrollmentFrame.aidl new file mode 100644 index 0000000000000000000000000000000000000000..0ea10d6ddb0ef2c0198480f551a84988316cca13 --- /dev/null +++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/EnrollmentFrame.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.face; +@VintfStability +parcelable EnrollmentFrame { + @nullable android.hardware.biometrics.face.Cell cell; + android.hardware.biometrics.face.EnrollmentStage stage = android.hardware.biometrics.face.EnrollmentStage.UNKNOWN; + android.hardware.biometrics.face.BaseFrame data; +} diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/EnrollmentStage.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/EnrollmentStage.aidl new file mode 100644 index 0000000000000000000000000000000000000000..ce5679ab31b2ce933c8591b53ccd2db9847d635f --- /dev/null +++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/EnrollmentStage.aidl @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.face; +@Backing(type="byte") @VintfStability +enum EnrollmentStage { + UNKNOWN = 0, + FIRST_FRAME_RECEIVED = 1, + WAITING_FOR_CENTERING = 2, + HOLD_STILL_IN_CENTER = 3, + ENROLLING_MOVEMENT_1 = 4, + ENROLLING_MOVEMENT_2 = 5, + ENROLLMENT_FINISHED = 6, +} diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/EnrollmentStageConfig.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/EnrollmentStageConfig.aidl new file mode 100644 index 0000000000000000000000000000000000000000..48db2cf615675a9aa06679c22a0276f3741e361c --- /dev/null +++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/EnrollmentStageConfig.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.face; +@VintfStability +parcelable EnrollmentStageConfig { + android.hardware.biometrics.face.EnrollmentStage stage = android.hardware.biometrics.face.EnrollmentStage.UNKNOWN; + List cells; +} diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/EnrollmentType.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/EnrollmentType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..8e99ad6529fd7f8a7997d9c1effb49384f93787f --- /dev/null +++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/EnrollmentType.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.face; +@Backing(type="byte") @VintfStability +enum EnrollmentType { + DEFAULT = 0, + ACCESSIBILITY = 1, +} diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/Error.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/Error.aidl new file mode 100644 index 0000000000000000000000000000000000000000..1a2166193265e9377fbc54514086bd27b7d1921f --- /dev/null +++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/Error.aidl @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.face; +@Backing(type="byte") @VintfStability +enum Error { + UNKNOWN = 0, + HW_UNAVAILABLE = 1, + UNABLE_TO_PROCESS = 2, + TIMEOUT = 3, + NO_SPACE = 4, + CANCELED = 5, + UNABLE_TO_REMOVE = 6, + VENDOR = 7, + REENROLL_REQUIRED = 8, +} diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/FaceSensorType.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/FaceSensorType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..a215b99f72e1854ac79dd905af61f94b7cde94a5 --- /dev/null +++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/FaceSensorType.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.face; +@Backing(type="byte") @VintfStability +enum FaceSensorType { + UNKNOWN = 0, + RGB = 1, + IR = 2, +} diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/Feature.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/Feature.aidl new file mode 100644 index 0000000000000000000000000000000000000000..1875b97431990bef2d5a3b5ace56f27de8c92cc2 --- /dev/null +++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/Feature.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.face; +@Backing(type="byte") @VintfStability +enum Feature { + REQUIRE_ATTENTION = 0, + REQUIRE_DIVERSE_POSES = 1, + DEBUG = 2, +} diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/IFace.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/IFace.aidl new file mode 100644 index 0000000000000000000000000000000000000000..fc4a4d04bb0a68dc6d19dc7fcacddf682fbd6a0e --- /dev/null +++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/IFace.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.face; +@VintfStability +interface IFace { + android.hardware.biometrics.face.SensorProps[] getSensorProps(); + android.hardware.biometrics.face.ISession createSession(in int sensorId, in int userId, in android.hardware.biometrics.face.ISessionCallback cb); +} diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/ISession.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/ISession.aidl new file mode 100644 index 0000000000000000000000000000000000000000..78178642cd9ec4fdd844158a23d58a82b82f87b7 --- /dev/null +++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/ISession.aidl @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.face; +@VintfStability +interface ISession { + void generateChallenge(); + void revokeChallenge(in long challenge); + android.hardware.biometrics.face.EnrollmentStageConfig[] getEnrollmentConfig(in android.hardware.biometrics.face.EnrollmentType enrollmentType); + android.hardware.biometrics.common.ICancellationSignal enroll(in android.hardware.keymaster.HardwareAuthToken hat, in android.hardware.biometrics.face.EnrollmentType type, in android.hardware.biometrics.face.Feature[] features, in @nullable android.hardware.common.NativeHandle previewSurface); + android.hardware.biometrics.common.ICancellationSignal authenticate(in long operationId); + android.hardware.biometrics.common.ICancellationSignal detectInteraction(); + void enumerateEnrollments(); + void removeEnrollments(in int[] enrollmentIds); + void getFeatures(); + void setFeature(in android.hardware.keymaster.HardwareAuthToken hat, in android.hardware.biometrics.face.Feature feature, boolean enabled); + void getAuthenticatorId(); + void invalidateAuthenticatorId(); + void resetLockout(in android.hardware.keymaster.HardwareAuthToken hat); + void close(); +} diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/ISessionCallback.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/ISessionCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..bbace29aa0f012060bf483af8efaef62c672c0e1 --- /dev/null +++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/ISessionCallback.aidl @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.face; +@VintfStability +interface ISessionCallback { + void onChallengeGenerated(in long challenge); + void onChallengeRevoked(in long challenge); + void onAuthenticationFrame(in android.hardware.biometrics.face.AuthenticationFrame frame); + void onEnrollmentFrame(in android.hardware.biometrics.face.EnrollmentFrame frame); + void onError(in android.hardware.biometrics.face.Error error, in int vendorCode); + void onEnrollmentProgress(in int enrollmentId, int remaining); + void onAuthenticationSucceeded(in int enrollmentId, in android.hardware.keymaster.HardwareAuthToken hat); + void onAuthenticationFailed(); + void onLockoutTimed(in long durationMillis); + void onLockoutPermanent(); + void onLockoutCleared(); + void onInteractionDetected(); + void onEnrollmentsEnumerated(in int[] enrollmentIds); + void onFeaturesRetrieved(in android.hardware.biometrics.face.Feature[] features); + void onFeatureSet(android.hardware.biometrics.face.Feature feature); + void onEnrollmentsRemoved(in int[] enrollmentIds); + void onAuthenticatorIdRetrieved(in long authenticatorId); + void onAuthenticatorIdInvalidated(in long newAuthenticatorId); + void onSessionClosed(); +} diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/SensorProps.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/SensorProps.aidl new file mode 100644 index 0000000000000000000000000000000000000000..8b3c51bb1270f891c3768dd9e332ee9166c7a521 --- /dev/null +++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/1/android/hardware/biometrics/face/SensorProps.aidl @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.face; +@VintfStability +parcelable SensorProps { + android.hardware.biometrics.common.CommonProps commonProps; + android.hardware.biometrics.face.FaceSensorType sensorType = android.hardware.biometrics.face.FaceSensorType.UNKNOWN; + boolean halControlsPreview; + int previewDisplayId; + int enrollPreviewWidth; + int enrollPreviewHeight; + float enrollTranslationX; + float enrollTranslationY; + float enrollPreviewScale; + boolean supportsDetectInteraction; +} diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/AcquiredInfo.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/AcquiredInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..eaa43f3f9e0ad776d09f74ad5422a84c4c118989 --- /dev/null +++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/AcquiredInfo.aidl @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.face; +@Backing(type="byte") @VintfStability +enum AcquiredInfo { + UNKNOWN = 0, + GOOD = 1, + INSUFFICIENT = 2, + TOO_BRIGHT = 3, + TOO_DARK = 4, + TOO_CLOSE = 5, + TOO_FAR = 6, + FACE_TOO_HIGH = 7, + FACE_TOO_LOW = 8, + FACE_TOO_RIGHT = 9, + FACE_TOO_LEFT = 10, + POOR_GAZE = 11, + NOT_DETECTED = 12, + TOO_MUCH_MOTION = 13, + RECALIBRATE = 14, + TOO_DIFFERENT = 15, + TOO_SIMILAR = 16, + PAN_TOO_EXTREME = 17, + TILT_TOO_EXTREME = 18, + ROLL_TOO_EXTREME = 19, + FACE_OBSCURED = 20, + START = 21, + SENSOR_DIRTY = 22, + VENDOR = 23, + FIRST_FRAME_RECEIVED = 24, + DARK_GLASSES_DETECTED = 25, + MOUTH_COVERING_DETECTED = 26, +} diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/AuthenticationFrame.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/AuthenticationFrame.aidl new file mode 100644 index 0000000000000000000000000000000000000000..20bc76779bae4770bb02f9fa0d576d09f1bf9e35 --- /dev/null +++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/AuthenticationFrame.aidl @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.face; +@VintfStability +parcelable AuthenticationFrame { + android.hardware.biometrics.face.BaseFrame data; +} diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/BaseFrame.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/BaseFrame.aidl new file mode 100644 index 0000000000000000000000000000000000000000..67b5cf41692df6234e13d7e724fd360b25e45dfc --- /dev/null +++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/BaseFrame.aidl @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.face; +@VintfStability +parcelable BaseFrame { + android.hardware.biometrics.face.AcquiredInfo acquiredInfo = android.hardware.biometrics.face.AcquiredInfo.UNKNOWN; + int vendorCode; + float pan; + float tilt; + float distance; + boolean isCancellable; +} diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/Cell.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/Cell.aidl new file mode 100644 index 0000000000000000000000000000000000000000..6be8c8e97518d1605c251ddb3679a51288999c09 --- /dev/null +++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/Cell.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.face; +@VintfStability +parcelable Cell { + int x; + int y; + int z; +} diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/EnrollmentFrame.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/EnrollmentFrame.aidl new file mode 100644 index 0000000000000000000000000000000000000000..0ea10d6ddb0ef2c0198480f551a84988316cca13 --- /dev/null +++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/EnrollmentFrame.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.face; +@VintfStability +parcelable EnrollmentFrame { + @nullable android.hardware.biometrics.face.Cell cell; + android.hardware.biometrics.face.EnrollmentStage stage = android.hardware.biometrics.face.EnrollmentStage.UNKNOWN; + android.hardware.biometrics.face.BaseFrame data; +} diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/EnrollmentStage.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/EnrollmentStage.aidl new file mode 100644 index 0000000000000000000000000000000000000000..ce5679ab31b2ce933c8591b53ccd2db9847d635f --- /dev/null +++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/EnrollmentStage.aidl @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.face; +@Backing(type="byte") @VintfStability +enum EnrollmentStage { + UNKNOWN = 0, + FIRST_FRAME_RECEIVED = 1, + WAITING_FOR_CENTERING = 2, + HOLD_STILL_IN_CENTER = 3, + ENROLLING_MOVEMENT_1 = 4, + ENROLLING_MOVEMENT_2 = 5, + ENROLLMENT_FINISHED = 6, +} diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/EnrollmentStageConfig.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/EnrollmentStageConfig.aidl new file mode 100644 index 0000000000000000000000000000000000000000..48db2cf615675a9aa06679c22a0276f3741e361c --- /dev/null +++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/EnrollmentStageConfig.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.face; +@VintfStability +parcelable EnrollmentStageConfig { + android.hardware.biometrics.face.EnrollmentStage stage = android.hardware.biometrics.face.EnrollmentStage.UNKNOWN; + List cells; +} diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/EnrollmentType.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/EnrollmentType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..8e99ad6529fd7f8a7997d9c1effb49384f93787f --- /dev/null +++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/EnrollmentType.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.face; +@Backing(type="byte") @VintfStability +enum EnrollmentType { + DEFAULT = 0, + ACCESSIBILITY = 1, +} diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/Error.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/Error.aidl new file mode 100644 index 0000000000000000000000000000000000000000..1a2166193265e9377fbc54514086bd27b7d1921f --- /dev/null +++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/Error.aidl @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.face; +@Backing(type="byte") @VintfStability +enum Error { + UNKNOWN = 0, + HW_UNAVAILABLE = 1, + UNABLE_TO_PROCESS = 2, + TIMEOUT = 3, + NO_SPACE = 4, + CANCELED = 5, + UNABLE_TO_REMOVE = 6, + VENDOR = 7, + REENROLL_REQUIRED = 8, +} diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/FaceSensorType.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/FaceSensorType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..a215b99f72e1854ac79dd905af61f94b7cde94a5 --- /dev/null +++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/FaceSensorType.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.face; +@Backing(type="byte") @VintfStability +enum FaceSensorType { + UNKNOWN = 0, + RGB = 1, + IR = 2, +} diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/Feature.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/Feature.aidl new file mode 100644 index 0000000000000000000000000000000000000000..1875b97431990bef2d5a3b5ace56f27de8c92cc2 --- /dev/null +++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/Feature.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.face; +@Backing(type="byte") @VintfStability +enum Feature { + REQUIRE_ATTENTION = 0, + REQUIRE_DIVERSE_POSES = 1, + DEBUG = 2, +} diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/IFace.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/IFace.aidl new file mode 100644 index 0000000000000000000000000000000000000000..fc4a4d04bb0a68dc6d19dc7fcacddf682fbd6a0e --- /dev/null +++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/IFace.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.face; +@VintfStability +interface IFace { + android.hardware.biometrics.face.SensorProps[] getSensorProps(); + android.hardware.biometrics.face.ISession createSession(in int sensorId, in int userId, in android.hardware.biometrics.face.ISessionCallback cb); +} diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISession.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISession.aidl new file mode 100644 index 0000000000000000000000000000000000000000..78178642cd9ec4fdd844158a23d58a82b82f87b7 --- /dev/null +++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISession.aidl @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.face; +@VintfStability +interface ISession { + void generateChallenge(); + void revokeChallenge(in long challenge); + android.hardware.biometrics.face.EnrollmentStageConfig[] getEnrollmentConfig(in android.hardware.biometrics.face.EnrollmentType enrollmentType); + android.hardware.biometrics.common.ICancellationSignal enroll(in android.hardware.keymaster.HardwareAuthToken hat, in android.hardware.biometrics.face.EnrollmentType type, in android.hardware.biometrics.face.Feature[] features, in @nullable android.hardware.common.NativeHandle previewSurface); + android.hardware.biometrics.common.ICancellationSignal authenticate(in long operationId); + android.hardware.biometrics.common.ICancellationSignal detectInteraction(); + void enumerateEnrollments(); + void removeEnrollments(in int[] enrollmentIds); + void getFeatures(); + void setFeature(in android.hardware.keymaster.HardwareAuthToken hat, in android.hardware.biometrics.face.Feature feature, boolean enabled); + void getAuthenticatorId(); + void invalidateAuthenticatorId(); + void resetLockout(in android.hardware.keymaster.HardwareAuthToken hat); + void close(); +} diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISessionCallback.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISessionCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..bbace29aa0f012060bf483af8efaef62c672c0e1 --- /dev/null +++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISessionCallback.aidl @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.face; +@VintfStability +interface ISessionCallback { + void onChallengeGenerated(in long challenge); + void onChallengeRevoked(in long challenge); + void onAuthenticationFrame(in android.hardware.biometrics.face.AuthenticationFrame frame); + void onEnrollmentFrame(in android.hardware.biometrics.face.EnrollmentFrame frame); + void onError(in android.hardware.biometrics.face.Error error, in int vendorCode); + void onEnrollmentProgress(in int enrollmentId, int remaining); + void onAuthenticationSucceeded(in int enrollmentId, in android.hardware.keymaster.HardwareAuthToken hat); + void onAuthenticationFailed(); + void onLockoutTimed(in long durationMillis); + void onLockoutPermanent(); + void onLockoutCleared(); + void onInteractionDetected(); + void onEnrollmentsEnumerated(in int[] enrollmentIds); + void onFeaturesRetrieved(in android.hardware.biometrics.face.Feature[] features); + void onFeatureSet(android.hardware.biometrics.face.Feature feature); + void onEnrollmentsRemoved(in int[] enrollmentIds); + void onAuthenticatorIdRetrieved(in long authenticatorId); + void onAuthenticatorIdInvalidated(in long newAuthenticatorId); + void onSessionClosed(); +} diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SensorProps.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SensorProps.aidl new file mode 100644 index 0000000000000000000000000000000000000000..8b3c51bb1270f891c3768dd9e332ee9166c7a521 --- /dev/null +++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SensorProps.aidl @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.face; +@VintfStability +parcelable SensorProps { + android.hardware.biometrics.common.CommonProps commonProps; + android.hardware.biometrics.face.FaceSensorType sensorType = android.hardware.biometrics.face.FaceSensorType.UNKNOWN; + boolean halControlsPreview; + int previewDisplayId; + int enrollPreviewWidth; + int enrollPreviewHeight; + float enrollTranslationX; + float enrollTranslationY; + float enrollPreviewScale; + boolean supportsDetectInteraction; +} diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/AcquiredInfo.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/AcquiredInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..cf68421062b1dbaa0f8af7f4c2d229c29d3ad2fa --- /dev/null +++ b/biometrics/face/aidl/android/hardware/biometrics/face/AcquiredInfo.aidl @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics.face; + +@VintfStability +@Backing(type="byte") +enum AcquiredInfo { + /** + * Placeholder value used for default initialization of AcquiredInfo. This + * value means AcquiredInfo wasn't explicitly initialized and must be + * discarded by the recipient. + */ + UNKNOWN, + + /** + * The acquired face data was good, no further user interaction is necessary. + */ + GOOD, + + /** + * The acquired face data was too noisy or did not have sufficient detail. + * This is a catch-all for all acquisition errors not captured by the other + * constants. + */ + INSUFFICIENT, + + /** + * Because there was too much ambient light, the captured face data was too + * bright. It's reasonable to return this after multiple + * AcquiredInfo.INSUFFICIENT. + * + * The user is expected to take action to retry the operation in better + * lighting conditions when this is returned. + */ + TOO_BRIGHT, + + /** + * Because there was not enough illumination, the captured face data was too + * dark. It's reasonable to return this after multiple + * AcquiredInfo.INSUFFICIENT. + * + * The user is expected to take action to retry the operation in better + * lighting conditions when this is returned. + */ + TOO_DARK, + + /** + * The detected face is too close to the sensor, and the image cannot be + * processed. + * + * The user is expected to be informed to move further from the sensor when + * this is returned. + */ + TOO_CLOSE, + + /** + * The detected face is too small, as the user might be too far away from + * the sensor. + * + * The user is expected to be informed to move closer to the sensor when + * this is returned. + */ + TOO_FAR, + + /** + * Only the upper part of the face was detected. The sensor's field of view + * is too high. + * + * The user should be informed to move up with respect to the sensor when + * this is returned. + */ + FACE_TOO_HIGH, + + /** + * Only the lower part of the face was detected. The sensor's field of view + * is too low. + * + * The user should be informed to move down with respect to the sensor when + * this is returned. + */ + FACE_TOO_LOW, + + /** + * Only the right part of the face was detected. The sensor's field of view + * is too far right. + * + * The user should be informed to move to the right with respect to the + * sensor when this is returned. + */ + FACE_TOO_RIGHT, + + /** + * Only the left part of the face was detected. The sensor's field of view + * is too far left. + * + * The user should be informed to move to the left with respect to the + * sensor when this is returned. + */ + FACE_TOO_LEFT, + + /** + * The user's eyes have strayed away from the sensor. If this message is + * sent, the user should be informed to look at the device. If the user + * can't be found in the frame, one of the other acquisition messages + * must be sent, e.g. NOT_DETECTED. + */ + POOR_GAZE, + + /** + * No face was detected within the sensor's field of view. + * + * The user should be informed to point the sensor to a face when this is + * returned. + */ + NOT_DETECTED, + + /** + * Too much motion was detected. + * + * The user should be informed to keep their face steady relative to the + * sensor. + */ + TOO_MUCH_MOTION, + + /** + * The sensor needs to be re-calibrated. This is an unexpected condition, + * and must only be sent if a serious, uncorrectable, and unrecoverable + * calibration issue is detected which requires user intervention, e.g. + * re-enrolling. The expected response to this message is to direct the + * user to re-enroll. + */ + RECALIBRATE, + + /** + * The face is too different from a previous acquisition. This condition + * only applies to enrollment. This can happen if the user passes the + * device to someone else in the middle of enrollment. + */ + TOO_DIFFERENT, + + /** + * The face is too similar to a previous acquisition. This condition only + * applies to enrollment. The user should change their pose. + */ + TOO_SIMILAR, + + /** + * The magnitude of the pan angle of the user’s face with respect to the sensor’s + * capture plane is too high. + * + * The pan angle is defined as the angle swept out by the user’s face turning + * their neck left and right. The pan angle would be zero if the user faced the + * camera directly. + * + * The user should be informed to look more directly at the camera. + */ + PAN_TOO_EXTREME, + + /** + * The magnitude of the tilt angle of the user’s face with respect to the sensor’s + * capture plane is too high. + * + * The tilt angle is defined as the angle swept out by the user’s face looking up + * and down. The tilt angle would be zero if the user faced the camera directly. + * + * The user should be informed to look more directly at the camera. + */ + TILT_TOO_EXTREME, + + /** + * The magnitude of the roll angle of the user’s face with respect to the sensor’s + * capture plane is too high. + * + * The roll angle is defined as the angle swept out by the user’s face tilting their head + * towards their shoulders to the left and right. The roll angle would be zero if the user's + * head is vertically aligned with the camera. + * + * The user should be informed to look more directly at the camera. + */ + ROLL_TOO_EXTREME, + + /** + * The user’s face has been obscured by some object. + * + * The user should be informed to remove any objects from the line of sight from + * the sensor to the user’s face. + */ + FACE_OBSCURED, + + /** + * This message represents the earliest message sent at the beginning of the authentication + * pipeline. It is expected to be used to measure latency. For example, in a camera-based + * authentication system it's expected to be sent prior to camera initialization. The framework + * will measure latency based on the time between the last START message and the onAuthenticated + * callback. + */ + START, + + /** + * The sensor is dirty. The user should be informed to clean the sensor. + */ + SENSOR_DIRTY, + + /** + * Vendor-specific acquisition message. See ISessionCallback#onAcquired vendorCode + * documentation. + */ + VENDOR, + + /** + * The first frame from the camera has been received. + */ + FIRST_FRAME_RECEIVED, + + /** + * Dark glasses detected. This can be useful for providing relevant feedback to the user and + * enabling an alternative authentication logic if the implementation supports it. + */ + DARK_GLASSES_DETECTED, + + /** + * A face mask or face covering detected. This can be useful for providing relevant feedback to + * the user and enabling an alternative authentication logic if the implementation supports it. + */ + MOUTH_COVERING_DETECTED, +} diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/AuthenticationFrame.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/AuthenticationFrame.aidl new file mode 100644 index 0000000000000000000000000000000000000000..be61a20c6f2bc6fde234e68301d2c9d9d471c38f --- /dev/null +++ b/biometrics/face/aidl/android/hardware/biometrics/face/AuthenticationFrame.aidl @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics.face; + +import android.hardware.biometrics.face.BaseFrame; + +/** + * Describes an individual frame captured during authentication. + */ +@VintfStability +parcelable AuthenticationFrame { + /** + * The frame metadata. Can be used by the framework to provide user feedback. + */ + BaseFrame data; +} diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/BaseFrame.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/BaseFrame.aidl new file mode 100644 index 0000000000000000000000000000000000000000..58ad01a0c0d5f9c3ebc471b699453d0760e360e4 --- /dev/null +++ b/biometrics/face/aidl/android/hardware/biometrics/face/BaseFrame.aidl @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics.face; + +import android.hardware.biometrics.face.AcquiredInfo; + +/** + * Metadata of an individual frame. Can be used by the framework to provide user feedback. + * This parcelable is part of AuthenticationFrame and EnrollmentFrame, and shouldn't be used + * independently of those parcelables. + */ +@VintfStability +parcelable BaseFrame { + /** + * Information about the frame that can be used by the framework to provide feedback to the + * user, for example ask the user to move their face in a certain way. + */ + AcquiredInfo acquiredInfo = AcquiredInfo.UNKNOWN; + + /** + * If acquiredInfo is set to AcquiredInfo::VENDOR. This is the index into the configuration + * "com.android.internal.R.array.face_acquired_vendor" that's installed on the vendor partition. + * Otherwise, this value must be ignored. + */ + int vendorCode; + + /** + * Pan value. It is recommended to use the range of [-1, 1] to represent valid values, and + * anything outside of that range to represent errors. However, vendors are free to define + * their own way of representing valid values and errors. + */ + float pan; + + /** + * Tilt value. It is recommended to use the range of [-1, 1] to represent valid values, and + * anything outside of that range to represent errors. However, vendors are free to define + * their own way of representing valid values and errors. + */ + float tilt; + + /** + * Distance value. It is recommended to use the range of [-1, 1] to represent valid values, and + * anything outside of that range to represent errors. However, vendors are free to define + * their own way of representing valid values and errors. + */ + float distance; + + /** + * Indicates that the HAL can no longer continue with authentication or enrollment. This allows + * the framework to correlate a failure condition with a particular AcquiredInfo, rather than + * having a sequence of AcquiredInfo + Error. + */ + boolean isCancellable; +} diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/Cell.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/Cell.aidl new file mode 100644 index 0000000000000000000000000000000000000000..77f33b96f3e701b35362d33128d18cf5368a5116 --- /dev/null +++ b/biometrics/face/aidl/android/hardware/biometrics/face/Cell.aidl @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics.face; + +/** + * Coordinates of an enrollment UI cell in a vendor-defined coordinate system. + */ +@VintfStability +parcelable Cell { + int x; + int y; + int z; +} diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/EnrollmentFrame.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/EnrollmentFrame.aidl new file mode 100644 index 0000000000000000000000000000000000000000..ecb0e79aca668385f40fbc1a050a1efd83904476 --- /dev/null +++ b/biometrics/face/aidl/android/hardware/biometrics/face/EnrollmentFrame.aidl @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics.face; + +import android.hardware.biometrics.face.BaseFrame; +import android.hardware.biometrics.face.Cell; +import android.hardware.biometrics.face.EnrollmentStage; + +/** + * Describes an individual frame captured during enrollment. + */ +@VintfStability +parcelable EnrollmentFrame { + /** + * The enrollment UI cell that was captured in this frame, or null if no cell was captured. + */ + @nullable Cell cell; + + /** + * The enrollment stage for which this frame was captured. + */ + EnrollmentStage stage = EnrollmentStage.UNKNOWN; + + /** + * The frame metadata. Can be used by the framework to provide user feedback. + */ + BaseFrame data; +} diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/EnrollmentStage.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/EnrollmentStage.aidl new file mode 100644 index 0000000000000000000000000000000000000000..5974838e01365936f5bc29be1e15cd0fab39c7a0 --- /dev/null +++ b/biometrics/face/aidl/android/hardware/biometrics/face/EnrollmentStage.aidl @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics.face; + +/** + * Enrollment stages that can be mapped to the enrollment UI actions in the framework. + */ +@VintfStability +@Backing(type="byte") +enum EnrollmentStage { + /** + * Placeholder value used for default initialization of EnrollmentStage. This + * value means EnrollmentStage wasn't explicitly initialized and must be + * discarded by the recipient. + */ + UNKNOWN, + + /** + * HAL has obtained the first camera frame. + */ + FIRST_FRAME_RECEIVED, + + /** + * HAL is waiting for the user's face to be centered. + */ + WAITING_FOR_CENTERING, + + /** + * HAL is expecting the user's face to stay centered. + */ + HOLD_STILL_IN_CENTER, + + /** + * Vendor defined movement 1. + */ + ENROLLING_MOVEMENT_1, + + /** + * Vendor defined movement 2. + */ + ENROLLING_MOVEMENT_2, + + /** + * HAL has finished the enrollment. + */ + ENROLLMENT_FINISHED, +} diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/EnrollmentStageConfig.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/EnrollmentStageConfig.aidl new file mode 100644 index 0000000000000000000000000000000000000000..a8fa9abc8ea33b21ede40910669d51f023478667 --- /dev/null +++ b/biometrics/face/aidl/android/hardware/biometrics/face/EnrollmentStageConfig.aidl @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics.face; + +import android.hardware.biometrics.face.Cell; +import android.hardware.biometrics.face.EnrollmentStage; + +@VintfStability +parcelable EnrollmentStageConfig { + /** + * The stage that's being configured. + */ + EnrollmentStage stage = EnrollmentStage.UNKNOWN; + + /** + * Optional list of cells that must be completed to finish this stage. + */ + List cells; +} diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/EnrollmentType.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/EnrollmentType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..c9609339962207bd0c6b612c4d783feffeffe2b2 --- /dev/null +++ b/biometrics/face/aidl/android/hardware/biometrics/face/EnrollmentType.aidl @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics.face; + +@VintfStability +@Backing(type="byte") +enum EnrollmentType { + /** + * Default enrollment type. + */ + DEFAULT, + + /** + * Enrollment type for people with limited vision or mobility. For example, + * enrollment of this type will not ask the user to move their head or + * look directly at the device. + */ + ACCESSIBILITY, +} diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/Error.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/Error.aidl new file mode 100644 index 0000000000000000000000000000000000000000..e99415ac3681b7d5ca3c1f8e506a4ccec95f0a72 --- /dev/null +++ b/biometrics/face/aidl/android/hardware/biometrics/face/Error.aidl @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics.face; + +@VintfStability +@Backing(type="byte") +enum Error { + /** + * Placeholder value used for default initialization of Error. This value + * means Error wasn't explicitly initialized and must be discarded by the + * recipient. + */ + UNKNOWN, + + /** + * A hardware error has occurred that cannot be resolved. Try again later. + */ + HW_UNAVAILABLE, + + /** + * The current operation could not be completed, e.g. the sensor was unable + * to process the current image or the HAT was invalid. + */ + UNABLE_TO_PROCESS, + + /** + * The current operation took too long to complete. This is intended to + * prevent programs from blocking the face HAL indefinitely. The timeout is + * framework and sensor-specific, but is generally on the order of 30 + * seconds. + * + * The timeout is a device-specific time meant to optimize power. For + * example after 30 seconds of searching for a face it can be use to + * indicate that the implementation is no longer looking and the framework + * should restart the operation on the next user interaction. + */ + TIMEOUT, + + /** + * The current operation could not be completed because there is not enough + * storage space remaining to do so. + */ + NO_SPACE, + + /** + * The current operation has been cancelled. This may happen if a new + * request (authenticate, remove, enumerate, enroll) is initiated while + * an on-going operation is in progress, or if cancel() was called. + */ + CANCELED, + + /** + * The current remove operation could not be completed; the face template + * provided could not be removed. + */ + UNABLE_TO_REMOVE, + + /** + * Used to enable a vendor-specific error message. + */ + VENDOR, + + /** + * Authentication cannot be performed because re-enrollment is required. + */ + REENROLL_REQUIRED, +} diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/FaceSensorType.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/FaceSensorType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..a5ed2e84e790d6628cb9349d46834427d8bd66bc --- /dev/null +++ b/biometrics/face/aidl/android/hardware/biometrics/face/FaceSensorType.aidl @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics.face; + +@VintfStability +@Backing(type="byte") +enum FaceSensorType { + /** + * Placeholder value used for default initialization of FaceSensorType. + * This value means FaceSensorType wasn't explicitly initialized and must + * be discarded by the recipient. + */ + UNKNOWN, + + /** + * The face sensor is an RGB camera. + */ + RGB, + + /** + * The face sensor is an infrared camera. + */ + IR, +} diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/Feature.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/Feature.aidl new file mode 100644 index 0000000000000000000000000000000000000000..bff1a022b78e5ec1c479ede11da4db5480806847 --- /dev/null +++ b/biometrics/face/aidl/android/hardware/biometrics/face/Feature.aidl @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics.face; + +@VintfStability +@Backing(type="byte") +enum Feature { + /** + * Require the user to look at the device during enrollment and authentication. This feature + * can be disabled to accommodate people who have limited vision. + */ + REQUIRE_ATTENTION, + + /** + * Require a diverse set of poses during enrollment. This feature can be disabled to accommodate + * people with limited mobility. + */ + REQUIRE_DIVERSE_POSES, + + /** + * Enable debugging functionality. + */ + DEBUG, +} diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/IFace.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/IFace.aidl new file mode 100644 index 0000000000000000000000000000000000000000..4d7e59ebb76e657d92c6bc7d685127bdceef8224 --- /dev/null +++ b/biometrics/face/aidl/android/hardware/biometrics/face/IFace.aidl @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics.face; + +import android.hardware.biometrics.face.ISession; +import android.hardware.biometrics.face.ISessionCallback; +import android.hardware.biometrics.face.SensorProps; + +@VintfStability +interface IFace { + /** + * getSensorProps: + * + * @return A list of properties for all of the face sensors supported by the HAL. + */ + SensorProps[] getSensorProps(); + + /** + * createSession: + * + * Creates an instance of ISession that can be used by the framework to perform operations such + * as ISession#enroll, ISession#authenticate, etc. for the given sensorId and userId. + * + * Calling this method while there is an active session is considered an error. If the framework + * wants to create a new session when it already has an active session, it must first cancel the + * current operation if it's cancellable or wait until it completes. Then, the framework must + * explicitly close the session with ISession#close. Once the framework receives + * ISessionCallback#onSessionClosed, a new session can be created. + * + * Implementations must store user-specific state or metadata in /data/vendor_de//facedata + * as specified by the SELinux policy. The directory /data/vendor_de is managed by vold (see + * vold_prepare_subdirs.cpp). Implementations may store additional user-specific data, such as + * embeddings or templates, in StrongBox. + * + * @param sensorId The sensorId for which this session is being created. + * @param userId The userId for which this session is being created. + * @param cb A callback to notify the framework about the session's events. + * @return A new session. + */ + ISession createSession(in int sensorId, in int userId, in ISessionCallback cb); +} diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl new file mode 100644 index 0000000000000000000000000000000000000000..5f06b408e81030280fc45c0dfd87d6f5f0d12134 --- /dev/null +++ b/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl @@ -0,0 +1,444 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics.face; + +import android.hardware.biometrics.common.ICancellationSignal; +import android.hardware.biometrics.face.EnrollmentStageConfig; +import android.hardware.biometrics.face.EnrollmentType; +import android.hardware.biometrics.face.Feature; +import android.hardware.common.NativeHandle; +import android.hardware.keymaster.HardwareAuthToken; + +/** + * Operations defined within this interface can be divided into the following categories: + * 1) Cancellable operations. These are usually the operations that can execute for several + * minutes. To allow for cancellation, they return an instance of ICancellationSignal that + * lets the framework cancel them by calling ICancellationSignal#cancel. If such an operation + * is cancelled, it must notify the framework by calling ISessionCallback#onError with + * Error::CANCELED. + * 2) Non-cancellable operations. Such operations cannot be cancelled once started. + * + * The lifecycle of an operation ends when one of its terminal callbacks is called. For example, + * ISession#authenticate is considered completed when any of the following callbacks is called: + * ISessionCallback#onError, ISessionCallback#onAuthenticationSucceeded, + * ISessionCallback#onAuthenticationFailed. + * + * ISession only supports execution of one operation at a time, regardless of whether it's + * cancellable or not. The framework must wait for a corresponding callback indicating the end of + * the current operation before a new operation can be started. + */ + +@VintfStability +interface ISession { + /** + * generateChallenge: + * + * Begins a secure transaction request. Note that the challenge by itself is not useful. It only + * becomes useful when wrapped in a verifiable message such as a HardwareAuthToken. + * + * Canonical example: + * 1) User requests an operation, such as face enrollment. + * 2) Face enrollment cannot happen until the user confirms their lockscreen credential + * (PIN/Pattern/Password). + * 3) However, the biometric subsystem does not want just "any" proof of credential + * confirmation. It needs proof that the user explicitly authenticated credential in order + * to allow addition of biometric enrollments. + * To secure this path, the following path is taken: + * 1) Upon user requesting face enroll, the framework requests + * ISession#generateChallenge + * 2) Framework sends the challenge to the credential subsystem, and upon credential + * confirmation, a HAT is created, containing the challenge in the "challenge" field. + * 3) Framework sends the HAT to the HAL, e.g. ISession#enroll. + * 4) Implementation verifies the authenticity and integrity of the HAT. + * 5) Implementation now has confidence that the user entered their credential to allow + * biometric enrollment. + * + * Note that this interface allows multiple in-flight challenges. Invoking generateChallenge + * twice does not invalidate the first challenge. The challenge is invalidated only when: + * 1) Its lifespan exceeds the challenge timeout defined in the TEE. + * 2) IFingerprint#revokeChallenge is invoked + * + * For example, the following is a possible table of valid challenges: + * ---------------------------------------------- + * | SensorId | UserId | ValidUntil | Challenge | + * |----------|--------|------------|-----------| + * | 0 | 0 | | | + * | 0 | 0 | | | + * | 1 | 0 | | | + * | 0 | 10 | | | + * ---------------------------------------------- + * + * Callbacks that signify the end of this operation's lifecycle: + * - ISessionCallback#onChallengeGenerated + * + */ + void generateChallenge(); + + /** + * revokeChallenge: + * + * Revokes a challenge that was previously generated. Note that if a non-existent challenge is + * provided, the HAL must still notify the framework using ISessionCallback#onChallengeRevoked. + * + * Callbacks that signify the end of this operation's lifecycle: + * - ISessionCallback#onChallengeRevoked + * + * @param challenge Challenge that should be revoked. + */ + void revokeChallenge(in long challenge); + + /** + * getEnrollmentConfig: + * + * Returns the enrollment configuration for the provided enrollment type. Enrollment + * configuration determines how many stages the enrollment will have and the requirements + * for each of the stages. + * + * @param enrollmentType See the EnrollmentType enum. + * @return An EnrollmentStageConfig array that describes each enrollment stage. + */ + EnrollmentStageConfig[] getEnrollmentConfig(in EnrollmentType enrollmentType); + + /** + * enroll: + * + * A request to add a face enrollment. + * + * At any point during enrollment, if a non-recoverable error occurs, the HAL must notify the + * framework via ISessionCallback#onError with the applicable enrollment-specific error. + * + * Before capturing face data, the HAL must first verify the authenticity and integrity of the + * provided HardwareAuthToken. In addition, it must check that the challenge within the provided + * HardwareAuthToken is valid. See ISession#generateChallenge. If any of the above checks fail, + * the framework must be notified using ISessionCallback#onError with Error::UNABLE_TO_PROCESS. + * + * During enrollment, the HAL may notify the framework via ISessionCallback#onAcquired with + * messages that may be used to guide the user. This callback can be invoked multiple times if + * necessary. Similarly, the framework may be notified of enrollment progress changes via + * ISessionCallback#onEnrollmentProgress. Once the framework is notified that there are 0 + * "remaining" steps, the framework may cache the "enrollmentId". See + * ISessionCallback#onEnrollmentProgress for more info. + * + * When a face is successfully added and before the framework is notified of remaining=0, the + * HAL must update and associate this (sensorId, userId) pair with a new entropy-encoded random + * identifier. See ISession#getAuthenticatorId for more information. + * + * Callbacks that signify the end of this operation's lifecycle: + * - ISessionCallback#onError + * - ISessionCallback#onEnrollmentProgress(enrollmentId, remaining=0) + * + * Other applicable callbacks: + * - ISessionCallback#onAcquired + * + * @param hat See above documentation. + * @param enrollmentType See the EnrollmentType enum. + * @param features See the Feature enum. + * @param previewSurface A surface provided by the framework if SensorProps#halControlsPreview + * is set to true. The HAL must send the preview frames to previewSurface + * if it's not null. + * @return ICancellationSignal An object that can be used by the framework to cancel this + * operation. + */ + ICancellationSignal enroll(in HardwareAuthToken hat, in EnrollmentType type, + in Feature[] features, in @nullable NativeHandle previewSurface); + + /** + * authenticate: + * + * A request to start looking for faces to authenticate. + * + * At any point during authentication, if a non-recoverable error occurs, the HAL must notify + * the framework via ISessionCallback#onError with the applicable authentication-specific error. + * + * During authentication, the HAL may notify the framework via ISessionCallback#onAcquired with + * messages that may be used to guide the user. This callback can be invoked multiple times if + * necessary. + * + * The HAL must notify the framework of accepts/rejects via + * ISessionCallback#onAuthenticationSucceeded and ISessionCallback#onAuthenticationFailed, + * correspondingly. + * + * The authentication lifecycle ends when any of the following happens: + * 1) A face is accepted, and ISessionCallback#onAuthenticationSucceeded is invoked. + * 2) A face is rejected, and ISessionCallback#onAuthenticationFailed is invoked. + * 3) Any non-recoverable error occurs (such as lockout). See the full list of + * authentication-specific errors in the Error enum. + * + * Note that upon successful authentication, the lockout counter for this (sensorId, userId) + * pair must be cleared. + * + * Note that upon successful authentication, ONLY sensors configured as SensorStrength::STRONG + * are allowed to create and send a HardwareAuthToken to the framework. See the Android CDD for + * more details. For SensorStrength::STRONG sensors, the HardwareAuthToken's "challenge" field + * must be set with the operationId passed in during #authenticate. If the sensor is NOT + * SensorStrength::STRONG, the HardwareAuthToken MUST be null. + * + * Callbacks that signify the end of this operation's lifecycle: + * - ISessionCallback#onError + * - ISessionCallback#onAuthenticationSucceeded + * - ISessionCallback#onAuthenticationFailed + * + * Other applicable callbacks: + * - ISessionCallback#onAcquired + * - ISessionCallback#onLockoutTimed + * - ISessionCallback#onLockoutPermanent + * + * @param operationId For sensors configured as SensorStrength::STRONG, this must be used ONLY + * upon successful authentication and wrapped in the HardwareAuthToken's + * "challenge" field and sent to the framework via + * ISessionCallback#onAuthenticationSucceeded. The operationId is an opaque + * identifier created from a separate secure subsystem such as, but not + * limited to KeyStore/KeyMaster. The HardwareAuthToken can then be used as + * an attestation for the provided operation. For example, this is used to + * unlock biometric-bound auth-per-use keys (see + * setUserAuthenticationParameters in KeyGenParameterSpec.Builder and + * KeyProtection.Builder). + * @return ICancellationSignal An object that can be used by the framework to cancel this + * operation. + */ + ICancellationSignal authenticate(in long operationId); + + /** + * detectInteraction: + * + * A request to start looking for faces without performing matching. Must only be called if + * SensorProps#supportsDetectInteraction is true. If invoked on HALs that do not support this + * functionality, the HAL must respond with ISession#onError(UNABLE_TO_PROCESS, 0). + * + * The framework will use this operation in cases where determining user presence is required, + * but identifying/authenticating is not. For example, when the device is encrypted (first boot) + * or in lockdown mode. + * + * At any point during detectInteraction, if a non-recoverable error occurs, the HAL must notify + * the framework via ISessionCallback#onError with the applicable error. + * + * The HAL must only check whether a face-like image was detected (e.g. to minimize interactions + * due to non-face objects), and the lockout counter must not be modified. + * + * Upon detecting any face, the HAL must invoke ISessionCallback#onInteractionDetected. + * + * The lifecycle of this operation ends when either: + * 1) Any face is detected and the framework is notified via + * ISessionCallback#onInteractionDetected. + * 2) An error occurrs, for example Error::TIMEOUT. + * + * Note that if the operation is canceled, the HAL must notify the framework via + * ISessionCallback#onError with Error::CANCELED. + * + * Callbacks that signify the end of this operation's lifecycle: + * - ISessionCallback#onError + * - ISessionCallback#onInteractionDetected + * + * Other applicable callbacks: + * - ISessionCallback#onAcquired + * + * @return ICancellationSignal An object that can be used by the framework to cancel this + * operation. + */ + ICancellationSignal detectInteraction(); + + /* + * enumerateEnrollments: + * + * A request to enumerate (list) the enrollments for this (sensorId, userId) pair. The framework + * typically uses this to ensure that its cache is in sync with the HAL. + * + * The HAL must then notify the framework with a list of enrollments applicable for the current + * session via ISessionCallback#onEnrollmentsEnumerated. + * + * Callbacks that signify the end of this operation's lifecycle: + * - ISessionCallback#onEnrollmentsEnumerated + */ + void enumerateEnrollments(); + + /** + * removeEnrollments: + * + * A request to remove the enrollments for this (sensorId, userId) pair. + * + * After removing the enrollmentIds from everywhere necessary (filesystem, secure subsystems, + * etc), the HAL must notify the framework via ISessionCallback#onEnrollmentsRemoved. + * + * Callbacks that signify the end of this operation's lifecycle: + * - ISessionCallback#onEnrollmentsRemoved + * + * @param enrollmentIds a list of enrollments that should be removed. + */ + void removeEnrollments(in int[] enrollmentIds); + + /** + * getFeatures: + * + * Returns a list of currently enabled features for this (sensorId, userId) pair. + * + * If the user is not enrolled, the HAL must invoke ISessionCallback#onError with + * Error::UNABLE_TO_PROCESS. + * + * The HAL must notify the framework about the result by calling + * ISessionCallback#onFeaturesRetrieved. + * + * Callbacks that signify the end of this operation's lifecycle: + * - ISessionCallback#onError + * - ISessionCallback#onFeaturesRetrieved + */ + void getFeatures(); + + /** + * setFeature: + * + * Enables or disables a feature for this (sensorId, userId) pair. Because certain features may + * decrease security, the user must enter their password before this operation is invoked + * (see @param hat). The HAL must verify the HAT before changing any feature state. + * + * If the HAT is invalid or if the user is not enrolled, the HAL must invoke + * ISessionCallback#onError with Error::UNABLE_TO_PROCESS. + * + * After the feature is successfully set, the HAL must notify the framework by calling + * ISessionCallback#onFeatureSet. + * + * Callbacks that signify the end of this operation's lifecycle: + * - ISessionCallback#onError + * - ISessionCallback#onFeatureSet + * + * @param hat HardwareAuthToken See above documentation. + * @param feature The feature to be enabled or disabled. + * @param enabled Whether the provided features should be enabled or disabled. + */ + void setFeature(in HardwareAuthToken hat, in Feature feature, boolean enabled); + + /** + * getAuthenticatorId: + * + * MUST return 0 via ISessionCallback#onAuthenticatorIdRetrieved for sensors that are configured + * as SensorStrength::WEAK or SensorStrength::CONVENIENCE. + * + * The following only applies to sensors that are configured as SensorStrength::STRONG. + * + * The authenticatorId is a (sensorId, user)-specific identifier which can be used during key + * generation and key import to to associate a key (in KeyStore / KeyMaster) with the current + * set of enrolled faces. For example, the following public Android APIs allow for keys + * to be invalidated when the user adds a new enrollment after the key was created: + * KeyGenParameterSpec.Builder.setInvalidatedByBiometricEnrollment and + * KeyProtection.Builder.setInvalidatedByBiometricEnrollment. + * + * In addition, upon successful face authentication, the signed HAT that is returned to + * the framework via ISessionCallback#onAuthenticationSucceeded must contain this identifier in + * the authenticatorId field. + * + * Returns an entropy-encoded random identifier associated with the current set of enrollments + * via ISessionCallback#onAuthenticatorIdRetrieved. The authenticatorId + * 1) MUST change whenever a new face is enrolled + * 2) MUST return 0 if no faces are enrolled + * 3) MUST not change if a face is deleted. + * 4) MUST be an entropy-encoded random number + * + * Callbacks that signify the end of this operation's lifecycle: + * - ISessionCallback#onAuthenticatorIdRetrieved + */ + void getAuthenticatorId(); + + /** + * invalidateAuthenticatorId: + * + * This operation only applies to sensors that are configured as SensorStrength::STRONG. If + * invoked by the framework for sensors of other strengths, the HAL should immediately invoke + * ISessionCallback#onAuthenticatorIdInvalidated. + * + * The following only applies to sensors that are configured as SensorStrength::STRONG. + * + * When invoked by the framework, the HAL must perform the following sequence of events: + * 1) Update the authenticatorId with a new entropy-encoded random number + * 2) Persist the new authenticatorId to non-ephemeral storage + * 3) Notify the framework that the above is completed, via + * ISessionCallback#onAuthenticatorInvalidated + * + * A practical use case of invalidation would be when the user adds a new enrollment to a sensor + * managed by a different HAL instance. The public android.security.keystore APIs bind keys to + * "all biometrics" rather than "fingerprint-only" or "face-only" (see #getAuthenticatorId for + * more details). As such, the framework would coordinate invalidation across multiple biometric + * HALs as necessary. + * + * Callbacks that signify the end of this operation's lifecycle: + * - ISessionCallback#onAuthenticatorIdInvalidated + */ + void invalidateAuthenticatorId(); + + /** + * resetLockout: + * + * Requests the HAL to clear the lockout counter. Upon receiving this request, the HAL must + * perform the following: + * 1) Verify the authenticity and integrity of the provided HAT + * 2) Verify that the timestamp provided within the HAT is relatively recent (e.g. on the + * order of minutes, not hours). + * If either of the checks fail, the HAL must invoke ISessionCallback#onError with + * Error::UNABLE_TO_PROCESS. + * + * Upon successful verification, the HAL must clear the lockout counter and notify the framework + * via ISessionCallback#onLockoutCleared. + * + * Note that lockout is user AND sensor specific. In other words, there is a separate lockout + * state for each (user, sensor) pair. For example, the following is a valid state on a + * multi-sensor device: + * ------------------------------------------------------------------ + * | SensorId | UserId | FailedAttempts | LockedOut | LockedUntil | + * |----------|--------|----------------|-----------|---------------| + * | 0 | 0 | 1 | false | x | + * | 1 | 0 | 5 | true | | + * | 0 | 10 | 0 | false | x | + * | 1 | 10 | 0 | false | x | + * ------------------------------------------------------------------ + * + * Lockout may be cleared in the following ways: + * 1) ISession#resetLockout + * 2) After a period of time, according to a rate-limiter. + * + * Note that the "FailedAttempts" counter must be cleared upon successful face + * authentication. For example, if SensorId=0 UserId=0 FailedAttempts=1, and a successful + * face authentication occurs, the counter for that (SensorId, UserId) pair must be reset + * to 0. + * + * In addition, lockout states MUST persist after device reboots, HAL crashes, etc. + * + * See the Android CDD section 7.3.10 for the full set of lockout and rate-limiting + * requirements. + * + * Callbacks that signify the end of this operation's lifecycle: + * - ISessionCallback#onLockoutCleared + * + * @param hat HardwareAuthToken See above documentation. + */ + void resetLockout(in HardwareAuthToken hat); + + /* + * Close this session and allow the HAL to release the resources associated with this session. + * + * A session can only be closed when the HAL is idling, i.e. not performing any operations. + * If the HAL is busy performing a cancellable operation, the operation must be explicitly + * cancelled with a call to ICancellationSignal#cancel before the session can be closed. + * + * After a session is closed, the HAL must notify the framework by calling + * ISessionCallback#onSessionClosed. + * + * All sessions must be explicitly closed. Calling IFace#createSession while there is an active + * session is considered an error. + * + * Callbacks that signify the end of this operation's lifecycle: + * - ISessionCallback#onSessionClosed + */ + void close(); +} diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..b3c348d5212c0299a846ead2e6e6c22ad8db1d00 --- /dev/null +++ b/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics.face; + +import android.hardware.biometrics.face.AcquiredInfo; +import android.hardware.biometrics.face.AuthenticationFrame; +import android.hardware.biometrics.face.EnrollmentFrame; +import android.hardware.biometrics.face.Error; +import android.hardware.biometrics.face.Feature; +import android.hardware.keymaster.HardwareAuthToken; + +@VintfStability +interface ISessionCallback { + /** + * Notifies the framework when a challenge is successfully generated. + */ + void onChallengeGenerated(in long challenge); + + /** + * Notifies the framework when a challenge has been revoked. + */ + void onChallengeRevoked(in long challenge); + + /** + * This method must only be used to notify the framework during the following operations: + * - ISession#authenticate + * - ISession#detectInteraction + * + * These messages may be used to provide user guidance multiple times per operation if + * necessary. + * + * @param frame See the AuthenticationFrame enum. + */ + void onAuthenticationFrame(in AuthenticationFrame frame); + + /** + * This method must only be used to notify the framework during the ISession#enroll + * operation. + * + * These messages may be used to provide user guidance multiple times per operation if + * necessary. + * + * @param frame See the EnrollmentFrame enum. + */ + void onEnrollmentFrame(in EnrollmentFrame frame); + + /** + * This method must only be used to notify the framework during the following operations: + * - ISession#enroll + * - ISession#authenticate + * - ISession#detectInteraction + * - ISession#invalidateAuthenticatorId + * - ISession#resetLockout + * + * These messages may be used to notify the framework or user that a non-recoverable error + * has occurred. The operation is finished, and the HAL must proceed with the next operation + * or return to the idling state. + * + * Note that cancellation (see common::ICancellationSignal) must be followed with an + * Error::CANCELED message. + * + * @param error See the Error enum. + * @param vendorCode Only valid if error == Error::VENDOR. The vendorCode must be used to index + * into the configuration + * com.android.internal.R.face_error_vendor that's installed on the + * vendor partition. + */ + void onError(in Error error, in int vendorCode); + + /** + * This method must only be used to notify the framework during the ISession#enroll operation. + * + * @param enrollmentId Unique stable identifier for the enrollment that's being added by this + * ISession#enroll invocation. + * @param remaining Remaining number of steps before enrollment is complete. + */ + void onEnrollmentProgress(in int enrollmentId, int remaining); + + /** + * This method must only be used to notify the framework during ISession#authenticate. + * + * Used to notify the framework about a successful authentication. This ends the authentication + * lifecycle. + * + * @param enrollmentId Face that was accepted. + * @param hat If the sensor is configured as SensorStrength::STRONG, a non-null attestation that + * a face was accepted. The HardwareAuthToken's "challenge" field must be set + * with the operationId passed in during ISession#authenticate. If the sensor is NOT + * SensorStrength::STRONG, the HardwareAuthToken MUST be null. + */ + void onAuthenticationSucceeded(in int enrollmentId, in HardwareAuthToken hat); + + /** + * This method must only be used to notify the framework during ISession#authenticate. + * + * Used to notify the framework about a failed authentication. This ends the authentication + * lifecycle. + */ + void onAuthenticationFailed(); + + /** + * This method must only be used to notify the framework during ISession#authenticate. + * + * Authentication is locked out due to too many unsuccessful attempts. This is a rate-limiting + * lockout, and authentication can be restarted after a period of time. See + * ISession#resetLockout. + * + * @param sensorId Sensor for which the user is locked out. + * @param userId User for which the sensor is locked out. + * @param durationMillis Remaining duration of the lockout. + */ + void onLockoutTimed(in long durationMillis); + + /** + * This method must only be used to notify the framework during ISession#authenticate. + * + * Authentication is disabled until the user unlocks with their device credential + * (PIN/Pattern/Password). See ISession#resetLockout. + * + * @param sensorId Sensor for which the user is locked out. + * @param userId User for which the sensor is locked out. + */ + void onLockoutPermanent(); + + /** + * Notifies the framework that lockout has been cleared for this (sensorId, userId) pair. + * + * Note that this method can be used to notify the framework during any state. + * + * Lockout can be cleared in the following scenarios: + * 1) A timed lockout has ended (e.g. durationMillis specified in previous #onLockoutTimed + * has expired. + * 2) See ISession#resetLockout. + * + * @param sensorId Sensor for which the user's lockout is cleared. + * @param userId User for the sensor's lockout is cleared. + */ + void onLockoutCleared(); + + /** + * This method must only be used to notify the framework during + * ISession#detectInteraction + * + * Notifies the framework that user interaction occurred. See ISession#detectInteraction. + */ + void onInteractionDetected(); + + /** + * This method must only be used to notify the framework during + * ISession#enumerateEnrollments. + * + * Notifies the framework of the current enrollments. See ISession#enumerateEnrollments. + * + * @param enrollmentIds A list of enrollments for the session's (userId, sensorId) pair. + */ + void onEnrollmentsEnumerated(in int[] enrollmentIds); + + /** + * This method must only be used to notify the framework during ISession#getFeatures. + * + * Provides a list of features that are currently enabled for the session's (userId, sensorId) + * pair. + * + * @param features A list of currently enabled features. See the Feature enum. + */ + void onFeaturesRetrieved(in Feature[] features); + + /** + * This method must only be used to notify the framework during ISession#setFeature. + * + * Notifies the framework that ISession#setFeature has completed. + * + * @param feature The feature that was set. + */ + void onFeatureSet(Feature feature); + + /** + * This method must only be used to notify the framework during + * ISession#removeEnrollments. + * + * Notifies the framework that the specified enrollments are removed. + * + * @param enrollmentIds The enrollments that were removed. + */ + void onEnrollmentsRemoved(in int[] enrollmentIds); + + /** + * This method must only be used to notify the framework during + * ISession#getAuthenticatorId. + * + * Notifies the framework with the authenticatorId corresponding to this session's + * (userId, sensorId) pair. + * + * @param authenticatorId See the above documentation. + */ + void onAuthenticatorIdRetrieved(in long authenticatorId); + + /** + * This method must only be used to notify the framework during + * ISession#invalidateAuthenticatorId. + * + * See ISession#invalidateAuthenticatorId for more information. + * + * @param newAuthenticatorId The new entropy-encoded random identifier associated with the + * current set of enrollments. + */ + void onAuthenticatorIdInvalidated(in long newAuthenticatorId); + + /** + * This method notifes the client that this session has closed. + * The client must not make any more calls to this session. + */ + void onSessionClosed(); +} diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/SensorProps.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/SensorProps.aidl new file mode 100644 index 0000000000000000000000000000000000000000..5f881ca1d3973352c1e4270f25e42eba0cff0c23 --- /dev/null +++ b/biometrics/face/aidl/android/hardware/biometrics/face/SensorProps.aidl @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics.face; + +import android.hardware.biometrics.common.CommonProps; +import android.hardware.biometrics.face.FaceSensorType; + +@VintfStability +parcelable SensorProps { + /** + * Statically configured properties that apply to this face sensor. + */ + CommonProps commonProps; + + /** + * A statically configured sensor type representing this face sensor. + */ + FaceSensorType sensorType = FaceSensorType.UNKNOWN; + + /** + * Whether or not the HAL is responsible for showing the face enrollment preview to the user. + * Devices with multiple front camera sensors can set this to false and rely on the framework to + * show the preview with one of the unused cameras. Devices with a single front sensor must set + * this to true and configure their send their camera stream to the preview surface provided by + * the framework. + */ + boolean halControlsPreview; + + /** + * The ID of the display that's used for enrollment preview. This must correspond to the + * android.hardware.DisplayManager#getDisplay Android API. This is useful for devices with + * multiple displays to ensure the correct display is used for this face sensor. + */ + int previewDisplayId; + + /** + * For implementations where the HAL manages the preview, this is the width, in pixels, of each + * frame that the camera is set up to output. + */ + int enrollPreviewWidth; + + /** + * For implementations where the HAL manages the preview, this is the height, in pixels, of + * each frame that the camera is set up to output. + */ + int enrollPreviewHeight; + + /** + * For implementations where the HAL manages the preview, this is the distance in pixels that + * the enrollment preview should be translated. This is typically used by devices where the + * camera used for enrollment preview is not centered. + */ + float enrollTranslationX; + + /** + * For implementations where the HAL manages the preview, this is the distance in pixels that + * the enrollment preview should be translated. + */ + float enrollTranslationY; + + /** + * For implementations where the HAL manages the preview, this is the scale factor that should + * be applied when configuring the preview texture. + */ + float enrollPreviewScale; + + /** + * Specifies whether or not the implementation supports ISession#detectInteraction. + */ + boolean supportsDetectInteraction; +} diff --git a/biometrics/face/aidl/default/Android.bp b/biometrics/face/aidl/default/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..509231859d604af8c91c746c6dadd3ac59fa8c5b --- /dev/null +++ b/biometrics/face/aidl/default/Android.bp @@ -0,0 +1,27 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_binary { + name: "android.hardware.biometrics.face-service.example", + relative_install_path: "hw", + init_rc: ["face-default.rc"], + vintf_fragments: ["face-default.xml"], + vendor: true, + shared_libs: [ + "libbase", + "libbinder_ndk", + "android.hardware.biometrics.face-V1-ndk", + "android.hardware.biometrics.common-V1-ndk", + ], + srcs: [ + "main.cpp", + "Face.cpp", + "Session.cpp", + ], +} diff --git a/biometrics/face/aidl/default/Face.cpp b/biometrics/face/aidl/default/Face.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aca3e135f600fbbd7989e2b7fd4c239932f65bac --- /dev/null +++ b/biometrics/face/aidl/default/Face.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Face.h" +#include "Session.h" + +namespace aidl::android::hardware::biometrics::face { + +const int kSensorId = 4; +const common::SensorStrength kSensorStrength = common::SensorStrength::STRONG; +const int kMaxEnrollmentsPerUser = 5; +const FaceSensorType kSensorType = FaceSensorType::RGB; +const bool kHalControlsPreview = true; +const std::string kHwComponentId = "faceSensor"; +const std::string kHardwareVersion = "vendor/model/revision"; +const std::string kFirmwareVersion = "1.01"; +const std::string kSerialNumber = "00000001"; +const std::string kSwComponentId = "matchingAlgorithm"; +const std::string kSoftwareVersion = "vendor/version/revision"; + +ndk::ScopedAStatus Face::getSensorProps(std::vector* return_val) { + common::ComponentInfo hw_component_info; + hw_component_info.componentId = kHwComponentId; + hw_component_info.hardwareVersion = kHardwareVersion; + hw_component_info.firmwareVersion = kFirmwareVersion; + hw_component_info.serialNumber = kSerialNumber; + hw_component_info.softwareVersion = ""; + + common::ComponentInfo sw_component_info; + sw_component_info.componentId = kSwComponentId; + sw_component_info.hardwareVersion = ""; + sw_component_info.firmwareVersion = ""; + sw_component_info.serialNumber = ""; + sw_component_info.softwareVersion = kSoftwareVersion; + + common::CommonProps commonProps; + commonProps.sensorId = kSensorId; + commonProps.sensorStrength = kSensorStrength; + commonProps.maxEnrollmentsPerUser = kMaxEnrollmentsPerUser; + commonProps.componentInfo = {std::move(hw_component_info), std::move(sw_component_info)}; + + SensorProps props; + props.commonProps = std::move(commonProps); + props.sensorType = kSensorType; + props.halControlsPreview = kHalControlsPreview; + props.enrollPreviewWidth = 1080; + props.enrollPreviewHeight = 1920; + props.enrollTranslationX = 100.f; + props.enrollTranslationY = 50.f; + props.enrollPreviewScale = 1.f; + + *return_val = {std::move(props)}; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Face::createSession(int32_t /*sensorId*/, int32_t /*userId*/, + const std::shared_ptr& cb, + std::shared_ptr* return_val) { + *return_val = SharedRefBase::make(cb); + return ndk::ScopedAStatus::ok(); +} + +} // namespace aidl::android::hardware::biometrics::face diff --git a/biometrics/face/aidl/default/Face.h b/biometrics/face/aidl/default/Face.h new file mode 100644 index 0000000000000000000000000000000000000000..786b4f89fe5210a5c15dbe932d36534c9f887fcd --- /dev/null +++ b/biometrics/face/aidl/default/Face.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +namespace aidl::android::hardware::biometrics::face { + +class Face : public BnFace { + public: + ndk::ScopedAStatus getSensorProps(std::vector* _aidl_return) override; + + ndk::ScopedAStatus createSession(int32_t sensorId, int32_t userId, + const std::shared_ptr& cb, + std::shared_ptr* _aidl_return) override; +}; + +} // namespace aidl::android::hardware::biometrics::face diff --git a/biometrics/face/aidl/default/Session.cpp b/biometrics/face/aidl/default/Session.cpp new file mode 100644 index 0000000000000000000000000000000000000000..01cb620b351ebe3ed59e81dff225676684f17fe6 --- /dev/null +++ b/biometrics/face/aidl/default/Session.cpp @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "Session.h" + +namespace aidl::android::hardware::biometrics::face { + +class CancellationSignal : public common::BnCancellationSignal { + private: + std::shared_ptr cb_; + + public: + explicit CancellationSignal(std::shared_ptr cb) : cb_(std::move(cb)) {} + + ndk::ScopedAStatus cancel() override { + cb_->onError(Error::CANCELED, 0 /* vendorCode */); + return ndk::ScopedAStatus::ok(); + } +}; + +Session::Session(std::shared_ptr cb) + : cb_(std::move(cb)), mRandom(std::mt19937::default_seed) {} + +ndk::ScopedAStatus Session::generateChallenge() { + LOG(INFO) << "generateChallenge"; + if (cb_) { + std::uniform_int_distribution dist; + auto challenge = dist(mRandom); + cb_->onChallengeGenerated(challenge); + } + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Session::revokeChallenge(int64_t challenge) { + LOG(INFO) << "revokeChallenge"; + if (cb_) { + cb_->onChallengeRevoked(challenge); + } + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Session::getEnrollmentConfig(EnrollmentType /*enrollmentType*/, + std::vector* return_val) { + *return_val = {}; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Session::enroll( + const keymaster::HardwareAuthToken& /*hat*/, EnrollmentType /*enrollmentType*/, + const std::vector& /*features*/, + const std::optional& /*previewSurface*/, + std::shared_ptr* /*return_val*/) { + LOG(INFO) << "enroll"; + if (cb_) { + cb_->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */); + } + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Session::authenticate(int64_t /*keystoreOperationId*/, + std::shared_ptr* return_val) { + LOG(INFO) << "authenticate"; + if (cb_) { + cb_->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorCode */); + } + *return_val = SharedRefBase::make(cb_); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Session::detectInteraction( + std::shared_ptr* /*return_val*/) { + LOG(INFO) << "detectInteraction"; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Session::enumerateEnrollments() { + LOG(INFO) << "enumerateEnrollments"; + if (cb_) { + cb_->onEnrollmentsEnumerated(std::vector()); + } + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Session::removeEnrollments(const std::vector& /*enrollmentIds*/) { + LOG(INFO) << "removeEnrollments"; + if (cb_) { + cb_->onEnrollmentsRemoved(std::vector()); + } + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Session::getFeatures() { + LOG(INFO) << "getFeatures"; + if (cb_) { + // Must error out with UNABLE_TO_PROCESS when no faces are enrolled. + cb_->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorCode */); + } + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Session::setFeature(const keymaster::HardwareAuthToken& /*hat*/, + Feature /*feature*/, bool /*enabled*/) { + LOG(INFO) << "setFeature"; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Session::getAuthenticatorId() { + LOG(INFO) << "getAuthenticatorId"; + if (cb_) { + cb_->onAuthenticatorIdRetrieved(0 /* authenticatorId */); + } + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Session::invalidateAuthenticatorId() { + LOG(INFO) << "invalidateAuthenticatorId"; + if (cb_) { + cb_->onAuthenticatorIdInvalidated(0); + } + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Session::resetLockout(const keymaster::HardwareAuthToken& /*hat*/) { + LOG(INFO) << "resetLockout"; + if (cb_) { + cb_->onLockoutCleared(); + } + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Session::close() { + if (cb_) { + cb_->onSessionClosed(); + } + return ndk::ScopedAStatus::ok(); +} + +} // namespace aidl::android::hardware::biometrics::face diff --git a/biometrics/face/aidl/default/Session.h b/biometrics/face/aidl/default/Session.h new file mode 100644 index 0000000000000000000000000000000000000000..4152909a4945e2e7333d55813037a60286fd8e36 --- /dev/null +++ b/biometrics/face/aidl/default/Session.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include +#include + +namespace aidl::android::hardware::biometrics::face { + +namespace common = aidl::android::hardware::biometrics::common; +namespace keymaster = aidl::android::hardware::keymaster; + +using aidl::android::hardware::common::NativeHandle; + +class Session : public BnSession { + public: + explicit Session(std::shared_ptr cb); + + ndk::ScopedAStatus generateChallenge() override; + + ndk::ScopedAStatus revokeChallenge(int64_t challenge) override; + + ndk::ScopedAStatus getEnrollmentConfig(EnrollmentType enrollmentType, + std::vector* return_val) override; + + ndk::ScopedAStatus enroll(const keymaster::HardwareAuthToken& hat, + EnrollmentType enrollmentType, const std::vector& features, + const std::optional& previewSurface, + std::shared_ptr* return_val) override; + + ndk::ScopedAStatus authenticate( + int64_t keystoreOperationId, + std::shared_ptr* returnVal) override; + + ndk::ScopedAStatus detectInteraction( + std::shared_ptr* returnVal) override; + + ndk::ScopedAStatus enumerateEnrollments() override; + + ndk::ScopedAStatus removeEnrollments(const std::vector& enrollmentIds) override; + + ndk::ScopedAStatus getFeatures() override; + + ndk::ScopedAStatus setFeature(const keymaster::HardwareAuthToken& hat, Feature feature, + bool enabled) override; + + ndk::ScopedAStatus getAuthenticatorId() override; + + ndk::ScopedAStatus invalidateAuthenticatorId() override; + + ndk::ScopedAStatus resetLockout(const keymaster::HardwareAuthToken& hat) override; + + ndk::ScopedAStatus close() override; + + private: + std::shared_ptr cb_; + std::mt19937 mRandom; +}; + +} // namespace aidl::android::hardware::biometrics::face diff --git a/biometrics/face/aidl/default/face-default.rc b/biometrics/face/aidl/default/face-default.rc new file mode 100644 index 0000000000000000000000000000000000000000..f6499f0a099f5b8943377dcc3950a7093c10b07e --- /dev/null +++ b/biometrics/face/aidl/default/face-default.rc @@ -0,0 +1,5 @@ +service vendor.face-default /vendor/bin/hw/android.hardware.biometrics.face-service.example + class hal + user nobody + group nobody + diff --git a/biometrics/face/aidl/default/face-default.xml b/biometrics/face/aidl/default/face-default.xml new file mode 100644 index 0000000000000000000000000000000000000000..6915ad0a4d346dfa7eea197b2e0f30140ee002b7 --- /dev/null +++ b/biometrics/face/aidl/default/face-default.xml @@ -0,0 +1,6 @@ + + + android.hardware.biometrics.face + IFace/default + + diff --git a/biometrics/face/aidl/default/main.cpp b/biometrics/face/aidl/default/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..80b153ea1fbf10f5c80bd6c0dcf9acc508a057bd --- /dev/null +++ b/biometrics/face/aidl/default/main.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Face.h" + +#include +#include +#include + +using aidl::android::hardware::biometrics::face::Face; + +int main() { + LOG(INFO) << "Face HAL started"; + ABinderProcess_setThreadPoolMaxThreadCount(0); + std::shared_ptr hal = ndk::SharedRefBase::make(); + + const std::string instance = std::string(Face::descriptor) + "/default"; + binder_status_t status = AServiceManager_addService(hal->asBinder().get(), instance.c_str()); + CHECK(status == STATUS_OK); + + ABinderProcess_joinThreadPool(); + return EXIT_FAILURE; // should not reach +} diff --git a/biometrics/face/aidl/vts/Android.bp b/biometrics/face/aidl/vts/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..09ec4d06e31352733dc8807477458f4de0148dc1 --- /dev/null +++ b/biometrics/face/aidl/vts/Android.bp @@ -0,0 +1,30 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_test { + name: "VtsHalBiometricsFaceTargetTest", + defaults: [ + "VtsHalTargetTestDefaults", + "use_libaidlvintf_gtest_helper_static", + ], + srcs: ["VtsHalBiometricsFaceTargetTest.cpp"], + static_libs: [ + "android.hardware.biometrics.common-V1-ndk", + "android.hardware.biometrics.face-V1-ndk", + "android.hardware.common-V2-ndk", + "android.hardware.keymaster-V3-ndk", + ], + shared_libs: [ + "libbinder_ndk", + ], + test_suites: [ + "general-tests", + "vts", + ], +} diff --git a/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp b/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..08ab5d694b4b406fc9ab4a50f5195fd772e6b023 --- /dev/null +++ b/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp @@ -0,0 +1,336 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include + +#include +#include + +#include +#include + +namespace aidl::android::hardware::biometrics::face { +namespace { + +using namespace std::literals::chrono_literals; + +using aidl::android::hardware::common::NativeHandle; + +constexpr int kSensorId = 0; +constexpr int kUserId = 0; + +class SessionCallback : public BnSessionCallback { + public: + ndk::ScopedAStatus onChallengeGenerated(int64_t challenge) override { + auto lock = std::lock_guard{mMutex}; + mOnChallengeGeneratedInvoked = true; + mGeneratedChallenge = challenge; + mCv.notify_one(); + return ndk::ScopedAStatus::ok(); + } + + ndk::ScopedAStatus onChallengeRevoked(int64_t challenge) override { + auto lock = std::lock_guard{mMutex}; + mOnChallengeRevokedInvoked = true; + mRevokedChallenge = challenge; + mCv.notify_one(); + return ndk::ScopedAStatus::ok(); + } + + ndk::ScopedAStatus onAuthenticationFrame(const AuthenticationFrame& /*frame*/) override { + return ndk::ScopedAStatus::ok(); + } + + ndk::ScopedAStatus onEnrollmentFrame(const EnrollmentFrame& /*frame*/) override { + return ndk::ScopedAStatus::ok(); + } + + ndk::ScopedAStatus onError(Error error, int32_t vendorCode) override { + auto lock = std::lock_guard{mMutex}; + mError = error; + mVendorCode = vendorCode; + mOnErrorInvoked = true; + mCv.notify_one(); + return ndk::ScopedAStatus::ok(); + } + + ndk::ScopedAStatus onEnrollmentProgress(int32_t /*enrollmentId*/, + int32_t /*remaining*/) override { + return ndk::ScopedAStatus::ok(); + } + + ndk::ScopedAStatus onAuthenticationSucceeded( + int32_t /*enrollmentId*/, const keymaster::HardwareAuthToken& /*hat*/) override { + return ndk::ScopedAStatus::ok(); + } + + ndk::ScopedAStatus onAuthenticationFailed() override { return ndk::ScopedAStatus::ok(); } + + ndk::ScopedAStatus onLockoutTimed(int64_t /*durationMillis*/) override { + return ndk::ScopedAStatus::ok(); + } + + ndk::ScopedAStatus onLockoutPermanent() override { return ndk::ScopedAStatus::ok(); } + + ndk::ScopedAStatus onLockoutCleared() override { return ndk::ScopedAStatus::ok(); } + + ndk::ScopedAStatus onInteractionDetected() override { return ndk::ScopedAStatus::ok(); } + + ndk::ScopedAStatus onEnrollmentsEnumerated( + const std::vector& /*enrollmentIds*/) override { + auto lock = std::lock_guard{mMutex}; + mOnEnrollmentsEnumeratedInvoked = true; + mCv.notify_one(); + return ndk::ScopedAStatus::ok(); + } + + ndk::ScopedAStatus onEnrollmentsRemoved( + const std::vector& /*enrollmentIds*/) override { + auto lock = std::lock_guard{mMutex}; + mOnEnrollmentsRemovedInvoked = true; + mCv.notify_one(); + return ndk::ScopedAStatus::ok(); + } + + ndk::ScopedAStatus onFeaturesRetrieved(const std::vector& /*features*/) override { + auto lock = std::lock_guard{mMutex}; + mOnFeaturesRetrievedInvoked = true; + mCv.notify_one(); + return ndk::ScopedAStatus::ok(); + } + + ndk::ScopedAStatus onFeatureSet(Feature /*feature*/) override { + return ndk::ScopedAStatus::ok(); + } + + ndk::ScopedAStatus onAuthenticatorIdRetrieved(int64_t /*authenticatorId*/) override { + auto lock = std::lock_guard{mMutex}; + mOnAuthenticatorIdRetrievedInvoked = true; + mCv.notify_one(); + return ndk::ScopedAStatus::ok(); + } + + ndk::ScopedAStatus onAuthenticatorIdInvalidated(int64_t /*newAuthenticatorId*/) override { + auto lock = std::lock_guard{mMutex}; + mOnAuthenticatorIdInvalidatedInvoked = true; + mCv.notify_one(); + return ndk::ScopedAStatus::ok(); + } + + ndk::ScopedAStatus onSessionClosed() override { + auto lock = std::lock_guard{mMutex}; + mOnSessionClosedInvoked = true; + mCv.notify_one(); + return ndk::ScopedAStatus::ok(); + } + + std::mutex mMutex; + std::condition_variable mCv; + Error mError = Error::UNKNOWN; + int32_t mVendorCode = 0; + int64_t mGeneratedChallenge = 0; + int64_t mRevokedChallenge = 0; + bool mOnChallengeGeneratedInvoked = false; + bool mOnChallengeRevokedInvoked = false; + bool mOnErrorInvoked = false; + bool mOnEnrollmentsEnumeratedInvoked = false; + bool mOnEnrollmentsRemovedInvoked = false; + bool mOnFeaturesRetrievedInvoked = false; + bool mOnAuthenticatorIdRetrievedInvoked = false; + bool mOnAuthenticatorIdInvalidatedInvoked = false; + bool mOnSessionClosedInvoked = false; +}; + +class Face : public testing::TestWithParam { + protected: + void SetUp() override { + // Prepare the callback. + mCb = ndk::SharedRefBase::make(); + + int retries = 0; + bool isOk = false; + // If the first attempt to create a session fails, we try to create a session again. The + // first attempt might fail if the framework already has an active session. The AIDL + // contract doesn't allow to create a new session without closing the old one. However, we + // can't close the framework's session from VTS. The expectation here is that the HAL will + // crash after the first illegal attempt to create a session, then it will restart, and then + // we'll be able to create a session. + do { + // Get an instance of the HAL. + AIBinder* binder = AServiceManager_waitForService(GetParam().c_str()); + ASSERT_NE(binder, nullptr); + mHal = IFace::fromBinder(ndk::SpAIBinder(binder)); + + // Create a session. + isOk = mHal->createSession(kSensorId, kUserId, mCb, &mSession).isOk(); + ++retries; + } while (!isOk && retries < 2); + + ASSERT_TRUE(isOk); + } + + void TearDown() override { + // Close the mSession. + ASSERT_TRUE(mSession->close().isOk()); + + // Make sure the mSession is closed. + auto lock = std::unique_lock(mCb->mMutex); + mCb->mCv.wait(lock, [this] { return mCb->mOnSessionClosedInvoked; }); + } + + std::shared_ptr mHal; + std::shared_ptr mCb; + std::shared_ptr mSession; +}; + +TEST_P(Face, GetSensorPropsWorksTest) { + std::vector sensorProps; + + // Call the method. + ASSERT_TRUE(mHal->getSensorProps(&sensorProps).isOk()); + + // Make sure the sensorProps aren't empty. + ASSERT_FALSE(sensorProps.empty()); + ASSERT_FALSE(sensorProps[0].commonProps.componentInfo.empty()); +} + +TEST_P(Face, EnrollWithBadHatResultsInErrorTest) { + // Call the method. + auto hat = keymaster::HardwareAuthToken{}; + std::shared_ptr cancellationSignal; + ASSERT_TRUE( + mSession->enroll(hat, EnrollmentType::DEFAULT, {}, std::nullopt, &cancellationSignal) + .isOk()); + + // Make sure an error is returned. + auto lock = std::unique_lock{mCb->mMutex}; + mCb->mCv.wait(lock, [this] { return mCb->mOnErrorInvoked; }); + EXPECT_EQ(mCb->mError, Error::UNABLE_TO_PROCESS); + EXPECT_EQ(mCb->mVendorCode, 0); +} + +TEST_P(Face, GenerateChallengeProducesUniqueChallengesTest) { + static constexpr int kIterations = 100; + + auto challenges = std::set{}; + for (unsigned int i = 0; i < kIterations; ++i) { + // Call the method. + ASSERT_TRUE(mSession->generateChallenge().isOk()); + + // Check that the generated challenge is unique and not 0. + auto lock = std::unique_lock{mCb->mMutex}; + mCb->mCv.wait(lock, [this] { return mCb->mOnChallengeGeneratedInvoked; }); + ASSERT_NE(mCb->mGeneratedChallenge, 0); + ASSERT_EQ(challenges.find(mCb->mGeneratedChallenge), challenges.end()); + + challenges.insert(mCb->mGeneratedChallenge); + mCb->mOnChallengeGeneratedInvoked = false; + } +} + +TEST_P(Face, RevokeChallengeWorksForNonexistentChallengeTest) { + const int64_t nonexistentChallenge = 123; + + // Call the method. + ASSERT_TRUE(mSession->revokeChallenge(nonexistentChallenge).isOk()); + + // Check that the challenge is revoked and matches the requested challenge. + auto lock = std::unique_lock{mCb->mMutex}; + mCb->mCv.wait(lock, [this] { return mCb->mOnChallengeRevokedInvoked; }); + ASSERT_EQ(mCb->mRevokedChallenge, nonexistentChallenge); +} + +TEST_P(Face, RevokeChallengeWorksForExistentChallengeTest) { + // Generate a challenge. + ASSERT_TRUE(mSession->generateChallenge().isOk()); + + // Wait for the result. + auto lock = std::unique_lock{mCb->mMutex}; + mCb->mCv.wait(lock, [this] { return mCb->mOnChallengeGeneratedInvoked; }); + lock.unlock(); + + // Revoke the challenge. + ASSERT_TRUE(mSession->revokeChallenge(mCb->mGeneratedChallenge).isOk()); + + // Check that the challenge is revoked and matches the requested challenge. + lock.lock(); + mCb->mCv.wait(lock, [this] { return mCb->mOnChallengeRevokedInvoked; }); + ASSERT_EQ(mCb->mRevokedChallenge, mCb->mGeneratedChallenge); +} + +TEST_P(Face, EnumerateEnrollmentsWorksTest) { + // Call the method. + ASSERT_TRUE(mSession->enumerateEnrollments().isOk()); + + // Wait for the result. + auto lock = std::unique_lock{mCb->mMutex}; + mCb->mCv.wait(lock, [this] { return mCb->mOnEnrollmentsEnumeratedInvoked; }); +} + +TEST_P(Face, RemoveEnrollmentsWorksTest) { + // Call the method. + ASSERT_TRUE(mSession->removeEnrollments({}).isOk()); + + // Wait for the result. + auto lock = std::unique_lock{mCb->mMutex}; + mCb->mCv.wait(lock, [this] { return mCb->mOnEnrollmentsRemovedInvoked; }); +} + +TEST_P(Face, GetFeaturesWithoutEnrollmentsResultsInUnableToProcess) { + // Call the method. + ASSERT_TRUE(mSession->getFeatures().isOk()); + + // Wait for the result. + auto lock = std::unique_lock{mCb->mMutex}; + mCb->mCv.wait(lock, [this] { return mCb->mOnErrorInvoked; }); + EXPECT_EQ(mCb->mError, Error::UNABLE_TO_PROCESS); + EXPECT_EQ(mCb->mVendorCode, 0); +} + +TEST_P(Face, GetAuthenticatorIdWorksTest) { + // Call the method. + ASSERT_TRUE(mSession->getAuthenticatorId().isOk()); + + // Wait for the result. + auto lock = std::unique_lock{mCb->mMutex}; + mCb->mCv.wait(lock, [this] { return mCb->mOnAuthenticatorIdRetrievedInvoked; }); +} + +TEST_P(Face, InvalidateAuthenticatorIdWorksTest) { + // Call the method. + ASSERT_TRUE(mSession->invalidateAuthenticatorId().isOk()); + + // Wait for the result. + auto lock = std::unique_lock{mCb->mMutex}; + mCb->mCv.wait(lock, [this] { return mCb->mOnAuthenticatorIdInvalidatedInvoked; }); +} + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Face); +INSTANTIATE_TEST_SUITE_P(IFace, Face, + testing::ValuesIn(::android::getAidlHalInstanceNames(IFace::descriptor)), + ::android::PrintInstanceNameToString); + +} // namespace +} // namespace aidl::android::hardware::biometrics::face + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + ABinderProcess_setThreadPoolMaxThreadCount(1); + ABinderProcess_startThreadPool(); + return RUN_ALL_TESTS(); +} diff --git a/biometrics/fingerprint/2.1/default/README.md b/biometrics/fingerprint/2.1/default/README.md new file mode 100644 index 0000000000000000000000000000000000000000..c41664e0fc51fb7f39e3178bf8bb5ad9d03ce52d --- /dev/null +++ b/biometrics/fingerprint/2.1/default/README.md @@ -0,0 +1,6 @@ +## Default IBiometricsFingerprint@2.1 HAL ## +--- + +## Overview: ## + +Provides a default implementation that loads pre-HIDL HALs and exposes it to the framework. \ No newline at end of file diff --git a/biometrics/fingerprint/2.2/default/Android.bp b/biometrics/fingerprint/2.2/default/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..f4fb57f20c57c587956ae189401238d08e7206ee --- /dev/null +++ b/biometrics/fingerprint/2.2/default/Android.bp @@ -0,0 +1,31 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_binary { + name: "android.hardware.biometrics.fingerprint@2.2-service.example", + defaults: ["hidl_defaults"], + init_rc: ["android.hardware.biometrics.fingerprint@2.2-service.rc"], + vintf_fragments: ["android.hardware.biometrics.fingerprint@2.2-service.xml"], + vendor: true, + relative_install_path: "hw", + srcs: [ + "BiometricsFingerprint.cpp", + "service.cpp", + ], + + shared_libs: [ + "libcutils", + "liblog", + "libhidlbase", + "libhardware", + "libutils", + "android.hardware.biometrics.fingerprint@2.2", + ], + +} diff --git a/biometrics/fingerprint/2.2/default/BiometricsFingerprint.cpp b/biometrics/fingerprint/2.2/default/BiometricsFingerprint.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b07a17ce072dc0aeb9170d042fb24d9b3433bb89 --- /dev/null +++ b/biometrics/fingerprint/2.2/default/BiometricsFingerprint.cpp @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define LOG_TAG "android.hardware.biometrics.fingerprint@2.2-service" +#define LOG_VERBOSE "android.hardware.biometrics.fingerprint@2.2-service" + +#include + +#include +#include +#include +#include "BiometricsFingerprint.h" + +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace biometrics { +namespace fingerprint { +namespace V2_2 { +namespace implementation { + +using RequestStatus = android::hardware::biometrics::fingerprint::V2_1::RequestStatus; +using FingerprintError = android::hardware::biometrics::fingerprint::V2_1::FingerprintError; + +constexpr uint64_t kDeviceId = 1; + +BiometricsFingerprint::BiometricsFingerprint() { + +} + +BiometricsFingerprint::~BiometricsFingerprint() { + +} + +Return BiometricsFingerprint::setNotify( + const sp& clientCallback) { + mClientCallback = clientCallback; + return kDeviceId; +} + +Return BiometricsFingerprint::preEnroll() { + // On a real implementation, this must be generated and stored in the TEE or its equivalent. + return rand(); +} + +Return BiometricsFingerprint::enroll(const hidl_array& /* hat */, + uint32_t /* gid */, uint32_t /* timeoutSec */) { + // On a real implementation, the HAT must be checked in the TEE or its equivalent. + mClientCallback->onError(kDeviceId, FingerprintError::ERROR_UNABLE_TO_PROCESS, + 0 /* vendorCode */); + return RequestStatus::SYS_OK; +} + +Return BiometricsFingerprint::postEnroll() { + return RequestStatus::SYS_OK; +} + +Return BiometricsFingerprint::getAuthenticatorId() { + return 1; +} + +Return BiometricsFingerprint::cancel() { + mClientCallback->onError(kDeviceId, FingerprintError::ERROR_CANCELED, 0 /* vendorCode */); + return RequestStatus::SYS_OK; +} + +Return BiometricsFingerprint::enumerate() { + mClientCallback->onEnumerate(kDeviceId, 0 /* fingerId */, 0 /* groupId */, + 0 /* remaining */); + return RequestStatus::SYS_OK; +} + +Return BiometricsFingerprint::remove(uint32_t gid, uint32_t fid) { + mClientCallback->onRemoved(kDeviceId, fid, gid, 0 /* remaining */); + return RequestStatus::SYS_OK; +} + +Return BiometricsFingerprint::setActiveGroup(uint32_t /* gid */, + const hidl_string& storePath) { + // Return invalid for paths that the HAL is unable to write to. + std::string path = storePath.c_str(); + if (path.compare("") == 0 || path.compare("/") == 0) { + return RequestStatus::SYS_EINVAL; + } + return RequestStatus::SYS_OK; +} + +Return BiometricsFingerprint::authenticate(uint64_t /* operationId */, + uint32_t /* gid */) { + return RequestStatus::SYS_OK; +} + +} // namespace implementation +} // namespace V2_2 +} // namespace fingerprint +} // namespace biometrics +} // namespace hardware +} // namespace android diff --git a/biometrics/fingerprint/2.2/default/BiometricsFingerprint.h b/biometrics/fingerprint/2.2/default/BiometricsFingerprint.h new file mode 100644 index 0000000000000000000000000000000000000000..a6861b32ba98630999356963fd52ef21be9d503e --- /dev/null +++ b/biometrics/fingerprint/2.2/default/BiometricsFingerprint.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_BIOMETRICS_FINGERPRINT_V2_2_BIOMETRICSFINGERPRINT_H +#define ANDROID_HARDWARE_BIOMETRICS_FINGERPRINT_V2_2_BIOMETRICSFINGERPRINT_H + +#include +#include +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace biometrics { +namespace fingerprint { +namespace V2_2 { +namespace implementation { + +using ::android::hardware::biometrics::fingerprint::V2_2::IBiometricsFingerprint; +using ::android::hardware::biometrics::fingerprint::V2_1::IBiometricsFingerprintClientCallback; +using ::android::hardware::biometrics::fingerprint::V2_1::RequestStatus; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::hidl_vec; +using ::android::hardware::hidl_string; +using ::android::sp; + +struct BiometricsFingerprint : public IBiometricsFingerprint { +public: + BiometricsFingerprint(); + ~BiometricsFingerprint(); + + // Methods from ::android::hardware::biometrics::fingerprint::V2_2::IBiometricsFingerprint follow. + Return setNotify(const sp& clientCallback) override; + Return preEnroll() override; + Return enroll(const hidl_array& hat, uint32_t gid, uint32_t timeoutSec) override; + Return postEnroll() override; + Return getAuthenticatorId() override; + Return cancel() override; + Return enumerate() override; + Return remove(uint32_t gid, uint32_t fid) override; + Return setActiveGroup(uint32_t gid, const hidl_string& storePath) override; + Return authenticate(uint64_t operationId, uint32_t gid) override; + +private: + sp mClientCallback; + +}; + +} // namespace implementation +} // namespace V2_2 +} // namespace fingerprint +} // namespace biometrics +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_BIOMETRICS_FINGERPRINT_V2_2_BIOMETRICSFINGERPRINT_H diff --git a/biometrics/fingerprint/2.2/default/android.hardware.biometrics.fingerprint@2.2-service.rc b/biometrics/fingerprint/2.2/default/android.hardware.biometrics.fingerprint@2.2-service.rc new file mode 100644 index 0000000000000000000000000000000000000000..1b406b08d07b573ceef14962afa4fbd88b14d5b7 --- /dev/null +++ b/biometrics/fingerprint/2.2/default/android.hardware.biometrics.fingerprint@2.2-service.rc @@ -0,0 +1,4 @@ +service vendor.fps_hal /vendor/bin/hw/android.hardware.biometrics.fingerprint@2.2-service.example + class hal + user nobody + group nobody diff --git a/biometrics/fingerprint/2.2/default/android.hardware.biometrics.fingerprint@2.2-service.xml b/biometrics/fingerprint/2.2/default/android.hardware.biometrics.fingerprint@2.2-service.xml new file mode 100644 index 0000000000000000000000000000000000000000..5e69a1ee5d867f118bcfea39f563ac338784f621 --- /dev/null +++ b/biometrics/fingerprint/2.2/default/android.hardware.biometrics.fingerprint@2.2-service.xml @@ -0,0 +1,27 @@ + + + + + android.hardware.biometrics.fingerprint + hwbinder + 2.2 + + IBiometricsFingerprint + default + + + diff --git a/biometrics/fingerprint/2.2/default/service.cpp b/biometrics/fingerprint/2.2/default/service.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5bc69a071964523946d5599381f3b5e917a571be --- /dev/null +++ b/biometrics/fingerprint/2.2/default/service.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "android.hardware.biometrics.fingerprint@2.2-service" + +#include +#include +#include +#include +#include +#include "BiometricsFingerprint.h" + +using android::hardware::biometrics::fingerprint::V2_2::IBiometricsFingerprint; +using android::hardware::biometrics::fingerprint::V2_2::implementation::BiometricsFingerprint; +using android::hardware::configureRpcThreadpool; +using android::hardware::joinRpcThreadpool; +using android::sp; + +int main() { + android::sp bio = new BiometricsFingerprint(); + + configureRpcThreadpool(1, true /*callerWillJoin*/); + + if (::android::OK != bio->registerAsService()) { + return 1; + } + + joinRpcThreadpool(); + + return 0; // should never get here +} diff --git a/biometrics/fingerprint/2.2/vts/functional/VtsHalBiometricsFingerprintV2_2TargetTest.cpp b/biometrics/fingerprint/2.2/vts/functional/VtsHalBiometricsFingerprintV2_2TargetTest.cpp index df29fd41794740db02f46c9e68d0f82b22b4e0b2..e0789ce11b73d0548a74f4af0c5e20b28bf17f89 100644 --- a/biometrics/fingerprint/2.2/vts/functional/VtsHalBiometricsFingerprintV2_2TargetTest.cpp +++ b/biometrics/fingerprint/2.2/vts/functional/VtsHalBiometricsFingerprintV2_2TargetTest.cpp @@ -136,6 +136,7 @@ TEST_P(FingerprintHidlTest, acquiredInfoStartTest) { } // anonymous namespace +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FingerprintHidlTest); INSTANTIATE_TEST_SUITE_P(PerInstance, FingerprintHidlTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames( IBiometricsFingerprint::descriptor)), diff --git a/biometrics/fingerprint/2.3/Android.bp b/biometrics/fingerprint/2.3/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..4608df7ebf83268108fd0470b6d14629c02f155d --- /dev/null +++ b/biometrics/fingerprint/2.3/Android.bp @@ -0,0 +1,24 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +hidl_interface { + name: "android.hardware.biometrics.fingerprint@2.3", + root: "android.hardware", + srcs: [ + "IBiometricsFingerprint.hal", + ], + interfaces: [ + "android.hardware.biometrics.fingerprint@2.1", + "android.hardware.biometrics.fingerprint@2.2", + "android.hidl.base@1.0", + ], + gen_java: true, +} diff --git a/biometrics/fingerprint/2.3/IBiometricsFingerprint.hal b/biometrics/fingerprint/2.3/IBiometricsFingerprint.hal new file mode 100644 index 0000000000000000000000000000000000000000..378b5645377c91ada00e968aeecd92eb4b9d8c8a --- /dev/null +++ b/biometrics/fingerprint/2.3/IBiometricsFingerprint.hal @@ -0,0 +1,70 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics.fingerprint@2.3; + +import @2.2::IBiometricsFingerprint; + +/** + * New use of this interface is strongly discouraged. The recommended option is + * to use the AIDL interface, android.hardware.biometrics.fingerprint + * (IFingerprint). + * + * The interface for biometric fingerprint authentication. + */ +interface IBiometricsFingerprint extends @2.2::IBiometricsFingerprint { + /** + * Returns whether the fingerprint sensor is an under-display fingerprint + * sensor. + * @param sensorId the unique sensor ID for which the operation should be + * performed. + * @return isUdfps indicating whether the specified sensor is an + * under-display fingerprint sensor. + */ + isUdfps(uint32_t sensorId) generates (bool isUdfps); + + /** + * Notifies about a touch occurring within the under-display fingerprint + * sensor area. + * + * It it assumed that the device can only have one active under-display + * fingerprint sensor at a time. + * + * If multiple fingers are detected within the sensor area, only the + * chronologically first event will be reported. + * + * @param x The screen x-coordinate of the center of the touch contact area, in + * display pixels. + * @param y The screen y-coordinate of the center of the touch contact area, in + * display pixels. + * @param minor The length of the minor axis of an ellipse that describes the + * touch area, in display pixels. + * @param major The length of the major axis of an ellipse that describes the + * touch area, in display pixels. + */ + onFingerDown(uint32_t x, uint32_t y, float minor, float major); + + /** + * Notifies about a finger leaving the under-display fingerprint sensor area. + * + * It it assumed that the device can only have one active under-display + * fingerprint sensor at a time. + * + * If multiple fingers have left the sensor area, only the finger which + * previously caused a "finger down" event will be reported. + */ + onFingerUp(); +}; diff --git a/biometrics/fingerprint/2.3/vts/functional/Android.bp b/biometrics/fingerprint/2.3/vts/functional/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..100aa29cd01c52fd1b0f3419f7c9e935f473654d --- /dev/null +++ b/biometrics/fingerprint/2.3/vts/functional/Android.bp @@ -0,0 +1,39 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_test { + name: "VtsHalBiometricsFingerprintV2_3TargetTest", + defaults: ["VtsHalTargetTestDefaults"], + srcs: ["VtsHalBiometricsFingerprintV2_3TargetTest.cpp"], + static_libs: [ + "android.hardware.biometrics.fingerprint@2.1", + "android.hardware.biometrics.fingerprint@2.2", + "android.hardware.biometrics.fingerprint@2.3", + ], + test_suites: [ + "general-tests", + "vts", + ], +} diff --git a/biometrics/fingerprint/2.3/vts/functional/VtsHalBiometricsFingerprintV2_3TargetTest.cpp b/biometrics/fingerprint/2.3/vts/functional/VtsHalBiometricsFingerprintV2_3TargetTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d2a08a03609dc7aae15508777c64b11061e42c9f --- /dev/null +++ b/biometrics/fingerprint/2.3/vts/functional/VtsHalBiometricsFingerprintV2_3TargetTest.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define ASSERT_OK(v) ASSERT_TRUE(v.isOk()) + +#include +#include +#include +#include +#include + +namespace { + +namespace hidl_interface_2_3 = android::hardware::biometrics::fingerprint::V2_3; + +using hidl_interface_2_3::IBiometricsFingerprint; + +using android::sp; + +// Callback arguments that need to be captured for the tests. +struct FingerprintCallbackArgs {}; + +class FingerprintHidlTest : public ::testing::TestWithParam { + public: + void SetUp() override { + mService = IBiometricsFingerprint::getService(GetParam()); + ASSERT_NE(mService, nullptr); + } + + sp mService; +}; + +// This method returns true or false depending on the implementation. +TEST_P(FingerprintHidlTest, isUdfpsTest) { + // Arbitrary ID + uint32_t sensorId = 1234; + ASSERT_OK(mService->isUdfps(sensorId)); +} + +// This method that doesn't return anything. +TEST_P(FingerprintHidlTest, onFingerDownTest) { + ASSERT_OK(mService->onFingerDown(1, 2, 3.0f, 4.0f)); +} + +// This method that doesn't return anything. +TEST_P(FingerprintHidlTest, onFingerUp) { + ASSERT_OK(mService->onFingerUp()); +} + +} // anonymous namespace + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FingerprintHidlTest); +INSTANTIATE_TEST_SUITE_P(PerInstance, FingerprintHidlTest, + testing::ValuesIn(android::hardware::getAllHalInstanceNames( + IBiometricsFingerprint::descriptor)), + android::hardware::PrintInstanceNameToString); diff --git a/biometrics/fingerprint/aidl/Android.bp b/biometrics/fingerprint/aidl/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..5295098c79b8c4c35366b95ab5d537b8467f3742 --- /dev/null +++ b/biometrics/fingerprint/aidl/Android.bp @@ -0,0 +1,30 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +aidl_interface { + name: "android.hardware.biometrics.fingerprint", + vendor_available: true, + srcs: [ + "android/hardware/biometrics/fingerprint/**/*.aidl", + ], + imports: [ + "android.hardware.biometrics.common", + "android.hardware.keymaster", + ], + stability: "vintf", + backend: { + java: { + platform_apis: true, + }, + cpp: { + enabled: false, + }, + }, + versions: ["1"], +} diff --git a/biometrics/fingerprint/aidl/OWNERS b/biometrics/fingerprint/aidl/OWNERS new file mode 100644 index 0000000000000000000000000000000000000000..36d726136fb188baf8f3dfc2180e8986c9f568fe --- /dev/null +++ b/biometrics/fingerprint/aidl/OWNERS @@ -0,0 +1,2 @@ +ilyamaty@google.com +kchyn@google.com diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/1/.hash b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/1/.hash new file mode 100644 index 0000000000000000000000000000000000000000..64b20831d8fdd573e7fb7ddcd5c0e92625f5300f --- /dev/null +++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/1/.hash @@ -0,0 +1 @@ +3621eefdbae063097dad0037cd1f111792ff12ec diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/1/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/1/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..c51aa033d4cd5a5de4562b526b357061ad37d711 --- /dev/null +++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/1/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.fingerprint; +@Backing(type="byte") @VintfStability +enum AcquiredInfo { + UNKNOWN = 0, + GOOD = 1, + PARTIAL = 2, + INSUFFICIENT = 3, + SENSOR_DIRTY = 4, + TOO_SLOW = 5, + TOO_FAST = 6, + VENDOR = 7, + START = 8, + TOO_DARK = 9, + TOO_BRIGHT = 10, + IMMOBILE = 11, + RETRYING_CAPTURE = 12, +} diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/1/android/hardware/biometrics/fingerprint/Error.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/1/android/hardware/biometrics/fingerprint/Error.aidl new file mode 100644 index 0000000000000000000000000000000000000000..af7bc3c56bb359b81b856630bd58fa39913da448 --- /dev/null +++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/1/android/hardware/biometrics/fingerprint/Error.aidl @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.fingerprint; +@Backing(type="byte") @VintfStability +enum Error { + UNKNOWN = 0, + HW_UNAVAILABLE = 1, + UNABLE_TO_PROCESS = 2, + TIMEOUT = 3, + NO_SPACE = 4, + CANCELED = 5, + UNABLE_TO_REMOVE = 6, + VENDOR = 7, + BAD_CALIBRATION = 8, +} diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/1/android/hardware/biometrics/fingerprint/FingerprintSensorType.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/1/android/hardware/biometrics/fingerprint/FingerprintSensorType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..9c208c4e7c20cb5301f75dc38d0ddf303871b057 --- /dev/null +++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/1/android/hardware/biometrics/fingerprint/FingerprintSensorType.aidl @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.fingerprint; +@Backing(type="byte") @VintfStability +enum FingerprintSensorType { + UNKNOWN = 0, + REAR = 1, + UNDER_DISPLAY_ULTRASONIC = 2, + UNDER_DISPLAY_OPTICAL = 3, + POWER_BUTTON = 4, + HOME_BUTTON = 5, +} diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/1/android/hardware/biometrics/fingerprint/IFingerprint.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/1/android/hardware/biometrics/fingerprint/IFingerprint.aidl new file mode 100644 index 0000000000000000000000000000000000000000..5d3df6fbaa2b1a403e90d42173ff1f971f4e452b --- /dev/null +++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/1/android/hardware/biometrics/fingerprint/IFingerprint.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.fingerprint; +@VintfStability +interface IFingerprint { + android.hardware.biometrics.fingerprint.SensorProps[] getSensorProps(); + android.hardware.biometrics.fingerprint.ISession createSession(in int sensorId, in int userId, in android.hardware.biometrics.fingerprint.ISessionCallback cb); +} diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/1/android/hardware/biometrics/fingerprint/ISession.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/1/android/hardware/biometrics/fingerprint/ISession.aidl new file mode 100644 index 0000000000000000000000000000000000000000..9934a763e785191c18dd86e54149113bf73327f3 --- /dev/null +++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/1/android/hardware/biometrics/fingerprint/ISession.aidl @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.fingerprint; +@VintfStability +interface ISession { + void generateChallenge(); + void revokeChallenge(in long challenge); + android.hardware.biometrics.common.ICancellationSignal enroll(in android.hardware.keymaster.HardwareAuthToken hat); + android.hardware.biometrics.common.ICancellationSignal authenticate(in long operationId); + android.hardware.biometrics.common.ICancellationSignal detectInteraction(); + void enumerateEnrollments(); + void removeEnrollments(in int[] enrollmentIds); + void getAuthenticatorId(); + void invalidateAuthenticatorId(); + void resetLockout(in android.hardware.keymaster.HardwareAuthToken hat); + void close(); + void onPointerDown(in int pointerId, in int x, in int y, in float minor, in float major); + void onPointerUp(in int pointerId); + void onUiReady(); +} diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/1/android/hardware/biometrics/fingerprint/ISessionCallback.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/1/android/hardware/biometrics/fingerprint/ISessionCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..3c40ad63bff3c586cf4c98915f26d80f4591031f --- /dev/null +++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/1/android/hardware/biometrics/fingerprint/ISessionCallback.aidl @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.fingerprint; +@VintfStability +interface ISessionCallback { + void onChallengeGenerated(in long challenge); + void onChallengeRevoked(in long challenge); + void onAcquired(in android.hardware.biometrics.fingerprint.AcquiredInfo info, in int vendorCode); + void onError(in android.hardware.biometrics.fingerprint.Error error, in int vendorCode); + void onEnrollmentProgress(in int enrollmentId, int remaining); + void onAuthenticationSucceeded(in int enrollmentId, in android.hardware.keymaster.HardwareAuthToken hat); + void onAuthenticationFailed(); + void onLockoutTimed(in long durationMillis); + void onLockoutPermanent(); + void onLockoutCleared(); + void onInteractionDetected(); + void onEnrollmentsEnumerated(in int[] enrollmentIds); + void onEnrollmentsRemoved(in int[] enrollmentIds); + void onAuthenticatorIdRetrieved(in long authenticatorId); + void onAuthenticatorIdInvalidated(in long newAuthenticatorId); + void onSessionClosed(); +} diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/1/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/1/android/hardware/biometrics/fingerprint/SensorLocation.aidl new file mode 100644 index 0000000000000000000000000000000000000000..515ddaa3583619a5afb88618304d90b89e818df8 --- /dev/null +++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/1/android/hardware/biometrics/fingerprint/SensorLocation.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.fingerprint; +@VintfStability +parcelable SensorLocation { + int displayId; + int sensorLocationX; + int sensorLocationY; + int sensorRadius; +} diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/1/android/hardware/biometrics/fingerprint/SensorProps.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/1/android/hardware/biometrics/fingerprint/SensorProps.aidl new file mode 100644 index 0000000000000000000000000000000000000000..782d2899d3d0cacc3d2a8918743e68fb44c2da29 --- /dev/null +++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/1/android/hardware/biometrics/fingerprint/SensorProps.aidl @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.fingerprint; +@VintfStability +parcelable SensorProps { + android.hardware.biometrics.common.CommonProps commonProps; + android.hardware.biometrics.fingerprint.FingerprintSensorType sensorType = android.hardware.biometrics.fingerprint.FingerprintSensorType.UNKNOWN; + android.hardware.biometrics.fingerprint.SensorLocation[] sensorLocations; + boolean supportsNavigationGestures; + boolean supportsDetectInteraction; + boolean halHandlesDisplayTouches; + boolean halControlsIllumination; +} diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..c51aa033d4cd5a5de4562b526b357061ad37d711 --- /dev/null +++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.fingerprint; +@Backing(type="byte") @VintfStability +enum AcquiredInfo { + UNKNOWN = 0, + GOOD = 1, + PARTIAL = 2, + INSUFFICIENT = 3, + SENSOR_DIRTY = 4, + TOO_SLOW = 5, + TOO_FAST = 6, + VENDOR = 7, + START = 8, + TOO_DARK = 9, + TOO_BRIGHT = 10, + IMMOBILE = 11, + RETRYING_CAPTURE = 12, +} diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/Error.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/Error.aidl new file mode 100644 index 0000000000000000000000000000000000000000..af7bc3c56bb359b81b856630bd58fa39913da448 --- /dev/null +++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/Error.aidl @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.fingerprint; +@Backing(type="byte") @VintfStability +enum Error { + UNKNOWN = 0, + HW_UNAVAILABLE = 1, + UNABLE_TO_PROCESS = 2, + TIMEOUT = 3, + NO_SPACE = 4, + CANCELED = 5, + UNABLE_TO_REMOVE = 6, + VENDOR = 7, + BAD_CALIBRATION = 8, +} diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/FingerprintSensorType.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/FingerprintSensorType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..9c208c4e7c20cb5301f75dc38d0ddf303871b057 --- /dev/null +++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/FingerprintSensorType.aidl @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.fingerprint; +@Backing(type="byte") @VintfStability +enum FingerprintSensorType { + UNKNOWN = 0, + REAR = 1, + UNDER_DISPLAY_ULTRASONIC = 2, + UNDER_DISPLAY_OPTICAL = 3, + POWER_BUTTON = 4, + HOME_BUTTON = 5, +} diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IFingerprint.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IFingerprint.aidl new file mode 100644 index 0000000000000000000000000000000000000000..5d3df6fbaa2b1a403e90d42173ff1f971f4e452b --- /dev/null +++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IFingerprint.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.fingerprint; +@VintfStability +interface IFingerprint { + android.hardware.biometrics.fingerprint.SensorProps[] getSensorProps(); + android.hardware.biometrics.fingerprint.ISession createSession(in int sensorId, in int userId, in android.hardware.biometrics.fingerprint.ISessionCallback cb); +} diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISession.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISession.aidl new file mode 100644 index 0000000000000000000000000000000000000000..9934a763e785191c18dd86e54149113bf73327f3 --- /dev/null +++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISession.aidl @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.fingerprint; +@VintfStability +interface ISession { + void generateChallenge(); + void revokeChallenge(in long challenge); + android.hardware.biometrics.common.ICancellationSignal enroll(in android.hardware.keymaster.HardwareAuthToken hat); + android.hardware.biometrics.common.ICancellationSignal authenticate(in long operationId); + android.hardware.biometrics.common.ICancellationSignal detectInteraction(); + void enumerateEnrollments(); + void removeEnrollments(in int[] enrollmentIds); + void getAuthenticatorId(); + void invalidateAuthenticatorId(); + void resetLockout(in android.hardware.keymaster.HardwareAuthToken hat); + void close(); + void onPointerDown(in int pointerId, in int x, in int y, in float minor, in float major); + void onPointerUp(in int pointerId); + void onUiReady(); +} diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISessionCallback.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISessionCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..3c40ad63bff3c586cf4c98915f26d80f4591031f --- /dev/null +++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISessionCallback.aidl @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.fingerprint; +@VintfStability +interface ISessionCallback { + void onChallengeGenerated(in long challenge); + void onChallengeRevoked(in long challenge); + void onAcquired(in android.hardware.biometrics.fingerprint.AcquiredInfo info, in int vendorCode); + void onError(in android.hardware.biometrics.fingerprint.Error error, in int vendorCode); + void onEnrollmentProgress(in int enrollmentId, int remaining); + void onAuthenticationSucceeded(in int enrollmentId, in android.hardware.keymaster.HardwareAuthToken hat); + void onAuthenticationFailed(); + void onLockoutTimed(in long durationMillis); + void onLockoutPermanent(); + void onLockoutCleared(); + void onInteractionDetected(); + void onEnrollmentsEnumerated(in int[] enrollmentIds); + void onEnrollmentsRemoved(in int[] enrollmentIds); + void onAuthenticatorIdRetrieved(in long authenticatorId); + void onAuthenticatorIdInvalidated(in long newAuthenticatorId); + void onSessionClosed(); +} diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SensorLocation.aidl new file mode 100644 index 0000000000000000000000000000000000000000..515ddaa3583619a5afb88618304d90b89e818df8 --- /dev/null +++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SensorLocation.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.fingerprint; +@VintfStability +parcelable SensorLocation { + int displayId; + int sensorLocationX; + int sensorLocationY; + int sensorRadius; +} diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SensorProps.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SensorProps.aidl new file mode 100644 index 0000000000000000000000000000000000000000..782d2899d3d0cacc3d2a8918743e68fb44c2da29 --- /dev/null +++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SensorProps.aidl @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.biometrics.fingerprint; +@VintfStability +parcelable SensorProps { + android.hardware.biometrics.common.CommonProps commonProps; + android.hardware.biometrics.fingerprint.FingerprintSensorType sensorType = android.hardware.biometrics.fingerprint.FingerprintSensorType.UNKNOWN; + android.hardware.biometrics.fingerprint.SensorLocation[] sensorLocations; + boolean supportsNavigationGestures; + boolean supportsDetectInteraction; + boolean halHandlesDisplayTouches; + boolean halControlsIllumination; +} diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..8ec8574965fd7134e0e035a7de87ae87f3005261 --- /dev/null +++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics.fingerprint; + +@VintfStability +@Backing(type="byte") +enum AcquiredInfo { + /** + * Placeholder value used for default initialization of AcquiredInfo. This + * value means AcquiredInfo wasn't explicitly initialized and must be + * discarded by the recipient. + */ + UNKNOWN, + + /** + * A high quality fingerprint image was detected, no further user interaction is necessary. + */ + GOOD, + + /** + * Not enough of a fingerprint was detected. Reposition the finger, or a longer swipe needed. + */ + PARTIAL, + + /** + * Image doesn't contain enough detail for recognition. + */ + INSUFFICIENT, + + /** + * The sensor needs to be cleaned. + */ + SENSOR_DIRTY, + + /** + * For swipe-type sensors, the swipe was too slow and not enough data was collected. + */ + TOO_SLOW, + + /** + * For swipe-type sensors, the swipe was too fast and not enough data was collected. + */ + TOO_FAST, + + /** + * Vendor-specific acquisition message. See ISessionCallback#onAcquired vendorCode + * documentation. + */ + VENDOR, + + /** + * This message represents the earliest message sent at the beginning of the authentication + * pipeline. It is expected to be used to measure latency. For example, in a camera-based + * authentication system it's expected to be sent prior to camera initialization. Note this + * should be sent whenever authentication is started or restarted. The framework may measure + * latency based on the time between the last START message and the onAuthenticated callback. + */ + START, + + /** + * For sensors that require illumination, such as optical under-display fingerprint sensors, + * the image was too dark to be used for matching. + */ + TOO_DARK, + + /** + * For sensors that require illumination, such as optical under-display fingerprint sensors, + * the image was too bright to be used for matching. + */ + TOO_BRIGHT, + + /** + * This message may be sent during enrollment if the same area of the finger has already + * been captured during this enrollment session. In general, enrolling multiple areas of the + * same finger can help against false rejections. + */ + IMMOBILE, + + /** + * This message may be sent to notify the framework that an additional image capture is taking + * place. Multiple RETRYING_CAPTURE may be sent before an ACQUIRED_GOOD message is sent. + * However, RETRYING_CAPTURE must not be sent after ACQUIRED_GOOD is sent. + */ + RETRYING_CAPTURE, +} diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/Error.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/Error.aidl new file mode 100644 index 0000000000000000000000000000000000000000..e69859a4425d4c0839d8ffc9708b5b009b59e798 --- /dev/null +++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/Error.aidl @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics.fingerprint; + +@VintfStability +@Backing(type="byte") +enum Error { + /** + * Placeholder value used for default initialization of Error. This value + * means Error wasn't explicitly initialized and must be discarded by the + * recipient. + */ + UNKNOWN, + + /** + * A hardware error has occurred that cannot be resolved. For example, I2C failure or a broken + * sensor. + */ + HW_UNAVAILABLE, + + /** + * The implementation is unable to process the request. For example, invalid arguments were + * supplied. + */ + UNABLE_TO_PROCESS, + + /** + * The current operation took too long to complete. + */ + TIMEOUT, + + /** + * No space available to store additional enrollments. + */ + NO_SPACE, + + /** + * The operation was canceled. See common::ICancellationSignal. + */ + CANCELED, + + /** + * The implementation was unable to remove an enrollment. + * See ISession#removeEnrollments. + */ + UNABLE_TO_REMOVE, + + /** + * Used to enable vendor-specific error messages. + */ + VENDOR, + + /** + * There's a problem with the sensor's calibration. + */ + BAD_CALIBRATION, +} diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/FingerprintSensorType.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/FingerprintSensorType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..dbe71377a219b8c25859a701be36099c97f0b36d --- /dev/null +++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/FingerprintSensorType.aidl @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics.fingerprint; + +@VintfStability +@Backing(type="byte") +enum FingerprintSensorType { + UNKNOWN, + REAR, + UNDER_DISPLAY_ULTRASONIC, + UNDER_DISPLAY_OPTICAL, + POWER_BUTTON, + HOME_BUTTON +} diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IFingerprint.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IFingerprint.aidl new file mode 100644 index 0000000000000000000000000000000000000000..75f90a12aee9991b4b2708b63b08d566effc5877 --- /dev/null +++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IFingerprint.aidl @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics.fingerprint; + +import android.hardware.biometrics.fingerprint.ISession; +import android.hardware.biometrics.fingerprint.ISessionCallback; +import android.hardware.biometrics.fingerprint.SensorProps; + +@VintfStability +interface IFingerprint { + /** + * getSensorProps: + * + * @return A list of properties for all of the fingerprint sensors supported by the HAL. + */ + SensorProps[] getSensorProps(); + + /** + * createSession: + * + * Creates an instance of ISession that can be used by the framework to perform operations such + * as ISession#enroll, ISession#authenticate, etc. for the given sensorId and userId. + * + * Calling this method while there is an active session is considered an error. If the framework + * wants to create a new session when it already has an active session, it must first cancel the + * current operation if it's cancellable or wait until it completes. Then, the framework must + * explicitly close the session with ISession#close. Once the framework receives + * ISessionCallback#onSessionClosed, a new session can be created. + * + * Implementations must store user-specific state or metadata in /data/vendor_de//fpdata + * as specified by the SELinux policy. The directory /data/vendor_de is managed by vold (see + * vold_prepare_subdirs.cpp). Implementations may store additional user-specific data, such as + * embeddings or templates, in StrongBox. + * + * @param sensorId The sensorId for which this session is being created. + * @param userId The userId for which this session is being created. + * @param cb A callback to notify the framework about the session's events. + * @return A new session. + */ + ISession createSession(in int sensorId, in int userId, in ISessionCallback cb); +} diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl new file mode 100644 index 0000000000000000000000000000000000000000..f1d96d3039cce175b5140b41c7a26df7ad843f16 --- /dev/null +++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl @@ -0,0 +1,451 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics.fingerprint; + +import android.hardware.biometrics.common.ICancellationSignal; +import android.hardware.keymaster.HardwareAuthToken; + +/** + * Operations defined within this interface can be split into the following categories: + * 1) Non-interrupting operations. These operations are handled by the HAL in a FIFO order. + * 1a) Cancellable operations. These operations can usually run for several minutes. To allow + * for cancellation, they return an instance of ICancellationSignal that allows the + * framework to cancel them by calling ICancellationSignal#cancel. If such an operation is + * cancelled, it must notify the framework by calling ISessionCallback#onError with + * Error::CANCELED. + * 1b) Non-cancellable operations. Such operations cannot be cancelled once started. + * 2) Interrupting operations. These operations may be invoked by the framework immediately, + * regardless of whether another operation is executing. For example, on devices with sensors + * of FingerprintSensorType::UNDER_DISPLAY_*, ISession#onPointerDown may be invoked while the + * HAL is executing ISession#enroll, ISession#authenticate or ISession#detectInteraction. + * + * The lifecycle of a non-interrupting operation ends when one of its final callbacks is called. + * For example, ISession#authenticate is considered completed when either ISessionCallback#onError + * or ISessionCallback#onAuthenticationSucceeded is called. + * + * The lifecycle of an interrupting operation ends when it returns. Interrupting operations do not + * have callbacks. + * + * ISession only supports execution of one non-interrupting operation at a time, regardless of + * whether it's cancellable. The framework must wait for a callback indicating the end of the + * current non-interrupting operation before a new non-interrupting operation can be started. + */ +@VintfStability +interface ISession { + /** + * Methods applicable to any fingerprint type. + */ + + /** + * generateChallenge: + * + * Begins a secure transaction request. Note that the challenge by itself is not useful. It only + * becomes useful when wrapped in a verifiable message such as a HardwareAuthToken. + * + * Canonical example: + * 1) User requests an operation, such as fingerprint enrollment. + * 2) Fingerprint enrollment cannot happen until the user confirms their lockscreen credential + * (PIN/Pattern/Password). + * 3) However, the biometric subsystem does not want just "any" proof of credential + * confirmation. It needs proof that the user explicitly authenticated credential in order + * to allow addition of biometric enrollments. + * To secure this path, the following path is taken: + * 1) Upon user requesting fingerprint enroll, the framework requests + * ISession#generateChallenge + * 2) Framework sends the challenge to the credential subsystem, and upon credential + * confirmation, a HAT is created, containing the challenge in the "challenge" field. + * 3) Framework sends the HAT to the HAL, e.g. ISession#enroll. + * 4) Implementation verifies the authenticity and integrity of the HAT. + * 5) Implementation now has confidence that the user entered their credential to allow + * biometric enrollment. + * + * Note that this interface allows multiple in-flight challenges. Invoking generateChallenge + * twice does not invalidate the first challenge. The challenge is invalidated only when: + * 1) Its lifespan exceeds the HAL's internal challenge timeout + * 2) IFingerprint#revokeChallenge is invoked + * + * For example, the following is a possible table of valid challenges: + * ---------------------------------------------- + * | SensorId | UserId | ValidUntil | Challenge | + * |----------|--------|------------|-----------| + * | 0 | 0 | | | + * | 0 | 0 | | | + * | 1 | 0 | | | + * | 0 | 10 | | | + * ---------------------------------------------- + * + * Callbacks that signify the end of this operation's lifecycle: + * - ISessionCallback#onChallengeGenerated + */ + void generateChallenge(); + + /** + * revokeChallenge: + * + * Revokes a challenge that was previously generated. Note that if a non-existent challenge is + * provided, the HAL must still notify the framework using ISessionCallback#onChallengeRevoked. + * + * Callbacks that signify the end of this operation's lifecycle: + * - ISessionCallback#onChallengeRevoked + * + * @param challenge Challenge that should be revoked. + */ + void revokeChallenge(in long challenge); + + /** + * enroll: + * + * A request to add a fingerprint enrollment. + * + * At any point during enrollment, if a non-recoverable error occurs, the HAL must notify the + * framework via ISessionCallback#onError with the applicable enrollment-specific error. + * + * Before capturing fingerprint data, the HAL must first verify the authenticity and integrity + * of the provided HardwareAuthToken. In addition, it must check that the challenge within the + * provided HardwareAuthToken is valid. See ISession#generateChallenge. If any of the above + * checks fail, the framework must be notified using ISessionCallback#onError with + * Error::UNABLE_TO_PROCESS. + * + * During enrollment, the HAL may notify the framework via ISessionCallback#onAcquired with + * messages that may be used to guide the user. This callback can be invoked multiple times if + * necessary. Similarly, the framework may be notified of enrollment progress changes via + * ISessionCallback#onEnrollmentProgress. Once the framework is notified that there are 0 + * "remaining" steps, the framework may cache the "enrollmentId". See + * ISessionCallback#onEnrollmentProgress for more info. + * + * When a finger is successfully added and before the framework is notified of remaining=0, the + * HAL must update and associate this (sensorId, userId) pair with a new entropy-encoded random + * identifier. See ISession#getAuthenticatorId for more information. + * + * Callbacks that signify the end of this operation's lifecycle: + * - ISessionCallback#onError + * - ISessionCallback#onEnrollmentProgress(enrollmentId, remaining=0) + * + * Other applicable callbacks: + * - ISessionCallback#onAcquired + * + * @param hat See above documentation. + * @return ICancellationSignal An object that can be used by the framework to cancel this + * operation. + */ + ICancellationSignal enroll(in HardwareAuthToken hat); + + /** + * authenticate: + * + * A request to start looking for fingerprints to authenticate. + * + * At any point during authentication, if a non-recoverable error occurs, the HAL must notify + * the framework via ISessionCallback#onError with the applicable authentication-specific error. + * + * During authentication, the HAL may notify the framework via ISessionCallback#onAcquired with + * messages that may be used to guide the user. This callback can be invoked multiple times if + * necessary. + * + * The HAL must notify the framework of accepts and rejects via + * ISessionCallback#onAuthenticationSucceeded and ISessionCallback#onAuthenticationFailed, + * correspondingly. + * + * The authentication lifecycle ends when either: + * 1) A fingerprint is accepted, and ISessionCallback#onAuthenticationSucceeded is invoked. + * 2) Any non-recoverable error occurs (such as lockout). See the full list of + * authentication-specific errors in the Error enum. + * + * Note that upon successful authentication, the lockout counter for this (sensorId, userId) + * pair must be cleared. + * + * Note that upon successful authentication, ONLY sensors configured as SensorStrength::STRONG + * are allowed to create and send a HardwareAuthToken to the framework. See the Android CDD for + * more details. For SensorStrength::STRONG sensors, the HardwareAuthToken's "challenge" field + * must be set with the operationId passed in during #authenticate. If the sensor is NOT + * SensorStrength::STRONG, the HardwareAuthToken MUST be null. + * + * Callbacks that signify the end of this operation's lifecycle: + * - ISessionCallback#onError + * - ISessionCallback#onAuthenticationSucceeded + * + * Other applicable callbacks: + * - ISessionCallback#onAcquired + * - ISessionCallback#onAuthenticationFailed + * - ISessionCallback#onLockoutTimed + * - ISessionCallback#onLockoutPermanent + * + * @param operationId For sensors configured as SensorStrength::STRONG, this must be used ONLY + * upon successful authentication and wrapped in the HardwareAuthToken's + * "challenge" field and sent to the framework via + * ISessionCallback#onAuthenticationSucceeded. The operationId is an opaque + * identifier created from a separate secure subsystem such as, but not + * limited to KeyStore/KeyMaster. The HardwareAuthToken can then be used as + * an attestation for the provided operation. For example, this is used to + * unlock biometric-bound auth-per-use keys (see + * setUserAuthenticationParameters in KeyGenParameterSpec.Builder and + * KeyProtection.Builder). + * @return ICancellationSignal An object that can be used by the framework to cancel this + * operation. + */ + ICancellationSignal authenticate(in long operationId); + + /** + * detectInteraction: + * + * A request to start looking for fingerprints without performing matching. Must only be called + * if SensorProps#supportsDetectInteraction is true. If invoked on HALs that do not support this + * functionality, the HAL must respond with ISession#onError(UNABLE_TO_PROCESS, 0). + * + * The framework will use this operation in cases where determining user presence is required, + * but identifying/authenticating is not. For example, when the device is encrypted (first boot) + * or in lockdown mode. + * + * At any point during detectInteraction, if a non-recoverable error occurs, the HAL must notify + * the framework via ISessionCallback#onError with the applicable error. + * + * The HAL must only check whether a fingerprint-like image was detected (e.g. to minimize + * interactions due to non-fingerprint objects), and the lockout counter must not be modified. + * + * Upon detecting any fingerprint, the HAL must invoke ISessionCallback#onInteractionDetected. + * + * The lifecycle of this operation ends when either: + * 1) Any fingerprint is detected and the framework is notified via + * ISessionCallback#onInteractionDetected. + * 2) An error occurs, for example Error::TIMEOUT. + * + * Note that if the operation is canceled, the HAL must notify the framework via + * ISessionCallback#onError with Error::CANCELED. + * + * Callbacks that signify the end of this operation's lifecycle: + * - ISessionCallback#onError + * - ISessionCallback#onInteractionDetected + * + * Other applicable callbacks: + * - ISessionCallback#onAcquired + * + * @return ICancellationSignal An object that can be used by the framework to cancel this + * operation. + */ + ICancellationSignal detectInteraction(); + + /* + * enumerateEnrollments: + * + * A request to enumerate (list) the enrollments for this (sensorId, userId) pair. The framework + * typically uses this to ensure that its cache is in sync with the HAL. + * + * The HAL must then notify the framework with a list of enrollments applicable for the current + * session via ISessionCallback#onEnrollmentsEnumerated. + * + * Callbacks that signify the end of this operation's lifecycle: + * - ISessionCallback#onEnrollmentsEnumerated + */ + void enumerateEnrollments(); + + /** + * removeEnrollments: + * + * A request to remove the enrollments for this (sensorId, userId) pair. + * + * After removing the enrollmentIds from everywhere necessary (filesystem, secure subsystems, + * etc), the HAL must notify the framework via ISessionCallback#onEnrollmentsRemoved. + * + * Callbacks that signify the end of this operation's lifecycle: + * - ISessionCallback#onEnrollmentsRemoved + * + * @param enrollmentIds a list of enrollments that should be removed. + */ + void removeEnrollments(in int[] enrollmentIds); + + /** + * getAuthenticatorId: + * + * MUST return 0 via ISessionCallback#onAuthenticatorIdRetrieved for sensors that are configured + * as SensorStrength::WEAK or SensorStrength::CONVENIENCE. + * + * The following only applies to sensors that are configured as SensorStrength::STRONG. + * + * The authenticatorId is a (sensorId, user)-specific identifier which can be used during key + * generation and import to associate the key (in KeyStore / KeyMaster) with the current set of + * enrolled fingerprints. For example, the following public Android APIs allow for keys to be + * invalidated when the user adds a new enrollment after the key was created: + * KeyGenParameterSpec.Builder.setInvalidatedByBiometricEnrollment and + * KeyProtection.Builder.setInvalidatedByBiometricEnrollment. + * + * In addition, upon successful fingerprint authentication, the signed HAT that is returned to + * the framework via ISessionCallback#onAuthenticationSucceeded must contain this identifier in + * the authenticatorId field. + * + * Returns an entropy-encoded random identifier associated with the current set of enrollments + * via ISessionCallback#onAuthenticatorIdRetrieved. The authenticatorId + * 1) MUST change whenever a new fingerprint is enrolled + * 2) MUST return 0 if no fingerprints are enrolled + * 3) MUST not change if a fingerprint is deleted. + * 4) MUST be an entropy-encoded random number + * + * Callbacks that signify the end of this operation's lifecycle: + * - ISessionCallback#onAuthenticatorIdRetrieved + */ + void getAuthenticatorId(); + + /** + * invalidateAuthenticatorId: + * + * This operation only applies to sensors that are configured as SensorStrength::STRONG. If + * invoked by the framework for sensors of other strengths, the HAL should immediately invoke + * ISessionCallback#onAuthenticatorIdInvalidated. + * + * The following only applies to sensors that are configured as SensorStrength::STRONG. + * + * When invoked by the framework, the HAL must perform the following sequence of events: + * 1) Update the authenticatorId with a new entropy-encoded random number + * 2) Persist the new authenticatorId to non-ephemeral storage + * 3) Notify the framework that the above is completed, via + * ISessionCallback#onAuthenticatorInvalidated + * + * A practical use case of invalidation would be when the user adds a new enrollment to a sensor + * managed by a different HAL instance. The public android.security.keystore APIs bind keys to + * "all biometrics" rather than "fingerprint-only" or "face-only" (see #getAuthenticatorId for + * more details). As such, the framework would coordinate invalidation across multiple biometric + * HALs as necessary. + * + * Callbacks that signify the end of this operation's lifecycle: + * - ISessionCallback#onAuthenticatorIdInvalidated + */ + void invalidateAuthenticatorId(); + + /** + * resetLockout: + * + * Requests the HAL to clear the lockout counter. Upon receiving this request, the HAL must + * perform the following: + * 1) Verify the authenticity and integrity of the provided HAT + * 2) Verify that the timestamp provided within the HAT is relatively recent (e.g. on the + * order of minutes, not hours). + * If either of the checks fail, the HAL must invoke ISessionCallback#onError with + * Error::UNABLE_TO_PROCESS. + * + * Upon successful verification, the HAL must clear the lockout counter and notify the framework + * via ISessionCallback#onLockoutCleared. + * + * Note that lockout is user AND sensor specific. In other words, there is a separate lockout + * state for each (user, sensor) pair. For example, the following is a valid state on a + * multi-sensor device: + * ------------------------------------------------------------------ + * | SensorId | UserId | FailedAttempts | LockedOut | LockedUntil | + * |----------|--------|----------------|-----------|---------------| + * | 0 | 0 | 1 | false | x | + * | 1 | 0 | 5 | true | | + * | 0 | 10 | 0 | false | x | + * | 1 | 10 | 0 | false | x | + * ------------------------------------------------------------------ + * + * Lockout may be cleared in the following ways: + * 1) ISession#resetLockout + * 2) After a period of time, according to a rate-limiter. + * + * Note that the "FailedAttempts" counter must be cleared upon successful fingerprint + * authentication. For example, if SensorId=0 UserId=0 FailedAttempts=1, and a successful + * fingerprint authentication occurs, the counter for that (SensorId, UserId) pair must be reset + * to 0. + * + * In addition, lockout states MUST persist after device reboots, HAL crashes, etc. + * + * See the Android CDD section 7.3.10 for the full set of lockout and rate-limiting + * requirements. + * + * Callbacks that signify the end of this operation's lifecycle: + * - ISessionCallback#onLockoutCleared + * + * @param hat HardwareAuthToken See above documentation. + */ + void resetLockout(in HardwareAuthToken hat); + + /* + * Close this session and allow the HAL to release the resources associated with this session. + * + * A session can only be closed when the HAL is idling, i.e. not performing any of the + * non-interruptable operations. If the HAL is busy performing a cancellable operation, the + * operation must be explicitly cancelled with a call to ICancellationSignal#cancel before + * the session can be closed. + * + * After a session is closed, the HAL must notify the framework by calling + * ISessionCallback#onSessionClosed. + * + * All sessions must be explicitly closed. Calling IFingerprint#createSession while there is an + * active session is considered an error. + * + * Callbacks that signify the end of this operation's lifecycle: + * - ISessionCallback#onSessionClosed + */ + void close(); + + /** + * Methods for notifying the under-display fingerprint sensor about external events. + */ + + /** + * onPointerDown: + * + * This operation only applies to sensors that are configured as + * FingerprintSensorType::UNDER_DISPLAY_*. If invoked erroneously by the framework for sensors + * of other types, the HAL must treat this as a no-op and return immediately. + * + * This operation is used to notify the HAL of display touches. This operation can be invoked + * when the HAL is performing any one of: ISession#authenticate, ISession#enroll, + * ISession#detectInteraction. + * + * Note that the framework will only invoke this operation if the event occurred on the display + * on which this sensor is located. + * + * Note that for sensors which require illumination such as + * FingerprintSensorType::UNDER_DISPLAY_OPTICAL, and where illumination is handled below the + * framework, this is a good time to start illuminating. + * + * @param pointerId See android.view.MotionEvent#getPointerId + * @param x The distance in pixels from the left edge of the display. + * @param y The distance in pixels from the top edge of the display. + * @param minor See android.view.MotionEvent#getTouchMinor + * @param major See android.view.MotionEvent#getTouchMajor + */ + void onPointerDown(in int pointerId, in int x, in int y, in float minor, in float major); + + /** + * onPointerUp: + * + * This operation only applies to sensors that are configured as + * FingerprintSensorType::UNDER_DISPLAY_*. If invoked for sensors of other types, the HAL must + * treat this as a no-op and return immediately. + * + * This operation can be invoked when the HAL is performing any one of: ISession#authenticate, + * ISession#enroll, ISession#detectInteraction. + * + * @param pointerId See android.view.MotionEvent#getPointerId + */ + void onPointerUp(in int pointerId); + + /* + * onUiReady: + * + * This operation only applies to sensors that are configured as + * FingerprintSensorType::UNDER_DISPLAY_OPTICAL. If invoked for sensors of other types, the HAL + * must treat this as a no-op and return immediately. + * + * This operation can be invoked when the HAL is performing any one of: ISession#authenticate, + * ISession#enroll, ISession#detectInteraction. + * + * For FingerprintSensorType::UNDER_DISPLAY_OPTICAL where illumination is handled above the + * HAL, the framework will invoke this operation to notify when the illumination is showing. + */ + void onUiReady(); +} diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..f699966f59cead7dfb7a48dad2b0aadf462ef2e8 --- /dev/null +++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics.fingerprint; + +import android.hardware.biometrics.fingerprint.AcquiredInfo; +import android.hardware.biometrics.fingerprint.Error; +import android.hardware.keymaster.HardwareAuthToken; + +@VintfStability +interface ISessionCallback { + /** + * Notifies the framework when a challenge is successfully generated. + */ + void onChallengeGenerated(in long challenge); + + /** + * Notifies the framework when a challenge has been revoked. + */ + void onChallengeRevoked(in long challenge); + + /** + * This method must only be used to notify the framework during the following operations: + * - ISession#enroll + * - ISession#authenticate + * - ISession#detectInteraction + * + * These messages may be used to provide user guidance multiple times per operation if + * necessary. + * + * @param info See the AcquiredInfo enum. + * @param vendorCode Only valid if info == AcquiredInfo::VENDOR. The vendorCode must be used to + * index into the configuration + * com.android.internal.R.array.fingerprint_acquired_vendor that's installed + * on the vendor partition. + */ + void onAcquired(in AcquiredInfo info, in int vendorCode); + + /** + * This method must only be used to notify the framework during the following operations: + * - ISession#enroll + * - ISession#authenticate + * - ISession#detectInteraction + * - ISession#invalidateAuthenticatorId + * - ISession#resetLockout + * + * These messages may be used to notify the framework or user that a non-recoverable error + * has occurred. The operation is finished, and the HAL can proceed with the next operation + * or return to the idling state. + * + * Note that cancellation (see common::ICancellationSignal) must be followed with an + * Error::CANCELED message. + * + * @param error See the Error enum. + * @param vendorCode Only valid if error == Error::VENDOR. The vendorCode must be used to index + * into the configuration + * com.android.internal.R.fingerprint_error_vendor that's installed on the + * vendor partition. + */ + void onError(in Error error, in int vendorCode); + + /** + * This method must only be used to notify the framework during the ISession#enroll operation. + * + * @param enrollmentId Unique stable identifier for the enrollment that's being added by this + * ISession#enroll invocation. + * @param remaining Remaining number of steps before enrollment is complete. + */ + void onEnrollmentProgress(in int enrollmentId, int remaining); + + /** + * This method must only be used to notify the framework during ISession#authenticate. + * + * Used to notify the framework upon successful authentication. Note that the authentication + * lifecycle ends when either 1) a fingerprint is accepted, or 2) an error occurred. The + * authentication lifecycle does NOT end when a fingerprint is rejected. + * + * @param enrollmentId Fingerprint that was accepted. + * @param hat If the sensor is configured as SensorStrength::STRONG, a non-null attestation that + * a fingerprint was accepted. The HardwareAuthToken's "challenge" field must be set + * with the operationId passed in during ISession#authenticate. If the sensor is NOT + * SensorStrength::STRONG, the HardwareAuthToken MUST be null. + */ + void onAuthenticationSucceeded(in int enrollmentId, in HardwareAuthToken hat); + + /** + * This method must only be used to notify the framework during ISession#authenticate. + * + * Used to notify the framework upon rejected attempts. Note that the authentication + * lifecycle ends when either 1) a fingerprint is accepted, or 2) an error occurred. + * The authentication lifecycle does NOT end when a fingerprint is rejected. + */ + void onAuthenticationFailed(); + + /** + * This method must only be used to notify the framework during ISession#authenticate. + * + * Authentication is locked out due to too many unsuccessful attempts. This is a rate-limiting + * lockout, and authentication can be restarted after a period of time. See + * ISession#resetLockout. + * + * @param sensorId Sensor for which the user is locked out. + * @param userId User for which the sensor is locked out. + * @param durationMillis Remaining duration of the lockout. + */ + void onLockoutTimed(in long durationMillis); + + /** + * This method must only be used to notify the framework during ISession#authenticate. + * + * Authentication is disabled until the user unlocks with their device credential + * (PIN/Pattern/Password). See ISession#resetLockout. + * + * @param sensorId Sensor for which the user is locked out. + * @param userId User for which the sensor is locked out. + */ + void onLockoutPermanent(); + + /** + * Notifies the framework that lockout has been cleared for this (sensorId, userId) pair. + * + * Note that this method can be used to notify the framework during any state. + * + * Lockout can be cleared in the following scenarios: + * 1) A timed lockout has ended (e.g. durationMillis specified in previous #onLockoutTimed + * has expired. + * 2) See ISession#resetLockout. + * + * @param sensorId Sensor for which the user's lockout is cleared. + * @param userId User for the sensor's lockout is cleared. + */ + void onLockoutCleared(); + + /** + * This method must only be used to notify the framework during + * ISession#detectInteraction + * + * Notifies the framework that user interaction occurred. See ISession#detectInteraction. + */ + void onInteractionDetected(); + + /** + * This method must only be used to notify the framework during + * ISession#enumerateEnrollments. + * + * Notifies the framework of the current enrollments. See ISession#enumerateEnrollments. + * + * @param enrollmentIds A list of enrollments for the session's (userId, sensorId) pair. + */ + void onEnrollmentsEnumerated(in int[] enrollmentIds); + + /** + * This method must only be used to notify the framework during + * ISession#removeEnrollments. + * + * Notifies the framework that the specified enrollments are removed. + * + * @param enrollmentIds The enrollments that were removed. + */ + void onEnrollmentsRemoved(in int[] enrollmentIds); + + /** + * This method must only be used to notify the framework during + * ISession#getAuthenticatorId. + * + * Notifies the framework with the authenticatorId corresponding to this session's + * (userId, sensorId) pair. + * + * @param authenticatorId See the above documentation. + */ + void onAuthenticatorIdRetrieved(in long authenticatorId); + + /** + * This method must only be used to notify the framework during + * ISession#invalidateAuthenticatorId. + * + * See ISession#invalidateAuthenticatorId for more information. + * + * @param newAuthenticatorId The new entropy-encoded random identifier associated with the + * current set of enrollments. + */ + void onAuthenticatorIdInvalidated(in long newAuthenticatorId); + + /** + * This method notifes the client that this session has closed. + * The client must not make any more calls to this session. + */ + void onSessionClosed(); +} diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SensorLocation.aidl new file mode 100644 index 0000000000000000000000000000000000000000..b1618b2d0c66cee9ab92665ec7f2935fa40483fd --- /dev/null +++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SensorLocation.aidl @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics.fingerprint; + +@VintfStability +parcelable SensorLocation { + /** + * The display to which the following measurements are relative to. This must correspond to the + * android.hardware.DisplayManager#getDisplay Android API. + * + * A few examples: + * 1) A capacitive rear fingerprint sensor would specify the display to which it is behind. + * 2) An under-display fingerprint sensor would specify the display on which the sensor is + * located. + * 3) A foldable device would specify multiple locations and have a SensorLocation entry + * for each display from which the sensor is accessible from. + */ + int displayId; + + /** + * The location of the center of the sensor if applicable. For example, sensors of + * FingerprintSensorType::UNDER_DISPLAY_* would report this value as the distance in pixels, + * measured from the left edge of the screen. + */ + int sensorLocationX; + + /** + * The location of the center of the sensor if applicable. For example, sensors of + * FingerprintSensorType::UNDER_DISPLAY_* would report this value as the distance in pixels, + * measured from the top edge of the screen. + */ + int sensorLocationY; + + /** + * The radius of the sensor if applicable. For example, sensors of + * FingerprintSensorType::UNDER_DISPLAY_* would report this value as the radius of the sensor, + * in pixels. + */ + int sensorRadius; +} diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SensorProps.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SensorProps.aidl new file mode 100644 index 0000000000000000000000000000000000000000..fb516da51e032e56a3ccaf50e5dbb55fb12cebee --- /dev/null +++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SensorProps.aidl @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics.fingerprint; + +import android.hardware.biometrics.common.CommonProps; +import android.hardware.biometrics.fingerprint.FingerprintSensorType; +import android.hardware.biometrics.fingerprint.SensorLocation; + +@VintfStability +parcelable SensorProps { + /** + * Statically configured properties that apply to this fingerprint sensor. + */ + CommonProps commonProps; + + /** + * A statically configured sensor type representing this fingerprint sensor. + */ + FingerprintSensorType sensorType = FingerprintSensorType.UNKNOWN; + + /** + * A list of display-specific locations from where the sensor is usable from. See SensorLocation + * for more details. + */ + SensorLocation[] sensorLocations; + + /** + * Must be set to true for sensors that support "swipe" gestures via + * android.view.KeyEvent#KEYCODE_SYSTEM_NAVIGATION_*. + */ + boolean supportsNavigationGestures; + + /** + * Specifies whether or not the implementation supports ISession#detectInteraction. + */ + boolean supportsDetectInteraction; + + /** + * Whether the HAL is responsible for detecting and processing of display touches. This is only + * applicable to under-display fingerprint sensors (UDFPS). If the value is false, the framework + * will be responsible for handling the display touch events and passing them down to the HAL by + * using ISession#onPointerDown and ISession#onPointerUp. If the value is true, the framework + * will not notify the HAL about touch events. + * + * This value must be ignored for non-UDFPS sensors. + */ + boolean halHandlesDisplayTouches; + + /** + * Whether the HAL is responsible for fingerprint illumination, for example through enabling the + * display's high-brightness mode. This is only applicable to optical under-display fingerprint + * sensors (optical UDFPS). If the value is false, the framework will be responsible for + * illuminating the finger and reporting ISession#onUiReady. If the value is true, the framework + * will not illuminate the finger and will not report ISession#onUiReady. + * + * This value must be ignored for sensors that aren't optical UDFPS. + */ + boolean halControlsIllumination; +} diff --git a/biometrics/fingerprint/aidl/default/Android.bp b/biometrics/fingerprint/aidl/default/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..08fe4b04b75e48d35f5ba6154e62c6b47826a888 --- /dev/null +++ b/biometrics/fingerprint/aidl/default/Android.bp @@ -0,0 +1,43 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_binary { + name: "android.hardware.biometrics.fingerprint-service.example", + vendor: true, + relative_install_path: "hw", + init_rc: ["fingerprint-default.rc"], + vintf_fragments: ["fingerprint-default.xml"], + local_include_dirs: ["include"], + srcs: [ + "CancellationSignal.cpp", + "Fingerprint.cpp", + "Session.cpp", + "WorkerThread.cpp", + "main.cpp", + ], + shared_libs: [ + "libbase", + "libbinder_ndk", + "android.hardware.biometrics.fingerprint-V1-ndk", + "android.hardware.biometrics.common-V1-ndk", + ], +} + +cc_test_host { + name: "android.hardware.biometrics.fingerprint.WorkerThreadTest", + local_include_dirs: ["include"], + srcs: [ + "tests/WorkerThreadTest.cpp", + "WorkerThread.cpp", + ], + shared_libs: [ + "libcutils", + ], + test_suites: ["general-tests"], +} diff --git a/biometrics/fingerprint/aidl/default/CancellationSignal.cpp b/biometrics/fingerprint/aidl/default/CancellationSignal.cpp new file mode 100644 index 0000000000000000000000000000000000000000..659831616daf196a61c26ce9be6b690507f87842 --- /dev/null +++ b/biometrics/fingerprint/aidl/default/CancellationSignal.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CancellationSignal.h" + +#include +#include + +namespace aidl::android::hardware::biometrics::fingerprint { + +CancellationSignal::CancellationSignal(std::promise&& cancellationPromise) + : mCancellationPromise(std::move(cancellationPromise)) {} + +ndk::ScopedAStatus CancellationSignal::cancel() { + mCancellationPromise.set_value(); + return ndk::ScopedAStatus::ok(); +} + +bool shouldCancel(const std::future& f) { + CHECK(f.valid()); + return f.wait_for(std::chrono::seconds(0)) == std::future_status::ready; +} + +} // namespace aidl::android::hardware::biometrics::fingerprint diff --git a/biometrics/fingerprint/aidl/default/Fingerprint.cpp b/biometrics/fingerprint/aidl/default/Fingerprint.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fbfa52f0e7c4d523e72f4ca6b351598396bbd715 --- /dev/null +++ b/biometrics/fingerprint/aidl/default/Fingerprint.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Fingerprint.h" + +#include "Session.h" + +namespace aidl::android::hardware::biometrics::fingerprint { +namespace { +constexpr size_t MAX_WORKER_QUEUE_SIZE = 5; +constexpr int SENSOR_ID = 1; +constexpr common::SensorStrength SENSOR_STRENGTH = common::SensorStrength::STRONG; +constexpr int MAX_ENROLLMENTS_PER_USER = 5; +constexpr FingerprintSensorType SENSOR_TYPE = FingerprintSensorType::REAR; +constexpr bool SUPPORTS_NAVIGATION_GESTURES = true; +constexpr char HW_COMPONENT_ID[] = "fingerprintSensor"; +constexpr char HW_VERSION[] = "vendor/model/revision"; +constexpr char FW_VERSION[] = "1.01"; +constexpr char SERIAL_NUMBER[] = "00000001"; +constexpr char SW_COMPONENT_ID[] = "matchingAlgorithm"; +constexpr char SW_VERSION[] = "vendor/version/revision"; + +} // namespace + +Fingerprint::Fingerprint() + : mEngine(std::make_unique()), mWorker(MAX_WORKER_QUEUE_SIZE) {} + +ndk::ScopedAStatus Fingerprint::getSensorProps(std::vector* out) { + std::vector componentInfo = { + {HW_COMPONENT_ID, HW_VERSION, FW_VERSION, SERIAL_NUMBER, "" /* softwareVersion */}, + {SW_COMPONENT_ID, "" /* hardwareVersion */, "" /* firmwareVersion */, + "" /* serialNumber */, SW_VERSION}}; + + common::CommonProps commonProps = {SENSOR_ID, SENSOR_STRENGTH, MAX_ENROLLMENTS_PER_USER, + componentInfo}; + + SensorLocation sensorLocation = {0 /* displayId */, 0 /* sensorLocationX */, + 0 /* sensorLocationY */, 0 /* sensorRadius */}; + + *out = {{commonProps, + SENSOR_TYPE, + {sensorLocation}, + SUPPORTS_NAVIGATION_GESTURES, + false /* supportsDetectInteraction */}}; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Fingerprint::createSession(int32_t sensorId, int32_t userId, + const std::shared_ptr& cb, + std::shared_ptr* out) { + CHECK(mSession == nullptr || mSession->isClosed()) << "Open session already exists!"; + + mSession = SharedRefBase::make(sensorId, userId, cb, mEngine.get(), &mWorker); + *out = mSession; + return ndk::ScopedAStatus::ok(); +} + +} // namespace aidl::android::hardware::biometrics::fingerprint diff --git a/biometrics/fingerprint/aidl/default/Session.cpp b/biometrics/fingerprint/aidl/default/Session.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ca481e7cf0301eb0bebe308b911123b02a53e87d --- /dev/null +++ b/biometrics/fingerprint/aidl/default/Session.cpp @@ -0,0 +1,247 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Session.h" + +#include + +#include "CancellationSignal.h" + +namespace aidl::android::hardware::biometrics::fingerprint { + +Session::Session(int sensorId, int userId, std::shared_ptr cb, + FakeFingerprintEngine* engine, WorkerThread* worker) + : mSensorId(sensorId), + mUserId(userId), + mCb(std::move(cb)), + mEngine(engine), + mWorker(worker), + mScheduledState(SessionState::IDLING), + mCurrentState(SessionState::IDLING) { + CHECK_GE(mSensorId, 0); + CHECK_GE(mUserId, 0); + CHECK(mEngine); + CHECK(mWorker); + CHECK(mCb); +} + +void Session::scheduleStateOrCrash(SessionState state) { + // TODO(b/166800618): call enterIdling from the terminal callbacks and restore these checks. + // CHECK(mScheduledState == SessionState::IDLING); + // CHECK(mCurrentState == SessionState::IDLING); + mScheduledState = state; +} + +void Session::enterStateOrCrash(SessionState state) { + CHECK(mScheduledState == state); + mCurrentState = state; + mScheduledState = SessionState::IDLING; +} + +void Session::enterIdling() { + // TODO(b/166800618): call enterIdling from the terminal callbacks and rethink this conditional. + if (mCurrentState != SessionState::CLOSED) { + mCurrentState = SessionState::IDLING; + } +} + +bool Session::isClosed() { + return mCurrentState == SessionState::CLOSED; +} + +ndk::ScopedAStatus Session::generateChallenge() { + LOG(INFO) << "generateChallenge"; + scheduleStateOrCrash(SessionState::GENERATING_CHALLENGE); + + mWorker->schedule(Callable::from([this] { + enterStateOrCrash(SessionState::GENERATING_CHALLENGE); + mEngine->generateChallengeImpl(mCb.get()); + enterIdling(); + })); + + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Session::revokeChallenge(int64_t challenge) { + LOG(INFO) << "revokeChallenge"; + scheduleStateOrCrash(SessionState::REVOKING_CHALLENGE); + + mWorker->schedule(Callable::from([this, challenge] { + enterStateOrCrash(SessionState::REVOKING_CHALLENGE); + mEngine->revokeChallengeImpl(mCb.get(), challenge); + enterIdling(); + })); + + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Session::enroll(const keymaster::HardwareAuthToken& hat, + std::shared_ptr* out) { + LOG(INFO) << "enroll"; + scheduleStateOrCrash(SessionState::ENROLLING); + + std::promise cancellationPromise; + auto cancFuture = cancellationPromise.get_future(); + + mWorker->schedule(Callable::from([this, hat, cancFuture = std::move(cancFuture)] { + enterStateOrCrash(SessionState::ENROLLING); + if (shouldCancel(cancFuture)) { + mCb->onError(Error::CANCELED, 0 /* vendorCode */); + } else { + mEngine->enrollImpl(mCb.get(), hat); + } + enterIdling(); + })); + + *out = SharedRefBase::make(std::move(cancellationPromise)); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Session::authenticate(int64_t operationId, + std::shared_ptr* out) { + LOG(INFO) << "authenticate"; + scheduleStateOrCrash(SessionState::AUTHENTICATING); + + std::promise cancPromise; + auto cancFuture = cancPromise.get_future(); + + mWorker->schedule(Callable::from([this, operationId, cancFuture = std::move(cancFuture)] { + enterStateOrCrash(SessionState::AUTHENTICATING); + if (shouldCancel(cancFuture)) { + mCb->onError(Error::CANCELED, 0 /* vendorCode */); + } else { + mEngine->authenticateImpl(mCb.get(), operationId); + } + enterIdling(); + })); + + *out = SharedRefBase::make(std::move(cancPromise)); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Session::detectInteraction(std::shared_ptr* out) { + LOG(INFO) << "detectInteraction"; + scheduleStateOrCrash(SessionState::DETECTING_INTERACTION); + + std::promise cancellationPromise; + auto cancFuture = cancellationPromise.get_future(); + + mWorker->schedule(Callable::from([this, cancFuture = std::move(cancFuture)] { + enterStateOrCrash(SessionState::DETECTING_INTERACTION); + if (shouldCancel(cancFuture)) { + mCb->onError(Error::CANCELED, 0 /* vendorCode */); + } else { + mEngine->detectInteractionImpl(mCb.get()); + } + enterIdling(); + })); + + *out = SharedRefBase::make(std::move(cancellationPromise)); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Session::enumerateEnrollments() { + LOG(INFO) << "enumerateEnrollments"; + scheduleStateOrCrash(SessionState::ENUMERATING_ENROLLMENTS); + + mWorker->schedule(Callable::from([this] { + enterStateOrCrash(SessionState::ENUMERATING_ENROLLMENTS); + mEngine->enumerateEnrollmentsImpl(mCb.get()); + enterIdling(); + })); + + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Session::removeEnrollments(const std::vector& enrollmentIds) { + LOG(INFO) << "removeEnrollments"; + scheduleStateOrCrash(SessionState::REMOVING_ENROLLMENTS); + + mWorker->schedule(Callable::from([this, enrollmentIds] { + enterStateOrCrash(SessionState::REMOVING_ENROLLMENTS); + mEngine->removeEnrollmentsImpl(mCb.get(), enrollmentIds); + enterIdling(); + })); + + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Session::getAuthenticatorId() { + LOG(INFO) << "getAuthenticatorId"; + scheduleStateOrCrash(SessionState::GETTING_AUTHENTICATOR_ID); + + mWorker->schedule(Callable::from([this] { + enterStateOrCrash(SessionState::GETTING_AUTHENTICATOR_ID); + mEngine->getAuthenticatorIdImpl(mCb.get()); + enterIdling(); + })); + + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Session::invalidateAuthenticatorId() { + LOG(INFO) << "invalidateAuthenticatorId"; + scheduleStateOrCrash(SessionState::INVALIDATING_AUTHENTICATOR_ID); + + mWorker->schedule(Callable::from([this] { + enterStateOrCrash(SessionState::INVALIDATING_AUTHENTICATOR_ID); + mEngine->invalidateAuthenticatorIdImpl(mCb.get()); + enterIdling(); + })); + + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Session::resetLockout(const keymaster::HardwareAuthToken& hat) { + LOG(INFO) << "resetLockout"; + scheduleStateOrCrash(SessionState::RESETTING_LOCKOUT); + + mWorker->schedule(Callable::from([this, hat] { + enterStateOrCrash(SessionState::RESETTING_LOCKOUT); + mEngine->resetLockoutImpl(mCb.get(), hat); + enterIdling(); + })); + + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Session::close() { + LOG(INFO) << "close"; + // TODO(b/166800618): call enterIdling from the terminal callbacks and restore this check. + // CHECK(mCurrentState == SessionState::IDLING) << "Can't close a non-idling session. + // Crashing."; + mCurrentState = SessionState::CLOSED; + mCb->onSessionClosed(); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Session::onPointerDown(int32_t /*pointerId*/, int32_t /*x*/, int32_t /*y*/, + float /*minor*/, float /*major*/) { + LOG(INFO) << "onPointerDown"; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Session::onPointerUp(int32_t /*pointerId*/) { + LOG(INFO) << "onPointerUp"; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Session::onUiReady() { + LOG(INFO) << "onUiReady"; + return ndk::ScopedAStatus::ok(); +} + +} // namespace aidl::android::hardware::biometrics::fingerprint diff --git a/biometrics/fingerprint/aidl/default/WorkerThread.cpp b/biometrics/fingerprint/aidl/default/WorkerThread.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d1a63d07eeb51606cfaec4e1d5f63ff22a66e1df --- /dev/null +++ b/biometrics/fingerprint/aidl/default/WorkerThread.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "WorkerThread.h" + +namespace aidl::android::hardware::biometrics::fingerprint { + +// It's important that mThread is initialized after everything else because it runs a member +// function that may use any member of this class. +WorkerThread::WorkerThread(size_t maxQueueSize) + : mMaxSize(maxQueueSize), + mIsDestructing(false), + mQueue(), + mQueueMutex(), + mQueueCond(), + mThread(&WorkerThread::threadFunc, this) {} + +WorkerThread::~WorkerThread() { + // This is a signal for threadFunc to terminate as soon as possible, and a hint for schedule + // that it doesn't need to do any work. + mIsDestructing = true; + mQueueCond.notify_all(); + mThread.join(); +} + +bool WorkerThread::schedule(std::unique_ptr task) { + if (mIsDestructing) { + return false; + } + + std::unique_lock lock(mQueueMutex); + if (mQueue.size() >= mMaxSize) { + return false; + } + mQueue.push_back(std::move(task)); + lock.unlock(); + mQueueCond.notify_one(); + return true; +} + +void WorkerThread::threadFunc() { + while (!mIsDestructing) { + std::unique_lock lock(mQueueMutex); + mQueueCond.wait(lock, [this] { return !mQueue.empty() || mIsDestructing; }); + if (mIsDestructing) { + return; + } + std::unique_ptr task = std::move(mQueue.front()); + mQueue.pop_front(); + lock.unlock(); + (*task)(); + } +} + +} // namespace aidl::android::hardware::biometrics::fingerprint diff --git a/biometrics/fingerprint/aidl/default/fingerprint-default.rc b/biometrics/fingerprint/aidl/default/fingerprint-default.rc new file mode 100644 index 0000000000000000000000000000000000000000..eb62c567fd02fbac728573d7a135c32a9f73a63f --- /dev/null +++ b/biometrics/fingerprint/aidl/default/fingerprint-default.rc @@ -0,0 +1,5 @@ +service vendor.fingerprint-default /vendor/bin/hw/android.hardware.biometrics.fingerprint-service.example + class hal + user nobody + group nobody + diff --git a/biometrics/fingerprint/aidl/default/fingerprint-default.xml b/biometrics/fingerprint/aidl/default/fingerprint-default.xml new file mode 100644 index 0000000000000000000000000000000000000000..89da765616dae4415691998c65ad1c53a924d150 --- /dev/null +++ b/biometrics/fingerprint/aidl/default/fingerprint-default.xml @@ -0,0 +1,6 @@ + + + android.hardware.biometrics.fingerprint + IFingerprint/default + + diff --git a/biometrics/fingerprint/aidl/default/include/Callable.h b/biometrics/fingerprint/aidl/default/include/Callable.h new file mode 100644 index 0000000000000000000000000000000000000000..c6295117e51ea3b829501744fb7524b03b18d63f --- /dev/null +++ b/biometrics/fingerprint/aidl/default/include/Callable.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +namespace aidl::android::hardware::biometrics::fingerprint { + +// Interface for representing parameterless functions. Unlike std::function, this can also +// represent move-only lambdas. +class Callable { + public: + virtual void operator()() = 0; + virtual ~Callable() = default; + + // Creates a heap-allocated Callable instance from any function object. + template + static std::unique_ptr from(T func); + + private: + template + class AnyFuncWrapper; +}; + +// Private helper class for wrapping any function object into a Callable. +template +class Callable::AnyFuncWrapper : public Callable { + public: + explicit AnyFuncWrapper(T func) : mFunc(std::move(func)) {} + + void operator()() override { mFunc(); } + + private: + T mFunc; +}; + +template +std::unique_ptr Callable::from(T func) { + return std::make_unique>(std::move(func)); +} + +} // namespace aidl::android::hardware::biometrics::fingerprint \ No newline at end of file diff --git a/biometrics/fingerprint/aidl/default/include/CancellationSignal.h b/biometrics/fingerprint/aidl/default/include/CancellationSignal.h new file mode 100644 index 0000000000000000000000000000000000000000..99f2fbae9743873dd25296eb5f3e7b139190df15 --- /dev/null +++ b/biometrics/fingerprint/aidl/default/include/CancellationSignal.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +#include + +#include "WorkerThread.h" + +namespace aidl::android::hardware::biometrics::fingerprint { + +class CancellationSignal : public common::BnCancellationSignal { + public: + explicit CancellationSignal(std::promise&& cancellationPromise); + + ndk::ScopedAStatus cancel() override; + + private: + std::promise mCancellationPromise; +}; + +// Returns whether the given cancellation future is ready, i.e. whether the operation corresponding +// to this future should be cancelled. +bool shouldCancel(const std::future& cancellationFuture); + +} // namespace aidl::android::hardware::biometrics::fingerprint diff --git a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h new file mode 100644 index 0000000000000000000000000000000000000000..b92777068c187717b1b267aca8b7a63c1a7ca86b --- /dev/null +++ b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +namespace aidl::android::hardware::biometrics::fingerprint { + +class FakeFingerprintEngine { + public: + FakeFingerprintEngine() : mRandom(std::mt19937::default_seed) {} + + void generateChallengeImpl(ISessionCallback* cb) { + LOG(INFO) << "generateChallengeImpl"; + std::uniform_int_distribution dist; + auto challenge = dist(mRandom); + cb->onChallengeGenerated(challenge); + } + + void revokeChallengeImpl(ISessionCallback* cb, int64_t challenge) { + LOG(INFO) << "revokeChallengeImpl"; + cb->onChallengeRevoked(challenge); + } + + void enrollImpl(ISessionCallback* cb, const keymaster::HardwareAuthToken& hat) { + LOG(INFO) << "enrollImpl"; + // Do proper HAT verification in the real implementation. + if (hat.mac.empty()) { + cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */); + return; + } + cb->onEnrollmentProgress(0 /* enrollmentId */, 0 /* remaining */); + } + + void authenticateImpl(ISessionCallback* cb, int64_t /* operationId */) { + LOG(INFO) << "authenticateImpl"; + cb->onAuthenticationSucceeded(0 /* enrollmentId */, {} /* hat */); + } + + void detectInteractionImpl(ISessionCallback* cb) { + LOG(INFO) << "detectInteractionImpl"; + cb->onInteractionDetected(); + } + + void enumerateEnrollmentsImpl(ISessionCallback* cb) { + LOG(INFO) << "enumerateEnrollmentsImpl"; + cb->onEnrollmentsEnumerated({} /* enrollmentIds */); + } + + void removeEnrollmentsImpl(ISessionCallback* cb, const std::vector& enrollmentIds) { + LOG(INFO) << "removeEnrollmentsImpl"; + cb->onEnrollmentsRemoved(enrollmentIds); + } + + void getAuthenticatorIdImpl(ISessionCallback* cb) { + LOG(INFO) << "getAuthenticatorIdImpl"; + cb->onAuthenticatorIdRetrieved(0 /* authenticatorId */); + } + + void invalidateAuthenticatorIdImpl(ISessionCallback* cb) { + LOG(INFO) << "invalidateAuthenticatorIdImpl"; + cb->onAuthenticatorIdInvalidated(0 /* newAuthenticatorId */); + } + + void resetLockoutImpl(ISessionCallback* cb, const keymaster::HardwareAuthToken& /*hat*/) { + LOG(INFO) << "resetLockoutImpl"; + cb->onLockoutCleared(); + } + + std::mt19937 mRandom; +}; + +} // namespace aidl::android::hardware::biometrics::fingerprint diff --git a/biometrics/fingerprint/aidl/default/include/Fingerprint.h b/biometrics/fingerprint/aidl/default/include/Fingerprint.h new file mode 100644 index 0000000000000000000000000000000000000000..7bd3d6ddfd22c5d65f338939f4c8559479f0f96f --- /dev/null +++ b/biometrics/fingerprint/aidl/default/include/Fingerprint.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include "FakeFingerprintEngine.h" +#include "Session.h" +#include "WorkerThread.h" + +namespace aidl::android::hardware::biometrics::fingerprint { + +class Fingerprint : public BnFingerprint { + public: + Fingerprint(); + + ndk::ScopedAStatus getSensorProps(std::vector* out) override; + + ndk::ScopedAStatus createSession(int32_t sensorId, int32_t userId, + const std::shared_ptr& cb, + std::shared_ptr* out) override; + + private: + std::unique_ptr mEngine; + WorkerThread mWorker; + std::shared_ptr mSession; +}; + +} // namespace aidl::android::hardware::biometrics::fingerprint diff --git a/biometrics/fingerprint/aidl/default/include/Session.h b/biometrics/fingerprint/aidl/default/include/Session.h new file mode 100644 index 0000000000000000000000000000000000000000..9e464229e1ec7f803e3b6b58e2b3ae0217160974 --- /dev/null +++ b/biometrics/fingerprint/aidl/default/include/Session.h @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +#include "FakeFingerprintEngine.h" +#include "WorkerThread.h" + +namespace aidl::android::hardware::biometrics::fingerprint { + +namespace common = aidl::android::hardware::biometrics::common; +namespace keymaster = aidl::android::hardware::keymaster; + +enum class SessionState { + IDLING, + CLOSED, + GENERATING_CHALLENGE, + REVOKING_CHALLENGE, + ENROLLING, + AUTHENTICATING, + DETECTING_INTERACTION, + ENUMERATING_ENROLLMENTS, + REMOVING_ENROLLMENTS, + GETTING_AUTHENTICATOR_ID, + INVALIDATING_AUTHENTICATOR_ID, + RESETTING_LOCKOUT, +}; + +class Session : public BnSession { + public: + Session(int sensorId, int userId, std::shared_ptr cb, + FakeFingerprintEngine* engine, WorkerThread* worker); + + ndk::ScopedAStatus generateChallenge() override; + + ndk::ScopedAStatus revokeChallenge(int64_t challenge) override; + + ndk::ScopedAStatus enroll(const keymaster::HardwareAuthToken& hat, + std::shared_ptr* out) override; + + ndk::ScopedAStatus authenticate(int64_t operationId, + std::shared_ptr* out) override; + + ndk::ScopedAStatus detectInteraction( + std::shared_ptr* out) override; + + ndk::ScopedAStatus enumerateEnrollments() override; + + ndk::ScopedAStatus removeEnrollments(const std::vector& enrollmentIds) override; + + ndk::ScopedAStatus getAuthenticatorId() override; + + ndk::ScopedAStatus invalidateAuthenticatorId() override; + + ndk::ScopedAStatus resetLockout(const keymaster::HardwareAuthToken& hat) override; + + ndk::ScopedAStatus close() override; + + ndk::ScopedAStatus onPointerDown(int32_t pointerId, int32_t x, int32_t y, float minor, + float major) override; + + ndk::ScopedAStatus onPointerUp(int32_t pointerId) override; + + ndk::ScopedAStatus onUiReady() override; + + bool isClosed(); + + private: + // Crashes the HAL if it's not currently idling because that would be an invalid state machine + // transition. Otherwise, sets the scheduled state to the given state. + void scheduleStateOrCrash(SessionState state); + + // Crashes the HAL if the provided state doesn't match the previously scheduled state. + // Otherwise, transitions into the provided state, clears the scheduled state, and notifies + // the client about the transition by calling ISessionCallback#onStateChanged. + void enterStateOrCrash(SessionState state); + + // Sets the current state to SessionState::IDLING and notifies the client about the transition + // by calling ISessionCallback#onStateChanged. + void enterIdling(); + + // The sensor and user IDs for which this session was created. + int32_t mSensorId; + int32_t mUserId; + + // Callback for talking to the framework. This callback must only be called from non-binder + // threads to prevent nested binder calls and consequently a binder thread exhaustion. + // Practically, it means that this callback should always be called from the worker thread. + std::shared_ptr mCb; + + // Module that communicates to the actual fingerprint hardware, keystore, TEE, etc. In real + // life such modules typically consume a lot of memory and are slow to initialize. This is here + // to showcase how such a module can be used within a Session without incurring the high + // initialization costs every time a Session is constructed. + FakeFingerprintEngine* mEngine; + + // Worker thread that allows to schedule tasks for asynchronous execution. + WorkerThread* mWorker; + + // Simple representation of the session's state machine. These are atomic because they can be + // modified from both the main and the worker threads. + std::atomic mScheduledState; + std::atomic mCurrentState; +}; + +} // namespace aidl::android::hardware::biometrics::fingerprint diff --git a/biometrics/fingerprint/aidl/default/include/WorkerThread.h b/biometrics/fingerprint/aidl/default/include/WorkerThread.h new file mode 100644 index 0000000000000000000000000000000000000000..6fff4f2cb70a3a0a09ce72ba174f8a9d45a2a62a --- /dev/null +++ b/biometrics/fingerprint/aidl/default/include/WorkerThread.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +#include + +#include "Callable.h" + +namespace aidl::android::hardware::biometrics::fingerprint { + +// A class that encapsulates a worker thread and a task queue, and provides a convenient interface +// for a Session to schedule its tasks for asynchronous execution. +class WorkerThread final { + public: + // Internally creates a queue that cannot exceed maxQueueSize elements and a new thread that + // polls the queue for tasks until this instance is destructed. + explicit WorkerThread(size_t maxQueueSize); + + // Unblocks the internal queue and calls join on the internal thread allowing it to gracefully + // exit. + ~WorkerThread(); + + // Disallow copying this class. + WorkerThread(const WorkerThread&) = delete; + WorkerThread& operator=(const WorkerThread&) = delete; + + // Also disable moving this class to simplify implementation. + WorkerThread(WorkerThread&&) = delete; + WorkerThread& operator=(WorkerThread&&) = delete; + + // If the internal queue is not full, pushes a task at the end of the queue and returns true. + // Otherwise, returns false. If the queue is busy, blocks until it becomes available. + // This method expects heap-allocated tasks because it's the simplest way to represent function + // objects of any type. Stack-allocated std::function could be used instead, but it cannot + // represent functions with move-only captures because std::function is inherently copyable. + // Not being able to pass move-only lambdas is a major limitation for the HAL implementation, + // so heap-allocated tasks that share a common interface (Callable) were chosen instead. + bool schedule(std::unique_ptr task); + + private: + // The function that runs on the internal thread. Sequentially runs the available tasks from + // the queue. If the queue is empty, waits until a new task is added. If the worker is being + // destructed, finishes its current task and gracefully exits. + void threadFunc(); + + // The maximum size that the queue is allowed to expand to. + size_t mMaxSize; + + // Whether the destructor was called. If true, tells threadFunc to exit as soon as possible, and + // tells schedule to avoid doing any work. + std::atomic mIsDestructing; + + // Queue that's guarded by mQueueMutex and mQueueCond. + std::deque> mQueue; + std::mutex mQueueMutex; + std::condition_variable mQueueCond; + + // The internal thread that works on the tasks from the queue. + std::thread mThread; +}; + +} // namespace aidl::android::hardware::biometrics::fingerprint diff --git a/biometrics/fingerprint/aidl/default/main.cpp b/biometrics/fingerprint/aidl/default/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4690d73d80c6c75c2928b0bab4b65382112381e0 --- /dev/null +++ b/biometrics/fingerprint/aidl/default/main.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Fingerprint.h" + +#include +#include +#include + +using aidl::android::hardware::biometrics::fingerprint::Fingerprint; + +int main() { + LOG(INFO) << "Fingerprint HAL started"; + ABinderProcess_setThreadPoolMaxThreadCount(0); + std::shared_ptr hal = ndk::SharedRefBase::make(); + + const std::string instance = std::string(Fingerprint::descriptor) + "/default"; + binder_status_t status = AServiceManager_addService(hal->asBinder().get(), instance.c_str()); + CHECK(status == STATUS_OK); + + ABinderProcess_joinThreadPool(); + return EXIT_FAILURE; // should not reach +} diff --git a/biometrics/fingerprint/aidl/default/tests/WorkerThreadTest.cpp b/biometrics/fingerprint/aidl/default/tests/WorkerThreadTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b2417bd2425cd30c752bdea5bdd956fc6fdc5e32 --- /dev/null +++ b/biometrics/fingerprint/aidl/default/tests/WorkerThreadTest.cpp @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include + +#include "WorkerThread.h" + +namespace { + +using aidl::android::hardware::biometrics::fingerprint::Callable; +using aidl::android::hardware::biometrics::fingerprint::WorkerThread; +using namespace std::chrono_literals; + +TEST(WorkerThreadTest, ScheduleReturnsTrueWhenQueueHasSpace) { + WorkerThread worker(1 /*maxQueueSize*/); + for (int i = 0; i < 100; ++i) { + std::promise promise; + auto future = promise.get_future(); + + ASSERT_TRUE(worker.schedule(Callable::from([promise = std::move(promise)]() mutable { + // Notify that the task has started. + promise.set_value(); + }))); + + future.wait(); + } +} + +TEST(WorkerThreadTest, ScheduleReturnsFalseWhenQueueIsFull) { + WorkerThread worker(2 /*maxQueueSize*/); + + std::promise promise; + auto future = promise.get_future(); + + // Schedule a long-running task. + ASSERT_TRUE(worker.schedule(Callable::from([promise = std::move(promise)]() mutable { + // Notify that the task has started. + promise.set_value(); + // Block for a "very long" time. + std::this_thread::sleep_for(1s); + }))); + + // Make sure the long-running task began executing. + future.wait(); + + // The first task is already being worked on, which means the queue must be empty. + // Fill the worker's queue to the maximum. + ASSERT_TRUE(worker.schedule(Callable::from([] {}))); + ASSERT_TRUE(worker.schedule(Callable::from([] {}))); + + EXPECT_FALSE(worker.schedule(Callable::from([] {}))); +} + +TEST(WorkerThreadTest, TasksExecuteInOrder) { + constexpr int NUM_TASKS = 10000; + WorkerThread worker(NUM_TASKS); + + std::mutex mut; + std::condition_variable cv; + bool finished = false; + std::vector results; + + for (int i = 0; i < NUM_TASKS; ++i) { + worker.schedule(Callable::from([&mut, &results, i] { + // Delay tasks differently to provoke races. + std::this_thread::sleep_for(std::chrono::nanoseconds(100 - i % 100)); + auto lock = std::lock_guard(mut); + results.push_back(i); + })); + } + + // Schedule a special task to signal when all of the tasks are finished. + worker.schedule(Callable::from([&mut, &cv, &finished] { + auto lock = std::lock_guard(mut); + finished = true; + cv.notify_one(); + })); + + auto lock = std::unique_lock(mut); + cv.wait(lock, [&finished] { return finished; }); + ASSERT_EQ(results.size(), NUM_TASKS); + EXPECT_TRUE(std::is_sorted(results.begin(), results.end())); +} + +TEST(WorkerThreadTest, ExecutionStopsAfterWorkerIsDestroyed) { + std::promise promise1; + std::promise promise2; + auto future1 = promise1.get_future(); + auto future2 = promise2.get_future(); + std::atomic value; + + // Local scope for the worker to test its destructor when it goes out of scope. + { + WorkerThread worker(2 /*maxQueueSize*/); + + ASSERT_TRUE(worker.schedule(Callable::from([promise = std::move(promise1)]() mutable { + promise.set_value(); + std::this_thread::sleep_for(200ms); + }))); + + // The first task should start executing. + future1.wait(); + + // The second task should schedule successfully. + ASSERT_TRUE( + worker.schedule(Callable::from([promise = std::move(promise2), &value]() mutable { + // The worker should destruct before it gets a chance to execute this. + value = true; + promise.set_value(); + }))); + } + + // The second task should never execute. + future2.wait(); + // The future is expected to be ready but contain an exception. + // Cannot use ASSERT_THROW because exceptions are disabled in this codebase. + // ASSERT_THROW(future2.get(), std::future_error); + EXPECT_FALSE(value); +} + +} // namespace diff --git a/biometrics/fingerprint/aidl/vts/Android.bp b/biometrics/fingerprint/aidl/vts/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..30d562414477140407399a61005ea7545a4bfd37 --- /dev/null +++ b/biometrics/fingerprint/aidl/vts/Android.bp @@ -0,0 +1,29 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_test { + name: "VtsHalBiometricsFingerprintTargetTest", + defaults: [ + "VtsHalTargetTestDefaults", + "use_libaidlvintf_gtest_helper_static", + ], + srcs: ["VtsHalBiometricsFingerprintTargetTest.cpp"], + static_libs: [ + "android.hardware.biometrics.common-V1-ndk", + "android.hardware.biometrics.fingerprint-V1-ndk", + "android.hardware.keymaster-V3-ndk", + ], + shared_libs: [ + "libbinder_ndk", + ], + test_suites: [ + "general-tests", + "vts", + ], +} diff --git a/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp b/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1cd8c769f2b1acfbb4030eb0ac2704c1477c2745 --- /dev/null +++ b/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp @@ -0,0 +1,303 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include +#include + +#include +#include + +namespace aidl::android::hardware::biometrics::fingerprint { +namespace { + +using namespace std::literals::chrono_literals; + +constexpr int kSensorId = 0; +constexpr int kUserId = 0; + +class SessionCallback : public BnSessionCallback { + public: + ndk::ScopedAStatus onChallengeGenerated(int64_t challenge) override { + auto lock = std::lock_guard{mMutex}; + mOnChallengeGeneratedInvoked = true; + mGeneratedChallenge = challenge; + mCv.notify_one(); + return ndk::ScopedAStatus::ok(); + } + + ndk::ScopedAStatus onChallengeRevoked(int64_t challenge) override { + auto lock = std::lock_guard{mMutex}; + mOnChallengeRevokedInvoked = true; + mRevokedChallenge = challenge; + mCv.notify_one(); + return ndk::ScopedAStatus::ok(); + } + + ndk::ScopedAStatus onAcquired(AcquiredInfo /*info*/, int32_t /*vendorCode*/) override { + return ndk::ScopedAStatus::ok(); + } + + ndk::ScopedAStatus onError(Error error, int32_t /*vendorCode*/) override { + auto lock = std::lock_guard{mMutex}; + mError = error; + mOnErrorInvoked = true; + mCv.notify_one(); + return ndk::ScopedAStatus::ok(); + } + + ndk::ScopedAStatus onEnrollmentProgress(int32_t /*enrollmentId*/, + int32_t /*remaining*/) override { + return ndk::ScopedAStatus::ok(); + } + + ndk::ScopedAStatus onAuthenticationSucceeded( + int32_t /*enrollmentId*/, const keymaster::HardwareAuthToken& /*hat*/) override { + return ndk::ScopedAStatus::ok(); + } + + ndk::ScopedAStatus onAuthenticationFailed() override { return ndk::ScopedAStatus::ok(); } + + ndk::ScopedAStatus onLockoutTimed(int64_t /*durationMillis*/) override { + return ndk::ScopedAStatus::ok(); + } + + ndk::ScopedAStatus onLockoutPermanent() override { return ndk::ScopedAStatus::ok(); } + + ndk::ScopedAStatus onLockoutCleared() override { return ndk::ScopedAStatus::ok(); } + + ndk::ScopedAStatus onInteractionDetected() override { return ndk::ScopedAStatus::ok(); } + + ndk::ScopedAStatus onEnrollmentsEnumerated( + const std::vector& /*enrollmentIds*/) override { + auto lock = std::lock_guard{mMutex}; + mOnEnrollmentsEnumeratedInvoked = true; + mCv.notify_one(); + return ndk::ScopedAStatus::ok(); + } + + ndk::ScopedAStatus onEnrollmentsRemoved( + const std::vector& /*enrollmentIds*/) override { + auto lock = std::lock_guard{mMutex}; + mOnEnrollmentsRemovedInvoked = true; + mCv.notify_one(); + return ndk::ScopedAStatus::ok(); + } + + ndk::ScopedAStatus onAuthenticatorIdRetrieved(int64_t /*authenticatorId*/) override { + auto lock = std::lock_guard{mMutex}; + mOnAuthenticatorIdRetrievedInvoked = true; + mCv.notify_one(); + return ndk::ScopedAStatus::ok(); + } + + ndk::ScopedAStatus onAuthenticatorIdInvalidated(int64_t /*newAuthenticatorId*/) override { + auto lock = std::lock_guard{mMutex}; + mOnAuthenticatorIdInvalidatedInvoked = true; + mCv.notify_one(); + return ndk::ScopedAStatus::ok(); + } + + ndk::ScopedAStatus onSessionClosed() override { + auto lock = std::lock_guard{mMutex}; + mOnSessionClosedInvoked = true; + mCv.notify_one(); + return ndk::ScopedAStatus::ok(); + } + + std::mutex mMutex; + std::condition_variable mCv; + Error mError = Error::UNKNOWN; + int64_t mGeneratedChallenge = 0; + int64_t mRevokedChallenge = 0; + bool mOnChallengeGeneratedInvoked = false; + bool mOnChallengeRevokedInvoked = false; + bool mOnErrorInvoked = false; + bool mOnEnrollmentsEnumeratedInvoked = false; + bool mOnEnrollmentsRemovedInvoked = false; + bool mOnAuthenticatorIdRetrievedInvoked = false; + bool mOnAuthenticatorIdInvalidatedInvoked = false; + bool mOnSessionClosedInvoked = false; +}; + +class Fingerprint : public testing::TestWithParam { + protected: + void SetUp() override { + // Prepare the callback. + mCb = ndk::SharedRefBase::make(); + + int retries = 0; + bool isOk = false; + // If the first attempt to create a session fails, we try to create a session again. The + // first attempt might fail if the framework already has an active session. The AIDL + // contract doesn't allow to create a new session without closing the old one. However, we + // can't close the framework's session from VTS. The expectation here is that the HAL will + // crash after the first illegal attempt to create a session, then it will restart, and then + // we'll be able to create a session. + do { + // Get an instance of the HAL. + AIBinder* binder = AServiceManager_waitForService(GetParam().c_str()); + ASSERT_NE(binder, nullptr); + mHal = IFingerprint::fromBinder(ndk::SpAIBinder(binder)); + + // Create a session. + isOk = mHal->createSession(kSensorId, kUserId, mCb, &mSession).isOk(); + ++retries; + } while (!isOk && retries < 2); + + ASSERT_TRUE(isOk); + } + + void TearDown() override { + // Close the mSession. + ASSERT_TRUE(mSession->close().isOk()); + + // Make sure the mSession is closed. + auto lock = std::unique_lock(mCb->mMutex); + mCb->mCv.wait(lock, [this] { return mCb->mOnSessionClosedInvoked; }); + } + + std::shared_ptr mHal; + std::shared_ptr mCb; + std::shared_ptr mSession; +}; + +TEST_P(Fingerprint, GetSensorPropsWorksTest) { + std::vector sensorProps; + + // Call the method. + ASSERT_TRUE(mHal->getSensorProps(&sensorProps).isOk()); + + // Make sure the sensorProps aren't empty. + ASSERT_FALSE(sensorProps.empty()); + ASSERT_FALSE(sensorProps[0].commonProps.componentInfo.empty()); +} + +TEST_P(Fingerprint, EnrollWithBadHatResultsInErrorTest) { + // Call the method. + auto hat = keymaster::HardwareAuthToken{}; + std::shared_ptr cancellationSignal; + ASSERT_TRUE(mSession->enroll(hat, &cancellationSignal).isOk()); + + // Make sure an error is returned. + auto lock = std::unique_lock{mCb->mMutex}; + mCb->mCv.wait(lock, [this] { return mCb->mOnErrorInvoked; }); +} + +TEST_P(Fingerprint, GenerateChallengeProducesUniqueChallengesTest) { + static constexpr int kIterations = 100; + + auto challenges = std::set{}; + for (unsigned int i = 0; i < kIterations; ++i) { + // Call the method. + ASSERT_TRUE(mSession->generateChallenge().isOk()); + + // Check that the generated challenge is unique and not 0. + auto lock = std::unique_lock{mCb->mMutex}; + mCb->mCv.wait(lock, [this] { return mCb->mOnChallengeGeneratedInvoked; }); + ASSERT_NE(mCb->mGeneratedChallenge, 0); + ASSERT_EQ(challenges.find(mCb->mGeneratedChallenge), challenges.end()); + + challenges.insert(mCb->mGeneratedChallenge); + mCb->mOnChallengeGeneratedInvoked = false; + } +} + +TEST_P(Fingerprint, RevokeChallengeWorksForNonexistentChallengeTest) { + const int64_t nonexistentChallenge = 123; + + // Call the method. + ASSERT_TRUE(mSession->revokeChallenge(nonexistentChallenge).isOk()); + + // Check that the challenge is revoked and matches the requested challenge. + auto lock = std::unique_lock{mCb->mMutex}; + mCb->mCv.wait(lock, [this] { return mCb->mOnChallengeRevokedInvoked; }); + ASSERT_EQ(mCb->mRevokedChallenge, nonexistentChallenge); +} + +TEST_P(Fingerprint, RevokeChallengeWorksForExistentChallengeTest) { + // Generate a challenge. + ASSERT_TRUE(mSession->generateChallenge().isOk()); + + // Wait for the result. + auto lock = std::unique_lock{mCb->mMutex}; + mCb->mCv.wait(lock, [this] { return mCb->mOnChallengeGeneratedInvoked; }); + lock.unlock(); + + // Revoke the challenge. + ASSERT_TRUE(mSession->revokeChallenge(mCb->mGeneratedChallenge).isOk()); + + // Check that the challenge is revoked and matches the requested challenge. + lock.lock(); + mCb->mCv.wait(lock, [this] { return mCb->mOnChallengeRevokedInvoked; }); + ASSERT_EQ(mCb->mRevokedChallenge, mCb->mGeneratedChallenge); +} + +TEST_P(Fingerprint, EnumerateEnrollmentsWorksTest) { + // Call the method. + ASSERT_TRUE(mSession->enumerateEnrollments().isOk()); + + // Wait for the result. + auto lock = std::unique_lock{mCb->mMutex}; + mCb->mCv.wait(lock, [this] { return mCb->mOnEnrollmentsEnumeratedInvoked; }); +} + +TEST_P(Fingerprint, RemoveEnrollmentsWorksTest) { + // Call the method. + ASSERT_TRUE(mSession->removeEnrollments({}).isOk()); + + // Wait for the result. + auto lock = std::unique_lock{mCb->mMutex}; + mCb->mCv.wait(lock, [this] { return mCb->mOnEnrollmentsRemovedInvoked; }); +} + +TEST_P(Fingerprint, GetAuthenticatorIdWorksTest) { + // Call the method. + ASSERT_TRUE(mSession->getAuthenticatorId().isOk()); + + // Wait for the result. + auto lock = std::unique_lock{mCb->mMutex}; + mCb->mCv.wait(lock, [this] { return mCb->mOnAuthenticatorIdRetrievedInvoked; }); +} + +TEST_P(Fingerprint, InvalidateAuthenticatorIdWorksTest) { + // Call the method. + ASSERT_TRUE(mSession->invalidateAuthenticatorId().isOk()); + + // Wait for the result. + auto lock = std::unique_lock{mCb->mMutex}; + mCb->mCv.wait(lock, [this] { return mCb->mOnAuthenticatorIdInvalidatedInvoked; }); +} + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Fingerprint); +INSTANTIATE_TEST_SUITE_P( + IFingerprint, Fingerprint, + testing::ValuesIn(::android::getAidlHalInstanceNames(IFingerprint::descriptor)), + ::android::PrintInstanceNameToString); + +} // namespace +} // namespace aidl::android::hardware::biometrics::fingerprint + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + ABinderProcess_setThreadPoolMaxThreadCount(1); + ABinderProcess_startThreadPool(); + return RUN_ALL_TESTS(); +} diff --git a/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp b/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp index fd82f4941927acfa4de82a187fee6ca46903355e..8ea1ddd0850dc7d00142111e8cb36bcb1479b712 100644 --- a/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp +++ b/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp @@ -50,7 +50,7 @@ using ::android::hardware::bluetooth::V1_0::Status; #define WAIT_FOR_HCI_EVENT_TIMEOUT std::chrono::milliseconds(2000) #define WAIT_FOR_SCO_DATA_TIMEOUT std::chrono::milliseconds(1000) #define WAIT_FOR_ACL_DATA_TIMEOUT std::chrono::milliseconds(1000) -#define INTERFACE_CLOSE_DELAY_MS std::chrono::milliseconds(200) +#define INTERFACE_CLOSE_DELAY_MS std::chrono::milliseconds(600) #define COMMAND_HCI_SHOULD_BE_UNKNOWN \ { 0xff, 0x3B, 0x08, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 } diff --git a/camera/common/1.0/default/HandleImporter.cpp b/camera/common/1.0/default/HandleImporter.cpp index 05a552cd955591082aac8aa9dc345bf2fad6a514..7fcf52330c7135293921a55f07291c0081476fa3 100644 --- a/camera/common/1.0/default/HandleImporter.cpp +++ b/camera/common/1.0/default/HandleImporter.cpp @@ -123,6 +123,24 @@ YCbCrLayout HandleImporter::lockYCbCrInternal(const sp mapper, buffer_handle_ return layout; } +std::vector getPlaneLayouts(const sp mapper, buffer_handle_t& buf) { + auto buffer = const_cast(buf); + std::vector planeLayouts; + hidl_vec encodedPlaneLayouts; + mapper->get(buffer, gralloc4::MetadataType_PlaneLayouts, + [&](const auto& tmpError, const auto& tmpEncodedPlaneLayouts) { + if (tmpError == MapperErrorV4::NONE) { + encodedPlaneLayouts = tmpEncodedPlaneLayouts; + } else { + ALOGE("%s: failed to get plane layouts %d!", __FUNCTION__, tmpError); + } + }); + + gralloc4::decodePlaneLayouts(encodedPlaneLayouts, &planeLayouts); + + return planeLayouts; +} + template <> YCbCrLayout HandleImporter::lockYCbCrInternal( const sp mapper, buffer_handle_t& buf, uint64_t cpuUsage, @@ -147,19 +165,7 @@ YCbCrLayout HandleImporter::lockYCbCrInternal( return layout; } - hidl_vec encodedPlaneLayouts; - mapper->get(buffer, gralloc4::MetadataType_PlaneLayouts, - [&](const auto& tmpError, const auto& tmpEncodedPlaneLayouts) { - if (tmpError == MapperErrorV4::NONE) { - encodedPlaneLayouts = tmpEncodedPlaneLayouts; - } else { - ALOGE("%s: failed to get plane layouts %d!", __FUNCTION__, tmpError); - } - }); - - std::vector planeLayouts; - gralloc4::decodePlaneLayouts(encodedPlaneLayouts, &planeLayouts); - + std::vector planeLayouts = getPlaneLayouts(mapper, buf); for (const auto& planeLayout : planeLayouts) { for (const auto& planeLayoutComponent : planeLayout.components) { const auto& type = planeLayoutComponent.type; @@ -401,6 +407,33 @@ YCbCrLayout HandleImporter::lockYCbCr( return {}; } +status_t HandleImporter::getMonoPlanarStrideBytes(buffer_handle_t &buf, uint32_t *stride /*out*/) { + if (stride == nullptr) { + return BAD_VALUE; + } + + Mutex::Autolock lock(mLock); + + if (!mInitialized) { + initializeLocked(); + } + + if (mMapperV4 != nullptr) { + std::vector planeLayouts = getPlaneLayouts(mMapperV4, buf); + if (planeLayouts.size() != 1) { + ALOGE("%s: Unexpected number of planes %zu!", __FUNCTION__, planeLayouts.size()); + return BAD_VALUE; + } + + *stride = planeLayouts[0].strideInBytes; + } else { + ALOGE("%s: mMapperV4 is null! Query not supported!", __FUNCTION__); + return NO_INIT; + } + + return OK; +} + int HandleImporter::unlock(buffer_handle_t& buf) { if (mMapperV4 != nullptr) { return unlockInternal(mMapperV4, buf); diff --git a/camera/common/1.0/default/include/HandleImporter.h b/camera/common/1.0/default/include/HandleImporter.h index edc97ad9a735608a8f7f15bf52e8a2ccfa2a2dc4..e404439cb66453495642c3f9609a26c550ba0198 100644 --- a/camera/common/1.0/default/include/HandleImporter.h +++ b/camera/common/1.0/default/include/HandleImporter.h @@ -56,6 +56,9 @@ public: YCbCrLayout lockYCbCr(buffer_handle_t& buf, uint64_t cpuUsage, const IMapper::Rect& accessRegion); + // Query the stride of the first plane in bytes. + status_t getMonoPlanarStrideBytes(buffer_handle_t& buf, uint32_t* stride /*out*/); + int unlock(buffer_handle_t& buf); // returns release fence private: diff --git a/camera/device/3.7/Android.bp b/camera/device/3.7/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..be08e91aed375e5da073543620f3ffeae3529f3a --- /dev/null +++ b/camera/device/3.7/Android.bp @@ -0,0 +1,37 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +hidl_interface { + name: "android.hardware.camera.device@3.7", + root: "android.hardware", + srcs: [ + "types.hal", + "ICameraDevice.hal", + "ICameraDeviceSession.hal", + "ICameraInjectionSession.hal", + ], + interfaces: [ + "android.hardware.camera.common@1.0", + "android.hardware.camera.device@3.2", + "android.hardware.camera.device@3.3", + "android.hardware.camera.device@3.4", + "android.hardware.camera.device@3.5", + "android.hardware.camera.device@3.6", + "android.hardware.camera.metadata@3.2", + "android.hardware.camera.metadata@3.3", + "android.hardware.camera.metadata@3.4", + "android.hardware.camera.metadata@3.5", + "android.hardware.camera.metadata@3.6", + "android.hardware.graphics.common@1.0", + "android.hidl.base@1.0", + ], + gen_java: false, +} diff --git a/camera/device/3.7/ICameraDevice.hal b/camera/device/3.7/ICameraDevice.hal new file mode 100644 index 0000000000000000000000000000000000000000..9bc208373b5433ff80dd67449137e251b5716503 --- /dev/null +++ b/camera/device/3.7/ICameraDevice.hal @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.camera.device@3.7; + +import android.hardware.camera.common@1.0::Status; +import @3.6::ICameraDevice; + +/** + * Camera device interface + * + * Supports the android.hardware.Camera API, and the android.hardware.camera2 + * API at LIMITED or better hardware level. + * + * ICameraDevice.open() must return @3.2::ICameraDeviceSession, + * @3.5::ICameraDeviceSession, @3.6::ICameraDeviceSession, or + * @3.7::ICameraDeviceSession. + */ +interface ICameraDevice extends @3.6::ICameraDevice { + /** + * isStreamCombinationSupported_3_7: + * + * Identical to @3.5::ICameraDevice.isStreamCombinationSupported, except + * that it takes a @3.7::StreamConfiguration parameter, which could contain + * information about multi-resolution input and output streams. + * + */ + isStreamCombinationSupported_3_7(StreamConfiguration streams) + generates (Status status, bool queryStatus); +}; diff --git a/camera/device/3.7/ICameraDeviceSession.hal b/camera/device/3.7/ICameraDeviceSession.hal new file mode 100644 index 0000000000000000000000000000000000000000..fb5c7fa89edec1d825fe5f8c50e7d193a6b99205 --- /dev/null +++ b/camera/device/3.7/ICameraDeviceSession.hal @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.camera.device@3.7; + +import android.hardware.camera.common@1.0::Status; +import @3.2::BufferCache; +import @3.5::StreamConfiguration; +import @3.6::ICameraDeviceSession; +import @3.6::HalStreamConfiguration; + +/** + * 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.6::ICameraDeviceSession { + /** + * configureStreams_3_7: + * + * Identical to @3.6::ICameraDeviceSession.configureStreams_3_6, except that: + * + * - The requestedConfiguration allows the camera framework to configure + * stream groups. + * - For requested configurations of streams within the same group, the + * corresponding halConfiguration must have the same usage flags and + * maxBuffers. + * - Within a CaptureRequest, the application is guaranteed not to request + * more than one streams within the same stream group. When one of the + * stream within a stream group is requested, the camera HAL can either + * produce output on that stream, or any other stream within the same + * stream group. + * - The requestedConfiguration allows the camera framework to indicate that + * input images of different sizes may be submitted within capture + * requests. + * + * @return status Status code for the operation, one of: + * OK: + * On successful stream configuration. + * INTERNAL_ERROR: + * If there has been a fatal error and the device is no longer + * operational. Only close() can be called successfully by the + * framework after this error is returned. + * ILLEGAL_ARGUMENT: + * If the requested stream configuration is invalid. Some examples + * of invalid stream configurations include: + * - Including more than 1 INPUT stream + * - Not including any OUTPUT streams + * - Including streams with unsupported formats, or an unsupported + * size for that format. + * - Including too many output streams of a certain format. + * - Unsupported rotation configuration + * - Stream sizes/formats don't satisfy the + * StreamConfigurationMode requirements + * for non-NORMAL mode, or the requested operation_mode is not + * supported by the HAL. + * - Unsupported usage flag + * - Unsupported stream groupIds, or unsupported multi-resolution + * input stream. + * The camera service cannot filter out all possible illegal stream + * configurations, since some devices may support more simultaneous + * streams or larger stream resolutions than the minimum required + * for a given camera device hardware level. The HAL must return an + * ILLEGAL_ARGUMENT for any unsupported stream set, and then be + * ready to accept a future valid stream configuration in a later + * configureStreams call. + * @return halConfiguration The stream parameters desired by the HAL for + * each stream, including maximum buffers, the usage flags, and the + * override format. + */ + configureStreams_3_7(StreamConfiguration requestedConfiguration) + generates (Status status, @3.6::HalStreamConfiguration halConfiguration); + + /** + * processCaptureRequest_3_7: + * + * Identical to @3.4::ICameraDeviceSession.processCaptureRequest, except that: + * + * - The capture request can include width and height of the input buffer for + * a reprocessing request. + * + * @return status Status code for the operation, one of: + * OK: + * On a successful start to processing the capture request + * ILLEGAL_ARGUMENT: + * If the input is malformed (the settings are empty when not + * allowed, the physical camera settings are invalid, there are 0 + * output buffers, etc) and capture processing + * cannot start. Failures during request processing must be + * handled by calling ICameraDeviceCallback::notify(). In case of + * this error, the framework retains responsibility for the + * stream buffers' fences and the buffer handles; the HAL must not + * close the fences or return these buffers with + * ICameraDeviceCallback::processCaptureResult(). + * In case of multi-resolution input image, this error must be returned + * if the caller passes in a CaptureRequest with an invalid + * [inputWith, inputHeight]. + * INTERNAL_ERROR: + * If the camera device has encountered a serious error. After this + * error is returned, only the close() method can be successfully + * called by the framework. + * @return numRequestProcessed Number of requests successfully processed by + * camera HAL. When status is OK, this must be equal to the size of + * requests. When the call fails, this number is the number of requests + * that HAL processed successfully before HAL runs into an error. + * + */ + processCaptureRequest_3_7(vec requests, vec cachesToRemove) + generates (Status status, uint32_t numRequestProcessed); +}; diff --git a/camera/device/3.7/ICameraInjectionSession.hal b/camera/device/3.7/ICameraInjectionSession.hal new file mode 100644 index 0000000000000000000000000000000000000000..f5797c3b175b978e1e0bf9d7dfdb2540e884ca85 --- /dev/null +++ b/camera/device/3.7/ICameraInjectionSession.hal @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.camera.device@3.7; + +import android.hardware.camera.common@1.0::Status; +import @3.2::BufferCache; +import @3.2::CameraMetadata; +import @3.5::StreamConfiguration; +import @3.6::HalStreamConfiguration; +import @3.7::ICameraDeviceSession; + +/** + * Injection Camera device active session interface. + * + * When an external camera is injected to replace the internal camera session, the + * injection session will be established in camera framework, and then + * configureInjectionStreams() will be called to ask the external camera to + * configure itself to match the stream configuration of the internal camera. + * + * Camera framework is responsible to close the injection session once the client + * switch back to internal camera streaming. + * + * If the external camera cannot support the configuration ILLEGAL_ARGUMENT will + * be returned. + */ +interface ICameraInjectionSession extends @3.7::ICameraDeviceSession { + /** + * configureInjectionStreams: + * + * Identical to @3.7::ICameraDeviceSession.configureStreams_3_7, except that: + * + * @param requestedConfiguration + * The current stream configuration of the internal camera session and + * the injection camera must follow the configuration without overriding + * any part of it. + * @param characteristics + * The characteristics of internal camera contains a list of keys so that + * the stream continuity can be maintained after the external camera is + * injected. + * + * @return status Status code for the operation, one of: + * OK: + * On successful stream configuration. + * INTERNAL_ERROR: + * If there has been a fatal error and the device is no longer + * operational. Only close() can be called successfully by the + * framework after this error is returned. + * ILLEGAL_ARGUMENT: + * If the requested stream configuration is invalid. Some examples + * of invalid stream configurations include: + * - Not including any OUTPUT streams + * - Including streams with unsupported formats, or an unsupported + * size for that format. + * - Including too many output streams of a certain format. + * - Unsupported rotation configuration + * - Stream sizes/formats don't satisfy the + * StreamConfigurationMode requirements + * for non-NORMAL mode, or the requested operation_mode is not + * supported by the HAL. + * - Unsupported usage flag + * The camera service cannot filter out all possible illegal stream + * configurations, since some devices may support more simultaneous + * streams or larger stream resolutions than the minimum required + * for a given camera device hardware level. The HAL must return an + * ILLEGAL_ARGUMENT for any unsupported stream set, and then be + * ready to accept a future valid stream configuration in a later + * configureInjectionStreams call. + */ + configureInjectionStreams(StreamConfiguration requestedConfiguration, + CameraMetadata characteristics) generates (Status status); +}; diff --git a/camera/device/3.7/types.hal b/camera/device/3.7/types.hal new file mode 100644 index 0000000000000000000000000000000000000000..55aceb8fa4ac0b1280cc6b4e7b0a2bcd97947a8b --- /dev/null +++ b/camera/device/3.7/types.hal @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.camera.device@3.7; + +import @3.2::CameraMetadata; +import @3.2::StreamConfigurationMode; +import @3.4::CaptureRequest; +import @3.4::Stream; + +import android.hardware.camera.metadata@3.6::CameraMetadataEnumAndroidSensorPixelMode; + +/** + * Stream: + * + * A descriptor for a single camera input or output stream. A stream is defined + * by the framework by its buffer resolution and format, and additionally by the + * HAL with the gralloc usage flags and the maximum in-flight buffer count. + * + * This version extends the @3.4 Stream with the multi-resolution output surface + * group Id field. + */ +struct Stream { + /** + * The definition of Stream from the prior version. + */ + @3.4::Stream v3_4; + + /** + * The surface group id used for multi-resolution output streams. + * + * This works similar to the surfaceGroupId of OutputConfiguration in the + * public API, with the exception that this is for multi-resolution image + * reader and is used by the camera HAL to choose a target stream within + * the same group to which images are written. All streams in the same group + * will have the same image format, data space, and usage flag. + * + * The framework must only call processCaptureRequest on at most one of the + * streams within a surface group. Depending on current active physical + * camera backing the logical multi-camera, or the pixel mode the camera is + * running in, the HAL can choose to request and return a buffer from any + * stream within the same group. -1 means that this stream is an input + * stream, or is an output stream which doesn't belong to any group. + * + * Streams with the same non-negative group id must have the same format and + * usage flag. + */ + int32_t groupId; + + /** + * The sensor pixel modes used by this stream. This can assist the camera + * HAL in decision making about stream combination support. + * If this is empty, the HAL must assume that this stream will only be used + * with ANDROID_SENSOR_PIXEL_MODE set to ANDROID_SENSOR_PIXEL_MODE_DEFAULT. + */ + vec sensorPixelModesUsed; +}; + +/** + * StreamConfiguration: + * + * Identical to @3.5::StreamConfiguration, except that the streams + * vector contains @3.7::Stream. + */ +struct StreamConfiguration { + /** + * An array of camera stream pointers, defining the input/output + * configuration for the camera HAL device. + */ + vec streams; + + /** + * The definition of operation mode from prior version. + * + */ + @3.2::StreamConfigurationMode operationMode; + + /** + * The definition of session parameters from prior version. + */ + @3.2::CameraMetadata sessionParams; + + /** + * The definition of stream configuration counter from prior version. + */ + uint32_t streamConfigCounter; + + /** + * If an input stream is configured, whether the input stream is expected to + * receive variable resolution images. + * + * This flag can only be set to true if the camera device supports + * multi-resolution input streams by advertising input stream configurations in + * physicalCameraMultiResolutionStreamConfigurations in its physical cameras' + * characteristics. + * + * When this flag is set to true, the input stream's width and height can be + * any one of the supported multi-resolution input stream sizes. + */ + bool multiResolutionInputImage; +}; + +/** + * CaptureRequest: + * + * This version extends 3.4::CaptureRequest with the input buffer's width and + * height. + */ +struct CaptureRequest { + /** + * The definition of CaptureRequest from the prior version. + */ + @3.4::CaptureRequest v3_4; + + /** + * The width and height of the input buffer for this capture request. + * + * These fields will be [0, 0] if no input buffer exists in the capture + * request. + * + * If the stream configuration contains an input stream and has the + * multiResolutionInputImage flag set to true, the camera client may submit a + * reprocessing request with input buffer size different than the + * configured input stream size. In that case, the inputWith and inputHeight + * fields will be the actual size of the input image. + * + * If the stream configuration contains an input stream and the + * multiResolutionInputImage flag is false, the inputWidth and inputHeight must + * match the input stream size. + */ + uint32_t inputWidth; + uint32_t inputHeight; +}; diff --git a/camera/metadata/3.2/types.hal b/camera/metadata/3.2/types.hal index ad671d9db42f43d8eab4fbe022c98ce3a7b78e60..4b02830402906363ec57d2d2523193e6d9369458 100644 --- a/camera/metadata/3.2/types.hal +++ b/camera/metadata/3.2/types.hal @@ -686,7 +686,9 @@ enum CameraMetadataTag : uint32_t { /** android.jpeg.maxSize [static, int32, system] * *

Maximum size in bytes for the compressed - * JPEG buffer

+ * JPEG buffer, in default sensor pixel mode (see ANDROID_SENSOR_PIXEL_MODE)

+ * + * @see ANDROID_SENSOR_PIXEL_MODE */ ANDROID_JPEG_MAX_SIZE, diff --git a/camera/metadata/3.5/types.hal b/camera/metadata/3.5/types.hal index 99d61152ac533074530da0c316c23ed19d7e55e1..d32bc9196883529cf5faa1ee4b85af55d5c35783 100644 --- a/camera/metadata/3.5/types.hal +++ b/camera/metadata/3.5/types.hal @@ -73,7 +73,7 @@ enum CameraMetadataTag : @3.4::CameraMetadataTag { ANDROID_CONTROL_END_3_5, - /** android.scaler.availableRotateAndCropModes [static, byte[], hidden] + /** android.scaler.availableRotateAndCropModes [static, byte[], public] * *

List of rotate-and-crop modes for ANDROID_SCALER_ROTATE_AND_CROP that are supported by this camera device.

* @@ -81,7 +81,7 @@ enum CameraMetadataTag : @3.4::CameraMetadataTag { */ ANDROID_SCALER_AVAILABLE_ROTATE_AND_CROP_MODES = android.hardware.camera.metadata@3.4::CameraMetadataTag:ANDROID_SCALER_END_3_4, - /** android.scaler.rotateAndCrop [dynamic, enum, hidden] + /** android.scaler.rotateAndCrop [dynamic, enum, public] * *

Whether a rotation-and-crop operation is applied to processed * outputs from the camera.

diff --git a/camera/metadata/3.6/Android.bp b/camera/metadata/3.6/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..9e2b8a35e6af95096e10c4003dd0d8da8b1c545e --- /dev/null +++ b/camera/metadata/3.6/Android.bp @@ -0,0 +1,25 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +hidl_interface { + name: "android.hardware.camera.metadata@3.6", + root: "android.hardware", + srcs: [ + "types.hal", + ], + interfaces: [ + "android.hardware.camera.metadata@3.2", + "android.hardware.camera.metadata@3.3", + "android.hardware.camera.metadata@3.4", + "android.hardware.camera.metadata@3.5", + ], + gen_java: true, +} diff --git a/camera/metadata/3.6/types.hal b/camera/metadata/3.6/types.hal new file mode 100644 index 0000000000000000000000000000000000000000..185687c4df1d75839271bffc235b00afb5614d73 --- /dev/null +++ b/camera/metadata/3.6/types.hal @@ -0,0 +1,397 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Autogenerated from camera metadata definitions in + * /system/media/camera/docs/metadata_definitions.xml + * *** DO NOT EDIT BY HAND *** + */ + +package android.hardware.camera.metadata@3.6; + +import android.hardware.camera.metadata@3.2; +import android.hardware.camera.metadata@3.3; +import android.hardware.camera.metadata@3.4; +import android.hardware.camera.metadata@3.5; + +// No new metadata sections added in this revision + +/** + * Main enumeration for defining camera metadata tags added in this revision + * + *

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

+ */ +enum CameraMetadataTag : @3.5::CameraMetadataTag { + /** android.control.availableHighSpeedVideoConfigurationsMaximumResolution [static, int32[], hidden] + * + *

List of available high speed video size, fps range and max batch size configurations + * supported by the camera device, in the format of + * (width, height, fps_min, fps_max, batch_size_max), + * when ANDROID_SENSOR_PIXEL_MODE is set to + * CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION.

+ * + * @see ANDROID_SENSOR_PIXEL_MODE + */ + ANDROID_CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS_MAXIMUM_RESOLUTION = android.hardware.camera.metadata@3.5::CameraMetadataTag:ANDROID_CONTROL_END_3_5, + + ANDROID_CONTROL_END_3_6, + + /** android.lens.distortionMaximumResolution [static, float[], public] + * + *

The correction coefficients to correct for this camera device's + * radial and tangential lens distortion for a + * CaptureRequest with ANDROID_SENSOR_PIXEL_MODE set to + * CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION.

+ * + * @see ANDROID_SENSOR_PIXEL_MODE + */ + ANDROID_LENS_DISTORTION_MAXIMUM_RESOLUTION = android.hardware.camera.metadata@3.3::CameraMetadataTag:ANDROID_LENS_END_3_3, + + /** android.lens.intrinsicCalibrationMaximumResolution [static, float[], public] + * + *

The parameters for this camera device's intrinsic + * calibration when ANDROID_SENSOR_PIXEL_MODE is set to + * CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION.

+ * + * @see ANDROID_SENSOR_PIXEL_MODE + */ + ANDROID_LENS_INTRINSIC_CALIBRATION_MAXIMUM_RESOLUTION, + + ANDROID_LENS_END_3_6, + + /** android.scaler.defaultSecureImageSize [static, int32[], public] + * + *

Default YUV/PRIVATE size to use for requesting secure image buffers.

+ */ + ANDROID_SCALER_DEFAULT_SECURE_IMAGE_SIZE = android.hardware.camera.metadata@3.5::CameraMetadataTag:ANDROID_SCALER_END_3_5, + + /** android.scaler.physicalCameraMultiResolutionStreamConfigurations [static, enum[], ndk_public] + * + *

The available multi-resolution stream configurations that this + * physical camera device supports + * (i.e. format, width, height, output/input stream).

+ */ + ANDROID_SCALER_PHYSICAL_CAMERA_MULTI_RESOLUTION_STREAM_CONFIGURATIONS, + + /** android.scaler.availableStreamConfigurationsMaximumResolution [static, enum[], ndk_public] + * + *

The available stream configurations that this + * camera device supports (i.e. format, width, height, output/input stream) for a + * CaptureRequest with ANDROID_SENSOR_PIXEL_MODE set to + * CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION.

+ * + * @see ANDROID_SENSOR_PIXEL_MODE + */ + ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION, + + /** android.scaler.availableMinFrameDurationsMaximumResolution [static, int64[], ndk_public] + * + *

This lists the minimum frame duration for each + * format/size combination when the camera device is sent a CaptureRequest with + * ANDROID_SENSOR_PIXEL_MODE set to + * CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION.

+ * + * @see ANDROID_SENSOR_PIXEL_MODE + */ + ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION, + + /** android.scaler.availableStallDurationsMaximumResolution [static, int64[], ndk_public] + * + *

This lists the maximum stall duration for each + * output format/size combination when CaptureRequests are submitted with + * ANDROID_SENSOR_PIXEL_MODE set to + * CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION

+ * + * @see ANDROID_SENSOR_PIXEL_MODE + */ + ANDROID_SCALER_AVAILABLE_STALL_DURATIONS_MAXIMUM_RESOLUTION, + + /** android.scaler.availableInputOutputFormatsMapMaximumResolution [static, int32, hidden] + * + *

The mapping of image formats that are supported by this + * camera device for input streams, to their corresponding output formats, when + * ANDROID_SENSOR_PIXEL_MODE is set to + * CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION.

+ * + * @see ANDROID_SENSOR_PIXEL_MODE + */ + ANDROID_SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP_MAXIMUM_RESOLUTION, + + /** android.scaler.multiResolutionStreamSupported [static, enum, ndk_public] + * + *

Whether the camera device supports multi-resolution input or output streams

+ */ + ANDROID_SCALER_MULTI_RESOLUTION_STREAM_SUPPORTED, + + ANDROID_SCALER_END_3_6, + + /** android.sensor.opaqueRawSizeMaximumResolution [static, int32[], system] + * + *

Size in bytes for all the listed opaque RAW buffer sizes when + * ANDROID_SENSOR_PIXEL_MODE is set to + * CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION.

+ * + * @see ANDROID_SENSOR_PIXEL_MODE + */ + ANDROID_SENSOR_OPAQUE_RAW_SIZE_MAXIMUM_RESOLUTION = android.hardware.camera.metadata@3.2::CameraMetadataTag:ANDROID_SENSOR_END, + + /** android.sensor.pixelMode [dynamic, enum, public] + * + *

Switches sensor pixel mode between maximum resolution mode and default mode.

+ */ + ANDROID_SENSOR_PIXEL_MODE, + + /** android.sensor.rawBinningFactorUsed [dynamic, enum, public] + * + *

Whether RAW images requested have their bayer pattern as described by + * ANDROID_SENSOR_INFO_BINNING_FACTOR.

+ * + * @see ANDROID_SENSOR_INFO_BINNING_FACTOR + */ + ANDROID_SENSOR_RAW_BINNING_FACTOR_USED, + + ANDROID_SENSOR_END_3_6, + + /** android.sensor.info.activeArraySizeMaximumResolution [static, int32[], public] + * + *

The area of the image sensor which corresponds to active pixels after any geometric + * distortion correction has been applied, when the sensor runs in maximum resolution mode.

+ */ + ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION = android.hardware.camera.metadata@3.2::CameraMetadataTag:ANDROID_SENSOR_INFO_END, + + /** android.sensor.info.pixelArraySizeMaximumResolution [static, int32[], public] + * + *

Dimensions of the full pixel array, possibly + * including black calibration pixels, when the sensor runs in maximum resolution mode. + * Analogous to ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE, when ANDROID_SENSOR_PIXEL_MODE is + * set to + * CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION.

+ * + * @see ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE + * @see ANDROID_SENSOR_PIXEL_MODE + */ + ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE_MAXIMUM_RESOLUTION, + + /** android.sensor.info.preCorrectionActiveArraySizeMaximumResolution [static, int32[], public] + * + *

The area of the image sensor which corresponds to active pixels prior to the + * application of any geometric distortion correction, when the sensor runs in maximum + * resolution mode. This key must be used for crop / metering regions, only when + * ANDROID_SENSOR_PIXEL_MODE is set to + * CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION.

+ * + * @see ANDROID_SENSOR_PIXEL_MODE + */ + ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION, + + /** android.sensor.info.binningFactor [static, int32[], public] + * + *

Dimensions of the group of pixels which are under the same color filter. + * This specifies the width and height (pair of integers) of the group of pixels which fall + * under the same color filter for ULTRA_HIGH_RESOLUTION sensors.

+ */ + ANDROID_SENSOR_INFO_BINNING_FACTOR, + + ANDROID_SENSOR_INFO_END_3_6, + + /** android.depth.availableDepthStreamConfigurationsMaximumResolution [static, enum[], ndk_public] + * + *

The available depth dataspace stream + * configurations that this camera device supports + * (i.e. format, width, height, output/input stream) when a CaptureRequest is submitted with + * ANDROID_SENSOR_PIXEL_MODE set to + * CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION.

+ * + * @see ANDROID_SENSOR_PIXEL_MODE + */ + ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION = android.hardware.camera.metadata@3.4::CameraMetadataTag:ANDROID_DEPTH_END_3_4, + + /** android.depth.availableDepthMinFrameDurationsMaximumResolution [static, int64[], ndk_public] + * + *

This lists the minimum frame duration for each + * format/size combination for depth output formats when a CaptureRequest is submitted with + * ANDROID_SENSOR_PIXEL_MODE set to + * CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION.

+ * + * @see ANDROID_SENSOR_PIXEL_MODE + */ + ANDROID_DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION, + + /** android.depth.availableDepthStallDurationsMaximumResolution [static, int64[], ndk_public] + * + *

This lists the maximum stall duration for each + * output format/size combination for depth streams for CaptureRequests where + * ANDROID_SENSOR_PIXEL_MODE is set to + * CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION.

+ * + * @see ANDROID_SENSOR_PIXEL_MODE + */ + ANDROID_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS_MAXIMUM_RESOLUTION, + + /** android.depth.availableDynamicDepthStreamConfigurationsMaximumResolution [static, enum[], ndk_public] + * + *

The available dynamic depth dataspace stream + * configurations that this camera device supports (i.e. format, width, height, + * output/input stream) for CaptureRequests where ANDROID_SENSOR_PIXEL_MODE is set to + * CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION.

+ * + * @see ANDROID_SENSOR_PIXEL_MODE + */ + ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION, + + /** android.depth.availableDynamicDepthMinFrameDurationsMaximumResolution [static, int64[], ndk_public] + * + *

This lists the minimum frame duration for each + * format/size combination for dynamic depth output streams for CaptureRequests where + * ANDROID_SENSOR_PIXEL_MODE is set to + * CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION.

+ * + * @see ANDROID_SENSOR_PIXEL_MODE + */ + ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION, + + /** android.depth.availableDynamicDepthStallDurationsMaximumResolution [static, int64[], ndk_public] + * + *

This lists the maximum stall duration for each + * output format/size combination for dynamic depth streams for CaptureRequests where + * ANDROID_SENSOR_PIXEL_MODE is set to + * CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION.

+ * + * @see ANDROID_SENSOR_PIXEL_MODE + */ + ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS_MAXIMUM_RESOLUTION, + + ANDROID_DEPTH_END_3_6, + + /** android.heic.availableHeicStreamConfigurationsMaximumResolution [static, enum[], ndk_public] + * + *

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

+ */ + ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION = android.hardware.camera.metadata@3.4::CameraMetadataTag:ANDROID_HEIC_END_3_4, + + /** android.heic.availableHeicMinFrameDurationsMaximumResolution [static, int64[], ndk_public] + * + *

This lists the minimum frame duration for each + * format/size combination for HEIC output formats for CaptureRequests where + * ANDROID_SENSOR_PIXEL_MODE is set to + * CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION.

+ * + * @see ANDROID_SENSOR_PIXEL_MODE + */ + ANDROID_HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION, + + /** android.heic.availableHeicStallDurationsMaximumResolution [static, int64[], ndk_public] + * + *

This lists the maximum stall duration for each + * output format/size combination for HEIC streams for CaptureRequests where + * ANDROID_SENSOR_PIXEL_MODE is set to + * CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION.

+ * + * @see ANDROID_SENSOR_PIXEL_MODE + */ + ANDROID_HEIC_AVAILABLE_HEIC_STALL_DURATIONS_MAXIMUM_RESOLUTION, + + ANDROID_HEIC_END_3_6, + +}; + +/* + * Enumeration definitions for the various entries that need them + */ + +/** android.request.availableCapabilities enumeration values added since v3.5 + * @see ANDROID_REQUEST_AVAILABLE_CAPABILITIES + */ +enum CameraMetadataEnumAndroidRequestAvailableCapabilities : + @3.5::CameraMetadataEnumAndroidRequestAvailableCapabilities { + ANDROID_REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR, + ANDROID_REQUEST_AVAILABLE_CAPABILITIES_REMOSAIC_REPROCESSING, +}; + +/** android.scaler.physicalCameraMultiResolutionStreamConfigurations enumeration values + * @see ANDROID_SCALER_PHYSICAL_CAMERA_MULTI_RESOLUTION_STREAM_CONFIGURATIONS + */ +enum CameraMetadataEnumAndroidScalerPhysicalCameraMultiResolutionStreamConfigurations : uint32_t { + ANDROID_SCALER_PHYSICAL_CAMERA_MULTI_RESOLUTION_STREAM_CONFIGURATIONS_OUTPUT, + ANDROID_SCALER_PHYSICAL_CAMERA_MULTI_RESOLUTION_STREAM_CONFIGURATIONS_INPUT, +}; + +/** android.scaler.availableStreamConfigurationsMaximumResolution enumeration values + * @see ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION + */ +enum CameraMetadataEnumAndroidScalerAvailableStreamConfigurationsMaximumResolution : uint32_t { + ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION_OUTPUT, + ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION_INPUT, +}; + +/** android.scaler.multiResolutionStreamSupported enumeration values + * @see ANDROID_SCALER_MULTI_RESOLUTION_STREAM_SUPPORTED + */ +enum CameraMetadataEnumAndroidScalerMultiResolutionStreamSupported : uint32_t { + ANDROID_SCALER_MULTI_RESOLUTION_STREAM_SUPPORTED_FALSE, + ANDROID_SCALER_MULTI_RESOLUTION_STREAM_SUPPORTED_TRUE, +}; + +/** android.sensor.testPatternMode enumeration values added since v3.2 + * @see ANDROID_SENSOR_TEST_PATTERN_MODE + */ +enum CameraMetadataEnumAndroidSensorTestPatternMode : + @3.2::CameraMetadataEnumAndroidSensorTestPatternMode { + ANDROID_SENSOR_TEST_PATTERN_MODE_BLACK, +}; + +/** android.sensor.pixelMode enumeration values + * @see ANDROID_SENSOR_PIXEL_MODE + */ +enum CameraMetadataEnumAndroidSensorPixelMode : uint32_t { + ANDROID_SENSOR_PIXEL_MODE_DEFAULT, + ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION, +}; + +/** android.sensor.rawBinningFactorUsed enumeration values + * @see ANDROID_SENSOR_RAW_BINNING_FACTOR_USED + */ +enum CameraMetadataEnumAndroidSensorRawBinningFactorUsed : uint32_t { + ANDROID_SENSOR_RAW_BINNING_FACTOR_USED_TRUE, + ANDROID_SENSOR_RAW_BINNING_FACTOR_USED_FALSE, +}; + +/** android.depth.availableDepthStreamConfigurationsMaximumResolution enumeration values + * @see ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION + */ +enum CameraMetadataEnumAndroidDepthAvailableDepthStreamConfigurationsMaximumResolution : uint32_t { + ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION_OUTPUT, + ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION_INPUT, +}; + +/** android.depth.availableDynamicDepthStreamConfigurationsMaximumResolution enumeration values + * @see ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION + */ +enum CameraMetadataEnumAndroidDepthAvailableDynamicDepthStreamConfigurationsMaximumResolution : uint32_t { + ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION_OUTPUT, + ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION_INPUT, +}; + +/** android.heic.availableHeicStreamConfigurationsMaximumResolution enumeration values + * @see ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION + */ +enum CameraMetadataEnumAndroidHeicAvailableHeicStreamConfigurationsMaximumResolution : uint32_t { + ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION_OUTPUT, + ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION_INPUT, +}; diff --git a/camera/provider/2.4/vts/functional/Android.bp b/camera/provider/2.4/vts/functional/Android.bp index 691d77252e6a3255a127d146b14b60ceb9028ded..8886ee1e8c4db7a88d7aca83514af0a581ead878 100644 --- a/camera/provider/2.4/vts/functional/Android.bp +++ b/camera/provider/2.4/vts/functional/Android.bp @@ -48,10 +48,12 @@ cc_test { "android.hardware.camera.device@3.4", "android.hardware.camera.device@3.5", "android.hardware.camera.device@3.6", + "android.hardware.camera.device@3.7", "android.hardware.camera.metadata@3.4", "android.hardware.camera.provider@2.4", "android.hardware.camera.provider@2.5", "android.hardware.camera.provider@2.6", + "android.hardware.camera.provider@2.7", "android.hardware.graphics.common@1.0", "android.hidl.allocator@1.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 7e6b5ad9fe2fdd31df57037ad5917f196e2e02e5..49e00f4f4bb1e8393aed7b505de943ee452ebfaa 100644 --- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp +++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp @@ -40,11 +40,15 @@ #include #include #include +#include +#include +#include #include #include #include #include #include +#include #include #include #include @@ -122,6 +126,7 @@ using ::android::hardware::camera::device::V3_4::PhysicalCameraMetadata; using ::android::hardware::camera::metadata::V3_4:: CameraMetadataEnumAndroidSensorInfoColorFilterArrangement; using ::android::hardware::camera::metadata::V3_4::CameraMetadataTag; +using ::android::hardware::camera::metadata::V3_6::CameraMetadataEnumAndroidSensorPixelMode; using ::android::hardware::camera::provider::V2_4::ICameraProvider; using ::android::hardware::camera::provider::V2_4::ICameraProviderCallback; using ::android::hardware::camera::provider::V2_6::CameraIdAndStreamCombination; @@ -189,12 +194,14 @@ enum SystemCameraKind { namespace { // "device@/legacy/" const char *kDeviceNameRE = "device@([0-9]+\\.[0-9]+)/%s/(.+)"; + const int CAMERA_DEVICE_API_VERSION_3_7 = 0x307; const int CAMERA_DEVICE_API_VERSION_3_6 = 0x306; const int CAMERA_DEVICE_API_VERSION_3_5 = 0x305; const int CAMERA_DEVICE_API_VERSION_3_4 = 0x304; const int CAMERA_DEVICE_API_VERSION_3_3 = 0x303; const int CAMERA_DEVICE_API_VERSION_3_2 = 0x302; const int CAMERA_DEVICE_API_VERSION_1_0 = 0x100; + const char *kHAL3_7 = "3.7"; const char *kHAL3_6 = "3.6"; const char *kHAL3_5 = "3.5"; const char *kHAL3_4 = "3.4"; @@ -223,15 +230,17 @@ namespace { return false; } - int getCameraDeviceVersion(const hidl_string& deviceName, - const hidl_string &providerType) { + int getCameraDeviceVersionAndId(const hidl_string& deviceName, + const hidl_string &providerType, std::string* id) { std::string version; - bool match = matchDeviceName(deviceName, providerType, &version, nullptr); + bool match = matchDeviceName(deviceName, providerType, &version, id); if (!match) { return -1; } - if (version.compare(kHAL3_6) == 0) { + if (version.compare(kHAL3_7) == 0) { + return CAMERA_DEVICE_API_VERSION_3_7; + } else if (version.compare(kHAL3_6) == 0) { return CAMERA_DEVICE_API_VERSION_3_6; } else if (version.compare(kHAL3_5) == 0) { return CAMERA_DEVICE_API_VERSION_3_5; @@ -247,6 +256,11 @@ namespace { return 0; } + int getCameraDeviceVersion(const hidl_string& deviceName, + const hidl_string &providerType) { + return getCameraDeviceVersionAndId(deviceName, providerType, nullptr); + } + bool parseProviderName(const std::string& name, std::string *type /*out*/, uint32_t *id /*out*/) { if (!type || !id) { @@ -570,7 +584,7 @@ public: uint32_t id; ASSERT_TRUE(parseProviderName(service_name, &mProviderType, &id)); - castProvider(mProvider, &mProvider2_5, &mProvider2_6); + castProvider(mProvider, &mProvider2_5, &mProvider2_6, &mProvider2_7); notifyDeviceState(provider::V2_5::DeviceState::NORMAL); } virtual void TearDown() override {} @@ -751,19 +765,27 @@ public: ::android::sp *device = nullptr/*out*/); void castProvider(const sp& provider, sp* provider2_5 /*out*/, - sp* provider2_6 /*out*/); + sp* provider2_6 /*out*/, + sp* provider2_7 /*out*/); void castSession(const sp &session, int32_t deviceVersion, sp *session3_3 /*out*/, sp *session3_4 /*out*/, sp *session3_5 /*out*/, - sp *session3_6 /*out*/); - void castDevice(const sp &device, int32_t deviceVersion, - sp *device3_5/*out*/); - void createStreamConfiguration(const ::android::hardware::hidl_vec& streams3_2, + sp *session3_6 /*out*/, + sp *session3_7 /*out*/); + void castInjectionSession( + const sp& session, + sp* injectionSession3_7 /*out*/); + void castDevice(const sp& device, int32_t deviceVersion, + sp* device3_5 /*out*/, + sp* device3_7 /*out*/); + void createStreamConfiguration( + const ::android::hardware::hidl_vec& streams3_2, StreamConfigurationMode configMode, - ::android::hardware::camera::device::V3_2::StreamConfiguration *config3_2, - ::android::hardware::camera::device::V3_4::StreamConfiguration *config3_4, - ::android::hardware::camera::device::V3_5::StreamConfiguration *config3_5, + ::android::hardware::camera::device::V3_2::StreamConfiguration* config3_2, + ::android::hardware::camera::device::V3_4::StreamConfiguration* config3_4, + ::android::hardware::camera::device::V3_5::StreamConfiguration* config3_5, + ::android::hardware::camera::device::V3_7::StreamConfiguration* config3_7, uint32_t jpegBufferSize = 0); void configureOfflineStillStream(const std::string &name, int32_t deviceVersion, @@ -777,6 +799,16 @@ public: sp *outCb /*out*/, uint32_t *jpegBufferSize /*out*/, bool *useHalBufManager /*out*/); + void configureStreams3_7(const std::string& name, int32_t deviceVersion, + sp provider, PixelFormat format, + sp* session3_7 /*out*/, + V3_2::Stream* previewStream /*out*/, + device::V3_6::HalStreamConfiguration* halStreamConfig /*out*/, + bool* supportsPartialResults /*out*/, + uint32_t* partialResultCount /*out*/, bool* useHalBufManager /*out*/, + sp* outCb /*out*/, uint32_t streamConfigCounter, + bool maxResolution); + void configurePreviewStreams3_4(const std::string &name, int32_t deviceVersion, sp provider, const AvailableStream *previewThreshold, @@ -813,7 +845,8 @@ public: uint32_t* partialResultCount /*out*/, bool* useHalBufManager /*out*/, sp* cb /*out*/, uint32_t streamConfigCounter = 0); - void verifyLogicalCameraMetadata(const std::string& cameraName, + void verifyLogicalOrUltraHighResCameraMetadata( + const std::string& cameraName, const ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice>& device, const CameraMetadata& chars, int deviceVersion, const hidl_vec& deviceNames); @@ -824,8 +857,11 @@ public: void verifyMonochromeCharacteristics(const CameraMetadata& chars, int deviceVersion); void verifyMonochromeCameraResult( const ::android::hardware::camera::common::V1_0::helper::CameraMetadata& metadata); - void verifyStreamCombination(sp cameraDevice3_5, - const ::android::hardware::camera::device::V3_4::StreamConfiguration &config3_4, + void verifyStreamCombination( + sp cameraDevice3_7, + const ::android::hardware::camera::device::V3_7::StreamConfiguration& config3_7, + sp cameraDevice3_5, + const ::android::hardware::camera::device::V3_4::StreamConfiguration& config3_4, bool expectedStatus, bool expectStreamCombQuery); void verifyLogicalCameraResult(const camera_metadata_t* staticMetadata, const ::android::hardware::camera::common::V1_0::helper::CameraMetadata& resultMetadata); @@ -838,6 +874,10 @@ public: hidl_vec streamIds, sp cb, uint32_t streamConfigCounter = 0); + void verifyBuffersReturned(sp session, + hidl_vec streamIds, sp cb, + uint32_t streamConfigCounter = 0); + void verifySessionReconfigurationQuery(sp session3_5, camera_metadata* oldSessionParams, camera_metadata* newSessionParams); @@ -845,12 +885,15 @@ public: static bool isDepthOnly(const camera_metadata_t* staticMeta); - static Status getAvailableOutputStreams(const camera_metadata_t *staticMeta, - std::vector &outputStreams, - const AvailableStream *threshold = nullptr); + static bool isUltraHighResolution(const camera_metadata_t* staticMeta); + + static Status getAvailableOutputStreams(const camera_metadata_t* staticMeta, + std::vector& outputStreams, + const AvailableStream* threshold = nullptr, + bool maxResolution = false); static Status getMaxOutputSizeForFormat(const camera_metadata_t* staticMeta, PixelFormat format, - Size* size); + Size* size, bool maxResolution = false); static Status getMandatoryConcurrentStreams(const camera_metadata_t* staticMeta, std::vector* outputStreams); @@ -887,6 +930,12 @@ public: static Status isMonochromeCamera(const camera_metadata_t *staticMeta); static Status getSystemCameraKind(const camera_metadata_t* staticMeta, SystemCameraKind* systemCameraKind); + static void getMultiResolutionStreamConfigurations( + camera_metadata_ro_entry* multiResStreamConfigs, + camera_metadata_ro_entry* streamConfigs, + camera_metadata_ro_entry* maxResolutionStreamConfigs, + const camera_metadata_t* staticMetadata); + static bool isColorCamera(const camera_metadata_t *metadata); static V3_2::DataspaceFlags getDataspace(PixelFormat format); @@ -958,7 +1007,8 @@ protected: frameNumber(0), partialResultCount(0), errorStreamId(-1), - hasInputBuffer(false) {} + hasInputBuffer(false), + collectedResult(1, 10) {} InFlightRequest(ssize_t numBuffers, bool hasInput, bool partialResults, uint32_t partialCount, @@ -974,7 +1024,8 @@ protected: frameNumber(0), partialResultCount(0), errorStreamId(-1), - hasInputBuffer(hasInput) {} + hasInputBuffer(hasInput), + collectedResult(1, 10) {} InFlightRequest(ssize_t numBuffers, bool hasInput, bool partialResults, uint32_t partialCount, @@ -992,6 +1043,7 @@ protected: partialResultCount(0), errorStreamId(-1), hasInputBuffer(hasInput), + collectedResult(1, 10), expectedPhysicalResults(extraPhysicalResult) {} }; @@ -1019,6 +1071,7 @@ protected: sp mProvider; sp<::android::hardware::camera::provider::V2_5::ICameraProvider> mProvider2_5; sp<::android::hardware::camera::provider::V2_6::ICameraProvider> mProvider2_6; + sp<::android::hardware::camera::provider::V2_7::ICameraProvider> mProvider2_7; // Camera provider type. std::string mProviderType; @@ -1267,9 +1320,27 @@ bool CameraHidlTest::DeviceCb::processCaptureResultLocked(const CaptureResult& r ADD_FAILURE(); return notify; } - request->collectedResult.append( - reinterpret_cast( - resultMetadata.data())); + + // Verify no duplicate tags between partial results + const camera_metadata_t* partialMetadata = + reinterpret_cast(resultMetadata.data()); + const camera_metadata_t* collectedMetadata = request->collectedResult.getAndLock(); + camera_metadata_ro_entry_t searchEntry, foundEntry; + for (size_t i = 0; i < get_camera_metadata_entry_count(partialMetadata); i++) { + if (0 != get_camera_metadata_ro_entry(partialMetadata, i, &searchEntry)) { + ADD_FAILURE(); + request->collectedResult.unlock(collectedMetadata); + return notify; + } + if (-ENOENT != + find_camera_metadata_ro_entry(collectedMetadata, searchEntry.tag, &foundEntry)) { + ADD_FAILURE(); + request->collectedResult.unlock(collectedMetadata); + return notify; + } + } + request->collectedResult.unlock(collectedMetadata); + request->collectedResult.append(partialMetadata); isPartialResult = (results.partialResult < request->numPartialResults); @@ -1865,6 +1936,7 @@ TEST_P(CameraHidlTest, getCameraDeviceInterface) { for (const auto& name : cameraDeviceNames) { int deviceVersion = getCameraDeviceVersion(name, mProviderType); switch (deviceVersion) { + case CAMERA_DEVICE_API_VERSION_3_7: case CAMERA_DEVICE_API_VERSION_3_6: case CAMERA_DEVICE_API_VERSION_3_5: case CAMERA_DEVICE_API_VERSION_3_4: @@ -1908,6 +1980,7 @@ TEST_P(CameraHidlTest, getResourceCost) { for (const auto& name : cameraDeviceNames) { int deviceVersion = getCameraDeviceVersion(name, mProviderType); switch (deviceVersion) { + case CAMERA_DEVICE_API_VERSION_3_7: case CAMERA_DEVICE_API_VERSION_3_6: case CAMERA_DEVICE_API_VERSION_3_5: case CAMERA_DEVICE_API_VERSION_3_4: @@ -2648,6 +2721,7 @@ TEST_P(CameraHidlTest, systemCameraTest) { for (const auto& name : cameraDeviceNames) { int deviceVersion = getCameraDeviceVersion(name, mProviderType); switch (deviceVersion) { + case CAMERA_DEVICE_API_VERSION_3_7: case CAMERA_DEVICE_API_VERSION_3_6: case CAMERA_DEVICE_API_VERSION_3_5: case CAMERA_DEVICE_API_VERSION_3_4: @@ -2734,6 +2808,7 @@ TEST_P(CameraHidlTest, getCameraCharacteristics) { for (const auto& name : cameraDeviceNames) { int deviceVersion = getCameraDeviceVersion(name, mProviderType); switch (deviceVersion) { + case CAMERA_DEVICE_API_VERSION_3_7: case CAMERA_DEVICE_API_VERSION_3_6: case CAMERA_DEVICE_API_VERSION_3_5: case CAMERA_DEVICE_API_VERSION_3_4: @@ -2755,8 +2830,8 @@ TEST_P(CameraHidlTest, getCameraCharacteristics) { verifyCameraCharacteristics(status, chars); verifyMonochromeCharacteristics(chars, deviceVersion); verifyRecommendedConfigs(chars); - verifyLogicalCameraMetadata(name, device3_x, chars, deviceVersion, - cameraDeviceNames); + verifyLogicalOrUltraHighResCameraMetadata(name, device3_x, chars, deviceVersion, + cameraDeviceNames); }); ASSERT_TRUE(ret.isOk()); @@ -2814,6 +2889,7 @@ TEST_P(CameraHidlTest, setTorchMode) { for (const auto& name : cameraDeviceNames) { int deviceVersion = getCameraDeviceVersion(name, mProviderType); switch (deviceVersion) { + case CAMERA_DEVICE_API_VERSION_3_7: case CAMERA_DEVICE_API_VERSION_3_6: case CAMERA_DEVICE_API_VERSION_3_5: case CAMERA_DEVICE_API_VERSION_3_4: @@ -2941,6 +3017,7 @@ TEST_P(CameraHidlTest, dumpState) { for (const auto& name : cameraDeviceNames) { int deviceVersion = getCameraDeviceVersion(name, mProviderType); switch (deviceVersion) { + case CAMERA_DEVICE_API_VERSION_3_7: case CAMERA_DEVICE_API_VERSION_3_6: case CAMERA_DEVICE_API_VERSION_3_5: case CAMERA_DEVICE_API_VERSION_3_4: @@ -3007,6 +3084,7 @@ TEST_P(CameraHidlTest, openClose) { for (const auto& name : cameraDeviceNames) { int deviceVersion = getCameraDeviceVersion(name, mProviderType); switch (deviceVersion) { + case CAMERA_DEVICE_API_VERSION_3_7: case CAMERA_DEVICE_API_VERSION_3_6: case CAMERA_DEVICE_API_VERSION_3_5: case CAMERA_DEVICE_API_VERSION_3_4: @@ -3038,9 +3116,13 @@ TEST_P(CameraHidlTest, openClose) { sp sessionV3_4; sp sessionV3_5; sp sessionV3_6; + sp sessionV3_7; castSession(session, deviceVersion, &sessionV3_3, - &sessionV3_4, &sessionV3_5, &sessionV3_6); - if (deviceVersion == CAMERA_DEVICE_API_VERSION_3_6) { + &sessionV3_4, &sessionV3_5, &sessionV3_6, + &sessionV3_7); + if (deviceVersion == CAMERA_DEVICE_API_VERSION_3_7) { + ASSERT_TRUE(sessionV3_7.get() != nullptr); + } else if (deviceVersion == CAMERA_DEVICE_API_VERSION_3_6) { ASSERT_TRUE(sessionV3_6.get() != nullptr); } else if (deviceVersion == CAMERA_DEVICE_API_VERSION_3_5) { ASSERT_TRUE(sessionV3_5.get() != nullptr); @@ -3104,6 +3186,7 @@ TEST_P(CameraHidlTest, constructDefaultRequestSettings) { for (const auto& name : cameraDeviceNames) { int deviceVersion = getCameraDeviceVersion(name, mProviderType); switch (deviceVersion) { + case CAMERA_DEVICE_API_VERSION_3_7: case CAMERA_DEVICE_API_VERSION_3_6: case CAMERA_DEVICE_API_VERSION_3_5: case CAMERA_DEVICE_API_VERSION_3_4: @@ -3203,12 +3286,15 @@ TEST_P(CameraHidlTest, configureStreamsAvailableOutputs) { sp session3_4; sp session3_5; sp session3_6; + sp session3_7; sp cameraDevice; sp cameraDevice3_5; + sp cameraDevice3_7; openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/, &cameraDevice /*out*/); - castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5, &session3_6); - castDevice(cameraDevice, deviceVersion, &cameraDevice3_5); + castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5, + &session3_6, &session3_7); + castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7); outputStreams.clear(); ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, outputStreams)); @@ -3232,15 +3318,29 @@ TEST_P(CameraHidlTest, configureStreamsAvailableOutputs) { dataspaceFlag, StreamRotation::ROTATION_0}; ::android::hardware::hidl_vec streams3_2 = {stream3_2}; + ::android::hardware::camera::device::V3_7::StreamConfiguration config3_7; ::android::hardware::camera::device::V3_5::StreamConfiguration config3_5; ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4; ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2; - createStreamConfiguration(streams3_2, StreamConfigurationMode::NORMAL_MODE, - &config3_2, &config3_4, &config3_5, jpegBufferSize); + createStreamConfiguration(streams3_2, StreamConfigurationMode::NORMAL_MODE, &config3_2, + &config3_4, &config3_5, &config3_7, jpegBufferSize); + if (session3_5 != nullptr) { bool expectStreamCombQuery = (isLogicalMultiCamera(staticMeta) == Status::OK); - verifyStreamCombination(cameraDevice3_5, config3_4, - /*expectedStatus*/ true, expectStreamCombQuery); + verifyStreamCombination(cameraDevice3_7, config3_7, cameraDevice3_5, config3_4, + /*expectedStatus*/ true, expectStreamCombQuery); + } + + if (session3_7 != nullptr) { + config3_7.streamConfigCounter = streamConfigCounter++; + ret = session3_7->configureStreams_3_7( + config3_7, + [streamId](Status s, device::V3_6::HalStreamConfiguration halConfig) { + ASSERT_EQ(Status::OK, s); + ASSERT_EQ(1u, halConfig.streams.size()); + ASSERT_EQ(halConfig.streams[0].v3_4.v3_3.v3_2.id, streamId); + }); + } else if (session3_5 != nullptr) { config3_5.streamConfigCounter = streamConfigCounter++; ret = session3_5->configureStreams_3_5(config3_5, [streamId](Status s, device::V3_4::HalStreamConfiguration halConfig) { @@ -3289,8 +3389,11 @@ TEST_P(CameraHidlTest, configureConcurrentStreamsAvailableOutputs) { sp session3_4; sp session3_5; sp session3_6; + sp session3_7; sp cameraDevice; sp cameraDevice3_5; + sp cameraDevice3_7; + ::android::hardware::camera::device::V3_7::StreamConfiguration config3_7; ::android::hardware::camera::device::V3_5::StreamConfiguration config3_5; ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4; ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2; @@ -3326,8 +3429,8 @@ TEST_P(CameraHidlTest, configureConcurrentStreamsAvailableOutputs) { openEmptyDeviceSession(name, mProvider2_6, &cti.session /*out*/, &cti.staticMeta /*out*/, &cti.cameraDevice /*out*/); castSession(cti.session, deviceVersion, &cti.session3_3, &cti.session3_4, - &cti.session3_5, &cti.session3_6); - castDevice(cti.cameraDevice, deviceVersion, &cti.cameraDevice3_5); + &cti.session3_5, &cti.session3_6, &cti.session3_7); + castDevice(cti.cameraDevice, deviceVersion, &cti.cameraDevice3_5, &cti.cameraDevice3_7); outputStreams.clear(); ASSERT_EQ(Status::OK, getMandatoryConcurrentStreams(cti.staticMeta, &outputStreams)); @@ -3359,7 +3462,7 @@ TEST_P(CameraHidlTest, configureConcurrentStreamsAvailableOutputs) { // Add the created stream configs to cameraIdsAndStreamCombinations createStreamConfiguration(streams3_2, StreamConfigurationMode::NORMAL_MODE, &cti.config3_2, &cti.config3_4, &cti.config3_5, - jpegBufferSize); + &cti.config3_7, jpegBufferSize); cti.config3_5.streamConfigCounter = outputStreams.size(); CameraIdAndStreamCombination cameraIdAndStreamCombination; @@ -3382,8 +3485,19 @@ TEST_P(CameraHidlTest, configureConcurrentStreamsAvailableOutputs) { for (const auto& cti : cameraTestInfos) { if (cti.session3_5 != nullptr) { bool expectStreamCombQuery = (isLogicalMultiCamera(cti.staticMeta) == Status::OK); - verifyStreamCombination(cti.cameraDevice3_5, cti.config3_4, + verifyStreamCombination(cti.cameraDevice3_7, cti.config3_7, cti.cameraDevice3_5, + cti.config3_4, /*expectedStatus*/ true, expectStreamCombQuery); + } + + if (cti.session3_7 != nullptr) { + ret = cti.session3_7->configureStreams_3_7( + cti.config3_7, + [&cti](Status s, device::V3_6::HalStreamConfiguration halConfig) { + ASSERT_EQ(Status::OK, s); + ASSERT_EQ(cti.config3_7.streams.size(), halConfig.streams.size()); + }); + } else if (cti.session3_5 != nullptr) { ret = cti.session3_5->configureStreams_3_5( cti.config3_5, [&cti](Status s, device::V3_4::HalStreamConfiguration halConfig) { @@ -3444,12 +3558,15 @@ TEST_P(CameraHidlTest, configureStreamsInvalidOutputs) { sp session3_4; sp session3_5; sp session3_6; + sp session3_7; sp cameraDevice; sp cameraDevice3_5; + sp cameraDevice3_7; openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/, &cameraDevice /*out*/); - castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5, &session3_6); - castDevice(cameraDevice, deviceVersion, &cameraDevice3_5); + castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5, + &session3_6, &session3_7); + castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7); outputStreams.clear(); ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, outputStreams)); @@ -3470,14 +3587,26 @@ TEST_P(CameraHidlTest, configureStreamsInvalidOutputs) { StreamRotation::ROTATION_0}; uint32_t streamConfigCounter = 0; ::android::hardware::hidl_vec streams = {stream3_2}; + ::android::hardware::camera::device::V3_7::StreamConfiguration config3_7; ::android::hardware::camera::device::V3_5::StreamConfiguration config3_5; ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4; ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2; - createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, - &config3_2, &config3_4, &config3_5, jpegBufferSize); + createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config3_2, + &config3_4, &config3_5, &config3_7, jpegBufferSize); + if (session3_5 != nullptr) { - verifyStreamCombination(cameraDevice3_5, config3_4, /*expectedStatus*/ false, - /*expectStreamCombQuery*/false); + verifyStreamCombination(cameraDevice3_7, config3_7, cameraDevice3_5, config3_4, + /*expectedStatus*/ false, /*expectStreamCombQuery*/ false); + } + + if (session3_7 != nullptr) { + config3_7.streamConfigCounter = streamConfigCounter++; + ret = session3_7->configureStreams_3_7( + config3_7, [](Status s, device::V3_6::HalStreamConfiguration) { + ASSERT_TRUE((Status::ILLEGAL_ARGUMENT == s) || + (Status::INTERNAL_ERROR == s)); + }); + } else if (session3_5 != nullptr) { config3_5.streamConfigCounter = streamConfigCounter++; ret = session3_5->configureStreams_3_5(config3_5, [](Status s, device::V3_4::HalStreamConfiguration) { @@ -3490,7 +3619,7 @@ TEST_P(CameraHidlTest, configureStreamsInvalidOutputs) { ASSERT_TRUE((Status::ILLEGAL_ARGUMENT == s) || (Status::INTERNAL_ERROR == s)); }); - } else if(session3_3 != nullptr) { + } else if (session3_3 != nullptr) { ret = session3_3->configureStreams_3_3(config3_2, [](Status s, device::V3_3::HalStreamConfiguration) { ASSERT_TRUE((Status::ILLEGAL_ARGUMENT == s) || @@ -3514,8 +3643,8 @@ TEST_P(CameraHidlTest, configureStreamsInvalidOutputs) { 0, StreamRotation::ROTATION_0}; streams[0] = stream3_2; - createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, - &config3_2, &config3_4, &config3_5, jpegBufferSize); + createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config3_2, + &config3_4, &config3_5, &config3_7, jpegBufferSize); if (session3_5 != nullptr) { config3_5.streamConfigCounter = streamConfigCounter++; ret = session3_5->configureStreams_3_5(config3_5, [](Status s, @@ -3550,8 +3679,8 @@ TEST_P(CameraHidlTest, configureStreamsInvalidOutputs) { 0, StreamRotation::ROTATION_0}; streams[0] = stream3_2; - createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, - &config3_2, &config3_4, &config3_5, jpegBufferSize); + createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config3_2, + &config3_4, &config3_5, &config3_7, jpegBufferSize); if (session3_5 != nullptr) { config3_5.streamConfigCounter = streamConfigCounter++; ret = session3_5->configureStreams_3_5(config3_5, @@ -3585,8 +3714,8 @@ TEST_P(CameraHidlTest, configureStreamsInvalidOutputs) { 0, static_cast(UINT32_MAX)}; streams[0] = stream3_2; - createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, - &config3_2, &config3_4, &config3_5, jpegBufferSize); + createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config3_2, + &config3_4, &config3_5, &config3_7, jpegBufferSize); if (session3_5 != nullptr) { config3_5.streamConfigCounter = streamConfigCounter++; ret = session3_5->configureStreams_3_5(config3_5, @@ -3642,12 +3771,15 @@ TEST_P(CameraHidlTest, configureStreamsZSLInputOutputs) { sp session3_4; sp session3_5; sp session3_6; + sp session3_7; sp cameraDevice; sp cameraDevice3_5; + sp cameraDevice3_7; openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/, &cameraDevice /*out*/); - castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5, &session3_6); - castDevice(cameraDevice, deviceVersion, &cameraDevice3_5); + castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5, + &session3_6, &session3_7); + castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7); Status rc = isZSLModeAvailable(staticMeta); if (Status::METHOD_NOT_SUPPORTED == rc) { @@ -3732,14 +3864,27 @@ TEST_P(CameraHidlTest, configureStreamsZSLInputOutputs) { ::android::hardware::hidl_vec streams = {inputStream, zslStream, outputStream}; + ::android::hardware::camera::device::V3_7::StreamConfiguration config3_7; ::android::hardware::camera::device::V3_5::StreamConfiguration config3_5; ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4; ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2; - createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, - &config3_2, &config3_4, &config3_5, jpegBufferSize); + createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config3_2, + &config3_4, &config3_5, &config3_7, jpegBufferSize); if (session3_5 != nullptr) { - verifyStreamCombination(cameraDevice3_5, config3_4, - /*expectedStatus*/ true, /*expectStreamCombQuery*/ false); + verifyStreamCombination(cameraDevice3_7, config3_7, cameraDevice3_5, config3_4, + /*expectedStatus*/ true, + /*expectStreamCombQuery*/ false); + } + + if (session3_7 != nullptr) { + config3_7.streamConfigCounter = streamConfigCounter++; + ret = session3_7->configureStreams_3_7( + config3_7, + [](Status s, device::V3_6::HalStreamConfiguration halConfig) { + ASSERT_EQ(Status::OK, s); + ASSERT_EQ(3u, halConfig.streams.size()); + }); + } else if (session3_5 != nullptr) { config3_5.streamConfigCounter = streamConfigCounter++; ret = session3_5->configureStreams_3_5(config3_5, [](Status s, device::V3_4::HalStreamConfiguration halConfig) { @@ -3810,8 +3955,10 @@ TEST_P(CameraHidlTest, configureStreamsWithSessionParameters) { sp session3_4; sp session3_5; sp session3_6; + sp session3_7; openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMetaBuffer /*out*/); - castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5, &session3_6); + castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5, + &session3_6, &session3_7); if (deviceVersion == CAMERA_DEVICE_API_VERSION_3_4) { ASSERT_NE(session3_4, nullptr); } else { @@ -3860,6 +4007,7 @@ TEST_P(CameraHidlTest, configureStreamsWithSessionParameters) { ::android::hardware::hidl_vec streams = {previewStream}; ::android::hardware::camera::device::V3_4::StreamConfiguration config; ::android::hardware::camera::device::V3_5::StreamConfiguration config3_5; + ::android::hardware::camera::device::V3_7::StreamConfiguration config3_7; config.streams = streams; config.operationMode = StreamConfigurationMode::NORMAL_MODE; modifiedSessionParams = sessionParams; @@ -3868,6 +4016,13 @@ TEST_P(CameraHidlTest, configureStreamsWithSessionParameters) { get_camera_metadata_size(sessionParamsBuffer)); config3_5.v3_4 = config; config3_5.streamConfigCounter = 0; + config3_7.streams = {{previewStream, -1, {ANDROID_SENSOR_PIXEL_MODE_DEFAULT}}}; + config3_7.operationMode = config.operationMode; + config3_7.sessionParams.setToExternal(reinterpret_cast(sessionParamsBuffer), + get_camera_metadata_size(sessionParamsBuffer)); + config3_7.streamConfigCounter = 0; + config3_7.multiResolutionInputImage = false; + if (session3_5 != nullptr) { bool newSessionParamsAvailable = false; for (const auto& it : availableSessionKeys) { @@ -3883,7 +4038,15 @@ TEST_P(CameraHidlTest, configureStreamsWithSessionParameters) { modifiedSessionParamsBuffer); modifiedSessionParams.acquire(modifiedSessionParamsBuffer); } + } + if (session3_7 != nullptr) { + ret = session3_7->configureStreams_3_7( + config3_7, [](Status s, device::V3_6::HalStreamConfiguration halConfig) { + ASSERT_EQ(Status::OK, s); + ASSERT_EQ(1u, halConfig.streams.size()); + }); + } else if (session3_5 != nullptr) { ret = session3_5->configureStreams_3_5(config3_5, [](Status s, device::V3_4::HalStreamConfiguration halConfig) { ASSERT_EQ(Status::OK, s); @@ -3933,12 +4096,15 @@ TEST_P(CameraHidlTest, configureStreamsPreviewStillOutputs) { sp session3_4; sp session3_5; sp session3_6; + sp session3_7; sp cameraDevice; sp cameraDevice3_5; + sp cameraDevice3_7; openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/, &cameraDevice /*out*/); - castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5, &session3_6); - castDevice(cameraDevice, deviceVersion, &cameraDevice3_5); + castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5, + &session3_6, &session3_7); + castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7); // Check if camera support depth only if (isDepthOnly(staticMeta)) { @@ -3985,14 +4151,27 @@ TEST_P(CameraHidlTest, configureStreamsPreviewStillOutputs) { StreamRotation::ROTATION_0}; ::android::hardware::hidl_vec streams = {previewStream, blobStream}; + ::android::hardware::camera::device::V3_7::StreamConfiguration config3_7; ::android::hardware::camera::device::V3_5::StreamConfiguration config3_5; ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4; ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2; - createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, - &config3_2, &config3_4, &config3_5, jpegBufferSize); + createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config3_2, + &config3_4, &config3_5, &config3_7, jpegBufferSize); if (session3_5 != nullptr) { - verifyStreamCombination(cameraDevice3_5, config3_4, - /*expectedStatus*/ true, /*expectStreamCombQuery*/ false); + verifyStreamCombination(cameraDevice3_7, config3_7, cameraDevice3_5, config3_4, + /*expectedStatus*/ true, + /*expectStreamCombQuery*/ false); + } + + if (session3_7 != nullptr) { + config3_7.streamConfigCounter = streamConfigCounter++; + ret = session3_7->configureStreams_3_7( + config3_7, + [](Status s, device::V3_6::HalStreamConfiguration halConfig) { + ASSERT_EQ(Status::OK, s); + ASSERT_EQ(2u, halConfig.streams.size()); + }); + } else if (session3_5 != nullptr) { config3_5.streamConfigCounter = streamConfigCounter++; ret = session3_5->configureStreams_3_5(config3_5, [](Status s, device::V3_4::HalStreamConfiguration halConfig) { @@ -4051,12 +4230,15 @@ TEST_P(CameraHidlTest, configureStreamsConstrainedOutputs) { sp session3_4; sp session3_5; sp session3_6; + sp session3_7; sp cameraDevice; sp cameraDevice3_5; + sp cameraDevice3_7; openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/, &cameraDevice /*out*/); - castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5, &session3_6); - castDevice(cameraDevice, deviceVersion, &cameraDevice3_5); + castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5, + &session3_6, &session3_7); + castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7); Status rc = isConstrainedModeAvailable(staticMeta); if (Status::METHOD_NOT_SUPPORTED == rc) { @@ -4081,14 +4263,27 @@ TEST_P(CameraHidlTest, configureStreamsConstrainedOutputs) { 0, StreamRotation::ROTATION_0}; ::android::hardware::hidl_vec streams = {stream}; + ::android::hardware::camera::device::V3_7::StreamConfiguration config3_7; ::android::hardware::camera::device::V3_5::StreamConfiguration config3_5; ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4; ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2; createStreamConfiguration(streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE, - &config3_2, &config3_4, &config3_5); + &config3_2, &config3_4, &config3_5, &config3_7); if (session3_5 != nullptr) { - verifyStreamCombination(cameraDevice3_5, config3_4, - /*expectedStatus*/ true, /*expectStreamCombQuery*/ false); + verifyStreamCombination(cameraDevice3_7, config3_7, cameraDevice3_5, config3_4, + /*expectedStatus*/ true, /*expectStreamCombQuery*/ false); + } + + if (session3_7 != nullptr) { + config3_7.streamConfigCounter = streamConfigCounter++; + ret = session3_7->configureStreams_3_7( + config3_7, + [streamId](Status s, device::V3_6::HalStreamConfiguration halConfig) { + ASSERT_EQ(Status::OK, s); + ASSERT_EQ(1u, halConfig.streams.size()); + ASSERT_EQ(halConfig.streams[0].v3_4.v3_3.v3_2.id, streamId); + }); + } else if (session3_5 != nullptr) { config3_5.streamConfigCounter = streamConfigCounter++; ret = session3_5->configureStreams_3_5(config3_5, [streamId](Status s, device::V3_4::HalStreamConfiguration halConfig) { @@ -4130,8 +4325,15 @@ TEST_P(CameraHidlTest, configureStreamsConstrainedOutputs) { StreamRotation::ROTATION_0}; streams[0] = stream; createStreamConfiguration(streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE, - &config3_2, &config3_4, &config3_5); - if (session3_5 != nullptr) { + &config3_2, &config3_4, &config3_5, &config3_7); + if (session3_7 != nullptr) { + config3_7.streamConfigCounter = streamConfigCounter++; + ret = session3_7->configureStreams_3_7( + config3_7, [](Status s, device::V3_6::HalStreamConfiguration) { + ASSERT_TRUE((Status::ILLEGAL_ARGUMENT == s) || + (Status::INTERNAL_ERROR == s)); + }); + } else if (session3_5 != nullptr) { config3_5.streamConfigCounter = streamConfigCounter++; ret = session3_5->configureStreams_3_5(config3_5, [](Status s, device::V3_4::HalStreamConfiguration) { @@ -4169,8 +4371,14 @@ TEST_P(CameraHidlTest, configureStreamsConstrainedOutputs) { StreamRotation::ROTATION_0}; streams[0] = stream; createStreamConfiguration(streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE, - &config3_2, &config3_4, &config3_5); - if (session3_5 != nullptr) { + &config3_2, &config3_4, &config3_5, &config3_7); + if (session3_7 != nullptr) { + config3_7.streamConfigCounter = streamConfigCounter++; + ret = session3_7->configureStreams_3_7( + config3_7, [](Status s, device::V3_6::HalStreamConfiguration) { + ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s); + }); + } else if (session3_5 != nullptr) { config3_5.streamConfigCounter = streamConfigCounter++; ret = session3_5->configureStreams_3_5(config3_5, [](Status s, device::V3_4::HalStreamConfiguration) { @@ -4204,8 +4412,14 @@ TEST_P(CameraHidlTest, configureStreamsConstrainedOutputs) { StreamRotation::ROTATION_0}; streams[0] = stream; createStreamConfiguration(streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE, - &config3_2, &config3_4, &config3_5); - if (session3_5 != nullptr) { + &config3_2, &config3_4, &config3_5, &config3_7); + if (session3_7 != nullptr) { + config3_7.streamConfigCounter = streamConfigCounter++; + ret = session3_7->configureStreams_3_7( + config3_7, [](Status s, device::V3_6::HalStreamConfiguration) { + ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s); + }); + } else if (session3_5 != nullptr) { config3_5.streamConfigCounter = streamConfigCounter++; ret = session3_5->configureStreams_3_5(config3_5, [](Status s, device::V3_4::HalStreamConfiguration) { @@ -4263,12 +4477,15 @@ TEST_P(CameraHidlTest, configureStreamsVideoStillOutputs) { sp session3_4; sp session3_5; sp session3_6; + sp session3_7; sp cameraDevice; sp cameraDevice3_5; + sp cameraDevice3_7; openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/, &cameraDevice /*out*/); - castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5, &session3_6); - castDevice(cameraDevice, deviceVersion, &cameraDevice3_5); + castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5, + &session3_6, &session3_7); + castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7); // Check if camera support depth only if (isDepthOnly(staticMeta)) { @@ -4315,14 +4532,27 @@ TEST_P(CameraHidlTest, configureStreamsVideoStillOutputs) { static_cast(Dataspace::V0_JFIF), StreamRotation::ROTATION_0}; ::android::hardware::hidl_vec streams = {videoStream, blobStream}; + ::android::hardware::camera::device::V3_7::StreamConfiguration config3_7; ::android::hardware::camera::device::V3_5::StreamConfiguration config3_5; ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4; ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2; - createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, - &config3_2, &config3_4, &config3_5, jpegBufferSize); + createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config3_2, + &config3_4, &config3_5, &config3_7, jpegBufferSize); if (session3_5 != nullptr) { - verifyStreamCombination(cameraDevice3_5, config3_4, - /*expectedStatus*/ true, /*expectStreamCombQuery*/ false); + verifyStreamCombination(cameraDevice3_7, config3_7, cameraDevice3_5, config3_4, + /*expectedStatus*/ true, + /*expectStreamCombQuery*/ false); + } + + if (session3_7 != nullptr) { + config3_7.streamConfigCounter = streamConfigCounter++; + ret = session3_7->configureStreams_3_7( + config3_7, + [](Status s, device::V3_6::HalStreamConfiguration halConfig) { + ASSERT_EQ(Status::OK, s); + ASSERT_EQ(2u, halConfig.streams.size()); + }); + } else if (session3_5 != nullptr) { config3_5.streamConfigCounter = streamConfigCounter++; ret = session3_5->configureStreams_3_5(config3_5, [](Status s, device::V3_4::HalStreamConfiguration halConfig) { @@ -4788,6 +5018,184 @@ TEST_P(CameraHidlTest, processMultiCaptureRequestPreview) { } } +// Generate and verify an ultra high resolution capture request +TEST_P(CameraHidlTest, processUltraHighResolutionRequest) { + hidl_vec cameraDeviceNames = getCameraDeviceNames(mProvider); + uint64_t bufferId = 1; + uint32_t frameNumber = 1; + ::android::hardware::hidl_vec settings; + + for (const auto& name : cameraDeviceNames) { + int deviceVersion = getCameraDeviceVersion(name, mProviderType); + if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_7) { + continue; + } + std::string version, deviceId; + ASSERT_TRUE(::matchDeviceName(name, mProviderType, &version, &deviceId)); + camera_metadata_t* staticMeta; + Return ret; + sp session; + openEmptyDeviceSession(name, mProvider, &session, &staticMeta); + if (!isUltraHighResolution(staticMeta)) { + free_camera_metadata(staticMeta); + ret = session->close(); + ASSERT_TRUE(ret.isOk()); + continue; + } + android::hardware::camera::common::V1_0::helper::CameraMetadata defaultSettings; + ret = session->constructDefaultRequestSettings( + RequestTemplate::STILL_CAPTURE, + [&defaultSettings](auto status, const auto& req) mutable { + ASSERT_EQ(Status::OK, status); + + const camera_metadata_t* metadata = + reinterpret_cast(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); + ASSERT_GT(entryCount, 0u); + defaultSettings = metadata; + }); + ASSERT_TRUE(ret.isOk()); + uint8_t sensorPixelMode = + static_cast(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION); + ASSERT_EQ(::android::OK, + defaultSettings.update(ANDROID_SENSOR_PIXEL_MODE, &sensorPixelMode, 1)); + + const camera_metadata_t* settingsBuffer = defaultSettings.getAndLock(); + settings.setToExternal( + reinterpret_cast(const_cast(settingsBuffer)), + get_camera_metadata_size(settingsBuffer)); + + free_camera_metadata(staticMeta); + ret = session->close(); + ASSERT_TRUE(ret.isOk()); + V3_6::HalStreamConfiguration halStreamConfig; + bool supportsPartialResults = false; + bool useHalBufManager = false; + uint32_t partialResultCount = 0; + V3_2::Stream previewStream; + sp session3_7; + sp cb; + std::list pixelFormats = {PixelFormat::YCBCR_420_888, PixelFormat::RAW16}; + for (PixelFormat format : pixelFormats) { + configureStreams3_7(name, deviceVersion, mProvider, format, &session3_7, &previewStream, + &halStreamConfig, &supportsPartialResults, &partialResultCount, + &useHalBufManager, &cb, 0, /*maxResolution*/ true); + ASSERT_NE(session3_7, nullptr); + + std::shared_ptr resultQueue; + auto resultQueueRet = session3_7->getCaptureResultMetadataQueue( + [&resultQueue](const auto& descriptor) { + resultQueue = std::make_shared(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()); + + std::vector graphicBuffers; + graphicBuffers.reserve(halStreamConfig.streams.size()); + ::android::hardware::hidl_vec outputBuffers; + outputBuffers.resize(halStreamConfig.streams.size()); + InFlightRequest inflightReq = {static_cast(halStreamConfig.streams.size()), + false, + supportsPartialResults, + partialResultCount, + std::unordered_set(), + resultQueue}; + + size_t k = 0; + for (const auto& halStream : halStreamConfig.streams) { + hidl_handle buffer_handle; + if (useHalBufManager) { + outputBuffers[k] = {halStream.v3_4.v3_3.v3_2.id, + 0, + buffer_handle, + BufferStatus::OK, + nullptr, + nullptr}; + } else { + allocateGraphicBuffer( + previewStream.width, previewStream.height, + android_convertGralloc1To0Usage(halStream.v3_4.v3_3.v3_2.producerUsage, + halStream.v3_4.v3_3.v3_2.consumerUsage), + halStream.v3_4.v3_3.v3_2.overrideFormat, &buffer_handle); + graphicBuffers.push_back(buffer_handle); + outputBuffers[k] = {halStream.v3_4.v3_3.v3_2.id, + bufferId, + buffer_handle, + BufferStatus::OK, + nullptr, + nullptr}; + bufferId++; + } + k++; + } + + StreamBuffer emptyInputBuffer = {-1, 0, nullptr, BufferStatus::ERROR, nullptr, nullptr}; + V3_4::CaptureRequest request3_4; + request3_4.v3_2.frameNumber = frameNumber; + request3_4.v3_2.fmqSettingsSize = 0; + request3_4.v3_2.settings = settings; + request3_4.v3_2.inputBuffer = emptyInputBuffer; + request3_4.v3_2.outputBuffers = outputBuffers; + V3_7::CaptureRequest request3_7; + request3_7.v3_4 = request3_4; + request3_7.inputWidth = 0; + request3_7.inputHeight = 0; + + { + std::unique_lock l(mLock); + mInflightMap.clear(); + mInflightMap.add(frameNumber, &inflightReq); + } + + Status stat = Status::INTERNAL_ERROR; + uint32_t numRequestProcessed = 0; + hidl_vec cachesToRemove; + Return returnStatus = session3_7->processCaptureRequest_3_7( + {request3_7}, cachesToRemove, + [&stat, &numRequestProcessed](auto s, uint32_t n) { + stat = s; + numRequestProcessed = n; + }); + ASSERT_TRUE(returnStatus.isOk()); + ASSERT_EQ(Status::OK, stat); + ASSERT_EQ(numRequestProcessed, 1u); + + { + std::unique_lock l(mLock); + while (!inflightReq.errorCodeValid && + ((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)); + } + + ASSERT_FALSE(inflightReq.errorCodeValid); + ASSERT_NE(inflightReq.resultOutputBuffers.size(), 0u); + } + if (useHalBufManager) { + hidl_vec streamIds(halStreamConfig.streams.size()); + for (size_t i = 0; i < streamIds.size(); i++) { + streamIds[i] = halStreamConfig.streams[i].v3_4.v3_3.v3_2.id; + } + verifyBuffersReturned(session3_7, streamIds, cb); + } + + ret = session3_7->close(); + ASSERT_TRUE(ret.isOk()); + } + } +} + // Generate and verify a burst containing alternating sensor sensitivity values TEST_P(CameraHidlTest, processCaptureRequestBurstISO) { hidl_vec cameraDeviceNames = getCameraDeviceNames(mProvider); @@ -5482,83 +5890,544 @@ TEST_P(CameraHidlTest, providerDeviceStateNotification) { notifyDeviceState(provider::V2_5::DeviceState::NORMAL); } -// Retrieve all valid output stream resolutions from the camera -// static characteristics. -Status CameraHidlTest::getAvailableOutputStreams(const camera_metadata_t *staticMeta, - std::vector &outputStreams, - const AvailableStream *threshold) { - AvailableStream depthPreviewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight, - static_cast(PixelFormat::Y16)}; - if (nullptr == staticMeta) { - return Status::ILLEGAL_ARGUMENT; - } +// Verify that all supported stream formats and sizes can be configured +// successfully for injection camera. +TEST_P(CameraHidlTest, configureInjectionStreamsAvailableOutputs) { + hidl_vec cameraDeviceNames = getCameraDeviceNames(mProvider); + std::vector outputStreams; - camera_metadata_ro_entry scalarEntry; - camera_metadata_ro_entry depthEntry; - int foundScalar = find_camera_metadata_ro_entry(staticMeta, - ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, &scalarEntry); - int foundDepth = find_camera_metadata_ro_entry(staticMeta, - ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS, &depthEntry); - if ((0 != foundScalar || (0 != (scalarEntry.count % 4))) && - (0 != foundDepth || (0 != (depthEntry.count % 4)))) { - return Status::ILLEGAL_ARGUMENT; - } + for (const auto& name : cameraDeviceNames) { + int deviceVersion = getCameraDeviceVersion(name, mProviderType); + if (deviceVersion <= 0) { + ALOGE("%s: Unsupported device version %d", __func__, deviceVersion); + ADD_FAILURE(); + return; + } else if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_7) { + continue; + } - if(foundScalar == 0 && (0 == (scalarEntry.count % 4))) { - fillOutputStreams(&scalarEntry, outputStreams, threshold, - ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT); - } + camera_metadata_t* staticMetaBuffer; + Return ret; + Status s; + sp session; + sp injectionSession3_7; + openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMetaBuffer /*out*/); + castInjectionSession(session, &injectionSession3_7); + if (injectionSession3_7 == nullptr) { + ALOGW("%s: The provider %s doesn't support ICameraInjectionSession", __func__, + mProviderType.c_str()); + continue; + } - if(foundDepth == 0 && (0 == (depthEntry.count % 4))) { - fillOutputStreams(&depthEntry, outputStreams, &depthPreviewThreshold, - ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_OUTPUT); - } + ::android::hardware::camera::device::V3_2::CameraMetadata hidlChars = {}; + hidlChars.setToExternal( + reinterpret_cast(const_cast(staticMetaBuffer)), + get_camera_metadata_size(staticMetaBuffer)); - return Status::OK; -} + outputStreams.clear(); + ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMetaBuffer, outputStreams)); + ASSERT_NE(0u, outputStreams.size()); -static Size getMinSize(Size a, Size b) { - if (a.width * a.height < b.width * b.height) { - return a; + uint32_t jpegBufferSize = 0; + ASSERT_EQ(Status::OK, getJpegBufferSize(staticMetaBuffer, &jpegBufferSize)); + ASSERT_NE(0u, jpegBufferSize); + + int32_t streamId = 0; + uint32_t streamConfigCounter = 0; + for (auto& it : outputStreams) { + V3_2::Stream stream3_2; + V3_2::DataspaceFlags dataspaceFlag = getDataspace(static_cast(it.format)); + stream3_2 = {streamId, + StreamType::OUTPUT, + static_cast(it.width), + static_cast(it.height), + static_cast(it.format), + GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, + dataspaceFlag, + StreamRotation::ROTATION_0}; + ::android::hardware::hidl_vec streams3_2 = {stream3_2}; + ::android::hardware::camera::device::V3_7::StreamConfiguration config3_7; + ::android::hardware::camera::device::V3_5::StreamConfiguration config3_5; + ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4; + ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2; + createStreamConfiguration(streams3_2, StreamConfigurationMode::NORMAL_MODE, &config3_2, + &config3_4, &config3_5, &config3_7, jpegBufferSize); + + config3_7.streamConfigCounter = streamConfigCounter++; + s = injectionSession3_7->configureInjectionStreams(config3_7, hidlChars); + ASSERT_EQ(Status::OK, s); + streamId++; + } + + free_camera_metadata(staticMetaBuffer); + ret = session->close(); + ASSERT_TRUE(ret.isOk()); } - return b; } -// TODO: Add more combinations -Status CameraHidlTest::getMandatoryConcurrentStreams(const camera_metadata_t* staticMeta, - std::vector* outputStreams) { - if (nullptr == staticMeta || nullptr == outputStreams) { - return Status::ILLEGAL_ARGUMENT; - } +// Check for correct handling of invalid/incorrect configuration parameters for injection camera. +TEST_P(CameraHidlTest, configureInjectionStreamsInvalidOutputs) { + hidl_vec cameraDeviceNames = getCameraDeviceNames(mProvider); + std::vector outputStreams; - if (isDepthOnly(staticMeta)) { - Size y16MaxSize(640, 480); - Size maxAvailableY16Size; - getMaxOutputSizeForFormat(staticMeta, PixelFormat::Y16, &maxAvailableY16Size); - Size y16ChosenSize = getMinSize(y16MaxSize, maxAvailableY16Size); - AvailableStream y16Stream = {.width = y16ChosenSize.width, - .height = y16ChosenSize.height, - .format = static_cast(PixelFormat::Y16)}; - outputStreams->push_back(y16Stream); - return Status::OK; - } + for (const auto& name : cameraDeviceNames) { + int deviceVersion = getCameraDeviceVersion(name, mProviderType); + if (deviceVersion <= 0) { + ALOGE("%s: Unsupported device version %d", __func__, deviceVersion); + ADD_FAILURE(); + return; + } else if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_7) { + continue; + } - Size yuvMaxSize(1280, 720); - Size jpegMaxSize(1920, 1440); - Size maxAvailableYuvSize; - Size maxAvailableJpegSize; - getMaxOutputSizeForFormat(staticMeta, PixelFormat::YCBCR_420_888, &maxAvailableYuvSize); - getMaxOutputSizeForFormat(staticMeta, PixelFormat::BLOB, &maxAvailableJpegSize); - Size yuvChosenSize = getMinSize(yuvMaxSize, maxAvailableYuvSize); - Size jpegChosenSize = getMinSize(jpegMaxSize, maxAvailableJpegSize); + camera_metadata_t* staticMetaBuffer; + Return ret; + Status s; + sp session; + sp injectionSession3_7; + openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMetaBuffer /*out*/); + castInjectionSession(session, &injectionSession3_7); + if (injectionSession3_7 == nullptr) { + ALOGW("%s: The provider %s doesn't support ICameraInjectionSession", __func__, + mProviderType.c_str()); + continue; + } - AvailableStream yuvStream = {.width = yuvChosenSize.width, - .height = yuvChosenSize.height, - .format = static_cast(PixelFormat::YCBCR_420_888)}; + ::android::hardware::camera::device::V3_2::CameraMetadata hidlChars = {}; + hidlChars.setToExternal( + reinterpret_cast(const_cast(staticMetaBuffer)), + get_camera_metadata_size(staticMetaBuffer)); - AvailableStream jpegStream = {.width = jpegChosenSize.width, - .height = jpegChosenSize.height, - .format = static_cast(PixelFormat::BLOB)}; + outputStreams.clear(); + ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMetaBuffer, outputStreams)); + ASSERT_NE(0u, outputStreams.size()); + + uint32_t jpegBufferSize = 0; + ASSERT_EQ(Status::OK, getJpegBufferSize(staticMetaBuffer, &jpegBufferSize)); + ASSERT_NE(0u, jpegBufferSize); + + int32_t streamId = 0; + V3_2::Stream stream3_2 = {streamId++, + StreamType::OUTPUT, + static_cast(0), + static_cast(0), + static_cast(outputStreams[0].format), + GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, + 0, + StreamRotation::ROTATION_0}; + uint32_t streamConfigCounter = 0; + ::android::hardware::hidl_vec streams = {stream3_2}; + ::android::hardware::camera::device::V3_7::StreamConfiguration config3_7; + ::android::hardware::camera::device::V3_5::StreamConfiguration config3_5; + ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4; + ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2; + createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config3_2, + &config3_4, &config3_5, &config3_7, jpegBufferSize); + + config3_7.streamConfigCounter = streamConfigCounter++; + s = injectionSession3_7->configureInjectionStreams(config3_7, hidlChars); + ASSERT_TRUE((Status::ILLEGAL_ARGUMENT == s) || (Status::INTERNAL_ERROR == s)); + + stream3_2 = {streamId++, + StreamType::OUTPUT, + static_cast(UINT32_MAX), + static_cast(UINT32_MAX), + static_cast(outputStreams[0].format), + GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, + 0, + StreamRotation::ROTATION_0}; + streams[0] = stream3_2; + createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config3_2, + &config3_4, &config3_5, &config3_7, jpegBufferSize); + config3_7.streamConfigCounter = streamConfigCounter++; + s = injectionSession3_7->configureInjectionStreams(config3_7, hidlChars); + ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s); + + for (auto& it : outputStreams) { + stream3_2 = {streamId++, + StreamType::OUTPUT, + static_cast(it.width), + static_cast(it.height), + static_cast(UINT32_MAX), + GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, + 0, + StreamRotation::ROTATION_0}; + streams[0] = stream3_2; + createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config3_2, + &config3_4, &config3_5, &config3_7, jpegBufferSize); + config3_7.streamConfigCounter = streamConfigCounter++; + s = injectionSession3_7->configureInjectionStreams(config3_7, hidlChars); + ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s); + + stream3_2 = {streamId++, + StreamType::OUTPUT, + static_cast(it.width), + static_cast(it.height), + static_cast(it.format), + GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, + 0, + static_cast(UINT32_MAX)}; + streams[0] = stream3_2; + createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config3_2, + &config3_4, &config3_5, &config3_7, jpegBufferSize); + config3_7.streamConfigCounter = streamConfigCounter++; + s = injectionSession3_7->configureInjectionStreams(config3_7, hidlChars); + ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s); + } + + free_camera_metadata(staticMetaBuffer); + ret = session->close(); + ASSERT_TRUE(ret.isOk()); + } +} + +// Check whether session parameters are supported for injection camera. If Hal support for them +// exist, then try to configure a preview stream using them. +TEST_P(CameraHidlTest, configureInjectionStreamsWithSessionParameters) { + hidl_vec cameraDeviceNames = getCameraDeviceNames(mProvider); + std::vector outputPreviewStreams; + AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight, + static_cast(PixelFormat::IMPLEMENTATION_DEFINED)}; + + for (const auto& name : cameraDeviceNames) { + int deviceVersion = getCameraDeviceVersion(name, mProviderType); + if (deviceVersion <= 0) { + ALOGE("%s: Unsupported device version %d", __func__, deviceVersion); + ADD_FAILURE(); + return; + } else if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_7) { + continue; + } + + camera_metadata_t* staticMetaBuffer; + Return ret; + Status s; + sp session; + sp injectionSession3_7; + openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMetaBuffer /*out*/); + castInjectionSession(session, &injectionSession3_7); + if (injectionSession3_7 == nullptr) { + ALOGW("%s: The provider %s doesn't support ICameraInjectionSession", __func__, + mProviderType.c_str()); + continue; + } + + ::android::hardware::camera::device::V3_2::CameraMetadata hidlChars = {}; + hidlChars.setToExternal( + reinterpret_cast(const_cast(staticMetaBuffer)), + get_camera_metadata_size(staticMetaBuffer)); + + std::unordered_set availableSessionKeys; + auto rc = getSupportedKeys(staticMetaBuffer, ANDROID_REQUEST_AVAILABLE_SESSION_KEYS, + &availableSessionKeys); + ASSERT_TRUE(Status::OK == rc); + if (availableSessionKeys.empty()) { + free_camera_metadata(staticMetaBuffer); + ret = session->close(); + ASSERT_TRUE(ret.isOk()); + continue; + } + + android::hardware::camera::common::V1_0::helper::CameraMetadata previewRequestSettings; + android::hardware::camera::common::V1_0::helper::CameraMetadata sessionParams, + modifiedSessionParams; + constructFilteredSettings(session, availableSessionKeys, RequestTemplate::PREVIEW, + &previewRequestSettings, &sessionParams); + if (sessionParams.isEmpty()) { + free_camera_metadata(staticMetaBuffer); + ret = session->close(); + ASSERT_TRUE(ret.isOk()); + continue; + } + + outputPreviewStreams.clear(); + + ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMetaBuffer, outputPreviewStreams, + &previewThreshold)); + ASSERT_NE(0u, outputPreviewStreams.size()); + + V3_4::Stream previewStream; + previewStream.v3_2 = {0, + StreamType::OUTPUT, + static_cast(outputPreviewStreams[0].width), + static_cast(outputPreviewStreams[0].height), + static_cast(outputPreviewStreams[0].format), + GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, + 0, + StreamRotation::ROTATION_0}; + previewStream.bufferSize = 0; + ::android::hardware::hidl_vec streams = {previewStream}; + ::android::hardware::camera::device::V3_4::StreamConfiguration config; + ::android::hardware::camera::device::V3_5::StreamConfiguration config3_5; + ::android::hardware::camera::device::V3_7::StreamConfiguration config3_7; + config.streams = streams; + config.operationMode = StreamConfigurationMode::NORMAL_MODE; + modifiedSessionParams = sessionParams; + auto sessionParamsBuffer = sessionParams.release(); + config.sessionParams.setToExternal(reinterpret_cast(sessionParamsBuffer), + get_camera_metadata_size(sessionParamsBuffer)); + config3_5.v3_4 = config; + config3_5.streamConfigCounter = 0; + config3_7.streams = {{previewStream, -1, {ANDROID_SENSOR_PIXEL_MODE_DEFAULT}}}; + config3_7.operationMode = config.operationMode; + config3_7.sessionParams.setToExternal(reinterpret_cast(sessionParamsBuffer), + get_camera_metadata_size(sessionParamsBuffer)); + config3_7.streamConfigCounter = 0; + config3_7.multiResolutionInputImage = false; + + s = injectionSession3_7->configureInjectionStreams(config3_7, hidlChars); + sessionParams.acquire(sessionParamsBuffer); + ASSERT_EQ(Status::OK, s); + + free_camera_metadata(staticMetaBuffer); + ret = session->close(); + ASSERT_TRUE(ret.isOk()); + } +} + +// Test the multi-camera API requirement for Google Requirement Freeze S +// Note that this requirement can only be partially tested. If a vendor +// device doesn't expose a physical camera in any shape or form, there is no way +// the test can catch it. +TEST_P(CameraHidlTest, grfSMultiCameraTest) { + const int socGrfApi = property_get_int32("ro.board.first_api_level", /*default*/ -1); + if (socGrfApi < 31 /*S*/) { + // Non-GRF devices, or version < 31 Skip + ALOGI("%s: socGrfApi level is %d. Skipping", __FUNCTION__, socGrfApi); + return; + } + + // Test that if more than one color cameras facing the same direction are + // supported, there must be at least one logical camera facing that + // direction. + hidl_vec cameraDeviceNames = getCameraDeviceNames(mProvider); + // Front and back facing non-logical color cameras + std::set frontColorCameras, rearColorCameras; + // Front and back facing logical cameras' physical camera Id sets + std::set> frontPhysicalIds, rearPhysicalIds; + for (const auto& name : cameraDeviceNames) { + std::string cameraId; + int deviceVersion = getCameraDeviceVersionAndId(name, mProviderType, &cameraId); + switch (deviceVersion) { + case CAMERA_DEVICE_API_VERSION_3_7: + case CAMERA_DEVICE_API_VERSION_3_6: + case CAMERA_DEVICE_API_VERSION_3_5: + case CAMERA_DEVICE_API_VERSION_3_4: + case CAMERA_DEVICE_API_VERSION_3_3: + case CAMERA_DEVICE_API_VERSION_3_2: { + ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_x; + ALOGI("getCameraCharacteristics: Testing camera device %s", name.c_str()); + Return ret; + ret = mProvider->getCameraDeviceInterface_V3_x( + name, [&](auto status, const auto& device) { + ALOGI("getCameraDeviceInterface_V3_x returns status:%d", (int)status); + ASSERT_EQ(Status::OK, status); + ASSERT_NE(device, nullptr); + device3_x = device; + }); + ASSERT_TRUE(ret.isOk()); + + ret = device3_x->getCameraCharacteristics([&](auto status, const auto& chars) { + ASSERT_EQ(Status::OK, status); + const camera_metadata_t* metadata = (camera_metadata_t*)chars.data(); + + // Skip if this is not a color camera. + if (!CameraHidlTest::isColorCamera(metadata)) { + return; + } + + // Check camera facing. Skip if facing is neither FRONT + // nor BACK. If this is not a logical camera, only note down + // the camera ID, and skip. + camera_metadata_ro_entry entry; + int retcode = find_camera_metadata_ro_entry( + metadata, ANDROID_LENS_FACING, &entry); + ASSERT_EQ(retcode, 0); + ASSERT_GT(entry.count, 0); + uint8_t facing = entry.data.u8[0]; + bool isLogicalCamera = (isLogicalMultiCamera(metadata) == Status::OK); + if (facing == ANDROID_LENS_FACING_FRONT) { + if (!isLogicalCamera) { + frontColorCameras.insert(cameraId); + return; + } + } else if (facing == ANDROID_LENS_FACING_BACK) { + if (!isLogicalCamera) { + rearColorCameras.insert(cameraId); + return; + } + } else { + // Not FRONT or BACK facing. Skip. + return; + } + + // Check logical camera's physical camera IDs for color + // cameras. + std::unordered_set physicalCameraIds; + Status s = getPhysicalCameraIds(metadata, &physicalCameraIds); + ASSERT_EQ(Status::OK, s); + if (facing == ANDROID_LENS_FACING_FRONT) { + frontPhysicalIds.emplace(physicalCameraIds.begin(), physicalCameraIds.end()); + } else { + rearPhysicalIds.emplace(physicalCameraIds.begin(), physicalCameraIds.end()); + } + for (const auto& physicalId : physicalCameraIds) { + // Skip if the physicalId is publicly available + for (auto& deviceName : cameraDeviceNames) { + std::string publicVersion, publicId; + ASSERT_TRUE(::matchDeviceName(deviceName, mProviderType, + &publicVersion, &publicId)); + if (physicalId == publicId) { + // Skip because public Ids will be iterated in outer loop. + return; + } + } + + auto castResult = device::V3_5::ICameraDevice::castFrom(device3_x); + ASSERT_TRUE(castResult.isOk()); + ::android::sp<::android::hardware::camera::device::V3_5::ICameraDevice> + device3_5 = castResult; + ASSERT_NE(device3_5, nullptr); + + // Check camera characteristics for hidden camera id + Return ret = device3_5->getPhysicalCameraCharacteristics( + physicalId, [&](auto status, const auto& chars) { + ASSERT_EQ(Status::OK, status); + const camera_metadata_t* physicalMetadata = + (camera_metadata_t*)chars.data(); + + if (CameraHidlTest::isColorCamera(physicalMetadata)) { + if (facing == ANDROID_LENS_FACING_FRONT) { + frontColorCameras.insert(physicalId); + } else if (facing == ANDROID_LENS_FACING_BACK) { + rearColorCameras.insert(physicalId); + } + } + }); + ASSERT_TRUE(ret.isOk()); + } + }); + ASSERT_TRUE(ret.isOk()); + } break; + case CAMERA_DEVICE_API_VERSION_1_0: { + // Not applicable + } break; + default: { + ALOGE("%s: Unsupported device version %d", __func__, deviceVersion); + ADD_FAILURE(); + } break; + } + } + + // If there are more than one color cameras facing one direction, a logical + // multi-camera must be defined consisting of all color cameras facing that + // direction. + if (frontColorCameras.size() > 1) { + bool hasFrontLogical = false; + for (const auto& physicalIds : frontPhysicalIds) { + if (std::includes(physicalIds.begin(), physicalIds.end(), + frontColorCameras.begin(), frontColorCameras.end())) { + hasFrontLogical = true; + break; + } + } + ASSERT_TRUE(hasFrontLogical); + } + if (rearColorCameras.size() > 1) { + bool hasRearLogical = false; + for (const auto& physicalIds : rearPhysicalIds) { + if (std::includes(physicalIds.begin(), physicalIds.end(), + rearColorCameras.begin(), rearColorCameras.end())) { + hasRearLogical = true; + break; + } + } + ASSERT_TRUE(hasRearLogical); + } +} + +// Retrieve all valid output stream resolutions from the camera +// static characteristics. +Status CameraHidlTest::getAvailableOutputStreams(const camera_metadata_t* staticMeta, + std::vector& outputStreams, + const AvailableStream* threshold, + bool maxResolution) { + AvailableStream depthPreviewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight, + static_cast(PixelFormat::Y16)}; + if (nullptr == staticMeta) { + return Status::ILLEGAL_ARGUMENT; + } + int scalerTag = maxResolution + ? ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION + : ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS; + int depthTag = maxResolution + ? ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION + : ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS; + + camera_metadata_ro_entry scalarEntry; + camera_metadata_ro_entry depthEntry; + int foundScalar = find_camera_metadata_ro_entry(staticMeta, scalerTag, &scalarEntry); + int foundDepth = find_camera_metadata_ro_entry(staticMeta, depthTag, &depthEntry); + if ((0 != foundScalar || (0 != (scalarEntry.count % 4))) && + (0 != foundDepth || (0 != (depthEntry.count % 4)))) { + return Status::ILLEGAL_ARGUMENT; + } + + if(foundScalar == 0 && (0 == (scalarEntry.count % 4))) { + fillOutputStreams(&scalarEntry, outputStreams, threshold, + ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT); + } + + if(foundDepth == 0 && (0 == (depthEntry.count % 4))) { + fillOutputStreams(&depthEntry, outputStreams, &depthPreviewThreshold, + ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_OUTPUT); + } + + return Status::OK; +} + +static Size getMinSize(Size a, Size b) { + if (a.width * a.height < b.width * b.height) { + return a; + } + return b; +} + +// TODO: Add more combinations +Status CameraHidlTest::getMandatoryConcurrentStreams(const camera_metadata_t* staticMeta, + std::vector* outputStreams) { + if (nullptr == staticMeta || nullptr == outputStreams) { + return Status::ILLEGAL_ARGUMENT; + } + + if (isDepthOnly(staticMeta)) { + Size y16MaxSize(640, 480); + Size maxAvailableY16Size; + getMaxOutputSizeForFormat(staticMeta, PixelFormat::Y16, &maxAvailableY16Size); + Size y16ChosenSize = getMinSize(y16MaxSize, maxAvailableY16Size); + AvailableStream y16Stream = {.width = y16ChosenSize.width, + .height = y16ChosenSize.height, + .format = static_cast(PixelFormat::Y16)}; + outputStreams->push_back(y16Stream); + return Status::OK; + } + + Size yuvMaxSize(1280, 720); + Size jpegMaxSize(1920, 1440); + Size maxAvailableYuvSize; + Size maxAvailableJpegSize; + getMaxOutputSizeForFormat(staticMeta, PixelFormat::YCBCR_420_888, &maxAvailableYuvSize); + getMaxOutputSizeForFormat(staticMeta, PixelFormat::BLOB, &maxAvailableJpegSize); + Size yuvChosenSize = getMinSize(yuvMaxSize, maxAvailableYuvSize); + Size jpegChosenSize = getMinSize(jpegMaxSize, maxAvailableJpegSize); + + AvailableStream yuvStream = {.width = yuvChosenSize.width, + .height = yuvChosenSize.height, + .format = static_cast(PixelFormat::YCBCR_420_888)}; + + AvailableStream jpegStream = {.width = jpegChosenSize.width, + .height = jpegChosenSize.height, + .format = static_cast(PixelFormat::BLOB)}; outputStreams->push_back(yuvStream); outputStreams->push_back(jpegStream); @@ -5566,9 +6435,12 @@ Status CameraHidlTest::getMandatoryConcurrentStreams(const camera_metadata_t* st } Status CameraHidlTest::getMaxOutputSizeForFormat(const camera_metadata_t* staticMeta, - PixelFormat format, Size* size) { + PixelFormat format, Size* size, + bool maxResolution) { std::vector outputStreams; - if (size == nullptr || getAvailableOutputStreams(staticMeta, outputStreams) != Status::OK) { + if (size == nullptr || + getAvailableOutputStreams(staticMeta, outputStreams, + /*threshold*/ nullptr, maxResolution) != Status::OK) { return Status::ILLEGAL_ARGUMENT; } Size maxSize; @@ -5883,6 +6755,28 @@ Status CameraHidlTest::getSystemCameraKind(const camera_metadata_t* staticMeta, return ret; } +void CameraHidlTest::getMultiResolutionStreamConfigurations( + camera_metadata_ro_entry* multiResStreamConfigs, camera_metadata_ro_entry* streamConfigs, + camera_metadata_ro_entry* maxResolutionStreamConfigs, + const camera_metadata_t* staticMetadata) { + ASSERT_NE(multiResStreamConfigs, nullptr); + ASSERT_NE(streamConfigs, nullptr); + ASSERT_NE(maxResolutionStreamConfigs, nullptr); + ASSERT_NE(staticMetadata, nullptr); + + int retcode = find_camera_metadata_ro_entry( + staticMetadata, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, streamConfigs); + ASSERT_TRUE(0 == retcode); + retcode = find_camera_metadata_ro_entry( + staticMetadata, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION, + maxResolutionStreamConfigs); + ASSERT_TRUE(-ENOENT == retcode || 0 == retcode); + retcode = find_camera_metadata_ro_entry( + staticMetadata, ANDROID_SCALER_PHYSICAL_CAMERA_MULTI_RESOLUTION_STREAM_CONFIGURATIONS, + multiResStreamConfigs); + ASSERT_TRUE(-ENOENT == retcode || 0 == retcode); +} + // Select an appropriate dataspace given a specific pixel format. V3_2::DataspaceFlags CameraHidlTest::getDataspace(PixelFormat format) { switch (format) { @@ -5924,6 +6818,23 @@ Status CameraHidlTest::isMonochromeCamera(const camera_metadata_t *staticMeta) { return ret; } +bool CameraHidlTest::isColorCamera(const camera_metadata_t *metadata) { + camera_metadata_ro_entry entry; + int retcode = find_camera_metadata_ro_entry( + metadata, ANDROID_REQUEST_AVAILABLE_CAPABILITIES, &entry); + if ((0 == retcode) && (entry.count > 0)) { + bool isBackwardCompatible = (std::find(entry.data.u8, entry.data.u8 + entry.count, + ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE) != + entry.data.u8 + entry.count); + bool isMonochrome = (std::find(entry.data.u8, entry.data.u8 + entry.count, + ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME) != + entry.data.u8 + entry.count); + bool isColor = isBackwardCompatible && !isMonochrome; + return isColor; + } + return false; +} + // Retrieve the reprocess input-output format map from the static // camera characteristics. Status CameraHidlTest::getZSLInputOutputMap(camera_metadata_t *staticMeta, @@ -5986,15 +6897,18 @@ Status CameraHidlTest::isAutoFocusModeAvailable( void CameraHidlTest::createStreamConfiguration( const ::android::hardware::hidl_vec& streams3_2, StreamConfigurationMode configMode, - ::android::hardware::camera::device::V3_2::StreamConfiguration *config3_2 /*out*/, - ::android::hardware::camera::device::V3_4::StreamConfiguration *config3_4 /*out*/, - ::android::hardware::camera::device::V3_5::StreamConfiguration *config3_5 /*out*/, + ::android::hardware::camera::device::V3_2::StreamConfiguration* config3_2 /*out*/, + ::android::hardware::camera::device::V3_4::StreamConfiguration* config3_4 /*out*/, + ::android::hardware::camera::device::V3_5::StreamConfiguration* config3_5 /*out*/, + ::android::hardware::camera::device::V3_7::StreamConfiguration* config3_7 /*out*/, uint32_t jpegBufferSize) { ASSERT_NE(nullptr, config3_2); ASSERT_NE(nullptr, config3_4); ASSERT_NE(nullptr, config3_5); + ASSERT_NE(nullptr, config3_7); ::android::hardware::hidl_vec streams3_4(streams3_2.size()); + ::android::hardware::hidl_vec streams3_7(streams3_2.size()); size_t idx = 0; for (auto& stream3_2 : streams3_2) { V3_4::Stream stream; @@ -6004,14 +6918,160 @@ void CameraHidlTest::createStreamConfiguration( stream3_2.dataSpace == static_cast(Dataspace::V0_JFIF)) { stream.bufferSize = jpegBufferSize; } - streams3_4[idx++] = stream; + streams3_4[idx] = stream; + streams3_7[idx] = {stream, /*groupId*/ -1, {ANDROID_SENSOR_PIXEL_MODE_DEFAULT}}; + idx++; } // Caller is responsible to fill in non-zero config3_5->streamConfigCounter after this returns + *config3_7 = {streams3_7, configMode, {}, 0, false}; *config3_5 = {{streams3_4, configMode, {}}, 0}; *config3_4 = config3_5->v3_4; *config3_2 = {streams3_2, configMode}; } +// Configure streams +void CameraHidlTest::configureStreams3_7( + const std::string& name, int32_t deviceVersion, sp provider, + PixelFormat format, sp* session3_7 /*out*/, + V3_2::Stream* previewStream /*out*/, + device::V3_6::HalStreamConfiguration* halStreamConfig /*out*/, + bool* supportsPartialResults /*out*/, uint32_t* partialResultCount /*out*/, + bool* useHalBufManager /*out*/, sp* outCb /*out*/, uint32_t streamConfigCounter, + bool maxResolution) { + ASSERT_NE(nullptr, session3_7); + ASSERT_NE(nullptr, halStreamConfig); + ASSERT_NE(nullptr, previewStream); + ASSERT_NE(nullptr, supportsPartialResults); + ASSERT_NE(nullptr, partialResultCount); + ASSERT_NE(nullptr, useHalBufManager); + ASSERT_NE(nullptr, outCb); + + std::vector outputStreams; + ::android::sp device3_x; + ALOGI("configureStreams: Testing camera device %s", name.c_str()); + Return ret; + ret = provider->getCameraDeviceInterface_V3_x(name, [&](auto status, const auto& device) { + ALOGI("getCameraDeviceInterface_V3_x returns status:%d", (int)status); + ASSERT_EQ(Status::OK, status); + ASSERT_NE(device, nullptr); + device3_x = device; + }); + ASSERT_TRUE(ret.isOk()); + + camera_metadata_t* staticMeta; + ret = device3_x->getCameraCharacteristics([&](Status s, CameraMetadata metadata) { + ASSERT_EQ(Status::OK, s); + staticMeta = + clone_camera_metadata(reinterpret_cast(metadata.data())); + ASSERT_NE(nullptr, staticMeta); + }); + ASSERT_TRUE(ret.isOk()); + + camera_metadata_ro_entry entry; + auto status = + find_camera_metadata_ro_entry(staticMeta, ANDROID_REQUEST_PARTIAL_RESULT_COUNT, &entry); + if ((0 == status) && (entry.count > 0)) { + *partialResultCount = entry.data.i32[0]; + *supportsPartialResults = (*partialResultCount > 1); + } + + sp cb = new DeviceCb(this, deviceVersion, staticMeta); + sp session; + ret = device3_x->open(cb, [&session](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()); + *outCb = cb; + + sp session3_3; + sp session3_4; + sp session3_5; + sp session3_6; + castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5, &session3_6, + session3_7); + ASSERT_NE(nullptr, (*session3_7).get()); + + *useHalBufManager = false; + status = find_camera_metadata_ro_entry( + staticMeta, ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION, &entry); + if ((0 == status) && (entry.count == 1)) { + *useHalBufManager = (entry.data.u8[0] == + ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5); + } + + outputStreams.clear(); + Size maxSize; + auto rc = getMaxOutputSizeForFormat(staticMeta, format, &maxSize, maxResolution); + ASSERT_EQ(Status::OK, rc); + free_camera_metadata(staticMeta); + + ::android::hardware::hidl_vec streams3_7(1); + streams3_7[0].groupId = -1; + streams3_7[0].sensorPixelModesUsed = { + CameraMetadataEnumAndroidSensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION}; + streams3_7[0].v3_4.bufferSize = 0; + streams3_7[0].v3_4.v3_2.id = 0; + streams3_7[0].v3_4.v3_2.streamType = StreamType::OUTPUT; + streams3_7[0].v3_4.v3_2.width = static_cast(maxSize.width); + streams3_7[0].v3_4.v3_2.height = static_cast(maxSize.height); + streams3_7[0].v3_4.v3_2.format = static_cast(format); + streams3_7[0].v3_4.v3_2.usage = GRALLOC1_CONSUMER_USAGE_CPU_READ; + streams3_7[0].v3_4.v3_2.dataSpace = 0; + streams3_7[0].v3_4.v3_2.rotation = StreamRotation::ROTATION_0; + + ::android::hardware::camera::device::V3_7::StreamConfiguration config3_7; + config3_7.streams = streams3_7; + config3_7.operationMode = StreamConfigurationMode::NORMAL_MODE; + config3_7.streamConfigCounter = streamConfigCounter; + config3_7.multiResolutionInputImage = false; + RequestTemplate reqTemplate = RequestTemplate::STILL_CAPTURE; + ret = (*session3_7) + ->constructDefaultRequestSettings(reqTemplate, + [&config3_7](auto status, const auto& req) { + ASSERT_EQ(Status::OK, status); + config3_7.sessionParams = req; + }); + ASSERT_TRUE(ret.isOk()); + + ASSERT_TRUE(deviceVersion >= CAMERA_DEVICE_API_VERSION_3_7); + sp cameraDevice3_5 = nullptr; + sp cameraDevice3_7 = nullptr; + castDevice(device3_x, deviceVersion, &cameraDevice3_5, &cameraDevice3_7); + ASSERT_NE(cameraDevice3_7, nullptr); + bool supported = false; + ret = cameraDevice3_7->isStreamCombinationSupported_3_7( + config3_7, [&supported](Status s, bool combStatus) { + ASSERT_TRUE((Status::OK == s) || (Status::METHOD_NOT_SUPPORTED == s)); + if (Status::OK == s) { + supported = combStatus; + } + }); + ASSERT_TRUE(ret.isOk()); + ASSERT_EQ(supported, true); + + if (*session3_7 != nullptr) { + ret = (*session3_7) + ->configureStreams_3_7( + config3_7, + [&](Status s, device::V3_6::HalStreamConfiguration halConfig) { + ASSERT_EQ(Status::OK, s); + *halStreamConfig = halConfig; + if (*useHalBufManager) { + hidl_vec streams(1); + hidl_vec halStreams(1); + streams[0] = streams3_7[0].v3_4; + halStreams[0] = halConfig.streams[0].v3_4.v3_3.v3_2; + cb->setCurrentStreamConfig(streams, halStreams); + } + }); + } + *previewStream = streams3_7[0].v3_4.v3_2; + ASSERT_TRUE(ret.isOk()); +} + // Configure multiple preview streams using different physical ids. void CameraHidlTest::configurePreviewStreams3_4(const std::string &name, int32_t deviceVersion, sp provider, @@ -6085,7 +7145,9 @@ void CameraHidlTest::configurePreviewStreams3_4(const std::string &name, int32_t sp session3_3; sp session3_6; - castSession(session, deviceVersion, &session3_3, session3_4, session3_5, &session3_6); + sp session3_7; + castSession(session, deviceVersion, &session3_3, session3_4, session3_5, + &session3_6, &session3_7); ASSERT_NE(nullptr, (*session3_4).get()); *useHalBufManager = false; @@ -6126,10 +7188,11 @@ void CameraHidlTest::configurePreviewStreams3_4(const std::string &name, int32_t }); ASSERT_TRUE(ret.isOk()); - ASSERT_TRUE(!allowUnsupport || deviceVersion == CAMERA_DEVICE_API_VERSION_3_5); + ASSERT_TRUE(!allowUnsupport || deviceVersion >= CAMERA_DEVICE_API_VERSION_3_5); if (allowUnsupport) { sp cameraDevice3_5; - castDevice(device3_x, deviceVersion, &cameraDevice3_5); + sp cameraDevice3_7; + castDevice(device3_x, deviceVersion, &cameraDevice3_5, &cameraDevice3_7); bool supported = false; ret = cameraDevice3_5->isStreamCombinationSupported(config3_4, @@ -6307,6 +7370,21 @@ void CameraHidlTest::configureOfflineStillStream(const std::string &name, ASSERT_TRUE(ret.isOk()); } +bool CameraHidlTest::isUltraHighResolution(const camera_metadata_t* staticMeta) { + camera_metadata_ro_entry scalarEntry; + int rc = find_camera_metadata_ro_entry(staticMeta, ANDROID_REQUEST_AVAILABLE_CAPABILITIES, + &scalarEntry); + if (rc == 0) { + for (uint32_t i = 0; i < scalarEntry.count; i++) { + if (scalarEntry.data.u8[i] == + ANDROID_REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR) { + return true; + } + } + } + return false; +} + bool CameraHidlTest::isDepthOnly(const camera_metadata_t* staticMeta) { camera_metadata_ro_entry scalarEntry; camera_metadata_ro_entry depthEntry; @@ -6428,7 +7506,9 @@ void CameraHidlTest::configureSingleStream( sp session3_4; sp session3_5; sp session3_6; - castSession(*session, deviceVersion, &session3_3, &session3_4, &session3_5, &session3_6); + sp session3_7; + castSession(*session, deviceVersion, &session3_3, &session3_4, &session3_5, + &session3_6, &session3_7); *useHalBufManager = false; status = find_camera_metadata_ro_entry(staticMeta, @@ -6471,9 +7551,32 @@ void CameraHidlTest::configureSingleStream( ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2; ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4; ::android::hardware::camera::device::V3_5::StreamConfiguration config3_5; - createStreamConfiguration(streams3_2, StreamConfigurationMode::NORMAL_MODE, - &config3_2, &config3_4, &config3_5, jpegBufferSize); - if (session3_5 != nullptr) { + ::android::hardware::camera::device::V3_7::StreamConfiguration config3_7; + createStreamConfiguration(streams3_2, StreamConfigurationMode::NORMAL_MODE, &config3_2, + &config3_4, &config3_5, &config3_7, jpegBufferSize); + if (session3_7 != nullptr) { + ret = session3_7->constructDefaultRequestSettings( + reqTemplate, [&config3_7](auto status, const auto& req) { + ASSERT_EQ(Status::OK, status); + config3_7.sessionParams = req; + }); + ASSERT_TRUE(ret.isOk()); + config3_7.streamConfigCounter = streamConfigCounter; + ret = session3_7->configureStreams_3_7( + config3_7, [&](Status s, device::V3_6::HalStreamConfiguration halConfig) { + ASSERT_EQ(Status::OK, s); + ASSERT_EQ(1u, halConfig.streams.size()); + halStreamConfig->streams.resize(1); + halStreamConfig->streams[0] = halConfig.streams[0].v3_4.v3_3.v3_2; + if (*useHalBufManager) { + hidl_vec streams(1); + hidl_vec halStreams(1); + streams[0] = config3_4.streams[0]; + halStreams[0] = halConfig.streams[0].v3_4.v3_3.v3_2; + cb->setCurrentStreamConfig(streams, halStreams); + } + }); + } else if (session3_5 != nullptr) { ret = session3_5->constructDefaultRequestSettings(reqTemplate, [&config3_5](auto status, const auto& req) { ASSERT_EQ(Status::OK, status); @@ -6533,20 +7636,37 @@ void CameraHidlTest::configureSingleStream( ASSERT_TRUE(ret.isOk()); } -void CameraHidlTest::castDevice(const sp &device, - int32_t deviceVersion, sp *device3_5/*out*/) { +void CameraHidlTest::castDevice(const sp& device, + int32_t deviceVersion, + sp* device3_5 /*out*/, + sp* device3_7 /*out*/) { ASSERT_NE(nullptr, device3_5); - if (deviceVersion == CAMERA_DEVICE_API_VERSION_3_5) { - auto castResult = device::V3_5::ICameraDevice::castFrom(device); - ASSERT_TRUE(castResult.isOk()); - *device3_5 = castResult; + ASSERT_NE(nullptr, device3_7); + + switch (deviceVersion) { + case CAMERA_DEVICE_API_VERSION_3_7: { + auto castResult = device::V3_7::ICameraDevice::castFrom(device); + ASSERT_TRUE(castResult.isOk()); + *device3_7 = castResult; + } + [[fallthrough]]; + case CAMERA_DEVICE_API_VERSION_3_5: { + auto castResult = device::V3_5::ICameraDevice::castFrom(device); + ASSERT_TRUE(castResult.isOk()); + *device3_5 = castResult; + break; + } + default: + // no-op + return; } } //Cast camera provider to corresponding version if available void CameraHidlTest::castProvider(const sp& provider, sp* provider2_5 /*out*/, - sp* provider2_6 /*out*/) { + sp* provider2_6 /*out*/, + sp* provider2_7 /*out*/) { ASSERT_NE(nullptr, provider2_5); auto castResult2_5 = provider::V2_5::ICameraProvider::castFrom(provider); if (castResult2_5.isOk()) { @@ -6558,6 +7678,12 @@ void CameraHidlTest::castProvider(const sp& provider, if (castResult2_6.isOk()) { *provider2_6 = castResult2_6; } + + ASSERT_NE(nullptr, provider2_7); + auto castResult2_7 = provider::V2_7::ICameraProvider::castFrom(provider); + if (castResult2_7.isOk()) { + *provider2_7 = castResult2_7; + } } //Cast camera device session to corresponding version @@ -6565,13 +7691,21 @@ void CameraHidlTest::castSession(const sp &session, int32_ sp *session3_3 /*out*/, sp *session3_4 /*out*/, sp *session3_5 /*out*/, - sp *session3_6 /*out*/) { + sp *session3_6 /*out*/, + sp *session3_7 /*out*/) { ASSERT_NE(nullptr, session3_3); ASSERT_NE(nullptr, session3_4); ASSERT_NE(nullptr, session3_5); ASSERT_NE(nullptr, session3_6); + ASSERT_NE(nullptr, session3_7); switch (deviceVersion) { + case CAMERA_DEVICE_API_VERSION_3_7: { + auto castResult = device::V3_7::ICameraDeviceSession::castFrom(session); + ASSERT_TRUE(castResult.isOk()); + *session3_7 = castResult; + } + [[fallthrough]]; case CAMERA_DEVICE_API_VERSION_3_6: { auto castResult = device::V3_6::ICameraDeviceSession::castFrom(session); ASSERT_TRUE(castResult.isOk()); @@ -6602,9 +7736,40 @@ void CameraHidlTest::castSession(const sp &session, int32_ } } -void CameraHidlTest::verifyStreamCombination(sp cameraDevice3_5, - const ::android::hardware::camera::device::V3_4::StreamConfiguration &config3_4, +// Cast camera device session to injection session +void CameraHidlTest::castInjectionSession( + const sp& session, + sp* injectionSession3_7 /*out*/) { + ASSERT_NE(nullptr, injectionSession3_7); + + sp session3_7; + auto castResult = device::V3_7::ICameraDeviceSession::castFrom(session); + ASSERT_TRUE(castResult.isOk()); + session3_7 = castResult; + + auto castInjectionResult = device::V3_7::ICameraInjectionSession::castFrom(session3_7); + ASSERT_TRUE(castInjectionResult.isOk()); + *injectionSession3_7 = castInjectionResult; +} + +void CameraHidlTest::verifyStreamCombination( + sp cameraDevice3_7, + const ::android::hardware::camera::device::V3_7::StreamConfiguration& config3_7, + sp cameraDevice3_5, + const ::android::hardware::camera::device::V3_4::StreamConfiguration& config3_4, bool expectedStatus, bool expectMethodSupported) { + if (cameraDevice3_7.get() != nullptr) { + auto ret = cameraDevice3_7->isStreamCombinationSupported_3_7( + config3_7, [expectedStatus, expectMethodSupported](Status s, bool combStatus) { + ASSERT_TRUE((Status::OK == s) || + (!expectMethodSupported && Status::METHOD_NOT_SUPPORTED == s)); + if (Status::OK == s) { + ASSERT_TRUE(combStatus == expectedStatus); + } + }); + ASSERT_TRUE(ret.isOk()); + } + if (cameraDevice3_5.get() != nullptr) { auto ret = cameraDevice3_5->isStreamCombinationSupported(config3_4, [expectedStatus, expectMethodSupported] (Status s, bool combStatus) { @@ -6618,11 +7783,11 @@ void CameraHidlTest::verifyStreamCombination(sp cam } } -// Verify logical camera static metadata -void CameraHidlTest::verifyLogicalCameraMetadata(const std::string& cameraName, +// Verify logical or ultra high resolution camera static metadata +void CameraHidlTest::verifyLogicalOrUltraHighResCameraMetadata( + const std::string& cameraName, const ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice>& device, - const CameraMetadata &chars, int deviceVersion, - const hidl_vec& deviceNames) { + const CameraMetadata& chars, int deviceVersion, const hidl_vec& deviceNames) { const camera_metadata_t* metadata = (camera_metadata_t*)chars.data(); ASSERT_NE(nullptr, metadata); SystemCameraKind systemCameraKind = SystemCameraKind::PUBLIC; @@ -6630,7 +7795,9 @@ void CameraHidlTest::verifyLogicalCameraMetadata(const std::string& cameraName, ASSERT_EQ(rc, Status::OK); rc = isLogicalMultiCamera(metadata); ASSERT_TRUE(Status::OK == rc || Status::METHOD_NOT_SUPPORTED == rc); - if (Status::METHOD_NOT_SUPPORTED == rc) { + bool isMultiCamera = (Status::OK == rc); + bool isUltraHighResCamera = isUltraHighResolution(metadata); + if (!isMultiCamera && !isUltraHighResCamera) { return; } @@ -6638,13 +7805,36 @@ void CameraHidlTest::verifyLogicalCameraMetadata(const std::string& cameraName, int retcode = find_camera_metadata_ro_entry(metadata, ANDROID_CONTROL_ZOOM_RATIO_RANGE, &entry); bool hasZoomRatioRange = (0 == retcode && entry.count == 2); + retcode = find_camera_metadata_ro_entry( + metadata, ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION, &entry); + bool hasHalBufferManager = + (0 == retcode && 1 == entry.count && + entry.data.i32[0] == ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5); + retcode = find_camera_metadata_ro_entry( + metadata, ANDROID_SCALER_MULTI_RESOLUTION_STREAM_SUPPORTED, &entry); + bool multiResolutionStreamSupported = + (0 == retcode && 1 == entry.count && + entry.data.u8[0] == ANDROID_SCALER_MULTI_RESOLUTION_STREAM_SUPPORTED_TRUE); + if (multiResolutionStreamSupported) { + ASSERT_TRUE(hasHalBufferManager); + } std::string version, cameraId; ASSERT_TRUE(::matchDeviceName(cameraName, mProviderType, &version, &cameraId)); std::unordered_set physicalIds; - ASSERT_TRUE(Status::OK == getPhysicalCameraIds(metadata, &physicalIds)); + rc = getPhysicalCameraIds(metadata, &physicalIds); + ASSERT_TRUE(isUltraHighResCamera || Status::OK == rc); for (auto physicalId : physicalIds) { ASSERT_NE(physicalId, cameraId); + } + if (physicalIds.size() == 0) { + ASSERT_TRUE(isUltraHighResCamera && !isMultiCamera); + physicalIds.insert(cameraId); + } + // Map from image format to number of multi-resolution sizes for that format + std::unordered_map multiResOutputFormatCounterMap; + std::unordered_map multiResInputFormatCounterMap; + for (auto physicalId : physicalIds) { bool isPublicId = false; std::string fullPublicId; SystemCameraKind physSystemCameraKind = SystemCameraKind::PUBLIC; @@ -6657,6 +7847,11 @@ void CameraHidlTest::verifyLogicalCameraMetadata(const std::string& cameraName, break; } } + + camera_metadata_ro_entry physicalMultiResStreamConfigs; + camera_metadata_ro_entry physicalStreamConfigs; + camera_metadata_ro_entry physicalMaxResolutionStreamConfigs; + bool isUltraHighRes = false; if (isPublicId) { ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> subDevice; Return ret; @@ -6668,62 +7863,195 @@ void CameraHidlTest::verifyLogicalCameraMetadata(const std::string& cameraName, }); ASSERT_TRUE(ret.isOk()); - ret = subDevice->getCameraCharacteristics( - [&](auto status, const auto& chars) { + ret = subDevice->getCameraCharacteristics([&](auto status, const auto& chars) { ASSERT_EQ(Status::OK, status); - const camera_metadata_t* staticMeta = + const camera_metadata_t* staticMetadata = reinterpret_cast(chars.data()); - rc = getSystemCameraKind(staticMeta, &physSystemCameraKind); + rc = getSystemCameraKind(staticMetadata, &physSystemCameraKind); ASSERT_EQ(rc, Status::OK); // Make sure that the system camera kind of a non-hidden // physical cameras is the same as the logical camera associated // with it. ASSERT_EQ(physSystemCameraKind, systemCameraKind); - retcode = find_camera_metadata_ro_entry(staticMeta, + retcode = find_camera_metadata_ro_entry(staticMetadata, ANDROID_CONTROL_ZOOM_RATIO_RANGE, &entry); bool subCameraHasZoomRatioRange = (0 == retcode && entry.count == 2); ASSERT_EQ(hasZoomRatioRange, subCameraHasZoomRatioRange); + + getMultiResolutionStreamConfigurations( + &physicalMultiResStreamConfigs, &physicalStreamConfigs, + &physicalMaxResolutionStreamConfigs, staticMetadata); + isUltraHighRes = isUltraHighResolution(staticMetadata); }); ASSERT_TRUE(ret.isOk()); - continue; + } else { + ASSERT_TRUE(deviceVersion >= CAMERA_DEVICE_API_VERSION_3_5); + auto castResult = device::V3_5::ICameraDevice::castFrom(device); + ASSERT_TRUE(castResult.isOk()); + ::android::sp<::android::hardware::camera::device::V3_5::ICameraDevice> device3_5 = + castResult; + ASSERT_NE(device3_5, nullptr); + + // Check camera characteristics for hidden camera id + Return ret = device3_5->getPhysicalCameraCharacteristics( + physicalId, [&](auto status, const auto& chars) { + verifyCameraCharacteristics(status, chars); + verifyMonochromeCharacteristics(chars, deviceVersion); + + auto staticMetadata = (const camera_metadata_t*)chars.data(); + retcode = find_camera_metadata_ro_entry( + staticMetadata, ANDROID_CONTROL_ZOOM_RATIO_RANGE, &entry); + bool subCameraHasZoomRatioRange = (0 == retcode && entry.count == 2); + ASSERT_EQ(hasZoomRatioRange, subCameraHasZoomRatioRange); + + getMultiResolutionStreamConfigurations( + &physicalMultiResStreamConfigs, &physicalStreamConfigs, + &physicalMaxResolutionStreamConfigs, staticMetadata); + isUltraHighRes = isUltraHighResolution(staticMetadata); + }); + ASSERT_TRUE(ret.isOk()); + + // Check calling getCameraDeviceInterface_V3_x() on hidden camera id returns + // ILLEGAL_ARGUMENT. + std::stringstream s; + s << "device@" << version << "/" << mProviderType << "/" << physicalId; + hidl_string fullPhysicalId(s.str()); + ret = mProvider->getCameraDeviceInterface_V3_x( + fullPhysicalId, [&](auto status, const auto& device3_x) { + ASSERT_EQ(Status::ILLEGAL_ARGUMENT, status); + ASSERT_EQ(device3_x, nullptr); + }); + ASSERT_TRUE(ret.isOk()); } - ASSERT_TRUE(deviceVersion >= CAMERA_DEVICE_API_VERSION_3_5); - auto castResult = device::V3_5::ICameraDevice::castFrom(device); - ASSERT_TRUE(castResult.isOk()); - ::android::sp<::android::hardware::camera::device::V3_5::ICameraDevice> device3_5 = - castResult; - ASSERT_NE(device3_5, nullptr); + if (physicalMultiResStreamConfigs.count > 0) { + ASSERT_GE(deviceVersion, CAMERA_DEVICE_API_VERSION_3_7); + ASSERT_EQ(physicalMultiResStreamConfigs.count % 4, 0); + + // Each supported size must be max size for that format, + for (size_t i = 0; i < physicalMultiResStreamConfigs.count / 4; i++) { + int32_t multiResFormat = physicalMultiResStreamConfigs.data.i32[i * 4]; + int32_t multiResWidth = physicalMultiResStreamConfigs.data.i32[i * 4 + 1]; + int32_t multiResHeight = physicalMultiResStreamConfigs.data.i32[i * 4 + 2]; + int32_t multiResInput = physicalMultiResStreamConfigs.data.i32[i * 4 + 3]; + + // Check if the resolution is the max resolution in stream + // configuration map + bool supported = false; + bool isMaxSize = true; + for (size_t j = 0; j < physicalStreamConfigs.count / 4; j++) { + int32_t format = physicalStreamConfigs.data.i32[j * 4]; + int32_t width = physicalStreamConfigs.data.i32[j * 4 + 1]; + int32_t height = physicalStreamConfigs.data.i32[j * 4 + 2]; + int32_t input = physicalStreamConfigs.data.i32[j * 4 + 3]; + if (format == multiResFormat && input == multiResInput) { + if (width == multiResWidth && height == multiResHeight) { + supported = true; + } else if (width * height > multiResWidth * multiResHeight) { + isMaxSize = false; + } + } + } + // Check if the resolution is the max resolution in max + // resolution stream configuration map + bool supportedUltraHighRes = false; + bool isUltraHighResMaxSize = true; + for (size_t j = 0; j < physicalMaxResolutionStreamConfigs.count / 4; j++) { + int32_t format = physicalMaxResolutionStreamConfigs.data.i32[j * 4]; + int32_t width = physicalMaxResolutionStreamConfigs.data.i32[j * 4 + 1]; + int32_t height = physicalMaxResolutionStreamConfigs.data.i32[j * 4 + 2]; + int32_t input = physicalMaxResolutionStreamConfigs.data.i32[j * 4 + 3]; + if (format == multiResFormat && input == multiResInput) { + if (width == multiResWidth && height == multiResHeight) { + supportedUltraHighRes = true; + } else if (width * height > multiResWidth * multiResHeight) { + isUltraHighResMaxSize = false; + } + } + } - // Check camera characteristics for hidden camera id - Return ret = device3_5->getPhysicalCameraCharacteristics( - physicalId, [&](auto status, const auto& chars) { - verifyCameraCharacteristics(status, chars); - verifyMonochromeCharacteristics(chars, deviceVersion); - retcode = - find_camera_metadata_ro_entry((const camera_metadata_t*)chars.data(), - ANDROID_CONTROL_ZOOM_RATIO_RANGE, &entry); - bool subCameraHasZoomRatioRange = (0 == retcode && entry.count == 2); - ASSERT_EQ(hasZoomRatioRange, subCameraHasZoomRatioRange); - }); - ASSERT_TRUE(ret.isOk()); + if (isUltraHighRes) { + // For ultra high resolution camera, the configuration must + // be the maximum size in stream configuration map, or max + // resolution stream configuration map + ASSERT_TRUE((supported && isMaxSize) || + (supportedUltraHighRes && isUltraHighResMaxSize)); + } else { + // The configuration must be the maximum size in stream + // configuration map + ASSERT_TRUE(supported && isMaxSize); + ASSERT_FALSE(supportedUltraHighRes); + } - // Check calling getCameraDeviceInterface_V3_x() on hidden camera id returns - // ILLEGAL_ARGUMENT. - std::stringstream s; - s << "device@" << version << "/" << mProviderType << "/" << physicalId; - hidl_string fullPhysicalId(s.str()); - ret = mProvider->getCameraDeviceInterface_V3_x(fullPhysicalId, - [&](auto status, const auto& device3_x) { - ASSERT_EQ(Status::ILLEGAL_ARGUMENT, status); - ASSERT_EQ(device3_x, nullptr); - }); - ASSERT_TRUE(ret.isOk()); + // Increment the counter for the configuration's format. + auto& formatCounterMap = multiResInput ? multiResInputFormatCounterMap + : multiResOutputFormatCounterMap; + if (formatCounterMap.count(multiResFormat) == 0) { + formatCounterMap[multiResFormat] = 1; + } else { + formatCounterMap[multiResFormat]++; + } + } + + // There must be no duplicates + for (size_t i = 0; i < physicalMultiResStreamConfigs.count / 4 - 1; i++) { + for (size_t j = i + 1; j < physicalMultiResStreamConfigs.count / 4; j++) { + // Input/output doesn't match + if (physicalMultiResStreamConfigs.data.i32[i * 4 + 3] != + physicalMultiResStreamConfigs.data.i32[j * 4 + 3]) { + continue; + } + // Format doesn't match + if (physicalMultiResStreamConfigs.data.i32[i * 4] != + physicalMultiResStreamConfigs.data.i32[j * 4]) { + continue; + } + // Width doesn't match + if (physicalMultiResStreamConfigs.data.i32[i * 4 + 1] != + physicalMultiResStreamConfigs.data.i32[j * 4 + 1]) { + continue; + } + // Height doesn't match + if (physicalMultiResStreamConfigs.data.i32[i * 4 + 2] != + physicalMultiResStreamConfigs.data.i32[j * 4 + 2]) { + continue; + } + // input/output, format, width, and height all match + ADD_FAILURE(); + } + } + } + } + + // If a multi-resolution stream is supported, there must be at least one + // format with more than one resolutions + if (multiResolutionStreamSupported) { + size_t numMultiResFormats = 0; + for (const auto& [format, sizeCount] : multiResOutputFormatCounterMap) { + if (sizeCount >= 2) { + numMultiResFormats++; + } + } + for (const auto& [format, sizeCount] : multiResInputFormatCounterMap) { + if (sizeCount >= 2) { + numMultiResFormats++; + + // If multi-resolution reprocessing is supported, the logical + // camera or ultra-high resolution sensor camera must support + // the corresponding reprocessing capability. + if (format == static_cast(PixelFormat::IMPLEMENTATION_DEFINED)) { + ASSERT_EQ(isZSLModeAvailable(metadata, PRIV_REPROCESS), Status::OK); + } else if (format == static_cast(PixelFormat::YCBCR_420_888)) { + ASSERT_EQ(isZSLModeAvailable(metadata, YUV_REPROCESS), Status::OK); + } + } + } + ASSERT_GT(numMultiResFormats, 0); } // Make sure ANDROID_LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_ID is available in // result keys. - if (deviceVersion >= CAMERA_DEVICE_API_VERSION_3_5) { + if (isMultiCamera && deviceVersion >= CAMERA_DEVICE_API_VERSION_3_5) { retcode = find_camera_metadata_ro_entry(metadata, ANDROID_REQUEST_AVAILABLE_RESULT_KEYS, &entry); if ((0 == retcode) && (entry.count > 0)) { @@ -7215,7 +8543,9 @@ void CameraHidlTest::verifyBuffersReturned( sp session3_4; sp session3_5; sp session3_6; - castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5, &session3_6); + sp session3_7; + castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5, + &session3_6, &session3_7); ASSERT_NE(nullptr, session3_5.get()); hidl_vec streamIds(1); @@ -7236,6 +8566,13 @@ void CameraHidlTest::verifyBuffersReturned( cb->waitForBuffersReturned(); } +void CameraHidlTest::verifyBuffersReturned(sp session3_7, + hidl_vec streamIds, sp cb, + uint32_t streamConfigCounter) { + session3_7->signalStreamFlush(streamIds, /*streamConfigCounter*/ streamConfigCounter); + cb->waitForBuffersReturned(); +} + void CameraHidlTest::verifyLogicalCameraResult(const camera_metadata_t* staticMetadata, const ::android::hardware::camera::common::V1_0::helper::CameraMetadata& resultMetadata) { std::unordered_set physicalIds; @@ -7582,6 +8919,7 @@ void CameraHidlTest::verifyRequestTemplate(const camera_metadata_t* metadata, } } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CameraHidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, CameraHidlTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames(ICameraProvider::descriptor)), diff --git a/camera/provider/2.7/Android.bp b/camera/provider/2.7/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..ba59b380f52a0c340af063c4723ad0da875b37a8 --- /dev/null +++ b/camera/provider/2.7/Android.bp @@ -0,0 +1,35 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +hidl_interface { + name: "android.hardware.camera.provider@2.7", + root: "android.hardware", + srcs: [ + "types.hal", + "ICameraProvider.hal", + ], + interfaces: [ + "android.hardware.camera.common@1.0", + "android.hardware.camera.device@1.0", + "android.hardware.camera.device@3.2", + "android.hardware.camera.device@3.3", + "android.hardware.camera.device@3.4", + "android.hardware.camera.device@3.5", + "android.hardware.camera.device@3.6", + "android.hardware.camera.device@3.7", + "android.hardware.camera.provider@2.4", + "android.hardware.camera.provider@2.5", + "android.hardware.camera.provider@2.6", + "android.hardware.graphics.common@1.0", + "android.hidl.base@1.0", + ], + gen_java: false, +} diff --git a/camera/provider/2.7/ICameraProvider.hal b/camera/provider/2.7/ICameraProvider.hal new file mode 100644 index 0000000000000000000000000000000000000000..c9d52ee21cef702e765e72d7520982d25719f61e --- /dev/null +++ b/camera/provider/2.7/ICameraProvider.hal @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.camera.provider@2.7; + +import @2.6::ICameraProvider; +import android.hardware.camera.common@1.0::Status; + +/** + * Camera provider HAL + * + * Adds support for the isConcurrentStreamCombinationSupported() with + * ICameraDevice@3.7::StreamConfiguration. + */ +interface ICameraProvider extends @2.6::ICameraProvider { + /** + * isConcurrentStreamCombinationSupported_2_7: + * + * Identical to @2.6::isConcurrentStreamCombinationSupported except that + * this function takes a vector of @3.7::StreamConfiguration. + * + * @param configs a vector of camera ids and their corresponding stream + * configurations that need to be queried for support. + * + * @return status Status code for the operation, one of: + * OK: + * On successful stream combination query. + * METHOD_NOT_SUPPORTED: + * The camera provider does not support stream combination query. + * INTERNAL_ERROR: + * The stream combination query cannot complete due to internal + * error. + * @return true in case the stream combination is supported, false otherwise. + * + */ + isConcurrentStreamCombinationSupported_2_7(vec configs) + generates (Status status, bool queryStatus); +}; diff --git a/camera/provider/2.7/types.hal b/camera/provider/2.7/types.hal new file mode 100644 index 0000000000000000000000000000000000000000..363e894ed384ef6e2d536625334a3a73dddb2ca7 --- /dev/null +++ b/camera/provider/2.7/types.hal @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.camera.provider@2.7; + +import android.hardware.camera.device@3.7::StreamConfiguration; + +/** + * CameraIdAndStreamCombination: + * + * This is identical to @2.6::CameraIdAndStreamCombination except that + * streamConfiguration is of version @3.7. + */ +struct CameraIdAndStreamCombination { + string cameraId; + @3.7::StreamConfiguration streamConfiguration; +}; diff --git a/cas/1.0/default/Android.bp b/cas/1.0/default/Android.bp index e8b1a069e0ede41469cdc45b1bf8ddda69ffcef0..fc5b3b43618ae2fd3d77a65dc87282dab6357286 100644 --- a/cas/1.0/default/Android.bp +++ b/cas/1.0/default/Android.bp @@ -21,6 +21,8 @@ cc_defaults { "TypeConvert.cpp", ], + compile_multilib: "prefer32", + shared_libs: [ "android.hardware.cas@1.0", "android.hardware.cas.native@1.0", diff --git a/cas/1.0/default/FactoryLoader.h b/cas/1.0/default/FactoryLoader.h index 18c2186dcbecbddc8f862a6bb9552d9f5dbabbb9..45e515afbfcae9453a85baf275f02e7879c26884 100644 --- a/cas/1.0/default/FactoryLoader.h +++ b/cas/1.0/default/FactoryLoader.h @@ -92,7 +92,12 @@ bool FactoryLoader::findFactoryForScheme( } // no luck, have to search +#ifdef __LP64__ + String8 dirPath("/vendor/lib64/mediacas"); +#else String8 dirPath("/vendor/lib/mediacas"); +#endif + DIR* pDir = opendir(dirPath.string()); if (pDir == NULL) { @@ -127,7 +132,12 @@ bool FactoryLoader::enumeratePlugins( results->clear(); +#ifdef __LP64__ + String8 dirPath("/vendor/lib64/mediacas"); +#else String8 dirPath("/vendor/lib/mediacas"); +#endif + DIR* pDir = opendir(dirPath.string()); if (pDir == NULL) { diff --git a/cas/1.0/vts/functional/Android.bp b/cas/1.0/vts/functional/Android.bp index fbfb7a7d3e5c26eb93a1e8a02b63bf3a8820b633..6d06cabfc32d2191bd40a0195fbb0fd125f3beec 100644 --- a/cas/1.0/vts/functional/Android.bp +++ b/cas/1.0/vts/functional/Android.bp @@ -29,6 +29,8 @@ cc_test { srcs: ["VtsHalCasV1_0TargetTest.cpp"], static_libs: [ "android.hardware.cas@1.0", + "android.hardware.cas@1.1", + "android.hardware.cas@1.2", "android.hardware.cas.native@1.0", "android.hidl.allocator@1.0", "android.hidl.memory@1.0", diff --git a/cas/1.0/vts/functional/VtsHalCasV1_0TargetTest.cpp b/cas/1.0/vts/functional/VtsHalCasV1_0TargetTest.cpp index 0f16de5e90150b3f44a6ce0f7c46b2e441298d7a..a1d59303865d9773b9abbb6d1b1ada9c1f9daa73 100644 --- a/cas/1.0/vts/functional/VtsHalCasV1_0TargetTest.cpp +++ b/cas/1.0/vts/functional/VtsHalCasV1_0TargetTest.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -212,6 +213,10 @@ void MediaCasListener::testEventEcho(sp& mediaCas, int32_t& event, int32_t class MediaCasHidlTest : public testing::TestWithParam { public: virtual void SetUp() override { + if (android::hardware::cas::V1_2::IMediaCasService::getService(GetParam()) == nullptr) { + ALOGI("Descrambler is need to be tested before cas@1.2."); + mIsTestDescrambler = true; + } mService = IMediaCasService::getService(GetParam()); ASSERT_NE(mService, nullptr); } @@ -226,6 +231,7 @@ class MediaCasHidlTest : public testing::TestWithParam { sp mMediaCas; sp mDescramblerBase; sp mCasListener; + bool mIsTestDescrambler = false; typedef struct _OobInputTestParams { const SubSample* subSamples; uint32_t numSubSamples; @@ -250,12 +256,19 @@ class MediaCasHidlTest : public testing::TestWithParam { ::testing::AssertionResult MediaCasHidlTest::createCasPlugin(int32_t caSystemId) { auto status = mService->isSystemIdSupported(caSystemId); + bool skipDescrambler = false; if (!status.isOk() || !status) { return ::testing::AssertionFailure(); } status = mService->isDescramblerSupported(caSystemId); if (!status.isOk() || !status) { - return ::testing::AssertionFailure(); + if (mIsTestDescrambler) { + return ::testing::AssertionFailure(); + } else { + ALOGI("Skip Descrambler test since it's not required in cas@1.2."); + mDescramblerBase = nullptr; + skipDescrambler = true; + } } mCasListener = new MediaCasListener(); @@ -268,10 +281,15 @@ class MediaCasHidlTest : public testing::TestWithParam { return ::testing::AssertionFailure(); } + if (skipDescrambler) { + return ::testing::AssertionSuccess(); + } + auto descramblerStatus = mService->createDescrambler(caSystemId); if (!descramblerStatus.isOk()) { return ::testing::AssertionFailure(); } + mDescramblerBase = descramblerStatus; return ::testing::AssertionResult(mDescramblerBase != nullptr); } @@ -494,14 +512,15 @@ TEST_P(MediaCasHidlTest, TestClearKeyApis) { 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); + if (mDescramblerBase != nullptr) { + returnStatus = mDescramblerBase->setMediaCasSession(sessionId); + EXPECT_TRUE(returnStatus.isOk()); + EXPECT_EQ(Status::OK, returnStatus); + + returnStatus = mDescramblerBase->setMediaCasSession(streamSessionId); + EXPECT_TRUE(returnStatus.isOk()); + EXPECT_EQ(Status::OK, returnStatus); + } hidl_vec hidlNullPtr; hidlNullPtr.setToExternal(static_cast(nullptr), 0); @@ -543,29 +562,32 @@ TEST_P(MediaCasHidlTest, TestClearKeyApis) { EXPECT_TRUE(returnStatus.isOk()); EXPECT_EQ(Status::OK, returnStatus); - EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent("video/avc")); + if (mDescramblerBase != nullptr) { + EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent("video/avc")); - sp descrambler; - descrambler = IDescrambler::castFrom(mDescramblerBase); - ASSERT_NE(descrambler, nullptr); + sp descrambler; + descrambler = IDescrambler::castFrom(mDescramblerBase); + ASSERT_NE(descrambler, nullptr); - Status descrambleStatus = Status::OK; - sp dataMemory; + Status descrambleStatus = Status::OK; + sp dataMemory; - ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory)); - EXPECT_EQ(Status::OK, descrambleStatus); + ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory)); + EXPECT_EQ(Status::OK, descrambleStatus); - ASSERT_NE(nullptr, dataMemory.get()); - uint8_t* opBuffer = static_cast(static_cast(dataMemory->unsecurePointer())); + ASSERT_NE(nullptr, dataMemory.get()); + uint8_t* opBuffer = + static_cast(static_cast(dataMemory->unsecurePointer())); - int compareResult = - memcmp(static_cast(opBuffer), static_cast(kOutRefBinaryBuffer), - sizeof(kOutRefBinaryBuffer)); - EXPECT_EQ(0, compareResult); + int compareResult = + memcmp(static_cast(opBuffer), + static_cast(kOutRefBinaryBuffer), sizeof(kOutRefBinaryBuffer)); + EXPECT_EQ(0, compareResult); - returnStatus = mDescramblerBase->release(); - EXPECT_TRUE(returnStatus.isOk()); - EXPECT_EQ(Status::OK, returnStatus); + returnStatus = mDescramblerBase->release(); + EXPECT_TRUE(returnStatus.isOk()); + EXPECT_EQ(Status::OK, returnStatus); + } returnStatus = mMediaCas->release(); EXPECT_TRUE(returnStatus.isOk()); @@ -590,13 +612,15 @@ TEST_P(MediaCasHidlTest, TestClearKeySessionClosedAfterRelease) { 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); + if (mDescramblerBase != nullptr) { + 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); + returnStatus = mDescramblerBase->setMediaCasSession(streamSessionId); + EXPECT_TRUE(returnStatus.isOk()); + EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, returnStatus); + } } TEST_P(MediaCasHidlTest, TestClearKeyErrors) { @@ -654,38 +678,40 @@ TEST_P(MediaCasHidlTest, TestClearKeyErrors) { 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); + if (mDescramblerBase != nullptr) { + /* + * 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 descrambler; - descrambler = IDescrambler::castFrom(mDescramblerBase); - ASSERT_NE(descrambler, nullptr); + // descramble should fail without a valid session + sp descrambler; + descrambler = IDescrambler::castFrom(mDescramblerBase); + ASSERT_NE(descrambler, nullptr); - Status descrambleStatus = Status::OK; - sp dataMemory; + Status descrambleStatus = Status::OK; + sp dataMemory; - ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory)); - EXPECT_EQ(Status::ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED, descrambleStatus); + 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); + // 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); + 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 empty mime + EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent("")); - // Verify that requiresSecureDecoderComponent handles invalid mime - EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent("bad")); + // Verify that requiresSecureDecoderComponent handles invalid mime + EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent("bad")); + } } TEST_P(MediaCasHidlTest, TestClearKeyOobFails) { @@ -700,9 +726,11 @@ TEST_P(MediaCasHidlTest, TestClearKeyOobFails) { std::vector sessionId; ASSERT_TRUE(openCasSession(&sessionId)); - returnStatus = mDescramblerBase->setMediaCasSession(sessionId); - EXPECT_TRUE(returnStatus.isOk()); - EXPECT_EQ(Status::OK, returnStatus); + if (mDescramblerBase != nullptr) { + returnStatus = mDescramblerBase->setMediaCasSession(sessionId); + EXPECT_TRUE(returnStatus.isOk()); + EXPECT_EQ(Status::OK, returnStatus); + } hidl_vec hidlEcm; hidlEcm.setToExternal(const_cast(kEcmBinaryBuffer), sizeof(kEcmBinaryBuffer)); @@ -710,126 +738,104 @@ TEST_P(MediaCasHidlTest, TestClearKeyOobFails) { EXPECT_TRUE(returnStatus.isOk()); EXPECT_EQ(Status::OK, returnStatus); - sp descrambler = IDescrambler::castFrom(mDescramblerBase); - ASSERT_NE(nullptr, descrambler.get()); - - Status descrambleStatus = Status::OK; - - // test invalid src buffer offset - ASSERT_TRUE(descrambleTestOobInput( - descrambler, - &descrambleStatus, - { - .subSamples = kSubSamples, - .numSubSamples = sizeof(kSubSamples)/sizeof(SubSample), - .imemSizeActual = sizeof(kInBinaryBuffer), - .imemOffset = 0xcccccc, - .imemSize = sizeof(kInBinaryBuffer), - .srcOffset = 0, - .dstOffset = 0 - })); - EXPECT_EQ(Status::BAD_VALUE, descrambleStatus); - - // test invalid src buffer size - ASSERT_TRUE(descrambleTestOobInput( - descrambler, - &descrambleStatus, - { - .subSamples = kSubSamples, - .numSubSamples = sizeof(kSubSamples)/sizeof(SubSample), - .imemSizeActual = sizeof(kInBinaryBuffer), - .imemOffset = 0, - .imemSize = 0xcccccc, - .srcOffset = 0, - .dstOffset = 0 - })); - EXPECT_EQ(Status::BAD_VALUE, descrambleStatus); - - // test invalid src buffer size - ASSERT_TRUE(descrambleTestOobInput( - descrambler, - &descrambleStatus, - { - .subSamples = kSubSamples, - .numSubSamples = sizeof(kSubSamples)/sizeof(SubSample), - .imemSizeActual = sizeof(kInBinaryBuffer), - .imemOffset = 1, - .imemSize = (uint64_t)-1, - .srcOffset = 0, - .dstOffset = 0 - })); - EXPECT_EQ(Status::BAD_VALUE, descrambleStatus); - - // test invalid srcOffset - ASSERT_TRUE(descrambleTestOobInput( - descrambler, - &descrambleStatus, - { - .subSamples = kSubSamples, - .numSubSamples = sizeof(kSubSamples)/sizeof(SubSample), - .imemSizeActual = sizeof(kInBinaryBuffer), - .imemOffset = 0, - .imemSize = sizeof(kInBinaryBuffer), - .srcOffset = 0xcccccc, - .dstOffset = 0 - })); - EXPECT_EQ(Status::BAD_VALUE, descrambleStatus); - - // test invalid dstOffset - ASSERT_TRUE(descrambleTestOobInput( - descrambler, - &descrambleStatus, - { - .subSamples = kSubSamples, - .numSubSamples = sizeof(kSubSamples)/sizeof(SubSample), - .imemSizeActual = sizeof(kInBinaryBuffer), - .imemOffset = 0, - .imemSize = sizeof(kInBinaryBuffer), - .srcOffset = 0, - .dstOffset = 0xcccccc - })); - EXPECT_EQ(Status::BAD_VALUE, descrambleStatus); - - // test detection of oob subsample sizes - const SubSample invalidSubSamples1[] = - {{162, 0}, {0, 184}, {0, 0xdddddd}}; - - ASSERT_TRUE(descrambleTestOobInput( - descrambler, - &descrambleStatus, - { - .subSamples = invalidSubSamples1, - .numSubSamples = sizeof(invalidSubSamples1)/sizeof(SubSample), - .imemSizeActual = sizeof(kInBinaryBuffer), - .imemOffset = 0, - .imemSize = sizeof(kInBinaryBuffer), - .srcOffset = 0, - .dstOffset = 0 - })); - EXPECT_EQ(Status::BAD_VALUE, descrambleStatus); - - // test detection of overflowing subsample sizes - const SubSample invalidSubSamples2[] = - {{162, 0}, {0, 184}, {2, (uint32_t)-1}}; - - ASSERT_TRUE(descrambleTestOobInput( - descrambler, - &descrambleStatus, - { - .subSamples = invalidSubSamples2, - .numSubSamples = sizeof(invalidSubSamples2)/sizeof(SubSample), - .imemSizeActual = sizeof(kInBinaryBuffer), - .imemOffset = 0, - .imemSize = sizeof(kInBinaryBuffer), - .srcOffset = 0, - .dstOffset = 0 - })); - EXPECT_EQ(Status::BAD_VALUE, descrambleStatus); - - returnStatus = mDescramblerBase->release(); - EXPECT_TRUE(returnStatus.isOk()); - EXPECT_EQ(Status::OK, returnStatus); - + if (mDescramblerBase != nullptr) { + sp descrambler = IDescrambler::castFrom(mDescramblerBase); + ASSERT_NE(nullptr, descrambler.get()); + + Status descrambleStatus = Status::OK; + + // test invalid src buffer offset + ASSERT_TRUE( + descrambleTestOobInput(descrambler, &descrambleStatus, + {.subSamples = kSubSamples, + .numSubSamples = sizeof(kSubSamples) / sizeof(SubSample), + .imemSizeActual = sizeof(kInBinaryBuffer), + .imemOffset = 0xcccccc, + .imemSize = sizeof(kInBinaryBuffer), + .srcOffset = 0, + .dstOffset = 0})); + EXPECT_EQ(Status::BAD_VALUE, descrambleStatus); + + // test invalid src buffer size + ASSERT_TRUE( + descrambleTestOobInput(descrambler, &descrambleStatus, + {.subSamples = kSubSamples, + .numSubSamples = sizeof(kSubSamples) / sizeof(SubSample), + .imemSizeActual = sizeof(kInBinaryBuffer), + .imemOffset = 0, + .imemSize = 0xcccccc, + .srcOffset = 0, + .dstOffset = 0})); + EXPECT_EQ(Status::BAD_VALUE, descrambleStatus); + + // test invalid src buffer size + ASSERT_TRUE( + descrambleTestOobInput(descrambler, &descrambleStatus, + {.subSamples = kSubSamples, + .numSubSamples = sizeof(kSubSamples) / sizeof(SubSample), + .imemSizeActual = sizeof(kInBinaryBuffer), + .imemOffset = 1, + .imemSize = (uint64_t)-1, + .srcOffset = 0, + .dstOffset = 0})); + EXPECT_EQ(Status::BAD_VALUE, descrambleStatus); + + // test invalid srcOffset + ASSERT_TRUE( + descrambleTestOobInput(descrambler, &descrambleStatus, + {.subSamples = kSubSamples, + .numSubSamples = sizeof(kSubSamples) / sizeof(SubSample), + .imemSizeActual = sizeof(kInBinaryBuffer), + .imemOffset = 0, + .imemSize = sizeof(kInBinaryBuffer), + .srcOffset = 0xcccccc, + .dstOffset = 0})); + EXPECT_EQ(Status::BAD_VALUE, descrambleStatus); + + // test invalid dstOffset + ASSERT_TRUE( + descrambleTestOobInput(descrambler, &descrambleStatus, + {.subSamples = kSubSamples, + .numSubSamples = sizeof(kSubSamples) / sizeof(SubSample), + .imemSizeActual = sizeof(kInBinaryBuffer), + .imemOffset = 0, + .imemSize = sizeof(kInBinaryBuffer), + .srcOffset = 0, + .dstOffset = 0xcccccc})); + EXPECT_EQ(Status::BAD_VALUE, descrambleStatus); + + // test detection of oob subsample sizes + const SubSample invalidSubSamples1[] = {{162, 0}, {0, 184}, {0, 0xdddddd}}; + + ASSERT_TRUE(descrambleTestOobInput( + descrambler, &descrambleStatus, + {.subSamples = invalidSubSamples1, + .numSubSamples = sizeof(invalidSubSamples1) / sizeof(SubSample), + .imemSizeActual = sizeof(kInBinaryBuffer), + .imemOffset = 0, + .imemSize = sizeof(kInBinaryBuffer), + .srcOffset = 0, + .dstOffset = 0})); + EXPECT_EQ(Status::BAD_VALUE, descrambleStatus); + + // test detection of overflowing subsample sizes + const SubSample invalidSubSamples2[] = {{162, 0}, {0, 184}, {2, (uint32_t)-1}}; + + ASSERT_TRUE(descrambleTestOobInput( + descrambler, &descrambleStatus, + {.subSamples = invalidSubSamples2, + .numSubSamples = sizeof(invalidSubSamples2) / sizeof(SubSample), + .imemSizeActual = sizeof(kInBinaryBuffer), + .imemOffset = 0, + .imemSize = sizeof(kInBinaryBuffer), + .srcOffset = 0, + .dstOffset = 0})); + EXPECT_EQ(Status::BAD_VALUE, descrambleStatus); + + returnStatus = mDescramblerBase->release(); + EXPECT_TRUE(returnStatus.isOk()); + EXPECT_EQ(Status::OK, returnStatus); + } returnStatus = mMediaCas->release(); EXPECT_TRUE(returnStatus.isOk()); EXPECT_EQ(Status::OK, returnStatus); @@ -837,6 +843,7 @@ TEST_P(MediaCasHidlTest, TestClearKeyOobFails) { } // anonymous namespace +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MediaCasHidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, MediaCasHidlTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames(IMediaCasService::descriptor)), diff --git a/cas/1.1/default/Android.bp b/cas/1.1/default/Android.bp index f60357398a66442423783e83972ef74d48d976f9..2cfc0b90fb79cd214be9e716339f21db91b34cfc 100644 --- a/cas/1.1/default/Android.bp +++ b/cas/1.1/default/Android.bp @@ -21,6 +21,8 @@ cc_defaults { "TypeConvert.cpp", ], + compile_multilib: "prefer32", + shared_libs: [ "android.hardware.cas@1.0", "android.hardware.cas@1.1", diff --git a/cas/1.1/default/FactoryLoader.h b/cas/1.1/default/FactoryLoader.h index c4a48e2852577a863b40c23288145d437664e08b..121f90c333b12d7aafdff421a2a9e0d33ace2837 100644 --- a/cas/1.1/default/FactoryLoader.h +++ b/cas/1.1/default/FactoryLoader.h @@ -85,7 +85,11 @@ bool FactoryLoader::findFactoryForScheme(int32_t CA_system_id, sp::enumeratePlugins(vector* results results->clear(); +#ifdef __LP64__ + String8 dirPath("/vendor/lib64/mediacas"); +#else String8 dirPath("/vendor/lib/mediacas"); +#endif DIR* pDir = opendir(dirPath.string()); if (pDir == NULL) { diff --git a/cas/1.1/vts/functional/Android.bp b/cas/1.1/vts/functional/Android.bp index 48731577f38454b92303f862a9ea6dad07338fc1..a5985541230e4ce443cd818619168c31ee36c7a4 100644 --- a/cas/1.1/vts/functional/Android.bp +++ b/cas/1.1/vts/functional/Android.bp @@ -30,6 +30,7 @@ cc_test { static_libs: [ "android.hardware.cas@1.0", "android.hardware.cas@1.1", + "android.hardware.cas@1.2", "android.hardware.cas.native@1.0", "android.hidl.allocator@1.0", "android.hidl.memory@1.0", diff --git a/cas/1.1/vts/functional/VtsHalCasV1_1TargetTest.cpp b/cas/1.1/vts/functional/VtsHalCasV1_1TargetTest.cpp index 1b5797b8454703f0859bf6edb4a3ed9b11243b17..42d70cfeb9419a685d0ca9a256f48c68fd0bf6c3 100644 --- a/cas/1.1/vts/functional/VtsHalCasV1_1TargetTest.cpp +++ b/cas/1.1/vts/functional/VtsHalCasV1_1TargetTest.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -255,6 +256,10 @@ void MediaCasListener::testSessionEventEcho(sp& mediaCas, const hidl_vec { public: virtual void SetUp() override { + if (android::hardware::cas::V1_2::IMediaCasService::getService(GetParam()) == nullptr) { + ALOGI("Descrambler is need to be tested before cas@1.2."); + mIsTestDescrambler = true; + } mService = IMediaCasService::getService(GetParam()); ASSERT_NE(mService, nullptr); } @@ -269,6 +274,7 @@ class MediaCasHidlTest : public testing::TestWithParam { sp mMediaCas; sp mDescramblerBase; sp mCasListener; + bool mIsTestDescrambler = false; typedef struct _OobInputTestParams { const SubSample* subSamples; uint32_t numSubSamples; @@ -291,12 +297,19 @@ class MediaCasHidlTest : public testing::TestWithParam { ::testing::AssertionResult MediaCasHidlTest::createCasPlugin(int32_t caSystemId) { auto status = mService->isSystemIdSupported(caSystemId); + bool skipDescrambler = false; if (!status.isOk() || !status) { return ::testing::AssertionFailure(); } status = mService->isDescramblerSupported(caSystemId); if (!status.isOk() || !status) { - return ::testing::AssertionFailure(); + if (mIsTestDescrambler) { + return ::testing::AssertionFailure(); + } else { + ALOGI("Skip Descrambler test since it's not required in cas@1.2."); + mDescramblerBase = nullptr; + skipDescrambler = true; + } } mCasListener = new MediaCasListener(); @@ -309,10 +322,15 @@ class MediaCasHidlTest : public testing::TestWithParam { return ::testing::AssertionFailure(); } + if (skipDescrambler) { + return ::testing::AssertionSuccess(); + } + auto descramblerStatus = mService->createDescrambler(caSystemId); if (!descramblerStatus.isOk()) { return ::testing::AssertionFailure(); } + mDescramblerBase = descramblerStatus; return ::testing::AssertionResult(mDescramblerBase != nullptr); } @@ -468,13 +486,15 @@ TEST_P(MediaCasHidlTest, TestClearKeyApisWithSession) { EXPECT_TRUE(returnStatus.isOk()); EXPECT_EQ(Status::OK, returnStatus); - returnStatus = mDescramblerBase->setMediaCasSession(sessionId); - EXPECT_TRUE(returnStatus.isOk()); - EXPECT_EQ(Status::OK, returnStatus); + if (mDescramblerBase != nullptr) { + 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); + returnStatus = mDescramblerBase->setMediaCasSession(streamSessionId); + EXPECT_TRUE(returnStatus.isOk()); + EXPECT_EQ(Status::OK, returnStatus); + } hidl_vec hidlNullPtr; hidlNullPtr.setToExternal(static_cast(nullptr), 0); @@ -518,29 +538,31 @@ TEST_P(MediaCasHidlTest, TestClearKeyApisWithSession) { EXPECT_TRUE(returnStatus.isOk()); EXPECT_EQ(Status::OK, returnStatus); - EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent("video/avc")); + if (mDescramblerBase != nullptr) { + EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent("video/avc")); - sp descrambler; - descrambler = IDescrambler::castFrom(mDescramblerBase); - ASSERT_NE(descrambler, nullptr); + sp descrambler; + descrambler = IDescrambler::castFrom(mDescramblerBase); + ASSERT_NE(descrambler, nullptr); - Status descrambleStatus = Status::OK; - sp dataMemory; + Status descrambleStatus = Status::OK; + sp dataMemory; - ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory)); - EXPECT_EQ(Status::OK, descrambleStatus); + ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory)); + EXPECT_EQ(Status::OK, descrambleStatus); - ASSERT_NE(nullptr, dataMemory.get()); - uint8_t* opBuffer = static_cast(static_cast(dataMemory->unsecurePointer())); + ASSERT_NE(nullptr, dataMemory.get()); + uint8_t* opBuffer = static_cast(static_cast(dataMemory->unsecurePointer())); - int compareResult = - memcmp(static_cast(opBuffer), - static_cast(kOutRefBinaryBuffer), sizeof(kOutRefBinaryBuffer)); - EXPECT_EQ(0, compareResult); + int compareResult = + memcmp(static_cast(opBuffer), + static_cast(kOutRefBinaryBuffer), sizeof(kOutRefBinaryBuffer)); + EXPECT_EQ(0, compareResult); - returnStatus = mDescramblerBase->release(); - EXPECT_TRUE(returnStatus.isOk()); - EXPECT_EQ(Status::OK, returnStatus); + returnStatus = mDescramblerBase->release(); + EXPECT_TRUE(returnStatus.isOk()); + EXPECT_EQ(Status::OK, returnStatus); + } returnStatus = mMediaCas->release(); EXPECT_TRUE(returnStatus.isOk()); @@ -549,6 +571,7 @@ TEST_P(MediaCasHidlTest, TestClearKeyApisWithSession) { } // anonymous namespace +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MediaCasHidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, MediaCasHidlTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames(IMediaCasService::descriptor)), diff --git a/cas/1.2/default/Android.bp b/cas/1.2/default/Android.bp index f4d68ed67525d563abfb5c1cb83bf60ad2ad0421..38561fd3e7301ac6f2942727908c4ea8401771e8 100644 --- a/cas/1.2/default/Android.bp +++ b/cas/1.2/default/Android.bp @@ -21,6 +21,8 @@ cc_defaults { "TypeConvert.cpp", ], + compile_multilib: "prefer32", + shared_libs: [ "android.hardware.cas@1.0", "android.hardware.cas@1.1", diff --git a/cas/1.2/default/FactoryLoader.h b/cas/1.2/default/FactoryLoader.h index 7403f86ac95eb666a4b315d1daede7fd177208e8..a374b3189181a86c65212cdee9e51a4441dca543 100644 --- a/cas/1.2/default/FactoryLoader.h +++ b/cas/1.2/default/FactoryLoader.h @@ -85,7 +85,11 @@ bool FactoryLoader::findFactoryForScheme(int32_t CA_system_id, sp::enumeratePlugins(vector* results results->clear(); +#ifdef __LP64__ + String8 dirPath("/vendor/lib64/mediacas"); +#else String8 dirPath("/vendor/lib/mediacas"); +#endif DIR* pDir = opendir(dirPath.string()); if (pDir == NULL) { diff --git a/cas/1.2/vts/functional/VtsHalCasV1_2TargetTest.cpp b/cas/1.2/vts/functional/VtsHalCasV1_2TargetTest.cpp index 58e0f2e0a80af5673e9df6c2a76f4bccb029e7dd..0d75f5b81290c81c485918c9975a394190b4a6f7 100644 --- a/cas/1.2/vts/functional/VtsHalCasV1_2TargetTest.cpp +++ b/cas/1.2/vts/functional/VtsHalCasV1_2TargetTest.cpp @@ -335,12 +335,15 @@ class MediaCasHidlTest : public testing::TestWithParam { ::testing::AssertionResult MediaCasHidlTest::createCasPlugin(int32_t caSystemId) { auto status = mService->isSystemIdSupported(caSystemId); + bool skipDescrambler = false; if (!status.isOk() || !status) { return ::testing::AssertionFailure(); } status = mService->isDescramblerSupported(caSystemId); if (!status.isOk() || !status) { - return ::testing::AssertionFailure(); + ALOGI("Skip Descrambler test since it's not required in cas@1.2."); + mDescramblerBase = nullptr; + skipDescrambler = true; } mCasListener = new MediaCasListener(); @@ -353,10 +356,15 @@ class MediaCasHidlTest : public testing::TestWithParam { return ::testing::AssertionFailure(); } + if (skipDescrambler) { + return ::testing::AssertionSuccess(); + } + auto descramblerStatus = mService->createDescrambler(caSystemId); if (!descramblerStatus.isOk()) { return ::testing::AssertionFailure(); } + mDescramblerBase = descramblerStatus; return ::testing::AssertionResult(mDescramblerBase != nullptr); } @@ -512,14 +520,15 @@ TEST_P(MediaCasHidlTest, TestClearKeyApisWithSession) { 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); + if (mDescramblerBase != nullptr) { + returnStatus = mDescramblerBase->setMediaCasSession(sessionId); + EXPECT_TRUE(returnStatus.isOk()); + EXPECT_EQ(Status::OK, returnStatus); + returnStatus = mDescramblerBase->setMediaCasSession(streamSessionId); + EXPECT_TRUE(returnStatus.isOk()); + EXPECT_EQ(Status::OK, returnStatus); + } hidl_vec hidlNullPtr; hidlNullPtr.setToExternal(static_cast(nullptr), 0); returnStatus = mMediaCas->refreshEntitlements(3, hidlNullPtr); @@ -566,29 +575,31 @@ TEST_P(MediaCasHidlTest, TestClearKeyApisWithSession) { EXPECT_TRUE(returnStatus.isOk()); EXPECT_EQ(Status::OK, returnStatus); - EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent("video/avc")); + if (mDescramblerBase != nullptr) { + EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent("video/avc")); - sp descrambler; - descrambler = IDescrambler::castFrom(mDescramblerBase); - ASSERT_NE(descrambler, nullptr); + sp descrambler; + descrambler = IDescrambler::castFrom(mDescramblerBase); + ASSERT_NE(descrambler, nullptr); - Status descrambleStatus = Status::OK; - sp dataMemory; + Status descrambleStatus = Status::OK; + sp dataMemory; - ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory)); - EXPECT_EQ(Status::OK, descrambleStatus); + ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory)); + EXPECT_EQ(Status::OK, descrambleStatus); - ASSERT_NE(nullptr, dataMemory.get()); - uint8_t* opBuffer = static_cast(static_cast(dataMemory->unsecurePointer())); + ASSERT_NE(nullptr, dataMemory.get()); + uint8_t* opBuffer = static_cast(static_cast(dataMemory->unsecurePointer())); - int compareResult = - memcmp(static_cast(opBuffer), - static_cast(kOutRefBinaryBuffer), sizeof(kOutRefBinaryBuffer)); - EXPECT_EQ(0, compareResult); + int compareResult = + memcmp(static_cast(opBuffer), + static_cast(kOutRefBinaryBuffer), sizeof(kOutRefBinaryBuffer)); + EXPECT_EQ(0, compareResult); - returnStatus = mDescramblerBase->release(); - EXPECT_TRUE(returnStatus.isOk()); - EXPECT_EQ(Status::OK, returnStatus); + returnStatus = mDescramblerBase->release(); + EXPECT_TRUE(returnStatus.isOk()); + EXPECT_EQ(Status::OK, returnStatus); + } returnStatus = mMediaCas->release(); EXPECT_TRUE(returnStatus.isOk()); @@ -597,6 +608,7 @@ TEST_P(MediaCasHidlTest, TestClearKeyApisWithSession) { } // anonymous namespace +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MediaCasHidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, MediaCasHidlTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames(IMediaCasService::descriptor)), diff --git a/common/aidl/Android.bp b/common/aidl/Android.bp index 912bfdc1f834896b8dd40da30d44c1098ed8989c..028c923de6f9cb1c965533dfbdbfa5eb68370c6b 100644 --- a/common/aidl/Android.bp +++ b/common/aidl/Android.bp @@ -36,5 +36,8 @@ aidl_interface { min_sdk_version: "29", }, }, - versions: ["1"], + versions: [ + "1", + "2", + ], } diff --git a/common/aidl/aidl_api/android.hardware.common/2/.hash b/common/aidl/aidl_api/android.hardware.common/2/.hash new file mode 100644 index 0000000000000000000000000000000000000000..5ef5e089a718b570c709d6db161e9b11706572ca --- /dev/null +++ b/common/aidl/aidl_api/android.hardware.common/2/.hash @@ -0,0 +1 @@ +c32ddfdeb69c6e4a8a45519e6f9a39c4b66fd99f diff --git a/common/aidl/aidl_api/android.hardware.common/2/android/hardware/common/Ashmem.aidl b/common/aidl/aidl_api/android.hardware.common/2/android/hardware/common/Ashmem.aidl new file mode 100644 index 0000000000000000000000000000000000000000..a4380315c9a9c71c233fb71be949e4f51019f568 --- /dev/null +++ b/common/aidl/aidl_api/android.hardware.common/2/android/hardware/common/Ashmem.aidl @@ -0,0 +1,39 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.common; +@VintfStability +parcelable Ashmem { + ParcelFileDescriptor fd; + long size; +} diff --git a/common/aidl/aidl_api/android.hardware.common/2/android/hardware/common/MappableFile.aidl b/common/aidl/aidl_api/android.hardware.common/2/android/hardware/common/MappableFile.aidl new file mode 100644 index 0000000000000000000000000000000000000000..394ea8ff077ff5d4fa73282d5abfea5c762ae3c2 --- /dev/null +++ b/common/aidl/aidl_api/android.hardware.common/2/android/hardware/common/MappableFile.aidl @@ -0,0 +1,41 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.common; +@VintfStability +parcelable MappableFile { + long length; + int prot; + ParcelFileDescriptor fd; + long offset; +} diff --git a/common/aidl/aidl_api/android.hardware.common/2/android/hardware/common/NativeHandle.aidl b/common/aidl/aidl_api/android.hardware.common/2/android/hardware/common/NativeHandle.aidl new file mode 100644 index 0000000000000000000000000000000000000000..2ed5c0b22d3a6228902e47c1b4b8bd76c9223f62 --- /dev/null +++ b/common/aidl/aidl_api/android.hardware.common/2/android/hardware/common/NativeHandle.aidl @@ -0,0 +1,39 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.common; +@VintfStability +parcelable NativeHandle { + ParcelFileDescriptor[] fds; + int[] ints; +} diff --git a/common/fmq/aidl/Android.bp b/common/fmq/aidl/Android.bp index 570d02d239f426132fc1ce0772aeabf7f7f47954..376ac972ea19daf70e36c2b8d1e38eac9d05c63c 100644 --- a/common/fmq/aidl/Android.bp +++ b/common/fmq/aidl/Android.bp @@ -31,4 +31,5 @@ aidl_interface { enabled: false, }, }, + versions: ["1"], } diff --git a/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/.hash b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/.hash new file mode 100644 index 0000000000000000000000000000000000000000..b88c5fcacbc7457f1eaf4289dec40f85b9096180 --- /dev/null +++ b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/.hash @@ -0,0 +1,2 @@ +12cf0ce8614557cc0efe73bdf011f5193f7a8653 +6a780550f6e6965d6969fd7964c3ca81b6b0ccdf diff --git a/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/android/hardware/common/fmq/GrantorDescriptor.aidl b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/android/hardware/common/fmq/GrantorDescriptor.aidl new file mode 100644 index 0000000000000000000000000000000000000000..0430c6e65c769f953977d955e96f37be3495a348 --- /dev/null +++ b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/android/hardware/common/fmq/GrantorDescriptor.aidl @@ -0,0 +1,41 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.common.fmq; +/* @hide */ +@VintfStability +parcelable GrantorDescriptor { + int fdIndex; + int offset; + long extent; +} diff --git a/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/android/hardware/common/fmq/MQDescriptor.aidl b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/android/hardware/common/fmq/MQDescriptor.aidl new file mode 100644 index 0000000000000000000000000000000000000000..ab3af0f5d0ab57d0f2f09697facfc0c932f0274c --- /dev/null +++ b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/android/hardware/common/fmq/MQDescriptor.aidl @@ -0,0 +1,42 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.common.fmq; +/* @hide */ +@VintfStability +parcelable MQDescriptor { + android.hardware.common.fmq.GrantorDescriptor[] grantors; + android.hardware.common.NativeHandle handle; + int quantum; + int flags; +} diff --git a/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/android/hardware/common/fmq/SynchronizedReadWrite.aidl b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/android/hardware/common/fmq/SynchronizedReadWrite.aidl new file mode 100644 index 0000000000000000000000000000000000000000..72bab1c6e26a794857a7f1b85f9d90fa5f97914e --- /dev/null +++ b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/android/hardware/common/fmq/SynchronizedReadWrite.aidl @@ -0,0 +1,39 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.common.fmq; +/* @hide */ +@VintfStability +enum SynchronizedReadWrite { + EMPTY = 0, +} diff --git a/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/android/hardware/common/fmq/UnsynchronizedWrite.aidl b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/android/hardware/common/fmq/UnsynchronizedWrite.aidl new file mode 100644 index 0000000000000000000000000000000000000000..f3086881cb915d6132192e908f982e1066743df4 --- /dev/null +++ b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/android/hardware/common/fmq/UnsynchronizedWrite.aidl @@ -0,0 +1,39 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.common.fmq; +/* @hide */ +@VintfStability +enum UnsynchronizedWrite { + EMPTY = 0, +} diff --git a/compatibility_matrices/compatibility_matrix.6.xml b/compatibility_matrices/compatibility_matrix.6.xml index 039ea846f0704531a8137685d23a6c3b07ef5be9..aee2c5164bd3c9f7e151670da5763a3175d43c05 100644 --- a/compatibility_matrices/compatibility_matrix.6.xml +++ b/compatibility_matrices/compatibility_matrix.6.xml @@ -41,10 +41,8 @@ default - + android.hardware.automotive.audiocontrol - 1.0 - 2.0 IAudioControl default @@ -103,14 +101,28 @@ default + + android.hardware.biometrics.face + + IFace + default + + android.hardware.biometrics.fingerprint - 2.1-2 + 2.1-3 IBiometricsFingerprint default + + android.hardware.biometrics.fingerprint + + IFingerprint + default + + android.hardware.bluetooth 1.0-1 @@ -153,7 +165,7 @@ android.hardware.camera.provider - 2.4-6 + 2.4-7 ICameraProvider [^/]+/[0-9]+ @@ -177,7 +189,7 @@ android.hardware.contexthub - 1.0-1 + 1.2 IContexthub default @@ -185,7 +197,7 @@ android.hardware.drm - 1.3 + 1.3-4 ICryptoFactory .* @@ -219,6 +231,13 @@ default + + android.hardware.gnss + + IGnss + default + + android.hardware.graphics.allocator @@ -340,7 +359,7 @@ android.hardware.media.c2 - 1.0-1 + 1.0-2 IComponentStore default[0-9]* @@ -400,7 +419,7 @@ android.hardware.power - 1 + 1-2 IPower default @@ -489,6 +508,7 @@ ISharedSecret default + strongbox @@ -502,7 +522,7 @@ android.hardware.soundtrigger - 2.0-3 + 2.3 ISoundTriggerHw default @@ -534,7 +554,7 @@ android.hardware.tv.cec - 1.0 + 1.0-1 IHdmiCec default @@ -550,7 +570,7 @@ android.hardware.tv.tuner - 1.0 + 1.0-1 ITuner default @@ -558,7 +578,7 @@ android.hardware.usb - 1.0-2 + 1.0-3 IUsb default @@ -566,7 +586,7 @@ android.hardware.usb.gadget - 1.0-1 + 1.0-2 IUsbGadget default @@ -574,11 +594,20 @@ android.hardware.vibrator + 1-2 IVibrator default + + android.hardware.vibrator + 1-2 + + IVibratorManager + default + + android.hardware.weaver 1.0 @@ -597,7 +626,7 @@ android.hardware.wifi - 1.3-4 + 1.3-5 IWifi default @@ -605,7 +634,7 @@ android.hardware.wifi.hostapd - 1.0-2 + 1.0-3 IHostapd default @@ -613,7 +642,7 @@ android.hardware.wifi.supplicant - 1.2-3 + 1.2-4 ISupplicant default diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml index 2c0bd17d53ee0b3a52fdf4a8f4a96228ace1e1dc..7fa586efdb8a574ea26d8bf9b7cc3a3c0148ba63 100644 --- a/compatibility_matrices/compatibility_matrix.current.xml +++ b/compatibility_matrices/compatibility_matrix.current.xml @@ -41,10 +41,8 @@ default - + android.hardware.automotive.audiocontrol - 1.0 - 2.0 IAudioControl default @@ -103,14 +101,28 @@ default + + android.hardware.biometrics.face + + IFace + default + + android.hardware.biometrics.fingerprint - 2.1-2 + 2.1-3 IBiometricsFingerprint default + + android.hardware.biometrics.fingerprint + + IFingerprint + default + + android.hardware.bluetooth 1.0-1 @@ -153,7 +165,7 @@ android.hardware.camera.provider - 2.4-6 + 2.4-7 ICameraProvider [^/]+/[0-9]+ @@ -177,7 +189,7 @@ android.hardware.contexthub - 1.0-1 + 1.2 IContexthub default @@ -185,7 +197,7 @@ android.hardware.drm - 1.3 + 1.3-4 ICryptoFactory .* @@ -219,6 +231,13 @@ default + + android.hardware.gnss + + IGnss + default + + android.hardware.graphics.allocator @@ -340,7 +359,7 @@ android.hardware.media.c2 - 1.0-1 + 1.0-2 IComponentStore default[0-9]* @@ -400,7 +419,7 @@ android.hardware.power - 1 + 1-2 IPower default @@ -557,6 +576,7 @@ ISharedSecret default + strongbox @@ -570,7 +590,7 @@ android.hardware.soundtrigger - 2.0-3 + 2.3 ISoundTriggerHw default @@ -602,7 +622,7 @@ android.hardware.tv.cec - 1.0 + 1.0-1 IHdmiCec default @@ -618,7 +638,7 @@ android.hardware.tv.tuner - 1.0 + 1.0-1 ITuner default @@ -626,7 +646,7 @@ android.hardware.usb - 1.0-2 + 1.0-3 IUsb default @@ -634,7 +654,7 @@ android.hardware.usb.gadget - 1.0-1 + 1.0-2 IUsbGadget default @@ -642,11 +662,20 @@ android.hardware.vibrator + 1-2 IVibrator default + + android.hardware.vibrator + 1-2 + + IVibratorManager + default + + android.hardware.weaver 1.0 @@ -665,7 +694,7 @@ android.hardware.wifi - 1.3-4 + 1.3-5 IWifi default @@ -673,7 +702,7 @@ android.hardware.wifi.hostapd - 1.0-2 + 1.0-3 IHostapd default @@ -689,7 +718,7 @@ android.hardware.wifi.supplicant - 1.2-3 + 1.2-4 ISupplicant default diff --git a/compatibility_matrices/exclude/fcm_exclude.cpp b/compatibility_matrices/exclude/fcm_exclude.cpp index c0b35d3c4c8934303cd8498bad17ffc8396d0cf9..d8c9170000144a89f640c60d77f0ee57bc326a54 100644 --- a/compatibility_matrices/exclude/fcm_exclude.cpp +++ b/compatibility_matrices/exclude/fcm_exclude.cpp @@ -51,6 +51,7 @@ bool ShouldCheckMissingHalsInFcm(const std::string& package) { "android.hardware.media.bufferpool@2.0", "android.hardware.radio.config@1.2", // AIDL + "android.hardware.biometrics.common", "android.hardware.common", "android.hardware.common.fmq", "android.hardware.graphics.common", diff --git a/contexthub/1.0/IContexthub.hal b/contexthub/1.0/IContexthub.hal index 8dccd6727661d9334f0f1b6500c6283d81a1bfee..950e0813269122bca8782737e61ca1f53081ef9d 100644 --- a/contexthub/1.0/IContexthub.hal +++ b/contexthub/1.0/IContexthub.hal @@ -41,7 +41,7 @@ interface IContexthub { * registration. * * @param hubId identifier for the hub - * callback an implementation of the IContextHubCallbacks + * @param callback an implementation of the IContextHubCallbacks * * @return result OK on success * BAD_VALUE if parameters are not sane @@ -53,7 +53,7 @@ interface IContexthub { * Send a message to a hub * * @param hubId identifier for hub to send message to - * msg message to be sent + * @param msg message to be sent * * @return result OK if successful, error code otherwise * BAD_VALUE if parameters are not sane @@ -77,9 +77,9 @@ interface IContexthub { * device. * * @param hubId identifer of the contextHub - * appBinary contains the binary representation of the nanoApp, plus + * @param appBinary contains the binary representation of the nanoApp, plus * metadata - * transactionId transactionId for this call + * @param transactionId transactionId for this call * * @return result OK if transation started * BAD_VALUE if parameters are not sane @@ -101,8 +101,8 @@ interface IContexthub { * Unloading a nanoapp must not take more than 5 seconds. * * @param hubId identifer of the contextHub - * appId appIdentifier returned by the HAL - * msg message to be sent + * @param appId appIdentifier returned by the HAL + * @param msg message to be sent * * @return result OK if transation started * BAD_VALUE if parameters are not sane @@ -122,8 +122,8 @@ interface IContexthub { * Enabling a nanoapp must not take more than 5 seconds. * * @param hubId identifer of the contextHub - * appId appIdentifier returned by the HAL - * msg message to be sent + * @param appId appIdentifier returned by the HAL + * @param msg message to be sent * * @return result OK if transation started * BAD_VALUE if parameters are not sane @@ -143,8 +143,8 @@ interface IContexthub { * Disabling a nanoapp must not take more than 5 seconds. * * @param hubId identifer of the contextHub - * appId appIdentifier returned by the HAL - * msg message to be sent + * @param appId appIdentifier returned by the HAL + * @param msg message to be sent * * @return result OK if transation started * BAD_VALUE if parameters are not sane diff --git a/contexthub/1.0/IContexthubCallback.hal b/contexthub/1.0/IContexthubCallback.hal index 264f84ca17081aeaa6d04c1bed91b3e294400cb2..70750f808be330d3eac907bc04fafb93b556b2a9 100644 --- a/contexthub/1.0/IContexthubCallback.hal +++ b/contexthub/1.0/IContexthubCallback.hal @@ -22,7 +22,7 @@ interface IContexthubCallback { * implementation to allow the HAL to send asynchronous messages back * to the service and registered clients of the ContextHub service. * - * @params msg : message + * @param msg message being sent from the contexthub * */ handleClientMsg(ContextHubMsg msg); @@ -32,9 +32,9 @@ interface IContexthubCallback { * implementation to allow the HAL to send the response for a * transaction. * - * @params txnId : transaction id whose result is being sent - * passed in by the service at start of transacation. - * result: result of transaction. + * @param txnId transaction id whose result is being sent + * passed in by the service at start of transacation. + * @param result result of transaction. * */ handleTxnResult(uint32_t txnId, TransactionResult result); @@ -44,7 +44,7 @@ interface IContexthubCallback { * implementation to allow the HAL to send an asynchronous event * to the ContextHub service. * - * @params msg : message + * @param evt event being sent from the contexthub * */ handleHubEvent(AsyncEventType evt); @@ -55,8 +55,8 @@ interface IContexthubCallback { * that a nanp-app has aborted. * This method must be called when a nanoapp invokes chreAbort(...)). * - * @params appId : app identifier - * : abortCode code passed by the nanoApp. + * @param appId app identifier + * @param abortCode code passed by the nanoApp. * * Also see chreAbort(...) * @@ -68,12 +68,11 @@ interface IContexthubCallback { * implementation to allow the HAL to send information about the * currently loaded and active nanoapps on the hub. * - * @params appInfo : vector of HubAppinfo structure for each nanoApp - * on the hub that can be enabled, disabled and - * unloaded by the service. Any nanoApps that cannot - * be controlled by the service must not be reported. - * All nanoApps that can be controlled by the service - * must be reported. + * @param appInfo vector of HubAppinfo structure for each nanoApp on the + * hub that can be enabled, disabled and unloaded by the + * service. Any nanoApps that cannot be controlled by the + * service must not be reported. All nanoApps that can be + * controlled by the service must be reported. */ handleAppsInfo(vec appInfo); }; diff --git a/contexthub/1.0/vts/functional/OWNERS b/contexthub/1.0/vts/functional/OWNERS index 161b2f069dadd485241b28de22a49451e5300f1f..1a33a9e097554151eced1bd795bc2c359ab485e2 100644 --- a/contexthub/1.0/vts/functional/OWNERS +++ b/contexthub/1.0/vts/functional/OWNERS @@ -5,4 +5,3 @@ stange@google.com #VTS team dshi@google.com -trong@google.com diff --git a/contexthub/1.0/vts/functional/VtsHalContexthubV1_0TargetTest.cpp b/contexthub/1.0/vts/functional/VtsHalContexthubV1_0TargetTest.cpp index ada232b9fc3508b362a70f4bf254c9185445b167..356ad97327eb0b56c5daa7b83798d3039c834f17 100644 --- a/contexthub/1.0/vts/functional/VtsHalContexthubV1_0TargetTest.cpp +++ b/contexthub/1.0/vts/functional/VtsHalContexthubV1_0TargetTest.cpp @@ -52,40 +52,17 @@ using ::android::hardware::contexthub::vts_utils::ContexthubCallbackBase; using ::android::hardware::contexthub::vts_utils::ContexthubHidlTestBase; using ::android::hardware::contexthub::vts_utils::getHalAndHubIdList; using ::android::hardware::contexthub::vts_utils::getHubsSync; +using ::android::hardware::contexthub::vts_utils::kNonExistentAppId; +using ::android::hardware::contexthub::vts_utils::waitForCallback; namespace { -// App ID with vendor "GoogT" (Google Testing), app identifier 0x555555. This -// app ID is reserved and must never appear in the list of loaded apps. -constexpr uint64_t kNonExistentAppId = 0x476f6f6754555555; - const std::vector> kTestParameters = getHalAndHubIdList(); class ContexthubHidlTest : public ContexthubHidlTestBase {}; -// Wait for a callback to occur (signaled by the given future) up to the -// provided timeout. If the future is invalid or the callback does not come -// within the given time, returns false. -template -bool waitForCallback(std::future future, ReturnType* result, - std::chrono::milliseconds timeout = std::chrono::seconds(5)) { - auto expiration = std::chrono::system_clock::now() + timeout; - - EXPECT_NE(result, nullptr); - EXPECT_TRUE(future.valid()); - if (result != nullptr && future.valid()) { - std::future_status status = future.wait_until(expiration); - EXPECT_NE(status, std::future_status::timeout) << "Timed out waiting for callback"; - - if (status == std::future_status::ready) { - *result = future.get(); - return true; - } - } - - return false; -} +class ContexthubCallbackV1_0 : public ContexthubCallbackBase {}; // Ensures that the metadata reported in getHubs() is sane TEST_P(ContexthubHidlTest, TestGetHubs) { @@ -110,7 +87,7 @@ TEST_P(ContexthubHidlTest, TestGetHubs) { TEST_P(ContexthubHidlTest, TestRegisterCallback) { ALOGD("TestRegisterCallback called, hubId %" PRIu32, getHubId()); - ASSERT_OK(registerCallback(new ContexthubCallbackBase())); + ASSERT_OK(registerCallback(new ContexthubCallbackV1_0())); } TEST_P(ContexthubHidlTest, TestRegisterNullCallback) { @@ -119,7 +96,7 @@ TEST_P(ContexthubHidlTest, TestRegisterNullCallback) { } // Helper callback that puts the async appInfo callback data into a promise -class QueryAppsCallback : public ContexthubCallbackBase { +class QueryAppsCallback : public ContexthubCallbackV1_0 { public: virtual Return handleAppsInfo(const hidl_vec& appInfo) override { ALOGD("Got app info callback with %zu apps", appInfo.size()); @@ -150,7 +127,7 @@ TEST_P(ContexthubHidlTest, TestQueryApps) { // Helper callback that puts the TransactionResult for the expectedTxnId into a // promise -class TxnResultCallback : public ContexthubCallbackBase { +class TxnResultCallback : public ContexthubCallbackV1_0 { public: virtual Return handleTxnResult(uint32_t txnId, TransactionResult result) override { ALOGD("Got transaction result callback for txnId %" PRIu32 " (expecting %" PRIu32 @@ -261,9 +238,11 @@ TEST_P(ContexthubTxnTest, TestDisableNonexistentNanoApp) { EXPECT_TRUE(checkFailureSyncOrAsync(result, Result::BAD_PARAMS, cb->promise.get_future())); } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContexthubHidlTest); INSTANTIATE_TEST_SUITE_P(HubIdSpecificTests, ContexthubHidlTest, testing::ValuesIn(kTestParameters), android::hardware::PrintInstanceTupleNameToString<>); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContexthubTxnTest); INSTANTIATE_TEST_SUITE_P(HubIdSpecificTests, ContexthubTxnTest, testing::ValuesIn(kTestParameters), android::hardware::PrintInstanceTupleNameToString<>); diff --git a/contexthub/1.1/default/Android.bp b/contexthub/1.1/default/Android.bp index 946e3a9fdc8313079d179ddc17ab00d914b0cf07..55f5026a9ab18c6d54a5b5079f528b9f4c63509b 100644 --- a/contexthub/1.1/default/Android.bp +++ b/contexthub/1.1/default/Android.bp @@ -47,5 +47,8 @@ cc_binary { "liblog", "libutils", ], + header_libs: [ + "android.hardware.contexthub@1.X-common-impl", + ], vintf_fragments: ["android.hardware.contexthub@1.1.xml"], } diff --git a/contexthub/1.1/default/Contexthub.cpp b/contexthub/1.1/default/Contexthub.cpp index 19cc2628d73f20f01fc33455d88092ef74b5a38c..2d4fbaee241d872c0c16c117487c65380ac0e3b6 100644 --- a/contexthub/1.1/default/Contexthub.cpp +++ b/contexthub/1.1/default/Contexthub.cpp @@ -23,36 +23,9 @@ namespace contexthub { namespace V1_1 { namespace implementation { -using ::android::hardware::contexthub::V1_0::ContextHub; -using ::android::hardware::contexthub::V1_0::HubAppInfo; using ::android::hardware::contexthub::V1_0::Result; -namespace { - -constexpr uint32_t kMockHubId = 0; - -} // anonymous namespace - -Return Contexthub::getHubs(getHubs_cb _hidl_cb) { - ContextHub hub = {}; - hub.name = "Mock Context Hub"; - hub.vendor = "AOSP"; - hub.toolchain = "n/a"; - hub.platformVersion = 1; - hub.toolchainVersion = 1; - hub.hubId = kMockHubId; - hub.peakMips = 1; - hub.peakPowerDrawMw = 1; - hub.maxSupportedMsgLen = 4096; - hub.chrePlatformId = UINT64_C(0x476f6f6754000000); - hub.chreApiMajorVersion = 1; - hub.chreApiMinorVersion = 4; - - // Report a single mock hub - std::vector hubs; - hubs.push_back(hub); - - _hidl_cb(hubs); +Return Contexthub::onSettingChanged(Setting /*setting*/, SettingValue /*newValue*/) { return Void(); } @@ -64,31 +37,6 @@ Return Contexthub::registerCallback(uint32_t hubId, const sp Contexthub::sendMessageToHub(uint32_t /*hubId*/, const ContextHubMsg& /*msg*/) { - return Result::BAD_PARAMS; -} - -Return Contexthub::loadNanoApp(uint32_t /*hubId*/, const NanoAppBinary& /*appBinary*/, - uint32_t /*transactionId*/) { - return Result::BAD_PARAMS; -} - -Return Contexthub::unloadNanoApp(uint32_t /*hubId*/, uint64_t /*appId*/, - uint32_t /*transactionId*/) { - return Result::BAD_PARAMS; -} - -Return Contexthub::enableNanoApp(uint32_t /*hubId*/, uint64_t /*appId*/, - uint32_t /*transactionId*/) { - return Result::BAD_PARAMS; -} - -Return Contexthub::disableNanoApp(uint32_t /*hubId*/, uint64_t /*appId*/, - uint32_t /*transactionId*/) { - return Result::BAD_PARAMS; -} - Return Contexthub::queryApps(uint32_t hubId) { if (hubId == kMockHubId && mCallback != nullptr) { std::vector nanoapps; @@ -98,10 +46,6 @@ Return Contexthub::queryApps(uint32_t hubId) { return Result::BAD_PARAMS; } -Return Contexthub::onSettingChanged(Setting /*setting*/, SettingValue /*newValue*/) { - return Void(); -} - } // namespace implementation } // namespace V1_1 } // namespace contexthub diff --git a/contexthub/1.1/default/Contexthub.h b/contexthub/1.1/default/Contexthub.h index 0da61d146400bbe1985466e0d8d5b51230d0f47c..648749e27ae515e7b1ce04a41b9aef1806dfd756 100644 --- a/contexthub/1.1/default/Contexthub.h +++ b/contexthub/1.1/default/Contexthub.h @@ -15,6 +15,8 @@ */ #pragma once +#include "ContextHub.h" + #include namespace android { @@ -23,23 +25,14 @@ namespace contexthub { namespace V1_1 { namespace implementation { -class Contexthub : public V1_1::IContexthub { - using ContextHubMsg = ::android::hardware::contexthub::V1_0::ContextHubMsg; - using IContexthubCallback = ::android::hardware::contexthub::V1_0::IContexthubCallback; - using NanoAppBinary = ::android::hardware::contexthub::V1_0::NanoAppBinary; +class Contexthub + : public ::android::hardware::contexthub::V1_X::implementation::ContextHub { using Result = ::android::hardware::contexthub::V1_0::Result; public: // Methods from V1_0::IContexthub - Return getHubs(getHubs_cb _hidl_cb) override; - Return registerCallback(uint32_t hubId, - const ::android::sp& cb) override; - Return sendMessageToHub(uint32_t hubId, const ContextHubMsg& msg) override; - Return loadNanoApp(uint32_t hubId, const NanoAppBinary& appBinary, - uint32_t transactionId) override; - Return unloadNanoApp(uint32_t hubId, uint64_t appId, uint32_t transactionId) override; - Return enableNanoApp(uint32_t hubId, uint64_t appId, uint32_t transactionId) override; - Return disableNanoApp(uint32_t hubId, uint64_t appId, uint32_t transactionId) override; + Return registerCallback(uint32_t hubId, const sp& cb) override; + Return queryApps(uint32_t hubId) override; // Methods from V1_1::IContexthub diff --git a/contexthub/1.1/vts/functional/OWNERS b/contexthub/1.1/vts/functional/OWNERS index 161b2f069dadd485241b28de22a49451e5300f1f..1a33a9e097554151eced1bd795bc2c359ab485e2 100644 --- a/contexthub/1.1/vts/functional/OWNERS +++ b/contexthub/1.1/vts/functional/OWNERS @@ -5,4 +5,3 @@ stange@google.com #VTS team dshi@google.com -trong@google.com diff --git a/contexthub/1.1/vts/functional/VtsHalContexthubV1_1TargetTest.cpp b/contexthub/1.1/vts/functional/VtsHalContexthubV1_1TargetTest.cpp index f2fcdfca48f002bfb8ceac66439a7e0b92f78810..acf4be0c4586a15e592d39f276caf30be91ace79 100644 --- a/contexthub/1.1/vts/functional/VtsHalContexthubV1_1TargetTest.cpp +++ b/contexthub/1.1/vts/functional/VtsHalContexthubV1_1TargetTest.cpp @@ -31,6 +31,7 @@ #include +using ::android::hardware::contexthub::V1_0::IContexthubCallback; using ::android::hardware::contexthub::V1_1::IContexthub; using ::android::hardware::contexthub::V1_1::Setting; using ::android::hardware::contexthub::V1_1::SettingValue; @@ -45,15 +46,18 @@ const std::vector> kTestParameters = class ContexthubHidlTest : public ContexthubHidlTestBase {}; +class ContexthubCallbackV1_0 : public ContexthubCallbackBase {}; + TEST_P(ContexthubHidlTest, TestOnSettingChanged) { // In VTS, we only test that sending the values doesn't cause things to blow up - other test // suites verify the expected E2E behavior in CHRE - ASSERT_OK(registerCallback(new ContexthubCallbackBase())); + ASSERT_OK(registerCallback(new ContexthubCallbackV1_0())); hubApi->onSettingChanged(Setting::LOCATION, SettingValue::DISABLED); hubApi->onSettingChanged(Setting::LOCATION, SettingValue::ENABLED); ASSERT_OK(registerCallback(nullptr)); } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContexthubHidlTest); INSTANTIATE_TEST_SUITE_P(HubIdSpecificTests, ContexthubHidlTest, testing::ValuesIn(kTestParameters), android::hardware::PrintInstanceTupleNameToString<>); diff --git a/contexthub/1.2/Android.bp b/contexthub/1.2/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..d7d4c49cfb15d186d2722fc3081599ddcf5838d7 --- /dev/null +++ b/contexthub/1.2/Android.bp @@ -0,0 +1,26 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +hidl_interface { + name: "android.hardware.contexthub@1.2", + root: "android.hardware", + srcs: [ + "types.hal", + "IContexthub.hal", + "IContexthubCallback.hal", + ], + interfaces: [ + "android.hardware.contexthub@1.0", + "android.hardware.contexthub@1.1", + "android.hidl.base@1.0", + ], + gen_java: true, +} diff --git a/contexthub/1.2/IContexthub.hal b/contexthub/1.2/IContexthub.hal new file mode 100644 index 0000000000000000000000000000000000000000..04a8cb29cc96a51efdc069877b588ed3d3125334 --- /dev/null +++ b/contexthub/1.2/IContexthub.hal @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.contexthub@1.2; + +import @1.0::ContextHub; +import @1.0::Result; +import @1.1::IContexthub; +import @1.1::SettingValue; +import IContexthubCallback; + +interface IContexthub extends @1.1::IContexthub { + /** + * Enumerate all available context hubs on the system. + * + * @return hubs list of hubs on this system. + * @return supportedPermissions list of Android permissions all hubs + * support for nanoapps to enforce host + * endpoints are granted in order to + * communicate with them. + */ + getHubs_1_2() generates (vec hubs, vec supportedPermissions); + + /** + * Register a callback for the HAL implementation to send asynchronous + * messages to the service from a context hub. There can be a maximum of + * one callback registered with the HAL. A call to this function when a + * callback has already been registered must override the previous + * registration. + * + * @param hubId identifier for the hub + * @param callback an implementation of the IContextHubCallbacks + * + * @return result OK on success + * BAD_VALUE if parameters are not valid + * + */ + registerCallback_1_2(uint32_t hubId, IContexthubCallback cb) generates (Result result); + + /** + * Notification sent by the framework to indicate that the user + * has changed a setting. + * + * @param setting User setting that has been modified. + * @param newValue The update value of the user setting. + */ + onSettingChanged_1_2(Setting setting, @1.1::SettingValue newValue); +}; diff --git a/contexthub/1.2/IContexthubCallback.hal b/contexthub/1.2/IContexthubCallback.hal new file mode 100644 index 0000000000000000000000000000000000000000..1a405128b7efa82d8cdc0d6d4d01147495555192 --- /dev/null +++ b/contexthub/1.2/IContexthubCallback.hal @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.contexthub@1.2; + +import @1.0::IContexthubCallback; + +interface IContexthubCallback extends @1.0::IContexthubCallback { + /** + * This callback is passed by the Contexthub service to the HAL + * implementation to allow the HAL to send asynchronous messages back + * to the service and registered clients of the ContextHub service. + * + * @param msg message that should be delivered to host app + * clients + * @param msgContentPerms list of Android permissions that cover the + * contents of the message being sent from the app. + * This is different from the permissions stored + * inside of ContextHubMsg in that these must be a + * subset of those permissions and are meant to + * assist in properly attributing the message + * contents when delivering to a ContextHub service + * client. + */ + handleClientMsg_1_2(ContextHubMsg msg, vec msgContentPerms); + + /** + * This callback is passed by the Contexthub service to the HAL + * implementation to allow the HAL to send information about the + * currently loaded and active nanoapps on the hub. + * + * @param appInfo vector of HubAppinfo structure for each nanoApp + * on the hub that can be enabled, disabled and + * unloaded by the service. Any nanoApps that cannot + * be controlled by the service must not be reported. + * All nanoApps that can be controlled by the service + * must be reported. + */ + handleAppsInfo_1_2(vec appInfo); +}; diff --git a/contexthub/1.2/default/Android.bp b/contexthub/1.2/default/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..a52577a62001c2f68491aa1a7d0f8123facbdd95 --- /dev/null +++ b/contexthub/1.2/default/Android.bp @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_binary { + name: "android.hardware.contexthub@1.2-service.mock", + defaults: ["hidl_defaults"], + vendor: true, + relative_install_path: "hw", + init_rc: ["android.hardware.contexthub@1.2-service.rc"], + srcs: [ + "Contexthub.cpp", + "service.cpp", + ], + cflags: [ + "-Wall", + "-Werror", + ], + shared_libs: [ + "android.hardware.contexthub@1.0", + "android.hardware.contexthub@1.1", + "android.hardware.contexthub@1.2", + "libbase", + "libcutils", + "libhardware", + "libhidlbase", + "liblog", + "libutils", + ], + header_libs: [ + "android.hardware.contexthub@1.X-common-impl", + "android.hardware.contexthub@1.X-common-utils", + ], + vintf_fragments: ["android.hardware.contexthub@1.2.xml"], +} diff --git a/contexthub/1.2/default/Contexthub.cpp b/contexthub/1.2/default/Contexthub.cpp new file mode 100644 index 0000000000000000000000000000000000000000..57145fc64f3bbdf0834c2369673afd825fe86d10 --- /dev/null +++ b/contexthub/1.2/default/Contexthub.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "Contexthub.h" + +#include + +namespace android { +namespace hardware { +namespace contexthub { +namespace V1_2 { +namespace implementation { + +using ::android::hardware::hidl_string; +using ::android::hardware::contexthub::V1_0::Result; +using ::android::hardware::contexthub::V1_X::implementation::IContextHubCallbackWrapperV1_0; +using ::android::hardware::contexthub::V1_X::implementation::IContextHubCallbackWrapperV1_2; + +Return Contexthub::getHubs_1_2(getHubs_1_2_cb _hidl_cb) { + ::android::hardware::contexthub::V1_0::ContextHub hub = {}; + hub.name = "Mock Context Hub"; + hub.vendor = "AOSP"; + hub.toolchain = "n/a"; + hub.platformVersion = 1; + hub.toolchainVersion = 1; + hub.hubId = kMockHubId; + hub.peakMips = 1; + hub.peakPowerDrawMw = 1; + hub.maxSupportedMsgLen = 4096; + hub.chrePlatformId = UINT64_C(0x476f6f6754000000); + hub.chreApiMajorVersion = 1; + hub.chreApiMinorVersion = 4; + + // Report a single mock hub + std::vector<::android::hardware::contexthub::V1_0::ContextHub> hubs; + hubs.push_back(hub); + + std::vector hubPermissionList; + + _hidl_cb(hubs, hubPermissionList); + return Void(); +} + +Return Contexthub::registerCallback(uint32_t hubId, + const sp& cb) { + if (hubId == kMockHubId) { + mCallback = new IContextHubCallbackWrapperV1_0(cb); + return Result::OK; + } + return Result::BAD_PARAMS; +} + +Return Contexthub::queryApps(uint32_t hubId) { + if (hubId == kMockHubId && mCallback != nullptr) { + std::vector nanoapps; + mCallback->handleAppsInfo(nanoapps); + return Result::OK; + } + return Result::BAD_PARAMS; +} + +Return Contexthub::registerCallback_1_2(uint32_t hubId, + const sp& cb) { + if (hubId == kMockHubId) { + mCallback = new IContextHubCallbackWrapperV1_2(cb); + return Result::OK; + } + return Result::BAD_PARAMS; +} + +Return Contexthub::onSettingChanged(SettingV1_1 /*setting*/, SettingValue /*newValue*/) { + return Void(); +} + +Return Contexthub::onSettingChanged_1_2(Setting /*setting*/, SettingValue /*newValue*/) { + return Void(); +} + +} // namespace implementation +} // namespace V1_2 +} // namespace contexthub +} // namespace hardware +} // namespace android diff --git a/contexthub/1.2/default/Contexthub.h b/contexthub/1.2/default/Contexthub.h new file mode 100644 index 0000000000000000000000000000000000000000..305544d5f47d477b834eb16963bbd72c109a2f8c --- /dev/null +++ b/contexthub/1.2/default/Contexthub.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include "ContextHub.h" +#include "IContextHubCallbackWrapper.h" + +#include + +namespace android { +namespace hardware { +namespace contexthub { +namespace V1_2 { +namespace implementation { + +class Contexthub + : public ::android::hardware::contexthub::V1_X::implementation::ContextHub { + using ContextHubMsg = ::android::hardware::contexthub::V1_2::ContextHubMsg; + using IContexthubCallback = ::android::hardware::contexthub::V1_2::IContexthubCallback; + using IContextHubCallbackWrapperBase = + ::android::hardware::contexthub::V1_X::implementation::IContextHubCallbackWrapperBase; + using Result = ::android::hardware::contexthub::V1_0::Result; + using SettingValue = ::android::hardware::contexthub::V1_1::SettingValue; + using SettingV1_1 = ::android::hardware::contexthub::V1_1::Setting; + using getHubs_1_2_cb = ::android::hardware::contexthub::V1_2::IContexthub::getHubs_1_2_cb; + + public: + // Methods from V1_0::IContexthub + Return registerCallback(uint32_t hubId, + const sp& cb) override; + + Return queryApps(uint32_t hubId) override; + + // Methods from V1_1::IContexthub + Return onSettingChanged(SettingV1_1 setting, SettingValue newValue) override; + + // Methods from V1_2::IContexthub + Return getHubs_1_2(getHubs_1_2_cb _hidl_cb) override; + + Return onSettingChanged_1_2(Setting setting, SettingValue newValue) override; + + Return registerCallback_1_2(uint32_t hubId, + const sp& cb) override; + + private: + sp mCallback; +}; + +} // namespace implementation +} // namespace V1_2 +} // namespace contexthub +} // namespace hardware +} // namespace android diff --git a/contexthub/1.2/default/OWNERS b/contexthub/1.2/default/OWNERS new file mode 100644 index 0000000000000000000000000000000000000000..90c233030ed137ec27c0e66ecb58a0758c0233f0 --- /dev/null +++ b/contexthub/1.2/default/OWNERS @@ -0,0 +1,3 @@ +arthuri@google.com +bduddie@google.com +stange@google.com diff --git a/contexthub/1.2/default/android.hardware.contexthub@1.2-service.rc b/contexthub/1.2/default/android.hardware.contexthub@1.2-service.rc new file mode 100644 index 0000000000000000000000000000000000000000..936222a607400e16e4e33f6c99923f04708392a1 --- /dev/null +++ b/contexthub/1.2/default/android.hardware.contexthub@1.2-service.rc @@ -0,0 +1,7 @@ +service vendor.contexthub-hal-1.2-mock /vendor/bin/hw/android.hardware.contexthub@1.2-service.mock + interface android.hardware.contexthub@1.0::IContexthub default + interface android.hardware.contexthub@1.1::IContexthub default + interface android.hardware.contexthub@1.2::IContexthub default + class hal + user context_hub + group context_hub diff --git a/contexthub/1.2/default/android.hardware.contexthub@1.2.xml b/contexthub/1.2/default/android.hardware.contexthub@1.2.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec6c6849944ba9c82f4b7d76763f388c64be2d69 --- /dev/null +++ b/contexthub/1.2/default/android.hardware.contexthub@1.2.xml @@ -0,0 +1,11 @@ + + + android.hardware.contexthub + hwbinder + 1.2 + + IContexthub + default + + + diff --git a/contexthub/1.2/default/service.cpp b/contexthub/1.2/default/service.cpp new file mode 100644 index 0000000000000000000000000000000000000000..41cb753159af877f9438df816a5f23e0f4333622 --- /dev/null +++ b/contexthub/1.2/default/service.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "android.hardware.contexthub@1.2-service" + +#include +#include +#include +#include +#include "Contexthub.h" + +using ::android::hardware::configureRpcThreadpool; +using ::android::hardware::joinRpcThreadpool; +using ::android::hardware::contexthub::V1_2::IContexthub; +using ::android::hardware::contexthub::V1_2::implementation::Contexthub; + +int main() { + configureRpcThreadpool(1, true /* callerWillJoin */); + + ::android::sp contexthub = new Contexthub(); + if (contexthub->registerAsService() != ::android::OK) { + ALOGE("Failed to register Contexthub HAL instance"); + return 1; + } + + joinRpcThreadpool(); + ALOGE("Service exited"); + return 1; +} diff --git a/contexthub/1.2/types.hal b/contexthub/1.2/types.hal new file mode 100644 index 0000000000000000000000000000000000000000..75122bc8982001acca206a54bfbe18e31a59d067 --- /dev/null +++ b/contexthub/1.2/types.hal @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.contexthub@1.2; + +import @1.0::ContextHubMsg; +import @1.0::HubAppInfo; +import @1.1::Setting; + +/** + * Used to indicate the type of user setting that has changed. + */ +enum Setting : @1.1::Setting { + /** + * Indicates that the WiFi capabilities can be used in CHRE. This setting + * follows the overall availability of WiFi-related functionality within + * the Android framework, for example if WiFi is disabled for connectivity + * purposes but is enabled for location purposes (scanning), then + * WIFI_AVAILABLE is enabled. + */ + WIFI_AVAILABLE, + AIRPLANE_MODE, + + /** + * Indicates if the microphone access is available for CHRE. Microphone + * access is disabled if the user has turned off the microphone as a + * privacy setting, in which case audio data cannot be used and propagated + * by CHRE. + */ + MICROPHONE, +}; + +struct ContextHubMsg { + @1.0::ContextHubMsg msg_1_0; + + /** + * The list of Android permissions held by the sending nanoapp at the time + * the message was sent. + * + * The framework MUST drop messages to host apps that don't have a superset + * of the permissions that the sending nanoapp is using. + */ + vec permissions; +}; + +struct HubAppInfo { + @1.0::HubAppInfo info_1_0; + + /** + * The list of Android permissions used by this nanoapp. This list MUST + * correspond to the permissions required for an equivalent Android app to + * sample similar signals through the Android framework. + * + * For example, if a nanoapp used location-based signals, the permissions + * list MUST contains android.permission.ACCESS_FINE_LOCATION and + * android.permission.ACCESS_BACKGROUND_LOCATION. If it were to also list to + * audio data, it would require adding android.permission.RECORD_AUDIO to + * this list. + */ + vec permissions; +}; diff --git a/contexthub/1.2/vts/functional/Android.bp b/contexthub/1.2/vts/functional/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..c923f42a2051e53aa95547c2b392c9cb386d3d34 --- /dev/null +++ b/contexthub/1.2/vts/functional/Android.bp @@ -0,0 +1,40 @@ +// +// Copyright (C) 2020 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_test { + name: "VtsHalContexthubV1_2TargetTest", + defaults: ["VtsHalTargetTestDefaults"], + srcs: ["VtsHalContexthubV1_2TargetTest.cpp"], + static_libs: [ + "android.hardware.contexthub@1.0", + "android.hardware.contexthub@1.1", + "android.hardware.contexthub@1.2", + "VtsHalContexthubUtils", + ], + test_suites: [ + "general-tests", + "vts", + ], +} diff --git a/contexthub/1.2/vts/functional/OWNERS b/contexthub/1.2/vts/functional/OWNERS new file mode 100644 index 0000000000000000000000000000000000000000..1a33a9e097554151eced1bd795bc2c359ab485e2 --- /dev/null +++ b/contexthub/1.2/vts/functional/OWNERS @@ -0,0 +1,7 @@ +#Context Hub team +arthuri@google.com +bduddie@google.com +stange@google.com + +#VTS team +dshi@google.com diff --git a/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp b/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9ee40ede01741ddf2b3b65a0f77d85dc5a7a684d --- /dev/null +++ b/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "contexthub_hidl_hal_test" + +#include "ContexthubCallbackBase.h" +#include "ContexthubHidlTestBase.h" +#include "VtsHalContexthubUtils.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using ::android::sp; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::contexthub::V1_0::ContextHub; +using ::android::hardware::contexthub::V1_0::Result; +using ::android::hardware::contexthub::V1_0::TransactionResult; +using ::android::hardware::contexthub::V1_1::SettingValue; +using ::android::hardware::contexthub::V1_2::ContextHubMsg; +using ::android::hardware::contexthub::V1_2::HubAppInfo; +using ::android::hardware::contexthub::V1_2::IContexthub; +using ::android::hardware::contexthub::V1_2::IContexthubCallback; +using ::android::hardware::contexthub::V1_2::Setting; +using ::android::hardware::contexthub::vts_utils::asBaseType; +using ::android::hardware::contexthub::vts_utils::ContexthubCallbackBase; +using ::android::hardware::contexthub::vts_utils::ContexthubHidlTestBase; +using ::android::hardware::contexthub::vts_utils::getHalAndHubIdList; +using ::android::hardware::contexthub::vts_utils::kNonExistentAppId; +using ::android::hardware::contexthub::vts_utils::waitForCallback; + +namespace { + +const std::vector> kTestParameters = + getHalAndHubIdList(); + +class ContexthubCallbackV1_2 : public ContexthubCallbackBase { + public: + virtual Return handleClientMsg_1_2( + const ContextHubMsg& /*msg*/, + const hidl_vec& /*msgContentPerms*/) override { + ALOGD("Got client message callback"); + return Void(); + } + + virtual Return handleAppsInfo_1_2(const hidl_vec& /*appInfo*/) override { + ALOGD("Got app info callback"); + return Void(); + } +}; + +class ContexthubHidlTest : public ContexthubHidlTestBase { + public: + Result registerCallback_1_2(sp cb) { + return hubApi->registerCallback_1_2(getHubId(), cb); + } +}; + +// Ensures that the metadata reported in getHubs_1_2() is valid +TEST_P(ContexthubHidlTest, TestGetHubs_1_2) { + hidl_vec hubList; + hubApi->getHubs_1_2( + [&hubList](const hidl_vec& hubs, + const hidl_vec& /*hubPermissions*/) { hubList = hubs; }); + + ALOGD("System reports %zu hubs", hubList.size()); + + for (const ContextHub& hub : hubList) { + ALOGD("Checking hub ID %" PRIu32, hub.hubId); + + EXPECT_FALSE(hub.name.empty()); + EXPECT_FALSE(hub.vendor.empty()); + EXPECT_FALSE(hub.toolchain.empty()); + EXPECT_GT(hub.peakMips, 0); + EXPECT_GE(hub.stoppedPowerDrawMw, 0); + EXPECT_GE(hub.sleepPowerDrawMw, 0); + EXPECT_GT(hub.peakPowerDrawMw, 0); + + // Minimum 128 byte MTU as required by CHRE API v1.0 + EXPECT_GE(hub.maxSupportedMsgLen, UINT32_C(128)); + } +} + +TEST_P(ContexthubHidlTest, TestRegisterCallback) { + ALOGD("TestRegisterCallback called, hubId %" PRIu32, getHubId()); + ASSERT_OK(registerCallback_1_2(new ContexthubCallbackV1_2())); +} + +TEST_P(ContexthubHidlTest, TestRegisterNullCallback) { + ALOGD("TestRegisterNullCallback called, hubId %" PRIu32, getHubId()); + ASSERT_OK(registerCallback_1_2(nullptr)); +} + +// In VTS, we only test that sending the values doesn't cause things to blow up - other test +// suites verify the expected E2E behavior in CHRE +TEST_P(ContexthubHidlTest, TestOnWifiSettingChanged) { + ASSERT_OK(registerCallback_1_2(new ContexthubCallbackV1_2())); + hubApi->onSettingChanged_1_2(Setting::WIFI_AVAILABLE, SettingValue::DISABLED); + hubApi->onSettingChanged_1_2(Setting::WIFI_AVAILABLE, SettingValue::ENABLED); + ASSERT_OK(registerCallback_1_2(nullptr)); +} + +TEST_P(ContexthubHidlTest, TestOnAirplaneModeSettingChanged) { + ASSERT_OK(registerCallback_1_2(new ContexthubCallbackV1_2())); + hubApi->onSettingChanged_1_2(Setting::AIRPLANE_MODE, SettingValue::DISABLED); + hubApi->onSettingChanged_1_2(Setting::AIRPLANE_MODE, SettingValue::ENABLED); + ASSERT_OK(registerCallback_1_2(nullptr)); +} + +TEST_P(ContexthubHidlTest, TestOnMicrophoneSettingChanged) { + ASSERT_OK(registerCallback_1_2(new ContexthubCallbackV1_2())); + hubApi->onSettingChanged_1_2(Setting::MICROPHONE, SettingValue::DISABLED); + hubApi->onSettingChanged_1_2(Setting::MICROPHONE, SettingValue::ENABLED); + ASSERT_OK(registerCallback_1_2(nullptr)); +} + +// Helper callback that puts the async appInfo callback data into a promise +class QueryAppsCallback : public ContexthubCallbackV1_2 { + public: + virtual Return handleAppsInfo_1_2(const hidl_vec& appInfo) override { + ALOGD("Got app info callback with %zu apps", appInfo.size()); + promise.set_value(appInfo); + return Void(); + } + + std::promise> promise; +}; + +// Calls queryApps() and checks the returned metadata +TEST_P(ContexthubHidlTest, TestQueryApps) { + hidl_vec hubPerms; + hubApi->getHubs_1_2([&hubPerms](const hidl_vec& /*hubs*/, + const hidl_vec& hubPermissions) { + hubPerms = hubPermissions; + }); + + ALOGD("TestQueryApps called, hubId %u", getHubId()); + sp cb = new QueryAppsCallback(); + ASSERT_OK(registerCallback_1_2(cb)); + + Result result = hubApi->queryApps(getHubId()); + ASSERT_OK(result); + + ALOGD("Waiting for app info callback"); + hidl_vec appList; + ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &appList)); + for (const HubAppInfo& appInfo : appList) { + EXPECT_NE(appInfo.info_1_0.appId, UINT64_C(0)); + EXPECT_NE(appInfo.info_1_0.appId, kNonExistentAppId); + for (std::string permission : appInfo.permissions) { + ASSERT_TRUE(hubPerms.contains(permission)); + } + } +} + +// Helper callback that puts the TransactionResult for the expectedTxnId into a +// promise +class TxnResultCallback : public ContexthubCallbackV1_2 { + public: + virtual Return handleTxnResult(uint32_t txnId, TransactionResult result) override { + ALOGD("Got transaction result callback for txnId %" PRIu32 " (expecting %" PRIu32 + ") with result %" PRId32, + txnId, expectedTxnId, result); + if (txnId == expectedTxnId) { + promise.set_value(result); + } + return Void(); + } + + uint32_t expectedTxnId = 0; + std::promise promise; +}; + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContexthubHidlTest); +INSTANTIATE_TEST_SUITE_P(HubIdSpecificTests, ContexthubHidlTest, testing::ValuesIn(kTestParameters), + android::hardware::PrintInstanceTupleNameToString<>); + +} // anonymous namespace diff --git a/contexthub/common/default/1.X/Android.bp b/contexthub/common/default/1.X/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..eef137ec83b66dac55f43d3f66e412b3daad8347 --- /dev/null +++ b/contexthub/common/default/1.X/Android.bp @@ -0,0 +1,37 @@ +// +// Copyright (C) 2020 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_library_headers { + name: "android.hardware.contexthub@1.X-common-impl", + vendor_available: true, + defaults: ["hidl_defaults"], + export_include_dirs: ["."], + shared_libs: [ + "android.hardware.contexthub@1.0", + "libbinder", + "libcutils", + "libhidlbase", + "libutils", + ], +} diff --git a/contexthub/common/default/1.X/ContextHub.h b/contexthub/common/default/1.X/ContextHub.h new file mode 100644 index 0000000000000000000000000000000000000000..00f74afa1b7d9e90437ff579aabf12a73817b0f8 --- /dev/null +++ b/contexthub/common/default/1.X/ContextHub.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_CONTEXTHUB_V1_X_CONTEXTHUB_H +#define ANDROID_HARDWARE_CONTEXTHUB_V1_X_CONTEXTHUB_H + +#include +#include +#include + +namespace android { +namespace hardware { +namespace contexthub { +namespace V1_X { +namespace implementation { + +template +struct ContextHub : public IContextHubInterface { + using ContextHubMsg = ::android::hardware::contexthub::V1_0::ContextHubMsg; + using HubAppInfo = ::android::hardware::contexthub::V1_0::HubAppInfo; + using IContexthubCallback = ::android::hardware::contexthub::V1_0::IContexthubCallback; + using NanoAppBinary = ::android::hardware::contexthub::V1_0::NanoAppBinary; + using Result = ::android::hardware::contexthub::V1_0::Result; + using getHubs_cb = ::android::hardware::contexthub::V1_0::IContexthub::getHubs_cb; + + public: + Return getHubs(getHubs_cb _hidl_cb) override { + ::android::hardware::contexthub::V1_0::ContextHub hub = {}; + hub.name = "Mock Context Hub"; + hub.vendor = "AOSP"; + hub.toolchain = "n/a"; + hub.platformVersion = 1; + hub.toolchainVersion = 1; + hub.hubId = kMockHubId; + hub.peakMips = 1; + hub.peakPowerDrawMw = 1; + hub.maxSupportedMsgLen = 4096; + hub.chrePlatformId = UINT64_C(0x476f6f6754000000); + hub.chreApiMajorVersion = 1; + hub.chreApiMinorVersion = 4; + + // Report a single mock hub + std::vector<::android::hardware::contexthub::V1_0::ContextHub> hubs; + hubs.push_back(hub); + + _hidl_cb(hubs); + return Void(); + } + + // We don't expose any nanoapps, therefore all nanoapp-related API calls return with BAD_PARAMS + Return sendMessageToHub(uint32_t /*hubId*/, const ContextHubMsg& /*msg*/) override { + return Result::BAD_PARAMS; + } + + Return loadNanoApp(uint32_t /*hubId*/, const NanoAppBinary& /*appBinary*/, + uint32_t /*transactionId*/) override { + return Result::BAD_PARAMS; + } + + Return unloadNanoApp(uint32_t /*hubId*/, uint64_t /*appId*/, + uint32_t /*transactionId*/) override { + return Result::BAD_PARAMS; + } + + Return enableNanoApp(uint32_t /*hubId*/, uint64_t /*appId*/, + uint32_t /*transactionId*/) override { + return Result::BAD_PARAMS; + } + + Return disableNanoApp(uint32_t /*hubId*/, uint64_t /*appId*/, + uint32_t /*transactionId*/) override { + return Result::BAD_PARAMS; + } + + protected: + static constexpr uint32_t kMockHubId = 0; +}; + +} // namespace implementation +} // namespace V1_X +} // namespace contexthub +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_CONTEXTHUB_V1_X_CONTEXTHUB_H diff --git a/contexthub/common/default/1.X/OWNERS b/contexthub/common/default/1.X/OWNERS new file mode 100644 index 0000000000000000000000000000000000000000..90c233030ed137ec27c0e66ecb58a0758c0233f0 --- /dev/null +++ b/contexthub/common/default/1.X/OWNERS @@ -0,0 +1,3 @@ +arthuri@google.com +bduddie@google.com +stange@google.com diff --git a/contexthub/common/default/1.X/utils/Android.bp b/contexthub/common/default/1.X/utils/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..dabe754ccab13a8917fd800eed110e5fa2db879c --- /dev/null +++ b/contexthub/common/default/1.X/utils/Android.bp @@ -0,0 +1,39 @@ +// +// Copyright (C) 2020 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_library_headers { + name: "android.hardware.contexthub@1.X-common-utils", + vendor_available: true, + defaults: ["hidl_defaults"], + export_include_dirs: ["."], + shared_libs: [ + "android.hardware.contexthub@1.0", + "android.hardware.contexthub@1.1", + "android.hardware.contexthub@1.2", + "libbinder", + "libcutils", + "libhidlbase", + "libutils", + ], +} diff --git a/contexthub/common/default/1.X/utils/IContextHubCallbackWrapper.h b/contexthub/common/default/1.X/utils/IContextHubCallbackWrapper.h new file mode 100644 index 0000000000000000000000000000000000000000..d9459b738115107c0ab8545ba2dcc684c92e2192 --- /dev/null +++ b/contexthub/common/default/1.X/utils/IContextHubCallbackWrapper.h @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_CONTEXTHUB_V1_X_ICONTEXTHUBCALLBACKWRAPPER_H +#define ANDROID_HARDWARE_CONTEXTHUB_V1_X_ICONTEXTHUBCALLBACKWRAPPER_H + +#include "android/hardware/contexthub/1.0/IContexthub.h" +#include "android/hardware/contexthub/1.0/IContexthubCallback.h" +#include "android/hardware/contexthub/1.0/types.h" +#include "android/hardware/contexthub/1.2/IContexthubCallback.h" +#include "android/hardware/contexthub/1.2/types.h" + +#include + +#include + +namespace android { +namespace hardware { +namespace contexthub { +namespace V1_X { +namespace implementation { + +inline V1_0::ContextHubMsg convertToOldMsg(V1_2::ContextHubMsg msg) { + return msg.msg_1_0; +} + +inline hidl_vec convertToOldAppInfo(hidl_vec appInfos) { + hidl_vec convertedInfo(appInfos.size()); + for (int i = 0; i < appInfos.size(); ++i) { + convertedInfo[i] = appInfos[i].info_1_0; + } + + return convertedInfo; +} + +/** + * The IContexthubCallback classes below abstract away the common logic between both the V1.0, and + * V1.2 versions of the Contexthub HAL callback interface. This allows users of these classes to + * only care about the HAL version at init time and then interact with either version of the + * callback without worrying about the class type by utilizing the base class. + */ +class IContextHubCallbackWrapperBase : public VirtualLightRefBase { + public: + virtual Return handleClientMsg(V1_2::ContextHubMsg msg, + hidl_vec msgContentPerms) = 0; + + virtual Return handleTxnResult(uint32_t txnId, V1_0::TransactionResult result) = 0; + + virtual Return handleHubEvent(V1_0::AsyncEventType evt) = 0; + + virtual Return handleAppAbort(uint64_t appId, uint32_t abortCode) = 0; + + virtual Return handleAppsInfo(hidl_vec appInfo) = 0; + + virtual Return linkToDeath(const sp& recipient, + uint64_t cookie) = 0; + + virtual Return unlinkToDeath(const sp& recipient) = 0; +}; + +template +class ContextHubCallbackWrapper : public IContextHubCallbackWrapperBase { + public: + ContextHubCallbackWrapper(sp callback) : mCallback(callback){}; + + virtual Return handleClientMsg(V1_2::ContextHubMsg msg, + hidl_vec /* msgContentPerms */) override { + return mCallback->handleClientMsg(convertToOldMsg(msg)); + } + + virtual Return handleTxnResult(uint32_t txnId, V1_0::TransactionResult result) override { + return mCallback->handleTxnResult(txnId, result); + } + + virtual Return handleHubEvent(V1_0::AsyncEventType evt) override { + return mCallback->handleHubEvent(evt); + } + + virtual Return handleAppAbort(uint64_t appId, uint32_t abortCode) override { + return mCallback->handleAppAbort(appId, abortCode); + } + + virtual Return handleAppsInfo(hidl_vec appInfo) override { + return mCallback->handleAppsInfo(convertToOldAppInfo(appInfo)); + } + + Return linkToDeath(const sp& recipient, uint64_t cookie) override { + return mCallback->linkToDeath(recipient, cookie); + } + + Return unlinkToDeath(const sp& recipient) override { + return mCallback->unlinkToDeath(recipient); + } + + protected: + sp mCallback; +}; + +class IContextHubCallbackWrapperV1_0 : public ContextHubCallbackWrapper { + public: + IContextHubCallbackWrapperV1_0(sp callback) + : ContextHubCallbackWrapper(callback){}; +}; + +class IContextHubCallbackWrapperV1_2 : public ContextHubCallbackWrapper { + public: + IContextHubCallbackWrapperV1_2(sp callback) + : ContextHubCallbackWrapper(callback){}; + + Return handleClientMsg(V1_2::ContextHubMsg msg, + hidl_vec msgContentPerms) override { + return mCallback->handleClientMsg_1_2(msg, msgContentPerms); + } + + Return handleAppsInfo(hidl_vec appInfo) override { + return mCallback->handleAppsInfo_1_2(appInfo); + } +}; + +} // namespace implementation +} // namespace V1_X +} // namespace contexthub +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_CONTEXTHUB_V1_X_ICONTEXTHUBCALLBACKWRAPPER_H \ No newline at end of file diff --git a/contexthub/common/vts/ContexthubCallbackBase.h b/contexthub/common/vts/ContexthubCallbackBase.h index 124a11601a873c7d4303cdb761b55b8921c87be2..24d6c52705457e99bdb781d2230313df9721ff86 100644 --- a/contexthub/common/vts/ContexthubCallbackBase.h +++ b/contexthub/common/vts/ContexthubCallbackBase.h @@ -27,7 +27,8 @@ namespace vts_utils { // Base callback implementation that just logs all callbacks by default, but // records a failure if -class ContexthubCallbackBase : public V1_0::IContexthubCallback { +template +class ContexthubCallbackBase : public CallbackType { public: virtual Return handleClientMsg(const V1_0::ContextHubMsg& /*msg*/) override { ALOGD("Got client message callback"); diff --git a/contexthub/common/vts/VtsHalContexthubUtils.h b/contexthub/common/vts/VtsHalContexthubUtils.h index 8f9b6946d9a50d5a944fe656baaff1c9f3e87993..dff1865f4ca93579142fbb5302e006655b2db2a8 100644 --- a/contexthub/common/vts/VtsHalContexthubUtils.h +++ b/contexthub/common/vts/VtsHalContexthubUtils.h @@ -30,6 +30,10 @@ namespace hardware { namespace contexthub { namespace vts_utils { +// App ID with vendor "GoogT" (Google Testing), app identifier 0x555555. This +// app ID is reserved and must never appear in the list of loaded apps. +constexpr uint64_t kNonExistentAppId = 0x476f6f6754555555; + #define ASSERT_OK(result) ASSERT_EQ(result, ::android::hardware::contexthub::V1_0::Result::OK) #define EXPECT_OK(result) EXPECT_EQ(result, ::android::hardware::contexthub::V1_0::Result::OK) @@ -64,6 +68,29 @@ static std::vector> getHalAndHubIdList() { return parameters; } +// Wait for a callback to occur (signaled by the given future) up to the +// provided timeout. If the future is invalid or the callback does not come +// within the given time, returns false. +template +bool waitForCallback(std::future future, ReturnType* result, + std::chrono::milliseconds timeout = std::chrono::seconds(5)) { + auto expiration = std::chrono::system_clock::now() + timeout; + + EXPECT_NE(result, nullptr); + EXPECT_TRUE(future.valid()); + if (result != nullptr && future.valid()) { + std::future_status status = future.wait_until(expiration); + EXPECT_NE(status, std::future_status::timeout) << "Timed out waiting for callback"; + + if (status == std::future_status::ready) { + *result = future.get(); + return true; + } + } + + return false; +} + } // namespace vts_utils } // namespace contexthub } // namespace hardware diff --git a/current.txt b/current.txt index a2b21d49d1379f06c5304a37dd049aa576f5d33c..59fbfa96be1c44d00eddc3cd78e0cd20f8a3d5b5 100644 --- a/current.txt +++ b/current.txt @@ -4,6 +4,7 @@ # Test HALs 717c17cd380bb48710dff601d1a03351d4ebc28028353d5d60489248f506523c android.hardware.tests.lazy@1.0::ILazy +67222a2ed4071b6c232e671ce0f4be4f85c1c6fb017ec2355396adaae1fe26be android.hardware.tests.lazy@1.1::ILazy # HALs released in Android O @@ -767,6 +768,14 @@ a64467bae843569f0d465c5be7f0c7a5b987985b55a3ef4794dd5afc68538650 android.hardwar 98592d193a717066facf91428426e5abe211e3bd718bc372e29fb944ddbe6e7c android.hardware.wifi.supplicant@1.3::types # ABI preserving changes to HALs during Android S +# b/193346383 +93d29fbe2fcc5e4e053a9db7c9abbd9190c46b85b443f2698a3460db2ee76c8d android.hardware.camera.metadata@3.2::types +159a0069336035852e9eca6354b86b7990680d1b239f23ef2f631b01807c4cb9 android.hardware.camera.metadata@3.5::types +e042522daa4b5f7fd4a0a19bcdadb93c79a1b04c09ef2c9813a3a8941032f3f5 android.hardware.contexthub@1.0::IContexthub +c2f64133b83ede65c9939ef97ab5bd867b73faf3dba0e7e69f77c3c43d9e487e android.hardware.contexthub@1.0::IContexthubCallback +bda492ec4021d13869de72bd6f8c15c5837b78d6136b8d538efec5320573a5ec android.hardware.gnss@1.0::IGnssMeasurementCallback +7ae2025662e30e690a3ffa1c65cc972c6297a68638174055c33cbf3d2e4bbddc android.hardware.gnss@1.1::IGnssMeasurementCallback +11e9e1a1fd0c9b3d9648750d4b10dc2a839d3a6688904c3fc49500a4e7ca75b0 android.hardware.gnss@2.1::IGnssMeasurementCallback 2c331a9605f3a08d9c1e0a36169ca57758bc43c11a78ef3f3730509885e52c15 android.hardware.graphics.composer@2.4::IComposerClient 3da3ce039247872d95c6bd48621dbfdfa1c2d2a91a90f257862f87ee2bc46300 android.hardware.health@2.1::types 9679f27a42f75781c8993ef163ed92808a1928de186639834841d0b8e326e63d android.hardware.gatekeeper@1.0::IGatekeeper @@ -800,7 +809,7 @@ bc3c8c233085fca3879dc74b490b9e5bc1063258470d3b4c12f7a74bf215cbbd android.hardwar 1d201e15c553cd44c62864ac8d7039351ddf048a7ee61e380f6efb0904442eb8 android.hardware.audio@7.0::IPrimaryDevice 38afa920e6d36013b5a800e8c82eefeebd24602de24441e2f8ce5b3bdf62d3af android.hardware.audio@7.0::IStream 77d84330418abba5a92b0cdc4e27fa7c85c27344eaf7eeef441b8e88829ee475 android.hardware.audio@7.0::IStreamIn -9e4d79ed8f3c7e18455f371342ea1802f080bae38f64db746cc433305ee1978b android.hardware.audio@7.0::IStreamOut +40c5c43e923da23497c0e3d5a1c2d699b423a0268e1e971f918e4854e1c39951 android.hardware.audio@7.0::IStreamOut 54cbc3c637fe8d4b889ccb5690e5e3069ca8efd9c6607ce1d021a3f47576c67e android.hardware.audio@7.0::IStreamOutCallback 8036ae0a68a698a79207218018de5f41aed344723f644112ffc99e20e5e2e9ff android.hardware.audio@7.0::IStreamOutEventCallback 84978dbd15d4fa8be6073d0974755f7718ee0cde519ce71449fb734f53cee46b android.hardware.audio@7.0::types @@ -820,21 +829,75 @@ a7d74d7e7e0b1e3b739f233b7776bf01e868856a536f5cdac0f307e9c2850e64 android.hardwar b4cbc1f2d38787f2ad069a8e4d10c0896287531a2596f0de0283e390b0ecf05d android.hardware.audio.effect@7.0::IVirtualizerEffect 2b5681e1ea6a2db0dc1e84edb96d3de2f7daf306046543e7956be76dcb8f20fb android.hardware.audio.effect@7.0::IVisualizerEffect fa1e2d78e66fd662de93cb479ffd55947fe54f51cb53915814b3d3e3036c86a5 android.hardware.audio.effect@7.0::types +e3865e74cb1a6e6afd38c7aa84115cb109ce47b972132de5242bc3838d2771f6 android.hardware.automotive.vehicle@2.0::types +b3caf524c46a47d67e6453a34419e1881942d059e146cda740502670e9a752c3 android.hardware.automotive.vehicle@2.0::IVehicle +7ce8728b27600e840cacf0a832f6942819fe535f9d3797ae052d5eef5065921c android.hardware.automotive.vehicle@2.0::IVehicleCallback +b525e91d886379c13588f4975bb04d625d46e1f41b4453792c4b2db1e7ff4340 android.hardware.biometrics.fingerprint@2.3::IBiometricsFingerprint +7a78e9963bec0b071e7d46928c6100e2174270892d3f15a1eaad074997adf279 android.hardware.biometrics.fingerprint@2.3::IBiometricsFingerprint # Added for b/160189286 for Android S 4baf8e0eca4aa896cc9ceb7bb676aaf4fa21372ef8b49eed68eced1221c3dc0d android.hardware.bluetooth.audio@2.1::IBluetoothAudioProvider d417a9212c8f96e3a06a2f221c8c5756c765355b2b81de2b2a65d4c9eee85401 android.hardware.bluetooth.audio@2.1::IBluetoothAudioProvidersFactory c17d9e27abd37ae5a8ff8da08fc5c9b13a264670feef6bbbc9d3ab1915216130 android.hardware.bluetooth.audio@2.1::types 6763dd2273b1b47f3ac68af9b66870287eba33fb5b4d66e8fe1d30ae18ce24cb android.hardware.boot@1.2::IBootControl +1a1dff6e8d25dbc02a69fed3c077dd0782b30331ca3f345848ec52fc67744224 android.hardware.camera.device@3.7::ICameraDevice +3be6faa3d11ad9c7ec01a1a0a009cf11cb65d701d109dab37613ce9cfb3cdd60 android.hardware.camera.device@3.7::ICameraDeviceSession +3740ec773b2eb8fa6bd8c6e879eedb56c4e4306b88f1c20fa51103d791d871b1 android.hardware.camera.device@3.7::ICameraInjectionSession +d272697484c41bbf76a0924d2aaebf065ce37a822fcb438316eb5dd2d112f052 android.hardware.camera.device@3.7::types +e932e7ef95210142e1fd3a4504e1d19bdb1acc988450f1ced543f3401f67855a android.hardware.camera.metadata@3.6::types +98ff825a7d37e5ab983502d13cec1f2e5a9cac9b674b6ff1a52bcf540f4e315e android.hardware.camera.provider@2.7::ICameraProvider +51fd14005859b16be55872660c34f5d423c77a2abcc5d4bdd5a537c40f32516b android.hardware.camera.provider@2.7::types +3500d3c4e2d49eeed2f3239330a166beb2db2d5071b84d9c738b048c2d54a3d9 android.hardware.contexthub@1.2::IContexthub +5ec58b1f9283d47857e3e70fbd39d9a4ff030c12d6fa3113af2b59fa3c77046e android.hardware.contexthub@1.2::IContexthubCallback +afe69d8a66fcbd87aa1d5c033e91017237d5466110538a57e8287d7efa114538 android.hardware.contexthub@1.2::types +c38a42661a90a0cef538b1757e29268d3a91867fcadf3c44185c992566da0b81 android.hardware.drm@1.4::ICryptoFactory +0e96e7699ee74d65432a8712e6b2474b425a3a079c55f4e3122aa65ff2b778a4 android.hardware.drm@1.4::ICryptoPlugin +4ebbe2b8ff3a6c8729619fe9ce62429f4b561d2e26e32eb54675babddfec9e59 android.hardware.drm@1.4::IDrmFactory +a71fa24841f1398620f9baf738863dbaf29bde62cd171ac7b4608797ca55e35d android.hardware.drm@1.4::IDrmPlugin +48127234347525a9d0fad9b7b79be5762d14e51cc87b1a09329a2452e06f3307 android.hardware.drm@1.4::types 0c0657fad2239c2c7ec363d3b13f2e002d1c267ca89d2cc96d2b1de0475386cb android.hardware.fastboot@1.1::IFastboot +61e5d73d12d558a3115e5b1e2e740fbe149235c36c607881f053f2f443cafdf5 android.hardware.media.c2@1.2::IComponent +fcd17fb86c1b5570c8b55d855fd2ab93e4a2c6629d9ba9374372928469aad961 android.hardware.media.c2@1.2::IComponentStore +8b149e213e77f4be50dcaf68ab55b8220ca62abd9443969e7f46a197b5adddfc android.hardware.media.c2@1.2::types 3e8866987de4ecb48807c09d4c88ec38365930a22415f1b74edf8b14da17846b android.hardware.radio@1.6::IRadio 715789427a44cc78f9d123b0ceb9e035e4ac2b1049501337c23a512e85b87850 android.hardware.radio@1.6::IRadioIndication -2e9c08c4bc9539d8da28d7de33500f87148f7fa2e377238ee898b41752ac4f29 android.hardware.radio@1.6::IRadioResponse -278e1997a379f2e93f0b7743c5bb28afb0cd6922915a760d58c2dd8177fde6ee android.hardware.radio@1.6::types +4443f5c5f789d77ab491aad4cf4673d131bba45014d6bb4816888cbac37aa8c1 android.hardware.radio@1.6::IRadioResponse +d06226cd3e916bb866b016b22f35c89c1d9286f62a4aa82a549daf8d52805183 android.hardware.radio@1.6::types f22813615be1445ddd817655c054fc69dc9efea56c9035cd0757f3cbed190641 android.hardware.radio.config@1.3::IRadioConfig c9ad18729268593d14681d88ffad1c97e707444a45e1b4ed804dab949edbd84f android.hardware.radio.config@1.3::IRadioConfigResponse -78dcb9a6975e8b377cb90bbe952078162960941468c992dcd2e1830a477b8c03 android.hardware.radio.config@1.3::types fd43298c43f70130c747a642ee43b0c242ac0cebffb377faa24f2725f0aa6caf android.hardware.tetheroffload.control@1.1::IOffloadControl ead4ec8713a2cb40906fe31ba793d21a6b1190143c446690d16a6ea686aa2fea android.hardware.tetheroffload.control@1.1::ITetheringOffloadCallback e34b4c7bec5e032c14804707ca924dd6b99ed5ba139da7505fe7d698d0fe178f android.hardware.tetheroffload.control@1.1::types +63dfdb433ac73fb2bf4a44d2ade7b7e289e155835206d1939640d6c88d208994 android.hardware.tv.cec@1.1::IHdmiCec +b9682587677ce9c872e04f0e9fd6c9c78a56ae795c07cbf8c50100e0351d4c44 android.hardware.tv.cec@1.1::IHdmiCecCallback +4c4243db0fad48931622b07c5ada346ed7b8e49ace30da88fde754c976e430c2 android.hardware.tv.cec@1.1::types +b8305da72fb09d5c8ae9f89bebdc30a4c1908a62253b705f9cb6df4dc28c9094 android.hardware.tv.tuner@1.1::IFilter +3e29c02ccc3f0c22414eb05604a0cfe93af4521c49fc4165f0fdcaa3c975dc4f android.hardware.tv.tuner@1.1::IFilterCallback +0f2deed38165f154f27a01c3e70e6ea770520d67f7dbf3630ee45992f7a644be android.hardware.tv.tuner@1.1::IFrontend +695213b5c7ccd13cc0227a7aaca652f77b5a5a2352483575f2905d1361562b5d android.hardware.tv.tuner@1.1::IFrontendCallback +6fd387a7ff5916def0d1c9010aa501b30ef2fe34f161164531c9631f67ff098a android.hardware.tv.tuner@1.1::ITuner +ea2453fa7563783fa0cd7c09aa86e6cd7ac799a1d0fc439b34c416d1c55062d1 android.hardware.tv.tuner@1.1::types +bcebdb0b3b59bd144eefc1b17aa96609c1b23bc9a5f7e0d7060dabd7f06ef9c0 android.hardware.usb@1.3::IUsb +f2a87e56164145160b3b3a097dba2ccc1b0ffc2fb87e8c984adfe59f47b5ecf7 android.hardware.usb.gadget@1.2::IUsbGadget +c539325b22bce686876f062b16292038555ae2857e8d34aa63a975df18e113b1 android.hardware.usb.gadget@1.2::IUsbGadgetCallback +95e23dbfcfb38d390f236e5fff77dd518ba272a85551df6ecb4707fe466e60bd android.hardware.usb.gadget@1.2::types +bb7b8f653452f2044e1db587ceb415edf72201ab9c1d547564c3f75bfab65a83 android.hardware.wifi@1.5::IWifi +c66c3ea1b375e69d7ad820d67950305a463b5a50908c4fddcbbdbab8bbac3951 android.hardware.wifi@1.5::IWifiApIface +a1193d37f7e13222bf79ef4b73dbad15b0f0a330d03356d12226dcda20de44a7 android.hardware.wifi@1.5::IWifiChip +d78f1c169cf7e92ddf49e0b6a2b6d5566730e8085a56aefd9140c76b107bb35d android.hardware.wifi@1.5::IWifiEventCallback +45ab93378f02a8bc3a658853ce4d3fdc1e9fa2c1d1c545821d490bf0f4d96cec android.hardware.wifi@1.5::IWifiNanIface +b20261b97359a8b8784700d4278aa00a8666fcd9fc259c3a8386ba34bad5ec83 android.hardware.wifi@1.5::IWifiNanIfaceEventCallback +b154b9fe8b94cf64392766bfd932c023edf658ba8ecc4b952f8424058120e5bd android.hardware.wifi@1.5::IWifiStaIface +ee214c95481f61aefc1255987c92be6c3b4519be327467b1692630572060b489 android.hardware.wifi@1.5::types +c972b342dd527a3952b5d2377bd6483dec48f6b85292ca537a97705381c7ea3c android.hardware.wifi.hostapd@1.3::IHostapd +6a3152de16dfa71b065c686e84ce8b85317745c0b9dd8f4790009ec6950d96c8 android.hardware.wifi.hostapd@1.3::IHostapdCallback +6d361bfd0ff1ecb6d2dddb72636ddce4d706453391de401852a6a53effb7b599 android.hardware.wifi.hostapd@1.3::types +17818b6b1952a75e4364ae82c534b9d2f5c0a9765a56256b16faa5a5cf45d3a8 android.hardware.wifi.supplicant@1.4::ISupplicant +d29fe62973c49b6fa40eb56c28567e37c4bbec015ff59111edfae446301dc06d android.hardware.wifi.supplicant@1.4::ISupplicantP2pIface +ea465970e96d9605ee6f6706b3b512726c66d2644738added9128c739f8f8b0c android.hardware.wifi.supplicant@1.4::ISupplicantP2pIfaceCallback +026b9a46658ee82b154ee624adc30a454f6401230db5eb446ead42e7ef51fc80 android.hardware.wifi.supplicant@1.4::ISupplicantStaIface +0d5adbc7ca369ca30c64a3e3f021335f991055787bc80ab44bbbbaa056d5515b android.hardware.wifi.supplicant@1.4::ISupplicantStaIfaceCallback +c8a57364f6ad20842be14f4db284df5304f7521ca8eac6bcc1fa6c5b466fb8a6 android.hardware.wifi.supplicant@1.4::ISupplicantStaNetwork +2123482b69f3b531c88023aa2a007110e130efbf4ed68ac9ce0bc55d5e82bc8b android.hardware.wifi.supplicant@1.4::ISupplicantStaNetworkCallback +0821f516e4d428bc15251969f7e19411c94d8f2ccbd99e1fc8168d8e49e38b0f android.hardware.wifi.supplicant@1.4::types # ABI preserving changes to HALs during Android T 62ace52d9c3ff1f60f94118557a2aaf0b953513e59dcd34d5f94ae28d4c7e780 android.hardware.fastboot@1.0::IFastboot diff --git a/drm/1.0/default/Android.bp b/drm/1.0/default/Android.bp index a5cba5c2f450e705a833e42e2411014dab8edb19..cbdab4ffe0c832977353cb174946cc5a9a00c0dd 100644 --- a/drm/1.0/default/Android.bp +++ b/drm/1.0/default/Android.bp @@ -60,8 +60,8 @@ android_hardware_drm_1_0_multilib { soong_config_variables: { TARGET_ENABLE_MEDIADRM_64: { compile_multilib: "both", - } - } + }, + }, } android_hardware_drm_1_0_multilib { @@ -70,8 +70,8 @@ android_hardware_drm_1_0_multilib { soong_config_variables: { TARGET_ENABLE_MEDIADRM_64: { compile_multilib: "first", - } - } + }, + }, } cc_defaults { @@ -99,7 +99,7 @@ cc_binary { name: "android.hardware.drm@1.0-service", defaults: [ "android.hardware.drm@1.0-multilib-exe", - "android.hardware.drm@1.0-service-defaults" + "android.hardware.drm@1.0-service-defaults", ], init_rc: ["android.hardware.drm@1.0-service.rc"], srcs: ["service.cpp"], @@ -111,7 +111,7 @@ cc_binary { name: "android.hardware.drm@1.0-service-lazy", defaults: [ "android.hardware.drm@1.0-multilib-exe", - "android.hardware.drm@1.0-service-defaults" + "android.hardware.drm@1.0-service-defaults", ], overrides: ["android.hardware.drm@1.0-service"], init_rc: ["android.hardware.drm@1.0-service-lazy.rc"], diff --git a/drm/1.2/vts/functional/drm_hal_test.cpp b/drm/1.2/vts/functional/drm_hal_test.cpp index 0dfff265288bb463db99e8651caabbb578a5c8bd..2d1068dcd22977039cf12f16d54414e6dd10a517 100644 --- a/drm/1.2/vts/functional/drm_hal_test.cpp +++ b/drm/1.2/vts/functional/drm_hal_test.cpp @@ -172,6 +172,7 @@ void checkKeySetIdState(Status status, OfflineLicenseState state) { TEST_P(DrmHalTest, OfflineLicenseTest) { auto sessionId = openSession(); hidl_vec keySetId = loadKeys(sessionId, KeyType::OFFLINE); + closeSession(sessionId); auto res = drmPlugin->getOfflineLicenseKeySetIds( [&](Status status, const hidl_vec& keySetIds) { @@ -201,8 +202,6 @@ TEST_P(DrmHalTest, OfflineLicenseTest) { err = drmPlugin->removeOfflineLicense(keySetId); EXPECT_EQ(Status::BAD_VALUE, err); - - closeSession(sessionId); } /** @@ -212,6 +211,8 @@ TEST_P(DrmHalTest, OfflineLicenseStateTest) { auto sessionId = openSession(); DrmHalVTSVendorModule_V1::ContentConfiguration content = getContent(KeyType::OFFLINE); hidl_vec keySetId = loadKeys(sessionId, content, KeyType::OFFLINE); + closeSession(sessionId); + drmPlugin->getOfflineLicenseState(keySetId, checkKeySetIdState); hidl_vec keyRequest = getKeyRequest(keySetId, content, KeyType::RELEASE); @@ -226,7 +227,6 @@ TEST_P(DrmHalTest, OfflineLicenseStateTest) { provideKeyResponse(keySetId, keyResponse); drmPlugin->getOfflineLicenseState(keySetId, checkKeySetIdState); - closeSession(sessionId); } /** diff --git a/drm/1.3/vts/functional/drm_hal_test_main.cpp b/drm/1.3/vts/functional/drm_hal_test_main.cpp index b8f64c0f6d5ff1f47d1897392a608e402c60f01a..8abba694d720d533ad354777062d9290f48a3a7e 100644 --- a/drm/1.3/vts/functional/drm_hal_test_main.cpp +++ b/drm/1.3/vts/functional/drm_hal_test_main.cpp @@ -94,27 +94,34 @@ INSTANTIATE_TEST_CASE_P(PerInstanceUuidV1_0, DrmHalVendorDecryptTest, testing::ValuesIn(kAllInstances), drm_vts::PrintParamInstanceToString); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DrmHalClearkeyFactoryTest); INSTANTIATE_TEST_SUITE_P(PerInstanceUuidV1_0, DrmHalClearkeyFactoryTest, testing::ValuesIn(kAllInstances), drm_vts::PrintParamInstanceToString); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DrmHalClearkeyPluginTest); INSTANTIATE_TEST_SUITE_P(PerInstanceUuidV1_0, DrmHalClearkeyPluginTest, testing::ValuesIn(kAllInstances), drm_vts::PrintParamInstanceToString); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DrmHalClearkeyDecryptTest); INSTANTIATE_TEST_SUITE_P(PerInstanceUuidV1_0, DrmHalClearkeyDecryptTest, testing::ValuesIn(kAllInstances), drm_vts::PrintParamInstanceToString); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DrmHalClearkeyTest); INSTANTIATE_TEST_SUITE_P(PerInstanceUuidV1_1, DrmHalClearkeyTest, testing::ValuesIn(kAllInstances), PrintParamInstanceToString); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DrmHalTest); INSTANTIATE_TEST_SUITE_P(PerInstanceUuidV1_2, DrmHalTest, testing::ValuesIn(kAllInstances), PrintParamInstanceToString); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DrmHalClearkeyTestV1_2); INSTANTIATE_TEST_SUITE_P(PerInstanceUuidV1_2, DrmHalClearkeyTestV1_2, testing::ValuesIn(kAllInstances), PrintParamInstanceToString); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DrmHalTestV1_3); INSTANTIATE_TEST_SUITE_P(PerInstanceUuidV1_3, DrmHalTestV1_3, testing::ValuesIn(kAllInstances), PrintParamInstanceToString); diff --git a/drm/1.4/Android.bp b/drm/1.4/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..d1bb4bc858e1186fe6fbb546f26c408be96145dd --- /dev/null +++ b/drm/1.4/Android.bp @@ -0,0 +1,30 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +hidl_interface { + name: "android.hardware.drm@1.4", + root: "android.hardware", + srcs: [ + "ICryptoFactory.hal", + "ICryptoPlugin.hal", + "IDrmFactory.hal", + "IDrmPlugin.hal", + "types.hal", + ], + interfaces: [ + "android.hardware.drm@1.0", + "android.hardware.drm@1.1", + "android.hardware.drm@1.2", + "android.hardware.drm@1.3", + "android.hidl.base@1.0", + ], + gen_java: false, +} diff --git a/drm/1.4/ICryptoFactory.hal b/drm/1.4/ICryptoFactory.hal new file mode 100644 index 0000000000000000000000000000000000000000..6cbf9e34493c5a29683bb438e6f40e23091f3ce2 --- /dev/null +++ b/drm/1.4/ICryptoFactory.hal @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.hardware.drm@1.4; + +import @1.3::ICryptoFactory; + +/** + * ICryptoFactory is the main entry point for interacting with a vendor's + * crypto HAL to create crypto plugins. Crypto plugins create crypto sessions + * which are used by a codec to decrypt protected video content. + * + * The 1.4 factory must always create 1.4 ICryptoPlugin interfaces, which are + * returned via the 1.0 createPlugin method. + * + * To use 1.4 features the caller must cast the returned interface to a + * 1.4 HAL, using V1_4::ICryptoPlugin::castFrom(). + */ +interface ICryptoFactory extends @1.3::ICryptoFactory { +}; diff --git a/drm/1.4/ICryptoPlugin.hal b/drm/1.4/ICryptoPlugin.hal new file mode 100644 index 0000000000000000000000000000000000000000..addfdd08d9edaeb3ad5e472b910efbcee837f723 --- /dev/null +++ b/drm/1.4/ICryptoPlugin.hal @@ -0,0 +1,39 @@ +/** + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.hardware.drm@1.4; + +import @1.2::ICryptoPlugin; +import @1.4::LogMessage; +import @1.4::Status; + +/** + * ICryptoPlugin is the HAL for vendor-provided crypto plugins. + * It allows crypto sessions to be opened and operated on, to + * load crypto keys for a codec to decrypt protected video content. + */ +interface ICryptoPlugin extends @1.2::ICryptoPlugin { + + /** + * @return logMessages latest plugin level log messages. Can be used + * by apps in diagnosis of errors. + * @return status the status of the call. The status must be: + * OK on success; + * GENERAL_OEM_ERROR on OEM-provided, low-level component failures; + * GENERAL_PLUGIN_ERROR on unexpected plugin-level errors. + */ + getLogMessages() generates (@1.4::Status status, vec logMessages); + +}; diff --git a/drm/1.4/IDrmFactory.hal b/drm/1.4/IDrmFactory.hal new file mode 100644 index 0000000000000000000000000000000000000000..035a2983ae9e5d0ddb6ff19b3241e7f2fae3f357 --- /dev/null +++ b/drm/1.4/IDrmFactory.hal @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.hardware.drm@1.4; + +import @1.3::IDrmFactory; + +/** + * IDrmFactory is the main entry point for interacting with a vendor's + * drm HAL to create drm plugin instances. A drm plugin instance + * creates drm sessions which are used to obtain keys for a crypto + * session so it can decrypt protected video content. + * + * The 1.4 factory must always create 1.4 IDrmPlugin interfaces, which are + * returned via the 1.0 createPlugin method. + * + * To use 1.4 features the caller must cast the returned interface to a + * 1.4 HAL, using V1_4::IDrmPlugin::castFrom(). + */ + +interface IDrmFactory extends @1.3::IDrmFactory { +}; diff --git a/drm/1.4/IDrmPlugin.hal b/drm/1.4/IDrmPlugin.hal new file mode 100644 index 0000000000000000000000000000000000000000..df04b9f2267a0bc16ea9c885b61a6202ac787327 --- /dev/null +++ b/drm/1.4/IDrmPlugin.hal @@ -0,0 +1,76 @@ +/** + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.hardware.drm@1.4; + +import @1.0::Status; +import @1.0::SessionId; +import @1.1::SecurityLevel; +import @1.2::IDrmPlugin; +import @1.4::LogMessage; +import @1.4::Status; + +/** + * IDrmPlugin is used to interact with a specific drm plugin that was + * created by IDrmFactory::createPlugin. A drm plugin provides methods for + * obtaining drm keys to be used by a codec to decrypt protected video + * content. + */ +interface IDrmPlugin extends @1.2::IDrmPlugin { + + /** + * Check if the specified mime-type & security level require a secure decoder + * component. + * + * @param mime The content mime-type + * @param level the requested security level + * @return secureRequired must be true if and only if a secure decoder is required + * for the specified mime-type & security level + */ + requiresSecureDecoder(string mime, @1.1::SecurityLevel level) generates (bool secureRequired); + + /** + * Check if the specified mime-type requires a secure decoder component + * at the highest security level supported on the device. + * + * @param mime The content mime-type + * @return secureRequired must be true if and only if a secure decoder is required + * for the specified mime-type + */ + requiresSecureDecoderDefault(string mime) generates (bool secureRequired); + + /** + * Set playback id of a drm session. The playback id can be used to join drm session metrics + * with metrics from other low level media components, e.g. codecs, or metrics from the high + * level player. + * + * @param sessionId drm session id + * @param playbackId high level playback id + * @return status the status of the call. The status must be OK on success, or + * ERROR_DRM_SESSION_NOT_OPENED if the drm session cannot be found + */ + setPlaybackId(SessionId sessionId, string playbackId) generates (@1.0::Status status); + + /** + * @return logMessages latest plugin level log messages. Can be used + * by apps in diagnosis of errors. + * @return status the status of the call. The status must be: + * OK on success; + * GENERAL_OEM_ERROR on OEM-provided, low-level component failures; + * GENERAL_PLUGIN_ERROR on unexpected plugin-level errors. + */ + getLogMessages() generates (@1.4::Status status, vec logMessages); + +}; diff --git a/drm/1.4/types.hal b/drm/1.4/types.hal new file mode 100644 index 0000000000000000000000000000000000000000..8cb27cdbe9a95898811c26ce5181c25c8960ef77 --- /dev/null +++ b/drm/1.4/types.hal @@ -0,0 +1,151 @@ +/** + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.drm@1.4; + +import @1.2::Status; + +enum LogPriority : uint32_t { + UNKNOWN, + DEFAULT, + VERBOSE, + DEBUG, + INFO, + WARN, + ERROR, + FATAL, +}; + +/** + * Returned by getLogMessages to report error diagnostics to the + * app. + * + * The |message| field is for informational purposes only, and + * NOT meant to be parsed programmatically when handling errors. + * For programmatic error handling, please check the return |Status| + * of APIs instead. + */ +struct LogMessage { + /** + * Epoch time in milliseconds. + */ + int64_t timeMs; + LogPriority priority; + string message; +}; + +enum Status : @1.2::Status { + /** + * queueSecureInput buffer called with 0 subsamples. + */ + CANNOT_DECRYPT_ZERO_SUBSAMPLES, + /** + * An error happened within the crypto library used by the drm plugin. + */ + CRYPTO_LIBRARY_ERROR, + /** + * Non-specific error reported by the device OEM subsystem. + */ + GENERAL_OEM_ERROR, + /** + * Unexpected internal failure in the drm/crypto plugin. + */ + GENERAL_PLUGIN_ERROR, + /** + * The init data parameter passed to getKeyRequest is empty or invalid. + */ + INIT_DATA_INVALID, + /** + * Either the key was not loaded from the license before attempting the + * operation, or the key ID parameter provided by the app is incorrect. + */ + KEY_NOT_LOADED, + /** + * The license response was empty, fields are missing or otherwise unable + * to be parsed. + */ + LICENSE_PARSE_ERROR, + /** + * The operation (e.g. to renew or persist a license) is prohibited by the + * license policy. + */ + LICENSE_POLICY_ERROR, + /** + * Failed to generate a release request because a field in the stored + * license is empty or malformed. + */ + LICENSE_RELEASE_ERROR, + /** + * The license server detected an error in the license request. + */ + LICENSE_REQUEST_REJECTED, + /** + * Failed to restore an offline license because a field is empty or + * malformed. + */ + LICENSE_RESTORE_ERROR, + /** + * License is in an invalid state for the attempted operation. + */ + LICENSE_STATE_ERROR, + /** + * Certificate is malformed or is of the wrong type. + */ + MALFORMED_CERTIFICATE, + /** + * Failure in the media framework. + */ + MEDIA_FRAMEWORK_ERROR, + /** + * Certificate has not been set. + */ + MISSING_CERTIFICATE, + /** + * There was an error loading the provisioned certificate. + */ + PROVISIONING_CERTIFICATE_ERROR, + /** + * Required steps where not performed before provisioning was attempted. + */ + PROVISIONING_CONFIGURATION_ERROR, + /** + * The provisioning response was empty, fields are missing or otherwise + * unable to be parsed. + */ + PROVISIONING_PARSE_ERROR, + /** + * The provisioning server detected an error in the provisioning request. + */ + PROVISIONING_REQUEST_REJECTED, + /** + * Provisioning failed in a way that is likely to succeed on a subsequent + * attempt. + */ + RETRYABLE_PROVISIONING_ERROR, + /** + * Failed to generate a secure stop request because a field in the stored + * license is empty or malformed. + */ + SECURE_STOP_RELEASE_ERROR, + /** + * The plugin was unable to read data from the filesystem. + */ + STORAGE_READ_FAILURE, + /** + * The plugin was unable to write data to the filesystem. + */ + STORAGE_WRITE_FAILURE, +}; diff --git a/drm/1.4/vts/OWNERS b/drm/1.4/vts/OWNERS new file mode 100644 index 0000000000000000000000000000000000000000..a652208454a104cb5f228236e00c9d39111b5b7b --- /dev/null +++ b/drm/1.4/vts/OWNERS @@ -0,0 +1,7 @@ +edwinwong@google.com +fredgc@google.com +jtinker@google.com +kylealexander@google.com +rfrias@google.com +robertshih@google.com +sigquit@google.com diff --git a/drm/1.4/vts/functional/Android.bp b/drm/1.4/vts/functional/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..e18d0883a24d83cbd195e8215fe6337d64535339 --- /dev/null +++ b/drm/1.4/vts/functional/Android.bp @@ -0,0 +1,104 @@ +// +// Copyright (C) 2021 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_library_static { + name: "android.hardware.drm@1.4-vts", + defaults: ["VtsHalTargetTestDefaults"], + local_include_dirs: [ + "include", + ], + srcs: [ + "drm_hal_test.cpp", + ], + shared_libs: [ + "android.hardware.drm@1.0", + "android.hardware.drm@1.1", + "android.hardware.drm@1.2", + "android.hardware.drm@1.3", + "android.hardware.drm@1.4", + "android.hidl.allocator@1.0", + "android.hidl.memory@1.0", + "libhidlmemory", + "libnativehelper", + ], + static_libs: [ + "android.hardware.drm@1.0-helper", + "android.hardware.drm@1.2-vts", + "libdrmvtshelper", + ], + export_static_lib_headers: [ + "android.hardware.drm@1.2-vts", + ], + export_include_dirs: [ + "include", + ], +} + +cc_test { + name: "VtsHalDrmV1_4TargetTest", + defaults: ["VtsHalTargetTestDefaults"], + include_dirs: ["hardware/interfaces/drm/1.0/vts/functional"], + srcs: [ + "drm_hal_test_main.cpp", + ], + whole_static_libs: [ + "android.hardware.drm@1.4-vts", + ], + shared_libs: [ + "android.hardware.drm@1.0", + "android.hardware.drm@1.1", + "android.hardware.drm@1.2", + "android.hardware.drm@1.3", + "android.hardware.drm@1.4", + "android.hidl.allocator@1.0", + "android.hidl.memory@1.0", + "libcrypto", + "libhidlmemory", + "libnativehelper", + ], + static_libs: [ + "android.hardware.drm@1.0-helper", + "android.hardware.drm@1.2-vts", + "libdrmvtshelper", + ], + arch: { + arm: { + data: [":libvtswidevine-arm-prebuilts"], + }, + arm64: { + data: [":libvtswidevine-arm64-prebuilts"], + }, + x86: { + data: [":libvtswidevine-x86-prebuilts"], + }, + x86_64: { + data: [":libvtswidevine-x86_64-prebuilts"], + }, + }, + test_suites: [ + "general-tests", + "vts", + ], +} diff --git a/drm/1.4/vts/functional/AndroidTest.xml b/drm/1.4/vts/functional/AndroidTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..b18da49a8c3aaac98712fd731024cbf2894244ec --- /dev/null +++ b/drm/1.4/vts/functional/AndroidTest.xml @@ -0,0 +1,38 @@ + + + + diff --git a/drm/1.4/vts/functional/drm_hal_test.cpp b/drm/1.4/vts/functional/drm_hal_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f9fa0bde3b873d33f2d9b88981d5b10ea20aa04b --- /dev/null +++ b/drm/1.4/vts/functional/drm_hal_test.cpp @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "drm_hal_test@1.4" + +#include "android/hardware/drm/1.4/vts/drm_hal_test.h" + +namespace android { +namespace hardware { +namespace drm { +namespace V1_4 { +namespace vts { + +const char* const DrmHalTest::kVideoMp4 = "video/mp4"; +const char* const DrmHalTest::kAudioMp4 = "audio/mp4"; +const uint32_t DrmHalTest::kSecLevelDefault = DrmHalTest::kSecLevelMax + 1; + +sp DrmHalTest::DrmPluginV1_4() const { + sp plugin(drm::V1_4::IDrmPlugin::castFrom(drmPlugin)); + EXPECT_NE(nullptr, plugin.get()); + return plugin; +} + +sp DrmHalTest::CryptoPlugin(const SessionId& sid) { + sp crypto; + auto res = cryptoFactory->createPlugin( + getUUID(), sid, + [&](V1_0::Status status, const sp& plugin) { + EXPECT_EQ(V1_0::Status::OK, status); + EXPECT_NE(nullptr, plugin.get()); + crypto = plugin; + }); + EXPECT_OK(res); + return crypto; +} + +SessionId DrmHalTest::OpenSession(uint32_t level = kSecLevelDefault) { + V1_0::Status err; + SessionId sessionId; + bool attemptedProvision = false; + + V1_0::IDrmPlugin::openSession_cb cb = [&]( + V1_0::Status status, + const hidl_vec &id) { + err = status; + sessionId = id; + }; + + while (true) { + Return res; + if (level > kSecLevelMax) { + res = drmPlugin->openSession(cb); + } else if (level >= kSecLevelMin) { + auto securityLevel = static_cast(level); + res = drmPlugin->openSession_1_1(securityLevel, cb); + } + EXPECT_OK(res); + if (V1_0::Status::ERROR_DRM_NOT_PROVISIONED == err + && !attemptedProvision) { + // provision once if necessary + provision(); + attemptedProvision = true; + continue; + } else if (V1_0::Status::ERROR_DRM_CANNOT_HANDLE == err) { + // must be able to handle default level + EXPECT_NE(kSecLevelDefault, level); + sessionId = {}; + } else { + EXPECT_EQ(V1_0::Status::OK, err); + EXPECT_NE(sessionId.size(), 0u); + } + break; + } + + return sessionId; +} + +TEST_P(DrmHalTest, RequiresSecureDecoder) { + for (uint32_t level : {kSecLevelMin, kSecLevelMax, kSecLevelDefault}) { + for (auto mime : {kVideoMp4, kAudioMp4}) { + auto sid = OpenSession(level); + if (sid.size() == 0u) { + continue; + } + auto drm = DrmPluginV1_4(); + sp crypto(CryptoPlugin(sid)); + if (drm == nullptr || crypto == nullptr) { + continue; + } + bool r1 = crypto->requiresSecureDecoderComponent(mime); + bool r2; + if (level == kSecLevelDefault) { + r2 = drm->requiresSecureDecoderDefault(mime); + } else { + auto sL = static_cast(level); + r2 = drm->requiresSecureDecoder(mime, sL); + } + EXPECT_EQ(r1, r2); + closeSession(sid); + } + } +} + +TEST_P(DrmHalTest, SetPlaybackId) { + auto testInfo = ::testing::UnitTest::GetInstance()->current_test_info(); + auto testName = testInfo->name(); + const hidl_string& pbId{testName}; + auto sid = OpenSession(); + auto drm = DrmPluginV1_4(); + if (drm == nullptr) { + return; + } + V1_0::Status err = drm->setPlaybackId(sid, pbId); + EXPECT_EQ(V1_0::Status::OK, err); + closeSession(sid); + + // search for playback id among metric attributes/values + bool foundPbId = false; + auto res = drmPlugin->getMetrics([&]( + V1_0::Status status, + hidl_vec metricGroups) { + EXPECT_EQ(V1_0::Status::OK, status); + for (const auto& group : metricGroups) { + for (const auto& metric : group.metrics) { + for (const auto& value : metric.values) { + if (value.stringValue == pbId) { + foundPbId = true; + break; + } + } + for (const auto& attr : metric.attributes) { + if (attr.stringValue == pbId) { + foundPbId = true; + break; + } + } + } + } + }); + EXPECT_OK(res); + EXPECT_TRUE(foundPbId); +} + +TEST_P(DrmHalTest, GetLogMessages) { + auto drm = DrmPluginV1_4(); + auto sid = OpenSession(); + auto crypto_1_0 = CryptoPlugin(sid); + sp crypto(V1_4::ICryptoPlugin::castFrom(crypto_1_0)); + + hidl_vec initData; + hidl_string mime{"text/plain"}; + V1_0::KeyedVector optionalParameters; + auto res = drmPlugin->getKeyRequest_1_2( + sid, initData, mime, V1_0::KeyType::STREAMING, + optionalParameters, [&](V1_2::Status status, const hidl_vec&, + V1_1::KeyRequestType, const hidl_string&) { + EXPECT_NE(V1_2::Status::OK, status); + }); + EXPECT_OK(res); + + V1_4::IDrmPlugin::getLogMessages_cb cb = [&]( + V1_4::Status status, + hidl_vec logs) { + EXPECT_EQ(V1_4::Status::OK, status); + EXPECT_NE(0, logs.size()); + for (auto log: logs) { + ALOGI("priority=[%u] message='%s'", log.priority, log.message.c_str()); + } + }; + + auto res2 = drm->getLogMessages(cb); + EXPECT_OK(res2); + + auto res3 = crypto->getLogMessages(cb); + EXPECT_OK(res3); + + closeSession(sid); +} + +} // namespace vts +} // namespace V1_4 +} // namespace drm +} // namespace hardware +} // namespace android diff --git a/drm/1.4/vts/functional/drm_hal_test_main.cpp b/drm/1.4/vts/functional/drm_hal_test_main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..65d1b7603865a7ef26cca0d849004b482e988dac --- /dev/null +++ b/drm/1.4/vts/functional/drm_hal_test_main.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Instantiate the set of test cases for each vendor module + */ + +#define LOG_TAG "drm_hal_test@1.4" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "android/hardware/drm/1.4/vts/drm_hal_test.h" + +using drm_vts::DrmHalTestParam; +using drm_vts::PrintParamInstanceToString; + +using android::hardware::drm::V1_4::vts::DrmHalTest; + +static const std::vector kAllInstances = [] { + using ::android::hardware::hidl_array; + using ::android::hardware::hidl_vec; + using ::android::hardware::drm::V1_4::ICryptoFactory; + using ::android::hardware::drm::V1_4::IDrmFactory; + + std::vector drmInstances = + android::hardware::getAllHalInstanceNames(IDrmFactory::descriptor); + std::vector cryptoInstances = + android::hardware::getAllHalInstanceNames(ICryptoFactory::descriptor); + std::set allInstances; + allInstances.insert(drmInstances.begin(), drmInstances.end()); + allInstances.insert(cryptoInstances.begin(), cryptoInstances.end()); + + std::vector firstInstanceUuidCombos; + for (const auto &instance : allInstances) { + auto drmFactory = IDrmFactory::getService(instance); + if (drmFactory == nullptr) { + continue; + } + drmFactory->getSupportedCryptoSchemes( + [&](const hidl_vec>& schemes) { + if (schemes.size() > 0) { + firstInstanceUuidCombos.push_back(DrmHalTestParam(instance, schemes[0])); + } + }); + } + return firstInstanceUuidCombos; +}(); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DrmHalTest); +INSTANTIATE_TEST_SUITE_P(PerInstance, DrmHalTest, + testing::ValuesIn(kAllInstances), + PrintParamInstanceToString); + +int main(int argc, char** argv) { +#if defined(__LP64__) + const char* kModulePath = "/data/local/tmp/64/lib"; +#else + const char* kModulePath = "/data/local/tmp/32/lib"; +#endif + DrmHalTest::gVendorModules + = new drm_vts::VendorModules(kModulePath); + if (DrmHalTest::gVendorModules->getPathList().size() == 0) { + std::cerr << "WARNING: No vendor modules found in " << kModulePath << + ", all vendor tests will be skipped" << std::endl; + } + ::testing::InitGoogleTest(&argc, argv); + int status = RUN_ALL_TESTS(); + ALOGI("Test result = %d", status); + return status; +} diff --git a/drm/1.4/vts/functional/include/android/hardware/drm/1.4/vts/drm_hal_test.h b/drm/1.4/vts/functional/include/android/hardware/drm/1.4/vts/drm_hal_test.h new file mode 100644 index 0000000000000000000000000000000000000000..ed49a6141b0e7051910a3fc19c6fde4bc04dadd8 --- /dev/null +++ b/drm/1.4/vts/functional/include/android/hardware/drm/1.4/vts/drm_hal_test.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DRM_HAL_TEST_V1_4_H +#define DRM_HAL_TEST_V1_4_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "drm_hal_vendor_module_api.h" +#include "drm_vts_helper.h" +#include "vendor_modules.h" +#include "VtsHalHidlTargetCallbackBase.h" + +#include "android/hardware/drm/1.2/vts/drm_hal_common.h" + +namespace android { +namespace hardware { +namespace drm { +namespace V1_4 { +namespace vts { + +namespace drm = ::android::hardware::drm; +using android::hardware::hidl_array; +using android::hardware::hidl_string; +using V1_0::SessionId; +using V1_1::SecurityLevel; + +using drm_vts::DrmHalTestParam; + +class DrmHalTest : public drm::V1_2::vts::DrmHalTest { +public: + using drm::V1_2::vts::DrmHalTest::DrmHalTest; + static const char* const kVideoMp4; + static const char* const kAudioMp4; + static const uint32_t kSecLevelMin = static_cast(SecurityLevel::SW_SECURE_CRYPTO); + static const uint32_t kSecLevelMax = static_cast(SecurityLevel::HW_SECURE_ALL); + static const uint32_t kSecLevelDefault; + +protected: + sp DrmPluginV1_4() const; + sp CryptoPlugin(const SessionId& sid); + SessionId OpenSession(uint32_t level); + +private: + void DoProvisioning(); +}; + +} // namespace vts +} // namespace V1_4 +} // namespace drm +} // namespace hardware +} // namespace android + +#endif // DRM_HAL_TEST_V1_4_H diff --git a/dumpstate/1.1/vts/functional/VtsHalDumpstateV1_1TargetTest.cpp b/dumpstate/1.1/vts/functional/VtsHalDumpstateV1_1TargetTest.cpp index 1bef66358a1148a7797ccb0ddc95bddd869e8cf5..dac43e35b65b4c552d7a2cd2bf37f06f3b9fc953 100644 --- a/dumpstate/1.1/vts/functional/VtsHalDumpstateV1_1TargetTest.cpp +++ b/dumpstate/1.1/vts/functional/VtsHalDumpstateV1_1TargetTest.cpp @@ -321,6 +321,7 @@ TEST_P(DumpstateHidl1_1GeneralTest, TestRepeatedToggle) { DisableVerboseLogging(); } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DumpstateHidl1_1GeneralTest); INSTANTIATE_TEST_SUITE_P( PerInstance, DumpstateHidl1_1GeneralTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames(IDumpstateDevice::descriptor)), @@ -334,6 +335,7 @@ static inline std::string PrintInstanceNameToStringWithMode( "_" + toString(std::get<1>(info.param)); } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DumpstateHidl1_1PerModeTest); INSTANTIATE_TEST_SUITE_P( PerInstanceAndMode, DumpstateHidl1_1PerModeTest, testing::Combine(testing::ValuesIn(android::hardware::getAllHalInstanceNames( diff --git a/gnss/1.0/IGnssMeasurementCallback.hal b/gnss/1.0/IGnssMeasurementCallback.hal index 2d447669876e05aa108dc8718f4540472b06d82b..603680d0b4e8c15dfae5eec02c0c86d923ebcf5e 100644 --- a/gnss/1.0/IGnssMeasurementCallback.hal +++ b/gnss/1.0/IGnssMeasurementCallback.hal @@ -106,8 +106,63 @@ interface IGnssMeasurementCallback { STATE_GLO_TOD_KNOWN = 1 << 15, }; - /** + /** * Flags indicating the Accumulated Delta Range's states. + * + * See the table below for a detailed interpretation of each state. + * + * +---------------------+-------------------+-----------------------------+ + * | ADR_STATE | Time of relevance | Interpretation | + * +---------------------+-------------------+-----------------------------+ + * | UNKNOWN | ADR(t) | No valid carrier phase | + * | | | information is available | + * | | | at time t. | + * +---------------------+-------------------+-----------------------------+ + * | VALID | ADR(t) | Valid carrier phase | + * | | | information is available | + * | | | at time t. This indicates | + * | | | that this measurement can | + * | | | be used as a reference for | + * | | | future measurements. | + * | | | However, to compare it to | + * | | | previous measurements to | + * | | | compute delta range, | + * | | | other bits should be | + * | | | checked. Specifically, it | + * | | | can be used for delta range | + * | | | computation if it is valid | + * | | | and has no reset or cycle | + * | | | slip at this epoch i.e. | + * | | | if VALID_BIT == 1 && | + * | | | CYCLE_SLIP_BIT == 0 && | + * | | | RESET_BIT == 0. | + * +---------------------+-------------------+-----------------------------+ + * | RESET | ADR(t) - ADR(t-1) | Carrier phase accumulation | + * | | | has been restarted between | + * | | | current time t and previous | + * | | | time t-1. This indicates | + * | | | that this measurement can | + * | | | be used as a reference for | + * | | | future measurements, but it | + * | | | should not be compared to | + * | | | previous measurements to | + * | | | compute delta range. | + * +---------------------+-------------------+-----------------------------+ + * | CYCLE_SLIP | ADR(t) - ADR(t-1) | Cycle slip(s) have been | + * | | | detected between the | + * | | | current time t and previous | + * | | | time t-1. This indicates | + * | | | that this measurement can | + * | | | be used as a reference for | + * | | | future measurements. | + * | | | Clients can use a | + * | | | measurement with a cycle | + * | | | slip to compute delta range | + * | | | against previous | + * | | | measurements at their own | + * | | | risk. | + * +---------------------+-------------------+-----------------------------+ + * */ @export(name="", value_prefix="GNSS_") enum GnssAccumulatedDeltaRangeState : uint16_t { @@ -589,22 +644,19 @@ interface IGnssMeasurementCallback { */ double snrDb; - /** - * Automatic gain control (AGC) level. AGC acts as a variable gain - * amplifier adjusting the power of the incoming signal. The AGC level - * may be used to indicate potential interference. When AGC is at a - * nominal level, this value must be set as 0. Higher gain (and/or lower - * input power) must be output as a positive number. Hence in cases of - * strong jamming, in the band of this signal, this value must go more - * negative. - * - * Note: Different hardware designs (e.g. antenna, pre-amplification, or - * other RF HW components) may also affect the typical output of of this - * value on any given hardware design in an open sky test - the - * important aspect of this output is that changes in this value are - * indicative of changes on input signal power in the frequency band for - * this measurement. - */ + + /** + * Automatic gain control (AGC) level. AGC acts as a variable gain amplifier adjusting the power + * of the incoming signal. The AGC level may be used to indicate potential interference. Higher + * gain (and/or lower input power) must be output as a positive number. Hence in cases of strong + * jamming, in the band of this signal, this value must go more negative. This value must be + * consistent given the same level of the incoming signal power. + * + * Note: Different hardware designs (e.g. antenna, pre-amplification, or other RF HW components) + * may also affect the typical output of this value on any given hardware design in an open sky + * test - the important aspect of this output is that changes in this value are indicative of + * changes on input signal power in the frequency band for this measurement. + */ double agcLevelDb; }; diff --git a/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp b/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp index 237e8ec9d8877fe187a344b0773d490551c85cdc..699ce9af142074dec6f403467575df4f8a0bc9b4 100644 --- a/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp +++ b/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp @@ -134,13 +134,30 @@ class GnssHalTest : public testing::TestWithParam { return status; } + /* + * SetPositionMode: + * Helper function to set positioning mode and verify output + */ + void SetPositionMode(const int min_interval_msec) { + const int kPreferredAccuracy = 0; // Ideally perfect (matches GnssLocationProvider) + const int kPreferredTimeMsec = 0; // Ideally immediate + + auto result = gnss_hal_->setPositionMode( + IGnss::GnssPositionMode::MS_BASED, IGnss::GnssPositionRecurrence::RECURRENCE_PERIODIC, + min_interval_msec, kPreferredAccuracy, kPreferredTimeMsec); + + ASSERT_TRUE(result.isOk()); + EXPECT_TRUE(result); + } + /* * StartAndGetSingleLocation: * Helper function to get one Location and check fields * * returns true if a location was successfully generated */ - bool StartAndGetSingleLocation(bool checkAccuracies) { + bool StartAndGetSingleLocation(const bool checkAccuracies, const int min_interval_msec) { + SetPositionMode(min_interval_msec); auto result = gnss_hal_->start(); EXPECT_TRUE(result.isOk()); @@ -349,37 +366,24 @@ TEST_P(GnssHalTest, SetCallbackCapabilitiesCleanup) {} * and checks them for reasonable validity. */ TEST_P(GnssHalTest, GetLocation) { -#define MIN_INTERVAL_MSEC 500 -#define PREFERRED_ACCURACY 0 // Ideally perfect (matches GnssLocationProvider) -#define PREFERRED_TIME_MSEC 0 // Ideally immediate - -#define LOCATION_TIMEOUT_SUBSEQUENT_SEC 3 -#define LOCATIONS_TO_CHECK 5 - - bool checkMoreAccuracies = - (info_called_count_ > 0 && last_info_.yearOfHw >= 2017); + const int kMinIntervalMsec = 500; + const int kLocationTimeoutSubsequentSec = 3; + const int kLocationsToCheck = 5; - auto result = gnss_hal_->setPositionMode( - IGnss::GnssPositionMode::MS_BASED, - IGnss::GnssPositionRecurrence::RECURRENCE_PERIODIC, MIN_INTERVAL_MSEC, - PREFERRED_ACCURACY, PREFERRED_TIME_MSEC); + bool checkMoreAccuracies = (info_called_count_ > 0 && last_info_.yearOfHw >= 2017); - ASSERT_TRUE(result.isOk()); - EXPECT_TRUE(result); - - /* - * GPS signals initially optional for this test, so don't expect no timeout - * yet - */ - bool gotLocation = StartAndGetSingleLocation(checkMoreAccuracies); - - if (gotLocation) { - for (int i = 1; i < LOCATIONS_TO_CHECK; i++) { - EXPECT_EQ(std::cv_status::no_timeout, wait(LOCATION_TIMEOUT_SUBSEQUENT_SEC)); - EXPECT_EQ(location_called_count_, i + 1); - CheckLocation(last_location_, checkMoreAccuracies, true); + /* + * GPS signals initially optional for this test, so don't expect timeout yet. + */ + bool gotLocation = StartAndGetSingleLocation(checkMoreAccuracies, kMinIntervalMsec); + + if (gotLocation) { + for (int i = 1; i < kLocationsToCheck; i++) { + EXPECT_EQ(std::cv_status::no_timeout, wait(kLocationTimeoutSubsequentSec)); + EXPECT_EQ(location_called_count_, i + 1); + CheckLocation(last_location_, checkMoreAccuracies, true); + } } - } StopAndClearLocations(); } @@ -410,7 +414,7 @@ TEST_P(GnssHalTest, InjectDelete) { ASSERT_TRUE(resultVoid.isOk()); // Ensure we can get a good location after a bad injection has been deleted - StartAndGetSingleLocation(false); + StartAndGetSingleLocation(false, /* min_interval_sec= */ 1000); StopAndClearLocations(); } @@ -430,7 +434,7 @@ TEST_P(GnssHalTest, InjectSeedLocation) { ASSERT_TRUE(result.isOk()); EXPECT_TRUE(result); - StartAndGetSingleLocation(false); + StartAndGetSingleLocation(false, /* min_interval_msec= */ 1000); // Ensure we don't get a location anywhere within 111km (1 degree of lat or lng) of the seed // location. diff --git a/gnss/1.1/IGnssMeasurementCallback.hal b/gnss/1.1/IGnssMeasurementCallback.hal index 5a60a56bdf5c7caa0a9c02b52f86d299d8f88d84..f94c67a8eab3c4d03e851375896242f2f2775234 100644 --- a/gnss/1.1/IGnssMeasurementCallback.hal +++ b/gnss/1.1/IGnssMeasurementCallback.hal @@ -20,8 +20,43 @@ import @1.0::IGnssMeasurementCallback; /** The callback interface to report measurements from the HAL. */ interface IGnssMeasurementCallback extends @1.0::IGnssMeasurementCallback { - /** + /** * Flags indicating the Accumulated Delta Range's states. + * + * See the table below for a detailed interpretation of each state. This is + * a continuation of the table from 1.0/IGnssMeasurementCallback.hal. + * + * +---------------------+-------------------+-----------------------------+ + * | ADR_STATE | Time of relevance | Interpretation | + * +---------------------+-------------------+-----------------------------+ + * | HALF_CYCLE_RESOLVED | ADR(t) | Half cycle ambiguity is | + * | | | resolved at time t. | + * | | | | + * | | | For signals that have | + * | | | databits, the carrier phase | + * | | | tracking loops typically | + * | | | use a costas loop | + * | | | discriminator. This type of | + * | | | tracking loop introduces a | + * | | | half-cycle ambiguity that | + * | | | is resolved by searching | + * | | | through the received data | + * | | | for known patterns of | + * | | | databits (e.g. GPS uses the | + * | | | TLM word) which then | + * | | | determines the polarity of | + * | | | the incoming data and | + * | | | resolves the half-cycle | + * | | | ambiguity. | + * | | | | + * | | | Before the half-cycle | + * | | | ambiguity has been resolved | + * | | | it is possible that the | + * | | | ADR_STATE_VALID flag is | + * | | | set, but the ADR_STATE_ | + * | | | HALF_CYCLE_RESOLVED flag is | + * | | | not set. | + * +---------------------+-------------------+-----------------------------+ */ enum GnssAccumulatedDeltaRangeState : @1.0::IGnssMeasurementCallback.GnssAccumulatedDeltaRangeState { diff --git a/gnss/1.1/default/Android.bp b/gnss/1.1/default/Android.bp index 1629e411dc292937ce1c126f9ecee740d2fcee7b..3c9c29a7d629cfd6a448012421ef110b0ca1c1df 100644 --- a/gnss/1.1/default/Android.bp +++ b/gnss/1.1/default/Android.bp @@ -27,6 +27,7 @@ cc_binary { "android.hardware.gnss@2.0", "android.hardware.gnss@1.1", "android.hardware.gnss@1.0", + "android.hardware.gnss-V1-ndk", ], static_libs: [ "android.hardware.gnss@common-default-lib", diff --git a/gnss/1.1/default/Gnss.cpp b/gnss/1.1/default/Gnss.cpp index 5043649b2ddef86396c36ffac848dd0203c01cfc..0d77ce4273ca8e4db62cff737578ec5b0d692e49 100644 --- a/gnss/1.1/default/Gnss.cpp +++ b/gnss/1.1/default/Gnss.cpp @@ -1,9 +1,9 @@ #define LOG_TAG "Gnss" +#include "Gnss.h" #include #include - -#include "Gnss.h" +#include "Constants.h" #include "GnssDebug.h" #include "GnssMeasurement.h" #include "Utils.h" @@ -16,6 +16,7 @@ namespace implementation { using ::android::hardware::gnss::common::Utils; using GnssSvFlags = IGnssCallback::GnssSvFlags; +using namespace ::android::hardware::gnss::common; const uint32_t MIN_INTERVAL_MILLIS = 100; sp<::android::hardware::gnss::V1_1::IGnssCallback> Gnss::sGnssCallback = nullptr; @@ -197,14 +198,21 @@ Return Gnss::injectBestLocation(const GnssLocation&) { Return Gnss::getMockSvStatus() const { std::unique_lock lock(mGnssConfiguration->getMutex()); GnssSvInfo mockGnssSvInfoList[] = { - Utils::getMockSvInfoV1_0(3, GnssConstellationType::GPS, 32.5, 59.1, 166.5), - Utils::getMockSvInfoV1_0(5, GnssConstellationType::GPS, 27.0, 29.0, 56.5), - Utils::getMockSvInfoV1_0(17, GnssConstellationType::GPS, 30.5, 71.0, 77.0), - Utils::getMockSvInfoV1_0(26, GnssConstellationType::GPS, 24.1, 28.0, 253.0), - Utils::getMockSvInfoV1_0(5, GnssConstellationType::GLONASS, 20.5, 11.5, 116.0), - Utils::getMockSvInfoV1_0(17, GnssConstellationType::GLONASS, 21.5, 28.5, 186.0), - Utils::getMockSvInfoV1_0(18, GnssConstellationType::GLONASS, 28.3, 38.8, 69.0), - Utils::getMockSvInfoV1_0(10, GnssConstellationType::GLONASS, 25.0, 66.0, 247.0)}; + Utils::getMockSvInfoV1_0(3, GnssConstellationType::GPS, 32.5, 59.1, 166.5, + kGpsL1FreqHz), + Utils::getMockSvInfoV1_0(5, GnssConstellationType::GPS, 27.0, 29.0, 56.5, kGpsL1FreqHz), + Utils::getMockSvInfoV1_0(17, GnssConstellationType::GPS, 30.5, 71.0, 77.0, + kGpsL5FreqHz), + Utils::getMockSvInfoV1_0(26, GnssConstellationType::GPS, 24.1, 28.0, 253.0, + kGpsL5FreqHz), + Utils::getMockSvInfoV1_0(5, GnssConstellationType::GLONASS, 20.5, 11.5, 116.0, + kGloG1FreqHz), + Utils::getMockSvInfoV1_0(17, GnssConstellationType::GLONASS, 21.5, 28.5, 186.0, + kGloG1FreqHz), + Utils::getMockSvInfoV1_0(18, GnssConstellationType::GLONASS, 28.3, 38.8, 69.0, + kGloG1FreqHz), + Utils::getMockSvInfoV1_0(10, GnssConstellationType::GLONASS, 25.0, 66.0, 247.0, + kGloG1FreqHz)}; GnssSvStatus svStatus = {.numSvs = sizeof(mockGnssSvInfoList) / sizeof(GnssSvInfo)}; for (uint32_t i = 0; i < svStatus.numSvs; i++) { diff --git a/gnss/1.1/default/GnssDebug.cpp b/gnss/1.1/default/GnssDebug.cpp index 471ed2421dd230f37c48aecfb241b231499f2bf8..39efcd232b969ac1ab91a44742c96e52bc014b7c 100644 --- a/gnss/1.1/default/GnssDebug.cpp +++ b/gnss/1.1/default/GnssDebug.cpp @@ -20,6 +20,7 @@ #include "Constants.h" #include "GnssDebug.h" +#include "MockLocation.h" using namespace ::android::hardware::gnss::common; @@ -32,17 +33,17 @@ namespace implementation { // Methods from ::android::hardware::gnss::V1_0::IGnssDebug follow. Return GnssDebug::getDebugData(V1_0::IGnssDebug::getDebugData_cb _hidl_cb) { PositionDebug positionDebug = { - .valid = true, - .latitudeDegrees = kMockLatitudeDegrees, - .longitudeDegrees = kMockLongitudeDegrees, - .altitudeMeters = kMockAltitudeMeters, - .speedMetersPerSec = kMockSpeedMetersPerSec, - .bearingDegrees = kMockBearingDegrees, - .horizontalAccuracyMeters = kMockHorizontalAccuracyMeters, - .verticalAccuracyMeters = kMockVerticalAccuracyMeters, - .speedAccuracyMetersPerSecond = kMockSpeedAccuracyMetersPerSecond, - .bearingAccuracyDegrees = kMockBearingAccuracyDegrees, - .ageSeconds = 0.99}; + .valid = true, + .latitudeDegrees = gMockLatitudeDegrees, + .longitudeDegrees = gMockLongitudeDegrees, + .altitudeMeters = gMockAltitudeMeters, + .speedMetersPerSec = gMockSpeedMetersPerSec, + .bearingDegrees = gMockBearingDegrees, + .horizontalAccuracyMeters = kMockHorizontalAccuracyMeters, + .verticalAccuracyMeters = kMockVerticalAccuracyMeters, + .speedAccuracyMetersPerSecond = kMockSpeedAccuracyMetersPerSecond, + .bearingAccuracyDegrees = kMockBearingAccuracyDegrees, + .ageSeconds = 0.99}; TimeDebug timeDebug = {.timeEstimate = kMockTimestamp, .timeUncertaintyNs = 1000, diff --git a/gnss/1.1/vts/functional/VtsHalGnssV1_1TargetTest.cpp b/gnss/1.1/vts/functional/VtsHalGnssV1_1TargetTest.cpp index 4a0a7f9ffab67d0d2a54599eaebc48d26e1d1767..e33ff58dd1325b4bc528af385164fdccf41f8f3b 100644 --- a/gnss/1.1/vts/functional/VtsHalGnssV1_1TargetTest.cpp +++ b/gnss/1.1/vts/functional/VtsHalGnssV1_1TargetTest.cpp @@ -23,6 +23,7 @@ using android::hardware::gnss::V1_1::IGnss; +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GnssHalTest); INSTANTIATE_TEST_SUITE_P( PerInstance, GnssHalTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames(IGnss::descriptor)), diff --git a/gnss/1.1/vts/functional/gnss_hal_test.cpp b/gnss/1.1/vts/functional/gnss_hal_test.cpp index 52aaa69753bdc925264a4a0bb6296918316c7a11..6663a19abfdc258e10b6757fdba2b4a7381a51e5 100644 --- a/gnss/1.1/vts/functional/gnss_hal_test.cpp +++ b/gnss/1.1/vts/functional/gnss_hal_test.cpp @@ -99,7 +99,9 @@ void GnssHalTest::SetPositionMode(const int min_interval_msec, const bool low_po EXPECT_TRUE(result); } -bool GnssHalTest::StartAndCheckFirstLocation(bool strict) { +bool GnssHalTest::StartAndCheckFirstLocation(const bool strict, const int min_interval_msec, + const bool low_power_mode) { + SetPositionMode(min_interval_msec, low_power_mode); auto result = gnss_hal_->start(); EXPECT_TRUE(result.isOk()); @@ -141,7 +143,9 @@ void GnssHalTest::StartAndCheckLocations(int count) { SetPositionMode(kMinIntervalMsec, kLowPowerMode); - EXPECT_TRUE(StartAndCheckFirstLocation(/* strict= */ true)); + EXPECT_TRUE(StartAndCheckFirstLocation(/* strict= */ true, + /* min_interval_msec= */ 1000, + /* low_power_mode= */ false)); for (int i = 1; i < count; i++) { EXPECT_TRUE(gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_, diff --git a/gnss/1.1/vts/functional/gnss_hal_test.h b/gnss/1.1/vts/functional/gnss_hal_test.h index 75c4216e4a456cdb6b1ca98a0a23a4c6babb7264..c6420287c1c055aba64ed8539535e4263e22d682 100644 --- a/gnss/1.1/vts/functional/gnss_hal_test.h +++ b/gnss/1.1/vts/functional/gnss_hal_test.h @@ -106,7 +106,8 @@ class GnssHalTest : public testing::TestWithParam { * * returns true if a location was successfully generated */ - bool StartAndCheckFirstLocation(bool strict); + bool StartAndCheckFirstLocation(const bool strict, const int min_interval_msec, + const bool low_power_mode); /* * CheckLocation: diff --git a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp index e6a51eb731165952cfbc531e196b620e7260d137..ef64324aadd1988f5796294a4086b2970ecdfea7 100644 --- a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp +++ b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp @@ -90,10 +90,8 @@ TEST_P(GnssHalTest, GetLocationLowPower) { gnss_cb_->location_cbq_.reset(); // Start of Low Power Mode test - SetPositionMode(kMinIntervalMsec, kLowPowerMode); - // Don't expect true - as without AGPS access - if (!StartAndCheckFirstLocation(/* strict= */ false)) { + if (!StartAndCheckFirstLocation(/* strict= */ false, kMinIntervalMsec, kLowPowerMode)) { ALOGW("GetLocationLowPower test - no first low power location received."); } diff --git a/gnss/2.0/default/Android.bp b/gnss/2.0/default/Android.bp index 73daff71dad6f79b39f3b098f356235ca0455c14..695246ad530dc6ff5e6dfb1cccfe90d628d0c11b 100644 --- a/gnss/2.0/default/Android.bp +++ b/gnss/2.0/default/Android.bp @@ -38,7 +38,7 @@ cc_binary { "GnssMeasurement.cpp", "GnssMeasurementCorrections.cpp", "GnssVisibilityControl.cpp", - "service.cpp" + "service.cpp", ], shared_libs: [ "libhidlbase", @@ -48,8 +48,9 @@ cc_binary { "android.hardware.gnss.visibility_control@1.0", "android.hardware.gnss@2.1", "android.hardware.gnss@2.0", - "android.hardware.gnss@1.0", "android.hardware.gnss@1.1", + "android.hardware.gnss@1.0", + "android.hardware.gnss-V1-ndk", ], static_libs: [ "android.hardware.gnss@common-default-lib", diff --git a/gnss/2.0/vts/functional/VtsHalGnssV2_0TargetTest.cpp b/gnss/2.0/vts/functional/VtsHalGnssV2_0TargetTest.cpp index 2c74fa37be9ff7f4cbf7428d9f8c7e9c3015a1cb..54f565208402357482fa5363fa41929b01062b12 100644 --- a/gnss/2.0/vts/functional/VtsHalGnssV2_0TargetTest.cpp +++ b/gnss/2.0/vts/functional/VtsHalGnssV2_0TargetTest.cpp @@ -23,6 +23,7 @@ using android::hardware::gnss::V2_0::IGnss; +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GnssHalTest); INSTANTIATE_TEST_SUITE_P( PerInstance, GnssHalTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames(IGnss::descriptor)), diff --git a/gnss/2.0/vts/functional/gnss_hal_test.cpp b/gnss/2.0/vts/functional/gnss_hal_test.cpp index 1cb44c5761f17f36bd01f798fa305fac0abd4cc2..522769313ebb102cd3b9a84421f7a6203639fca6 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test.cpp +++ b/gnss/2.0/vts/functional/gnss_hal_test.cpp @@ -97,7 +97,9 @@ void GnssHalTest::SetPositionMode(const int min_interval_msec, const bool low_po EXPECT_TRUE(result); } -bool GnssHalTest::StartAndCheckFirstLocation(bool strict) { +bool GnssHalTest::StartAndCheckFirstLocation(const bool strict, const int min_interval_msec, + const bool low_power_mode) { + SetPositionMode(min_interval_msec, low_power_mode); const auto result = gnss_hal_->start(); EXPECT_TRUE(result.isOk()); @@ -137,7 +139,9 @@ void GnssHalTest::StartAndCheckLocations(int count) { SetPositionMode(kMinIntervalMsec, kLowPowerMode); - EXPECT_TRUE(StartAndCheckFirstLocation(/* strict= */ true)); + EXPECT_TRUE(StartAndCheckFirstLocation(/* strict= */ true, + /* min_interval_msec= */ 1000, + /* low_power_mode= */ false)); for (int i = 1; i < count; i++) { EXPECT_TRUE(gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_, diff --git a/gnss/2.0/vts/functional/gnss_hal_test.h b/gnss/2.0/vts/functional/gnss_hal_test.h index 7fbd7350eb886385a752848cbe8210895785ba6a..28a19792b63a2095db2cfdf4aa23e2c5f5c8d955 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test.h +++ b/gnss/2.0/vts/functional/gnss_hal_test.h @@ -159,7 +159,8 @@ class GnssHalTest : public testing::TestWithParam { * * returns true if a location was successfully generated */ - bool StartAndCheckFirstLocation(bool strict); + bool StartAndCheckFirstLocation(const bool strict, const int min_interval_msec, + const bool low_power_mode); /* * CheckLocation: diff --git a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp index 3e0058fa0555017ae76d0379bd9d69c28aac1228..f57c5991252a6ccf8dd3a193785bea2c57f86247 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp +++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp @@ -403,7 +403,9 @@ TEST_P(GnssHalTest, TestGnssDataElapsedRealtimeFlags) { } TEST_P(GnssHalTest, TestGnssLocationElapsedRealtime) { - StartAndCheckFirstLocation(/* strict= */ true); + StartAndCheckFirstLocation(/* strict= */ true, + /* min_interval_msec= */ 1000, + /* low_power_mode= */ false); ASSERT_TRUE((int)gnss_cb_->last_location_.elapsedRealtime.flags <= (int)(ElapsedRealtimeFlags::HAS_TIMESTAMP_NS | @@ -419,7 +421,9 @@ TEST_P(GnssHalTest, TestGnssLocationElapsedRealtime) { // This test only verify that injectBestLocation_2_0 does not crash. TEST_P(GnssHalTest, TestInjectBestLocation_2_0) { - StartAndCheckFirstLocation(/* strict= */ true); + StartAndCheckFirstLocation(/* strict= */ true, + /* min_interval_msec= */ 1000, + /* low_power_mode= */ false); gnss_hal_->injectBestLocation_2_0(gnss_cb_->last_location_); StopAndClearLocations(); } @@ -460,10 +464,10 @@ TEST_P(GnssHalTest, GetLocationLowPower) { gnss_cb_->location_cbq_.reset(); // Start of Low Power Mode test - SetPositionMode(kMinIntervalMsec, kLowPowerMode); - // Don't expect true - as without AGPS access - if (!StartAndCheckFirstLocation(/* strict= */ false)) { + if (!StartAndCheckFirstLocation(/* strict= */ false, + /* min_interval_msec= */ kMinIntervalMsec, + /* low_power_mode= */ kLowPowerMode)) { ALOGW("GetLocationLowPower test - no first low power location received."); } diff --git a/gnss/2.1/IGnssMeasurementCallback.hal b/gnss/2.1/IGnssMeasurementCallback.hal index 60a542330dd6f5b34246301ebdc928561441149d..beef4fd9496ade78524a29f1b2916c36a9157f35 100644 --- a/gnss/2.1/IGnssMeasurementCallback.hal +++ b/gnss/2.1/IGnssMeasurementCallback.hal @@ -103,6 +103,9 @@ interface IGnssMeasurementCallback extends @2.0::IGnssMeasurementCallback { * * The value does not include the inter-frequency Ionospheric bias. * + * The sign of the value is defined by the following equation: + * corrected pseudorange = raw pseudorange - fullInterSignalBias + * * The full ISB of GnssClock.referenceSignalTypeForIsb is defined to be 0.0 nanoseconds. */ double fullInterSignalBiasNs; @@ -127,6 +130,9 @@ interface IGnssMeasurementCallback extends @2.0::IGnssMeasurementCallback { * - Satellite inter-code bias (e.g., Differential Code Bias (DCB)) (with respect to the * code type in GnssClock.referenceSignalTypeForIsb) * + * The sign of the value is defined by the following equation: + * corrected pseudorange = raw pseudorange - satelliteInterSignalBias + * * The satellite ISB of GnssClock.referenceSignalTypeForIsb is defined to be 0.0 * nanoseconds. */ diff --git a/gnss/2.1/default/Android.bp b/gnss/2.1/default/Android.bp index bc39384595c439dde5221af55f04c2819519e0b7..c46c73545c89759128b1948826ac8a97283ffc2b 100644 --- a/gnss/2.1/default/Android.bp +++ b/gnss/2.1/default/Android.bp @@ -30,15 +30,10 @@ cc_binary { vendor: true, vintf_fragments: ["android.hardware.gnss@2.1-service.xml"], srcs: [ - "Gnss.cpp", - "GnssAntennaInfo.cpp", - "GnssDebug.cpp", - "GnssMeasurement.cpp", - "GnssMeasurementCorrections.cpp", - "GnssConfiguration.cpp", "service.cpp", ], shared_libs: [ + "libcutils", "libhidlbase", "libutils", "liblog", @@ -49,6 +44,7 @@ cc_binary { "android.hardware.gnss@1.0", "android.hardware.gnss@1.1", "android.hardware.gnss@2.0", + "android.hardware.gnss-V1-ndk", ], static_libs: [ "android.hardware.gnss@common-default-lib", diff --git a/gnss/2.1/default/Gnss.cpp b/gnss/2.1/default/Gnss.cpp deleted file mode 100644 index 2b327a99169c515294183fbcdd628c49c8837817..0000000000000000000000000000000000000000 --- a/gnss/2.1/default/Gnss.cpp +++ /dev/null @@ -1,439 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "Gnss" - -#include "Gnss.h" -#include "GnssAntennaInfo.h" -#include "GnssDebug.h" -#include "GnssMeasurement.h" -#include "GnssMeasurementCorrections.h" -#include "Utils.h" - -#include - -using ::android::hardware::gnss::common::Utils; -using ::android::hardware::gnss::measurement_corrections::V1_1::implementation:: - GnssMeasurementCorrections; - -namespace android { -namespace hardware { -namespace gnss { -namespace V2_1 { -namespace implementation { - -sp Gnss::sGnssCallback_2_1 = nullptr; -sp Gnss::sGnssCallback_2_0 = nullptr; -sp Gnss::sGnssCallback_1_1 = nullptr; -sp Gnss::sGnssCallback_1_0 = nullptr; - -Gnss::Gnss() : mMinIntervalMs(1000), mGnssConfiguration{new GnssConfiguration()} {} - -Gnss::~Gnss() { - stop(); -} - -Return Gnss::start() { - ALOGD("start"); - if (mIsActive) { - ALOGW("Gnss has started. Restarting..."); - stop(); - } - - mIsActive = true; - mThread = std::thread([this]() { - while (mIsActive == true) { - auto svStatus = filterBlacklistedSatellitesV2_1(Utils::getMockSvInfoListV2_1()); - this->reportSvStatus(svStatus); - - if (sGnssCallback_2_1 != nullptr || sGnssCallback_2_0 != nullptr) { - const auto location = Utils::getMockLocationV2_0(); - this->reportLocation(location); - } else { - const auto location = Utils::getMockLocationV1_0(); - this->reportLocation(location); - } - - std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMs)); - } - }); - return true; -} - -hidl_vec Gnss::filterBlacklistedSatellitesV2_1(hidl_vec gnssSvInfoList) { - for (uint32_t i = 0; i < gnssSvInfoList.size(); i++) { - if (mGnssConfiguration->isBlacklistedV2_1(gnssSvInfoList[i])) { - gnssSvInfoList[i].v2_0.v1_0.svFlag &= - ~static_cast(V1_0::IGnssCallback::GnssSvFlags::USED_IN_FIX); - } - } - return gnssSvInfoList; -} - -Return Gnss::stop() { - ALOGD("stop"); - mIsActive = false; - if (mThread.joinable()) { - mThread.join(); - } - return true; -} - -// Methods from V1_0::IGnss follow. -Return Gnss::setCallback(const sp& callback) { - if (callback == nullptr) { - ALOGE("%s: Null callback ignored", __func__); - return false; - } - - sGnssCallback_1_0 = callback; - - uint32_t capabilities = 0x0 | V1_0::IGnssCallback::Capabilities::MEASUREMENTS | - V1_0::IGnssCallback::Capabilities::SCHEDULING; - auto ret = sGnssCallback_1_0->gnssSetCapabilitesCb(capabilities); - if (!ret.isOk()) { - ALOGE("%s: Unable to invoke callback", __func__); - } - - IGnssCallback::GnssSystemInfo gnssInfo = {.yearOfHw = 2018}; - - ret = sGnssCallback_1_0->gnssSetSystemInfoCb(gnssInfo); - if (!ret.isOk()) { - ALOGE("%s: Unable to invoke callback", __func__); - } - - return true; -} - -Return Gnss::cleanup() { - sGnssCallback_2_1 = nullptr; - sGnssCallback_2_0 = nullptr; - return Void(); -} - -Return Gnss::injectTime(int64_t, int64_t, int32_t) { - return true; -} - -Return Gnss::injectLocation(double, double, float) { - return true; -} - -Return Gnss::deleteAidingData(V1_0::IGnss::GnssAidingData) { - // TODO implement - return Void(); -} - -Return Gnss::setPositionMode(V1_0::IGnss::GnssPositionMode, - V1_0::IGnss::GnssPositionRecurrence, uint32_t minIntervalMs, - uint32_t, uint32_t) { - mMinIntervalMs = minIntervalMs; - return true; -} - -Return> Gnss::getExtensionAGnssRil() { - // TODO implement - return ::android::sp{}; -} - -Return> Gnss::getExtensionGnssGeofencing() { - // TODO implement - return ::android::sp{}; -} - -Return> Gnss::getExtensionAGnss() { - // TODO implement - return ::android::sp{}; -} - -Return> Gnss::getExtensionGnssNi() { - // TODO implement - return ::android::sp{}; -} - -Return> Gnss::getExtensionGnssMeasurement() { - ALOGD("Gnss::getExtensionGnssMeasurement"); - return new GnssMeasurement(); -} - -Return> Gnss::getExtensionGnssNavigationMessage() { - // TODO implement - return ::android::sp{}; -} - -Return> Gnss::getExtensionXtra() { - // TODO implement - return ::android::sp{}; -} - -Return> Gnss::getExtensionGnssConfiguration() { - // TODO implement - return ::android::sp{}; -} - -Return> Gnss::getExtensionGnssDebug() { - return new V1_1::implementation::GnssDebug(); -} - -Return> Gnss::getExtensionGnssBatching() { - // TODO implement - return ::android::sp{}; -} - -// Methods from V1_1::IGnss follow. -Return Gnss::setCallback_1_1(const sp& callback) { - if (callback == nullptr) { - ALOGE("%s: Null callback ignored", __func__); - return false; - } - - sGnssCallback_1_1 = callback; - - uint32_t capabilities = 0x0; - auto ret = sGnssCallback_1_1->gnssSetCapabilitesCb(capabilities); - if (!ret.isOk()) { - ALOGE("%s: Unable to invoke callback", __func__); - } - - IGnssCallback::GnssSystemInfo gnssInfo = {.yearOfHw = 2018}; - - ret = sGnssCallback_1_1->gnssSetSystemInfoCb(gnssInfo); - if (!ret.isOk()) { - ALOGE("%s: Unable to invoke callback", __func__); - } - - auto gnssName = "Google Mock GNSS Implementation v2.1"; - ret = sGnssCallback_1_1->gnssNameCb(gnssName); - if (!ret.isOk()) { - ALOGE("%s: Unable to invoke callback", __func__); - } - - return true; -} - -Return Gnss::setPositionMode_1_1(V1_0::IGnss::GnssPositionMode, - V1_0::IGnss::GnssPositionRecurrence, uint32_t minIntervalMs, - uint32_t, uint32_t, bool) { - mMinIntervalMs = minIntervalMs; - return true; -} - -Return> Gnss::getExtensionGnssConfiguration_1_1() { - // TODO implement - return ::android::sp{}; -} - -Return> Gnss::getExtensionGnssMeasurement_1_1() { - // TODO implement - return ::android::sp{}; -} - -Return Gnss::injectBestLocation(const V1_0::GnssLocation&) { - return true; -} - -// Methods from V2_0::IGnss follow. -Return Gnss::setCallback_2_0(const sp& callback) { - ALOGD("Gnss::setCallback_2_0"); - if (callback == nullptr) { - ALOGE("%s: Null callback ignored", __func__); - return false; - } - - sGnssCallback_2_0 = callback; - - using Capabilities = V2_0::IGnssCallback::Capabilities; - const auto capabilities = Capabilities::MEASUREMENTS | Capabilities::MEASUREMENT_CORRECTIONS | - Capabilities::LOW_POWER_MODE | Capabilities::SATELLITE_BLACKLIST; - auto ret = sGnssCallback_2_0->gnssSetCapabilitiesCb_2_0(capabilities); - if (!ret.isOk()) { - ALOGE("%s: Unable to invoke callback", __func__); - } - - V1_1::IGnssCallback::GnssSystemInfo gnssInfo = {.yearOfHw = 2019}; - - ret = sGnssCallback_2_0->gnssSetSystemInfoCb(gnssInfo); - if (!ret.isOk()) { - ALOGE("%s: Unable to invoke callback", __func__); - } - - auto gnssName = "Google Mock GNSS Implementation v2.1"; - ret = sGnssCallback_2_0->gnssNameCb(gnssName); - if (!ret.isOk()) { - ALOGE("%s: Unable to invoke callback", __func__); - } - - return true; -} - -Return> Gnss::getExtensionGnssConfiguration_2_0() { - ALOGD("Gnss::getExtensionGnssConfiguration_2_0"); - return mGnssConfiguration; -} - -Return> Gnss::getExtensionGnssDebug_2_0() { - // TODO implement - return ::android::sp{}; -} - -Return> Gnss::getExtensionAGnss_2_0() { - // TODO implement - return ::android::sp{}; -} - -Return> Gnss::getExtensionAGnssRil_2_0() { - // TODO implement - return ::android::sp{}; -} - -Return> Gnss::getExtensionGnssMeasurement_2_0() { - ALOGD("Gnss::getExtensionGnssMeasurement_2_0"); - return new GnssMeasurement(); -} - -Return> -Gnss::getExtensionMeasurementCorrections() { - ALOGD("Gnss::getExtensionMeasurementCorrections()"); - return new GnssMeasurementCorrections(); -} - -Return> Gnss::getExtensionVisibilityControl() { - // TODO implement - return ::android::sp{}; -} - -Return> Gnss::getExtensionGnssBatching_2_0() { - // TODO implement - return ::android::sp{}; -} - -Return Gnss::injectBestLocation_2_0(const V2_0::GnssLocation&) { - // TODO(b/124012850): Implement function. - return bool{}; -} - -// Methods from V2_1::IGnss follow. -Return Gnss::setCallback_2_1(const sp& callback) { - ALOGD("Gnss::setCallback_2_1"); - if (callback == nullptr) { - ALOGE("%s: Null callback ignored", __func__); - return false; - } - - sGnssCallback_2_1 = callback; - - using Capabilities = V2_1::IGnssCallback::Capabilities; - const auto capabilities = Capabilities::MEASUREMENTS | Capabilities::MEASUREMENT_CORRECTIONS | - Capabilities::LOW_POWER_MODE | Capabilities::SATELLITE_BLACKLIST | - Capabilities::ANTENNA_INFO; - auto ret = sGnssCallback_2_1->gnssSetCapabilitiesCb_2_1(capabilities); - if (!ret.isOk()) { - ALOGE("%s: Unable to invoke callback", __func__); - } - - V1_1::IGnssCallback::GnssSystemInfo gnssInfo = {.yearOfHw = 2020}; - - ret = sGnssCallback_2_1->gnssSetSystemInfoCb(gnssInfo); - if (!ret.isOk()) { - ALOGE("%s: Unable to invoke callback", __func__); - } - - auto gnssName = "Android Mock GNSS Implementation v2.1"; - ret = sGnssCallback_2_1->gnssNameCb(gnssName); - if (!ret.isOk()) { - ALOGE("%s: Unable to invoke callback", __func__); - } - - return true; -} - -Return> Gnss::getExtensionGnssMeasurement_2_1() { - ALOGD("Gnss::getExtensionGnssMeasurement_2_1"); - return new GnssMeasurement(); -} - -Return> Gnss::getExtensionGnssConfiguration_2_1() { - ALOGD("Gnss::getExtensionGnssConfiguration_2_1"); - return mGnssConfiguration; -} - -Return> -Gnss::getExtensionMeasurementCorrections_1_1() { - ALOGD("Gnss::getExtensionMeasurementCorrections_1_1()"); - return new GnssMeasurementCorrections(); -} - -Return> Gnss::getExtensionGnssAntennaInfo() { - ALOGD("Gnss::getExtensionGnssAntennaInfo"); - return new GnssAntennaInfo(); -} - -void Gnss::reportSvStatus(const hidl_vec& svInfoList) const { - std::unique_lock lock(mMutex); - // TODO(skz): update this to call 2_0 callback if non-null - if (sGnssCallback_2_1 == nullptr) { - ALOGE("%s: sGnssCallback v2.1 is null.", __func__); - return; - } - auto ret = sGnssCallback_2_1->gnssSvStatusCb_2_1(svInfoList); - if (!ret.isOk()) { - ALOGE("%s: Unable to invoke callback", __func__); - } -} - -void Gnss::reportLocation(const V1_0::GnssLocation& location) const { - std::unique_lock lock(mMutex); - if (sGnssCallback_1_1 != nullptr) { - auto ret = sGnssCallback_1_1->gnssLocationCb(location); - if (!ret.isOk()) { - ALOGE("%s: Unable to invoke callback v1.1", __func__); - } - return; - } - if (sGnssCallback_1_0 == nullptr) { - ALOGE("%s: No non-null callback", __func__); - return; - } - auto ret = sGnssCallback_1_0->gnssLocationCb(location); - if (!ret.isOk()) { - ALOGE("%s: Unable to invoke callback v1.0", __func__); - } -} - -void Gnss::reportLocation(const V2_0::GnssLocation& location) const { - std::unique_lock lock(mMutex); - if (sGnssCallback_2_1 != nullptr) { - auto ret = sGnssCallback_2_1->gnssLocationCb_2_0(location); - if (!ret.isOk()) { - ALOGE("%s: Unable to invoke callback v2.1", __func__); - } - return; - } - if (sGnssCallback_2_0 == nullptr) { - ALOGE("%s: No non-null callback", __func__); - return; - } - auto ret = sGnssCallback_2_0->gnssLocationCb_2_0(location); - if (!ret.isOk()) { - ALOGE("%s: Unable to invoke callback v2.0", __func__); - } -} - -} // namespace implementation -} // namespace V2_1 -} // namespace gnss -} // namespace hardware -} // namespace android diff --git a/gnss/2.1/default/Gnss.h b/gnss/2.1/default/Gnss.h deleted file mode 100644 index bd5e6e852c7249d493d9f94b62467ad1f35f396f..0000000000000000000000000000000000000000 --- a/gnss/2.1/default/Gnss.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include "GnssAntennaInfo.h" -#include "GnssConfiguration.h" - -namespace android { -namespace hardware { -namespace gnss { -namespace V2_1 { - -using GnssSvInfo = IGnssCallback::GnssSvInfo; - -namespace implementation { - -struct Gnss : public IGnss { - Gnss(); - ~Gnss(); - // Methods from V1_0::IGnss follow. - Return setCallback(const sp& callback) override; - Return start() override; - Return stop() override; - Return cleanup() override; - Return injectTime(int64_t timeMs, int64_t timeReferenceMs, - int32_t uncertaintyMs) override; - Return injectLocation(double latitudeDegrees, double longitudeDegrees, - float accuracyMeters) override; - Return deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) override; - Return setPositionMode(V1_0::IGnss::GnssPositionMode mode, - V1_0::IGnss::GnssPositionRecurrence recurrence, - uint32_t minIntervalMs, uint32_t preferredAccuracyMeters, - uint32_t preferredTimeMs) override; - Return> getExtensionAGnssRil() override; - Return> getExtensionGnssGeofencing() override; - Return> getExtensionAGnss() override; - Return> getExtensionGnssNi() override; - Return> getExtensionGnssMeasurement() override; - Return> getExtensionGnssNavigationMessage() override; - Return> getExtensionXtra() override; - Return> getExtensionGnssConfiguration() override; - Return> getExtensionGnssDebug() override; - Return> getExtensionGnssBatching() override; - - // Methods from V1_1::IGnss follow. - Return setCallback_1_1(const sp& callback) override; - Return setPositionMode_1_1(V1_0::IGnss::GnssPositionMode mode, - V1_0::IGnss::GnssPositionRecurrence recurrence, - uint32_t minIntervalMs, uint32_t preferredAccuracyMeters, - uint32_t preferredTimeMs, bool lowPowerMode) override; - Return> getExtensionGnssConfiguration_1_1() override; - Return> getExtensionGnssMeasurement_1_1() override; - Return injectBestLocation(const V1_0::GnssLocation& location) override; - - // Methods from V2_0::IGnss follow. - Return setCallback_2_0(const sp& callback) override; - Return> getExtensionGnssConfiguration_2_0() override; - Return> getExtensionGnssDebug_2_0() override; - Return> getExtensionAGnss_2_0() override; - Return> getExtensionAGnssRil_2_0() override; - Return> getExtensionGnssMeasurement_2_0() override; - Return> - getExtensionMeasurementCorrections() override; - Return> getExtensionVisibilityControl() - override; - Return> getExtensionGnssBatching_2_0() override; - Return injectBestLocation_2_0(const V2_0::GnssLocation& location) override; - - // Methods from V2_1::IGnss follow. - Return setCallback_2_1(const sp& callback) override; - Return> getExtensionGnssMeasurement_2_1() override; - Return> getExtensionGnssConfiguration_2_1() override; - Return> - getExtensionMeasurementCorrections_1_1() override; - Return> getExtensionGnssAntennaInfo() override; - - private: - void reportLocation(const V2_0::GnssLocation&) const; - void reportLocation(const V1_0::GnssLocation&) const; - void reportSvStatus(const hidl_vec&) const; - - static sp sGnssCallback_2_1; - static sp sGnssCallback_2_0; - static sp sGnssCallback_1_1; - static sp sGnssCallback_1_0; - std::atomic mMinIntervalMs; - sp mGnssConfiguration; - std::atomic mIsActive; - std::thread mThread; - mutable std::mutex mMutex; - hidl_vec filterBlacklistedSatellitesV2_1(hidl_vec gnssSvInfoList); -}; - -} // namespace implementation -} // namespace V2_1 -} // namespace gnss -} // namespace hardware -} // namespace android diff --git a/gnss/2.1/default/service.cpp b/gnss/2.1/default/service.cpp index 5e004d56979205df0f8146f5313770a657ba6f2e..4f282cfdaf8142896b06e0935dad1de6bbabc07d 100644 --- a/gnss/2.1/default/service.cpp +++ b/gnss/2.1/default/service.cpp @@ -18,17 +18,17 @@ #include #include -#include "Gnss.h" +#include "v2_1/GnssTemplate.h" using ::android::OK; using ::android::sp; using ::android::hardware::configureRpcThreadpool; using ::android::hardware::joinRpcThreadpool; +using ::android::hardware::gnss::common::implementation::GnssTemplate; using ::android::hardware::gnss::V2_1::IGnss; -using ::android::hardware::gnss::V2_1::implementation::Gnss; int main(int /* argc */, char* /* argv */[]) { - sp gnss = new Gnss(); + sp gnss = new GnssTemplate(); configureRpcThreadpool(1, true /* will join */); if (gnss->registerAsService() != OK) { ALOGE("Could not register gnss 2.1 service."); diff --git a/gnss/2.1/vts/functional/Android.bp b/gnss/2.1/vts/functional/Android.bp index 67f1cc65f836593644eba60c4db0cc641249ff25..aaddd96f8caca24ad3c7b29f72fa66bede6c589e 100644 --- a/gnss/2.1/vts/functional/Android.bp +++ b/gnss/2.1/vts/functional/Android.bp @@ -41,6 +41,9 @@ cc_test { "android.hardware.gnss@2.1", "android.hardware.gnss@common-vts-lib", ], + shared_libs: [ + "libvintf", + ], test_suites: [ "general-tests", "vts", diff --git a/gnss/2.1/vts/functional/VtsHalGnssV2_1TargetTest.cpp b/gnss/2.1/vts/functional/VtsHalGnssV2_1TargetTest.cpp index e61d885654d72ac64d6dee294e06435f5d172dc7..89a97811251f4509860883eb09de3648fcfeec59 100644 --- a/gnss/2.1/vts/functional/VtsHalGnssV2_1TargetTest.cpp +++ b/gnss/2.1/vts/functional/VtsHalGnssV2_1TargetTest.cpp @@ -23,6 +23,7 @@ using android::hardware::gnss::V2_1::IGnss; +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GnssHalTest); INSTANTIATE_TEST_SUITE_P( PerInstance, GnssHalTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames(IGnss::descriptor)), diff --git a/gnss/2.1/vts/functional/gnss_hal_test.cpp b/gnss/2.1/vts/functional/gnss_hal_test.cpp index da7a62b4bd34e93b17124f408c7c00fb186c0cc4..1154260bc095df94cb1ed25c63db3968192a3df7 100644 --- a/gnss/2.1/vts/functional/gnss_hal_test.cpp +++ b/gnss/2.1/vts/functional/gnss_hal_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 The Android Open Source Project + * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,263 +16,28 @@ #define LOG_TAG "GnssHalTest" -#include -#include -#include "Utils.h" +#include +#include +#include +#include -#include +#include "gnss_hal_test.h" -using ::android::hardware::gnss::common::Utils; +using ::android::hardware::hidl_string; +using ::android::hidl::manager::V1_2::IServiceManager; -// Implementations for the main test class for GNSS HAL -void GnssHalTest::SetUp() { - gnss_hal_ = IGnss::getService(GetParam()); - ASSERT_NE(gnss_hal_, nullptr); +bool GnssHalTest::IsGnssHalVersion_2_1() const { + sp manager = ::android::hardware::defaultServiceManager1_2(); + bool hasGnssHalVersion_2_1 = false; + manager->listManifestByInterface( + "android.hardware.gnss@2.1::IGnss", + [&hasGnssHalVersion_2_1](const hidl_vec& registered) { + hasGnssHalVersion_2_1 = registered.size() > 0; + }); - SetUpGnssCallback(); -} + auto deviceManifest = ::android::vintf::VintfObject::GetDeviceHalManifest(); + bool hasGnssAidl = + deviceManifest->getAidlInstances("android.hardware.gnss", "IGnss").size() > 0; -void GnssHalTest::TearDown() { - if (gnss_hal_ != nullptr) { - gnss_hal_->cleanup(); - gnss_hal_ = nullptr; - } - - // Set to nullptr to destruct the callback event queues and warn of any unprocessed events. - gnss_cb_ = nullptr; -} - -void GnssHalTest::SetUpGnssCallback() { - gnss_cb_ = new GnssCallback(); - ASSERT_NE(gnss_cb_, nullptr); - - auto result = gnss_hal_->setCallback_2_1(gnss_cb_); - if (!result.isOk()) { - ALOGE("result of failed setCallback %s", result.description().c_str()); - } - - ASSERT_TRUE(result.isOk()); - ASSERT_TRUE(result); - - /* - * All capabilities, name and systemInfo callbacks should trigger - */ - EXPECT_TRUE(gnss_cb_->capabilities_cbq_.retrieve(gnss_cb_->last_capabilities_, TIMEOUT_SEC)); - EXPECT_TRUE(gnss_cb_->info_cbq_.retrieve(gnss_cb_->last_info_, TIMEOUT_SEC)); - EXPECT_TRUE(gnss_cb_->name_cbq_.retrieve(gnss_cb_->last_name_, TIMEOUT_SEC)); - - EXPECT_EQ(gnss_cb_->capabilities_cbq_.calledCount(), 1); - EXPECT_EQ(gnss_cb_->info_cbq_.calledCount(), 1); - EXPECT_EQ(gnss_cb_->name_cbq_.calledCount(), 1); -} - -void GnssHalTest::StopAndClearLocations() { - const auto result = gnss_hal_->stop(); - - EXPECT_TRUE(result.isOk()); - EXPECT_TRUE(result); - - /* - * Clear notify/waiting counter, allowing up till the timeout after - * the last reply for final startup messages to arrive (esp. system - * info.) - */ - while (gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_, TIMEOUT_SEC)) { - } - gnss_cb_->location_cbq_.reset(); -} - -void GnssHalTest::SetPositionMode(const int min_interval_msec, const bool low_power_mode) { - const int kPreferredAccuracy = 0; // Ideally perfect (matches GnssLocationProvider) - const int kPreferredTimeMsec = 0; // Ideally immediate - - const auto result = gnss_hal_->setPositionMode_1_1( - IGnss::GnssPositionMode::MS_BASED, IGnss::GnssPositionRecurrence::RECURRENCE_PERIODIC, - min_interval_msec, kPreferredAccuracy, kPreferredTimeMsec, low_power_mode); - - ASSERT_TRUE(result.isOk()); - EXPECT_TRUE(result); -} - -bool GnssHalTest::StartAndCheckFirstLocation() { - const auto result = gnss_hal_->start(); - - EXPECT_TRUE(result.isOk()); - EXPECT_TRUE(result); - - /* - * GnssLocationProvider support of AGPS SUPL & XtraDownloader is not available in VTS, - * so allow time to demodulate ephemeris over the air. - */ - const int kFirstGnssLocationTimeoutSeconds = 75; - - EXPECT_TRUE(gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_, - kFirstGnssLocationTimeoutSeconds)); - int locationCalledCount = gnss_cb_->location_cbq_.calledCount(); - EXPECT_EQ(locationCalledCount, 1); - - if (locationCalledCount > 0) { - // don't require speed on first fix - CheckLocation(gnss_cb_->last_location_, false); - return true; - } - return false; -} - -void GnssHalTest::CheckLocation(const GnssLocation_2_0& location, bool check_speed) { - const bool check_more_accuracies = - (gnss_cb_->info_cbq_.calledCount() > 0 && gnss_cb_->last_info_.yearOfHw >= 2017); - - Utils::checkLocation(location.v1_0, check_speed, check_more_accuracies); -} - -void GnssHalTest::StartAndCheckLocations(int count) { - const int kMinIntervalMsec = 500; - const int kLocationTimeoutSubsequentSec = 2; - const bool kLowPowerMode = false; - - SetPositionMode(kMinIntervalMsec, kLowPowerMode); - - EXPECT_TRUE(StartAndCheckFirstLocation()); - - for (int i = 1; i < count; i++) { - EXPECT_TRUE(gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_, - kLocationTimeoutSubsequentSec)); - int locationCalledCount = gnss_cb_->location_cbq_.calledCount(); - EXPECT_EQ(locationCalledCount, i + 1); - // Don't cause confusion by checking details if no location yet - if (locationCalledCount > 0) { - // Should be more than 1 location by now, but if not, still don't check first fix speed - CheckLocation(gnss_cb_->last_location_, locationCalledCount > 1); - } - } -} - -GnssConstellationType GnssHalTest::startLocationAndGetNonGpsConstellation( - const int locations_to_await, const int gnss_sv_info_list_timeout) { - gnss_cb_->location_cbq_.reset(); - StartAndCheckLocations(locations_to_await); - const int location_called_count = gnss_cb_->location_cbq_.calledCount(); - - // Tolerate 1 less sv status to handle edge cases in reporting. - int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size(); - EXPECT_GE(sv_info_list_cbq_size + 1, locations_to_await); - ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations (%d received)", - sv_info_list_cbq_size, locations_to_await, location_called_count); - - // Find first non-GPS constellation to blacklist - GnssConstellationType constellation_to_blacklist = GnssConstellationType::UNKNOWN; - for (int i = 0; i < sv_info_list_cbq_size; ++i) { - hidl_vec sv_info_vec; - gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, gnss_sv_info_list_timeout); - for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) { - const auto& gnss_sv = sv_info_vec[iSv]; - if ((gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX) && - (gnss_sv.v2_0.constellation != GnssConstellationType::UNKNOWN) && - (gnss_sv.v2_0.constellation != GnssConstellationType::GPS)) { - // found a non-GPS constellation - constellation_to_blacklist = gnss_sv.v2_0.constellation; - break; - } - } - if (constellation_to_blacklist != GnssConstellationType::UNKNOWN) { - break; - } - } - - if (constellation_to_blacklist == GnssConstellationType::UNKNOWN) { - ALOGI("No non-GPS constellations found, constellation blacklist test less effective."); - // Proceed functionally to blacklist something. - constellation_to_blacklist = GnssConstellationType::GLONASS; - } - - return constellation_to_blacklist; -} - -GnssHalTest::GnssCallback::GnssCallback() - : info_cbq_("system_info"), - name_cbq_("name"), - capabilities_cbq_("capabilities"), - location_cbq_("location"), - sv_info_list_cbq_("sv_info") {} - -Return GnssHalTest::GnssCallback::gnssSetSystemInfoCb( - const IGnssCallback_1_0::GnssSystemInfo& info) { - ALOGI("Info received, year %d", info.yearOfHw); - info_cbq_.store(info); - return Void(); -} - -Return GnssHalTest::GnssCallback::gnssSetCapabilitesCb(uint32_t capabilities) { - ALOGI("Capabilities received %d", capabilities); - capabilities_cbq_.store(capabilities); - return Void(); -} - -Return GnssHalTest::GnssCallback::gnssSetCapabilitiesCb_2_0(uint32_t capabilities) { - ALOGI("Capabilities (v2.0) received %d", capabilities); - capabilities_cbq_.store(capabilities); - return Void(); -} - -Return GnssHalTest::GnssCallback::gnssSetCapabilitiesCb_2_1(uint32_t capabilities) { - ALOGI("Capabilities (v2.1) received %d", capabilities); - capabilities_cbq_.store(capabilities); - return Void(); -} - -Return GnssHalTest::GnssCallback::gnssNameCb(const android::hardware::hidl_string& name) { - ALOGI("Name received: %s", name.c_str()); - name_cbq_.store(name); - return Void(); -} - -Return GnssHalTest::GnssCallback::gnssLocationCb(const GnssLocation_1_0& location) { - ALOGI("Location received"); - GnssLocation_2_0 location_v2_0; - location_v2_0.v1_0 = location; - return gnssLocationCbImpl(location_v2_0); -} - -Return GnssHalTest::GnssCallback::gnssLocationCb_2_0(const GnssLocation_2_0& location) { - ALOGI("Location (v2.0) received"); - return gnssLocationCbImpl(location); -} - -Return GnssHalTest::GnssCallback::gnssLocationCbImpl(const GnssLocation_2_0& location) { - location_cbq_.store(location); - return Void(); -} - -Return GnssHalTest::GnssCallback::gnssSvStatusCb(const IGnssCallback_1_0::GnssSvStatus&) { - ALOGI("gnssSvStatusCb"); - return Void(); -} - -Return GnssHalTest::GnssCallback::gnssSvStatusCb_2_1( - const hidl_vec& svInfoList) { - ALOGI("gnssSvStatusCb_2_1. Size = %d", (int)svInfoList.size()); - sv_info_list_cbq_.store(svInfoList); - return Void(); -} - -Return GnssHalTest::GnssMeasurementCallback::gnssMeasurementCb_2_1( - const IGnssMeasurementCallback_2_1::GnssData& data) { - ALOGD("GnssMeasurement v2.1 received. Size = %d", (int)data.measurements.size()); - measurement_cbq_.store(data); - return Void(); -} - -Return GnssHalTest::GnssMeasurementCorrectionsCallback::setCapabilitiesCb( - uint32_t capabilities) { - ALOGI("GnssMeasurementCorrectionsCallback capabilities received %d", capabilities); - capabilities_cbq_.store(capabilities); - return Void(); -} - -Return GnssHalTest::GnssAntennaInfoCallback::gnssAntennaInfoCb( - const hidl_vec& gnssAntennaInfos) { - ALOGD("GnssAntennaInfo v2.1 received. Size = %d", (int)gnssAntennaInfos.size()); - antenna_info_cbq_.store(gnssAntennaInfos); - return Void(); + return hasGnssHalVersion_2_1 && !hasGnssAidl; } \ No newline at end of file diff --git a/gnss/2.1/vts/functional/gnss_hal_test.h b/gnss/2.1/vts/functional/gnss_hal_test.h index 9e6e162a13e46e6d67a1c9ea14f50c1de02000ba..2bcecf4ba2741a6821e410d5b19885a6df4fdd82 100644 --- a/gnss/2.1/vts/functional/gnss_hal_test.h +++ b/gnss/2.1/vts/functional/gnss_hal_test.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 The Android Open Source Project + * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,221 +14,18 @@ * limitations under the License. */ -#ifndef GNSS_HAL_TEST_H_ -#define GNSS_HAL_TEST_H_ +#pragma once #include -#include "GnssCallbackEventQueue.h" - -#include - -using android::hardware::hidl_vec; -using android::hardware::Return; -using android::hardware::Void; - -using android::hardware::gnss::common::GnssCallbackEventQueue; -using android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrectionsCallback; -using android::hardware::gnss::V1_0::GnssLocationFlags; -using android::hardware::gnss::V2_0::GnssConstellationType; -using android::hardware::gnss::V2_1::IGnss; -using android::hardware::gnss::V2_1::IGnssAntennaInfo; -using android::hardware::gnss::V2_1::IGnssAntennaInfoCallback; - -using GnssLocation_1_0 = android::hardware::gnss::V1_0::GnssLocation; -using GnssLocation_2_0 = android::hardware::gnss::V2_0::GnssLocation; - -using IGnssCallback_1_0 = android::hardware::gnss::V1_0::IGnssCallback; -using IGnssCallback_2_0 = android::hardware::gnss::V2_0::IGnssCallback; -using IGnssCallback_2_1 = android::hardware::gnss::V2_1::IGnssCallback; - -using IGnssMeasurementCallback_1_0 = android::hardware::gnss::V1_0::IGnssMeasurementCallback; -using IGnssMeasurementCallback_1_1 = android::hardware::gnss::V1_1::IGnssMeasurementCallback; -using IGnssMeasurementCallback_2_0 = android::hardware::gnss::V2_0::IGnssMeasurementCallback; -using IGnssMeasurementCallback_2_1 = android::hardware::gnss::V2_1::IGnssMeasurementCallback; - -using android::sp; - -#define TIMEOUT_SEC 2 // for basic commands/responses +#include "v2_1/gnss_hal_test_template.h" // The main test class for GNSS HAL. -class GnssHalTest : public testing::TestWithParam { +class GnssHalTest : public android::hardware::gnss::common::GnssHalTestTemplate< + android::hardware::gnss::V2_1::IGnss> { public: - virtual void SetUp() override; - - virtual void TearDown() override; - - /* Callback class for data & Event. */ - class GnssCallback : public IGnssCallback_2_1 { - public: - IGnssCallback_1_0::GnssSystemInfo last_info_; - android::hardware::hidl_string last_name_; - uint32_t last_capabilities_; - GnssLocation_2_0 last_location_; - - GnssCallbackEventQueue info_cbq_; - GnssCallbackEventQueue name_cbq_; - GnssCallbackEventQueue capabilities_cbq_; - GnssCallbackEventQueue location_cbq_; - GnssCallbackEventQueue> sv_info_list_cbq_; - - GnssCallback(); - virtual ~GnssCallback() = default; - - // Dummy callback handlers - Return gnssStatusCb(const IGnssCallback_1_0::GnssStatusValue /* status */) override { - return Void(); - } - Return gnssNmeaCb(int64_t /* timestamp */, - const android::hardware::hidl_string& /* nmea */) override { - return Void(); - } - Return gnssAcquireWakelockCb() override { return Void(); } - Return gnssReleaseWakelockCb() override { return Void(); } - Return gnssRequestLocationCb(bool /* independentFromGnss */) override { - return Void(); - } - Return gnssRequestTimeCb() override { return Void(); } - // Actual (test) callback handlers - Return gnssNameCb(const android::hardware::hidl_string& name) override; - Return gnssLocationCb(const GnssLocation_1_0& location) override; - Return gnssSetCapabilitesCb(uint32_t capabilities) override; - Return gnssSetSystemInfoCb(const IGnssCallback_1_0::GnssSystemInfo& info) override; - Return gnssSvStatusCb(const IGnssCallback_1_0::GnssSvStatus& svStatus) override; - - // New in v2.0 - Return gnssLocationCb_2_0(const GnssLocation_2_0& location) override; - Return gnssRequestLocationCb_2_0(bool /* independentFromGnss */, - bool /* isUserEmergency */) override { - return Void(); - } - Return gnssSetCapabilitiesCb_2_0(uint32_t capabilities) override; - Return gnssSvStatusCb_2_0(const hidl_vec&) override { - return Void(); - } - - // New in v2.1 - Return gnssSvStatusCb_2_1( - const hidl_vec& svInfoList) override; - Return gnssSetCapabilitiesCb_2_1(uint32_t capabilities) override; - - private: - Return gnssLocationCbImpl(const GnssLocation_2_0& location); - }; - - /* Callback class for GnssMeasurement. */ - class GnssMeasurementCallback : public IGnssMeasurementCallback_2_1 { - public: - GnssCallbackEventQueue measurement_cbq_; - - GnssMeasurementCallback() : measurement_cbq_("measurement"){}; - virtual ~GnssMeasurementCallback() = default; - - // Methods from V1_0::IGnssMeasurementCallback follow. - Return GnssMeasurementCb(const IGnssMeasurementCallback_1_0::GnssData&) override { - return Void(); - } - - // Methods from V1_1::IGnssMeasurementCallback follow. - Return gnssMeasurementCb(const IGnssMeasurementCallback_1_1::GnssData&) override { - return Void(); - } - - // Methods from V2_0::IGnssMeasurementCallback follow. - Return gnssMeasurementCb_2_0(const IGnssMeasurementCallback_2_0::GnssData&) override { - return Void(); - } - - // Methods from V2_1::IGnssMeasurementCallback follow. - Return gnssMeasurementCb_2_1(const IGnssMeasurementCallback_2_1::GnssData&) override; - }; - - /* Callback class for GnssMeasurementCorrections. */ - class GnssMeasurementCorrectionsCallback : public IMeasurementCorrectionsCallback { - public: - uint32_t last_capabilities_; - GnssCallbackEventQueue capabilities_cbq_; - - GnssMeasurementCorrectionsCallback() : capabilities_cbq_("capabilities"){}; - virtual ~GnssMeasurementCorrectionsCallback() = default; - - // Methods from V1_0::IMeasurementCorrectionsCallback follow. - Return setCapabilitiesCb(uint32_t capabilities) override; - }; - - /* Callback class for GnssAntennaInfo. */ - class GnssAntennaInfoCallback : public IGnssAntennaInfoCallback { - public: - GnssCallbackEventQueue> - antenna_info_cbq_; - - GnssAntennaInfoCallback() : antenna_info_cbq_("info"){}; - virtual ~GnssAntennaInfoCallback() = default; - - // Methods from V2_1::GnssAntennaInfoCallback follow. - Return gnssAntennaInfoCb( - const hidl_vec& gnssAntennaInfos); - }; - - /* - * SetUpGnssCallback: - * Set GnssCallback and verify the result. - */ - void SetUpGnssCallback(); - - /* - * StartAndCheckFirstLocation: - * Helper function to start location, and check the first one. - * - *

Note this leaves the Location request active, to enable Stop call vs. other call - * reordering tests. - * - * returns true if a location was successfully generated - */ - bool StartAndCheckFirstLocation(); - - /* - * CheckLocation: - * Helper function to vet Location fields - * - * check_speed: true if speed related fields are also verified. + /** + * IsGnssHalVersion_2_1: + * returns true if the GNSS HAL version is exactly 2.1. */ - void CheckLocation(const GnssLocation_2_0& location, const bool check_speed); - - /* - * StartAndCheckLocations: - * Helper function to collect, and check a number of - * normal ~1Hz locations. - * - * Note this leaves the Location request active, to enable Stop call vs. other call - * reordering tests. - */ - void StartAndCheckLocations(int count); - - /* - * StopAndClearLocations: - * Helper function to stop locations, and clear any remaining notifications - */ - void StopAndClearLocations(); - - /* - * SetPositionMode: - * Helper function to set positioning mode and verify output - */ - void SetPositionMode(const int min_interval_msec, const bool low_power_mode); - - /* - * startLocationAndGetNonGpsConstellation: - * 1. Start location - * 2. Find and return first non-GPS constellation - * - * Note that location is not stopped in this method. The client should call - * StopAndClearLocations() after the call. - */ - GnssConstellationType startLocationAndGetNonGpsConstellation( - const int locations_to_await, const int gnss_sv_info_list_timeout); - - sp gnss_hal_; // GNSS HAL to call into - sp gnss_cb_; // Primary callback interface + bool IsGnssHalVersion_2_1() const; }; - -#endif // GNSS_HAL_TEST_H_ diff --git a/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp index 290280922ce5e5f6e81f7aa6db3cdb5e709fa259..8fa5f7e6685f2da1e4ac849cf9bdaa11b8bacf4e 100644 --- a/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp +++ b/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp @@ -27,6 +27,9 @@ using android::hardware::hidl_vec; using android::hardware::gnss::common::Utils; +using android::hardware::gnss::V2_1::IGnssAntennaInfo; +using android::hardware::gnss::V2_1::IGnssAntennaInfoCallback; + using IGnssMeasurement_2_1 = android::hardware::gnss::V2_1::IGnssMeasurement; using IGnssMeasurement_2_0 = android::hardware::gnss::V2_0::IGnssMeasurement; using IGnssMeasurement_1_1 = android::hardware::gnss::V1_1::IGnssMeasurement; @@ -87,6 +90,10 @@ TEST_P(GnssHalTest, TestGnssMeasurementExtension) { * Gets the GnssConfigurationExtension and verifies that it returns an actual extension. */ TEST_P(GnssHalTest, TestGnssConfigurationExtension) { + if (!IsGnssHalVersion_2_1()) { + ALOGI("Test TestGnssConfigurationExtension skipped. GNSS HAL version is greater than 2.1."); + return; + } auto gnssConfiguration_2_1 = gnss_hal_->getExtensionGnssConfiguration_2_1(); auto gnssConfiguration_2_0 = gnss_hal_->getExtensionGnssConfiguration_2_0(); auto gnssConfiguration_1_1 = gnss_hal_->getExtensionGnssConfiguration_1_1(); @@ -242,35 +249,40 @@ TEST_P(GnssHalTest, TestGnssAntennaInfo) { /* * TestGnssSvInfoFields: - * Gets 1 location and a GnssSvInfo, and verifies - * 1. basebandCN0DbHz is valid. + * Gets 1 location and a (non-empty) GnssSvInfo, and verifies basebandCN0DbHz is valid. */ TEST_P(GnssHalTest, TestGnssSvInfoFields) { gnss_cb_->location_cbq_.reset(); - StartAndCheckFirstLocation(); + gnss_cb_->sv_info_list_cbq_.reset(); + StartAndCheckFirstLocation(/* min_interval_msec= */ 1000, /* low_power_mode= */ false); int location_called_count = gnss_cb_->location_cbq_.calledCount(); - - // Tolerate 1 less sv status to handle edge cases in reporting. - int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size(); - EXPECT_GE(sv_info_list_cbq_size, 0); ALOGD("Observed %d GnssSvStatus, while awaiting one location (%d received)", - sv_info_list_cbq_size, location_called_count); - - // Get the last sv_info_list - std::list> sv_info_vec_list; - gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec_list, sv_info_list_cbq_size, 1); - hidl_vec last_sv_info_list = sv_info_vec_list.back(); - + gnss_cb_->sv_info_list_cbq_.size(), location_called_count); + + // Wait for up to kNumSvInfoLists events for kTimeoutSeconds for each event. + int kTimeoutSeconds = 2; + int kNumSvInfoLists = 4; + std::list> sv_info_lists; + hidl_vec last_sv_info_list; + + do { + EXPECT_GT(gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_lists, kNumSvInfoLists, + kTimeoutSeconds), + 0); + last_sv_info_list = sv_info_lists.back(); + } while (last_sv_info_list.size() == 0); + + ALOGD("last_sv_info size = %d", (int)last_sv_info_list.size()); bool nonZeroCn0Found = false; for (auto sv_info : last_sv_info_list) { - ASSERT_TRUE(sv_info.basebandCN0DbHz >= 0.0 && sv_info.basebandCN0DbHz <= 65.0); + EXPECT_TRUE(sv_info.basebandCN0DbHz >= 0.0 && sv_info.basebandCN0DbHz <= 65.0); if (sv_info.basebandCN0DbHz > 0.0) { nonZeroCn0Found = true; } } // Assert at least one value is non-zero. Zero is ok in status as it's possibly // reporting a searched but not found satellite. - ASSERT_TRUE(nonZeroCn0Found); + EXPECT_TRUE(nonZeroCn0Found); StopAndClearLocations(); } @@ -358,20 +370,24 @@ IGnssConfiguration::BlacklistedSource FindStrongFrequentNonGpsSource( } /* - * BlacklistIndividualSatellites: + * BlocklistIndividualSatellites: * * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding * GnssStatus for common satellites (strongest and one other.) - * 2a & b) Turns off location, and blacklists common satellites. + * 2a & b) Turns off location, and blocklists common satellites. * 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding * GnssStatus does not use those satellites. - * 4a & b) Turns off location, and send in empty blacklist. + * 4a & b) Turns off location, and send in empty blocklist. * 5a) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding * GnssStatus does re-use at least the previously strongest satellite * 5b) Retry a few times, in case GNSS search strategy takes a while to reacquire even the * formerly strongest satellite */ -TEST_P(GnssHalTest, BlacklistIndividualSatellites) { +TEST_P(GnssHalTest, BlocklistIndividualSatellites) { + if (!IsGnssHalVersion_2_1()) { + ALOGI("Test BlocklistIndividualSatellites skipped. GNSS HAL version is greater than 2.1."); + return; + } if (!(gnss_cb_->last_capabilities_ & IGnssCallback_2_1::Capabilities::SATELLITE_BLACKLIST)) { ALOGI("Test BlacklistIndividualSatellites skipped. SATELLITE_BLACKLIST capability not " "supported."); @@ -509,16 +525,21 @@ TEST_P(GnssHalTest, BlacklistIndividualSatellites) { } /* - * BlacklistConstellationLocationOff: + * BlocklistConstellationLocationOff: * * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding * GnssStatus for any non-GPS constellations. - * 2a & b) Turns off location, and blacklist first non-GPS constellations. + * 2a & b) Turns off location, and blocklist first non-GPS constellations. * 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding * GnssStatus does not use any constellation but GPS. - * 4a & b) Clean up by turning off location, and send in empty blacklist. + * 4a & b) Clean up by turning off location, and send in empty blocklist. */ -TEST_P(GnssHalTest, BlacklistConstellationLocationOff) { +TEST_P(GnssHalTest, BlocklistConstellationLocationOff) { + if (!IsGnssHalVersion_2_1()) { + ALOGI("Test BlocklistConstellationLocationOff skipped. GNSS HAL version is greater than " + "2.1."); + return; + } if (!(gnss_cb_->last_capabilities_ & IGnssCallback_2_1::Capabilities::SATELLITE_BLACKLIST)) { ALOGI("Test BlacklistConstellationLocationOff skipped. SATELLITE_BLACKLIST capability not " "supported."); @@ -591,16 +612,21 @@ TEST_P(GnssHalTest, BlacklistConstellationLocationOff) { } /* - * BlacklistConstellationLocationOn: + * BlocklistConstellationLocationOn: * * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding * GnssStatus for any non-GPS constellations. - * 2a & b) Blacklist first non-GPS constellation, and turn off location. + * 2a & b) Blocklist first non-GPS constellation, and turn off location. * 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding * GnssStatus does not use any constellation but GPS. - * 4a & b) Clean up by turning off location, and send in empty blacklist. + * 4a & b) Clean up by turning off location, and send in empty blocklist. */ -TEST_P(GnssHalTest, BlacklistConstellationLocationOn) { +TEST_P(GnssHalTest, BlocklistConstellationLocationOn) { + if (!IsGnssHalVersion_2_1()) { + ALOGI("Test BlocklistConstellationLocationOn skipped. GNSS HAL version is greater than " + "2.1."); + return; + } if (!(gnss_cb_->last_capabilities_ & IGnssCallback_2_1::Capabilities::SATELLITE_BLACKLIST)) { ALOGI("Test BlacklistConstellationLocationOn skipped. SATELLITE_BLACKLIST capability not " "supported."); diff --git a/gnss/aidl/Android.bp b/gnss/aidl/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..b197eae32d6d77a2393ec87099ed0ca202bede51 --- /dev/null +++ b/gnss/aidl/Android.bp @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +aidl_interface { + name: "android.hardware.gnss", + vendor_available: true, + srcs: ["android/hardware/gnss/*.aidl"], + stability: "vintf", + backend: { + java: { + platform_apis: true, + }, + ndk: { + vndk: { + enabled: true, + }, + }, + }, + versions: ["1"], +} diff --git a/gnss/aidl/OWNERS b/gnss/aidl/OWNERS new file mode 100644 index 0000000000000000000000000000000000000000..b7b4a2e902d7b45012af30dc0160c3ef7be59b32 --- /dev/null +++ b/gnss/aidl/OWNERS @@ -0,0 +1,4 @@ +gomo@google.com +smalkos@google.com +wyattriley@google.com +yuhany@google.com diff --git a/gnss/aidl/TEST_MAPPING b/gnss/aidl/TEST_MAPPING new file mode 100644 index 0000000000000000000000000000000000000000..c21c3e49ccfc7bda7a5ed391cf30586b3ed9bf81 --- /dev/null +++ b/gnss/aidl/TEST_MAPPING @@ -0,0 +1,7 @@ +{ + "presubmit": [ + { + "name": "VtsHalGnssTargetTest" + } + ] +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/1/.hash b/gnss/aidl/aidl_api/android.hardware.gnss/1/.hash new file mode 100644 index 0000000000000000000000000000000000000000..2f689c405471ac3b0df0912731c4987002462c3a --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/1/.hash @@ -0,0 +1 @@ +10839720b90aaec329521e810d9e0501cfcef0d3 diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/BlocklistedSource.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/BlocklistedSource.aidl new file mode 100644 index 0000000000000000000000000000000000000000..a4f00971c5ceb9005c08f6d9931f4af9deb22475 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/BlocklistedSource.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +parcelable BlocklistedSource { + android.hardware.gnss.GnssConstellationType constellation = android.hardware.gnss.GnssConstellationType.UNKNOWN; + int svid; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/CorrelationVector.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/CorrelationVector.aidl new file mode 100644 index 0000000000000000000000000000000000000000..b0848bb9c4ba76badd49a551d8d7d20280bdff95 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/CorrelationVector.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +parcelable CorrelationVector { + double frequencyOffsetMps; + double samplingWidthM; + double samplingStartM; + int[] magnitude; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/ElapsedRealtime.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/ElapsedRealtime.aidl new file mode 100644 index 0000000000000000000000000000000000000000..7d3baa41f2ceef0ca4b762eb39574ca2ea026f09 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/ElapsedRealtime.aidl @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +parcelable ElapsedRealtime { + int flags; + long timestampNs; + double timeUncertaintyNs; + const int HAS_TIMESTAMP_NS = 1; + const int HAS_TIME_UNCERTAINTY_NS = 2; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/GnssClock.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/GnssClock.aidl new file mode 100644 index 0000000000000000000000000000000000000000..c54cc2c50097f3c92c9686f5fa9b3800f3ed9f99 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/GnssClock.aidl @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +parcelable GnssClock { + int gnssClockFlags; + int leapSecond; + long timeNs; + double timeUncertaintyNs; + long fullBiasNs; + double biasNs; + double biasUncertaintyNs; + double driftNsps; + double driftUncertaintyNsps; + int hwClockDiscontinuityCount; + android.hardware.gnss.GnssSignalType referenceSignalTypeForIsb; + const int HAS_LEAP_SECOND = 1; + const int HAS_TIME_UNCERTAINTY = 2; + const int HAS_FULL_BIAS = 4; + const int HAS_BIAS = 8; + const int HAS_BIAS_UNCERTAINTY = 16; + const int HAS_DRIFT = 32; + const int HAS_DRIFT_UNCERTAINTY = 64; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/GnssConstellationType.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/GnssConstellationType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..c1fcfcc741547e41994136319a50f42d11c52d29 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/GnssConstellationType.aidl @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@Backing(type="int") @VintfStability +enum GnssConstellationType { + UNKNOWN = 0, + GPS = 1, + SBAS = 2, + GLONASS = 3, + QZSS = 4, + BEIDOU = 5, + GALILEO = 6, + IRNSS = 7, +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/GnssData.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/GnssData.aidl new file mode 100644 index 0000000000000000000000000000000000000000..ebb5d0bdff51955797d74a026b7539de3d5d2c94 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/GnssData.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +parcelable GnssData { + android.hardware.gnss.GnssMeasurement[] measurements; + android.hardware.gnss.GnssClock clock; + android.hardware.gnss.ElapsedRealtime elapsedRealtime; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/GnssMeasurement.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/GnssMeasurement.aidl new file mode 100644 index 0000000000000000000000000000000000000000..948c540fc319f40ceb255643cc6a5e5316c2da4d --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/GnssMeasurement.aidl @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +parcelable GnssMeasurement { + int flags; + int svid; + android.hardware.gnss.GnssSignalType signalType; + double timeOffsetNs; + int state; + long receivedSvTimeInNs; + long receivedSvTimeUncertaintyInNs; + double antennaCN0DbHz; + double basebandCN0DbHz; + double pseudorangeRateMps; + double pseudorangeRateUncertaintyMps; + int accumulatedDeltaRangeState; + double accumulatedDeltaRangeM; + double accumulatedDeltaRangeUncertaintyM; + long carrierCycles; + double carrierPhase; + double carrierPhaseUncertainty; + android.hardware.gnss.GnssMultipathIndicator multipathIndicator = android.hardware.gnss.GnssMultipathIndicator.UNKNOWN; + double snrDb; + double agcLevelDb; + double fullInterSignalBiasNs; + double fullInterSignalBiasUncertaintyNs; + double satelliteInterSignalBiasNs; + double satelliteInterSignalBiasUncertaintyNs; + android.hardware.gnss.SatellitePvt satellitePvt; + android.hardware.gnss.CorrelationVector[] correlationVectors; + const int HAS_SNR = 1; + const int HAS_CARRIER_FREQUENCY = 512; + const int HAS_CARRIER_CYCLES = 1024; + const int HAS_CARRIER_PHASE = 2048; + const int HAS_CARRIER_PHASE_UNCERTAINTY = 4096; + const int HAS_AUTOMATIC_GAIN_CONTROL = 8192; + const int HAS_FULL_ISB = 65536; + const int HAS_FULL_ISB_UNCERTAINTY = 131072; + const int HAS_SATELLITE_ISB = 262144; + const int HAS_SATELLITE_ISB_UNCERTAINTY = 524288; + const int HAS_SATELLITE_PVT = 1048576; + const int HAS_CORRELATION_VECTOR = 2097152; + const int STATE_UNKNOWN = 0; + const int STATE_CODE_LOCK = 1; + const int STATE_BIT_SYNC = 2; + const int STATE_SUBFRAME_SYNC = 4; + const int STATE_TOW_DECODED = 8; + const int STATE_MSEC_AMBIGUOUS = 16; + const int STATE_SYMBOL_SYNC = 32; + const int STATE_GLO_STRING_SYNC = 64; + const int STATE_GLO_TOD_DECODED = 128; + const int STATE_BDS_D2_BIT_SYNC = 256; + const int STATE_BDS_D2_SUBFRAME_SYNC = 512; + const int STATE_GAL_E1BC_CODE_LOCK = 1024; + const int STATE_GAL_E1C_2ND_CODE_LOCK = 2048; + const int STATE_GAL_E1B_PAGE_SYNC = 4096; + const int STATE_SBAS_SYNC = 8192; + const int STATE_TOW_KNOWN = 16384; + const int STATE_GLO_TOD_KNOWN = 32768; + const int STATE_2ND_CODE_LOCK = 65536; + const int ADR_STATE_UNKNOWN = 0; + const int ADR_STATE_VALID = 1; + const int ADR_STATE_RESET = 2; + const int ADR_STATE_CYCLE_SLIP = 4; + const int ADR_STATE_HALF_CYCLE_RESOLVED = 8; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/GnssMultipathIndicator.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/GnssMultipathIndicator.aidl new file mode 100644 index 0000000000000000000000000000000000000000..24f45c42fa32cdcd1a945bc6181556012db94738 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/GnssMultipathIndicator.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@Backing(type="int") @VintfStability +enum GnssMultipathIndicator { + UNKNOWN = 0, + PRESENT = 1, + NOT_PRESENT = 2, +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/GnssPowerStats.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/GnssPowerStats.aidl new file mode 100644 index 0000000000000000000000000000000000000000..670244fd1f68edaa51ce3c88a3dce26c7314fe7d --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/GnssPowerStats.aidl @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +parcelable GnssPowerStats { + android.hardware.gnss.ElapsedRealtime elapsedRealtime; + double totalEnergyMilliJoule; + double singlebandTrackingModeEnergyMilliJoule; + double multibandTrackingModeEnergyMilliJoule; + double singlebandAcquisitionModeEnergyMilliJoule; + double multibandAcquisitionModeEnergyMilliJoule; + double[] otherModesEnergyMilliJoule; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/GnssSignalType.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/GnssSignalType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..c2a5b51e15f02b9625f8b1be1d59bbd5e2c75c78 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/GnssSignalType.aidl @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +parcelable GnssSignalType { + android.hardware.gnss.GnssConstellationType constellation = android.hardware.gnss.GnssConstellationType.UNKNOWN; + double carrierFrequencyHz; + @utf8InCpp String codeType; + const @utf8InCpp String CODE_TYPE_A = "A"; + const @utf8InCpp String CODE_TYPE_B = "B"; + const @utf8InCpp String CODE_TYPE_C = "C"; + const @utf8InCpp String CODE_TYPE_D = "D"; + const @utf8InCpp String CODE_TYPE_I = "I"; + const @utf8InCpp String CODE_TYPE_L = "L"; + const @utf8InCpp String CODE_TYPE_M = "M"; + const @utf8InCpp String CODE_TYPE_N = "N"; + const @utf8InCpp String CODE_TYPE_P = "P"; + const @utf8InCpp String CODE_TYPE_Q = "Q"; + const @utf8InCpp String CODE_TYPE_S = "S"; + const @utf8InCpp String CODE_TYPE_W = "W"; + const @utf8InCpp String CODE_TYPE_X = "X"; + const @utf8InCpp String CODE_TYPE_Y = "Y"; + const @utf8InCpp String CODE_TYPE_Z = "Z"; + const @utf8InCpp String CODE_TYPE_UNKNOWN = "UNKNOWN"; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/IGnss.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/IGnss.aidl new file mode 100644 index 0000000000000000000000000000000000000000..f93b496cddb941d159fc80e75955d6e8d958120b --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/IGnss.aidl @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +interface IGnss { + void setCallback(in android.hardware.gnss.IGnssCallback callback); + void close(); + android.hardware.gnss.IGnssPsds getExtensionPsds(); + android.hardware.gnss.IGnssConfiguration getExtensionGnssConfiguration(); + android.hardware.gnss.IGnssMeasurementInterface getExtensionGnssMeasurement(); + android.hardware.gnss.IGnssPowerIndication getExtensionGnssPowerIndication(); + const int ERROR_INVALID_ARGUMENT = 1; + const int ERROR_ALREADY_INIT = 2; + const int ERROR_GENERIC = 3; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/IGnssCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/IGnssCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..fb0931c59adc66f0b85de99a4896104a69fa8c5f --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/IGnssCallback.aidl @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +interface IGnssCallback { + void gnssSetCapabilitiesCb(in int capabilities); + const int CAPABILITY_SATELLITE_BLOCKLIST = 512; + const int CAPABILITY_CORRELATION_VECTOR = 4096; + const int CAPABILITY_SATELLITE_PVT = 8192; + const int CAPABILITY_MEASUREMENT_CORRECTIONS_FOR_DRIVING = 16384; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/IGnssConfiguration.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/IGnssConfiguration.aidl new file mode 100644 index 0000000000000000000000000000000000000000..54cd022f66b14e5de4d06ca785a460586a215c5b --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/IGnssConfiguration.aidl @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +interface IGnssConfiguration { + void setSuplVersion(in int version); + void setSuplMode(in int mode); + void setLppProfile(in int lppProfile); + void setGlonassPositioningProtocol(in int protocol); + void setEmergencySuplPdn(in boolean enable); + void setEsExtensionSec(in int emergencyExtensionSeconds); + void setBlocklist(in android.hardware.gnss.BlocklistedSource[] blocklist); + const int SUPL_MODE_MSB = 1; + const int SUPL_MODE_MSA = 2; + const int LPP_PROFILE_USER_PLANE = 1; + const int LPP_PROFILE_CONTROL_PLANE = 2; + const int GLONASS_POS_PROTOCOL_RRC_CPLANE = 1; + const int GLONASS_POS_PROTOCOL_RRLP_UPLANE = 2; + const int GLONASS_POS_PROTOCOL_LPP_UPLANE = 4; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/IGnssMeasurementCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/IGnssMeasurementCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..6e626172b9d2f799c77b67f2354d9e05a0268649 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/IGnssMeasurementCallback.aidl @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +interface IGnssMeasurementCallback { + void gnssMeasurementCb(in android.hardware.gnss.GnssData data); +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/IGnssMeasurementInterface.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/IGnssMeasurementInterface.aidl new file mode 100644 index 0000000000000000000000000000000000000000..24d6f9c4cf6a6bcdd685d9189d7d9f1a156c9914 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/IGnssMeasurementInterface.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +interface IGnssMeasurementInterface { + void setCallback(in android.hardware.gnss.IGnssMeasurementCallback callback, in boolean enableFullTracking, in boolean enableCorrVecOutputs); + void close(); +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/IGnssPowerIndication.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/IGnssPowerIndication.aidl new file mode 100644 index 0000000000000000000000000000000000000000..fbf1f6ffb600be07edb1ad1105b859fa590df146 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/IGnssPowerIndication.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +interface IGnssPowerIndication { + void setCallback(in android.hardware.gnss.IGnssPowerIndicationCallback callback); + oneway void requestGnssPowerStats(); +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/IGnssPowerIndicationCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/IGnssPowerIndicationCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..bfa787e3e2579df756fba0e7750e2dd4ed6053d1 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/IGnssPowerIndicationCallback.aidl @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +interface IGnssPowerIndicationCallback { + void setCapabilitiesCb(in int capabilities); + oneway void gnssPowerStatsCb(in android.hardware.gnss.GnssPowerStats gnssPowerStats); + const int CAPABILITY_TOTAL = 1; + const int CAPABILITY_SINGLEBAND_TRACKING = 2; + const int CAPABILITY_MULTIBAND_TRACKING = 4; + const int CAPABILITY_SINGLEBAND_ACQUISITION = 8; + const int CAPABILITY_MULTIBAND_ACQUISITION = 16; + const int CAPABILITY_OTHER_MODES = 32; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/IGnssPsds.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/IGnssPsds.aidl new file mode 100644 index 0000000000000000000000000000000000000000..526ecc8fcdfb92171a345aa5501c8a3de6c7c049 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/IGnssPsds.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +interface IGnssPsds { + void injectPsdsData(in android.hardware.gnss.PsdsType psdsType, in byte[] psdsData); + void setCallback(in android.hardware.gnss.IGnssPsdsCallback callback); +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/IGnssPsdsCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/IGnssPsdsCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..2205bc46dd91868a70f6df572d280221fda72ac0 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/IGnssPsdsCallback.aidl @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +interface IGnssPsdsCallback { + void downloadRequestCb(in android.hardware.gnss.PsdsType psdsType); +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/PsdsType.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/PsdsType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..727bb6912b9c74468d5778a2f50d36f72f9654be --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/PsdsType.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@Backing(type="int") @VintfStability +enum PsdsType { + LONG_TERM = 1, + NORMAL = 2, + REALTIME = 3, +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/SatelliteClockInfo.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/SatelliteClockInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..ed23e639a8a76fc830f456cd167adc934b48bef3 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/SatelliteClockInfo.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +parcelable SatelliteClockInfo { + double satHardwareCodeBiasMeters; + double satTimeCorrectionMeters; + double satClkDriftMps; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/SatellitePositionEcef.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/SatellitePositionEcef.aidl new file mode 100644 index 0000000000000000000000000000000000000000..e1a20c378ec5e809859bc3acf847bed492215870 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/SatellitePositionEcef.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +parcelable SatellitePositionEcef { + double posXMeters; + double posYMeters; + double posZMeters; + double ureMeters; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/SatellitePvt.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/SatellitePvt.aidl new file mode 100644 index 0000000000000000000000000000000000000000..8c1784174d2d75bf8cf3b3dbb0d8a80d4e567c07 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/SatellitePvt.aidl @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +parcelable SatellitePvt { + int flags; + android.hardware.gnss.SatellitePositionEcef satPosEcef; + android.hardware.gnss.SatelliteVelocityEcef satVelEcef; + android.hardware.gnss.SatelliteClockInfo satClockInfo; + double ionoDelayMeters; + double tropoDelayMeters; + const int HAS_POSITION_VELOCITY_CLOCK_INFO = 1; + const int HAS_IONO = 2; + const int HAS_TROPO = 4; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/SatelliteVelocityEcef.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/SatelliteVelocityEcef.aidl new file mode 100644 index 0000000000000000000000000000000000000000..a571048c205fe49375ebe9b0cb3c6a341cd9a87a --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/1/android/hardware/gnss/SatelliteVelocityEcef.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +parcelable SatelliteVelocityEcef { + double velXMps; + double velYMps; + double velZMps; + double ureRateMps; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/BlocklistedSource.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/BlocklistedSource.aidl new file mode 100644 index 0000000000000000000000000000000000000000..a4f00971c5ceb9005c08f6d9931f4af9deb22475 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/BlocklistedSource.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +parcelable BlocklistedSource { + android.hardware.gnss.GnssConstellationType constellation = android.hardware.gnss.GnssConstellationType.UNKNOWN; + int svid; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/CorrelationVector.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/CorrelationVector.aidl new file mode 100644 index 0000000000000000000000000000000000000000..b0848bb9c4ba76badd49a551d8d7d20280bdff95 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/CorrelationVector.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +parcelable CorrelationVector { + double frequencyOffsetMps; + double samplingWidthM; + double samplingStartM; + int[] magnitude; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/ElapsedRealtime.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/ElapsedRealtime.aidl new file mode 100644 index 0000000000000000000000000000000000000000..7d3baa41f2ceef0ca4b762eb39574ca2ea026f09 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/ElapsedRealtime.aidl @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +parcelable ElapsedRealtime { + int flags; + long timestampNs; + double timeUncertaintyNs; + const int HAS_TIMESTAMP_NS = 1; + const int HAS_TIME_UNCERTAINTY_NS = 2; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssClock.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssClock.aidl new file mode 100644 index 0000000000000000000000000000000000000000..c54cc2c50097f3c92c9686f5fa9b3800f3ed9f99 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssClock.aidl @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +parcelable GnssClock { + int gnssClockFlags; + int leapSecond; + long timeNs; + double timeUncertaintyNs; + long fullBiasNs; + double biasNs; + double biasUncertaintyNs; + double driftNsps; + double driftUncertaintyNsps; + int hwClockDiscontinuityCount; + android.hardware.gnss.GnssSignalType referenceSignalTypeForIsb; + const int HAS_LEAP_SECOND = 1; + const int HAS_TIME_UNCERTAINTY = 2; + const int HAS_FULL_BIAS = 4; + const int HAS_BIAS = 8; + const int HAS_BIAS_UNCERTAINTY = 16; + const int HAS_DRIFT = 32; + const int HAS_DRIFT_UNCERTAINTY = 64; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssConstellationType.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssConstellationType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..c1fcfcc741547e41994136319a50f42d11c52d29 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssConstellationType.aidl @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@Backing(type="int") @VintfStability +enum GnssConstellationType { + UNKNOWN = 0, + GPS = 1, + SBAS = 2, + GLONASS = 3, + QZSS = 4, + BEIDOU = 5, + GALILEO = 6, + IRNSS = 7, +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssData.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssData.aidl new file mode 100644 index 0000000000000000000000000000000000000000..ebb5d0bdff51955797d74a026b7539de3d5d2c94 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssData.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +parcelable GnssData { + android.hardware.gnss.GnssMeasurement[] measurements; + android.hardware.gnss.GnssClock clock; + android.hardware.gnss.ElapsedRealtime elapsedRealtime; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMeasurement.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMeasurement.aidl new file mode 100644 index 0000000000000000000000000000000000000000..948c540fc319f40ceb255643cc6a5e5316c2da4d --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMeasurement.aidl @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +parcelable GnssMeasurement { + int flags; + int svid; + android.hardware.gnss.GnssSignalType signalType; + double timeOffsetNs; + int state; + long receivedSvTimeInNs; + long receivedSvTimeUncertaintyInNs; + double antennaCN0DbHz; + double basebandCN0DbHz; + double pseudorangeRateMps; + double pseudorangeRateUncertaintyMps; + int accumulatedDeltaRangeState; + double accumulatedDeltaRangeM; + double accumulatedDeltaRangeUncertaintyM; + long carrierCycles; + double carrierPhase; + double carrierPhaseUncertainty; + android.hardware.gnss.GnssMultipathIndicator multipathIndicator = android.hardware.gnss.GnssMultipathIndicator.UNKNOWN; + double snrDb; + double agcLevelDb; + double fullInterSignalBiasNs; + double fullInterSignalBiasUncertaintyNs; + double satelliteInterSignalBiasNs; + double satelliteInterSignalBiasUncertaintyNs; + android.hardware.gnss.SatellitePvt satellitePvt; + android.hardware.gnss.CorrelationVector[] correlationVectors; + const int HAS_SNR = 1; + const int HAS_CARRIER_FREQUENCY = 512; + const int HAS_CARRIER_CYCLES = 1024; + const int HAS_CARRIER_PHASE = 2048; + const int HAS_CARRIER_PHASE_UNCERTAINTY = 4096; + const int HAS_AUTOMATIC_GAIN_CONTROL = 8192; + const int HAS_FULL_ISB = 65536; + const int HAS_FULL_ISB_UNCERTAINTY = 131072; + const int HAS_SATELLITE_ISB = 262144; + const int HAS_SATELLITE_ISB_UNCERTAINTY = 524288; + const int HAS_SATELLITE_PVT = 1048576; + const int HAS_CORRELATION_VECTOR = 2097152; + const int STATE_UNKNOWN = 0; + const int STATE_CODE_LOCK = 1; + const int STATE_BIT_SYNC = 2; + const int STATE_SUBFRAME_SYNC = 4; + const int STATE_TOW_DECODED = 8; + const int STATE_MSEC_AMBIGUOUS = 16; + const int STATE_SYMBOL_SYNC = 32; + const int STATE_GLO_STRING_SYNC = 64; + const int STATE_GLO_TOD_DECODED = 128; + const int STATE_BDS_D2_BIT_SYNC = 256; + const int STATE_BDS_D2_SUBFRAME_SYNC = 512; + const int STATE_GAL_E1BC_CODE_LOCK = 1024; + const int STATE_GAL_E1C_2ND_CODE_LOCK = 2048; + const int STATE_GAL_E1B_PAGE_SYNC = 4096; + const int STATE_SBAS_SYNC = 8192; + const int STATE_TOW_KNOWN = 16384; + const int STATE_GLO_TOD_KNOWN = 32768; + const int STATE_2ND_CODE_LOCK = 65536; + const int ADR_STATE_UNKNOWN = 0; + const int ADR_STATE_VALID = 1; + const int ADR_STATE_RESET = 2; + const int ADR_STATE_CYCLE_SLIP = 4; + const int ADR_STATE_HALF_CYCLE_RESOLVED = 8; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMultipathIndicator.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMultipathIndicator.aidl new file mode 100644 index 0000000000000000000000000000000000000000..24f45c42fa32cdcd1a945bc6181556012db94738 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMultipathIndicator.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@Backing(type="int") @VintfStability +enum GnssMultipathIndicator { + UNKNOWN = 0, + PRESENT = 1, + NOT_PRESENT = 2, +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssPowerStats.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssPowerStats.aidl new file mode 100644 index 0000000000000000000000000000000000000000..670244fd1f68edaa51ce3c88a3dce26c7314fe7d --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssPowerStats.aidl @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +parcelable GnssPowerStats { + android.hardware.gnss.ElapsedRealtime elapsedRealtime; + double totalEnergyMilliJoule; + double singlebandTrackingModeEnergyMilliJoule; + double multibandTrackingModeEnergyMilliJoule; + double singlebandAcquisitionModeEnergyMilliJoule; + double multibandAcquisitionModeEnergyMilliJoule; + double[] otherModesEnergyMilliJoule; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssSignalType.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssSignalType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..c2a5b51e15f02b9625f8b1be1d59bbd5e2c75c78 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssSignalType.aidl @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +parcelable GnssSignalType { + android.hardware.gnss.GnssConstellationType constellation = android.hardware.gnss.GnssConstellationType.UNKNOWN; + double carrierFrequencyHz; + @utf8InCpp String codeType; + const @utf8InCpp String CODE_TYPE_A = "A"; + const @utf8InCpp String CODE_TYPE_B = "B"; + const @utf8InCpp String CODE_TYPE_C = "C"; + const @utf8InCpp String CODE_TYPE_D = "D"; + const @utf8InCpp String CODE_TYPE_I = "I"; + const @utf8InCpp String CODE_TYPE_L = "L"; + const @utf8InCpp String CODE_TYPE_M = "M"; + const @utf8InCpp String CODE_TYPE_N = "N"; + const @utf8InCpp String CODE_TYPE_P = "P"; + const @utf8InCpp String CODE_TYPE_Q = "Q"; + const @utf8InCpp String CODE_TYPE_S = "S"; + const @utf8InCpp String CODE_TYPE_W = "W"; + const @utf8InCpp String CODE_TYPE_X = "X"; + const @utf8InCpp String CODE_TYPE_Y = "Y"; + const @utf8InCpp String CODE_TYPE_Z = "Z"; + const @utf8InCpp String CODE_TYPE_UNKNOWN = "UNKNOWN"; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl new file mode 100644 index 0000000000000000000000000000000000000000..f93b496cddb941d159fc80e75955d6e8d958120b --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +interface IGnss { + void setCallback(in android.hardware.gnss.IGnssCallback callback); + void close(); + android.hardware.gnss.IGnssPsds getExtensionPsds(); + android.hardware.gnss.IGnssConfiguration getExtensionGnssConfiguration(); + android.hardware.gnss.IGnssMeasurementInterface getExtensionGnssMeasurement(); + android.hardware.gnss.IGnssPowerIndication getExtensionGnssPowerIndication(); + const int ERROR_INVALID_ARGUMENT = 1; + const int ERROR_ALREADY_INIT = 2; + const int ERROR_GENERIC = 3; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..fb0931c59adc66f0b85de99a4896104a69fa8c5f --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.aidl @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +interface IGnssCallback { + void gnssSetCapabilitiesCb(in int capabilities); + const int CAPABILITY_SATELLITE_BLOCKLIST = 512; + const int CAPABILITY_CORRELATION_VECTOR = 4096; + const int CAPABILITY_SATELLITE_PVT = 8192; + const int CAPABILITY_MEASUREMENT_CORRECTIONS_FOR_DRIVING = 16384; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssConfiguration.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssConfiguration.aidl new file mode 100644 index 0000000000000000000000000000000000000000..54cd022f66b14e5de4d06ca785a460586a215c5b --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssConfiguration.aidl @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +interface IGnssConfiguration { + void setSuplVersion(in int version); + void setSuplMode(in int mode); + void setLppProfile(in int lppProfile); + void setGlonassPositioningProtocol(in int protocol); + void setEmergencySuplPdn(in boolean enable); + void setEsExtensionSec(in int emergencyExtensionSeconds); + void setBlocklist(in android.hardware.gnss.BlocklistedSource[] blocklist); + const int SUPL_MODE_MSB = 1; + const int SUPL_MODE_MSA = 2; + const int LPP_PROFILE_USER_PLANE = 1; + const int LPP_PROFILE_CONTROL_PLANE = 2; + const int GLONASS_POS_PROTOCOL_RRC_CPLANE = 1; + const int GLONASS_POS_PROTOCOL_RRLP_UPLANE = 2; + const int GLONASS_POS_PROTOCOL_LPP_UPLANE = 4; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..6e626172b9d2f799c77b67f2354d9e05a0268649 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementCallback.aidl @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +interface IGnssMeasurementCallback { + void gnssMeasurementCb(in android.hardware.gnss.GnssData data); +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementInterface.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementInterface.aidl new file mode 100644 index 0000000000000000000000000000000000000000..24d6f9c4cf6a6bcdd685d9189d7d9f1a156c9914 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementInterface.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +interface IGnssMeasurementInterface { + void setCallback(in android.hardware.gnss.IGnssMeasurementCallback callback, in boolean enableFullTracking, in boolean enableCorrVecOutputs); + void close(); +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndication.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndication.aidl new file mode 100644 index 0000000000000000000000000000000000000000..fbf1f6ffb600be07edb1ad1105b859fa590df146 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndication.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +interface IGnssPowerIndication { + void setCallback(in android.hardware.gnss.IGnssPowerIndicationCallback callback); + oneway void requestGnssPowerStats(); +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndicationCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndicationCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..bfa787e3e2579df756fba0e7750e2dd4ed6053d1 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndicationCallback.aidl @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +interface IGnssPowerIndicationCallback { + void setCapabilitiesCb(in int capabilities); + oneway void gnssPowerStatsCb(in android.hardware.gnss.GnssPowerStats gnssPowerStats); + const int CAPABILITY_TOTAL = 1; + const int CAPABILITY_SINGLEBAND_TRACKING = 2; + const int CAPABILITY_MULTIBAND_TRACKING = 4; + const int CAPABILITY_SINGLEBAND_ACQUISITION = 8; + const int CAPABILITY_MULTIBAND_ACQUISITION = 16; + const int CAPABILITY_OTHER_MODES = 32; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsds.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsds.aidl new file mode 100644 index 0000000000000000000000000000000000000000..526ecc8fcdfb92171a345aa5501c8a3de6c7c049 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsds.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +interface IGnssPsds { + void injectPsdsData(in android.hardware.gnss.PsdsType psdsType, in byte[] psdsData); + void setCallback(in android.hardware.gnss.IGnssPsdsCallback callback); +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsdsCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsdsCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..2205bc46dd91868a70f6df572d280221fda72ac0 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsdsCallback.aidl @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +interface IGnssPsdsCallback { + void downloadRequestCb(in android.hardware.gnss.PsdsType psdsType); +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/PsdsType.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/PsdsType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..727bb6912b9c74468d5778a2f50d36f72f9654be --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/PsdsType.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@Backing(type="int") @VintfStability +enum PsdsType { + LONG_TERM = 1, + NORMAL = 2, + REALTIME = 3, +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatelliteClockInfo.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatelliteClockInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..ed23e639a8a76fc830f456cd167adc934b48bef3 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatelliteClockInfo.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +parcelable SatelliteClockInfo { + double satHardwareCodeBiasMeters; + double satTimeCorrectionMeters; + double satClkDriftMps; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatellitePositionEcef.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatellitePositionEcef.aidl new file mode 100644 index 0000000000000000000000000000000000000000..e1a20c378ec5e809859bc3acf847bed492215870 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatellitePositionEcef.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +parcelable SatellitePositionEcef { + double posXMeters; + double posYMeters; + double posZMeters; + double ureMeters; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatellitePvt.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatellitePvt.aidl new file mode 100644 index 0000000000000000000000000000000000000000..8c1784174d2d75bf8cf3b3dbb0d8a80d4e567c07 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatellitePvt.aidl @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +parcelable SatellitePvt { + int flags; + android.hardware.gnss.SatellitePositionEcef satPosEcef; + android.hardware.gnss.SatelliteVelocityEcef satVelEcef; + android.hardware.gnss.SatelliteClockInfo satClockInfo; + double ionoDelayMeters; + double tropoDelayMeters; + const int HAS_POSITION_VELOCITY_CLOCK_INFO = 1; + const int HAS_IONO = 2; + const int HAS_TROPO = 4; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatelliteVelocityEcef.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatelliteVelocityEcef.aidl new file mode 100644 index 0000000000000000000000000000000000000000..a571048c205fe49375ebe9b0cb3c6a341cd9a87a --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatelliteVelocityEcef.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +parcelable SatelliteVelocityEcef { + double velXMps; + double velYMps; + double velZMps; + double ureRateMps; +} diff --git a/gnss/aidl/android/hardware/gnss/BlocklistedSource.aidl b/gnss/aidl/android/hardware/gnss/BlocklistedSource.aidl new file mode 100644 index 0000000000000000000000000000000000000000..8b730921ffddbb518c06db3832e15b31afb09e25 --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/BlocklistedSource.aidl @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.gnss; + +import android.hardware.gnss.GnssConstellationType; + +/** + * Represents a blocklisted source. + */ +@VintfStability +parcelable BlocklistedSource { + /** + * Defines the constellation of the given satellite(s). + */ + GnssConstellationType constellation = GnssConstellationType.UNKNOWN; + + /** + * Satellite (space vehicle) ID number, as defined in GnssSvInfo::svid, or 0 to blocklist all + * svid's for the specified constellation. + */ + int svid; +} \ No newline at end of file diff --git a/gnss/aidl/android/hardware/gnss/CorrelationVector.aidl b/gnss/aidl/android/hardware/gnss/CorrelationVector.aidl new file mode 100644 index 0000000000000000000000000000000000000000..6fbabbc1406dd156ae0b8e48520c8f62bf90bf47 --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/CorrelationVector.aidl @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.gnss; + +/** + * Contains info about the correlation output of incoming GNSS signal and a local copy of + * its corresponding spreading code at a given frequency offset. + */ +@VintfStability +parcelable CorrelationVector { + /** + * Frequency offset from reported pseudorange rate for this Correlation Vector. + */ + double frequencyOffsetMps; + + /** + * Space between correlation samples in meters. + */ + double samplingWidthM; + + /** + * Offset of the first sampling bin in meters. + * The following sampling bins are located at positive offsets from this value as follows: + * samplingStartM, samplingStartM + samplingWidthM, ... , samplingStartM + + * (magnitude.size-1) * samplingWidthM. + */ + double samplingStartM; + + /** + * Normalized correlation magnitude values from -1 to 1, the reported value must be encoded as + * signed 16 bit integer where 1 is represented by 32767 and -1 is represented by -32768. + * + * The length of the array is defined by the GNSS chipset. + */ + int[] magnitude; +} diff --git a/gnss/aidl/android/hardware/gnss/ElapsedRealtime.aidl b/gnss/aidl/android/hardware/gnss/ElapsedRealtime.aidl new file mode 100644 index 0000000000000000000000000000000000000000..67d090eb24252facab17369decf4b8b0796a9957 --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/ElapsedRealtime.aidl @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.gnss; + +/** + * Cumulative GNSS power statistics since boot. + */ +@VintfStability +parcelable ElapsedRealtime { + + /** Bit mask indicating a valid timestampNs is stored in the ElapsedRealtime parcelable. */ + const int HAS_TIMESTAMP_NS = 1 << 0; + + /** + * Bit mask indicating a valid timeUncertaintyNs is stored in the ElapsedRealtime parcelable. + */ + const int HAS_TIME_UNCERTAINTY_NS = 1 << 1; + + /** + * A bit field of flags indicating the validity of each field in this data structure. + * + * The bit masks are the constants with prefix HAS_. + * + * Fields may have invalid information in them, if not marked as valid by the corresponding bit + * in flags. + */ + int flags; + + /** + * Estimate of the elapsed time since boot value for the corresponding event in nanoseconds. + */ + long timestampNs; + + /** + * Estimate of the relative precision of the alignment of this SystemClock timestamp, with the + * reported measurements in nanoseconds (68% confidence). + */ + double timeUncertaintyNs; +} \ No newline at end of file diff --git a/gnss/aidl/android/hardware/gnss/GnssClock.aidl b/gnss/aidl/android/hardware/gnss/GnssClock.aidl new file mode 100644 index 0000000000000000000000000000000000000000..f416e08e5f54b57e95573bbfa93186869ce3f6b0 --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/GnssClock.aidl @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.gnss; + +import android.hardware.gnss.GnssSignalType; + +/** + * Represents an estimate of the GNSS clock time. + */ +@VintfStability +parcelable GnssClock { + /** Bit mask indicating a valid 'leap second' is stored in the GnssClock. */ + const int HAS_LEAP_SECOND = 1 << 0; + /** Bit mask indicating a valid 'time uncertainty' is stored in the GnssClock. */ + const int HAS_TIME_UNCERTAINTY = 1 << 1; + /** Bit mask indicating a valid 'full bias' is stored in the GnssClock. */ + const int HAS_FULL_BIAS = 1 << 2; + /** Bit mask indicating a valid 'bias' is stored in the GnssClock. */ + const int HAS_BIAS = 1 << 3; + /** Bit mask indicating a valid 'bias uncertainty' is stored in the GnssClock. */ + const int HAS_BIAS_UNCERTAINTY = 1 << 4; + /** Bit mask indicating a valid 'drift' is stored in the GnssClock. */ + const int HAS_DRIFT = 1 << 5; + /** Bit mask indicating a valid 'drift uncertainty' is stored in the GnssClock. */ + const int HAS_DRIFT_UNCERTAINTY = 1 << 6; + + /** + * A bitfield of flags indicating the validity of the fields in this data + * structure. + * + * The bit masks are the constants with perfix HAS_. + * + * Fields for which there is no corresponding flag must be filled in + * with a valid value. For convenience, these are marked as mandatory. + * + * Others fields may have invalid information in them, if not marked as + * valid by the corresponding bit in gnssClockFlags. + */ + int gnssClockFlags; + + /** + * Leap second data. + * The sign of the value is defined by the following equation: + * utcTimeNs = timeNs - (fullBiasNs + biasNs) - leapSecond * + * 1,000,000,000 + * + * If this data is available, gnssClockFlags must contain + * HAS_LEAP_SECOND. + */ + int leapSecond; + + /** + * The GNSS receiver internal clock value. This is the local hardware clock + * value. + * + * For local hardware clock, this value is expected to be monotonically + * increasing while the hardware clock remains powered on. (For the case of a + * HW clock that is not continuously on, see the + * hwClockDiscontinuityCount field). The receiver's estimate of GNSS time + * can be derived by subtracting the sum of fullBiasNs and biasNs (when + * available) from this value. + * + * This GNSS time must be the best estimate of current GNSS time + * that GNSS receiver can achieve. + * + * Sub-nanosecond accuracy can be provided by means of the 'biasNs' field. + * The value contains the timeUncertaintyNs in it. + * + * This value is mandatory. + */ + long timeNs; + + /** + * 1-Sigma uncertainty associated with the clock's time in nanoseconds. + * The uncertainty is represented as an absolute (single sided) value. + * + * If the data is available, gnssClockFlags must contain + * HAS_TIME_UNCERTAINTY. Ths value is ideally zero, as the time + * 'latched' by timeNs is defined as the reference clock vs. which all + * other times (and corresponding uncertainties) are measured. + */ + double timeUncertaintyNs; + + /** + * The difference between hardware clock ('time' field) inside GNSS receiver + * and the true GPS time since 0000Z, January 6, 1980, in nanoseconds. + * + * The sign of the value is defined by the following equation: + * local estimate of GPS time = timeNs - (fullBiasNs + biasNs) + * + * If receiver has computed time for a non-GPS constellation, the time offset of + * that constellation versus GPS time must be applied to fill this value. + * + * The error estimate for the sum of this and the biasNs is the biasUncertaintyNs. + * + * If the data is available gnssClockFlags must contain HAS_FULL_BIAS. + * + * This value is mandatory if the receiver has estimated GPS time. + */ + long fullBiasNs; + + /** + * Sub-nanosecond bias - used with fullBiasNS, see fullBiasNs for details. + * + * The error estimate for the sum of this and the fullBiasNs is the + * biasUncertaintyNs. + * + * If the data is available gnssClockFlags must contain HAS_BIAS. + * + * This value is mandatory if the receiver has estimated GPS time. + */ + double biasNs; + + /** + * 1-Sigma uncertainty associated with the local estimate of GNSS time (clock + * bias) in nanoseconds. The uncertainty is represented as an absolute + * (single sided) value. + * + * The caller is responsible for using this uncertainty (it can be very + * large before the GPS time has been fully resolved.) + * + * If the data is available gnssClockFlags must contain HAS_BIAS_UNCERTAINTY. + * + * This value is mandatory if the receiver has estimated GPS time. + */ + double biasUncertaintyNs; + + /** + * The clock's drift in nanoseconds (per second). + * + * A positive value means that the frequency is higher than the nominal + * frequency, and that the (fullBiasNs + biasNs) is growing more positive + * over time. + * + * If the data is available gnssClockFlags must contain HAS_DRIFT. + * + * This value is mandatory if the receiver has estimated GPS time. + */ + double driftNsps; + + /** + * 1-Sigma uncertainty associated with the clock's drift in nanoseconds (per + * second). + * The uncertainty is represented as an absolute (single sided) value. + * + * If the data is available gnssClockFlags must contain HAS_DRIFT_UNCERTAINTY. + * + * This value is mandatory if the receiver has estimated GPS time. + */ + double driftUncertaintyNsps; + + /** + * This field must be incremented, when there are discontinuities in the + * hardware clock. + * + * A "discontinuity" is meant to cover the case of a switch from one source + * of clock to another. A single free-running crystal oscillator (XO) + * will generally not have any discontinuities, and this can be set and + * left at 0. + * + * If, however, the timeNs value (HW clock) is derived from a composite of + * sources, that is not as smooth as a typical XO, or is otherwise stopped & + * restarted, then this value shall be incremented each time a discontinuity + * occurs. (E.g. this value can start at zero at device boot-up and + * increment each time there is a change in clock continuity. In the + * unlikely event that this value reaches full scale, rollover (not + * clamping) is required, such that this value continues to change, during + * subsequent discontinuity events.) + * + * While this number stays the same, between GnssClock reports, it can be + * safely assumed that the timeNs value has been running continuously, e.g. + * derived from a single, high quality clock (XO like, or better, that is + * typically used during continuous GNSS signal sampling.) + * + * It is expected, esp. during periods where there are few GNSS signals + * available, that the HW clock be discontinuity-free as long as possible, + * as this avoids the need to use (waste) a GNSS measurement to fully + * re-solve for the GNSS clock bias and drift, when using the accompanying + * measurements, from consecutive GnssData reports. + * + * This value is mandatory. + */ + int hwClockDiscontinuityCount; + + /** + * Reference GNSS signal type for inter-signal bias. + */ + GnssSignalType referenceSignalTypeForIsb; +} \ No newline at end of file diff --git a/gnss/aidl/android/hardware/gnss/GnssConstellationType.aidl b/gnss/aidl/android/hardware/gnss/GnssConstellationType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..af3e089c5efed8acc41c7164d8bddd69acdb5bcf --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/GnssConstellationType.aidl @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.gnss; + +/** + * GNSS constellation type + * + * This is to specify the navigation satellite system, for example, as listed in Section 3.5 in + * RINEX Version 3.04. + */ +@VintfStability +@Backing(type="int") +enum GnssConstellationType { + UNKNOWN = 0, + /** Global Positioning System. */ + GPS = 1, + /** Satellite-Based Augmentation System. */ + SBAS = 2, + /** Global Navigation Satellite System. */ + GLONASS = 3, + /** Quasi-Zenith Satellite System. */ + QZSS = 4, + /** BeiDou Navigation Satellite System. */ + BEIDOU = 5, + /** Galileo Navigation Satellite System. */ + GALILEO = 6, + /** Indian Regional Navigation Satellite System. */ + IRNSS = 7, +} \ No newline at end of file diff --git a/gnss/aidl/android/hardware/gnss/GnssData.aidl b/gnss/aidl/android/hardware/gnss/GnssData.aidl new file mode 100644 index 0000000000000000000000000000000000000000..ed30c989f806fc712d28d18d796fa535c746c41e --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/GnssData.aidl @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.gnss; + +import android.hardware.gnss.ElapsedRealtime; +import android.hardware.gnss.GnssClock; +import android.hardware.gnss.GnssMeasurement; + +/** + * Represents a reading of GNSS measurements. For devices launched in Android Q or newer, it is + * mandatory that these be provided, on request, when the GNSS receiver is searching/tracking + * signals. + * + * - Reporting of GNSS constellation measurements is mandatory. + * - Reporting of all tracked constellations are encouraged. + */ +@VintfStability +parcelable GnssData { + /** The array of measurements. */ + GnssMeasurement[] measurements; + + /** The GNSS clock time reading. */ + GnssClock clock; + + /** + * Timing information of the GNSS data synchronized with SystemClock.elapsedRealtimeNanos() + * clock. + */ + ElapsedRealtime elapsedRealtime; +} \ No newline at end of file diff --git a/gnss/aidl/android/hardware/gnss/GnssMeasurement.aidl b/gnss/aidl/android/hardware/gnss/GnssMeasurement.aidl new file mode 100644 index 0000000000000000000000000000000000000000..efecddd41e3e8ce828cbbf5f0d2c1befc3a83cd8 --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/GnssMeasurement.aidl @@ -0,0 +1,675 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.gnss; + +import android.hardware.gnss.CorrelationVector; +import android.hardware.gnss.GnssMultipathIndicator; +import android.hardware.gnss.GnssSignalType; +import android.hardware.gnss.SatellitePvt; + +/** + * Represents a GNSS Measurement, it contains raw and computed information. + * + * All signal measurement information (e.g. svTime, pseudorangeRate, multipathIndicator) reported in + * this struct must be based on GNSS signal measurements only. You must not synthesize measurements + * by calculating or reporting expected measurements based on known or estimated position, velocity, + * or time. + */ +@VintfStability +parcelable GnssMeasurement { + /** Bit mask indicating a valid 'snr' is stored in the GnssMeasurement. */ + const int HAS_SNR = 1 << 0; + /** Bit mask indicating a valid 'carrier frequency' is stored in the GnssMeasurement. */ + const int HAS_CARRIER_FREQUENCY = 1 << 9; + /** Bit mask indicating a valid 'carrier cycles' is stored in the GnssMeasurement. */ + const int HAS_CARRIER_CYCLES = 1 << 10; + /** Bit mask indicating a valid 'carrier phase' is stored in the GnssMeasurement. */ + const int HAS_CARRIER_PHASE = 1 << 11; + /** Bit mask indicating a valid 'carrier phase uncertainty' is stored in the GnssMeasurement. */ + const int HAS_CARRIER_PHASE_UNCERTAINTY = 1 << 12; + /** Bit mask indicating a valid automatic gain control is stored in the GnssMeasurement. */ + const int HAS_AUTOMATIC_GAIN_CONTROL = 1 << 13; + /** Bit mask indicating a valid full inter-signal bias is stored in the GnssMeasurement. */ + const int HAS_FULL_ISB = 1 << 16; + /** + * Bit mask indicating a valid full inter-signal bias uncertainty is stored in the + * GnssMeasurement. + */ + const int HAS_FULL_ISB_UNCERTAINTY = 1 << 17; + /** + * Bit mask indicating a valid satellite inter-signal bias is stored in the GnssMeasurement. + */ + const int HAS_SATELLITE_ISB = 1 << 18; + /** + * Bit mask indicating a valid satellite inter-signal bias uncertainty is stored in the + * GnssMeasurement. + */ + const int HAS_SATELLITE_ISB_UNCERTAINTY = 1 << 19; + /** + * Bit mask indicating a valid satellite PVT is stored in the GnssMeasurement. + */ + const int HAS_SATELLITE_PVT = 1 << 20; + /** + * Bit mask indicating valid correlation vectors are stored in the GnssMeasurement. + */ + const int HAS_CORRELATION_VECTOR = 1 << 21; + + /** + * A bitfield of flags indicating the validity of the fields in this GnssMeasurement. The bit + * masks are defined in the constants with prefix HAS_* + * + * Fields for which there is no corresponding flag must be filled in with a valid value. For + * convenience, these are marked as mandatory. + * + * Others fields may have invalid information in them, if not marked as valid by the + * corresponding bit in flags. + */ + int flags; + + /** + * Satellite vehicle ID number, as defined in GnssSvInfo::svid + * + * This value is mandatory. + */ + int svid; + + /** + * Defines the constellation of the given SV. + * + * This value is mandatory. + */ + GnssSignalType signalType; + + /** + * Time offset at which the measurement was taken in nanoseconds. + * The reference receiver's time is specified by GnssData::clock::timeNs. + * + * The sign of timeOffsetNs is given by the following equation: + * measurement time = GnssClock::timeNs + timeOffsetNs + * + * It provides an individual time-stamp for the measurement, and allows + * sub-nanosecond accuracy. It may be zero if all measurements are + * aligned to a common time. + * + * This value is mandatory. + */ + double timeOffsetNs; + + /** + * Flags indicating the GNSS measurement state. + * + * The expected behavior here is for GNSS HAL to set all the flags that apply. For example, if + * the state for a satellite is only C/A code locked and bit synchronized, and there is still + * millisecond ambiguity, the state must be set as: + * + * STATE_CODE_LOCK | STATE_BIT_SYNC | STATE_MSEC_AMBIGUOUS + * + * If GNSS is still searching for a satellite, the corresponding state must be set to + * STATE_UNKNOWN(0). + * + * The received satellite time is relative to the beginning of the system week for all + * constellations except for Glonass where it is relative to the beginning of the Glonass system + * day. + * + * The table below indicates the valid range of the received GNSS satellite time. These ranges + * depend on the constellation and code being tracked and the state of the tracking algorithms + * given by the getState method. If the state flag is set, then the valid measurement range is + * zero to the value in the table. The state flag with the widest range indicates the range of + * the received GNSS satellite time value. + * + * +---------------------------+--------------------+-----+-----------+--------------------+------+ + * | |GPS/QZSS |GLNS |BDS |GAL |SBAS | + * +---------------------------+------+------+------+-----+------+----+------+------+------+------+ + * |State Flag |L1 |L5I |L5Q |L1OF |B1I |B1I |E1B |E1C |E5AQ |L1 | + * | |C/A | | | |(D1) |(D2)| | | |C/A | + * |---------------------------+------+------+------+-----+------+----+------+------+------+------+ + * |STATE_UNKNOWN |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | + * |---------------------------+------+------+------+-----+------+----+------+------+------+------+ + * |STATE_CODE_LOCK |1ms |1 ms |1 ms |1 ms |1 ms |1 ms|- |- |1 ms |1 ms | + * |---------------------------+------+------+------+-----+------+----+------+------+------+------+ + * |STATE_SYMBOL_SYNC |20ms |10 ms |1 ms |10 ms|20 ms |2 ms|4 ms |4 ms |1 ms |2 ms | + * | |(opt.)| |(opt.)| |(opt.)| |(opt.)|(opt.)|(opt.)| | + * |---------------------------+------+------+------+-----+------+----+------+------+------+------+ + * |STATE_BIT_SYNC |20 ms |20 ms |1 ms |20 ms|20 ms |- |8 ms |- |1 ms |4 ms | + * | | | |(opt.)| | | | | |(opt.)| | + * |---------------------------+------+------+------+-----+------+----+------+------+------+------+ + * |STATE_SUBFRAME_SYNC |6s |6s |- |2 s |6 s |- |- |- |100 ms|- | + * |---------------------------+------+------+------+-----+------+----+------+------+------+------+ + * |STATE_TOW_DECODED |1 week|- |- |1 day|1 week|- |1 week|- |- |1 week| + * |---------------------------+------+------+------+-----+------+----+------+------+------+------+ + * |STATE_TOW_KNOWN |1 week|- |- |1 day|1 week|- |1 week|- |- |1 week| + * |---------------------------+------+------+------+-----+------+----+------+------+------+------+ + * |STATE_GLO_STRING_SYNC |- |- |- |2 s |- |- |- |- |- |- | + * |---------------------------+------+------+------+-----+------+----+------+------+------+------+ + * |STATE_GLO_TOD_DECODED |- |- |- |1 day|- |- |- |- |- |- | + * |---------------------------+------+------+------+-----+------+----+------+------+------+------+ + * |STATE_GLO_TOD_KNOWN |- |- |- |1 day|- |- |- |- |- |- | + * |---------------------------+------+------+------+-----+------+----+------+------+------+------+ + * |STATE_BDS_D2_BIT_SYNC |- |- |- |- |- |2 ms|- |- |- |- | + * |---------------------------+------+------+------+-----+------+----+------+------+------+------+ + * |STATE_BDS_D2_SUBFRAME_SYNC |- |- |- |- |- |600 |- |- |- |- | + * | | | | | | |ms | | | | | + * |---------------------------+------+------+------+-----+------+----+------+------+------+------+ + * |STATE_GAL_E1BC_CODE_LOCK |- |- |- |- |- |- |4 ms |4 ms |- |- | + * |---------------------------+------+------+------+-----+------+----+------+------+------+------+ + * |STATE_GAL_E1C_2ND_CODE_LOCK|- |- |- |- |- |- |- |100 ms|- |- | + * |---------------------------+------+------+------+-----+------+----+------+------+------+------+ + * |STATE_2ND_CODE_LOCK |- |10 ms |20 ms |- |- |- |- |100 ms|100 ms|- | + * | | |(opt.)| | | | | |(opt.)| | | + * |---------------------------+------+------+------+-----+------+----+------+------+------+------+ + * |STATE_GAL_E1B_PAGE_SYNC |- |- |- |- |- |- |2 s |- |- |- | + * |---------------------------+------+------+------+-----+------+----+------+------+------+------+ + * |STATE_SBAS_SYNC |- |- |- |- |- |- |- |- |- |1s | + * +---------------------------+------+------+------+-----+------+----+------+------+------+------+ + * + * Note: TOW Known refers to the case where TOW is possibly not decoded over the air but has + * been determined from other sources. If TOW decoded is set then TOW Known must also be set. + * + * Note well: if there is any ambiguity in integer millisecond, STATE_MSEC_AMBIGUOUS must be + * set accordingly, in the 'state' field. This value must be populated if 'state' != + * STATE_UNKNOWN. + * + * Note on optional flags: + * - For L1 C/A and B1I, STATE_SYMBOL_SYNC is optional since the symbol length is the + * same as the bit length. + * - For L5Q and E5aQ, STATE_BIT_SYNC and STATE_SYMBOL_SYNC are optional since they are + * implied by STATE_CODE_LOCK. + * - STATE_2ND_CODE_LOCK for L5I is optional since it is implied by STATE_SYMBOL_SYNC. + * - STATE_2ND_CODE_LOCK for E1C is optional since it is implied by + * STATE_GAL_E1C_2ND_CODE_LOCK. + * - For E1B and E1C, STATE_SYMBOL_SYNC is optional, because it is implied by + * STATE_GAL_E1BC_CODE_LOCK. + */ + const int STATE_UNKNOWN = 0; + const int STATE_CODE_LOCK = 1 << 0; + const int STATE_BIT_SYNC = 1 << 1; + const int STATE_SUBFRAME_SYNC = 1 << 2; + const int STATE_TOW_DECODED = 1 << 3; + const int STATE_MSEC_AMBIGUOUS = 1 << 4; + const int STATE_SYMBOL_SYNC = 1 << 5; + const int STATE_GLO_STRING_SYNC = 1 << 6; + const int STATE_GLO_TOD_DECODED = 1 << 7; + const int STATE_BDS_D2_BIT_SYNC = 1 << 8; + const int STATE_BDS_D2_SUBFRAME_SYNC = 1 << 9; + const int STATE_GAL_E1BC_CODE_LOCK = 1 << 10; + const int STATE_GAL_E1C_2ND_CODE_LOCK = 1 << 11; + const int STATE_GAL_E1B_PAGE_SYNC = 1 << 12; + const int STATE_SBAS_SYNC = 1 << 13; + const int STATE_TOW_KNOWN = 1 << 14; + const int STATE_GLO_TOD_KNOWN = 1 << 15; + const int STATE_2ND_CODE_LOCK = 1 << 16; + + /** + * A bitfield of flags indicating the GnssMeasurementState per satellite sync state. It + * represents the current sync state for the associated satellite. + * + * Based on the sync state, the 'received GNSS tow' field must be interpreted accordingly. + * + * The bit masks are defined in the constants with prefix STATE_. + * + * This value is mandatory. + */ + int state; + + /** + * The received GNSS Time-of-Week at the measurement time, in nanoseconds. + * For GNSS & QZSS, this is the received GNSS Time-of-Week at the + * measurement time, in nanoseconds. The value is relative to the + * beginning of the current GNSS week. + * + * Given the highest sync state that can be achieved, per each satellite, + * valid range for this field can be: + * Searching : [ 0 ] : STATE_UNKNOWN + * C/A code lock : [ 0 1ms ] : STATE_CODE_LOCK set + * Bit sync : [ 0 20ms ] : STATE_BIT_SYNC set + * Subframe sync : [ 0 6s ] : STATE_SUBFRAME_SYNC set + * TOW decoded : [ 0 1week ] : STATE_TOW_DECODED set + * TOW Known : [ 0 1week ] : STATE_TOW_KNOWN set + * + * Note: TOW Known refers to the case where TOW is possibly not decoded + * over the air but has been determined from other sources. If TOW + * decoded is set then TOW Known must also be set. + * + * Note: If there is any ambiguity in integer millisecond, + * STATE_MSEC_AMBIGUOUS must be set accordingly, in the + * 'state' field. + * + * This value must be populated if 'state' != STATE_UNKNOWN. + * + * For Glonass, this is the received Glonass time of day, at the + * measurement time in nanoseconds. + * + * Given the highest sync state that can be achieved, per each satellite, + * valid range for this field can be: + * Searching : [ 0 ] : STATE_UNKNOWN set + * C/A code lock : [ 0 1ms ] : STATE_CODE_LOCK set + * Symbol sync : [ 0 10ms ] : STATE_SYMBOL_SYNC set + * Bit sync : [ 0 20ms ] : STATE_BIT_SYNC set + * String sync : [ 0 2s ] : STATE_GLO_STRING_SYNC set + * Time of day decoded : [ 0 1day ] : STATE_GLO_TOD_DECODED set + * Time of day known : [ 0 1day ] : STATE_GLO_TOD_KNOWN set + * + * Note: Time of day known refers to the case where it is possibly not + * decoded over the air but has been determined from other sources. If + * Time of day decoded is set then Time of day known must also be set. + * + * For Beidou, this is the received Beidou time of week, + * at the measurement time in nanoseconds. + * + * Given the highest sync state that can be achieved, per each satellite, + * valid range for this field can be: + * Searching : [ 0 ] : STATE_UNKNOWN set. + * C/A code lock : [ 0 1ms ] : STATE_CODE_LOCK set. + * Bit sync (D2) : [ 0 2ms ] : STATE_BDS_D2_BIT_SYNC set. + * Bit sync (D1) : [ 0 20ms ] : STATE_BIT_SYNC set. + * Subframe (D2) : [ 0 0.6s ] : STATE_BDS_D2_SUBFRAME_SYNC set. + * Subframe (D1) : [ 0 6s ] : STATE_SUBFRAME_SYNC set. + * Time of week decoded : [ 0 1week ] : STATE_TOW_DECODED set. + * Time of week known : [ 0 1week ] : STATE_TOW_KNOWN set + * + * Note: TOW Known refers to the case where TOW is possibly not decoded + * over the air but has been determined from other sources. If TOW + * decoded is set then TOW Known must also be set. + * + * For Galileo, this is the received Galileo time of week, + * at the measurement time in nanoseconds. + * + * E1BC code lock : [ 0 4ms ] : STATE_GAL_E1BC_CODE_LOCK set. + * E1C 2nd code lock : [ 0 100ms] : STATE_GAL_E1C_2ND_CODE_LOCK set. + * E1B page : [ 0 2s ] : STATE_GAL_E1B_PAGE_SYNC set. + * Time of week decoded : [ 0 1week] : STATE_TOW_DECODED is set. + * Time of week known : [ 0 1week] : STATE_TOW_KNOWN set + * + * Note: TOW Known refers to the case where TOW is possibly not decoded + * over the air but has been determined from other sources. If TOW + * decoded is set then TOW Known must also be set. + * + * For SBAS, this is received SBAS time, at the measurement time in + * nanoseconds. + * + * Given the highest sync state that can be achieved, per each satellite, + * valid range for this field can be: + * Searching : [ 0 ] : STATE_UNKNOWN + * C/A code lock: [ 0 1ms ] : STATE_CODE_LOCK is set + * Symbol sync : [ 0 2ms ] : STATE_SYMBOL_SYNC is set + * Message : [ 0 1s ] : STATE_SBAS_SYNC is set + */ + long receivedSvTimeInNs; + + /** + * 1-Sigma uncertainty of the Received GNSS Time-of-Week in nanoseconds. + * + * This value must be populated if 'state' != STATE_UNKNOWN. + */ + long receivedSvTimeUncertaintyInNs; + + /** + * Carrier-to-noise density in dB-Hz, typically in the range [0, 63]. + * It contains the measured C/N0 value for the signal at the antenna port. + * + * If a signal has separate components (e.g. Pilot and Data channels) and + * the receiver only processes one of the components, then the reported + * antennaCN0DbHz reflects only the component that is processed. + * + * This value is mandatory. + */ + double antennaCN0DbHz; + + /** + * Baseband Carrier-to-noise density in dB-Hz, typically in the range [0, 63]. It contains the + * measured C/N0 value for the signal measured at the baseband. + * + * This is typically a few dB weaker than the value estimated for C/N0 at the antenna port, + * which is reported in cN0DbHz. + * + * If a signal has separate components (e.g. Pilot and Data channels) and the receiver only + * processes one of the components, then the reported basebandCN0DbHz reflects only the + * component that is processed. + * + * This value is mandatory. + */ + double basebandCN0DbHz; + + /** + * Pseudorange rate at the timestamp in m/s. The correction of a given + * Pseudorange Rate value includes corrections for receiver and satellite + * clock frequency errors. Ensure that this field is independent (see + * comment at top of GnssMeasurement struct.) + * + * It is mandatory to provide the 'uncorrected' 'pseudorange rate', and + * provide GnssClock's 'drift' field as well. When providing the + * uncorrected pseudorange rate, do not apply the corrections described above.) + * + * The value includes the 'pseudorange rate uncertainty' in it. + * A positive 'uncorrected' value indicates that the SV is moving away from + * the receiver. + * + * The sign of the 'uncorrected' 'pseudorange rate' and its relation to the + * sign of 'doppler shift' is given by the equation: + * pseudorange rate = -k * doppler shift (where k is a constant) + * + * This must be the most accurate pseudorange rate available, based on + * fresh signal measurements from this channel. + * + * It is mandatory that this value be provided at typical carrier phase PRR + * quality (few cm/sec per second of uncertainty, or better) - when signals + * are sufficiently strong & stable, e.g. signals from a GNSS simulator at >= + * 35 dB-Hz. + */ + double pseudorangeRateMps; + + /** + * 1-Sigma uncertainty of the pseudorangeRateMps. + * The uncertainty is represented as an absolute (single sided) value. + * + * This value is mandatory. + */ + double pseudorangeRateUncertaintyMps; + + /** + * Flags indicating the Accumulated Delta Range's states. + * + * See the table below for a detailed interpretation of each state. + * + * +---------------------+-------------------+-----------------------------+ + * | ADR_STATE | Time of relevance | Interpretation | + * +---------------------+-------------------+-----------------------------+ + * | UNKNOWN | ADR(t) | No valid carrier phase | + * | | | information is available | + * | | | at time t. | + * +---------------------+-------------------+-----------------------------+ + * | VALID | ADR(t) | Valid carrier phase | + * | | | information is available | + * | | | at time t. This indicates | + * | | | that this measurement can | + * | | | be used as a reference for | + * | | | future measurements. | + * | | | However, to compare it to | + * | | | previous measurements to | + * | | | compute delta range, | + * | | | other bits should be | + * | | | checked. Specifically, it | + * | | | can be used for delta range | + * | | | computation if it is valid | + * | | | and has no reset or cycle | + * | | | slip at this epoch i.e. | + * | | | if VALID_BIT == 1 && | + * | | | CYCLE_SLIP_BIT == 0 && | + * | | | RESET_BIT == 0. | + * +---------------------+-------------------+-----------------------------+ + * | RESET | ADR(t) - ADR(t-1) | Carrier phase accumulation | + * | | | has been restarted between | + * | | | current time t and previous | + * | | | time t-1. This indicates | + * | | | that this measurement can | + * | | | be used as a reference for | + * | | | future measurements, but it | + * | | | should not be compared to | + * | | | previous measurements to | + * | | | compute delta range. | + * +---------------------+-------------------+-----------------------------+ + * | CYCLE_SLIP | ADR(t) - ADR(t-1) | Cycle slip(s) have been | + * | | | detected between the | + * | | | current time t and previous | + * | | | time t-1. This indicates | + * | | | that this measurement can | + * | | | be used as a reference for | + * | | | future measurements. | + * | | | Clients can use a | + * | | | measurement with a cycle | + * | | | slip to compute delta range | + * | | | against previous | + * | | | measurements at their own | + * | | | risk. | + * +---------------------+-------------------+-----------------------------+ + * | HALF_CYCLE_RESOLVED | ADR(t) | Half cycle ambiguity is | + * | | | resolved at time t. | + * | | | | + * | | | For signals that have | + * | | | databits, the carrier phase | + * | | | tracking loops typically | + * | | | use a costas loop | + * | | | discriminator. This type of | + * | | | tracking loop introduces a | + * | | | half-cycle ambiguity that | + * | | | is resolved by searching | + * | | | through the received data | + * | | | for known patterns of | + * | | | databits (e.g. GPS uses the | + * | | | TLM word) which then | + * | | | determines the polarity of | + * | | | the incoming data and | + * | | | resolves the half-cycle | + * | | | ambiguity. | + * | | | | + * | | | Before the half-cycle | + * | | | ambiguity has been resolved | + * | | | it is possible that the | + * | | | ADR_STATE_VALID flag is | + * | | | set, but the ADR_STATE_ | + * | | | HALF_CYCLE_RESOLVED flag is | + * | | | not set. | + * +---------------------+-------------------+-----------------------------+ + */ + const int ADR_STATE_UNKNOWN = 0; + const int ADR_STATE_VALID = 1 << 0; + const int ADR_STATE_RESET = 1 << 1; + const int ADR_STATE_CYCLE_SLIP = 1 << 2; + const int ADR_STATE_HALF_CYCLE_RESOLVED = 1 << 3; + + /** + * A bitfield of flags indicating the accumulated delta range's state. It indicates whether ADR + * is reset or there is a cycle slip(indicating loss of lock). + * + * The bit masks are defined in constants with prefix ADR_STATE_. + * + * This value is mandatory. + */ + int accumulatedDeltaRangeState; + + /** + * Accumulated delta range since the last channel reset in meters. + * A positive value indicates that the SV is moving away from the receiver. + * + * The sign of the 'accumulated delta range' and its relation to the sign of + * 'carrier phase' is given by the equation: + * accumulated delta range = -k * carrier phase (where k is a constant) + * + * This value must be populated if 'accumulated delta range state' != + * ADR_STATE_UNKNOWN. + * However, it is expected that the data is only accurate when: + * 'accumulated delta range state' == ADR_STATE_VALID. + * + * The alignment of the phase measurement will not be adjusted by the receiver so the in-phase + * and quadrature phase components will have a quarter cycle offset as they do when transmitted + * from the satellites. If the measurement is from a combination of the in-phase and quadrature + * phase components, then the alignment of the phase measurement will be aligned to the in-phase + * component. + */ + double accumulatedDeltaRangeM; + + /** + * 1-Sigma uncertainty of the accumulated delta range in meters. + * This value must be populated if 'accumulated delta range state' != + * ADR_STATE_UNKNOWN. + */ + double accumulatedDeltaRangeUncertaintyM; + + /** + * The number of full carrier cycles between the satellite and the + * receiver. The reference frequency is given by the field + * 'carrierFrequencyHz'. Indications of possible cycle slips and + * resets in the accumulation of this value can be inferred from the + * accumulatedDeltaRangeState flags. + * + * If the data is available, gnssMeasurementFlags must contain + * HAS_CARRIER_CYCLES. + */ + long carrierCycles; + + /** + * The RF phase detected by the receiver, in the range [0.0, 1.0]. + * This is usually the fractional part of the complete carrier phase + * measurement. + * + * The reference frequency is given by the field 'carrierFrequencyHz'. + * The value contains the 'carrier-phase uncertainty' in it. + * + * If the data is available, gnssMeasurementFlags must contain + * HAS_CARRIER_PHASE. + */ + double carrierPhase; + + /** + * 1-Sigma uncertainty of the carrier-phase. + * If the data is available, gnssMeasurementFlags must contain + * HAS_CARRIER_PHASE_UNCERTAINTY. + */ + double carrierPhaseUncertainty; + + /** + * An enumeration that indicates the 'multipath' state of the event. + * + * The multipath Indicator is intended to report the presence of overlapping + * signals that manifest as distorted correlation peaks. + * + * - if there is a distorted correlation peak shape, report that multipath + * is MULTIPATH_INDICATOR_PRESENT. + * - if there is no distorted correlation peak shape, report + * MULTIPATH_INDICATOR_NOT_PRESENT + * - if signals are too weak to discern this information, report + * MULTIPATH_INDICATOR_UNKNOWN + * + * Example: when doing the standardized overlapping Multipath Performance + * test (3GPP TS 34.171) the Multipath indicator must report + * MULTIPATH_INDICATOR_PRESENT for those signals that are tracked, and + * contain multipath, and MULTIPATH_INDICATOR_NOT_PRESENT for those + * signals that are tracked and do not contain multipath. + */ + GnssMultipathIndicator multipathIndicator = GnssMultipathIndicator.UNKNOWN; + + /** + * Signal-to-noise ratio at correlator output in dB. + * If the data is available, GnssMeasurementFlags must contain HAS_SNR. + * This is the power ratio of the "correlation peak height above the + * observed noise floor" to "the noise RMS". + */ + double snrDb; + + /** + * Automatic gain control (AGC) level. AGC acts as a variable gain amplifier adjusting the power + * of the incoming signal. The AGC level may be used to indicate potential interference. Higher + * gain (and/or lower input power) must be output as a positive number. Hence in cases of strong + * jamming, in the band of this signal, this value must go more negative. This value must be + * consistent given the same level of the incoming signal power. + * + * Note: Different hardware designs (e.g. antenna, pre-amplification, or other RF HW components) + * may also affect the typical output of this value on any given hardware design in an open sky + * test - the important aspect of this output is that changes in this value are indicative of + * changes on input signal power in the frequency band for this measurement. + */ + double agcLevelDb; + + /** + * The full inter-signal bias (ISB) in nanoseconds. + * + * This value is the sum of the estimated receiver-side and the space-segment-side inter-system + * bias, inter-frequency bias and inter-code bias, including + * + * - Receiver inter-constellation bias (with respect to the constellation in + * GnssClock.referenceSignalTypeForIsb) + * - Receiver inter-frequency bias (with respect to the carrier frequency in + * GnssClock.referenceSignalTypeForIsb) + * - Receiver inter-code bias (with respect to the code type in + * GnssClock.referenceSignalTypeForIsb) + * - Master clock bias (e.g., GPS-GAL Time Offset (GGTO), GPS-UTC Time Offset (TauGps), BDS-GLO + * Time Offset (BGTO)) (with respect to the constellation in + * GnssClock.referenceSignalTypeForIsb) + * - Group delay (e.g., Total Group Delay (TGD)) + * - Satellite inter-frequency bias (GLO only) (with respect to the carrier frequency in + * GnssClock.referenceSignalTypeForIsb) + * - Satellite inter-code bias (e.g., Differential Code Bias (DCB)) (with respect to the code + * type in GnssClock.referenceSignalTypeForIsb) + * + * If a component of the above is already compensated in the provided + * GnssMeasurement.receivedSvTimeInNs, then it must not be included in the reported full ISB. + * + * The value does not include the inter-frequency Ionospheric bias. + * + * The full ISB of GnssClock.referenceSignalTypeForIsb is defined to be 0.0 nanoseconds. + */ + double fullInterSignalBiasNs; + + /** + * 1-sigma uncertainty associated with the full inter-signal bias in nanoseconds. + */ + double fullInterSignalBiasUncertaintyNs; + + /** + * The satellite inter-signal bias in nanoseconds. + * + * This value is the sum of the space-segment-side inter-system bias, inter-frequency bias + * and inter-code bias, including + * + * - Master clock bias (e.g., GPS-GAL Time Offset (GGTO), GPS-UTC Time Offset (TauGps), BDS-GLO + * Time Offset (BGTO)) (with respect to the constellation in + * GnssClock.referenceSignalTypeForIsb) + * - Group delay (e.g., Total Group Delay (TGD)) + * - Satellite inter-frequency bias (GLO only) (with respect to the carrier frequency in + * GnssClock.referenceSignalTypeForIsb) + * - Satellite inter-code bias (e.g., Differential Code Bias (DCB)) (with respect to the code + * type in GnssClock.referenceSignalTypeForIsb) + * + * The satellite ISB of GnssClock.referenceSignalTypeForIsb is defined to be 0.0 nanoseconds. + */ + double satelliteInterSignalBiasNs; + + /** + * 1-sigma uncertainty associated with the satellite inter-signal bias in nanoseconds. + */ + double satelliteInterSignalBiasUncertaintyNs; + + /** + * The GNSS satellite position, velocity and time information at the same signal transmission + * time receivedSvTimeInNs. + * + * The position and velocity must be in ECEF coordinates. + * + * If the data is available, gnssMeasurementFlags must contain HAS_SATELLITE_PVT. + * + * If SatellitePvt is derived from Broadcast ephemeris, then the position is already w.r.t. + * the antenna phase center. However, if SatellitePvt is derived from other modeled orbits, + * such as long-term-orbits, or precise orbits, then the orbits may have been computed w.r.t. + * the satellite center of mass, and then GNSS vendors are expected to correct for the effect + * on different phase centers (can differ by meters) of different GNSS signals (e.g. L1, L5) + * on the reported satellite position. Accordingly, we might observe a different satellite + * position reported for L1 GnssMeasurement struct compared to L5 GnssMeasurement struct. + * + * If receivedSvTimeNs is not fully decoded, Satellite PVT could still be reported and + * receivedSvTimeNs uncertainty field would be used to provide confidence. + */ + SatellitePvt satellitePvt; + + /** + * A list of Correlation Vectors with each vector corresponding to a frequency offset. + * + * To represent correlation values over a 2D spaces (delay and frequency), a CorrelationVector + * is required per frequency offset, and each CorrelationVector contains correlation values + * at equally spaced spatial offsets. + */ + CorrelationVector[] correlationVectors; +} diff --git a/gnss/aidl/android/hardware/gnss/GnssMultipathIndicator.aidl b/gnss/aidl/android/hardware/gnss/GnssMultipathIndicator.aidl new file mode 100644 index 0000000000000000000000000000000000000000..ec1ce6270501b2c6ea2e7e547f4b072757d530c4 --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/GnssMultipathIndicator.aidl @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.gnss; + +/** + * Enumeration of available values for the GNSS Measurement's multipath + * indicator. + */ +@VintfStability +@Backing(type="int") +enum GnssMultipathIndicator { + /** The indicator is not available or unknown. */ + UNKNOWN = 0, + /** The measurement is indicated to be affected by multipath. */ + PRESENT = 1, + /** The measurement is indicated to be not affected by multipath. */ + NOT_PRESENT = 2, +} \ No newline at end of file diff --git a/gnss/aidl/android/hardware/gnss/GnssPowerStats.aidl b/gnss/aidl/android/hardware/gnss/GnssPowerStats.aidl new file mode 100644 index 0000000000000000000000000000000000000000..2bea44dbb995e0cd019a4f1e9437d91170e0869f --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/GnssPowerStats.aidl @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.gnss; + +import android.hardware.gnss.ElapsedRealtime; + +/** + * Cumulative GNSS power statistics since boot. + */ +@VintfStability +parcelable GnssPowerStats { + /** + * Timing information of the GnssPowerStats synchronized with SystemClock.elapsedRealtimeNanos() + * clock. + */ + ElapsedRealtime elapsedRealtime; + + /** + * Total GNSS energy consumption in milli-joules (mWatt-seconds). + */ + double totalEnergyMilliJoule; + + /** + * Total energy consumption in milli-joules (mWatt-seconds) for which the GNSS engine is + * tracking signals of a single frequency band. + */ + double singlebandTrackingModeEnergyMilliJoule; + + /** + * Total energy consumption in milli-joules (mWatt-seconds) for which the GNSS engine is + * tracking signals of multiple frequency bands. + */ + double multibandTrackingModeEnergyMilliJoule; + + /** + * Total energy consumption in milli-joules (mWatt-seconds) for which the GNSS engine is + * acquiring signals of a single frequency band. + */ + double singlebandAcquisitionModeEnergyMilliJoule; + + /** + * Total energy consumption in milli-joules (mWatt-seconds) for which the GNSS engine is + * acquiring signals of multiple frequency bands. + */ + double multibandAcquisitionModeEnergyMilliJoule; + + /** + * Total energy consumption in milli-joules (mWatt-seconds) for which the GNSS engine is + * operating in each of the vendor-specific power modes. + */ + double[] otherModesEnergyMilliJoule; +} \ No newline at end of file diff --git a/gnss/aidl/android/hardware/gnss/GnssSignalType.aidl b/gnss/aidl/android/hardware/gnss/GnssSignalType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..a16b170da4e9c7e80ae00735a39e71d9bb6f4826 --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/GnssSignalType.aidl @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.gnss; + +import android.hardware.gnss.GnssConstellationType; + +/** + * Represents a GNSS signal type. + */ +@VintfStability +parcelable GnssSignalType { + /** + * Constellation type of the SV that transmits the signal. + */ + GnssConstellationType constellation = GnssConstellationType.UNKNOWN; + + /** + * Carrier frequency of the signal tracked, for example it can be the + * GPS central frequency for L1 = 1575.45 MHz, or L2 = 1227.60 MHz, L5 = + * 1176.45 MHz, varying GLO channels, etc. If the field is not set, it + * is the primary common use central frequency, e.g. L1 = 1575.45 MHz + * for GPS. + * + * For an L1, L5 receiver tracking a satellite on L1 and L5 at the same + * time, two raw measurement structs must be reported for this same + * satellite, in one of the measurement structs, all the values related + * to L1 must be filled, and in the other all of the values related to + * L5 must be filled. + */ + double carrierFrequencyHz; + + /** + * GNSS signal code type "A" representing GALILEO E1A, GALILEO E6A, IRNSS L5A, IRNSS SA. + */ + const @utf8InCpp String CODE_TYPE_A = "A"; + + /** + * GNSS signal code type "B" representing GALILEO E1B, GALILEO E6B, IRNSS L5B, IRNSS SB. + */ + const @utf8InCpp String CODE_TYPE_B = "B"; + + /** + * GNSS signal code type "C" representing GPS L1 C/A, GPS L2 C/A, GLONASS G1 C/A, + * GLONASS G2 C/A, GALILEO E1C, GALILEO E6C, SBAS L1 C/A, QZSS L1 C/A, IRNSS L5C. + */ + const @utf8InCpp String CODE_TYPE_C = "C"; + + /** + * GNSS signal code type "D" representing BDS B1C D. + */ + const @utf8InCpp String CODE_TYPE_D = "D"; + + /** + * GNSS signal code type "I" representing GPS L5 I, GLONASS G3 I, GALILEO E5a I, GALILEO E5b I, + * GALILEO E5a+b I, SBAS L5 I, QZSS L5 I, BDS B1 I, BDS B2 I, BDS B3 I. + */ + const @utf8InCpp String CODE_TYPE_I = "I"; + + /** + * GNSS signal code type "L" representing GPS L1C (P), GPS L2C (L), QZSS L1C (P), QZSS L2C (L), + * LEX(6) L. + */ + const @utf8InCpp String CODE_TYPE_L = "L"; + + /** + * GNSS signal code type "M" representing GPS L1M, GPS L2M. + */ + const @utf8InCpp String CODE_TYPE_M = "M"; + + /** + * GNSS signal code type "N" representing GPS L1 codeless, GPS L2 codeless. + */ + const @utf8InCpp String CODE_TYPE_N = "N"; + + /** + * GNSS signal code type "P" representing GPS L1P, GPS L2P, GLONASS G1P, GLONASS G2P, BDS B1C P. + */ + const @utf8InCpp String CODE_TYPE_P = "P"; + + /** + * GNSS signal code type "Q" representing GPS L5 Q, GLONASS G3 Q, GALILEO E5a Q, GALILEO E5b Q, + * GALILEO E5a+b Q, SBAS L5 Q, QZSS L5 Q, BDS B1 Q, BDS B2 Q, BDS B3 Q. + */ + const @utf8InCpp String CODE_TYPE_Q = "Q"; + + /** + * GNSS signal code type "S" represents GPS L1C (D), GPS L2C (M), QZSS L1C (D), QZSS L2C (M), + * LEX(6) S. + */ + const @utf8InCpp String CODE_TYPE_S = "S"; + + /** + * GNSS signal code type "W" representing GPS L1 Z-tracking, GPS L2 Z-tracking. + */ + const @utf8InCpp String CODE_TYPE_W = "W"; + + /** + * GNSS signal code type "X" representing GPS L1C (D+P), GPS L2C (M+L), GPS L5 (I+Q), + * GLONASS G3 (I+Q), GALILEO E1 (B+C), GALILEO E5a (I+Q), GALILEO E5b (I+Q), GALILEO E5a+b(I+Q), + * GALILEO E6 (B+C), SBAS L5 (I+Q), QZSS L1C (D+P), QZSS L2C (M+L), QZSS L5 (I+Q), + * LEX(6) (S+L), BDS B1 (I+Q), BDS B1C (D+P), BDS B2 (I+Q), BDS B3 (I+Q), IRNSS L5 (B+C). + */ + const @utf8InCpp String CODE_TYPE_X = "X"; + + /** + * GNSS signal code type "Y" representing GPS L1Y, GPS L2Y. + */ + const @utf8InCpp String CODE_TYPE_Y = "Y"; + + /** + * GNSS signal code type "Z" representing GALILEO E1 (A+B+C), GALILEO E6 (A+B+C), QZSS L1-SAIF. + */ + const @utf8InCpp String CODE_TYPE_Z = "Z"; + + /** + * GNSS signal code type "UNKNOWN" representing the GNSS Measurement's code type is unknown. + */ + const @utf8InCpp String CODE_TYPE_UNKNOWN = "UNKNOWN"; + + /** + * The type of code that is currently being tracked in the GNSS signal. + * + * For high precision applications the type of code being tracked needs to be considered + * in-order to properly apply code specific corrections to the pseudorange measurements. + * + * The value is one of the constant Strings with prefix CODE_TYPE_ defined in this parcelable. + * + * This is used to specify the observation descriptor defined in GNSS Observation Data File + * Header Section Description in the RINEX standard (Version 3.XX). In RINEX Version 3.03, + * in Appendix Table A2 Attributes are listed as uppercase letters (for instance, "A" for + * "A channel"). In the future, if for instance a code "G" was added in the official RINEX + * standard, "G" could be specified here. + */ + @utf8InCpp String codeType; +} diff --git a/gnss/aidl/android/hardware/gnss/IGnss.aidl b/gnss/aidl/android/hardware/gnss/IGnss.aidl new file mode 100644 index 0000000000000000000000000000000000000000..f99b512c5f54be79b810f6b69de81859749c921c --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/IGnss.aidl @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.gnss; + +import android.hardware.gnss.IGnssCallback; +import android.hardware.gnss.IGnssConfiguration; +import android.hardware.gnss.IGnssMeasurementInterface; +import android.hardware.gnss.IGnssPowerIndication; +import android.hardware.gnss.IGnssPsds; + +/** + * Represents the standard GNSS (Global Navigation Satellite System) interface. + */ +@VintfStability +interface IGnss { + + /** + * All GNSS Binder calls may return a ServiceSpecificException with the following error + * codes. + */ + const int ERROR_INVALID_ARGUMENT = 1; + + /** A callback has already been registered. */ + const int ERROR_ALREADY_INIT = 2; + + /** Any other error. */ + const int ERROR_GENERIC = 3; + + /** + * Opens the interface and provides the callback routines to the implementation of this + * interface. + * + * The framework calls this method to instruct the GPS engine to prepare for serving requests + * from the framework. The GNSS HAL implementation must respond to all GNSS requests from the + * framework upon successful return from this method until cleanup() method is called to + * close this interface. + * + * @param callback Callback interface for IGnss. + */ + void setCallback(in IGnssCallback callback); + + /** + * Closes the interface. + * + * The close() method is called by the framework to tell the GNSS HAL implementation to + * clear the callback and not expect any GNSS requests in the immediate future - e.g. this may + * be called when location is disabled by a user setting or low battery conditions. The GNSS HAL + * implementation must immediately stop responding to any existing requests until the + * setCallback() method is called again and the requests are re-initiated by the framework. + * + * After this method is called, the GNSS HAL implementation may choose to modify GNSS hardware + * states to save power. It is expected that when setCallback() method is called again to + * reopen this interface, to serve requests, there may be some minor delays in GNSS response + * requests as hardware readiness states are restored, not to exceed those that occur on normal + * device boot up. + */ + void close(); + + /** + * This method returns the IGnssPsds interface. + * + * This method must return non-null. + * + * @return Handle to the IGnssPsds interface. + */ + IGnssPsds getExtensionPsds(); + + /** + * This method returns the IGnssConfiguration interface. + * + * This method must return non-null. + * + * @return Handle to the IGnssConfiguration interface. + */ + IGnssConfiguration getExtensionGnssConfiguration(); + + /** + * This methods returns the IGnssMeasurementInterface interface. + * + * This method must return non-null. + * + * @return Handle to the IGnssMeasurementInterface interface. + */ + IGnssMeasurementInterface getExtensionGnssMeasurement(); + + /** + * This method returns the IGnssPowerIndication interface. + * + * This method must return non-null. + * + * @return Handle to the IGnssPowerIndication interface. + */ + IGnssPowerIndication getExtensionGnssPowerIndication(); +} diff --git a/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl b/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..aad09ef98b86755e2493d18f42160bd0d1fc8c10 --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.gnss; + +import android.hardware.gnss.IGnssConfiguration; +import android.hardware.gnss.IGnssPsds; + +/** + * This interface is required for the HAL to communicate certain information + * like status and location info back to the framework, the framework implements + * the interfaces and passes a handle to the HAL. + */ +@VintfStability +interface IGnssCallback { + /** Capability bit mask indicating that GNSS supports blocklisting satellites */ + const int CAPABILITY_SATELLITE_BLOCKLIST = 1 << 9; + + /** Capability bit mask indicating that GNSS supports correlation vector */ + const int CAPABILITY_CORRELATION_VECTOR = 1 << 12; + + /** Capability bit mask indicating that GNSS supports satellite PVT */ + const int CAPABILITY_SATELLITE_PVT = 1 << 13; + + /** Capability bit mask indicating that GNSS supports measurement corrections for driving */ + const int CAPABILITY_MEASUREMENT_CORRECTIONS_FOR_DRIVING = 1 << 14; + + /** + * Callback to inform framework of the GNSS HAL implementation's capabilities. + * + * @param capabilities Capability parameter is a bit field of the Capability bit masks. + */ + void gnssSetCapabilitiesCb(in int capabilities); +} diff --git a/gnss/aidl/android/hardware/gnss/IGnssConfiguration.aidl b/gnss/aidl/android/hardware/gnss/IGnssConfiguration.aidl new file mode 100644 index 0000000000000000000000000000000000000000..e0ad3575f02feb8ccc660fa7ec779daabb0525c0 --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/IGnssConfiguration.aidl @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.gnss; + +import android.hardware.gnss.BlocklistedSource; + +/** + * Extended interface for GNSS Configuration support. + */ +@VintfStability +interface IGnssConfiguration { + + /** SUPL mode bitmask for Mobile Station Based. */ + const int SUPL_MODE_MSB = 0x01; + + /** SUPL mode bitmask for Mobile Station Assisted. */ + const int SUPL_MODE_MSA = 0x02; + + /** LPP profile settings bitmask for enabling LTE Positioning Protocol User Plane. */ + const int LPP_PROFILE_USER_PLANE = 0x01; + + /** LPP profile settings bitmask for enabling LTE Positioning Protocol Control Plane. */ + const int LPP_PROFILE_CONTROL_PLANE = 0x02; + + /** A-Glonass positioning protocol bitmask for Radio Resource Control (RRC) Control Plane. */ + const int GLONASS_POS_PROTOCOL_RRC_CPLANE = 0x01; + + /** A-Glonass positioning protocol bitmask for Radio Resource Location User Plane. */ + const int GLONASS_POS_PROTOCOL_RRLP_UPLANE = 0x02; + + /** A-Glonass positioning protocol bitmask for LTE Positioning Protocol User Plane. */ + const int GLONASS_POS_PROTOCOL_LPP_UPLANE = 0x04; + + /** + * This method sets the SUPL version requested by Carrier. The GNSS HAL must use this version + * of the SUPL protocol if supported. + * + * @param version SUPL version requested by carrier. This is a bit mask with bits 0:7 + * representing a service indicator field, bits 8:15 representing the minor version and bits + * 16:23 representing the major version. + */ + void setSuplVersion(in int version); + + /** + * This method sets the SUPL mode. + * + * @param mode Bitmask that specifies the SUPL mode which is set with the SUPL_MODE_* constants. + */ + void setSuplMode(in int mode); + + /** + * This method sets the LTE Positioning Profile configuration. + * + * @param lppProfile Bitmask that specifies the LTE Positioning Profile configuration to be set + * as per the LPP_PROFILE_* constants. If none of the bits are set, the default setting is + * Radio Resource Location Protocol (RRLP). + */ + void setLppProfile(in int lppProfile); + + /** + * This method selects positioning protocol on A-Glonass system. + * + * @param protocol Bitmask that specifies the positioning protocol to be set as per + * GLONASS_POS_PROTOCOL_* constants. + */ + void setGlonassPositioningProtocol(in int protocol); + + /** + * This method configures which PDN to use. + * + * @param enable Use emergency PDN if true and regular PDN if false. + */ + void setEmergencySuplPdn(in boolean enable); + + /** + * This method sets the emergency session extension duration. The GNSS HAL + * implementation must serve emergency SUPL and Control Plane network initiated + * location requests for this extra duration after the user initiated emergency + * session ends. + * + * @param emergencyExtensionSeconds Number of seconds to extend the emergency + * session duration post emergency call. + */ + void setEsExtensionSec(in int emergencyExtensionSeconds); + + /** + * Injects a vector of BlocklistedSource(s) which the HAL must not use to calculate the + * GNSS location output. + * + * The superset of all satellite sources provided, including wildcards, in the latest call + * to this method, is the set of satellites sources that must not be used in calculating + * location. + * + * All measurements from the specified satellites, across frequency bands, are blocklisted + * together. + * + * If this method is never called after the IGnssConfiguration.hal connection is made on boot, + * or is called with an empty vector, then no satellites are to be blocklisted as a result of + * this API. + * + * This blocklist must be considered as an additional source of which satellites + * should not be trusted for location on top of existing sources of similar information + * such as satellite broadcast health being unhealthy and measurement outlier removal. + * + * @param blocklist The BlocklistedSource(s) of satellites the HAL must not use. + */ + void setBlocklist(in BlocklistedSource[] blocklist); +} \ No newline at end of file diff --git a/gnss/aidl/android/hardware/gnss/IGnssMeasurementCallback.aidl b/gnss/aidl/android/hardware/gnss/IGnssMeasurementCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..328cf2abadd02c76d269c295618dc7899206e20c --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/IGnssMeasurementCallback.aidl @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.gnss; + +import android.hardware.gnss.GnssData; + +/** + * The callback interface to report GNSS Measurement from the HAL. + */ +@VintfStability +interface IGnssMeasurementCallback { + /** + * Callback for the hal to pass a GnssData structure back to the client. + * + * @param data Contains a reading of GNSS measurements. + */ + void gnssMeasurementCb(in GnssData data); +} \ No newline at end of file diff --git a/gnss/aidl/android/hardware/gnss/IGnssMeasurementInterface.aidl b/gnss/aidl/android/hardware/gnss/IGnssMeasurementInterface.aidl new file mode 100644 index 0000000000000000000000000000000000000000..08c83a42e7983ae17285d7d8ef464b5bd3bcba8e --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/IGnssMeasurementInterface.aidl @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.gnss; + +import android.hardware.gnss.IGnssMeasurementCallback; + +/** + * Extended interface for GNSS Measurement support. + */ +@VintfStability +interface IGnssMeasurementInterface { + /** + * Initializes the interface and registers the callback routines with the HAL. After a + * successful call to 'setCallback' the HAL must begin to provide updates at an average + * output rate of 1Hz (occasional intra-measurement time offsets in the range from 0-2000msec + * can be tolerated.) + * + * @param callback Handle to GnssMeasurement callback interface. + * @param enableFullTracking If true, GNSS chipset must switch off duty cycling. In such mode + * no clock discontinuities are expected and, when supported, carrier phase should be + * continuous in good signal conditions. All non-blocklisted, healthy constellations, + * satellites and frequency bands that the chipset supports must be reported in this mode. + * The GNSS chipset is allowed to consume more power in this mode. If false, API must + * optimize power via duty cycling, constellations and frequency limits, etc. + * + * @param enableCorrVecOutputs If true, enable correlation vectors as part of the raw GNSS + * measurements outputs. If false, disable correlation vectors. + * + * Returns ok() if successful. Returns ERROR_ALREADY_INIT if a callback has already been + * registered without a corresponding call to 'close'. Returns ERROR_GENERIC for any other + * error. The HAL must not generate any other updates upon returning this error code. + */ + void setCallback(in IGnssMeasurementCallback callback, in boolean enableFullTracking, + in boolean enableCorrVecOutputs); + + /** + * Stops updates from the HAL, and unregisters the callback routines. After a call to close(), + * the previously registered callbacks must be considered invalid by the HAL. + * + * If close() is invoked without a previous setCallback, this function must perform + * no work. + */ + void close(); +} \ No newline at end of file diff --git a/gnss/aidl/android/hardware/gnss/IGnssPowerIndication.aidl b/gnss/aidl/android/hardware/gnss/IGnssPowerIndication.aidl new file mode 100644 index 0000000000000000000000000000000000000000..93fdadc886c81ae13d1155dad286d3cfe6061bab --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/IGnssPowerIndication.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.gnss; + +import android.hardware.gnss.IGnssPowerIndicationCallback; + +/** + * Extended interface for GNSS Power Indication support. + */ +@VintfStability +interface IGnssPowerIndication { + + /** + * Opens the IGnssPowerIndication interface and provides the callback routines to the HAL. + * + * @param callback Callback interface for IGnssPowerIndication. + */ + void setCallback(in IGnssPowerIndicationCallback callback); + + /** + * Requests the GNSS power statistics. One request call corresponds to one response callback + * from IGnssPowerIndicationCallback.gnssPowerStatsCb(). + */ + oneway void requestGnssPowerStats(); +} \ No newline at end of file diff --git a/gnss/aidl/android/hardware/gnss/IGnssPowerIndicationCallback.aidl b/gnss/aidl/android/hardware/gnss/IGnssPowerIndicationCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..4474c0c69c4e41a10753bbae89e894e0ec33ed9c --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/IGnssPowerIndicationCallback.aidl @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.gnss; + +import android.hardware.gnss.GnssPowerStats; + +/** + * The callback interface to report GNSS Power Indication from the HAL. + */ +@VintfStability +interface IGnssPowerIndicationCallback { + + /** Capability bit mask indicating GNSS supports totalEnergyMilliJoule. */ + const int CAPABILITY_TOTAL = 1 << 0; + + /** Capability bit mask indicating GNSS supports singlebandTrackingModeEnergyMilliJoule. */ + const int CAPABILITY_SINGLEBAND_TRACKING = 1 << 1; + + /** Capability bit mask indicating GNSS supports multibandTrackingModeEnergyMilliJoule. */ + const int CAPABILITY_MULTIBAND_TRACKING = 1 << 2; + + /** Capability bit mask indicating GNSS supports singlebandAcquisitionModeEnergyMilliJoule. */ + const int CAPABILITY_SINGLEBAND_ACQUISITION = 1 << 3; + + /** Capability bit mask indicating GNSS supports multibandAcquisitionModeEnergyMilliJoule. */ + const int CAPABILITY_MULTIBAND_ACQUISITION = 1 << 4; + + /** Capability bit mask indicating GNSS supports otherModesEnergyMilliJoule. */ + const int CAPABILITY_OTHER_MODES = 1 << 5; + + /** + * Callback to inform framework the Power Indication specific capabilities of the GNSS HAL + * implementation. + * + * The GNSS HAL must call this method immediately after the framework opens the + * IGnssPowerIndication interface. + * + * @param capabilities Bitmask of CAPABILITY_* specifying the supported GNSS Power Indication + * capabilities. + */ + void setCapabilitiesCb(in int capabilities); + + /** + * Callback for the HAL to pass a GnssPowerStats structure back to the client. + * + * @param gnssPowerStats GNSS power statistics since boot. + */ + oneway void gnssPowerStatsCb(in GnssPowerStats gnssPowerStats); +} \ No newline at end of file diff --git a/gnss/aidl/android/hardware/gnss/IGnssPsds.aidl b/gnss/aidl/android/hardware/gnss/IGnssPsds.aidl new file mode 100644 index 0000000000000000000000000000000000000000..7c4609653fc8eabe25a408bbd630c97c9c5e2f2f --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/IGnssPsds.aidl @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.gnss; + +import android.hardware.gnss.IGnssPsdsCallback; +import android.hardware.gnss.PsdsType; + +/** + * This interface is used by the GNSS HAL to request the framework to download Predicted Satellite + * Data Service data. + */ +@VintfStability +interface IGnssPsds { + + /** + * Inject the downloaded PSDS data into the GNSS receiver. + * + * @param psdsType Type of PSDS data. + * @param psdsData GNSS PSDS data. Framework must not parse the data since the data format is + * opaque to framework. + */ + void injectPsdsData(in PsdsType psdsType, in byte[] psdsData); + + /** + * Opens the PSDS interface and provides the callback routines to the implementation of this + * interface. + * + * @param callback Handle to the IGnssPsdsCallback interface. + */ + void setCallback(in IGnssPsdsCallback callback); +} \ No newline at end of file diff --git a/gnss/aidl/android/hardware/gnss/IGnssPsdsCallback.aidl b/gnss/aidl/android/hardware/gnss/IGnssPsdsCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..72b693b4a32838d15637c3a483bab310035e1491 --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/IGnssPsdsCallback.aidl @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.gnss; + +import android.hardware.gnss.PsdsType; + +/** + * This interface is used by the GNSS HAL to request download data from Predicted Satellite Data + * Service (PSDS). + */ +@VintfStability +interface IGnssPsdsCallback { + + /** + * Callback to request the client to download PSDS data from one of the URLs defined in the + * framework specified by psdsType. The URLs must be specified via properties on the vendor + * partitions. E.g., LONGTERM_PSDS_SERVER_1, NORMAL_PSDS_SERVER, or REALTIME_PSDS_SERVER. The + * client must download PSDS data and inject it by calling injectPsdsData(). + * + * @param psdsType Type of PSDS data. + */ + void downloadRequestCb(in PsdsType psdsType); +} \ No newline at end of file diff --git a/gnss/aidl/android/hardware/gnss/PsdsType.aidl b/gnss/aidl/android/hardware/gnss/PsdsType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..d4fec77adee9ef0b020783810851d008f96f8b4e --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/PsdsType.aidl @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.gnss; + +/** The type of PSDS data. */ +@VintfStability +@Backing(type="int") +enum PsdsType { + + /** + * Long-Term type PSDS data, which lasts for many hours to several days and often provides + * satellite orbit and clock accuracy of 2 - 20 meters. + */ + LONG_TERM = 1, + + /** + * Normal type PSDS data, which is similar to broadcast ephemeris in longevity - lasting for + * hours and providings satellite orbit and clock accuracy of 1 - 2 meters. + */ + NORMAL = 2, + + /** + * Real-Time type PSDS data, which lasts for minutes and provides brief satellite status + * information such as temporary malfunction, but does not include satellite orbit or clock + * information. + */ + REALTIME = 3, +} diff --git a/gnss/aidl/android/hardware/gnss/SatelliteClockInfo.aidl b/gnss/aidl/android/hardware/gnss/SatelliteClockInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..4b7d5d68cb18480a496d24196270e3dee737f88c --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/SatelliteClockInfo.aidl @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.gnss; + +/** + * Contains estimates of the satellite clock info. + */ +@VintfStability +parcelable SatelliteClockInfo { + /** + * Satellite hardware code bias of the reported code type w.r.t + * ionosphere-free measurement in meters. + * + * When broadcast ephemeris is used, this is the offset caused + * by the satellite hardware delays at different frequencies; + * e.g. in IS-GPS-705D, this term is described in Section + * 20.3.3.3.1.2.1. + * + * For GPS this term is ~10ns, and affects the satellite position + * computation by less than a millimeter. + */ + double satHardwareCodeBiasMeters; + + /** + * Satellite time correction for ionospheric-free signal measurement + * (meters). The satellite clock correction for the given signal type + * = satTimeCorrectionMeters - satHardwareCodeBiasMeters. + * + * When broadcast ephemeris is used, this is the offset modeled in the + * clock terms broadcast over the air by the satellites; + * e.g. in IS-GPS-200H, Section 20.3.3.3.3.1, this term is + * ∆tsv = af0 + af1(t - toc) + af2(t - toc)^2 + ∆tr. + * + * If another source of ephemeris is used for SatellitePvt, then the + * equivalent value of satTimeCorrection must be provided. + * + * For GPS this term is ~1ms, and affects the satellite position + * computation by ~1m. + */ + double satTimeCorrectionMeters; + + /** Satellite clock drift (meters per second). */ + double satClkDriftMps; +} diff --git a/gnss/aidl/android/hardware/gnss/SatellitePositionEcef.aidl b/gnss/aidl/android/hardware/gnss/SatellitePositionEcef.aidl new file mode 100644 index 0000000000000000000000000000000000000000..febe62333f6066a017efce2c2c1ac01d9c749149 --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/SatellitePositionEcef.aidl @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.gnss; + +/** + * Contains estimates of the satellite position fields in ECEF coordinate frame. + * + * The satellite position must be defined at the time of transmission of the + * signal receivedSvTimeNs. + */ +@VintfStability +parcelable SatellitePositionEcef { + /** Satellite position X in WGS84 ECEF (meters). */ + double posXMeters; + + /** Satellite position Y in WGS84 ECEF (meters). */ + double posYMeters; + + /** Satellite position Z in WGS84 ECEF (meters). */ + double posZMeters; + + /** + * The Signal in Space User Range Error (URE) (meters). + * + * It covers satellite position and clock errors projected to the pseudorange measurements. + */ + double ureMeters; +} diff --git a/gnss/aidl/android/hardware/gnss/SatellitePvt.aidl b/gnss/aidl/android/hardware/gnss/SatellitePvt.aidl new file mode 100644 index 0000000000000000000000000000000000000000..a238e3fc26c183f5d3cb1eaf3850e108b5ff1221 --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/SatellitePvt.aidl @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.gnss; + +import android.hardware.gnss.SatelliteClockInfo; +import android.hardware.gnss.SatellitePositionEcef; +import android.hardware.gnss.SatelliteVelocityEcef; + +/** + * Contains estimates of the satellite position, velocity and time in the + * ECEF coordinate frame. + */ +@VintfStability +parcelable SatellitePvt { + /** + * Bit mask indicating valid satellite position, velocity and clock info fields are + * stored in the SatellitePvt. + */ + const int HAS_POSITION_VELOCITY_CLOCK_INFO = 1 << 0; + + /** + * Bit mask indicating a valid iono delay field is stored in the SatellitePvt. + */ + const int HAS_IONO = 1 << 1; + + /** + * Bit mask indicating a valid tropo delay field is stored in the SatellitePvt. + */ + const int HAS_TROPO = 1 << 2; + + /** + * A bitfield of flags indicating the validity of the fields in this SatellitePvt. + * The bit masks are defined in the constants with prefix HAS_* + * + * Fields for which there is no corresponding flag must be filled in with a valid value. + * For convenience, these are marked as mandatory. + * + * Others fields may have invalid information in them, if not marked as valid by the + * corresponding bit in flags. + */ + int flags; + + /** + * Satellite position in WGS84 ECEF. See comments of + * SatellitePositionEcef for units. + */ + SatellitePositionEcef satPosEcef; + + /** + * Satellite velocity in WGS84 ECEF. See comments of + * SatelliteVelocityEcef for units. + */ + SatelliteVelocityEcef satVelEcef; + + /** Satellite clock bias and drift info. */ + SatelliteClockInfo satClockInfo; + + /** Ionospheric delay in meters. */ + double ionoDelayMeters; + + /** Tropospheric delay in meters. */ + double tropoDelayMeters; +} diff --git a/gnss/aidl/android/hardware/gnss/SatelliteVelocityEcef.aidl b/gnss/aidl/android/hardware/gnss/SatelliteVelocityEcef.aidl new file mode 100644 index 0000000000000000000000000000000000000000..f2d7ab6030914858bf34d834a20e5a2d3234e402 --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/SatelliteVelocityEcef.aidl @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.gnss; + +/** + * Contains estimates of the satellite velocity fields in the ECEF coordinate frame. + * + * The satellite velocity must be defined at the time of transmission of the + * signal receivedSvTimeNs. + */ +@VintfStability +parcelable SatelliteVelocityEcef { + /** Satellite velocity X in WGS84 ECEF (meters per second). */ + double velXMps; + + /** Satellite velocity Y in WGS84 ECEF (meters per second). */ + double velYMps; + + /** Satellite velocity Z in WGS84 ECEF (meters per second). */ + double velZMps; + + /** + * The Signal in Space User Range Error Rate (URE Rate) (meters per second). + * + * It covers satellite velocity error and Satellite clock drift + * projected to the pseudorange rate measurements. + */ + double ureRateMps; +} diff --git a/gnss/aidl/default/Android.bp b/gnss/aidl/default/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..c028dd764e6d8d5160080abf65001754d853a2c5 --- /dev/null +++ b/gnss/aidl/default/Android.bp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_binary { + name: "android.hardware.gnss-service.example", + relative_install_path: "hw", + init_rc: [ + "gnss-default.rc", + ], + vintf_fragments: [ + "gnss-default.xml", + "gnss@2.1-service.xml", + ], + vendor: true, + cflags: [ + "-Wall", + "-Wextra", + ], + shared_libs: [ + "libbase", + "libcutils", + "libbinder_ndk", + "libhidlbase", + "libutils", + "liblog", + "android.hardware.gnss@2.1", + "android.hardware.gnss@2.0", + "android.hardware.gnss@1.1", + "android.hardware.gnss@1.0", + "android.hardware.gnss.measurement_corrections@1.1", + "android.hardware.gnss.measurement_corrections@1.0", + "android.hardware.gnss.visibility_control@1.0", + "android.hardware.gnss-V1-ndk", + ], + srcs: [ + "Gnss.cpp", + "GnssHidlHal.cpp", + "GnssPowerIndication.cpp", + "GnssPsds.cpp", + "GnssConfiguration.cpp", + "GnssMeasurementInterface.cpp", + "service.cpp", + ], + static_libs: [ + "android.hardware.gnss@common-default-lib", + ], +} diff --git a/gnss/aidl/default/Gnss.cpp b/gnss/aidl/default/Gnss.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6061eec817bfe61ae5bfebb8ba0fd645449c29a6 --- /dev/null +++ b/gnss/aidl/default/Gnss.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "GnssAidl" + +#include "Gnss.h" +#include +#include "GnssConfiguration.h" +#include "GnssMeasurementInterface.h" +#include "GnssPsds.h" + +namespace aidl::android::hardware::gnss { + +std::shared_ptr Gnss::sGnssCallback = nullptr; + +ndk::ScopedAStatus Gnss::setCallback(const std::shared_ptr& callback) { + ALOGD("Gnss::setCallback"); + if (callback == nullptr) { + ALOGE("%s: Null callback ignored", __func__); + return ndk::ScopedAStatus::fromExceptionCode(STATUS_INVALID_OPERATION); + } + + sGnssCallback = callback; + + int capabilities = (int)(IGnssCallback::CAPABILITY_SATELLITE_BLOCKLIST | + IGnssCallback::CAPABILITY_SATELLITE_PVT | + IGnssCallback::CAPABILITY_CORRELATION_VECTOR); + + auto status = sGnssCallback->gnssSetCapabilitiesCb(capabilities); + if (!status.isOk()) { + ALOGE("%s: Unable to invoke callback.gnssSetCapabilities", __func__); + } + + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Gnss::close() { + ALOGD("Gnss::close"); + sGnssCallback = nullptr; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Gnss::getExtensionPsds(std::shared_ptr* iGnssPsds) { + ALOGD("Gnss::getExtensionPsds"); + *iGnssPsds = SharedRefBase::make(); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Gnss::getExtensionGnssConfiguration( + std::shared_ptr* iGnssConfiguration) { + ALOGD("Gnss::getExtensionGnssConfiguration"); + if (mGnssConfiguration == nullptr) { + mGnssConfiguration = SharedRefBase::make(); + } + *iGnssConfiguration = mGnssConfiguration; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Gnss::getExtensionGnssPowerIndication( + std::shared_ptr* iGnssPowerIndication) { + ALOGD("Gnss::getExtensionGnssPowerIndication"); + if (mGnssPowerIndication == nullptr) { + mGnssPowerIndication = SharedRefBase::make(); + } + + *iGnssPowerIndication = mGnssPowerIndication; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Gnss::getExtensionGnssMeasurement( + std::shared_ptr* iGnssMeasurement) { + ALOGD("Gnss::getExtensionGnssMeasurement"); + + *iGnssMeasurement = SharedRefBase::make(); + return ndk::ScopedAStatus::ok(); +} + +} // namespace aidl::android::hardware::gnss diff --git a/gnss/aidl/default/Gnss.h b/gnss/aidl/default/Gnss.h new file mode 100644 index 0000000000000000000000000000000000000000..76ebe4d126baf3cd8884379f80cdde3d06be7779 --- /dev/null +++ b/gnss/aidl/default/Gnss.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include "GnssConfiguration.h" +#include "GnssPowerIndication.h" + +namespace aidl::android::hardware::gnss { + +class Gnss : public BnGnss { + public: + ndk::ScopedAStatus setCallback(const std::shared_ptr& callback) override; + ndk::ScopedAStatus close() override; + ndk::ScopedAStatus getExtensionPsds(std::shared_ptr* iGnssPsds) override; + ndk::ScopedAStatus getExtensionGnssConfiguration( + std::shared_ptr* iGnssConfiguration) override; + ndk::ScopedAStatus getExtensionGnssPowerIndication( + std::shared_ptr* iGnssPowerIndication) override; + ndk::ScopedAStatus getExtensionGnssMeasurement( + std::shared_ptr* iGnssMeasurement) override; + + std::shared_ptr mGnssConfiguration; + std::shared_ptr mGnssPowerIndication; + + private: + static std::shared_ptr sGnssCallback; +}; + +} // namespace aidl::android::hardware::gnss diff --git a/gnss/aidl/default/GnssConfiguration.cpp b/gnss/aidl/default/GnssConfiguration.cpp new file mode 100644 index 0000000000000000000000000000000000000000..30e0d8c8b9942965ef092a465887b45b04488a27 --- /dev/null +++ b/gnss/aidl/default/GnssConfiguration.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "GnssConfigurationAidl" + +#include "GnssConfiguration.h" +#include + +namespace aidl::android::hardware::gnss { + +ndk::ScopedAStatus GnssConfiguration::setBlocklist(const vector& sourceList) { + ALOGD("GnssConfiguration::setBlocklist"); + std::unique_lock lock(mMutex); + mBlocklistedConstellationSet.clear(); + mBlocklistedSourceSet.clear(); + for (const auto& source : sourceList) { + if (source.svid == 0) { + // Wildcard blocklist, i.e., blocklist entire constellation. + mBlocklistedConstellationSet.insert(source.constellation); + } else { + mBlocklistedSourceSet.insert(source); + } + } + return ndk::ScopedAStatus::ok(); +} + +bool GnssConfiguration::isBlocklistedV2_1(const GnssSvInfoV2_1& gnssSvInfo) const { + std::unique_lock lock(mMutex); + if (mBlocklistedConstellationSet.find(static_cast( + gnssSvInfo.v2_0.constellation)) != mBlocklistedConstellationSet.end()) { + return true; + } + BlocklistedSource source = { + .constellation = static_cast(gnssSvInfo.v2_0.constellation), + .svid = gnssSvInfo.v2_0.v1_0.svid}; + return (mBlocklistedSourceSet.find(source) != mBlocklistedSourceSet.end()); +} + +} // namespace aidl::android::hardware::gnss diff --git a/gnss/aidl/default/GnssConfiguration.h b/gnss/aidl/default/GnssConfiguration.h new file mode 100644 index 0000000000000000000000000000000000000000..491733c9cad7d35a61ac504aa39c968fdfa34b38 --- /dev/null +++ b/gnss/aidl/default/GnssConfiguration.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace aidl::android::hardware::gnss { + +struct BlocklistedSourceHash { + inline int operator()(const BlocklistedSource& source) const { + return int(source.constellation) * 1000 + int(source.svid); + } +}; + +struct BlocklistedSourceEqual { + inline bool operator()(const BlocklistedSource& s1, const BlocklistedSource& s2) const { + return (s1.constellation == s2.constellation) && (s1.svid == s2.svid); + } +}; + +using GnssSvInfoV2_1 = ::android::hardware::gnss::V2_1::IGnssCallback::GnssSvInfo; +using std::vector; +using BlocklistedSourceSet = + std::unordered_set; +using BlocklistedConstellationSet = + std::unordered_set; + +struct GnssConfiguration : public BnGnssConfiguration { + public: + ndk::ScopedAStatus setSuplVersion(int) override { return ndk::ScopedAStatus::ok(); } + + ndk::ScopedAStatus setSuplMode(int) override { return ndk::ScopedAStatus::ok(); } + + ndk::ScopedAStatus setLppProfile(int) override { return ndk::ScopedAStatus::ok(); } + + ndk::ScopedAStatus setGlonassPositioningProtocol(int) override { + return ndk::ScopedAStatus::ok(); + } + + ndk::ScopedAStatus setEmergencySuplPdn(bool) override { return ndk::ScopedAStatus::ok(); } + + ndk::ScopedAStatus setEsExtensionSec(int) override { return ndk::ScopedAStatus::ok(); } + + ndk::ScopedAStatus setBlocklist(const vector& blocklist) override; + + bool isBlocklistedV2_1(const GnssSvInfoV2_1& gnssSvInfo) const; + + private: + BlocklistedSourceSet mBlocklistedSourceSet; + BlocklistedConstellationSet mBlocklistedConstellationSet; + mutable std::recursive_mutex mMutex; +}; + +} // namespace aidl::android::hardware::gnss diff --git a/gnss/aidl/default/GnssHidlHal.cpp b/gnss/aidl/default/GnssHidlHal.cpp new file mode 100644 index 0000000000000000000000000000000000000000..10b0106f327fecf5ddc20a6fa9db6b1bf43e2a29 --- /dev/null +++ b/gnss/aidl/default/GnssHidlHal.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "GnssHidlHal" + +#include "GnssHidlHal.h" + +namespace aidl::android::hardware::gnss { + +using GnssSvInfo = ::android::hardware::gnss::V2_1::IGnssCallback::GnssSvInfo; + +GnssHidlHal::GnssHidlHal(const std::shared_ptr& gnssAidl) : mGnssAidl(gnssAidl) { + Gnss* iGnss = mGnssAidl.get(); + std::shared_ptr iGnssConfiguration; + auto status = iGnss->getExtensionGnssConfiguration(&iGnssConfiguration); + if (!status.isOk()) { + ALOGE("Failed to getExtensionGnssConfiguration."); + } else { + mGnssConfigurationAidl = iGnss->mGnssConfiguration; + } + + std::shared_ptr iGnssPowerIndication; + status = iGnss->getExtensionGnssPowerIndication(&iGnssPowerIndication); + if (!status.isOk()) { + ALOGE("Failed to getExtensionGnssPowerIndication."); + } else { + mGnssPowerIndicationAidl = iGnss->mGnssPowerIndication; + } +}; + +hidl_vec GnssHidlHal::filterBlocklistedSatellitesV2_1( + hidl_vec gnssSvInfoList) { + if (mGnssConfigurationAidl == nullptr) { + ALOGE("Handle to AIDL GnssConfiguration is not available."); + return gnssSvInfoList; + } + for (uint32_t i = 0; i < gnssSvInfoList.size(); i++) { + if (mGnssConfigurationAidl->isBlocklistedV2_1(gnssSvInfoList[i])) { + ALOGD("Blocklisted constellation: %d, svid: %d", + (int)gnssSvInfoList[i].v2_0.constellation, gnssSvInfoList[i].v2_0.v1_0.svid); + gnssSvInfoList[i].v2_0.v1_0.svFlag &= ~static_cast( + ::android::hardware::gnss::V1_0::IGnssCallback::GnssSvFlags::USED_IN_FIX); + } + } + return gnssSvInfoList; +} + +void GnssHidlHal::notePowerConsumption() { + mGnssPowerIndicationAidl->notePowerConsumption(); +} + +} // namespace aidl::android::hardware::gnss diff --git a/gnss/aidl/default/GnssHidlHal.h b/gnss/aidl/default/GnssHidlHal.h new file mode 100644 index 0000000000000000000000000000000000000000..5fb4f972deaef4970275180e073e29d857622814 --- /dev/null +++ b/gnss/aidl/default/GnssHidlHal.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "Gnss.h" +#include "GnssConfiguration.h" +#include "v2_1/GnssTemplate.h" + +namespace aidl::android::hardware::gnss { + +class GnssHidlHal : public ::android::hardware::gnss::common::implementation::GnssTemplate< + ::android::hardware::gnss::V2_1::IGnss> { + public: + GnssHidlHal(const std::shared_ptr& gnssAidl); + + private: + hidl_vec<::android::hardware::gnss::V2_1::IGnssCallback::GnssSvInfo> + filterBlocklistedSatellitesV2_1( + hidl_vec<::android::hardware::gnss::V2_1::IGnssCallback::GnssSvInfo> gnssSvInfoList) + override; + void notePowerConsumption() override; + + std::shared_ptr mGnssAidl; + std::shared_ptr mGnssConfigurationAidl; + std::shared_ptr mGnssPowerIndicationAidl; +}; + +} // namespace aidl::android::hardware::gnss diff --git a/gnss/aidl/default/GnssMeasurementInterface.cpp b/gnss/aidl/default/GnssMeasurementInterface.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fcc1f986cc08346992304d8deca2d8f4bee13e34 --- /dev/null +++ b/gnss/aidl/default/GnssMeasurementInterface.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "GnssMeasIfaceAidl" + +#include "GnssMeasurementInterface.h" +#include +#include +#include "Utils.h" + +namespace aidl::android::hardware::gnss { + +using Utils = ::android::hardware::gnss::common::Utils; + +std::shared_ptr GnssMeasurementInterface::sCallback = nullptr; + +GnssMeasurementInterface::GnssMeasurementInterface() : mMinIntervalMillis(1000) {} + +GnssMeasurementInterface::~GnssMeasurementInterface() { + stop(); +} + +ndk::ScopedAStatus GnssMeasurementInterface::setCallback( + const std::shared_ptr& callback, const bool enableFullTracking, + const bool enableCorrVecOutputs) { + ALOGD("setCallback: enableFullTracking: %d enableCorrVecOutputs: %d", (int)enableFullTracking, + (int)enableCorrVecOutputs); + std::unique_lock lock(mMutex); + sCallback = callback; + + if (mIsActive) { + ALOGW("GnssMeasurement callback already set. Resetting the callback..."); + stop(); + } + start(enableCorrVecOutputs); + + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus GnssMeasurementInterface::close() { + ALOGD("close"); + stop(); + std::unique_lock lock(mMutex); + sCallback = nullptr; + return ndk::ScopedAStatus::ok(); +} + +void GnssMeasurementInterface::start(const bool enableCorrVecOutputs) { + ALOGD("start"); + mIsActive = true; + mThread = std::thread([this, enableCorrVecOutputs]() { + while (mIsActive == true) { + auto measurement = Utils::getMockMeasurement(enableCorrVecOutputs); + this->reportMeasurement(measurement); + + std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMillis)); + } + }); + mThread.detach(); +} + +void GnssMeasurementInterface::stop() { + ALOGD("stop"); + mIsActive = false; +} + +void GnssMeasurementInterface::reportMeasurement(const GnssData& data) { + ALOGD("reportMeasurement()"); + std::shared_ptr callbackCopy; + { + std::unique_lock lock(mMutex); + if (sCallback == nullptr) { + ALOGE("%s: GnssMeasurement::sCallback is null.", __func__); + return; + } + callbackCopy = sCallback; + } + callbackCopy->gnssMeasurementCb(data); +} + +} // namespace aidl::android::hardware::gnss diff --git a/gnss/aidl/default/GnssMeasurementInterface.h b/gnss/aidl/default/GnssMeasurementInterface.h new file mode 100644 index 0000000000000000000000000000000000000000..db6351555db3b3e70d250cbe9aeb5537b0c8f413 --- /dev/null +++ b/gnss/aidl/default/GnssMeasurementInterface.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace aidl::android::hardware::gnss { + +struct GnssMeasurementInterface : public BnGnssMeasurementInterface { + public: + GnssMeasurementInterface(); + ~GnssMeasurementInterface(); + ndk::ScopedAStatus setCallback(const std::shared_ptr& callback, + const bool enableFullTracking, + const bool enableCorrVecOutputs) override; + ndk::ScopedAStatus close() override; + + private: + void start(const bool enableCorrVecOutputs); + void stop(); + void reportMeasurement(const GnssData&); + + std::atomic mMinIntervalMillis; + std::atomic mIsActive; + std::thread mThread; + + // Guarded by mMutex + static std::shared_ptr sCallback; + + // Synchronization lock for sCallback + mutable std::mutex mMutex; +}; + +} // namespace aidl::android::hardware::gnss diff --git a/gnss/aidl/default/GnssPowerIndication.cpp b/gnss/aidl/default/GnssPowerIndication.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4dec1c6a852ea2dfe4835e3ae546e5383b380f03 --- /dev/null +++ b/gnss/aidl/default/GnssPowerIndication.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "GnssPowerIndicationAidl" + +#include "GnssPowerIndication.h" +#include +#include +#include + +namespace aidl::android::hardware::gnss { + +std::shared_ptr GnssPowerIndication::sCallback = nullptr; + +ndk::ScopedAStatus GnssPowerIndication::setCallback( + const std::shared_ptr& callback) { + ALOGD("setCallback"); + std::unique_lock lock(mMutex); + sCallback = callback; + sCallback->setCapabilitiesCb(IGnssPowerIndicationCallback::CAPABILITY_TOTAL | + IGnssPowerIndicationCallback::CAPABILITY_SINGLEBAND_TRACKING | + IGnssPowerIndicationCallback::CAPABILITY_MULTIBAND_TRACKING | + IGnssPowerIndicationCallback::CAPABILITY_SINGLEBAND_ACQUISITION | + IGnssPowerIndicationCallback::CAPABILITY_MULTIBAND_ACQUISITION | + IGnssPowerIndicationCallback::CAPABILITY_OTHER_MODES); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus GnssPowerIndication::requestGnssPowerStats() { + ALOGD("requestGnssPowerStats"); + std::unique_lock lock(mMutex); + + ElapsedRealtime elapsedRealtime = { + .flags = ElapsedRealtime::HAS_TIMESTAMP_NS | ElapsedRealtime::HAS_TIME_UNCERTAINTY_NS, + .timestampNs = ::android::elapsedRealtimeNano(), + .timeUncertaintyNs = 1000, + }; + GnssPowerStats gnssPowerStats = { + .elapsedRealtime = elapsedRealtime, + .totalEnergyMilliJoule = 1.500e+3 + numLocationReported * 22.0, + .singlebandTrackingModeEnergyMilliJoule = 0.0, + .multibandTrackingModeEnergyMilliJoule = 1.28e+2 + numLocationReported * 4.0, + .singlebandAcquisitionModeEnergyMilliJoule = 0.0, + .multibandAcquisitionModeEnergyMilliJoule = 3.65e+2 + numLocationReported * 15.0, + .otherModesEnergyMilliJoule = {1.232e+2, 3.234e+3}, + }; + sCallback->gnssPowerStatsCb(gnssPowerStats); + return ndk::ScopedAStatus::ok(); +} + +void GnssPowerIndication::notePowerConsumption() { + numLocationReported++; +} + +} // namespace aidl::android::hardware::gnss diff --git a/gnss/aidl/default/GnssPowerIndication.h b/gnss/aidl/default/GnssPowerIndication.h new file mode 100644 index 0000000000000000000000000000000000000000..93ca0b7097f172fcddec2bba7e993be837318043 --- /dev/null +++ b/gnss/aidl/default/GnssPowerIndication.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +namespace aidl::android::hardware::gnss { + +struct GnssPowerIndication : public BnGnssPowerIndication { + public: + ndk::ScopedAStatus setCallback( + const std::shared_ptr& callback) override; + ndk::ScopedAStatus requestGnssPowerStats() override; + + void notePowerConsumption(); + + private: + // Guarded by mMutex + static std::shared_ptr sCallback; + + // Synchronization lock for sCallback + mutable std::mutex mMutex; + + int numLocationReported; +}; + +} // namespace aidl::android::hardware::gnss diff --git a/gnss/aidl/default/GnssPsds.cpp b/gnss/aidl/default/GnssPsds.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6512af610a9b7aece1b3f5682d17bea9582747be --- /dev/null +++ b/gnss/aidl/default/GnssPsds.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "GnssPsdsAidl" + +#include "GnssPsds.h" +#include +#include + +namespace aidl::android::hardware::gnss { + +std::shared_ptr GnssPsds::sCallback = nullptr; + +ndk::ScopedAStatus GnssPsds::setCallback(const std::shared_ptr& callback) { + ALOGD("setCallback"); + std::unique_lock lock(mMutex); + sCallback = callback; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus GnssPsds::injectPsdsData(PsdsType psdsType, + const std::vector& psdsData) { + ALOGD("injectPsdsData. psdsType: %d, psdsData: %d bytes", static_cast(psdsType), + static_cast(psdsData.size())); + if (psdsData.size() > 0) { + return ndk::ScopedAStatus::ok(); + } else { + return ndk::ScopedAStatus::fromServiceSpecificError(IGnss::ERROR_INVALID_ARGUMENT); + } +} +} // namespace aidl::android::hardware::gnss diff --git a/gnss/aidl/default/GnssPsds.h b/gnss/aidl/default/GnssPsds.h new file mode 100644 index 0000000000000000000000000000000000000000..de9e68f74523ba0ccbd1a35dc53ee107a149a807 --- /dev/null +++ b/gnss/aidl/default/GnssPsds.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +namespace aidl::android::hardware::gnss { + +struct GnssPsds : public BnGnssPsds { + public: + ndk::ScopedAStatus setCallback(const std::shared_ptr& callback) override; + ndk::ScopedAStatus injectPsdsData(PsdsType psdsType, + const std::vector& psdsData) override; + + private: + // Guarded by mMutex + static std::shared_ptr sCallback; + + // Synchronization lock for sCallback + mutable std::mutex mMutex; +}; + +} // namespace aidl::android::hardware::gnss diff --git a/gnss/aidl/default/gnss-default.rc b/gnss/aidl/default/gnss-default.rc new file mode 100644 index 0000000000000000000000000000000000000000..fe179c34f04da7f24b49d54be0eb6a6b026bf835 --- /dev/null +++ b/gnss/aidl/default/gnss-default.rc @@ -0,0 +1,4 @@ +service vendor.gnss-default /vendor/bin/hw/android.hardware.gnss-service.example + class hal + user nobody + group nobody diff --git a/gnss/aidl/default/gnss-default.xml b/gnss/aidl/default/gnss-default.xml new file mode 100644 index 0000000000000000000000000000000000000000..2b06cd28de3ba111856671dfa1f7c235995d3af6 --- /dev/null +++ b/gnss/aidl/default/gnss-default.xml @@ -0,0 +1,9 @@ + + + android.hardware.gnss + + IGnss + default + + + diff --git a/gnss/aidl/default/gnss@2.1-service.xml b/gnss/aidl/default/gnss@2.1-service.xml new file mode 100644 index 0000000000000000000000000000000000000000..12a1fdfa089fcb4cc4c02ab3cfdc806e385aa793 --- /dev/null +++ b/gnss/aidl/default/gnss@2.1-service.xml @@ -0,0 +1,12 @@ + + + android.hardware.gnss + hwbinder + 2.1 + 1.1 + + IGnss + default + + + diff --git a/gnss/aidl/default/service.cpp b/gnss/aidl/default/service.cpp new file mode 100644 index 0000000000000000000000000000000000000000..09f1ad2b367b441f6378b905dc3e9ea193617e81 --- /dev/null +++ b/gnss/aidl/default/service.cpp @@ -0,0 +1,58 @@ +/* + * Copyright 2020, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "Gnss-main" + +#include +#include +#include +#include +#include +#include +#include +#include "Gnss.h" +#include "GnssHidlHal.h" + +using aidl::android::hardware::gnss::Gnss; +using aidl::android::hardware::gnss::GnssHidlHal; +using ::android::OK; +using ::android::sp; +using ::android::hardware::configureRpcThreadpool; +using ::android::hardware::joinRpcThreadpool; +using ::android::hardware::gnss::V2_1::IGnss; + +int main() { + ABinderProcess_setThreadPoolMaxThreadCount(1); + ABinderProcess_startThreadPool(); + + std::shared_ptr gnssAidl = ndk::SharedRefBase::make(); + const std::string instance = std::string() + Gnss::descriptor + "/default"; + binder_status_t status = + AServiceManager_addService(gnssAidl->asBinder().get(), instance.c_str()); + CHECK(status == STATUS_OK); + + sp gnss = new GnssHidlHal(gnssAidl); + configureRpcThreadpool(1, true /* will join */); + if (gnss->registerAsService() != OK) { + ALOGE("Could not register gnss 2.1 service."); + return 0; + } + + joinRpcThreadpool(); + ABinderProcess_joinThreadPool(); + + return EXIT_FAILURE; // should not reach +} diff --git a/gnss/aidl/vts/Android.bp b/gnss/aidl/vts/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..838849d535098e62b6338458224b802af9ce7b5e --- /dev/null +++ b/gnss/aidl/vts/Android.bp @@ -0,0 +1,53 @@ +// Copyright (C) 2020 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_test { + name: "VtsHalGnssTargetTest", + defaults: [ + "VtsHalTargetTestDefaults", + "use_libaidlvintf_gtest_helper_static", + ], + srcs: [ + "gnss_hal_test.cpp", + "gnss_hal_test_cases.cpp", + "GnssCallbackAidl.cpp", + "GnssMeasurementCallbackAidl.cpp", + "GnssPowerIndicationCallback.cpp", + "VtsHalGnssTargetTest.cpp", + ], + shared_libs: [ + "android.hardware.gnss@2.1", + "android.hardware.gnss@2.0", + "android.hardware.gnss@1.1", + "android.hardware.gnss@1.0", + "libbinder", + ], + static_libs: [ + "android.hardware.gnss-V1-cpp", + "android.hardware.gnss@common-vts-lib", + ], + test_suites: [ + "general-tests", + "vts", + ], +} diff --git a/gnss/aidl/vts/GnssCallbackAidl.cpp b/gnss/aidl/vts/GnssCallbackAidl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f5c745b75c3e434908037b7c4df13a8fd60c9946 --- /dev/null +++ b/gnss/aidl/vts/GnssCallbackAidl.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "GnssCallbackAidl.h" +#include + +android::binder::Status GnssCallbackAidl::gnssSetCapabilitiesCb(const int capabilities) { + ALOGI("Capabilities received %d", capabilities); + capabilities_cbq_.store(capabilities); + return android::binder::Status::ok(); +} diff --git a/gnss/aidl/vts/GnssCallbackAidl.h b/gnss/aidl/vts/GnssCallbackAidl.h new file mode 100644 index 0000000000000000000000000000000000000000..7f802ea02ed2958ca0793d5315e50df906bb3791 --- /dev/null +++ b/gnss/aidl/vts/GnssCallbackAidl.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include "GnssCallbackEventQueue.h" + +/* Callback class for data & Event. */ +class GnssCallbackAidl : public android::hardware::gnss::BnGnssCallback { + public: + GnssCallbackAidl() : capabilities_cbq_("capabilities"){}; + ~GnssCallbackAidl(){}; + + android::binder::Status gnssSetCapabilitiesCb(const int capabilities) override; + + int last_capabilities_; + android::hardware::gnss::common::GnssCallbackEventQueue capabilities_cbq_; +}; \ No newline at end of file diff --git a/gnss/aidl/vts/GnssMeasurementCallbackAidl.cpp b/gnss/aidl/vts/GnssMeasurementCallbackAidl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c4fad7fb35feac2b546b8956a478d826b62a42f7 --- /dev/null +++ b/gnss/aidl/vts/GnssMeasurementCallbackAidl.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "GnssMeasurementCallbackAidl" + +#include "GnssMeasurementCallbackAidl.h" +#include +#include + +using android::hardware::gnss::GnssData; + +android::binder::Status GnssMeasurementCallbackAidl::gnssMeasurementCb(const GnssData& gnssData) { + ALOGI("gnssMeasurementCb"); + ALOGI("elapsedRealtime: flags = %d, timestampNs: %" PRId64 ", timeUncertaintyNs=%lf", + gnssData.elapsedRealtime.flags, gnssData.elapsedRealtime.timestampNs, + gnssData.elapsedRealtime.timeUncertaintyNs); + for (const auto& measurement : gnssData.measurements) { + ALOGI("measurement.receivedSvTimeInNs=%" PRId64, measurement.receivedSvTimeInNs); + } + gnss_data_cbq_.store(gnssData); + return android::binder::Status::ok(); +} diff --git a/gnss/aidl/vts/GnssMeasurementCallbackAidl.h b/gnss/aidl/vts/GnssMeasurementCallbackAidl.h new file mode 100644 index 0000000000000000000000000000000000000000..f6c79cfaf2a55e716abe6716bf61e7abed7877cd --- /dev/null +++ b/gnss/aidl/vts/GnssMeasurementCallbackAidl.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include "GnssCallbackEventQueue.h" + +/** Implementation for IGnssMeasurementCallback. */ +class GnssMeasurementCallbackAidl : public android::hardware::gnss::BnGnssMeasurementCallback { + public: + GnssMeasurementCallbackAidl() : gnss_data_cbq_("gnss_data") {} + ~GnssMeasurementCallbackAidl() {} + + android::binder::Status gnssMeasurementCb( + const android::hardware::gnss::GnssData& gnssData) override; + + android::hardware::gnss::common::GnssCallbackEventQueue + gnss_data_cbq_; +}; diff --git a/gnss/aidl/vts/GnssPowerIndicationCallback.cpp b/gnss/aidl/vts/GnssPowerIndicationCallback.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1cbfc20f8c2a12ad85fb46d883a1c35617f74746 --- /dev/null +++ b/gnss/aidl/vts/GnssPowerIndicationCallback.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "GnssPwrIndCallback" + +#include "GnssPowerIndicationCallback.h" +#include + +using android::hardware::gnss::GnssPowerStats; + +android::binder::Status GnssPowerIndicationCallback::setCapabilitiesCb(const int capabilities) { + ALOGI("Capabilities received %d", capabilities); + capabilities_cbq_.store(capabilities); + return android::binder::Status::ok(); +} + +android::binder::Status GnssPowerIndicationCallback::gnssPowerStatsCb( + const GnssPowerStats& gnssPowerStats) { + ALOGI("gnssPowerStatsCb"); + ALOGI("elapsedRealtime: %ld, totalEnergyMilliJoule: %f", + (long)gnssPowerStats.elapsedRealtime.timestampNs, gnssPowerStats.totalEnergyMilliJoule); + ALOGI("singlebandTrackingModeEnergyMilliJoule: %f, multibandTrackingModeEnergyMilliJoule: %f", + gnssPowerStats.singlebandTrackingModeEnergyMilliJoule, + gnssPowerStats.multibandTrackingModeEnergyMilliJoule); + ALOGI("singlebandAcquisitionModeEnergyMilliJoule: %f, " + "multibandAcquisitionModeEnergyMilliJoule: %f", + gnssPowerStats.singlebandAcquisitionModeEnergyMilliJoule, + gnssPowerStats.multibandAcquisitionModeEnergyMilliJoule); + for (const auto& otherModeEnergyMilliJoule : gnssPowerStats.otherModesEnergyMilliJoule) { + ALOGI("otherModeEnergyMilliJoule: %f", otherModeEnergyMilliJoule); + } + gnss_power_stats_cbq_.store(gnssPowerStats); + return android::binder::Status::ok(); +} diff --git a/gnss/aidl/vts/GnssPowerIndicationCallback.h b/gnss/aidl/vts/GnssPowerIndicationCallback.h new file mode 100644 index 0000000000000000000000000000000000000000..3416f172308672b5e5597d121e0d3697cc269aef --- /dev/null +++ b/gnss/aidl/vts/GnssPowerIndicationCallback.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include "GnssCallbackEventQueue.h" + +/** Implementation for IGnssPowerIndicationCallback. */ +class GnssPowerIndicationCallback : public android::hardware::gnss::BnGnssPowerIndicationCallback { + public: + GnssPowerIndicationCallback() + : capabilities_cbq_("capabilities"), + gnss_power_stats_cbq_("gnss_power_stats") {} + ~GnssPowerIndicationCallback() {} + + android::binder::Status setCapabilitiesCb(const int capabilities) override; + android::binder::Status gnssPowerStatsCb( + const android::hardware::gnss::GnssPowerStats& gnssPowerStats) override; + + android::hardware::gnss::common::GnssCallbackEventQueue capabilities_cbq_; + int last_capabilities_; + android::hardware::gnss::common::GnssCallbackEventQueue + gnss_power_stats_cbq_; + android::hardware::gnss::GnssPowerStats last_gnss_power_stats_; +}; diff --git a/gnss/aidl/vts/VtsHalGnssTargetTest.cpp b/gnss/aidl/vts/VtsHalGnssTargetTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4bba92b49b034e6844ec9680000eedc474796838 --- /dev/null +++ b/gnss/aidl/vts/VtsHalGnssTargetTest.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "gnss_hal_test.h" + +#include +#include +#include + +using android::ProcessState; + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GnssHalTest); +INSTANTIATE_TEST_SUITE_P(, GnssHalTest, + testing::ValuesIn(android::getAidlHalInstanceNames(IGnssAidl::descriptor)), + android::PrintInstanceNameToString); + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + ProcessState::self()->setThreadPoolMaxThreadCount(1); + ProcessState::self()->startThreadPool(); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/gnss/aidl/vts/gnss_hal_test.cpp b/gnss/aidl/vts/gnss_hal_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2447bf8c84bb8bf4b306a0687229daa169f42751 --- /dev/null +++ b/gnss/aidl/vts/gnss_hal_test.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "gnss_hal_test.h" +#include + +using GnssConstellationTypeAidl = android::hardware::gnss::GnssConstellationType; + +void GnssHalTest::SetUp() { + // Get AIDL handle + aidl_gnss_hal_ = android::waitForDeclaredService(String16(GetParam().c_str())); + ASSERT_NE(aidl_gnss_hal_, nullptr); + + const auto& hidlInstanceNames = android::hardware::getAllHalInstanceNames( + android::hardware::gnss::V2_1::IGnss::descriptor); + gnss_hal_ = IGnss_V2_1::getService(hidlInstanceNames[0]); + ASSERT_NE(gnss_hal_, nullptr); + + SetUpGnssCallback(); +} + +void GnssHalTest::SetUpGnssCallback() { + aidl_gnss_cb_ = new GnssCallbackAidl(); + ASSERT_NE(aidl_gnss_cb_, nullptr); + + auto status = aidl_gnss_hal_->setCallback(aidl_gnss_cb_); + if (!status.isOk()) { + ALOGE("Failed to setCallback"); + } + + ASSERT_TRUE(status.isOk()); + + /* + * Capabilities callback should trigger. + */ + EXPECT_TRUE(aidl_gnss_cb_->capabilities_cbq_.retrieve(aidl_gnss_cb_->last_capabilities_, + TIMEOUT_SEC)); + + EXPECT_EQ(aidl_gnss_cb_->capabilities_cbq_.calledCount(), 1); + + // Invoke the super method. + GnssHalTestTemplate::SetUpGnssCallback(); +} diff --git a/gnss/aidl/vts/gnss_hal_test.h b/gnss/aidl/vts/gnss_hal_test.h new file mode 100644 index 0000000000000000000000000000000000000000..f72f7fe4e897e1bbccb5b4d5a68bb546982432e9 --- /dev/null +++ b/gnss/aidl/vts/gnss_hal_test.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +#include +#include + +#include +#include "GnssCallbackAidl.h" +#include "v2_1/gnss_hal_test_template.h" + +using IGnss_V2_1 = android::hardware::gnss::V2_1::IGnss; + +using android::ProcessState; +using android::sp; +using android::String16; +using IGnssAidl = android::hardware::gnss::IGnss; +using android::hardware::gnss::BlocklistedSource; +using android::hardware::gnss::IGnssConfiguration; + +// The main test class for GNSS HAL. +class GnssHalTest : public android::hardware::gnss::common::GnssHalTestTemplate { + public: + GnssHalTest(){}; + ~GnssHalTest(){}; + virtual void SetUp() override; + virtual void SetUpGnssCallback() override; + + sp aidl_gnss_hal_; + sp aidl_gnss_cb_; // Primary callback interface +}; diff --git a/gnss/aidl/vts/gnss_hal_test_cases.cpp b/gnss/aidl/vts/gnss_hal_test_cases.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b484f9c3831ddabe506689f4c96365ea0d390b4c --- /dev/null +++ b/gnss/aidl/vts/gnss_hal_test_cases.cpp @@ -0,0 +1,752 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "GnssHalTestCases" + +#include +#include +#include +#include +#include +#include "GnssMeasurementCallbackAidl.h" +#include "GnssPowerIndicationCallback.h" +#include "gnss_hal_test.h" + +using android::sp; +using android::hardware::gnss::BlocklistedSource; +using android::hardware::gnss::ElapsedRealtime; +using android::hardware::gnss::GnssClock; +using android::hardware::gnss::GnssData; +using android::hardware::gnss::GnssMeasurement; +using android::hardware::gnss::GnssPowerStats; +using android::hardware::gnss::IGnss; +using android::hardware::gnss::IGnssConfiguration; +using android::hardware::gnss::IGnssMeasurementCallback; +using android::hardware::gnss::IGnssMeasurementInterface; +using android::hardware::gnss::IGnssPowerIndication; +using android::hardware::gnss::IGnssPsds; +using android::hardware::gnss::PsdsType; +using android::hardware::gnss::SatellitePvt; + +using GnssConstellationTypeAidl = android::hardware::gnss::GnssConstellationType; + +/* + * SetupTeardownCreateCleanup: + * Requests the gnss HAL then calls cleanup + * + * Empty test fixture to verify basic Setup & Teardown + */ +TEST_P(GnssHalTest, SetupTeardownCreateCleanup) {} + +/* + * TestPsdsExtension: + * 1. Gets the PsdsExtension and verifies that it returns a non-null extension. + * 2. Injects empty PSDS data and verifies that it returns an error. + */ +TEST_P(GnssHalTest, TestPsdsExtension) { + sp iGnssPsds; + auto status = aidl_gnss_hal_->getExtensionPsds(&iGnssPsds); + ASSERT_TRUE(status.isOk()); + ASSERT_TRUE(iGnssPsds != nullptr); + + status = iGnssPsds->injectPsdsData(PsdsType::LONG_TERM, std::vector()); + ASSERT_FALSE(status.isOk()); +} + +void CheckSatellitePvt(const SatellitePvt& satellitePvt) { + const double kMaxOrbitRadiusMeters = 43000000.0; + const double kMaxVelocityMps = 4000.0; + // The below values are determined using GPS ICD Table 20-1 + const double kMinHardwareCodeBiasMeters = -17.869; + const double kMaxHardwareCodeBiasMeters = 17.729; + const double kMaxTimeCorrelationMeters = 3e6; + const double kMaxSatClkDriftMps = 1.117; + + ASSERT_TRUE(satellitePvt.flags & SatellitePvt::HAS_POSITION_VELOCITY_CLOCK_INFO || + satellitePvt.flags & SatellitePvt::HAS_IONO || + satellitePvt.flags & SatellitePvt::HAS_TROPO); + if (satellitePvt.flags & SatellitePvt::HAS_POSITION_VELOCITY_CLOCK_INFO) { + ALOGD("Found HAS_POSITION_VELOCITY_CLOCK_INFO"); + ASSERT_TRUE(satellitePvt.satPosEcef.posXMeters >= -kMaxOrbitRadiusMeters && + satellitePvt.satPosEcef.posXMeters <= kMaxOrbitRadiusMeters); + ASSERT_TRUE(satellitePvt.satPosEcef.posYMeters >= -kMaxOrbitRadiusMeters && + satellitePvt.satPosEcef.posYMeters <= kMaxOrbitRadiusMeters); + ASSERT_TRUE(satellitePvt.satPosEcef.posZMeters >= -kMaxOrbitRadiusMeters && + satellitePvt.satPosEcef.posZMeters <= kMaxOrbitRadiusMeters); + ASSERT_TRUE(satellitePvt.satPosEcef.ureMeters > 0); + ASSERT_TRUE(satellitePvt.satVelEcef.velXMps >= -kMaxVelocityMps && + satellitePvt.satVelEcef.velXMps <= kMaxVelocityMps); + ASSERT_TRUE(satellitePvt.satVelEcef.velYMps >= -kMaxVelocityMps && + satellitePvt.satVelEcef.velYMps <= kMaxVelocityMps); + ASSERT_TRUE(satellitePvt.satVelEcef.velZMps >= -kMaxVelocityMps && + satellitePvt.satVelEcef.velZMps <= kMaxVelocityMps); + ASSERT_TRUE(satellitePvt.satVelEcef.ureRateMps > 0); + ASSERT_TRUE( + satellitePvt.satClockInfo.satHardwareCodeBiasMeters > kMinHardwareCodeBiasMeters && + satellitePvt.satClockInfo.satHardwareCodeBiasMeters < kMaxHardwareCodeBiasMeters); + ASSERT_TRUE(satellitePvt.satClockInfo.satTimeCorrectionMeters > + -kMaxTimeCorrelationMeters && + satellitePvt.satClockInfo.satTimeCorrectionMeters < kMaxTimeCorrelationMeters); + ASSERT_TRUE(satellitePvt.satClockInfo.satClkDriftMps > -kMaxSatClkDriftMps && + satellitePvt.satClockInfo.satClkDriftMps < kMaxSatClkDriftMps); + } + if (satellitePvt.flags & SatellitePvt::HAS_IONO) { + ALOGD("Found HAS_IONO"); + ASSERT_TRUE(satellitePvt.ionoDelayMeters > 0 && satellitePvt.ionoDelayMeters < 100); + } + if (satellitePvt.flags & SatellitePvt::HAS_TROPO) { + ALOGD("Found HAS_TROPO"); + ASSERT_TRUE(satellitePvt.tropoDelayMeters > 0 && satellitePvt.tropoDelayMeters < 100); + } +} + +void CheckGnssMeasurementClockFields(const GnssData& measurement) { + ASSERT_TRUE(measurement.elapsedRealtime.flags >= 0 && + measurement.elapsedRealtime.flags <= (ElapsedRealtime::HAS_TIMESTAMP_NS | + ElapsedRealtime::HAS_TIME_UNCERTAINTY_NS)); + if (measurement.elapsedRealtime.flags & ElapsedRealtime::HAS_TIMESTAMP_NS) { + ASSERT_TRUE(measurement.elapsedRealtime.timestampNs > 0); + } + if (measurement.elapsedRealtime.flags & ElapsedRealtime::HAS_TIME_UNCERTAINTY_NS) { + ASSERT_TRUE(measurement.elapsedRealtime.timeUncertaintyNs > 0); + } + ASSERT_TRUE(measurement.clock.gnssClockFlags >= 0 && + measurement.clock.gnssClockFlags <= + (GnssClock::HAS_LEAP_SECOND | GnssClock::HAS_TIME_UNCERTAINTY | + GnssClock::HAS_FULL_BIAS | GnssClock::HAS_BIAS | + GnssClock::HAS_BIAS_UNCERTAINTY | GnssClock::HAS_DRIFT | + GnssClock::HAS_DRIFT_UNCERTAINTY)); +} + +void CheckGnssMeasurementFlags(const GnssMeasurement& measurement) { + ASSERT_TRUE(measurement.flags >= 0 && + measurement.flags <= + (GnssMeasurement::HAS_SNR | GnssMeasurement::HAS_CARRIER_FREQUENCY | + GnssMeasurement::HAS_CARRIER_CYCLES | GnssMeasurement::HAS_CARRIER_PHASE | + GnssMeasurement::HAS_CARRIER_PHASE_UNCERTAINTY | + GnssMeasurement::HAS_AUTOMATIC_GAIN_CONTROL | + GnssMeasurement::HAS_FULL_ISB | GnssMeasurement::HAS_FULL_ISB_UNCERTAINTY | + GnssMeasurement::HAS_SATELLITE_ISB | + GnssMeasurement::HAS_SATELLITE_ISB_UNCERTAINTY | + GnssMeasurement::HAS_SATELLITE_PVT | + GnssMeasurement::HAS_CORRELATION_VECTOR)); +} + +/* + * TestGnssMeasurementExtensionAndSatellitePvt: + * 1. Gets the GnssMeasurementExtension and verifies that it returns a non-null extension. + * 2. Sets a GnssMeasurementCallback, waits for a measurement, and verifies mandatory fields are + * valid. + * 3. If SatellitePvt is supported, waits for a measurement with SatellitePvt, and verifies the + * fields are valid. + */ +TEST_P(GnssHalTest, TestGnssMeasurementExtensionAndSatellitePvt) { + const bool kIsSatellitePvtSupported = + aidl_gnss_cb_->last_capabilities_ & (int)GnssCallbackAidl::CAPABILITY_SATELLITE_PVT; + ALOGD("SatellitePvt supported: %s", kIsSatellitePvtSupported ? "true" : "false"); + const int kFirstGnssMeasurementTimeoutSeconds = 10; + const int kNumMeasurementEvents = 75; + + sp iGnssMeasurement; + auto status = aidl_gnss_hal_->getExtensionGnssMeasurement(&iGnssMeasurement); + ASSERT_TRUE(status.isOk()); + ASSERT_TRUE(iGnssMeasurement != nullptr); + + auto callback = sp::make(); + status = iGnssMeasurement->setCallback(callback, /* enableFullTracking= */ true, + /* enableCorrVecOutputs */ false); + ASSERT_TRUE(status.isOk()); + + bool satellitePvtFound = false; + for (int i = 0; i < kNumMeasurementEvents; i++) { + if (i > 0 && (!kIsSatellitePvtSupported || satellitePvtFound)) { + break; + } + GnssData lastMeasurement; + ASSERT_TRUE(callback->gnss_data_cbq_.retrieve(lastMeasurement, + kFirstGnssMeasurementTimeoutSeconds)); + EXPECT_EQ(callback->gnss_data_cbq_.calledCount(), i + 1); + ASSERT_TRUE(lastMeasurement.measurements.size() > 0); + + // Validity check GnssData fields + CheckGnssMeasurementClockFields(lastMeasurement); + + for (const auto& measurement : lastMeasurement.measurements) { + CheckGnssMeasurementFlags(measurement); + if (measurement.flags & GnssMeasurement::HAS_SATELLITE_PVT && + kIsSatellitePvtSupported == true) { + ALOGD("Found a measurement with SatellitePvt"); + satellitePvtFound = true; + CheckSatellitePvt(measurement.satellitePvt); + } + } + } + if (kIsSatellitePvtSupported) { + ASSERT_TRUE(satellitePvtFound); + } + + status = iGnssMeasurement->close(); + ASSERT_TRUE(status.isOk()); +} + +/* + * TestCorrelationVector: + * 1. Gets the GnssMeasurementExtension and verifies that it returns a non-null extension. + * 2. Sets a GnssMeasurementCallback, waits for GnssMeasurements with CorrelationVector, and + * verifies fields are valid. + */ +TEST_P(GnssHalTest, TestCorrelationVector) { + const bool kIsCorrelationVectorSupported = aidl_gnss_cb_->last_capabilities_ & + (int)GnssCallbackAidl::CAPABILITY_CORRELATION_VECTOR; + const int kNumMeasurementEvents = 75; + // Pass the test if CorrelationVector is not supported + if (!kIsCorrelationVectorSupported) { + return; + } + + const int kFirstGnssMeasurementTimeoutSeconds = 10; + sp iGnssMeasurement; + auto status = aidl_gnss_hal_->getExtensionGnssMeasurement(&iGnssMeasurement); + ASSERT_TRUE(status.isOk()); + ASSERT_TRUE(iGnssMeasurement != nullptr); + + auto callback = sp::make(); + status = + iGnssMeasurement->setCallback(callback, /* enableFullTracking= */ true, + /* enableCorrVecOutputs */ kIsCorrelationVectorSupported); + ASSERT_TRUE(status.isOk()); + + bool correlationVectorFound = false; + for (int i = 0; i < kNumMeasurementEvents; i++) { + // Pass the test if at least one CorrelationVector has been found. + if (correlationVectorFound) { + break; + } + GnssData lastMeasurement; + ASSERT_TRUE(callback->gnss_data_cbq_.retrieve(lastMeasurement, + kFirstGnssMeasurementTimeoutSeconds)); + EXPECT_EQ(callback->gnss_data_cbq_.calledCount(), i + 1); + ASSERT_TRUE(lastMeasurement.measurements.size() > 0); + + // Validity check GnssData fields + CheckGnssMeasurementClockFields(lastMeasurement); + + for (const auto& measurement : lastMeasurement.measurements) { + CheckGnssMeasurementFlags(measurement); + if (measurement.flags & GnssMeasurement::HAS_CORRELATION_VECTOR) { + correlationVectorFound = true; + ASSERT_TRUE(measurement.correlationVectors.size() > 0); + for (const auto& correlationVector : measurement.correlationVectors) { + ASSERT_GE(correlationVector.frequencyOffsetMps, 0); + ASSERT_GT(correlationVector.samplingWidthM, 0); + ASSERT_TRUE(correlationVector.magnitude.size() > 0); + for (const auto& magnitude : correlationVector.magnitude) { + ASSERT_TRUE(magnitude >= -32768 && magnitude <= 32767); + } + } + } + } + } + ASSERT_TRUE(correlationVectorFound); + + status = iGnssMeasurement->close(); + ASSERT_TRUE(status.isOk()); +} + +/* + * TestGnssPowerIndication + * 1. Gets the GnssPowerIndicationExtension. + * 2. Sets a GnssPowerIndicationCallback. + * 3. Requests and verifies the 1st GnssPowerStats is received. + * 4. Gets a location. + * 5. Requests the 2nd GnssPowerStats, and verifies it has larger values than the 1st one. + */ +TEST_P(GnssHalTest, TestGnssPowerIndication) { + // Set up gnssPowerIndication and callback + sp iGnssPowerIndication; + auto status = aidl_gnss_hal_->getExtensionGnssPowerIndication(&iGnssPowerIndication); + ASSERT_TRUE(status.isOk()); + ASSERT_TRUE(iGnssPowerIndication != nullptr); + + auto gnssPowerIndicationCallback = sp::make(); + status = iGnssPowerIndication->setCallback(gnssPowerIndicationCallback); + ASSERT_TRUE(status.isOk()); + + const int kTimeoutSec = 2; + EXPECT_TRUE(gnssPowerIndicationCallback->capabilities_cbq_.retrieve( + gnssPowerIndicationCallback->last_capabilities_, kTimeoutSec)); + + EXPECT_EQ(gnssPowerIndicationCallback->capabilities_cbq_.calledCount(), 1); + + // Request and verify a GnssPowerStats is received + gnssPowerIndicationCallback->gnss_power_stats_cbq_.reset(); + iGnssPowerIndication->requestGnssPowerStats(); + + EXPECT_TRUE(gnssPowerIndicationCallback->gnss_power_stats_cbq_.retrieve( + gnssPowerIndicationCallback->last_gnss_power_stats_, kTimeoutSec)); + EXPECT_EQ(gnssPowerIndicationCallback->gnss_power_stats_cbq_.calledCount(), 1); + auto powerStats1 = gnssPowerIndicationCallback->last_gnss_power_stats_; + + // Get a location and request another GnssPowerStats + gnss_cb_->location_cbq_.reset(); + StartAndCheckFirstLocation(/* min_interval_msec= */ 1000, /* low_power_mode= */ false); + + // Request and verify the 2nd GnssPowerStats has larger values than the 1st one + iGnssPowerIndication->requestGnssPowerStats(); + + EXPECT_TRUE(gnssPowerIndicationCallback->gnss_power_stats_cbq_.retrieve( + gnssPowerIndicationCallback->last_gnss_power_stats_, kTimeoutSec)); + EXPECT_EQ(gnssPowerIndicationCallback->gnss_power_stats_cbq_.calledCount(), 2); + + auto powerStats2 = gnssPowerIndicationCallback->last_gnss_power_stats_; + + if ((gnssPowerIndicationCallback->last_capabilities_ & + (int)GnssPowerIndicationCallback::CAPABILITY_TOTAL)) { + // Elapsed realtime must increase + EXPECT_GT(powerStats2.elapsedRealtime.timestampNs, powerStats1.elapsedRealtime.timestampNs); + + // Total energy must increase + EXPECT_GT(powerStats2.totalEnergyMilliJoule, powerStats1.totalEnergyMilliJoule); + } + + // At least oone of singleband and multiband acquisition energy must increase + bool singlebandAcqEnergyIncreased = powerStats2.singlebandAcquisitionModeEnergyMilliJoule > + powerStats1.singlebandAcquisitionModeEnergyMilliJoule; + bool multibandAcqEnergyIncreased = powerStats2.multibandAcquisitionModeEnergyMilliJoule > + powerStats1.multibandAcquisitionModeEnergyMilliJoule; + + if ((gnssPowerIndicationCallback->last_capabilities_ & + (int)GnssPowerIndicationCallback::CAPABILITY_SINGLEBAND_ACQUISITION) || + (gnssPowerIndicationCallback->last_capabilities_ & + (int)GnssPowerIndicationCallback::CAPABILITY_MULTIBAND_ACQUISITION)) { + EXPECT_TRUE(singlebandAcqEnergyIncreased || multibandAcqEnergyIncreased); + } + + // At least one of singleband and multiband tracking energy must increase + bool singlebandTrackingEnergyIncreased = powerStats2.singlebandTrackingModeEnergyMilliJoule > + powerStats1.singlebandTrackingModeEnergyMilliJoule; + bool multibandTrackingEnergyIncreased = powerStats2.multibandTrackingModeEnergyMilliJoule > + powerStats1.multibandTrackingModeEnergyMilliJoule; + if ((gnssPowerIndicationCallback->last_capabilities_ & + (int)GnssPowerIndicationCallback::CAPABILITY_SINGLEBAND_TRACKING) || + (gnssPowerIndicationCallback->last_capabilities_ & + (int)GnssPowerIndicationCallback::CAPABILITY_MULTIBAND_TRACKING)) { + EXPECT_TRUE(singlebandTrackingEnergyIncreased || multibandTrackingEnergyIncreased); + } + + // Clean up + StopAndClearLocations(); +} + +/* + * FindStrongFrequentNonGpsSource: + * + * Search through a GnssSvStatus list for the strongest non-GPS satellite observed enough times + * + * returns the strongest source, + * or a source with constellation == UNKNOWN if none are found sufficient times + */ +BlocklistedSource FindStrongFrequentNonGpsSource( + const std::list> sv_info_list, + const int min_observations) { + struct ComparableBlocklistedSource { + BlocklistedSource id; + + ComparableBlocklistedSource() { + id.constellation = GnssConstellationTypeAidl::UNKNOWN; + id.svid = 0; + } + + bool operator<(const ComparableBlocklistedSource& compare) const { + return ((id.svid < compare.id.svid) || ((id.svid == compare.id.svid) && + (id.constellation < compare.id.constellation))); + } + }; + + struct SignalCounts { + int observations; + float max_cn0_dbhz; + }; + + std::map mapSignals; + + for (const auto& sv_info_vec : sv_info_list) { + for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) { + const auto& gnss_sv = sv_info_vec[iSv]; + if ((gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX) && + (gnss_sv.v2_0.constellation != GnssConstellationType::GPS)) { + ComparableBlocklistedSource source; + source.id.svid = gnss_sv.v2_0.v1_0.svid; + source.id.constellation = + static_cast(gnss_sv.v2_0.constellation); + + const auto& itSignal = mapSignals.find(source); + if (itSignal == mapSignals.end()) { + SignalCounts counts; + counts.observations = 1; + counts.max_cn0_dbhz = gnss_sv.v2_0.v1_0.cN0Dbhz; + mapSignals.insert( + std::pair(source, counts)); + } else { + itSignal->second.observations++; + if (itSignal->second.max_cn0_dbhz < gnss_sv.v2_0.v1_0.cN0Dbhz) { + itSignal->second.max_cn0_dbhz = gnss_sv.v2_0.v1_0.cN0Dbhz; + } + } + } + } + } + + float max_cn0_dbhz_with_sufficient_count = 0.; + int total_observation_count = 0; + int blocklisted_source_count_observation = 0; + + ComparableBlocklistedSource source_to_blocklist; // initializes to zero = UNKNOWN constellation + for (auto const& pairSignal : mapSignals) { + total_observation_count += pairSignal.second.observations; + if ((pairSignal.second.observations >= min_observations) && + (pairSignal.second.max_cn0_dbhz > max_cn0_dbhz_with_sufficient_count)) { + source_to_blocklist = pairSignal.first; + blocklisted_source_count_observation = pairSignal.second.observations; + max_cn0_dbhz_with_sufficient_count = pairSignal.second.max_cn0_dbhz; + } + } + ALOGD("Among %d observations, chose svid %d, constellation %d, " + "with %d observations at %.1f max CNo", + total_observation_count, source_to_blocklist.id.svid, + (int)source_to_blocklist.id.constellation, blocklisted_source_count_observation, + max_cn0_dbhz_with_sufficient_count); + + return source_to_blocklist.id; +} + +/* + * BlocklistIndividualSatellites: + * + * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding + * GnssStatus for common satellites (strongest and one other.) + * 2a & b) Turns off location, and blocklists common satellites. + * 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding + * GnssStatus does not use those satellites. + * 4a & b) Turns off location, and send in empty blocklist. + * 5a) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding + * GnssStatus does re-use at least the previously strongest satellite + * 5b) Retry a few times, in case GNSS search strategy takes a while to reacquire even the + * formerly strongest satellite + */ +TEST_P(GnssHalTest, BlocklistIndividualSatellites) { + if (!(aidl_gnss_cb_->last_capabilities_ & + (int)GnssCallbackAidl::CAPABILITY_SATELLITE_BLOCKLIST)) { + ALOGI("Test BlocklistIndividualSatellites skipped. SATELLITE_BLOCKLIST capability not " + "supported."); + return; + } + + const int kLocationsToAwait = 3; + const int kRetriesToUnBlocklist = 10; + + gnss_cb_->location_cbq_.reset(); + StartAndCheckLocations(kLocationsToAwait); + int location_called_count = gnss_cb_->location_cbq_.calledCount(); + + // Tolerate 1 less sv status to handle edge cases in reporting. + int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size(); + EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait); + ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations (%d received)", + sv_info_list_cbq_size, kLocationsToAwait, location_called_count); + + /* + * Identify strongest SV seen at least kLocationsToAwait -1 times + * Why -1? To avoid test flakiness in case of (plausible) slight flakiness in strongest signal + * observability (one epoch RF null) + */ + + const int kGnssSvInfoListTimeout = 2; + std::list> sv_info_vec_list; + int count = gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec_list, sv_info_list_cbq_size, + kGnssSvInfoListTimeout); + + ASSERT_EQ(count, sv_info_list_cbq_size); + + BlocklistedSource source_to_blocklist = + FindStrongFrequentNonGpsSource(sv_info_vec_list, kLocationsToAwait - 1); + + if (source_to_blocklist.constellation == GnssConstellationTypeAidl::UNKNOWN) { + // Cannot find a non-GPS satellite. Let the test pass. + ALOGD("Cannot find a non-GPS satellite. Letting the test pass."); + return; + } + + // Stop locations, blocklist the common SV + StopAndClearLocations(); + + sp gnss_configuration_hal; + auto status = aidl_gnss_hal_->getExtensionGnssConfiguration(&gnss_configuration_hal); + ASSERT_TRUE(status.isOk()); + ASSERT_NE(gnss_configuration_hal, nullptr); + + std::vector sources; + sources.resize(1); + sources[0] = source_to_blocklist; + + status = gnss_configuration_hal->setBlocklist(sources); + ASSERT_TRUE(status.isOk()); + + // retry and ensure satellite not used + gnss_cb_->sv_info_list_cbq_.reset(); + + gnss_cb_->location_cbq_.reset(); + StartAndCheckLocations(kLocationsToAwait); + + // early exit if test is being run with insufficient signal + location_called_count = gnss_cb_->location_cbq_.calledCount(); + if (location_called_count == 0) { + ALOGE("0 Gnss locations received - ensure sufficient signal and retry"); + } + ASSERT_TRUE(location_called_count > 0); + + // Tolerate 1 less sv status to handle edge cases in reporting. + sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size(); + EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait); + ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations (%d received)", + sv_info_list_cbq_size, kLocationsToAwait, location_called_count); + for (int i = 0; i < sv_info_list_cbq_size; ++i) { + hidl_vec sv_info_vec; + gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout); + for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) { + const auto& gnss_sv = sv_info_vec[iSv]; + EXPECT_FALSE((gnss_sv.v2_0.v1_0.svid == source_to_blocklist.svid) && + (static_cast(gnss_sv.v2_0.constellation) == + source_to_blocklist.constellation) && + (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX)); + } + } + + // clear blocklist and restart - this time updating the blocklist while location is still on + sources.resize(0); + + status = gnss_configuration_hal->setBlocklist(sources); + ASSERT_TRUE(status.isOk()); + + bool strongest_sv_is_reobserved = false; + // do several loops awaiting a few locations, allowing non-immediate reacquisition strategies + int unblocklist_loops_remaining = kRetriesToUnBlocklist; + while (!strongest_sv_is_reobserved && (unblocklist_loops_remaining-- > 0)) { + StopAndClearLocations(); + gnss_cb_->sv_info_list_cbq_.reset(); + + gnss_cb_->location_cbq_.reset(); + StartAndCheckLocations(kLocationsToAwait); + + // early exit loop if test is being run with insufficient signal + location_called_count = gnss_cb_->location_cbq_.calledCount(); + if (location_called_count == 0) { + ALOGE("0 Gnss locations received - ensure sufficient signal and retry"); + } + ASSERT_TRUE(location_called_count > 0); + + // Tolerate 1 less sv status to handle edge cases in reporting. + sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size(); + EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait); + ALOGD("Clear blocklist, observed %d GnssSvInfo, while awaiting %d Locations" + ", tries remaining %d", + sv_info_list_cbq_size, kLocationsToAwait, unblocklist_loops_remaining); + + for (int i = 0; i < sv_info_list_cbq_size; ++i) { + hidl_vec sv_info_vec; + gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout); + for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) { + const auto& gnss_sv = sv_info_vec[iSv]; + if ((gnss_sv.v2_0.v1_0.svid == source_to_blocklist.svid) && + (static_cast(gnss_sv.v2_0.constellation) == + source_to_blocklist.constellation) && + (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX)) { + strongest_sv_is_reobserved = true; + break; + } + } + if (strongest_sv_is_reobserved) break; + } + } + EXPECT_TRUE(strongest_sv_is_reobserved); + StopAndClearLocations(); +} + +/* + * BlocklistConstellationLocationOff: + * + * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding + * GnssStatus for any non-GPS constellations. + * 2a & b) Turns off location, and blocklist first non-GPS constellations. + * 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding + * GnssStatus does not use any constellation but GPS. + * 4a & b) Clean up by turning off location, and send in empty blocklist. + */ +TEST_P(GnssHalTest, BlocklistConstellationLocationOff) { + if (!(aidl_gnss_cb_->last_capabilities_ & + (int)GnssCallbackAidl::CAPABILITY_SATELLITE_BLOCKLIST)) { + ALOGI("Test BlocklistConstellationLocationOff skipped. SATELLITE_BLOCKLIST capability not " + "supported."); + return; + } + + const int kLocationsToAwait = 3; + const int kGnssSvInfoListTimeout = 2; + + // Find first non-GPS constellation to blocklist + GnssConstellationTypeAidl constellation_to_blocklist = static_cast( + startLocationAndGetNonGpsConstellation(kLocationsToAwait, kGnssSvInfoListTimeout)); + + // Turns off location + StopAndClearLocations(); + + BlocklistedSource source_to_blocklist_1; + source_to_blocklist_1.constellation = constellation_to_blocklist; + source_to_blocklist_1.svid = 0; // documented wildcard for all satellites in this constellation + + // IRNSS was added in 2.0. Always attempt to blocklist IRNSS to verify that the new enum is + // supported. + BlocklistedSource source_to_blocklist_2; + source_to_blocklist_2.constellation = GnssConstellationTypeAidl::IRNSS; + source_to_blocklist_2.svid = 0; // documented wildcard for all satellites in this constellation + + sp gnss_configuration_hal; + auto status = aidl_gnss_hal_->getExtensionGnssConfiguration(&gnss_configuration_hal); + ASSERT_TRUE(status.isOk()); + ASSERT_NE(gnss_configuration_hal, nullptr); + + hidl_vec sources; + sources.resize(2); + sources[0] = source_to_blocklist_1; + sources[1] = source_to_blocklist_2; + + status = gnss_configuration_hal->setBlocklist(sources); + ASSERT_TRUE(status.isOk()); + + // retry and ensure constellation not used + gnss_cb_->sv_info_list_cbq_.reset(); + + gnss_cb_->location_cbq_.reset(); + StartAndCheckLocations(kLocationsToAwait); + + // Tolerate 1 less sv status to handle edge cases in reporting. + int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size(); + EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait); + ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations", sv_info_list_cbq_size, + kLocationsToAwait); + for (int i = 0; i < sv_info_list_cbq_size; ++i) { + hidl_vec sv_info_vec; + gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout); + for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) { + const auto& gnss_sv = sv_info_vec[iSv]; + EXPECT_FALSE((static_cast(gnss_sv.v2_0.constellation) == + source_to_blocklist_1.constellation) && + (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX)); + EXPECT_FALSE((static_cast(gnss_sv.v2_0.constellation) == + source_to_blocklist_2.constellation) && + (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX)); + } + } + + // clean up + StopAndClearLocations(); + sources.resize(0); + status = gnss_configuration_hal->setBlocklist(sources); + ASSERT_TRUE(status.isOk()); +} + +/* + * BlocklistConstellationLocationOn: + * + * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding + * GnssStatus for any non-GPS constellations. + * 2a & b) Blocklist first non-GPS constellation, and turn off location. + * 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding + * GnssStatus does not use any constellation but GPS. + * 4a & b) Clean up by turning off location, and send in empty blocklist. + */ +TEST_P(GnssHalTest, BlocklistConstellationLocationOn) { + if (!(aidl_gnss_cb_->last_capabilities_ & + (int)GnssCallbackAidl::CAPABILITY_SATELLITE_BLOCKLIST)) { + ALOGI("Test BlocklistConstellationLocationOn skipped. SATELLITE_BLOCKLIST capability not " + "supported."); + return; + } + + const int kLocationsToAwait = 3; + const int kGnssSvInfoListTimeout = 2; + + // Find first non-GPS constellation to blocklist + GnssConstellationTypeAidl constellation_to_blocklist = static_cast( + startLocationAndGetNonGpsConstellation(kLocationsToAwait, kGnssSvInfoListTimeout)); + + BlocklistedSource source_to_blocklist_1; + source_to_blocklist_1.constellation = constellation_to_blocklist; + source_to_blocklist_1.svid = 0; // documented wildcard for all satellites in this constellation + + // IRNSS was added in 2.0. Always attempt to blocklist IRNSS to verify that the new enum is + // supported. + BlocklistedSource source_to_blocklist_2; + source_to_blocklist_2.constellation = GnssConstellationTypeAidl::IRNSS; + source_to_blocklist_2.svid = 0; // documented wildcard for all satellites in this constellation + + sp gnss_configuration_hal; + auto status = aidl_gnss_hal_->getExtensionGnssConfiguration(&gnss_configuration_hal); + ASSERT_TRUE(status.isOk()); + ASSERT_NE(gnss_configuration_hal, nullptr); + + hidl_vec sources; + sources.resize(2); + sources[0] = source_to_blocklist_1; + sources[1] = source_to_blocklist_2; + + status = gnss_configuration_hal->setBlocklist(sources); + ASSERT_TRUE(status.isOk()); + + // Turns off location + StopAndClearLocations(); + + // retry and ensure constellation not used + gnss_cb_->sv_info_list_cbq_.reset(); + + gnss_cb_->location_cbq_.reset(); + StartAndCheckLocations(kLocationsToAwait); + + // Tolerate 1 less sv status to handle edge cases in reporting. + int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size(); + EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait); + ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations", sv_info_list_cbq_size, + kLocationsToAwait); + for (int i = 0; i < sv_info_list_cbq_size; ++i) { + hidl_vec sv_info_vec; + gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout); + for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) { + const auto& gnss_sv = sv_info_vec[iSv]; + EXPECT_FALSE((static_cast(gnss_sv.v2_0.constellation) == + source_to_blocklist_1.constellation) && + (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX)); + EXPECT_FALSE((static_cast(gnss_sv.v2_0.constellation) == + source_to_blocklist_2.constellation) && + (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX)); + } + } + + // clean up + StopAndClearLocations(); + sources.resize(0); + status = gnss_configuration_hal->setBlocklist(sources); + ASSERT_TRUE(status.isOk()); +} diff --git a/gnss/common/utils/default/Android.bp b/gnss/common/utils/default/Android.bp index fb83a269b2a0fcbc84ec572f51b62e2f9394caa6..a1d31235006d2a6fdeb0760855e01f8283f6bd7e 100644 --- a/gnss/common/utils/default/Android.bp +++ b/gnss/common/utils/default/Android.bp @@ -33,14 +33,25 @@ cc_library_static { "-Werror", ], srcs: [ + "v2_1/GnssAntennaInfo.cpp", + "v2_1/GnssConfiguration.cpp", + "v2_1/GnssDebug.cpp", + "v2_1/GnssMeasurement.cpp", + "v2_1/GnssMeasurementCorrections.cpp", + "MockLocation.cpp", "Utils.cpp", + "NmeaFixInfo.cpp", ], export_include_dirs: ["include"], shared_libs: [ + "libcutils", "libhidlbase", "libutils", "android.hardware.gnss@1.0", "android.hardware.gnss@2.0", "android.hardware.gnss@2.1", + "android.hardware.gnss.measurement_corrections@1.1", + "android.hardware.gnss.measurement_corrections@1.0", + "android.hardware.gnss-V1-ndk", ], } diff --git a/gnss/common/utils/default/MockLocation.cpp b/gnss/common/utils/default/MockLocation.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c90075fa8471b8620a1f238ed93cc5b92768194a --- /dev/null +++ b/gnss/common/utils/default/MockLocation.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "MockLocation.h" + +namespace android::hardware::gnss::common { + +float gMockLatitudeDegrees{37.4219999}; +float gMockLongitudeDegrees{-122.0840575}; +float gMockAltitudeMeters{1.60062531}; +float gMockBearingDegrees{0}; +float gMockSpeedMetersPerSec{0}; + +} // namespace android::hardware::gnss::common diff --git a/gnss/common/utils/default/NmeaFixInfo.cpp b/gnss/common/utils/default/NmeaFixInfo.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c7ee13488b3af7938922ccba4e3c9c65444f35a0 --- /dev/null +++ b/gnss/common/utils/default/NmeaFixInfo.cpp @@ -0,0 +1,273 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "NmeaFixInfo" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace common { + +NmeaFixInfo::NmeaFixInfo() : hasGMCRecord(false), hasGGARecord(false) {} + +float NmeaFixInfo::getAltitudeMeters() const { + return altitudeMeters; +} + +float NmeaFixInfo::checkAndConvertToFloat(const std::string& sentence) { + if (sentence.empty()) { + return std::numeric_limits::quiet_NaN(); + } + return std::stof(sentence); +} + +float NmeaFixInfo::getBearingAccuracyDegrees() const { + // Current NMEA doesn't contains beaing accuracy inforamtion + return kMockBearingAccuracyDegrees; +} +float NmeaFixInfo::getBearingDegrees() const { + return bearingDegrees; +} + +float NmeaFixInfo::getHorizontalAccuracyMeters() const { + // Current NMEA doesn't contains horizontal accuracy inforamtion + return kMockHorizontalAccuracyMeters; +} + +float NmeaFixInfo::getLatDeg() const { + return latDeg; +} + +float NmeaFixInfo::getLngDeg() const { + return lngDeg; +} + +float NmeaFixInfo::getSpeedAccuracyMetersPerSecond() const { + // Current NMEA doesn't contains speed accuracy inforamtion + return kMockSpeedAccuracyMetersPerSecond; +} + +float NmeaFixInfo::getSpeedMetersPerSec() const { + return speedMetersPerSec; +} + +int64_t NmeaFixInfo::getTimestamp() const { + return timestamp; +} + +float NmeaFixInfo::getVerticalAccuracyMeters() const { + // Current NMEA doesn't contains vertical accuracy inforamtion + return kMockVerticalAccuracyMeters; +} + +int64_t NmeaFixInfo::nmeaPartsToTimestamp(const std::string& timeStr, const std::string& dateStr) { + /** + * In NMEA format, the full time can only get from the $GPRMC record, see + * the following example: + * $GPRMC,213204.00,A,3725.371240,N,12205.589239,W,000.0,000.0,290819,,,A*49 + * the datetime is stored in two parts, 213204 and 290819, which means + * 2019/08/29 21:32:04, however for in unix the year starts from 1900, we + * need to add the offset. + */ + struct tm tm; + const int32_t unixYearOffset = 100; + tm.tm_mday = std::stoi(dateStr.substr(0, 2).c_str()); + tm.tm_mon = std::stoi(dateStr.substr(2, 2).c_str()) - 1; + tm.tm_year = std::stoi(dateStr.substr(4, 2).c_str()) + unixYearOffset; + tm.tm_hour = std::stoi(timeStr.substr(0, 2).c_str()); + tm.tm_min = std::stoi(timeStr.substr(2, 2).c_str()); + tm.tm_sec = std::stoi(timeStr.substr(4, 2).c_str()); + return static_cast(mktime(&tm) - timezone); +} + +bool NmeaFixInfo::isValidFix() const { + return hasGMCRecord && hasGGARecord; +} + +void NmeaFixInfo::parseGGALine(const std::vector& sentenceValues) { + if (sentenceValues.size() == 0 || sentenceValues[0].compare(GPGA_RECORD_TAG) != 0) { + return; + } + // LatDeg, need covert to degree, if it is 'N', should be negative value + this->latDeg = std::stof(sentenceValues[2].substr(0, 2)) + + (std::stof(sentenceValues[2].substr(2)) / 60.0); + if (sentenceValues[3].compare("N") != 0) { + this->latDeg *= -1; + } + + // LngDeg, need covert to degree, if it is 'E', should be negative value + this->lngDeg = std::stof(sentenceValues[4].substr(0, 3)) + + std::stof(sentenceValues[4].substr(3)) / 60.0; + if (sentenceValues[5].compare("E") != 0) { + this->lngDeg *= -1; + } + + this->altitudeMeters = std::stof(sentenceValues[9]); + + this->hDop = sentenceValues[8].empty() ? std::numeric_limits::quiet_NaN() + : std::stof(sentenceValues[8]); + this->hasGGARecord = true; +} + +void NmeaFixInfo::parseRMCLine(const std::vector& sentenceValues) { + if (sentenceValues.size() == 0 || sentenceValues[0].compare(GPRMC_RECORD_TAG) != 0) { + return; + } + this->speedMetersPerSec = checkAndConvertToFloat(sentenceValues[7]); + this->bearingDegrees = checkAndConvertToFloat(sentenceValues[8]); + this->timestamp = nmeaPartsToTimestamp(sentenceValues[1], sentenceValues[9]); + this->hasGMCRecord = true; +} + +/** invalid the current NmeaFixInfo */ +void NmeaFixInfo::reset() { + this->altitudeMeters = 0; + this->bearingDegrees = 0; + this->fixId = 0; + this->hasGMCRecord = false; + this->hasGGARecord = false; + this->latDeg = 0; + this->lngDeg = 0; + this->hDop = 0; + this->vDop = 0; + this->satelliteCount = 0; + this->speedMetersPerSec = 0; + this->timestamp = 0; +} + +void NmeaFixInfo::splitStr(const std::string& line, const char& delimiter, + std::vector& out) { + std::istringstream iss(line); + std::string item; + while (std::getline(iss, item, delimiter)) { + out.push_back(item); + } +} + +NmeaFixInfo& NmeaFixInfo::operator=(const NmeaFixInfo& rhs) { + if (this == &rhs) return *this; + this->altitudeMeters = rhs.altitudeMeters; + this->bearingDegrees = rhs.bearingDegrees; + this->fixId = rhs.fixId; + this->hasGMCRecord = rhs.hasGMCRecord; + this->hasGGARecord = rhs.hasGGARecord; + this->hDop = rhs.hDop; + this->vDop = rhs.vDop; + this->latDeg = rhs.latDeg; + this->lngDeg = rhs.lngDeg; + this->satelliteCount = rhs.satelliteCount; + this->speedMetersPerSec = rhs.speedMetersPerSec; + this->timestamp = rhs.timestamp; + + return *this; +} + +/** + * Parses the input string in NMEA format and convert to GnssLocation. + * Currently version only cares about $GPGGA and $GPRMC records. but we + * can easily extend to other types supported by NMEA if needed. + */ +std::unique_ptr NmeaFixInfo::getLocationFromInputStr( + const std::string& inputStr) { + std::vector nmeaRecords; + splitStr(inputStr, LINE_SEPARATOR, nmeaRecords); + NmeaFixInfo nmeaFixInfo; + NmeaFixInfo candidateFixInfo; + uint32_t fixId = 0; + double lastTimeStamp = 0; + for (const auto& line : nmeaRecords) { + if (line.compare(0, strlen(GPGA_RECORD_TAG), GPGA_RECORD_TAG) != 0 && + line.compare(0, strlen(GPRMC_RECORD_TAG), GPRMC_RECORD_TAG) != 0) { + continue; + } + std::vector sentenceValues; + splitStr(line, COMMA_SEPARATOR, sentenceValues); + if (sentenceValues.size() < MIN_COL_NUM) { + continue; + } + double currentTimeStamp = std::stof(sentenceValues[1]); + // If see a new timestamp, report correct location. + if ((currentTimeStamp - lastTimeStamp) > TIMESTAMP_EPSILON && + candidateFixInfo.isValidFix()) { + nmeaFixInfo = candidateFixInfo; + candidateFixInfo.reset(); + fixId++; + } + if (line.compare(0, strlen(GPGA_RECORD_TAG), GPGA_RECORD_TAG) == 0) { + candidateFixInfo.fixId = fixId; + candidateFixInfo.parseGGALine(sentenceValues); + } else if (line.compare(0, strlen(GPRMC_RECORD_TAG), GPRMC_RECORD_TAG) == 0) { + candidateFixInfo.parseRMCLine(sentenceValues); + } + } + if (candidateFixInfo.isValidFix()) { + nmeaFixInfo = candidateFixInfo; + candidateFixInfo.reset(); + } + if (!nmeaFixInfo.isValidFix()) { + return nullptr; + } + return nmeaFixInfo.toGnssLocation(); +} + +/** + * Parses the input string in NMEA format and convert to GnssLocation. + */ +std::unique_ptr NmeaFixInfo::toGnssLocation() const { + const V2_0::ElapsedRealtime currentOsTimestamp = { + .flags = V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS | + V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS, + .timestampNs = static_cast(::android::elapsedRealtimeNano()), + // This is an hardcoded value indicating a 1ms of uncertainty between the two clocks. + // In an actual implementation provide an estimate of the synchronization uncertainty + // or don't set the field. + .timeUncertaintyNs = 1000000}; + + V1_0::GnssLocation locationV1 = { + .gnssLocationFlags = 0xFF, + .latitudeDegrees = this->getLatDeg(), + .longitudeDegrees = this->getLngDeg(), + .altitudeMeters = this->getAltitudeMeters(), + .speedMetersPerSec = this->getSpeedMetersPerSec(), + .bearingDegrees = this->getBearingDegrees(), + .horizontalAccuracyMeters = this->getHorizontalAccuracyMeters(), + .verticalAccuracyMeters = this->getVerticalAccuracyMeters(), + .speedAccuracyMetersPerSecond = this->getSpeedAccuracyMetersPerSecond(), + .bearingAccuracyDegrees = this->getBearingAccuracyDegrees(), + .timestamp = this->getTimestamp()}; + + V2_0::GnssLocation locationV2 = {.v1_0 = locationV1, .elapsedRealtime = currentOsTimestamp}; + + return std::make_unique(locationV2); +} + +} // namespace common +} // namespace gnss +} // namespace hardware +} // namespace android \ No newline at end of file diff --git a/gnss/common/utils/default/Utils.cpp b/gnss/common/utils/default/Utils.cpp index 386090e4866906d15d1b867a4f692219a726c76e..23e39b26ec59884c5c5f00cdfb9998d45047079e 100644 --- a/gnss/common/utils/default/Utils.cpp +++ b/gnss/common/utils/default/Utils.cpp @@ -15,7 +15,9 @@ */ #include +#include #include +#include #include namespace android { @@ -23,16 +25,32 @@ namespace hardware { namespace gnss { namespace common { +using aidl::android::hardware::gnss::ElapsedRealtime; +using aidl::android::hardware::gnss::GnssClock; +using aidl::android::hardware::gnss::GnssData; +using aidl::android::hardware::gnss::GnssMeasurement; +using aidl::android::hardware::gnss::IGnss; +using aidl::android::hardware::gnss::IGnssMeasurementCallback; +using aidl::android::hardware::gnss::SatellitePvt; + using GnssSvFlags = V1_0::IGnssCallback::GnssSvFlags; using GnssMeasurementFlagsV1_0 = V1_0::IGnssMeasurementCallback::GnssMeasurementFlags; using GnssMeasurementFlagsV2_1 = V2_1::IGnssMeasurementCallback::GnssMeasurementFlags; using GnssMeasurementStateV2_0 = V2_0::IGnssMeasurementCallback::GnssMeasurementState; -using ElapsedRealtime = V2_0::ElapsedRealtime; using ElapsedRealtimeFlags = V2_0::ElapsedRealtimeFlags; using GnssConstellationTypeV2_0 = V2_0::GnssConstellationType; using IGnssMeasurementCallbackV2_0 = V2_0::IGnssMeasurementCallback; using GnssSignalType = V2_1::GnssSignalType; +using GnssDataV2_0 = V2_0::IGnssMeasurementCallback::GnssData; +using GnssDataV2_1 = V2_1::IGnssMeasurementCallback::GnssData; +using GnssSvInfoV1_0 = V1_0::IGnssCallback::GnssSvInfo; +using GnssSvInfoV2_0 = V2_0::IGnssCallback::GnssSvInfo; +using GnssSvInfoV2_1 = V2_1::IGnssCallback::GnssSvInfo; +using GnssAntennaInfo = ::android::hardware::gnss::V2_1::IGnssAntennaInfoCallback::GnssAntennaInfo; +using Row = V2_1::IGnssAntennaInfoCallback::Row; +using Coord = V2_1::IGnssAntennaInfoCallback::Coord; + GnssDataV2_1 Utils::getMockMeasurementV2_1() { GnssDataV2_0 gnssDataV2_0 = Utils::getMockMeasurementV2_0(); V2_1::IGnssMeasurementCallback::GnssMeasurement gnssMeasurementV2_1 = { @@ -109,7 +127,7 @@ GnssDataV2_0 Utils::getMockMeasurementV2_0() { .driftUncertaintyNsps = 310.64968328491528, .hwClockDiscontinuityCount = 1}; - ElapsedRealtime timestamp = { + V2_0::ElapsedRealtime timestamp = { .flags = ElapsedRealtimeFlags::HAS_TIMESTAMP_NS | ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS, .timestampNs = static_cast(::android::elapsedRealtimeNano()), @@ -123,6 +141,97 @@ GnssDataV2_0 Utils::getMockMeasurementV2_0() { return gnssData; } +GnssData Utils::getMockMeasurement(const bool enableCorrVecOutputs) { + aidl::android::hardware::gnss::GnssSignalType signalType = { + .constellation = aidl::android::hardware::gnss::GnssConstellationType::GLONASS, + .carrierFrequencyHz = 1.59975e+09, + .codeType = aidl::android::hardware::gnss::GnssSignalType::CODE_TYPE_C, + }; + GnssMeasurement measurement = { + .flags = GnssMeasurement::HAS_AUTOMATIC_GAIN_CONTROL | + GnssMeasurement::HAS_CARRIER_FREQUENCY | GnssMeasurement::HAS_CARRIER_PHASE | + GnssMeasurement::HAS_CARRIER_PHASE_UNCERTAINTY | + GnssMeasurement::HAS_FULL_ISB | GnssMeasurement::HAS_FULL_ISB_UNCERTAINTY | + GnssMeasurement::HAS_SATELLITE_ISB | + GnssMeasurement::HAS_SATELLITE_ISB_UNCERTAINTY | + GnssMeasurement::HAS_SATELLITE_PVT, + .svid = 13, + .signalType = signalType, + .receivedSvTimeInNs = 8195997131077, + .receivedSvTimeUncertaintyInNs = 15, + .antennaCN0DbHz = 30.0, + .basebandCN0DbHz = 26.5, + .agcLevelDb = 2.3, + .pseudorangeRateMps = -484.13739013671875, + .pseudorangeRateUncertaintyMps = 1.0379999876022339, + .accumulatedDeltaRangeState = GnssMeasurement::ADR_STATE_UNKNOWN, + .accumulatedDeltaRangeM = 1.52, + .accumulatedDeltaRangeUncertaintyM = 2.43, + .multipathIndicator = aidl::android::hardware::gnss::GnssMultipathIndicator::UNKNOWN, + .state = GnssMeasurement::STATE_CODE_LOCK | GnssMeasurement::STATE_BIT_SYNC | + GnssMeasurement::STATE_SUBFRAME_SYNC | GnssMeasurement::STATE_TOW_DECODED | + GnssMeasurement::STATE_GLO_STRING_SYNC | + GnssMeasurement::STATE_GLO_TOD_DECODED, + .fullInterSignalBiasNs = 21.5, + .fullInterSignalBiasUncertaintyNs = 792.0, + .satelliteInterSignalBiasNs = 233.9, + .satelliteInterSignalBiasUncertaintyNs = 921.2, + .satellitePvt = {.flags = SatellitePvt::HAS_POSITION_VELOCITY_CLOCK_INFO | + SatellitePvt::HAS_IONO | SatellitePvt::HAS_TROPO, + .satPosEcef = {.posXMeters = 10442993.1153328, + .posYMeters = -19926932.8051666, + .posZMeters = -12034295.0216203, + .ureMeters = 1000.2345678}, + .satVelEcef = {.velXMps = -478.667183715732, + .velYMps = 1580.68371984114, + .velZMps = -3030.52994449997, + .ureRateMps = 10.2345678}, + .satClockInfo = {.satHardwareCodeBiasMeters = 1.396983861923e-09, + .satTimeCorrectionMeters = -7113.08964331, + .satClkDriftMps = 0}, + .ionoDelayMeters = 3.069949602639317e-08, + .tropoDelayMeters = 3.882265204404031}, + .correlationVectors = {}}; + + GnssClock clock = {.gnssClockFlags = GnssClock::HAS_FULL_BIAS | GnssClock::HAS_BIAS | + GnssClock::HAS_BIAS_UNCERTAINTY | GnssClock::HAS_DRIFT | + GnssClock::HAS_DRIFT_UNCERTAINTY, + .timeNs = 35854545000000, + .fullBiasNs = -234621900521857520, + .biasNs = 0.2352389998626708984, + .biasUncertaintyNs = 274.989972114563, + .driftNsps = -124.3742360, + .driftUncertaintyNsps = 239.6234285828, + .hwClockDiscontinuityCount = 999}; + + ElapsedRealtime timestamp = { + .flags = ElapsedRealtime::HAS_TIMESTAMP_NS | ElapsedRealtime::HAS_TIME_UNCERTAINTY_NS, + .timestampNs = ::android::elapsedRealtimeNano(), + // This is an hardcoded value indicating a 1ms of uncertainty between the two clocks. + // In an actual implementation provide an estimate of the synchronization uncertainty + // or don't set the field. + .timeUncertaintyNs = 1020400}; + + if (enableCorrVecOutputs) { + aidl::android::hardware::gnss::CorrelationVector correlationVector1 = { + .frequencyOffsetMps = 10, + .samplingWidthM = 30, + .samplingStartM = 0, + .magnitude = {0, 5000, 10000, 5000, 0, 0, 3000, 0}}; + aidl::android::hardware::gnss::CorrelationVector correlationVector2 = { + .frequencyOffsetMps = 20, + .samplingWidthM = 30, + .samplingStartM = -10, + .magnitude = {0, 3000, 5000, 3000, 0, 0, 1000, 0}}; + measurement.correlationVectors = {correlationVector1, correlationVector2}; + measurement.flags |= GnssMeasurement::HAS_CORRELATION_VECTOR; + } + + GnssData gnssData = { + .measurements = {measurement}, .clock = clock, .elapsedRealtime = timestamp}; + return gnssData; +} + V2_0::GnssLocation Utils::getMockLocationV2_0() { const V2_0::ElapsedRealtime timestamp = { .flags = V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS | @@ -141,64 +250,65 @@ V2_0::GnssLocation Utils::getMockLocationV2_0() { V1_0::GnssLocation Utils::getMockLocationV1_0() { V1_0::GnssLocation location = { .gnssLocationFlags = 0xFF, - .latitudeDegrees = kMockLatitudeDegrees, - .longitudeDegrees = kMockLongitudeDegrees, - .altitudeMeters = kMockAltitudeMeters, - .speedMetersPerSec = kMockSpeedMetersPerSec, - .bearingDegrees = kMockBearingDegrees, + .latitudeDegrees = gMockLatitudeDegrees, + .longitudeDegrees = gMockLongitudeDegrees, + .altitudeMeters = gMockAltitudeMeters, + .speedMetersPerSec = gMockSpeedMetersPerSec, + .bearingDegrees = gMockBearingDegrees, .horizontalAccuracyMeters = kMockHorizontalAccuracyMeters, .verticalAccuracyMeters = kMockVerticalAccuracyMeters, .speedAccuracyMetersPerSecond = kMockSpeedAccuracyMetersPerSecond, .bearingAccuracyDegrees = kMockBearingAccuracyDegrees, - .timestamp = kMockTimestamp}; + .timestamp = + static_cast(kMockTimestamp + ::android::elapsedRealtimeNano() / 1e6)}; return location; } hidl_vec Utils::getMockSvInfoListV2_1() { - GnssSvInfoV1_0 gnssSvInfoV1_0 = - Utils::getMockSvInfoV1_0(3, V1_0::GnssConstellationType::GPS, 32.5, 59.1, 166.5); + GnssSvInfoV1_0 gnssSvInfoV1_0 = Utils::getMockSvInfoV1_0(3, V1_0::GnssConstellationType::GPS, + 32.5, 59.1, 166.5, kGpsL1FreqHz); GnssSvInfoV2_0 gnssSvInfoV2_0 = Utils::getMockSvInfoV2_0(gnssSvInfoV1_0, V2_0::GnssConstellationType::GPS); hidl_vec gnssSvInfoList = { Utils::getMockSvInfoV2_1(gnssSvInfoV2_0, 27.5), getMockSvInfoV2_1( getMockSvInfoV2_0(getMockSvInfoV1_0(5, V1_0::GnssConstellationType::GPS, 27.0, - 29.0, 56.5), + 29.0, 56.5, kGpsL1FreqHz), V2_0::GnssConstellationType::GPS), 22.0), getMockSvInfoV2_1( getMockSvInfoV2_0(getMockSvInfoV1_0(17, V1_0::GnssConstellationType::GPS, 30.5, - 71.0, 77.0), + 71.0, 77.0, kGpsL5FreqHz), V2_0::GnssConstellationType::GPS), 25.5), getMockSvInfoV2_1( getMockSvInfoV2_0(getMockSvInfoV1_0(26, V1_0::GnssConstellationType::GPS, 24.1, - 28.0, 253.0), + 28.0, 253.0, kGpsL5FreqHz), V2_0::GnssConstellationType::GPS), 19.1), getMockSvInfoV2_1( getMockSvInfoV2_0(getMockSvInfoV1_0(5, V1_0::GnssConstellationType::GLONASS, - 20.5, 11.5, 116.0), + 20.5, 11.5, 116.0, kGloG1FreqHz), V2_0::GnssConstellationType::GLONASS), 15.5), getMockSvInfoV2_1( getMockSvInfoV2_0(getMockSvInfoV1_0(17, V1_0::GnssConstellationType::GLONASS, - 21.5, 28.5, 186.0), + 21.5, 28.5, 186.0, kGloG1FreqHz), V2_0::GnssConstellationType::GLONASS), 16.5), getMockSvInfoV2_1( getMockSvInfoV2_0(getMockSvInfoV1_0(18, V1_0::GnssConstellationType::GLONASS, - 28.3, 38.8, 69.0), + 28.3, 38.8, 69.0, kGloG1FreqHz), V2_0::GnssConstellationType::GLONASS), 25.3), getMockSvInfoV2_1( getMockSvInfoV2_0(getMockSvInfoV1_0(10, V1_0::GnssConstellationType::GLONASS, - 25.0, 66.0, 247.0), + 25.0, 66.0, 247.0, kGloG1FreqHz), V2_0::GnssConstellationType::GLONASS), 20.0), getMockSvInfoV2_1( getMockSvInfoV2_0(getMockSvInfoV1_0(3, V1_0::GnssConstellationType::UNKNOWN, - 22.0, 35.0, 112.0), + 22.0, 35.0, 112.0, kIrnssL5FreqHz), V2_0::GnssConstellationType::IRNSS), 19.7), }; @@ -223,21 +333,23 @@ GnssSvInfoV2_0 Utils::getMockSvInfoV2_0(GnssSvInfoV1_0 gnssSvInfoV1_0, } GnssSvInfoV1_0 Utils::getMockSvInfoV1_0(int16_t svid, V1_0::GnssConstellationType type, - float cN0DbHz, float elevationDegrees, - float azimuthDegrees) { + float cN0DbHz, float elevationDegrees, float azimuthDegrees, + float carrierFrequencyHz) { GnssSvInfoV1_0 svInfo = {.svid = svid, .constellation = type, .cN0Dbhz = cN0DbHz, .elevationDegrees = elevationDegrees, .azimuthDegrees = azimuthDegrees, + .carrierFrequencyHz = carrierFrequencyHz, .svFlag = GnssSvFlags::USED_IN_FIX | GnssSvFlags::HAS_EPHEMERIS_DATA | - GnssSvFlags::HAS_ALMANAC_DATA}; + GnssSvFlags::HAS_ALMANAC_DATA | + GnssSvFlags::HAS_CARRIER_FREQUENCY}; return svInfo; } hidl_vec Utils::getMockAntennaInfos() { GnssAntennaInfo mockAntennaInfo_1 = { - .carrierFrequencyMHz = 123412.12, + .carrierFrequencyMHz = kGpsL1FreqHz * 1e-6, .phaseCenterOffsetCoordinateMillimeters = Coord{.x = 1, .xUncertainty = 0.1, .y = 2, @@ -271,7 +383,7 @@ hidl_vec Utils::getMockAntennaInfos() { }; GnssAntennaInfo mockAntennaInfo_2 = { - .carrierFrequencyMHz = 532324.23, + .carrierFrequencyMHz = kGpsL5FreqHz * 1e-6, .phaseCenterOffsetCoordinateMillimeters = Coord{.x = 5, .xUncertainty = 0.1, .y = 6, diff --git a/gnss/common/utils/default/include/Constants.h b/gnss/common/utils/default/include/Constants.h index 000a9ec7d25d512ee9281844653a03c78c1b171e..22afee1ad1e0c8004599232feab65d0bd876a262 100644 --- a/gnss/common/utils/default/include/Constants.h +++ b/gnss/common/utils/default/include/Constants.h @@ -24,16 +24,15 @@ namespace hardware { namespace gnss { namespace common { -const float kMockLatitudeDegrees = 37.4219999; -const float kMockLongitudeDegrees = -122.0840575; -const float kMockAltitudeMeters = 1.60062531; -const float kMockSpeedMetersPerSec = 0; -const float kMockBearingDegrees = 0; const float kMockHorizontalAccuracyMeters = 5; const float kMockVerticalAccuracyMeters = 5; const float kMockSpeedAccuracyMetersPerSecond = 1; const float kMockBearingAccuracyDegrees = 90; const int64_t kMockTimestamp = 1519930775453L; +const float kGpsL1FreqHz = 1575.42 * 1e6; +const float kGpsL5FreqHz = 1176.45 * 1e6; +const float kGloG1FreqHz = 1602.0 * 1e6; +const float kIrnssL5FreqHz = 1176.45 * 1e6; } // namespace common } // namespace gnss diff --git a/gnss/common/utils/default/include/MockLocation.h b/gnss/common/utils/default/include/MockLocation.h new file mode 100644 index 0000000000000000000000000000000000000000..0bfdd1a32ef93343d37fe99017286bdc7d328851 --- /dev/null +++ b/gnss/common/utils/default/include/MockLocation.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_gnss_common_MockLocation_H_ +#define android_hardware_gnss_common_MockLocation_H_ + +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace common { + +extern float gMockLatitudeDegrees; +extern float gMockLongitudeDegrees; +extern float gMockAltitudeMeters; +extern float gMockBearingDegrees; +extern float gMockSpeedMetersPerSec; + +} // namespace common +} // namespace gnss +} // namespace hardware +} // namespace android + +#endif // android_hardware_gnss_common_MockLocation_H_ diff --git a/gnss/common/utils/default/include/NmeaFixInfo.h b/gnss/common/utils/default/include/NmeaFixInfo.h new file mode 100644 index 0000000000000000000000000000000000000000..c96eecea005ae3204fdf14282bdf29a7886dc516 --- /dev/null +++ b/gnss/common/utils/default/include/NmeaFixInfo.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +namespace android { +namespace hardware { +namespace gnss { +namespace common { + +constexpr char GPGA_RECORD_TAG[] = "$GPGGA"; +constexpr char GPRMC_RECORD_TAG[] = "$GPRMC"; +constexpr char LINE_SEPARATOR = '\n'; +constexpr char COMMA_SEPARATOR = ','; +constexpr double TIMESTAMP_EPSILON = 0.001; +constexpr int MIN_COL_NUM = 13; + +/** Helper class to parse and store the GNSS fix details information. */ +class NmeaFixInfo { + private: + float altitudeMeters; + float bearingDegrees; + uint32_t fixId; + bool hasGMCRecord; + bool hasGGARecord; + float hDop; + float vDop; + float latDeg; + float lngDeg; + uint32_t satelliteCount; + float speedMetersPerSec; + int64_t timestamp; + + public: + static std::unique_ptr getLocationFromInputStr(const std::string& inputStr); + + private: + static void splitStr(const std::string& line, const char& delimiter, + std::vector& out); + static float checkAndConvertToFloat(const std::string& sentence); + static int64_t nmeaPartsToTimestamp(const std::string& timeStr, const std::string& dateStr); + + NmeaFixInfo(); + void parseGGALine(const std::vector& sentenceValues); + void parseRMCLine(const std::vector& sentenceValues); + std::unique_ptr toGnssLocation() const; + + // Getters + float getAltitudeMeters() const; + float getBearingAccuracyDegrees() const; + float getBearingDegrees() const; + uint32_t getFixId() const; + float getHorizontalAccuracyMeters() const; + float getLatDeg() const; + float getLngDeg() const; + float getSpeedAccuracyMetersPerSecond() const; + float getSpeedMetersPerSec() const; + int64_t getTimestamp() const; + float getVerticalAccuracyMeters() const; + + bool isValidFix() const; + void reset(); + NmeaFixInfo& operator=(const NmeaFixInfo& rhs); +}; + +} // namespace common +} // namespace gnss +} // namespace hardware +} // namespace android \ No newline at end of file diff --git a/gnss/common/utils/default/include/Utils.h b/gnss/common/utils/default/include/Utils.h index d9ad5a5a66e7a15da2f0926c4b1b2d3d9e096299..43772ce11abc35fea7147756d4ab05e888e3f7e4 100644 --- a/gnss/common/utils/default/include/Utils.h +++ b/gnss/common/utils/default/include/Utils.h @@ -17,6 +17,7 @@ #ifndef android_hardware_gnss_common_default_Utils_H_ #define android_hardware_gnss_common_default_Utils_H_ +#include #include #include #include @@ -28,28 +29,24 @@ namespace hardware { namespace gnss { namespace common { -using GnssDataV2_0 = V2_0::IGnssMeasurementCallback::GnssData; -using GnssDataV2_1 = V2_1::IGnssMeasurementCallback::GnssData; -using GnssSvInfoV1_0 = V1_0::IGnssCallback::GnssSvInfo; -using GnssSvInfoV2_0 = V2_0::IGnssCallback::GnssSvInfo; -using GnssSvInfoV2_1 = V2_1::IGnssCallback::GnssSvInfo; -using GnssAntennaInfo = ::android::hardware::gnss::V2_1::IGnssAntennaInfoCallback::GnssAntennaInfo; -using Row = ::android::hardware::gnss::V2_1::IGnssAntennaInfoCallback::Row; -using Coord = ::android::hardware::gnss::V2_1::IGnssAntennaInfoCallback::Coord; - struct Utils { - static GnssDataV2_0 getMockMeasurementV2_0(); - static GnssDataV2_1 getMockMeasurementV2_1(); + static aidl::android::hardware::gnss::GnssData getMockMeasurement( + const bool enableCorrVecOutputs); + static V2_0::IGnssMeasurementCallback::GnssData getMockMeasurementV2_0(); + static V2_1::IGnssMeasurementCallback::GnssData getMockMeasurementV2_1(); static V2_0::GnssLocation getMockLocationV2_0(); static V1_0::GnssLocation getMockLocationV1_0(); - static hidl_vec getMockSvInfoListV2_1(); - static GnssSvInfoV2_1 getMockSvInfoV2_1(GnssSvInfoV2_0 gnssSvInfoV2_0, float basebandCN0DbHz); - static GnssSvInfoV2_0 getMockSvInfoV2_0(GnssSvInfoV1_0 gnssSvInfoV1_0, - V2_0::GnssConstellationType type); - static GnssSvInfoV1_0 getMockSvInfoV1_0(int16_t svid, V1_0::GnssConstellationType type, - float cN0DbHz, float elevationDegrees, - float azimuthDegrees); - static hidl_vec getMockAntennaInfos(); + static hidl_vec getMockSvInfoListV2_1(); + static V2_1::IGnssCallback::GnssSvInfo getMockSvInfoV2_1( + V2_0::IGnssCallback::GnssSvInfo gnssSvInfoV2_0, float basebandCN0DbHz); + static V2_0::IGnssCallback::GnssSvInfo getMockSvInfoV2_0( + V1_0::IGnssCallback::GnssSvInfo gnssSvInfoV1_0, V2_0::GnssConstellationType type); + static V1_0::IGnssCallback::GnssSvInfo getMockSvInfoV1_0(int16_t svid, + V1_0::GnssConstellationType type, + float cN0DbHz, float elevationDegrees, + float azimuthDegrees, + float carrierFrequencyHz); + static hidl_vec getMockAntennaInfos(); }; } // namespace common diff --git a/gnss/2.1/default/GnssAntennaInfo.h b/gnss/common/utils/default/include/v2_1/GnssAntennaInfo.h similarity index 61% rename from gnss/2.1/default/GnssAntennaInfo.h rename to gnss/common/utils/default/include/v2_1/GnssAntennaInfo.h index 94b2111d065619f5b76a2ca455f2951e4d96d04a..a2324994cc9d0416c8946db71362b660a78d0542 100644 --- a/gnss/2.1/default/GnssAntennaInfo.h +++ b/gnss/common/utils/default/include/v2_1/GnssAntennaInfo.h @@ -14,41 +14,34 @@ * limitations under the License. */ -#ifndef ANDROID_HARDWARE_GNSS_V2_1_GNSSANTENNAINFO_H -#define ANDROID_HARDWARE_GNSS_V2_1_GNSSANTENNAINFO_H +#pragma once #include #include #include -namespace android { -namespace hardware { -namespace gnss { -namespace V2_1 { -namespace implementation { +namespace android::hardware::gnss::V2_1::implementation { -using ::android::sp; -using ::android::hardware::Return; -using ::android::hardware::Void; - -struct GnssAntennaInfo : public IGnssAntennaInfo { +struct GnssAntennaInfo : public ::android::hardware::gnss::V2_1::IGnssAntennaInfo { GnssAntennaInfo(); ~GnssAntennaInfo(); // Methods from ::android::hardware::gnss::V2_1::IGnssAntennaInfo follow. Return setCallback( - const sp& callback) override; + const sp<::android::hardware::gnss::V2_1::IGnssAntennaInfoCallback>& callback) override; Return close() override; private: void start(); void stop(); void reportAntennaInfo( - const hidl_vec& antennaInfo) const; + const hidl_vec< + ::android::hardware::gnss::V2_1::IGnssAntennaInfoCallback::GnssAntennaInfo>& + antennaInfo) const; // Guarded by mMutex - static sp sCallback; + static sp<::android::hardware::gnss::V2_1::IGnssAntennaInfoCallback> sCallback; std::atomic mMinIntervalMillis; std::atomic mIsActive; @@ -58,10 +51,4 @@ struct GnssAntennaInfo : public IGnssAntennaInfo { mutable std::mutex mMutex; }; -} // namespace implementation -} // namespace V2_1 -} // namespace gnss -} // namespace hardware -} // namespace android - -#endif // ANDROID_HARDWARE_GNSS_V2_1_GNSSCONFIGURATION_H +} // namespace android::hardware::gnss::V2_1::implementation diff --git a/gnss/2.1/default/GnssConfiguration.h b/gnss/common/utils/default/include/v2_1/GnssConfiguration.h similarity index 65% rename from gnss/2.1/default/GnssConfiguration.h rename to gnss/common/utils/default/include/v2_1/GnssConfiguration.h index 662d61d038bab581eec4c90f8a83430f8e5f9067..2cfb38f4f98667255510b5d1e886992043776c80 100644 --- a/gnss/2.1/default/GnssConfiguration.h +++ b/gnss/common/utils/default/include/v2_1/GnssConfiguration.h @@ -14,8 +14,7 @@ * limitations under the License. */ -#ifndef ANDROID_HARDWARE_GNSS_V2_1_GNSSCONFIGURATION_H -#define ANDROID_HARDWARE_GNSS_V2_1_GNSSCONFIGURATION_H +#pragma once #include #include @@ -24,41 +23,29 @@ #include #include -namespace android { -namespace hardware { -namespace gnss { -namespace V2_1 { -namespace implementation { - -using ::android::sp; -using ::android::hardware::hidl_array; -using ::android::hardware::hidl_memory; -using ::android::hardware::hidl_string; -using ::android::hardware::hidl_vec; -using ::android::hardware::Return; -using ::android::hardware::Void; - -using BlacklistedSourceV2_1 = - ::android::hardware::gnss::V2_1::IGnssConfiguration::BlacklistedSource; -using GnssConstellationTypeV2_0 = V2_0::GnssConstellationType; -using GnssSvInfoV2_1 = V2_1::IGnssCallback::GnssSvInfo; +namespace android::hardware::gnss::V2_1::implementation { struct BlacklistedSourceHashV2_1 { - inline int operator()(const BlacklistedSourceV2_1& source) const { + inline int operator()( + const ::android::hardware::gnss::V2_1::IGnssConfiguration::BlacklistedSource& source) + const { return int(source.constellation) * 1000 + int(source.svid); } }; struct BlacklistedSourceEqualV2_1 { - inline bool operator()(const BlacklistedSourceV2_1& s1, const BlacklistedSourceV2_1& s2) const { + inline bool operator()( + const ::android::hardware::gnss::V2_1::IGnssConfiguration::BlacklistedSource& s1, + const ::android::hardware::gnss::V2_1::IGnssConfiguration::BlacklistedSource& s2) + const { return (s1.constellation == s2.constellation) && (s1.svid == s2.svid); } }; using BlacklistedSourceSetV2_1 = - std::unordered_set; -using BlacklistedConstellationSetV2_1 = std::unordered_set; + std::unordered_set<::android::hardware::gnss::V2_1::IGnssConfiguration::BlacklistedSource, + BlacklistedSourceHashV2_1, BlacklistedSourceEqualV2_1>; +using BlacklistedConstellationSetV2_1 = std::unordered_set; struct GnssConfiguration : public IGnssConfiguration { // Methods from ::android::hardware::gnss::V1_0::IGnssConfiguration follow. @@ -83,7 +70,7 @@ struct GnssConfiguration : public IGnssConfiguration { Return setBlacklist_2_1( const hidl_vec& blacklist) override; - Return isBlacklistedV2_1(const GnssSvInfoV2_1& gnssSvInfo) const; + Return isBlacklistedV2_1(const V2_1::IGnssCallback::GnssSvInfo& gnssSvInfo) const; private: mutable std::recursive_mutex mMutex; @@ -92,10 +79,4 @@ struct GnssConfiguration : public IGnssConfiguration { BlacklistedConstellationSetV2_1 mBlacklistedConstellationSet; }; -} // namespace implementation -} // namespace V2_1 -} // namespace gnss -} // namespace hardware -} // namespace android - -#endif // ANDROID_HARDWARE_GNSS_V2_1_GNSSCONFIGURATION_H \ No newline at end of file +} // namespace android::hardware::gnss::V2_1::implementation diff --git a/gnss/2.1/default/GnssDebug.h b/gnss/common/utils/default/include/v2_1/GnssDebug.h similarity index 61% rename from gnss/2.1/default/GnssDebug.h rename to gnss/common/utils/default/include/v2_1/GnssDebug.h index 969d337524b2e4b29d963013e72a1fa2de6049fe..481de5990106d3bba5aa2fdef472c7d9a6f5ec78 100644 --- a/gnss/2.1/default/GnssDebug.h +++ b/gnss/common/utils/default/include/v2_1/GnssDebug.h @@ -14,27 +14,15 @@ * limitations under the License. */ -#ifndef android_hardware_gnss_V1_1_GnssDebug_H_ -#define android_hardware_gnss_V1_1_GnssDebug_H_ +#pragma once #include #include -namespace android { -namespace hardware { -namespace gnss { -namespace V1_1 { -namespace implementation { - -using ::android::sp; -using ::android::hardware::hidl_string; -using ::android::hardware::hidl_vec; -using ::android::hardware::Return; -using ::android::hardware::Void; -using V1_0::IGnssDebug; +namespace android::hardware::gnss::V1_1::implementation { /* Interface for GNSS Debug support. */ -struct GnssDebug : public IGnssDebug { +struct GnssDebug : public V1_0::IGnssDebug { /* * Methods from ::android::hardware::gnss::V1_0::IGnssDebug follow. * These declarations were generated from IGnssDebug.hal. @@ -42,10 +30,4 @@ struct GnssDebug : public IGnssDebug { Return getDebugData(V1_0::IGnssDebug::getDebugData_cb _hidl_cb) override; }; -} // namespace implementation -} // namespace V1_1 -} // namespace gnss -} // namespace hardware -} // namespace android - -#endif // android_hardware_gnss_V1_1_GnssDebug_H_ +} // namespace android::hardware::gnss::V1_1::implementation diff --git a/gnss/2.1/default/GnssMeasurement.h b/gnss/common/utils/default/include/v2_1/GnssMeasurement.h similarity index 76% rename from gnss/2.1/default/GnssMeasurement.h rename to gnss/common/utils/default/include/v2_1/GnssMeasurement.h index d44641978f4f185f1b5d2d3077cd30bebb65ebb8..db8407b4ef287078b14edf72f90c5e64eacd628f 100644 --- a/gnss/2.1/default/GnssMeasurement.h +++ b/gnss/common/utils/default/include/v2_1/GnssMeasurement.h @@ -23,22 +23,7 @@ #include #include -namespace android { -namespace hardware { -namespace gnss { -namespace V2_1 { -namespace implementation { - -using GnssDataV2_1 = V2_1::IGnssMeasurementCallback::GnssData; -using GnssDataV2_0 = V2_0::IGnssMeasurementCallback::GnssData; - -using ::android::sp; -using ::android::hardware::hidl_array; -using ::android::hardware::hidl_memory; -using ::android::hardware::hidl_string; -using ::android::hardware::hidl_vec; -using ::android::hardware::Return; -using ::android::hardware::Void; +namespace android::hardware::gnss::V2_1::implementation { struct GnssMeasurement : public IGnssMeasurement { GnssMeasurement(); @@ -63,8 +48,8 @@ struct GnssMeasurement : public IGnssMeasurement { private: void start(); void stop(); - void reportMeasurement(const GnssDataV2_0&); - void reportMeasurement(const GnssDataV2_1&); + void reportMeasurement(const V2_0::IGnssMeasurementCallback::GnssData&); + void reportMeasurement(const V2_1::IGnssMeasurementCallback::GnssData&); // Guarded by mMutex static sp sCallback_2_1; @@ -80,8 +65,4 @@ struct GnssMeasurement : public IGnssMeasurement { mutable std::mutex mMutex; }; -} // namespace implementation -} // namespace V2_1 -} // namespace gnss -} // namespace hardware -} // namespace android +} // namespace android::hardware::gnss::V2_1::implementation diff --git a/gnss/2.1/default/GnssMeasurementCorrections.h b/gnss/common/utils/default/include/v2_1/GnssMeasurementCorrections.h similarity index 69% rename from gnss/2.1/default/GnssMeasurementCorrections.h rename to gnss/common/utils/default/include/v2_1/GnssMeasurementCorrections.h index 036e855586297e698e9fe571cb664c26284a0985..54045ad897a8fe73a9e15c1df3d7a712361c4dc4 100644 --- a/gnss/2.1/default/GnssMeasurementCorrections.h +++ b/gnss/common/utils/default/include/v2_1/GnssMeasurementCorrections.h @@ -20,22 +20,12 @@ #include #include -namespace android { -namespace hardware { -namespace gnss { -namespace measurement_corrections { -namespace V1_1 { -namespace implementation { - -using ::android::sp; -using ::android::hardware::hidl_array; -using ::android::hardware::hidl_memory; -using ::android::hardware::hidl_string; -using ::android::hardware::hidl_vec; -using ::android::hardware::Return; -using ::android::hardware::Void; +namespace android::hardware::gnss::measurement_corrections::V1_1::implementation { struct GnssMeasurementCorrections : public IMeasurementCorrections { + GnssMeasurementCorrections(); + ~GnssMeasurementCorrections(); + // Methods from V1_0::IMeasurementCorrections follow. Return setCorrections(const V1_0::MeasurementCorrections& corrections) override; Return setCallback(const sp& callback) override; @@ -44,9 +34,4 @@ struct GnssMeasurementCorrections : public IMeasurementCorrections { Return setCorrections_1_1(const V1_1::MeasurementCorrections& corrections) override; }; -} // namespace implementation -} // namespace V1_1 -} // namespace measurement_corrections -} // namespace gnss -} // namespace hardware -} // namespace android +} // namespace android::hardware::gnss::measurement_corrections::V1_1::implementation diff --git a/gnss/common/utils/default/include/v2_1/GnssTemplate.h b/gnss/common/utils/default/include/v2_1/GnssTemplate.h new file mode 100644 index 0000000000000000000000000000000000000000..131af24fbe3d18902f42cc00cdf42fa17ada282b --- /dev/null +++ b/gnss/common/utils/default/include/v2_1/GnssTemplate.h @@ -0,0 +1,750 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "GnssAntennaInfo.h" +#include "GnssConfiguration.h" +#include "GnssDebug.h" +#include "GnssMeasurement.h" +#include "GnssMeasurementCorrections.h" +#include "MockLocation.h" +#include "NmeaFixInfo.h" +#include "Utils.h" + +namespace android::hardware::gnss::common::implementation { + +constexpr int INPUT_BUFFER_SIZE = 128; +constexpr char CMD_GET_LOCATION[] = "CMD_GET_LOCATION"; +constexpr char GNSS_PATH[] = "/dev/gnss0"; + +template +struct GnssTemplate : public T_IGnss { + GnssTemplate(); + ~GnssTemplate(); + // Methods from V1_0::IGnss follow. + Return setCallback(const sp& callback) override; + Return start() override; + Return stop() override; + Return cleanup() override; + Return injectTime(int64_t timeMs, int64_t timeReferenceMs, + int32_t uncertaintyMs) override; + Return injectLocation(double latitudeDegrees, double longitudeDegrees, + float accuracyMeters) override; + Return deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) override; + Return setPositionMode(V1_0::IGnss::GnssPositionMode mode, + V1_0::IGnss::GnssPositionRecurrence recurrence, + uint32_t minIntervalMs, uint32_t preferredAccuracyMeters, + uint32_t preferredTimeMs) override; + Return> getExtensionAGnssRil() override; + Return> getExtensionGnssGeofencing() override; + Return> getExtensionAGnss() override; + Return> getExtensionGnssNi() override; + Return> getExtensionGnssMeasurement() override; + Return> getExtensionGnssNavigationMessage() override; + Return> getExtensionXtra() override; + Return> getExtensionGnssConfiguration() override; + Return> getExtensionGnssDebug() override; + Return> getExtensionGnssBatching() override; + + // Methods from V1_1::IGnss follow. + Return setCallback_1_1(const sp& callback) override; + Return setPositionMode_1_1(V1_0::IGnss::GnssPositionMode mode, + V1_0::IGnss::GnssPositionRecurrence recurrence, + uint32_t minIntervalMs, uint32_t preferredAccuracyMeters, + uint32_t preferredTimeMs, bool lowPowerMode) override; + Return> getExtensionGnssConfiguration_1_1() override; + Return> getExtensionGnssMeasurement_1_1() override; + Return injectBestLocation(const V1_0::GnssLocation& location) override; + + // Methods from V2_0::IGnss follow. + Return setCallback_2_0(const sp& callback) override; + Return> getExtensionGnssConfiguration_2_0() override; + Return> getExtensionGnssDebug_2_0() override; + Return> getExtensionAGnss_2_0() override; + Return> getExtensionAGnssRil_2_0() override; + Return> getExtensionGnssMeasurement_2_0() override; + Return> + getExtensionMeasurementCorrections() override; + Return> getExtensionVisibilityControl() + override; + Return> getExtensionGnssBatching_2_0() override; + Return injectBestLocation_2_0(const V2_0::GnssLocation& location) override; + + // Methods from V2_1::IGnss follow. + Return setCallback_2_1(const sp& callback) override; + Return> getExtensionGnssMeasurement_2_1() override; + Return> getExtensionGnssConfiguration_2_1() override; + Return> + getExtensionMeasurementCorrections_1_1() override; + Return> getExtensionGnssAntennaInfo() override; + + Return debug(const hidl_handle& fd, const hidl_vec& options) override; + + private: + std::unique_ptr getLocationFromHW(); + void reportLocation(const V2_0::GnssLocation&) const; + void reportLocation(const V1_0::GnssLocation&) const; + void reportSvStatus(const hidl_vec&) const; + void reportGnssStatusValue(const V1_0::IGnssCallback::GnssStatusValue) const; + + Return help(const hidl_handle& fd); + Return setLocation(const hidl_handle& fd, const hidl_vec& options); + + static sp sGnssCallback_2_1; + static sp sGnssCallback_2_0; + static sp sGnssCallback_1_1; + static sp sGnssCallback_1_0; + + std::atomic mMinIntervalMs; + sp mGnssConfiguration; + std::atomic mIsActive; + std::atomic mHardwareModeChecked; + std::atomic mGnssFd; + std::thread mThread; + + mutable std::mutex mMutex; + virtual hidl_vec filterBlocklistedSatellitesV2_1( + hidl_vec gnssSvInfoList); + virtual void notePowerConsumption(); +}; + +template +sp GnssTemplate::sGnssCallback_2_1 = nullptr; +template +sp GnssTemplate::sGnssCallback_2_0 = nullptr; +template +sp GnssTemplate::sGnssCallback_1_1 = nullptr; +template +sp GnssTemplate::sGnssCallback_1_0 = nullptr; + +template +GnssTemplate::GnssTemplate() + : mMinIntervalMs(1000), + mGnssConfiguration{new V2_1::implementation::GnssConfiguration()}, + mHardwareModeChecked(false), + mGnssFd(-1) {} + +template +GnssTemplate::~GnssTemplate() { + stop(); +} + +template +std::unique_ptr GnssTemplate::getLocationFromHW() { + char inputBuffer[INPUT_BUFFER_SIZE]; + if (!mHardwareModeChecked) { + // default using gnss0 + const char * gnss_dev_path = GNSS_PATH; + char devname_value[PROPERTY_VALUE_MAX] = ""; + if (property_get("debug.location.gnss.devname", devname_value, NULL) > 0) { + gnss_dev_path = devname_value; + ALOGD("using %s instead of the default %s", gnss_dev_path, GNSS_PATH); + } + + mGnssFd = open(gnss_dev_path, O_RDWR | O_NONBLOCK); + if (mGnssFd == -1) { + ALOGW("Failed to open %s errno: %d", gnss_dev_path, errno); + } + mHardwareModeChecked = true; + } + + if (mGnssFd == -1) { + return nullptr; + } + + int bytes_write = write(mGnssFd, CMD_GET_LOCATION, strlen(CMD_GET_LOCATION)); + if (bytes_write <= 0) { + return nullptr; + } + + struct epoll_event ev, events[1]; + ev.data.fd = mGnssFd; + ev.events = EPOLLIN; + int epoll_fd = epoll_create1(0); + epoll_ctl(epoll_fd, EPOLL_CTL_ADD, mGnssFd, &ev); + int bytes_read = -1; + std::string inputStr = ""; + int epoll_ret = epoll_wait(epoll_fd, events, 1, mMinIntervalMs); + + if (epoll_ret == -1) { + return nullptr; + } + while (true) { + memset(inputBuffer, 0, INPUT_BUFFER_SIZE); + bytes_read = read(mGnssFd, &inputBuffer, INPUT_BUFFER_SIZE); + if (bytes_read <= 0) { + break; + } + inputStr += std::string(inputBuffer, bytes_read); + } + return NmeaFixInfo::getLocationFromInputStr(inputStr); +} + +template +Return GnssTemplate::start() { + if (mIsActive) { + ALOGW("Gnss has started. Restarting..."); + stop(); + } + + mIsActive = true; + this->reportGnssStatusValue(V1_0::IGnssCallback::GnssStatusValue::SESSION_BEGIN); + mThread = std::thread([this]() { + while (mIsActive == true) { + auto svStatus = filterBlocklistedSatellitesV2_1(Utils::getMockSvInfoListV2_1()); + this->reportSvStatus(svStatus); + auto currentLocation = getLocationFromHW(); + notePowerConsumption(); + if (mGnssFd != -1) { + // Only report location if the return from hardware is valid + // note that we can not merge these two "if" together, if didn't + // get location from hardware, we shouldn't report location, not + // report the "default" one. + if (currentLocation != nullptr) { + this->reportLocation(*currentLocation); + } + } else { + if (sGnssCallback_2_1 != nullptr || sGnssCallback_2_0 != nullptr) { + const auto location = Utils::getMockLocationV2_0(); + this->reportLocation(location); + } else { + const auto location = Utils::getMockLocationV1_0(); + this->reportLocation(location); + } + } + std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMs)); + } + }); + return true; +} + +template +hidl_vec GnssTemplate::filterBlocklistedSatellitesV2_1( + hidl_vec gnssSvInfoList) { + ALOGD("GnssTemplate::filterBlocklistedSatellitesV2_1"); + for (uint32_t i = 0; i < gnssSvInfoList.size(); i++) { + if (mGnssConfiguration->isBlacklistedV2_1(gnssSvInfoList[i])) { + gnssSvInfoList[i].v2_0.v1_0.svFlag &= + ~static_cast(V1_0::IGnssCallback::GnssSvFlags::USED_IN_FIX); + } + } + return gnssSvInfoList; +} + +template +void GnssTemplate::notePowerConsumption() { + ALOGD("GnssTemplate::notePowerConsumption"); +} + +template +Return GnssTemplate::stop() { + ALOGD("stop"); + mIsActive = false; + this->reportGnssStatusValue(V1_0::IGnssCallback::GnssStatusValue::SESSION_END); + if (mThread.joinable()) { + mThread.join(); + } + if (mGnssFd != -1) { + close(mGnssFd); + mGnssFd = -1; + mHardwareModeChecked = false; + } + return true; +} + +// Methods from V1_0::IGnss follow. +template +Return GnssTemplate::setCallback(const sp& callback) { + if (callback == nullptr) { + ALOGE("%s: Null callback ignored", __func__); + return false; + } + + sGnssCallback_1_0 = callback; + + uint32_t capabilities = 0x0 | V1_0::IGnssCallback::Capabilities::MEASUREMENTS | + V1_0::IGnssCallback::Capabilities::SCHEDULING; + auto ret = sGnssCallback_1_0->gnssSetCapabilitesCb(capabilities); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + } + + V2_1::IGnssCallback::GnssSystemInfo gnssInfo = {.yearOfHw = 2018}; + + ret = sGnssCallback_1_0->gnssSetSystemInfoCb(gnssInfo); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + } + + return true; +} + +template +Return GnssTemplate::cleanup() { + sGnssCallback_2_1 = nullptr; + sGnssCallback_2_0 = nullptr; + return Void(); +} + +template +Return GnssTemplate::injectTime(int64_t, int64_t, int32_t) { + return true; +} + +template +Return GnssTemplate::injectLocation(double, double, float) { + return true; +} + +template +Return GnssTemplate::deleteAidingData(V1_0::IGnss::GnssAidingData) { + // TODO implement + return Void(); +} + +template +Return GnssTemplate::setPositionMode(V1_0::IGnss::GnssPositionMode, + V1_0::IGnss::GnssPositionRecurrence, + uint32_t minIntervalMs, uint32_t, uint32_t) { + mMinIntervalMs = minIntervalMs; + return true; +} + +template +Return> GnssTemplate::getExtensionAGnssRil() { + // TODO implement + return ::android::sp{}; +} + +template +Return> GnssTemplate::getExtensionGnssGeofencing() { + // TODO implement + return ::android::sp{}; +} + +template +Return> GnssTemplate::getExtensionAGnss() { + // TODO implement + return ::android::sp{}; +} + +template +Return> GnssTemplate::getExtensionGnssNi() { + // TODO implement + return ::android::sp{}; +} + +template +Return> GnssTemplate::getExtensionGnssMeasurement() { + ALOGD("Gnss::getExtensionGnssMeasurement"); + return new V2_1::implementation::GnssMeasurement(); +} + +template +Return> +GnssTemplate::getExtensionGnssNavigationMessage() { + // TODO implement + return ::android::sp{}; +} + +template +Return> GnssTemplate::getExtensionXtra() { + // TODO implement + return ::android::sp{}; +} + +template +Return> GnssTemplate::getExtensionGnssConfiguration() { + // TODO implement + return ::android::sp{}; +} + +template +Return> GnssTemplate::getExtensionGnssDebug() { + return new V1_1::implementation::GnssDebug(); +} + +template +Return> GnssTemplate::getExtensionGnssBatching() { + // TODO implement + return ::android::sp{}; +} + +// Methods from V1_1::IGnss follow. +template +Return GnssTemplate::setCallback_1_1(const sp& callback) { + if (callback == nullptr) { + ALOGE("%s: Null callback ignored", __func__); + return false; + } + + sGnssCallback_1_1 = callback; + + uint32_t capabilities = 0x0; + auto ret = sGnssCallback_1_1->gnssSetCapabilitesCb(capabilities); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + } + + V2_1::IGnssCallback::GnssSystemInfo gnssInfo = {.yearOfHw = 2018}; + + ret = sGnssCallback_1_1->gnssSetSystemInfoCb(gnssInfo); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + } + + auto gnssName = "Google Mock GNSS Implementation v2.1"; + ret = sGnssCallback_1_1->gnssNameCb(gnssName); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + } + + return true; +} + +template +Return GnssTemplate::setPositionMode_1_1(V1_0::IGnss::GnssPositionMode, + V1_0::IGnss::GnssPositionRecurrence, + uint32_t minIntervalMs, uint32_t, uint32_t, + bool) { + mMinIntervalMs = minIntervalMs; + return true; +} + +template +Return> GnssTemplate::getExtensionGnssConfiguration_1_1() { + // TODO implement + return ::android::sp{}; +} + +template +Return> GnssTemplate::getExtensionGnssMeasurement_1_1() { + // TODO implement + return ::android::sp{}; +} + +template +Return GnssTemplate::injectBestLocation(const V1_0::GnssLocation&) { + return true; +} + +// Methods from V2_0::IGnss follow. +template +Return GnssTemplate::setCallback_2_0(const sp& callback) { + ALOGD("Gnss::setCallback_2_0"); + if (callback == nullptr) { + ALOGE("%s: Null callback ignored", __func__); + return false; + } + + sGnssCallback_2_0 = callback; + + using Capabilities = V2_0::IGnssCallback::Capabilities; + const auto capabilities = Capabilities::MEASUREMENTS | Capabilities::MEASUREMENT_CORRECTIONS | + Capabilities::LOW_POWER_MODE | Capabilities::SATELLITE_BLACKLIST; + auto ret = sGnssCallback_2_0->gnssSetCapabilitiesCb_2_0(capabilities); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + } + + V1_1::IGnssCallback::GnssSystemInfo gnssInfo = {.yearOfHw = 2019}; + + ret = sGnssCallback_2_0->gnssSetSystemInfoCb(gnssInfo); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + } + + auto gnssName = "Google Mock GNSS Implementation v2.1"; + ret = sGnssCallback_2_0->gnssNameCb(gnssName); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + } + + return true; +} + +template +Return> GnssTemplate::getExtensionGnssConfiguration_2_0() { + ALOGD("Gnss::getExtensionGnssConfiguration_2_0"); + return mGnssConfiguration; +} + +template +Return> GnssTemplate::getExtensionGnssDebug_2_0() { + // TODO implement + return ::android::sp{}; +} + +template +Return> GnssTemplate::getExtensionAGnss_2_0() { + // TODO implement + return ::android::sp{}; +} + +template +Return> GnssTemplate::getExtensionAGnssRil_2_0() { + // TODO implement + return ::android::sp{}; +} + +template +Return> GnssTemplate::getExtensionGnssMeasurement_2_0() { + ALOGD("Gnss::getExtensionGnssMeasurement_2_0"); + return new V2_1::implementation::GnssMeasurement(); +} + +template +Return> +GnssTemplate::getExtensionMeasurementCorrections() { + ALOGD("Gnss::getExtensionMeasurementCorrections()"); + return new measurement_corrections::V1_1::implementation::GnssMeasurementCorrections(); +} + +template +Return> +GnssTemplate::getExtensionVisibilityControl() { + // TODO implement + return ::android::sp{}; +} + +template +Return> GnssTemplate::getExtensionGnssBatching_2_0() { + // TODO implement + return ::android::sp{}; +} + +template +Return GnssTemplate::injectBestLocation_2_0(const V2_0::GnssLocation&) { + // TODO(b/124012850): Implement function. + return bool{}; +} + +// Methods from V2_1::IGnss follow. +template +Return GnssTemplate::setCallback_2_1(const sp& callback) { + ALOGD("Gnss::setCallback_2_1"); + if (callback == nullptr) { + ALOGE("%s: Null callback ignored", __func__); + return false; + } + + sGnssCallback_2_1 = callback; + + using Capabilities = V2_1::IGnssCallback::Capabilities; + const auto capabilities = Capabilities::MEASUREMENTS | Capabilities::MEASUREMENT_CORRECTIONS | + Capabilities::LOW_POWER_MODE | Capabilities::SATELLITE_BLACKLIST | + Capabilities::ANTENNA_INFO; + auto ret = sGnssCallback_2_1->gnssSetCapabilitiesCb_2_1(capabilities); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + } + + V1_1::IGnssCallback::GnssSystemInfo gnssInfo = {.yearOfHw = 2020}; + + ret = sGnssCallback_2_1->gnssSetSystemInfoCb(gnssInfo); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + } + + auto gnssName = "Android Mock GNSS Implementation v2.1"; + ret = sGnssCallback_2_1->gnssNameCb(gnssName); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + } + + return true; +} + +template +Return> GnssTemplate::getExtensionGnssMeasurement_2_1() { + ALOGD("Gnss::getExtensionGnssMeasurement_2_1"); + return new V2_1::implementation::GnssMeasurement(); +} + +template +Return> GnssTemplate::getExtensionGnssConfiguration_2_1() { + ALOGD("Gnss::getExtensionGnssConfiguration_2_1"); + return mGnssConfiguration; +} + +template +Return> +GnssTemplate::getExtensionMeasurementCorrections_1_1() { + ALOGD("Gnss::getExtensionMeasurementCorrections_1_1()"); + return new measurement_corrections::V1_1::implementation::GnssMeasurementCorrections(); +} + +template +Return> GnssTemplate::getExtensionGnssAntennaInfo() { + ALOGD("Gnss::getExtensionGnssAntennaInfo"); + return new V2_1::implementation::GnssAntennaInfo(); +} + +template +void GnssTemplate::reportGnssStatusValue( + const V1_0::IGnssCallback::GnssStatusValue gnssStatusValue) const { + std::unique_lock lock(mMutex); + if (sGnssCallback_2_1 == nullptr) { + ALOGE("%s: sGnssCallback v2.1 is null.", __func__); + return; + } + auto ret = sGnssCallback_2_1->gnssStatusCb(gnssStatusValue); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + } +} + +template +void GnssTemplate::reportSvStatus( + const hidl_vec& svInfoList) const { + std::unique_lock lock(mMutex); + // TODO(skz): update this to call 2_0 callback if non-null + if (sGnssCallback_2_1 == nullptr) { + ALOGE("%s: sGnssCallback v2.1 is null.", __func__); + return; + } + auto ret = sGnssCallback_2_1->gnssSvStatusCb_2_1(svInfoList); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + } +} + +template +void GnssTemplate::reportLocation(const V1_0::GnssLocation& location) const { + std::unique_lock lock(mMutex); + if (sGnssCallback_1_1 != nullptr) { + auto ret = sGnssCallback_1_1->gnssLocationCb(location); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback v1.1", __func__); + } + return; + } + if (sGnssCallback_1_0 == nullptr) { + ALOGE("%s: No non-null callback", __func__); + return; + } + auto ret = sGnssCallback_1_0->gnssLocationCb(location); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback v1.0", __func__); + } +} + +template +void GnssTemplate::reportLocation(const V2_0::GnssLocation& location) const { + std::unique_lock lock(mMutex); + if (sGnssCallback_2_1 != nullptr) { + auto ret = sGnssCallback_2_1->gnssLocationCb_2_0(location); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback v2.1", __func__); + } + return; + } + if (sGnssCallback_2_0 == nullptr) { + ALOGE("%s: No non-null callback", __func__); + return; + } + auto ret = sGnssCallback_2_0->gnssLocationCb_2_0(location); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback v2.0", __func__); + } +} + +template +Return GnssTemplate::setLocation(const hidl_handle& fd, + const hidl_vec& options) { + auto lat = gMockLatitudeDegrees; + auto lon = gMockLongitudeDegrees; + auto ele = gMockAltitudeMeters; + auto bea = gMockBearingDegrees; + auto spd = gMockSpeedMetersPerSec; + + for (size_t i = 1; i < options.size(); ++i) { + std::string option = options[i]; + if (option.rfind("lat=", 0) == 0) { + option = option.substr(4); + lat = stof(option); + } else if (option.rfind("lon=", 0) == 0) { + option = option.substr(4); + lon = stof(option); + } else if (option.rfind("ele=", 0) == 0) { + option = option.substr(4); + ele = stof(option); + } else if (option.rfind("bea=", 0) == 0) { + option = option.substr(4); + bea = stof(option); + } else if (option.rfind("spd=", 0) == 0) { + option = option.substr(4); + spd = stof(option); + } else { + dprintf(fd->data[0], "unsupported location argument: %s\n", option.c_str()); + } + } + + gMockLatitudeDegrees = lat; + gMockLongitudeDegrees = lon; + gMockAltitudeMeters = ele; + gMockBearingDegrees = bea; + gMockSpeedMetersPerSec = spd; + + dprintf(fd->data[0], "mock location updated to lat=%f lon=%f ele=%f bea=%f spd=%f\n", + gMockLatitudeDegrees, gMockLongitudeDegrees, gMockAltitudeMeters, gMockBearingDegrees, + gMockSpeedMetersPerSec); + + return Void(); +} + +template +Return GnssTemplate::help(const hidl_handle& fd) { + dprintf(fd->data[0], + "invalid option for Gnss HAL; valid options are:\n" + "location [lat=..] [lon=..] [ele=..] [bea=..] [spd=..]\n"); + return Void(); +} + +template +Return GnssTemplate::debug(const hidl_handle& fd, + const hidl_vec& options) { + if (fd == nullptr || fd->numFds == 0) { + return Void(); + } + + if (options.size() == 0) { + return help(fd); + } else if (options[0] == "location") { + return setLocation(fd, options); + } else { + return help(fd); + } + + return Void(); +} + +} // namespace android::hardware::gnss::common::implementation diff --git a/gnss/2.1/default/GnssAntennaInfo.cpp b/gnss/common/utils/default/v2_1/GnssAntennaInfo.cpp similarity index 91% rename from gnss/2.1/default/GnssAntennaInfo.cpp rename to gnss/common/utils/default/v2_1/GnssAntennaInfo.cpp index ed183a9383da5936a374c6f639441428f9784d73..962451c0ddc920f7ebd86e56edbf1bdda4fc52fb 100644 --- a/gnss/2.1/default/GnssAntennaInfo.cpp +++ b/gnss/common/utils/default/v2_1/GnssAntennaInfo.cpp @@ -16,18 +16,14 @@ #define LOG_TAG "GnssAntennaInfo" -#include "GnssAntennaInfo.h" +#include "v2_1/GnssAntennaInfo.h" #include "Utils.h" #include using ::android::hardware::gnss::common::Utils; -namespace android { -namespace hardware { -namespace gnss { -namespace V2_1 { -namespace implementation { +namespace android::hardware::gnss::V2_1::implementation { sp GnssAntennaInfo::sCallback = nullptr; @@ -102,8 +98,4 @@ void GnssAntennaInfo::reportAntennaInfo( } } -} // namespace implementation -} // namespace V2_1 -} // namespace gnss -} // namespace hardware -} // namespace android \ No newline at end of file +} // namespace android::hardware::gnss::V2_1::implementation diff --git a/gnss/2.1/default/GnssConfiguration.cpp b/gnss/common/utils/default/v2_1/GnssConfiguration.cpp similarity index 90% rename from gnss/2.1/default/GnssConfiguration.cpp rename to gnss/common/utils/default/v2_1/GnssConfiguration.cpp index cd8f07fcc4e73f939a169ec50bb6e933274de00f..be974bcdb294f1b212b0fe78cf7e2277deebb848 100644 --- a/gnss/2.1/default/GnssConfiguration.cpp +++ b/gnss/common/utils/default/v2_1/GnssConfiguration.cpp @@ -16,14 +16,13 @@ #define LOG_TAG "GnssConfiguration" -#include "GnssConfiguration.h" +#include "v2_1/GnssConfiguration.h" #include -namespace android { -namespace hardware { -namespace gnss { -namespace V2_1 { -namespace implementation { +namespace android::hardware::gnss::V2_1::implementation { + +using GnssSvInfoV2_1 = V2_1::IGnssCallback::GnssSvInfo; +using BlacklistedSourceV2_1 = V2_1::IGnssConfiguration::BlacklistedSource; // Methods from ::android::hardware::gnss::V1_0::IGnssConfiguration follow. Return GnssConfiguration::setSuplEs(bool enable) { @@ -73,7 +72,7 @@ Return GnssConfiguration::setEsExtensionSec(uint32_t emergencyExtensionSec // Methods from ::android::hardware::gnss::V2_1::IGnssConfiguration follow. Return GnssConfiguration::setBlacklist_2_1( - const hidl_vec& sourceList) { + const hidl_vec& sourceList) { std::unique_lock lock(mMutex); mBlacklistedConstellationSet.clear(); mBlacklistedSourceSet.clear(); @@ -99,8 +98,4 @@ Return GnssConfiguration::isBlacklistedV2_1(const GnssSvInfoV2_1& gnssSvIn return (mBlacklistedSourceSet.find(source) != mBlacklistedSourceSet.end()); } -} // namespace implementation -} // namespace V2_1 -} // namespace gnss -} // namespace hardware -} // namespace android \ No newline at end of file +} // namespace android::hardware::gnss::V2_1::implementation diff --git a/gnss/2.1/default/GnssDebug.cpp b/gnss/common/utils/default/v2_1/GnssDebug.cpp similarity index 75% rename from gnss/2.1/default/GnssDebug.cpp rename to gnss/common/utils/default/v2_1/GnssDebug.cpp index a9f7ded2a74b0ce174d620fbdace68104c6fae04..537a90c7b0faa726560a0242f7f205a90efa7d4b 100644 --- a/gnss/2.1/default/GnssDebug.cpp +++ b/gnss/common/utils/default/v2_1/GnssDebug.cpp @@ -19,25 +19,22 @@ #include #include "Constants.h" -#include "GnssDebug.h" +#include "MockLocation.h" +#include "v2_1/GnssDebug.h" using namespace ::android::hardware::gnss::common; -namespace android { -namespace hardware { -namespace gnss { -namespace V1_1 { -namespace implementation { +namespace android::hardware::gnss::V1_1::implementation { // Methods from ::android::hardware::gnss::V1_0::IGnssDebug follow. Return GnssDebug::getDebugData(V1_0::IGnssDebug::getDebugData_cb _hidl_cb) { PositionDebug positionDebug = { .valid = true, - .latitudeDegrees = kMockLatitudeDegrees, - .longitudeDegrees = kMockLongitudeDegrees, - .altitudeMeters = kMockAltitudeMeters, - .speedMetersPerSec = kMockSpeedMetersPerSec, - .bearingDegrees = kMockBearingDegrees, + .latitudeDegrees = gMockLatitudeDegrees, + .longitudeDegrees = gMockLongitudeDegrees, + .altitudeMeters = gMockAltitudeMeters, + .speedMetersPerSec = gMockSpeedMetersPerSec, + .bearingDegrees = gMockBearingDegrees, .horizontalAccuracyMeters = kMockHorizontalAccuracyMeters, .verticalAccuracyMeters = kMockVerticalAccuracyMeters, .speedAccuracyMetersPerSecond = kMockSpeedAccuracyMetersPerSecond, @@ -55,8 +52,4 @@ Return GnssDebug::getDebugData(V1_0::IGnssDebug::getDebugData_cb _hidl_cb) return Void(); } -} // namespace implementation -} // namespace V1_1 -} // namespace gnss -} // namespace hardware -} // namespace android +} // namespace android::hardware::gnss::V1_1::implementation diff --git a/gnss/2.1/default/GnssMeasurement.cpp b/gnss/common/utils/default/v2_1/GnssMeasurement.cpp similarity index 91% rename from gnss/2.1/default/GnssMeasurement.cpp rename to gnss/common/utils/default/v2_1/GnssMeasurement.cpp index 63bbc0a399c05610e1d4dacc50e5dde645bac08f..887cb5a136b4558460bc86ef3f114af6dbc71a72 100644 --- a/gnss/2.1/default/GnssMeasurement.cpp +++ b/gnss/common/utils/default/v2_1/GnssMeasurement.cpp @@ -16,19 +16,14 @@ #define LOG_TAG "GnssMeasurement" -#include "GnssMeasurement.h" +#include "v2_1/GnssMeasurement.h" #include #include "Utils.h" -namespace android { -namespace hardware { -namespace gnss { +namespace android::hardware::gnss::V2_1::implementation { using common::Utils; -namespace V2_1 { -namespace implementation { - sp GnssMeasurement::sCallback_2_1 = nullptr; sp GnssMeasurement::sCallback_2_0 = nullptr; @@ -119,7 +114,7 @@ void GnssMeasurement::stop() { } } -void GnssMeasurement::reportMeasurement(const GnssDataV2_0& data) { +void GnssMeasurement::reportMeasurement(const V2_0::IGnssMeasurementCallback::GnssData& data) { ALOGD("reportMeasurement()"); std::unique_lock lock(mMutex); if (sCallback_2_0 == nullptr) { @@ -132,7 +127,7 @@ void GnssMeasurement::reportMeasurement(const GnssDataV2_0& data) { } } -void GnssMeasurement::reportMeasurement(const GnssDataV2_1& data) { +void GnssMeasurement::reportMeasurement(const V2_1::IGnssMeasurementCallback::GnssData& data) { ALOGD("reportMeasurement()"); std::unique_lock lock(mMutex); if (sCallback_2_1 == nullptr) { @@ -145,8 +140,4 @@ void GnssMeasurement::reportMeasurement(const GnssDataV2_1& data) { } } -} // namespace implementation -} // namespace V2_1 -} // namespace gnss -} // namespace hardware -} // namespace android +} // namespace android::hardware::gnss::V2_1::implementation diff --git a/gnss/2.1/default/GnssMeasurementCorrections.cpp b/gnss/common/utils/default/v2_1/GnssMeasurementCorrections.cpp similarity index 93% rename from gnss/2.1/default/GnssMeasurementCorrections.cpp rename to gnss/common/utils/default/v2_1/GnssMeasurementCorrections.cpp index accf62b7333a20e96b04408850131542ae68783d..9be7e2350fa0c2f16f74445b6fc7fe3cad957566 100644 --- a/gnss/2.1/default/GnssMeasurementCorrections.cpp +++ b/gnss/common/utils/default/v2_1/GnssMeasurementCorrections.cpp @@ -16,15 +16,14 @@ #define LOG_TAG "GnssMeasurementCorrections" -#include "GnssMeasurementCorrections.h" +#include "v2_1/GnssMeasurementCorrections.h" #include -namespace android { -namespace hardware { -namespace gnss { -namespace measurement_corrections { -namespace V1_1 { -namespace implementation { +namespace android::hardware::gnss::measurement_corrections::V1_1::implementation { + +GnssMeasurementCorrections::GnssMeasurementCorrections() {} + +GnssMeasurementCorrections::~GnssMeasurementCorrections() {} // Methods from V1_0::IMeasurementCorrections follow. Return GnssMeasurementCorrections::setCorrections( @@ -101,9 +100,4 @@ Return GnssMeasurementCorrections::setCorrections_1_1( return true; } -} // namespace implementation -} // namespace V1_1 -} // namespace measurement_corrections -} // namespace gnss -} // namespace hardware -} // namespace android +} // namespace android::hardware::gnss::measurement_corrections::V1_1::implementation diff --git a/gnss/common/utils/vts/Android.bp b/gnss/common/utils/vts/Android.bp index 1c4cec3cd4082ffce76a64b25633160026fb7741..47eff2ec9c692dc3c6872ad4634afb694ce2dd51 100644 --- a/gnss/common/utils/vts/Android.bp +++ b/gnss/common/utils/vts/Android.bp @@ -34,11 +34,14 @@ cc_library_static { ], srcs: [ "Utils.cpp", + "v2_1/GnssCallback.cpp", ], export_include_dirs: ["include"], shared_libs: [ "android.hardware.gnss@1.0", + "android.hardware.gnss@1.1", "android.hardware.gnss@2.0", + "android.hardware.gnss@2.1", "android.hardware.gnss.measurement_corrections@1.0", "android.hardware.gnss.measurement_corrections@1.1", ], diff --git a/gnss/common/utils/vts/include/v2_1/GnssCallback.h b/gnss/common/utils/vts/include/v2_1/GnssCallback.h new file mode 100644 index 0000000000000000000000000000000000000000..ab1375d3a5993c7c48104012eec661b8954e1be2 --- /dev/null +++ b/gnss/common/utils/vts/include/v2_1/GnssCallback.h @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include "GnssCallbackEventQueue.h" + +#include + +using android::hardware::hidl_vec; +using android::hardware::Return; +using android::hardware::Void; + +using android::hardware::gnss::common::GnssCallbackEventQueue; +using android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrectionsCallback; +using android::hardware::gnss::V1_0::GnssLocationFlags; +using android::hardware::gnss::V2_0::GnssConstellationType; + +using GnssLocation_1_0 = android::hardware::gnss::V1_0::GnssLocation; +using GnssLocation_2_0 = android::hardware::gnss::V2_0::GnssLocation; + +using IGnssCallback_1_0 = android::hardware::gnss::V1_0::IGnssCallback; +using IGnssCallback_2_0 = android::hardware::gnss::V2_0::IGnssCallback; +using IGnssCallback_2_1 = android::hardware::gnss::V2_1::IGnssCallback; + +using IGnssMeasurementCallback_1_0 = android::hardware::gnss::V1_0::IGnssMeasurementCallback; +using IGnssMeasurementCallback_1_1 = android::hardware::gnss::V1_1::IGnssMeasurementCallback; +using IGnssMeasurementCallback_2_0 = android::hardware::gnss::V2_0::IGnssMeasurementCallback; +using IGnssMeasurementCallback_2_1 = android::hardware::gnss::V2_1::IGnssMeasurementCallback; + +using android::sp; + +#define TIMEOUT_SEC 2 // for basic commands/responses + +namespace android::hardware::gnss::common { + +/* Callback class for data & Event. */ +class GnssCallback : public IGnssCallback_2_1 { + public: + IGnssCallback_1_0::GnssSystemInfo last_info_; + android::hardware::hidl_string last_name_; + uint32_t last_capabilities_; + GnssLocation_2_0 last_location_; + + GnssCallbackEventQueue info_cbq_; + GnssCallbackEventQueue name_cbq_; + GnssCallbackEventQueue capabilities_cbq_; + GnssCallbackEventQueue location_cbq_; + GnssCallbackEventQueue> sv_info_list_cbq_; + + GnssCallback(); + virtual ~GnssCallback() = default; + + // Dummy callback handlers + Return gnssStatusCb(const IGnssCallback_1_0::GnssStatusValue /* status */) override { + return Void(); + } + Return gnssNmeaCb(int64_t /* timestamp */, + const android::hardware::hidl_string& /* nmea */) override { + return Void(); + } + Return gnssAcquireWakelockCb() override { return Void(); } + Return gnssReleaseWakelockCb() override { return Void(); } + Return gnssRequestLocationCb(bool /* independentFromGnss */) override { return Void(); } + Return gnssRequestTimeCb() override { return Void(); } + // Actual (test) callback handlers + Return gnssNameCb(const android::hardware::hidl_string& name) override; + Return gnssLocationCb(const GnssLocation_1_0& location) override; + Return gnssSetCapabilitesCb(uint32_t capabilities) override; + Return gnssSetSystemInfoCb(const IGnssCallback_1_0::GnssSystemInfo& info) override; + Return gnssSvStatusCb(const IGnssCallback_1_0::GnssSvStatus& svStatus) override; + + // New in v2.0 + Return gnssLocationCb_2_0(const GnssLocation_2_0& location) override; + Return gnssRequestLocationCb_2_0(bool /* independentFromGnss */, + bool /* isUserEmergency */) override { + return Void(); + } + Return gnssSetCapabilitiesCb_2_0(uint32_t capabilities) override; + Return gnssSvStatusCb_2_0(const hidl_vec&) override { + return Void(); + } + + // New in v2.1 + Return gnssSvStatusCb_2_1( + const hidl_vec& svInfoList) override; + Return gnssSetCapabilitiesCb_2_1(uint32_t capabilities) override; + + private: + Return gnssLocationCbImpl(const GnssLocation_2_0& location); +}; + +} // namespace android::hardware::gnss::common diff --git a/gnss/common/utils/vts/include/v2_1/gnss_hal_test_template.h b/gnss/common/utils/vts/include/v2_1/gnss_hal_test_template.h new file mode 100644 index 0000000000000000000000000000000000000000..03166be8d70db635c89de5b0f4ad0e132b5d3990 --- /dev/null +++ b/gnss/common/utils/vts/include/v2_1/gnss_hal_test_template.h @@ -0,0 +1,360 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "GnssCallbackEventQueue.h" +#include "Utils.h" +#include "v2_1/GnssCallback.h" + +#include +#include + +#define TIMEOUT_SEC 2 // for basic commands/responses + +namespace android::hardware::gnss::common { + +// The main test class for GNSS HAL. +template +class GnssHalTestTemplate : public testing::TestWithParam { + public: + virtual void SetUp() override; + + virtual void TearDown() override; + + /* Callback class for GnssMeasurement. */ + class GnssMeasurementCallback : public V2_1::IGnssMeasurementCallback { + public: + GnssCallbackEventQueue measurement_cbq_; + + GnssMeasurementCallback() : measurement_cbq_("measurement"){}; + virtual ~GnssMeasurementCallback() = default; + + // Methods from V1_0::IGnssMeasurementCallback follow. + Return GnssMeasurementCb(const V1_0::IGnssMeasurementCallback::GnssData&) override { + return Void(); + } + + // Methods from V1_1::IGnssMeasurementCallback follow. + Return gnssMeasurementCb(const V1_1::IGnssMeasurementCallback::GnssData&) override { + return Void(); + } + + // Methods from V2_0::IGnssMeasurementCallback follow. + Return gnssMeasurementCb_2_0( + const V2_0::IGnssMeasurementCallback::GnssData&) override { + return Void(); + } + + // Methods from V2_1::IGnssMeasurementCallback follow. + Return gnssMeasurementCb_2_1( + const V2_1::IGnssMeasurementCallback::GnssData&) override; + }; + + /* Callback class for GnssMeasurementCorrections. */ + class GnssMeasurementCorrectionsCallback + : public measurement_corrections::V1_0::IMeasurementCorrectionsCallback { + public: + uint32_t last_capabilities_; + GnssCallbackEventQueue capabilities_cbq_; + + GnssMeasurementCorrectionsCallback() : capabilities_cbq_("capabilities"){}; + virtual ~GnssMeasurementCorrectionsCallback() = default; + + // Methods from V1_0::IMeasurementCorrectionsCallback follow. + Return setCapabilitiesCb(uint32_t capabilities) override; + }; + + /* Callback class for GnssAntennaInfo. */ + class GnssAntennaInfoCallback : public V2_1::IGnssAntennaInfoCallback { + public: + GnssCallbackEventQueue> + antenna_info_cbq_; + + GnssAntennaInfoCallback() : antenna_info_cbq_("info"){}; + virtual ~GnssAntennaInfoCallback() = default; + + // Methods from V2_1::GnssAntennaInfoCallback follow. + Return gnssAntennaInfoCb( + const hidl_vec& gnssAntennaInfos); + }; + + /* + * SetUpGnssCallback: + * Set GnssCallback and verify the result. + */ + virtual void SetUpGnssCallback(); + + /* + * StartAndCheckFirstLocation: + * Helper function to start location, and check the first one. + * + *

Note this leaves the Location request active, to enable Stop call vs. other call + * reordering tests. + * + * returns true if a location was successfully generated + */ + bool StartAndCheckFirstLocation(const int min_interval_msec, const bool low_power_mode); + + /* + * CheckLocation: + * Helper function to vet Location fields + * + * check_speed: true if speed related fields are also verified. + */ + void CheckLocation(const V2_0::GnssLocation& location, const bool check_speed); + + /* + * StartAndCheckLocations: + * Helper function to collect, and check a number of + * normal ~1Hz locations. + * + * Note this leaves the Location request active, to enable Stop call vs. other call + * reordering tests. + */ + void StartAndCheckLocations(int count); + + /* + * StopAndClearLocations: + * Helper function to stop locations, and clear any remaining notifications + */ + void StopAndClearLocations(); + + /* + * SetPositionMode: + * Helper function to set positioning mode and verify output + */ + void SetPositionMode(const int min_interval_msec, const bool low_power_mode); + + /* + * startLocationAndGetNonGpsConstellation: + * 1. Start location + * 2. Find and return first non-GPS constellation + * + * Note that location is not stopped in this method. The client should call + * StopAndClearLocations() after the call. + */ + V2_0::GnssConstellationType startLocationAndGetNonGpsConstellation( + const int locations_to_await, const int gnss_sv_info_list_timeout); + + sp gnss_hal_; // GNSS HAL to call into + sp gnss_cb_; // Primary callback interface +}; + +using ::android::hardware::gnss::common::Utils; + +// Implementations for the main test class for GNSS HAL +template +void GnssHalTestTemplate::SetUp() { + gnss_hal_ = T_IGnss::getService(GetParam()); + ASSERT_NE(gnss_hal_, nullptr); + + SetUpGnssCallback(); +} + +template +void GnssHalTestTemplate::TearDown() { + if (gnss_hal_ != nullptr) { + gnss_hal_->cleanup(); + gnss_hal_ = nullptr; + } + + // Set to nullptr to destruct the callback event queues and warn of any unprocessed events. + gnss_cb_ = nullptr; +} + +template +void GnssHalTestTemplate::SetUpGnssCallback() { + gnss_cb_ = new GnssCallback(); + ASSERT_NE(gnss_cb_, nullptr); + + auto result = gnss_hal_->setCallback_2_1(gnss_cb_); + if (!result.isOk()) { + ALOGE("result of failed setCallback %s", result.description().c_str()); + } + + ASSERT_TRUE(result.isOk()); + ASSERT_TRUE(result); + + /* + * All capabilities, name and systemInfo callbacks should trigger + */ + EXPECT_TRUE(gnss_cb_->capabilities_cbq_.retrieve(gnss_cb_->last_capabilities_, TIMEOUT_SEC)); + EXPECT_TRUE(gnss_cb_->info_cbq_.retrieve(gnss_cb_->last_info_, TIMEOUT_SEC)); + EXPECT_TRUE(gnss_cb_->name_cbq_.retrieve(gnss_cb_->last_name_, TIMEOUT_SEC)); + + EXPECT_EQ(gnss_cb_->capabilities_cbq_.calledCount(), 1); + EXPECT_EQ(gnss_cb_->info_cbq_.calledCount(), 1); + EXPECT_EQ(gnss_cb_->name_cbq_.calledCount(), 1); +} + +template +void GnssHalTestTemplate::StopAndClearLocations() { + const auto result = gnss_hal_->stop(); + + EXPECT_TRUE(result.isOk()); + EXPECT_TRUE(result); + + /* + * Clear notify/waiting counter, allowing up till the timeout after + * the last reply for final startup messages to arrive (esp. system + * info.) + */ + while (gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_, TIMEOUT_SEC)) { + } + gnss_cb_->location_cbq_.reset(); +} + +template +void GnssHalTestTemplate::SetPositionMode(const int min_interval_msec, + const bool low_power_mode) { + const int kPreferredAccuracy = 0; // Ideally perfect (matches GnssLocationProvider) + const int kPreferredTimeMsec = 0; // Ideally immediate + + const auto result = gnss_hal_->setPositionMode_1_1( + T_IGnss::GnssPositionMode::MS_BASED, + T_IGnss::GnssPositionRecurrence::RECURRENCE_PERIODIC, min_interval_msec, + kPreferredAccuracy, kPreferredTimeMsec, low_power_mode); + + ASSERT_TRUE(result.isOk()); + EXPECT_TRUE(result); +} + +template +bool GnssHalTestTemplate::StartAndCheckFirstLocation(const int min_interval_msec, + const bool low_power_mode) { + SetPositionMode(min_interval_msec, low_power_mode); + const auto result = gnss_hal_->start(); + + EXPECT_TRUE(result.isOk()); + EXPECT_TRUE(result); + + /* + * GnssLocationProvider support of AGPS SUPL & XtraDownloader is not available in VTS, + * so allow time to demodulate ephemeris over the air. + */ + const int kFirstGnssLocationTimeoutSeconds = 75; + + EXPECT_TRUE(gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_, + kFirstGnssLocationTimeoutSeconds)); + int locationCalledCount = gnss_cb_->location_cbq_.calledCount(); + EXPECT_EQ(locationCalledCount, 1); + + if (locationCalledCount > 0) { + // don't require speed on first fix + CheckLocation(gnss_cb_->last_location_, false); + return true; + } + return false; +} + +template +void GnssHalTestTemplate::CheckLocation(const V2_0::GnssLocation& location, + bool check_speed) { + const bool check_more_accuracies = + (gnss_cb_->info_cbq_.calledCount() > 0 && gnss_cb_->last_info_.yearOfHw >= 2017); + + Utils::checkLocation(location.v1_0, check_speed, check_more_accuracies); +} + +template +void GnssHalTestTemplate::StartAndCheckLocations(int count) { + const int kMinIntervalMsec = 500; + const int kLocationTimeoutSubsequentSec = 2; + const bool kLowPowerMode = false; + + EXPECT_TRUE(StartAndCheckFirstLocation(kMinIntervalMsec, kLowPowerMode)); + + for (int i = 1; i < count; i++) { + EXPECT_TRUE(gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_, + kLocationTimeoutSubsequentSec)); + int locationCalledCount = gnss_cb_->location_cbq_.calledCount(); + EXPECT_EQ(locationCalledCount, i + 1); + // Don't cause confusion by checking details if no location yet + if (locationCalledCount > 0) { + // Should be more than 1 location by now, but if not, still don't check first fix speed + CheckLocation(gnss_cb_->last_location_, locationCalledCount > 1); + } + } +} + +template +V2_0::GnssConstellationType GnssHalTestTemplate::startLocationAndGetNonGpsConstellation( + const int locations_to_await, const int gnss_sv_info_list_timeout) { + gnss_cb_->location_cbq_.reset(); + StartAndCheckLocations(locations_to_await); + const int location_called_count = gnss_cb_->location_cbq_.calledCount(); + + // Tolerate 1 less sv status to handle edge cases in reporting. + int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size(); + EXPECT_GE(sv_info_list_cbq_size + 1, locations_to_await); + ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations (%d received)", + sv_info_list_cbq_size, locations_to_await, location_called_count); + + // Find first non-GPS constellation to blacklist + V2_0::GnssConstellationType constellation_to_blacklist = V2_0::GnssConstellationType::UNKNOWN; + for (int i = 0; i < sv_info_list_cbq_size; ++i) { + hidl_vec sv_info_vec; + gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, gnss_sv_info_list_timeout); + for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) { + const auto& gnss_sv = sv_info_vec[iSv]; + if ((gnss_sv.v2_0.v1_0.svFlag & V1_0::IGnssCallback::GnssSvFlags::USED_IN_FIX) && + (gnss_sv.v2_0.constellation != V2_0::GnssConstellationType::UNKNOWN) && + (gnss_sv.v2_0.constellation != V2_0::GnssConstellationType::GPS)) { + // found a non-GPS constellation + constellation_to_blacklist = gnss_sv.v2_0.constellation; + break; + } + } + if (constellation_to_blacklist != V2_0::GnssConstellationType::UNKNOWN) { + break; + } + } + + if (constellation_to_blacklist == V2_0::GnssConstellationType::UNKNOWN) { + ALOGI("No non-GPS constellations found, constellation blacklist test less effective."); + // Proceed functionally to blacklist something. + constellation_to_blacklist = V2_0::GnssConstellationType::GLONASS; + } + + return constellation_to_blacklist; +} + +template +Return GnssHalTestTemplate::GnssMeasurementCallback::gnssMeasurementCb_2_1( + const V2_1::IGnssMeasurementCallback::GnssData& data) { + ALOGD("GnssMeasurement v2.1 received. Size = %d", (int)data.measurements.size()); + measurement_cbq_.store(data); + return Void(); +} + +template +Return GnssHalTestTemplate::GnssMeasurementCorrectionsCallback::setCapabilitiesCb( + uint32_t capabilities) { + ALOGI("GnssMeasurementCorrectionsCallback capabilities received %d", capabilities); + capabilities_cbq_.store(capabilities); + return Void(); +} + +template +Return GnssHalTestTemplate::GnssAntennaInfoCallback::gnssAntennaInfoCb( + const hidl_vec& gnssAntennaInfos) { + ALOGD("GnssAntennaInfo v2.1 received. Size = %d", (int)gnssAntennaInfos.size()); + antenna_info_cbq_.store(gnssAntennaInfos); + return Void(); +} + +} // namespace android::hardware::gnss::common diff --git a/gnss/common/utils/vts/v2_1/GnssCallback.cpp b/gnss/common/utils/vts/v2_1/GnssCallback.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3b96fb834b16c2f123e73927fb28c1cda29c0608 --- /dev/null +++ b/gnss/common/utils/vts/v2_1/GnssCallback.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "GnssCallback" + +#include "v2_1/GnssCallback.h" +#include +#include "Utils.h" + +#include + +using ::android::hardware::gnss::common::Utils; + +namespace android::hardware::gnss::common { + +GnssCallback::GnssCallback() + : info_cbq_("system_info"), + name_cbq_("name"), + capabilities_cbq_("capabilities"), + location_cbq_("location"), + sv_info_list_cbq_("sv_info") {} + +Return GnssCallback::gnssSetSystemInfoCb(const IGnssCallback_1_0::GnssSystemInfo& info) { + ALOGI("Info received, year %d", info.yearOfHw); + info_cbq_.store(info); + return Void(); +} + +Return GnssCallback::gnssSetCapabilitesCb(uint32_t capabilities) { + ALOGI("Capabilities received %d", capabilities); + capabilities_cbq_.store(capabilities); + return Void(); +} + +Return GnssCallback::gnssSetCapabilitiesCb_2_0(uint32_t capabilities) { + ALOGI("Capabilities (v2.0) received %d", capabilities); + capabilities_cbq_.store(capabilities); + return Void(); +} + +Return GnssCallback::gnssSetCapabilitiesCb_2_1(uint32_t capabilities) { + ALOGI("Capabilities (v2.1) received %d", capabilities); + capabilities_cbq_.store(capabilities); + return Void(); +} + +Return GnssCallback::gnssNameCb(const android::hardware::hidl_string& name) { + ALOGI("Name received: %s", name.c_str()); + name_cbq_.store(name); + return Void(); +} + +Return GnssCallback::gnssLocationCb(const GnssLocation_1_0& location) { + ALOGI("Location received"); + GnssLocation_2_0 location_v2_0; + location_v2_0.v1_0 = location; + return gnssLocationCbImpl(location_v2_0); +} + +Return GnssCallback::gnssLocationCb_2_0(const GnssLocation_2_0& location) { + ALOGI("Location (v2.0) received"); + return gnssLocationCbImpl(location); +} + +Return GnssCallback::gnssLocationCbImpl(const GnssLocation_2_0& location) { + location_cbq_.store(location); + return Void(); +} + +Return GnssCallback::gnssSvStatusCb(const IGnssCallback_1_0::GnssSvStatus&) { + ALOGI("gnssSvStatusCb"); + return Void(); +} + +Return GnssCallback::gnssSvStatusCb_2_1( + const hidl_vec& svInfoList) { + ALOGI("gnssSvStatusCb_2_1. Size = %d", (int)svInfoList.size()); + sv_info_list_cbq_.store(svInfoList); + return Void(); +} + +} // namespace android::hardware::gnss::common diff --git a/graphics/common/aidl/Android.bp b/graphics/common/aidl/Android.bp index 2a7adced97e7009592617468633d8ac756072935..b23d4a7caf223e484104b25c08b26a373d6374d8 100644 --- a/graphics/common/aidl/Android.bp +++ b/graphics/common/aidl/Android.bp @@ -39,5 +39,8 @@ aidl_interface { min_sdk_version: "29", }, }, - versions: ["1"], + versions: [ + "1", + "2", + ], } diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/.hash b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/.hash new file mode 100644 index 0000000000000000000000000000000000000000..167ed0e3003c494084fb3ae66afb04ca53157caf --- /dev/null +++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/.hash @@ -0,0 +1 @@ +bd2f5e2ab1d5112dfe982f64012e425f544c9d60 diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/BlendMode.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/BlendMode.aidl new file mode 100644 index 0000000000000000000000000000000000000000..1c1938105e870e78c2e31cd39d50c989ffee4b02 --- /dev/null +++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/BlendMode.aidl @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2019, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.graphics.common; +@Backing(type="int") @VintfStability +enum BlendMode { + INVALID = 0, + NONE = 1, + PREMULTIPLIED = 2, + COVERAGE = 3, +} diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/BufferUsage.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/BufferUsage.aidl new file mode 100644 index 0000000000000000000000000000000000000000..b4ef4515c7ee2a033e94849c7a176382b7726b05 --- /dev/null +++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/BufferUsage.aidl @@ -0,0 +1,63 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.graphics.common; +@Backing(type="long") @VintfStability +enum BufferUsage { + CPU_READ_MASK = 15, + CPU_READ_NEVER = 0, + CPU_READ_RARELY = 2, + CPU_READ_OFTEN = 3, + CPU_WRITE_MASK = 240, + CPU_WRITE_NEVER = 0, + CPU_WRITE_RARELY = 32, + CPU_WRITE_OFTEN = 48, + GPU_TEXTURE = 256, + GPU_RENDER_TARGET = 512, + COMPOSER_OVERLAY = 2048, + COMPOSER_CLIENT_TARGET = 4096, + PROTECTED = 16384, + COMPOSER_CURSOR = 32768, + VIDEO_ENCODER = 65536, + CAMERA_OUTPUT = 131072, + CAMERA_INPUT = 262144, + RENDERSCRIPT = 1048576, + VIDEO_DECODER = 4194304, + SENSOR_DIRECT_DATA = 8388608, + GPU_CUBE_MAP = 33554432, + GPU_MIPMAP_COMPLETE = 67108864, + HW_IMAGE_ENCODER = 134217728, + GPU_DATA_BUFFER = 16777216, + VENDOR_MASK = -268435456, + VENDOR_MASK_HI = -281474976710656, +} diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/ChromaSiting.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/ChromaSiting.aidl new file mode 100644 index 0000000000000000000000000000000000000000..7f0d73460a26fdf1fb749a816565cd0305b88367 --- /dev/null +++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/ChromaSiting.aidl @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2019, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.graphics.common; +@Backing(type="long") @VintfStability +enum ChromaSiting { + NONE = 0, + UNKNOWN = 1, + SITED_INTERSTITIAL = 2, + COSITED_HORIZONTAL = 3, +} diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/Compression.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/Compression.aidl new file mode 100644 index 0000000000000000000000000000000000000000..5b76376a2e10d0a33d5ef2c16c6769415be01a6b --- /dev/null +++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/Compression.aidl @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2019, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.graphics.common; +@Backing(type="long") @VintfStability +enum Compression { + NONE = 0, + DISPLAY_STREAM_COMPRESSION = 1, +} diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/Cta861_3.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/Cta861_3.aidl new file mode 100644 index 0000000000000000000000000000000000000000..fbe4b2a4d21c1a372b2017cb2a2fe2bf5b0294a4 --- /dev/null +++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/Cta861_3.aidl @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2019, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.graphics.common; +@VintfStability +parcelable Cta861_3 { + float maxContentLightLevel; + float maxFrameAverageLightLevel; +} diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/Dataspace.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/Dataspace.aidl new file mode 100644 index 0000000000000000000000000000000000000000..3d97cff0d283c6d21e4fb0270e2124281a693b51 --- /dev/null +++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/Dataspace.aidl @@ -0,0 +1,97 @@ +/** + * Copyright (c) 2019, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.graphics.common; +@Backing(type="int") @VintfStability +enum Dataspace { + UNKNOWN = 0, + ARBITRARY = 1, + STANDARD_SHIFT = 16, + STANDARD_MASK = 4128768, + STANDARD_UNSPECIFIED = 0, + STANDARD_BT709 = 65536, + STANDARD_BT601_625 = 131072, + STANDARD_BT601_625_UNADJUSTED = 196608, + STANDARD_BT601_525 = 262144, + STANDARD_BT601_525_UNADJUSTED = 327680, + STANDARD_BT2020 = 393216, + STANDARD_BT2020_CONSTANT_LUMINANCE = 458752, + STANDARD_BT470M = 524288, + STANDARD_FILM = 589824, + STANDARD_DCI_P3 = 655360, + STANDARD_ADOBE_RGB = 720896, + TRANSFER_SHIFT = 22, + TRANSFER_MASK = 130023424, + TRANSFER_UNSPECIFIED = 0, + TRANSFER_LINEAR = 4194304, + TRANSFER_SRGB = 8388608, + TRANSFER_SMPTE_170M = 12582912, + TRANSFER_GAMMA2_2 = 16777216, + TRANSFER_GAMMA2_6 = 20971520, + TRANSFER_GAMMA2_8 = 25165824, + TRANSFER_ST2084 = 29360128, + TRANSFER_HLG = 33554432, + RANGE_SHIFT = 27, + RANGE_MASK = 939524096, + RANGE_UNSPECIFIED = 0, + RANGE_FULL = 134217728, + RANGE_LIMITED = 268435456, + RANGE_EXTENDED = 402653184, + SRGB_LINEAR = 138477568, + SCRGB_LINEAR = 406913024, + SRGB = 142671872, + SCRGB = 411107328, + JFIF = 146931712, + BT601_625 = 281149440, + BT601_525 = 281280512, + BT709 = 281083904, + DCI_P3_LINEAR = 139067392, + DCI_P3 = 155844608, + DISPLAY_P3_LINEAR = 139067392, + DISPLAY_P3 = 143261696, + ADOBE_RGB = 151715840, + BT2020_LINEAR = 138805248, + BT2020 = 147193856, + BT2020_PQ = 163971072, + DEPTH = 4096, + SENSOR = 4097, + BT2020_ITU = 281411584, + BT2020_ITU_PQ = 298188800, + BT2020_ITU_HLG = 302383104, + BT2020_HLG = 168165376, + DISPLAY_BT2020 = 142999552, + DYNAMIC_DEPTH = 4098, + JPEG_APP_SEGMENTS = 4099, + HEIF = 4100, + BT709_FULL_RANGE = 146866176, +} diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/ExtendableType.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/ExtendableType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..3ada312a5c1376e79fd1599b69ecb12153f4b1bd --- /dev/null +++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/ExtendableType.aidl @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2019, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.graphics.common; +@VintfStability +parcelable ExtendableType { + @utf8InCpp String name; + long value = 0; +} diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/HardwareBuffer.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/HardwareBuffer.aidl new file mode 100644 index 0000000000000000000000000000000000000000..4d8f78d77cfbb3599d058ca143371de6ff7b985f --- /dev/null +++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/HardwareBuffer.aidl @@ -0,0 +1,39 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.graphics.common; +@VintfStability +parcelable HardwareBuffer { + android.hardware.graphics.common.HardwareBufferDescription description; + android.hardware.common.NativeHandle handle; +} diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/HardwareBufferDescription.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/HardwareBufferDescription.aidl new file mode 100644 index 0000000000000000000000000000000000000000..495504931dbd21e44b4969b9f4b6b5d8058ade9d --- /dev/null +++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/HardwareBufferDescription.aidl @@ -0,0 +1,43 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.graphics.common; +@VintfStability +parcelable HardwareBufferDescription { + int width; + int height; + int layers; + android.hardware.graphics.common.PixelFormat format = android.hardware.graphics.common.PixelFormat.UNSPECIFIED; + android.hardware.graphics.common.BufferUsage usage = android.hardware.graphics.common.BufferUsage.CPU_READ_NEVER; + int stride; +} diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/Interlaced.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/Interlaced.aidl new file mode 100644 index 0000000000000000000000000000000000000000..30b4e03c45c3a4853a9ee93e68637e59d2107299 --- /dev/null +++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/Interlaced.aidl @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2019, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.graphics.common; +@Backing(type="long") @VintfStability +enum Interlaced { + NONE = 0, + TOP_BOTTOM = 1, + RIGHT_LEFT = 2, +} diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/PixelFormat.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/PixelFormat.aidl new file mode 100644 index 0000000000000000000000000000000000000000..04a863be0a4c51030d02b8ad41032953a7ce723f --- /dev/null +++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/PixelFormat.aidl @@ -0,0 +1,66 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.graphics.common; +@Backing(type="int") @VintfStability +enum PixelFormat { + UNSPECIFIED = 0, + RGBA_8888 = 1, + RGBX_8888 = 2, + RGB_888 = 3, + RGB_565 = 4, + BGRA_8888 = 5, + YCBCR_422_SP = 16, + YCRCB_420_SP = 17, + YCBCR_422_I = 20, + RGBA_FP16 = 22, + RAW16 = 32, + BLOB = 33, + IMPLEMENTATION_DEFINED = 34, + YCBCR_420_888 = 35, + RAW_OPAQUE = 36, + RAW10 = 37, + RAW12 = 38, + RGBA_1010102 = 43, + Y8 = 538982489, + Y16 = 540422489, + YV12 = 842094169, + DEPTH_16 = 48, + DEPTH_24 = 49, + DEPTH_24_STENCIL_8 = 50, + DEPTH_32F = 51, + DEPTH_32F_STENCIL_8 = 52, + STENCIL_8 = 53, + YCBCR_P010 = 54, + HSV_888 = 55, +} diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/PlaneLayout.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/PlaneLayout.aidl new file mode 100644 index 0000000000000000000000000000000000000000..75fac9f3db13bbb6765482b0909e9f370d9cddda --- /dev/null +++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/PlaneLayout.aidl @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2019, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.graphics.common; +@VintfStability +parcelable PlaneLayout { + android.hardware.graphics.common.PlaneLayoutComponent[] components; + long offsetInBytes; + long sampleIncrementInBits; + long strideInBytes; + long widthInSamples; + long heightInSamples; + long totalSizeInBytes; + long horizontalSubsampling; + long verticalSubsampling; +} diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/PlaneLayoutComponent.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/PlaneLayoutComponent.aidl new file mode 100644 index 0000000000000000000000000000000000000000..20c0a0bb0109fdeceeca632f2a67a96c5a211816 --- /dev/null +++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/PlaneLayoutComponent.aidl @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2019, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.graphics.common; +@VintfStability +parcelable PlaneLayoutComponent { + android.hardware.graphics.common.ExtendableType type; + long offsetInBits; + long sizeInBits; +} diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/PlaneLayoutComponentType.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/PlaneLayoutComponentType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..2f7d414aaceba9e732c94fcfeeddf09708790144 --- /dev/null +++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/PlaneLayoutComponentType.aidl @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2019, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.graphics.common; +@Backing(type="long") @VintfStability +enum PlaneLayoutComponentType { + Y = 1, + CB = 2, + CR = 4, + R = 1024, + G = 2048, + B = 4096, + RAW = 1048576, + A = 1073741824, +} diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/Rect.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/Rect.aidl new file mode 100644 index 0000000000000000000000000000000000000000..eb42027f16cc0254043672b34ac934334ca5fcdd --- /dev/null +++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/Rect.aidl @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2019, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.graphics.common; +@VintfStability +parcelable Rect { + int left; + int top; + int right; + int bottom; +} diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/Smpte2086.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/Smpte2086.aidl new file mode 100644 index 0000000000000000000000000000000000000000..2be31d8e9934eb4c1e99215c616a3d6ebe3fdb0f --- /dev/null +++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/Smpte2086.aidl @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2019, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.graphics.common; +@VintfStability +parcelable Smpte2086 { + android.hardware.graphics.common.XyColor primaryRed; + android.hardware.graphics.common.XyColor primaryGreen; + android.hardware.graphics.common.XyColor primaryBlue; + android.hardware.graphics.common.XyColor whitePoint; + float maxLuminance; + float minLuminance; +} diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/StandardMetadataType.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/StandardMetadataType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..20273501b9fe9337be870c11f7830dd1951ea4b0 --- /dev/null +++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/StandardMetadataType.aidl @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2019,libgralloctypes_helper The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.graphics.common; +@Backing(type="long") @VintfStability +enum StandardMetadataType { + INVALID = 0, + BUFFER_ID = 1, + NAME = 2, + WIDTH = 3, + HEIGHT = 4, + LAYER_COUNT = 5, + PIXEL_FORMAT_REQUESTED = 6, + PIXEL_FORMAT_FOURCC = 7, + PIXEL_FORMAT_MODIFIER = 8, + USAGE = 9, + ALLOCATION_SIZE = 10, + PROTECTED_CONTENT = 11, + COMPRESSION = 12, + INTERLACED = 13, + CHROMA_SITING = 14, + PLANE_LAYOUTS = 15, + CROP = 16, + DATASPACE = 17, + BLEND_MODE = 18, + SMPTE2086 = 19, + CTA861_3 = 20, + SMPTE2094_40 = 21, +} diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/XyColor.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/XyColor.aidl new file mode 100644 index 0000000000000000000000000000000000000000..b42de183dd04d6af7a8edb72432d5d8c2ad8e72e --- /dev/null +++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/2/android/hardware/graphics/common/XyColor.aidl @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2019, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.graphics.common; +@VintfStability +parcelable XyColor { + float x; + float y; +} diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h index 47ead41fb0da40e0d4fa263920e6e8ec0b17e998..46f5d6e1e0da97b43047ad6c446d535df3a4b088 100644 --- a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h +++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h @@ -87,19 +87,28 @@ class ComposerClientImpl : public Interface { class HalEventCallback : public Hal::EventCallback { public: - HalEventCallback(const sp callback, ComposerResources* resources) - : mCallback(callback), mResources(resources) {} - - void onHotplug(Display display, IComposerCallback::Connection connected) { - if (connected == IComposerCallback::Connection::CONNECTED) { - mResources->addPhysicalDisplay(display); - } else if (connected == IComposerCallback::Connection::DISCONNECTED) { - mResources->removeDisplay(display); - } - - auto ret = mCallback->onHotplug(display, connected); - ALOGE_IF(!ret.isOk(), "failed to send onHotplug: %s", ret.description().c_str()); - } + HalEventCallback(Hal* hal, const sp callback, + ComposerResources* resources) + : mHal(hal), mCallback(callback), mResources(resources) {} + + void onHotplug(Display display, IComposerCallback::Connection connected) { + if (connected == IComposerCallback::Connection::CONNECTED) { + if (mResources->hasDisplay(display)) { + // This is a subsequent hotplug "connected" for a display. This signals a + // display change and thus the framework may want to reallocate buffers. We + // need to free all cached handles, since they are holding a strong reference + // to the underlying buffers. + cleanDisplayResources(display, mResources, mHal); + mResources->removeDisplay(display); + } + mResources->addPhysicalDisplay(display); + } else if (connected == IComposerCallback::Connection::DISCONNECTED) { + mResources->removeDisplay(display); + } + + auto ret = mCallback->onHotplug(display, connected); + ALOGE_IF(!ret.isOk(), "failed to send onHotplug: %s", ret.description().c_str()); + } void onRefresh(Display display) { mResources->setDisplayMustValidateState(display, true); @@ -113,13 +122,14 @@ class ComposerClientImpl : public Interface { } protected: - const sp mCallback; - ComposerResources* const mResources; + Hal* const mHal; + const sp mCallback; + ComposerResources* const mResources; }; Return registerCallback(const sp& callback) override { // no locking as we require this function to be called only once - mHalEventCallback = std::make_unique(callback, mResources.get()); + mHalEventCallback = std::make_unique(mHal, callback, mResources.get()); mHal->registerEventCallback(mHalEventCallback.get()); return Void(); } @@ -320,6 +330,57 @@ class ComposerClientImpl : public Interface { return std::make_unique(mHal, mResources.get()); } + static void cleanDisplayResources(Display display, ComposerResources* const resources, + Hal* const hal) { + size_t cacheSize; + Error err = resources->getDisplayClientTargetCacheSize(display, &cacheSize); + if (err == Error::NONE) { + for (int slot = 0; slot < cacheSize; slot++) { + ComposerResources::ReplacedHandle replacedBuffer(/*isBuffer*/ true); + // Replace the buffer slots with NULLs. Keep the old handle until it is + // replaced in ComposerHal, otherwise we risk leaving a dangling pointer. + const native_handle_t* clientTarget = nullptr; + err = resources->getDisplayClientTarget(display, slot, /*useCache*/ true, + /*rawHandle*/ nullptr, &clientTarget, + &replacedBuffer); + if (err != Error::NONE) { + continue; + } + const std::vector damage; + err = hal->setClientTarget(display, clientTarget, /*fence*/ -1, 0, damage); + ALOGE_IF(err != Error::NONE, + "Can't clean slot %d of the client target buffer" + "cache for display %" PRIu64, + slot, display); + } + } else { + ALOGE("Can't clean client target cache for display %" PRIu64, display); + } + + err = resources->getDisplayOutputBufferCacheSize(display, &cacheSize); + if (err == Error::NONE) { + for (int slot = 0; slot < cacheSize; slot++) { + // Replace the buffer slots with NULLs. Keep the old handle until it is + // replaced in ComposerHal, otherwise we risk leaving a dangling pointer. + ComposerResources::ReplacedHandle replacedBuffer(/*isBuffer*/ true); + const native_handle_t* outputBuffer = nullptr; + err = resources->getDisplayOutputBuffer(display, slot, /*useCache*/ true, + /*rawHandle*/ nullptr, &outputBuffer, + &replacedBuffer); + if (err != Error::NONE) { + continue; + } + err = hal->setOutputBuffer(display, outputBuffer, /*fence*/ -1); + ALOGE_IF(err != Error::NONE, + "Can't clean slot %d of the output buffer cache" + "for display %" PRIu64, + slot, display); + } + } else { + ALOGE("Can't clean output buffer cache for display %" PRIu64, display); + } + } + void destroyResources() { // We want to call hwc2_close here (and move hwc2_open to the // constructor), with the assumption that hwc2_close would diff --git a/graphics/composer/2.1/utils/resources/Android.bp b/graphics/composer/2.1/utils/resources/Android.bp index 6dbd7f509639f307e99401d3976c15c2b4eedab3..9eb23fa82e830d22e7c63726a20dba6e7637ebc9 100644 --- a/graphics/composer/2.1/utils/resources/Android.bp +++ b/graphics/composer/2.1/utils/resources/Android.bp @@ -24,6 +24,7 @@ package { cc_library { name: "android.hardware.graphics.composer@2.1-resources", + system_ext_specific: true, defaults: ["hidl_defaults"], vendor_available: true, shared_libs: [ diff --git a/graphics/composer/2.1/utils/resources/ComposerResources.cpp b/graphics/composer/2.1/utils/resources/ComposerResources.cpp index 21f60355f8e965ae6ca80cfd494b5907db701daf..e52bf7124a5f0d5c6ae60db9d32778f04f9ac746 100644 --- a/graphics/composer/2.1/utils/resources/ComposerResources.cpp +++ b/graphics/composer/2.1/utils/resources/ComposerResources.cpp @@ -144,6 +144,10 @@ ComposerHandleCache::~ComposerHandleCache() { } } +size_t ComposerHandleCache::getCacheSize() const { + return mHandles.size(); +} + bool ComposerHandleCache::initCache(HandleType type, uint32_t cacheSize) { // already initialized if (mHandleType != HandleType::INVALID) { @@ -220,6 +224,14 @@ bool ComposerDisplayResource::initClientTargetCache(uint32_t cacheSize) { return mClientTargetCache.initCache(ComposerHandleCache::HandleType::BUFFER, cacheSize); } +size_t ComposerDisplayResource::getClientTargetCacheSize() const { + return mClientTargetCache.getCacheSize(); +} + +size_t ComposerDisplayResource::getOutputBufferCacheSize() const { + return mOutputBufferCache.getCacheSize(); +} + bool ComposerDisplayResource::isVirtual() const { return mType == DisplayType::VIRTUAL; } @@ -293,6 +305,10 @@ void ComposerResources::clear(RemoveDisplay removeDisplay) { mDisplayResources.clear(); } +bool ComposerResources::hasDisplay(Display display) { + return mDisplayResources.count(display) > 0; +} + Error ComposerResources::addPhysicalDisplay(Display display) { auto displayResource = createDisplayResource(ComposerDisplayResource::DisplayType::PHYSICAL, 0); @@ -327,6 +343,26 @@ Error ComposerResources::setDisplayClientTargetCacheSize(Display display, : Error::BAD_PARAMETER; } +Error ComposerResources::getDisplayClientTargetCacheSize(Display display, size_t* outCacheSize) { + std::lock_guard lock(mDisplayResourcesMutex); + ComposerDisplayResource* displayResource = findDisplayResourceLocked(display); + if (!displayResource) { + return Error::BAD_DISPLAY; + } + *outCacheSize = displayResource->getClientTargetCacheSize(); + return Error::NONE; +} + +Error ComposerResources::getDisplayOutputBufferCacheSize(Display display, size_t* outCacheSize) { + std::lock_guard lock(mDisplayResourcesMutex); + ComposerDisplayResource* displayResource = findDisplayResourceLocked(display); + if (!displayResource) { + return Error::BAD_DISPLAY; + } + *outCacheSize = displayResource->getOutputBufferCacheSize(); + return Error::NONE; +} + Error ComposerResources::addLayer(Display display, Layer layer, uint32_t bufferCacheSize) { auto layerResource = createLayerResource(bufferCacheSize); diff --git a/graphics/composer/2.1/utils/resources/include/composer-resources/2.1/ComposerResources.h b/graphics/composer/2.1/utils/resources/include/composer-resources/2.1/ComposerResources.h index 37382785592d1b4c024a0e49a38bd959ea155a53..de78a59e91330cca5be3cd6e8cc7899bf0e40806 100644 --- a/graphics/composer/2.1/utils/resources/include/composer-resources/2.1/ComposerResources.h +++ b/graphics/composer/2.1/utils/resources/include/composer-resources/2.1/ComposerResources.h @@ -74,6 +74,7 @@ class ComposerHandleCache { ComposerHandleCache& operator=(const ComposerHandleCache&) = delete; bool initCache(HandleType type, uint32_t cacheSize); + size_t getCacheSize() const; Error lookupCache(uint32_t slot, const native_handle_t** outHandle); Error updateCache(uint32_t slot, const native_handle_t* handle, const native_handle** outReplacedHandle); @@ -120,7 +121,8 @@ class ComposerDisplayResource { uint32_t outputBufferCacheSize); bool initClientTargetCache(uint32_t cacheSize); - + size_t getClientTargetCacheSize() const; + size_t getOutputBufferCacheSize() const; bool isVirtual() const; Error getClientTarget(uint32_t slot, bool fromCache, const native_handle_t* inHandle, @@ -162,12 +164,15 @@ class ComposerResources { std::function& layers)>; void clear(RemoveDisplay removeDisplay); + bool hasDisplay(Display display); Error addPhysicalDisplay(Display display); Error addVirtualDisplay(Display display, uint32_t outputBufferCacheSize); Error removeDisplay(Display display); Error setDisplayClientTargetCacheSize(Display display, uint32_t clientTargetCacheSize); + Error getDisplayClientTargetCacheSize(Display display, size_t* outCacheSize); + Error getDisplayOutputBufferCacheSize(Display display, size_t* outCacheSize); Error addLayer(Display display, Layer layer, uint32_t bufferCacheSize); Error removeLayer(Display display, Layer layer); @@ -177,7 +182,8 @@ class ComposerResources { bool mustValidateDisplay(Display display); // When a buffer in the cache is replaced by a new one, we must keep it - // alive until it has been replaced in ComposerHal. + // alive until it has been replaced in ComposerHal because it is still using + // the old buffer. class ReplacedHandle { public: explicit ReplacedHandle(bool isBuffer) : mIsBuffer(isBuffer) {} diff --git a/graphics/composer/2.1/utils/vts/ComposerVts.cpp b/graphics/composer/2.1/utils/vts/ComposerVts.cpp index 4b6b7c86b887607d478c0aaaee7d2a1f32c66fff..55aaf12b8e39aeb860ecdc69675ec659013af3d7 100644 --- a/graphics/composer/2.1/utils/vts/ComposerVts.cpp +++ b/graphics/composer/2.1/utils/vts/ComposerVts.cpp @@ -308,6 +308,12 @@ void ComposerClient::execute(TestCommandReader* reader, CommandWriterBase* write writer->reset(); } +NativeHandleWrapper::~NativeHandleWrapper() { + if (mHandle) { + mGralloc.freeBuffer(mHandle); + } +} + Gralloc::Gralloc() { [this] { ASSERT_NO_FATAL_FAILURE(mGralloc4 = std::make_shared("default", "default", @@ -324,9 +330,10 @@ Gralloc::Gralloc() { }(); } -const native_handle_t* Gralloc::allocate(uint32_t width, uint32_t height, uint32_t layerCount, - PixelFormat format, uint64_t usage, bool import, - uint32_t* outStride) { +const NativeHandleWrapper Gralloc::allocate(uint32_t width, uint32_t height, uint32_t layerCount, + PixelFormat format, uint64_t usage, bool import, + uint32_t* outStride) { + const native_handle_t* handle; if (mGralloc4) { IMapper4::BufferDescriptorInfo info{}; info.width = width; @@ -334,7 +341,7 @@ const native_handle_t* Gralloc::allocate(uint32_t width, uint32_t height, uint32 info.layerCount = layerCount; info.format = static_cast(format); info.usage = usage; - return mGralloc4->allocate(info, import, outStride); + handle = mGralloc4->allocate(info, import, outStride); } else if (mGralloc3) { IMapper3::BufferDescriptorInfo info{}; info.width = width; @@ -342,7 +349,7 @@ const native_handle_t* Gralloc::allocate(uint32_t width, uint32_t height, uint32 info.layerCount = layerCount; info.format = static_cast(format); info.usage = usage; - return mGralloc3->allocate(info, import, outStride); + handle = mGralloc3->allocate(info, import, outStride); } else { IMapper2::BufferDescriptorInfo info{}; info.width = width; @@ -350,8 +357,9 @@ const native_handle_t* Gralloc::allocate(uint32_t width, uint32_t height, uint32 info.layerCount = layerCount; info.format = format; info.usage = usage; - return mGralloc2->allocate(info, import, outStride); + handle = mGralloc2->allocate(info, import, outStride); } + return NativeHandleWrapper(*this, handle); } void* Gralloc::lock(const native_handle_t* bufferHandle, uint64_t cpuUsage, diff --git a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h index 63aa713e54fcb399802d513432d51bc30ee7db72..29498233641863413acff8d71ae16d0429a8f42a 100644 --- a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h +++ b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h @@ -136,13 +136,30 @@ class AccessRegion { int32_t height; }; +class Gralloc; + +// RAII wrapper around native_handle_t* +class NativeHandleWrapper { + public: + NativeHandleWrapper(Gralloc& gralloc, const native_handle_t* handle) + : mGralloc(gralloc), mHandle(handle) {} + + ~NativeHandleWrapper(); + + const native_handle_t* get() { return mHandle; } + + private: + Gralloc& mGralloc; + const native_handle_t* mHandle; +}; + class Gralloc { public: explicit Gralloc(); - const native_handle_t* allocate(uint32_t width, uint32_t height, uint32_t layerCount, - PixelFormat format, uint64_t usage, bool import = true, - uint32_t* outStride = nullptr); + const NativeHandleWrapper allocate(uint32_t width, uint32_t height, uint32_t layerCount, + PixelFormat format, uint64_t usage, bool import = true, + uint32_t* outStride = nullptr); void* lock(const native_handle_t* bufferHandle, uint64_t cpuUsage, const AccessRegion& accessRegionRect, int acquireFence); diff --git a/graphics/composer/2.1/vts/OWNERS b/graphics/composer/2.1/vts/OWNERS index 0b42d2ef84d64fcd41adea6f52a779f908f00996..ea06752da79f2c260fe3e9a807c5f8e722d2fbdd 100644 --- a/graphics/composer/2.1/vts/OWNERS +++ b/graphics/composer/2.1/vts/OWNERS @@ -1,6 +1,6 @@ # Graphics team +adyabr@google.com lpy@google.com -vhau@google.com # VTS team yim@google.com diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp index 2604be6d4692f53e31258e1f2e6ab90fd5a71d60..48226785d50206c8fd9c0033618013f60be96c05 100644 --- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp +++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp @@ -666,7 +666,7 @@ class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest { ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown()); } - const native_handle_t* allocate() { + NativeHandleWrapper allocate() { uint64_t usage = static_cast(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN | BufferUsage::COMPOSER_OVERLAY); @@ -727,11 +727,11 @@ TEST_P(GraphicsComposerHidlCommandTest, SET_OUTPUT_BUFFER) { display = mComposerClient->createVirtualDisplay(64, 64, PixelFormat::IMPLEMENTATION_DEFINED, kBufferSlotCount, &format)); - const native_handle_t* handle; - ASSERT_NO_FATAL_FAILURE(handle = allocate()); + std::unique_ptr handle; + ASSERT_NO_FATAL_FAILURE(handle.reset(new NativeHandleWrapper(allocate()))); mWriter->selectDisplay(display); - mWriter->setOutputBuffer(0, handle, -1); + mWriter->setOutputBuffer(0, handle->get(), -1); execute(); } @@ -783,7 +783,7 @@ TEST_P(GraphicsComposerHidlCommandTest, PRESENT_DISPLAY_NO_LAYER_STATE_CHANGES) mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::NATIVE); auto handle = allocate(); - ASSERT_NE(nullptr, handle); + ASSERT_NE(nullptr, handle.get()); IComposerClient::Rect displayFrame{0, 0, mDisplayWidth, mDisplayHeight}; @@ -800,7 +800,7 @@ TEST_P(GraphicsComposerHidlCommandTest, PRESENT_DISPLAY_NO_LAYER_STATE_CHANGES) mWriter->setLayerZOrder(10); mWriter->setLayerBlendMode(IComposerClient::BlendMode::NONE); mWriter->setLayerSurfaceDamage(std::vector(1, displayFrame)); - mWriter->setLayerBuffer(0, handle, -1); + mWriter->setLayerBuffer(0, handle.get(), -1); mWriter->setLayerDataspace(Dataspace::UNKNOWN); mWriter->validateDisplay(); @@ -817,8 +817,8 @@ TEST_P(GraphicsComposerHidlCommandTest, PRESENT_DISPLAY_NO_LAYER_STATE_CHANGES) mWriter->selectLayer(layer); auto handle2 = allocate(); - ASSERT_NE(nullptr, handle2); - mWriter->setLayerBuffer(0, handle2, -1); + ASSERT_NE(nullptr, handle2.get()); + mWriter->setLayerBuffer(0, handle2.get(), -1); mWriter->setLayerSurfaceDamage(std::vector(1, {0, 0, 10, 10})); mWriter->presentDisplay(); execute(); @@ -833,12 +833,12 @@ TEST_P(GraphicsComposerHidlCommandTest, SET_LAYER_CURSOR_POSITION) { mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); auto handle = allocate(); - ASSERT_NE(nullptr, handle); + ASSERT_NE(nullptr, handle.get()); IComposerClient::Rect displayFrame{0, 0, mDisplayWidth, mDisplayHeight}; mWriter->selectDisplay(mPrimaryDisplay); mWriter->selectLayer(layer); - mWriter->setLayerBuffer(0, handle, -1); + mWriter->setLayerBuffer(0, handle.get(), -1); mWriter->setLayerCompositionType(IComposerClient::Composition::CURSOR); mWriter->setLayerDisplayFrame(displayFrame); mWriter->setLayerPlaneAlpha(1); @@ -871,7 +871,7 @@ TEST_P(GraphicsComposerHidlCommandTest, SET_LAYER_CURSOR_POSITION) { */ TEST_P(GraphicsComposerHidlCommandTest, SET_LAYER_BUFFER) { auto handle = allocate(); - ASSERT_NE(nullptr, handle); + ASSERT_NE(nullptr, handle.get()); Layer layer; ASSERT_NO_FATAL_FAILURE(layer = @@ -879,7 +879,7 @@ TEST_P(GraphicsComposerHidlCommandTest, SET_LAYER_BUFFER) { mWriter->selectDisplay(mPrimaryDisplay); mWriter->selectLayer(layer); - mWriter->setLayerBuffer(0, handle, -1); + mWriter->setLayerBuffer(0, handle.get(), -1); execute(); } @@ -1003,7 +1003,7 @@ TEST_P(GraphicsComposerHidlCommandTest, SET_LAYER_SIDEBAND_STREAM) { } auto handle = allocate(); - ASSERT_NE(nullptr, handle); + ASSERT_NE(nullptr, handle.get()); Layer layer; ASSERT_NO_FATAL_FAILURE(layer = @@ -1011,7 +1011,7 @@ TEST_P(GraphicsComposerHidlCommandTest, SET_LAYER_SIDEBAND_STREAM) { mWriter->selectDisplay(mPrimaryDisplay); mWriter->selectLayer(layer); - mWriter->setLayerSidebandStream(handle); + mWriter->setLayerSidebandStream(handle.get()); execute(); } @@ -1084,11 +1084,13 @@ TEST_P(GraphicsComposerHidlCommandTest, SET_LAYER_Z_ORDER) { execute(); } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsComposerHidlCommandTest); INSTANTIATE_TEST_SUITE_P( PerInstance, GraphicsComposerHidlCommandTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames(IComposer::descriptor)), android::hardware::PrintInstanceNameToString); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsComposerHidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, GraphicsComposerHidlTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames(IComposer::descriptor)), diff --git a/graphics/composer/2.2/utils/vts/ReadbackVts.cpp b/graphics/composer/2.2/utils/vts/ReadbackVts.cpp index 7bb9121cba92496832a734f71fd0a764753b1454..30596fc4c9fc3efbd0552fef83a54e1b37ef55cf 100644 --- a/graphics/composer/2.2/utils/vts/ReadbackVts.cpp +++ b/graphics/composer/2.2/utils/vts/ReadbackVts.cpp @@ -15,6 +15,8 @@ */ #include +#include +#include "renderengine/ExternalTexture.h" namespace android { namespace hardware { @@ -206,22 +208,13 @@ ReadbackBuffer::ReadbackBuffer(Display display, const std::shared_ptrfreeBuffer(mBufferHandle); - } -} - void ReadbackBuffer::setReadbackBuffer() { - if (mBufferHandle != nullptr) { - mGralloc->freeBuffer(mBufferHandle); - mBufferHandle = nullptr; - } - mBufferHandle = mGralloc->allocate(mWidth, mHeight, mLayerCount, mFormat, mUsage, - /*import*/ true, &mStride); - ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle, mWidth, mHeight, mLayerCount, - mFormat, mUsage, mStride)); - ASSERT_NO_FATAL_FAILURE(mComposerClient->setReadbackBuffer(mDisplay, mBufferHandle, -1)); + mBufferHandle.reset(new Gralloc::NativeHandleWrapper( + mGralloc->allocate(mWidth, mHeight, mLayerCount, mFormat, mUsage, + /*import*/ true, &mStride))); + ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle->get(), mWidth, mHeight, + mLayerCount, mFormat, mUsage, mStride)); + ASSERT_NO_FATAL_FAILURE(mComposerClient->setReadbackBuffer(mDisplay, mBufferHandle->get(), -1)); } void ReadbackBuffer::checkReadbackBuffer(std::vector expectedColors) { @@ -229,11 +222,11 @@ void ReadbackBuffer::checkReadbackBuffer(std::vector exp int32_t fenceHandle; ASSERT_NO_FATAL_FAILURE(mComposerClient->getReadbackBufferFence(mDisplay, &fenceHandle)); - void* bufData = mGralloc->lock(mBufferHandle, mUsage, mAccessRegion, fenceHandle); + void* bufData = mGralloc->lock(mBufferHandle->get(), mUsage, mAccessRegion, fenceHandle); ASSERT_TRUE(mPixelFormat == PixelFormat::RGB_888 || mPixelFormat == PixelFormat::RGBA_8888); ReadbackHelper::compareColorBuffers(expectedColors, bufData, mStride, mWidth, mHeight, mPixelFormat); - int32_t unlockFence = mGralloc->unlock(mBufferHandle); + int32_t unlockFence = mGralloc->unlock(mBufferHandle->get()); if (unlockFence != -1) { sync_wait(unlockFence, -1); close(unlockFence); @@ -257,10 +250,11 @@ LayerSettings TestColorLayer::toRenderEngineLayerSettings() { } TestBufferLayer::TestBufferLayer(const std::shared_ptr& client, - const std::shared_ptr& gralloc, Display display, - int32_t width, int32_t height, PixelFormat format, + const std::shared_ptr& gralloc, + TestRenderEngine& renderEngine, Display display, int32_t width, + int32_t height, PixelFormat format, IComposerClient::Composition composition) - : TestLayer{client, display} { + : TestLayer{client, display}, mRenderEngine(renderEngine) { mGralloc = gralloc; mComposition = composition; mWidth = width; @@ -268,7 +262,7 @@ TestBufferLayer::TestBufferLayer(const std::shared_ptr& client, mLayerCount = 1; mFormat = format; mUsage = static_cast(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_OVERLAY); + BufferUsage::COMPOSER_OVERLAY | BufferUsage::GPU_TEXTURE); mAccessRegion.top = 0; mAccessRegion.left = 0; @@ -278,24 +272,20 @@ TestBufferLayer::TestBufferLayer(const std::shared_ptr& client, setSourceCrop({0, 0, (float)width, (float)height}); } -TestBufferLayer::~TestBufferLayer() { - if (mBufferHandle != nullptr) { - mGralloc->freeBuffer(mBufferHandle); - } -} - void TestBufferLayer::write(const std::shared_ptr& writer) { TestLayer::write(writer); writer->setLayerCompositionType(mComposition); writer->setLayerVisibleRegion(std::vector(1, mDisplayFrame)); - if (mBufferHandle != nullptr) writer->setLayerBuffer(0, mBufferHandle, mFillFence); + if (mBufferHandle != nullptr) writer->setLayerBuffer(0, mBufferHandle->get(), mFillFence); } LayerSettings TestBufferLayer::toRenderEngineLayerSettings() { LayerSettings layerSettings = TestLayer::toRenderEngineLayerSettings(); - layerSettings.source.buffer.buffer = - new GraphicBuffer(mBufferHandle, GraphicBuffer::CLONE_HANDLE, mWidth, mHeight, - static_cast(mFormat), 1, mUsage, mStride); + layerSettings.source.buffer.buffer = std::make_shared( + new GraphicBuffer(mBufferHandle->get(), GraphicBuffer::CLONE_HANDLE, mWidth, mHeight, + static_cast(mFormat), 1, mUsage, mStride), + mRenderEngine.getInternalRenderEngine(), + renderengine::ExternalTexture::Usage::READABLE); layerSettings.source.buffer.usePremultipliedAlpha = mBlendMode == IComposerClient::BlendMode::PREMULTIPLIED; @@ -313,10 +303,10 @@ LayerSettings TestBufferLayer::toRenderEngineLayerSettings() { } void TestBufferLayer::fillBuffer(std::vector expectedColors) { - void* bufData = mGralloc->lock(mBufferHandle, mUsage, mAccessRegion, -1); + void* bufData = mGralloc->lock(mBufferHandle->get(), mUsage, mAccessRegion, -1); ASSERT_NO_FATAL_FAILURE( ReadbackHelper::fillBuffer(mWidth, mHeight, mStride, bufData, mFormat, expectedColors)); - mFillFence = mGralloc->unlock(mBufferHandle); + mFillFence = mGralloc->unlock(mBufferHandle->get()); if (mFillFence != -1) { sync_wait(mFillFence, -1); close(mFillFence); @@ -324,16 +314,13 @@ void TestBufferLayer::fillBuffer(std::vector expectedCol } void TestBufferLayer::setBuffer(std::vector colors) { - if (mBufferHandle != nullptr) { - mGralloc->freeBuffer(mBufferHandle); - mBufferHandle = nullptr; - } - mBufferHandle = mGralloc->allocate(mWidth, mHeight, mLayerCount, mFormat, mUsage, - /*import*/ true, &mStride); - ASSERT_NE(nullptr, mBufferHandle); + mBufferHandle.reset(new Gralloc::NativeHandleWrapper( + mGralloc->allocate(mWidth, mHeight, mLayerCount, mFormat, mUsage, + /*import*/ true, &mStride))); + ASSERT_NE(nullptr, mBufferHandle->get()); ASSERT_NO_FATAL_FAILURE(fillBuffer(colors)); - ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle, mWidth, mHeight, mLayerCount, - mFormat, mUsage, mStride)); + ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle->get(), mWidth, mHeight, + mLayerCount, mFormat, mUsage, mStride)); } void TestBufferLayer::setDataspace(Dataspace dataspace, diff --git a/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp b/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp index c78c3588577e159546b18c9cfba301ecf5c0ba29..f78dda2689545171e6caa10242641bd3b58a380d 100644 --- a/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp +++ b/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp @@ -69,9 +69,10 @@ void TestRenderEngine::drawLayers() { [](renderengine::LayerSettings& settings) -> renderengine::LayerSettings* { return &settings; }); - mRenderEngine->drawLayers(mDisplaySettings, compositionLayerPointers, - mGraphicBuffer->getNativeBuffer(), true, std::move(bufferFence), - &readyFence); + auto texture = std::make_shared( + mGraphicBuffer, *mRenderEngine, renderengine::ExternalTexture::Usage::WRITEABLE); + mRenderEngine->drawLayers(mDisplaySettings, compositionLayerPointers, texture, true, + std::move(bufferFence), &readyFence); int fd = readyFence.release(); if (fd != -1) { ASSERT_EQ(0, sync_wait(fd, -1)); diff --git a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h index 6bc2732d7ddb3a08bb26d00752faa47d58a738f1..d3bba17ed31fc543f7a53702e7375e0949719088 100644 --- a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h +++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h @@ -93,10 +93,12 @@ class ComposerClient : public V2_1::vts::ComposerClient { class Gralloc : public V2_1::vts::Gralloc { public: + using NativeHandleWrapper = V2_1::vts::NativeHandleWrapper; + Gralloc(); - const native_handle_t* allocate(uint32_t width, uint32_t height, uint32_t layerCount, - PixelFormat format, uint64_t usage, bool import = true, - uint32_t* outStride = nullptr) { + const NativeHandleWrapper allocate(uint32_t width, uint32_t height, uint32_t layerCount, + PixelFormat format, uint64_t usage, bool import = true, + uint32_t* outStride = nullptr) { return V2_1::vts::Gralloc::allocate( width, height, layerCount, static_cast(format), usage, diff --git a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ReadbackVts.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ReadbackVts.h index d5eedf122cf78ef81e1b14168c0c6c9f16ab031b..58efde9b5ace8737e64706a944d36efe85d2d6b1 100644 --- a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ReadbackVts.h +++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ReadbackVts.h @@ -25,6 +25,8 @@ #include #include +#include + namespace android { namespace hardware { namespace graphics { @@ -50,6 +52,8 @@ static const IComposerClient::Color TRANSLUCENT_RED = {0xff, 0, 0, 0x33}; static const IComposerClient::Color GREEN = {0, 0xff, 0, 0xff}; static const IComposerClient::Color BLUE = {0, 0, 0xff, 0xff}; +class TestRenderEngine; + class TestLayer { public: TestLayer(const std::shared_ptr& client, Display display) @@ -110,11 +114,10 @@ class TestBufferLayer : public TestLayer { public: TestBufferLayer( const std::shared_ptr& client, const std::shared_ptr& gralloc, - Display display, int32_t width, int32_t height, PixelFormat format, + TestRenderEngine& renderEngine, Display display, int32_t width, int32_t height, + PixelFormat format, IComposerClient::Composition composition = IComposerClient::Composition::DEVICE); - ~TestBufferLayer(); - void write(const std::shared_ptr& writer) override; LayerSettings toRenderEngineLayerSettings() override; @@ -138,8 +141,9 @@ class TestBufferLayer : public TestLayer { protected: IComposerClient::Composition mComposition; std::shared_ptr mGralloc; + TestRenderEngine& mRenderEngine; int32_t mFillFence; - const native_handle_t* mBufferHandle = nullptr; + std::unique_ptr mBufferHandle; }; class ReadbackHelper { @@ -178,7 +182,6 @@ class ReadbackBuffer { ReadbackBuffer(Display display, const std::shared_ptr& client, const std::shared_ptr& gralloc, uint32_t width, uint32_t height, PixelFormat pixelFormat, Dataspace dataspace); - ~ReadbackBuffer(); void setReadbackBuffer(); @@ -192,7 +195,7 @@ class ReadbackBuffer { uint64_t mUsage; AccessRegion mAccessRegion; uint32_t mStride; - const native_handle_t* mBufferHandle = nullptr; + std::unique_ptr mBufferHandle = nullptr; PixelFormat mPixelFormat; Dataspace mDataspace; Display mDisplay; diff --git a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/RenderEngineVts.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/RenderEngineVts.h index f2d5f1933fdb13bf4b0bbbb6a3314981db7930e5..26027d33a2573b8f072cbcdecd0b8281cd036b2a 100644 --- a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/RenderEngineVts.h +++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/RenderEngineVts.h @@ -14,9 +14,12 @@ * limitations under the License. */ +#pragma once + #include #include #include +#include #include #include #include @@ -51,12 +54,15 @@ class TestRenderEngine { void drawLayers(); void checkColorBuffer(std::vector& expectedColors); + renderengine::RenderEngine& getInternalRenderEngine() { return *mRenderEngine; } + private: common::V1_1::PixelFormat mFormat; std::vector mCompositionLayers; std::unique_ptr mRenderEngine; std::vector mRenderLayers; sp mGraphicBuffer; + DisplaySettings mDisplaySettings; }; diff --git a/graphics/composer/2.2/vts/functional/Android.bp b/graphics/composer/2.2/vts/functional/Android.bp index 7fe453c5aad54dba0732fec4cd90d0e8fd1c1096..36f3c00fae973bf88b80589009ad4455c83afa1b 100644 --- a/graphics/composer/2.2/vts/functional/Android.bp +++ b/graphics/composer/2.2/vts/functional/Android.bp @@ -25,7 +25,11 @@ package { cc_test { name: "VtsHalGraphicsComposerV2_2TargetTest", - defaults: ["VtsHalTargetTestDefaults"], + defaults: [ + "VtsHalTargetTestDefaults", + // Needed for librenderengine + "skia_deps", + ], srcs: [ "VtsHalGraphicsComposerV2_2ReadbackTest.cpp", "VtsHalGraphicsComposerV2_2TargetTest.cpp", diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp index b0eb4ef169baf89631b0754cfa6f16d7fb0b5784..7a053f1eb75f4f9bc3cf325acd4b6385ca0bf55a 100644 --- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp +++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp @@ -39,15 +39,13 @@ namespace V2_2 { namespace vts { namespace { -using android::GraphicBuffer; using android::Rect; -using android::hardware::hidl_handle; using common::V1_1::BufferUsage; using common::V1_1::Dataspace; using common::V1_1::PixelFormat; -using mapper::V2_1::IMapper; using V2_1::Config; using V2_1::Display; +using V2_1::vts::NativeHandleWrapper; using V2_1::vts::TestCommandReader; using vts::Gralloc; @@ -103,7 +101,8 @@ class GraphicsCompositionTestBase : public ::testing::Test { mTestRenderEngine->initGraphicBuffer( static_cast(mDisplayWidth), static_cast(mDisplayHeight), 1, - static_cast(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN)); + static_cast(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::GPU_RENDER_TARGET)); mTestRenderEngine->setDisplaySettings(clientCompositionDisplay); } @@ -287,9 +286,9 @@ TEST_P(GraphicsCompositionTest, SetLayerBuffer) { {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight}, BLUE); - auto layer = std::make_shared(mComposerClient, mGralloc, mPrimaryDisplay, - mDisplayWidth, mDisplayHeight, - PixelFormat::RGBA_8888); + auto layer = std::make_shared( + mComposerClient, mGralloc, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth, + mDisplayHeight, PixelFormat::RGBA_8888); layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight}); layer->setZOrder(10); layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter); @@ -354,9 +353,9 @@ TEST_P(GraphicsCompositionTest, SetLayerBufferNoEffect) { // This following buffer call should have no effect uint64_t usage = static_cast(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN); - const native_handle_t* bufferHandle = + NativeHandleWrapper bufferHandle = mGralloc->allocate(mDisplayWidth, mDisplayHeight, 1, PixelFormat::RGBA_8888, usage); - mWriter->setLayerBuffer(0, bufferHandle, -1); + mWriter->setLayerBuffer(0, bufferHandle.get(), -1); // expected color for each pixel std::vector expectedColors(mDisplayWidth * mDisplayHeight); @@ -421,9 +420,9 @@ TEST_P(GraphicsCompositionTest, ClientComposition) { {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight}, BLUE); - auto layer = std::make_shared(mComposerClient, mGralloc, mPrimaryDisplay, - mDisplayWidth, mDisplayHeight, - PixelFormat::RGBA_FP16); + auto layer = std::make_shared( + mComposerClient, mGralloc, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth, + mDisplayHeight, PixelFormat::RGBA_FP16); layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight}); layer->setZOrder(10); layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter); @@ -459,29 +458,30 @@ TEST_P(GraphicsCompositionTest, ClientComposition) { << " pixel format: PixelFormat::RGBA_8888 dataspace: " << ReadbackHelper::getDataspaceString(clientDataspace) << " unsupported for display" << std::endl; + mReader->mCompositionChanges.clear(); continue; } // create client target buffer uint32_t clientStride; - const native_handle_t* clientBufferHandle = + NativeHandleWrapper clientBufferHandle = mGralloc->allocate(layer->mWidth, layer->mHeight, layer->mLayerCount, clientFormat, clientUsage, /*import*/ true, &clientStride); - ASSERT_NE(nullptr, clientBufferHandle); + ASSERT_NE(nullptr, clientBufferHandle.get()); void* clientBufData = - mGralloc->lock(clientBufferHandle, clientUsage, layer->mAccessRegion, -1); + mGralloc->lock(clientBufferHandle.get(), clientUsage, layer->mAccessRegion, -1); ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer(layer->mWidth, layer->mHeight, clientStride, clientBufData, clientFormat, expectedColors)); - int clientFence = mGralloc->unlock(clientBufferHandle); + int clientFence = mGralloc->unlock(clientBufferHandle.get()); if (clientFence != -1) { sync_wait(clientFence, -1); close(clientFence); } - mWriter->setClientTarget(0, clientBufferHandle, clientFence, clientDataspace, + mWriter->setClientTarget(0, clientBufferHandle.get(), clientFence, clientDataspace, std::vector(1, damage)); layer->setToClientComposition(mWriter); @@ -537,8 +537,8 @@ TEST_P(GraphicsCompositionTest, DeviceAndClientComposition) { ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); auto deviceLayer = std::make_shared( - mComposerClient, mGralloc, mPrimaryDisplay, mDisplayWidth, mDisplayHeight / 2, - PixelFormat::RGBA_8888); + mComposerClient, mGralloc, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth, + mDisplayHeight / 2, PixelFormat::RGBA_8888); std::vector deviceColors(deviceLayer->mWidth * deviceLayer->mHeight); ReadbackHelper::fillColorsArea(deviceColors, deviceLayer->mWidth, @@ -574,8 +574,8 @@ TEST_P(GraphicsCompositionTest, DeviceAndClientComposition) { } auto clientLayer = std::make_shared( - mComposerClient, mGralloc, mPrimaryDisplay, clientWidth, clientHeight, - PixelFormat::RGBA_FP16, IComposerClient::Composition::DEVICE); + mComposerClient, mGralloc, *mTestRenderEngine, mPrimaryDisplay, clientWidth, + clientHeight, PixelFormat::RGBA_FP16, IComposerClient::Composition::DEVICE); IComposerClient::Rect clientFrame = {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight}; clientLayer->setDisplayFrame(clientFrame); clientLayer->setZOrder(0); @@ -592,12 +592,12 @@ TEST_P(GraphicsCompositionTest, DeviceAndClientComposition) { // create client target buffer ASSERT_EQ(1, mReader->mCompositionChanges[0].second); uint32_t clientStride; - const native_handle_t* clientBufferHandle = + NativeHandleWrapper clientBufferHandle = mGralloc->allocate(mDisplayWidth, mDisplayHeight, clientLayer->mLayerCount, clientFormat, clientUsage, /*import*/ true, &clientStride); - ASSERT_NE(nullptr, clientBufferHandle); + ASSERT_NE(nullptr, clientBufferHandle.get()); - void* clientBufData = mGralloc->lock(clientBufferHandle, clientUsage, + void* clientBufData = mGralloc->lock(clientBufferHandle.get(), clientUsage, {0, 0, mDisplayWidth, mDisplayHeight}, -1); std::vector clientColors(mDisplayWidth * mDisplayHeight); @@ -605,13 +605,13 @@ TEST_P(GraphicsCompositionTest, DeviceAndClientComposition) { ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer(mDisplayWidth, mDisplayHeight, clientStride, clientBufData, clientFormat, clientColors)); - int clientFence = mGralloc->unlock(clientBufferHandle); + int clientFence = mGralloc->unlock(clientBufferHandle.get()); if (clientFence != -1) { sync_wait(clientFence, -1); close(clientFence); } - mWriter->setClientTarget(0, clientBufferHandle, clientFence, clientDataspace, + mWriter->setClientTarget(0, clientBufferHandle.get(), clientFence, clientDataspace, std::vector(1, clientFrame)); clientLayer->setToClientComposition(mWriter); mWriter->validateDisplay(); @@ -656,9 +656,9 @@ TEST_P(GraphicsCompositionTest, SetLayerDamage) { std::vector expectedColors(mDisplayWidth * mDisplayHeight); ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, redRect, RED); - auto layer = std::make_shared(mComposerClient, mGralloc, mPrimaryDisplay, - mDisplayWidth, mDisplayHeight, - PixelFormat::RGBA_8888); + auto layer = std::make_shared( + mComposerClient, mGralloc, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth, + mDisplayHeight, PixelFormat::RGBA_8888); layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight}); layer->setZOrder(10); layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter); @@ -804,9 +804,9 @@ TEST_P(GraphicsCompositionTest, SetLayerSourceCrop) { {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight}, BLUE); - auto layer = std::make_shared(mComposerClient, mGralloc, mPrimaryDisplay, - mDisplayWidth, mDisplayHeight, - PixelFormat::RGBA_8888); + auto layer = std::make_shared( + mComposerClient, mGralloc, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth, + mDisplayHeight, PixelFormat::RGBA_8888); layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight}); layer->setZOrder(10); layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter); @@ -956,9 +956,9 @@ class GraphicsBlendModeCompositionTest backgroundLayer->setZOrder(0); backgroundLayer->setColor(mBackgroundColor); - auto layer = std::make_shared(mComposerClient, mGralloc, mPrimaryDisplay, - mDisplayWidth, mDisplayHeight, - PixelFormat::RGBA_8888); + auto layer = std::make_shared( + mComposerClient, mGralloc, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth, + mDisplayHeight, PixelFormat::RGBA_8888); layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight}); layer->setZOrder(10); layer->setDataspace(Dataspace::UNKNOWN, mWriter); @@ -1194,9 +1194,9 @@ class GraphicsTransformCompositionTest : public GraphicsCompositionTest { IComposerClient::Rect blueRect = {mSideLength / 2, mSideLength / 2, mSideLength, mSideLength}; - mLayer = - std::make_shared(mComposerClient, mGralloc, mPrimaryDisplay, - mSideLength, mSideLength, PixelFormat::RGBA_8888); + mLayer = std::make_shared(mComposerClient, mGralloc, *mTestRenderEngine, + mPrimaryDisplay, mSideLength, mSideLength, + PixelFormat::RGBA_8888); mLayer->setDisplayFrame({0, 0, mSideLength, mSideLength}); mLayer->setZOrder(10); @@ -1381,6 +1381,7 @@ TEST_P(GraphicsTransformCompositionTest, ROT_180) { } } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsCompositionTest); INSTANTIATE_TEST_SUITE_P( PerInstance, GraphicsCompositionTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames(IComposer::descriptor)), @@ -1394,6 +1395,7 @@ INSTANTIATE_TEST_CASE_P( testing::Values("0.2", "1.0")), android::hardware::PrintInstanceTupleNameToString<>); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsTransformCompositionTest); INSTANTIATE_TEST_SUITE_P( PerInstance, GraphicsTransformCompositionTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames(IComposer::descriptor)), diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp index f4c0382dffc452834aafcd089f805ea5911200db..7e25a2e12560b2130ab9efee4db90f48100ddd46 100644 --- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp +++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp @@ -36,13 +36,11 @@ namespace vts { namespace { using common::V1_0::BufferUsage; -using common::V1_0::ColorTransform; -using common::V1_0::Transform; using common::V1_1::ColorMode; using common::V1_1::Dataspace; using common::V1_1::PixelFormat; using common::V1_1::RenderIntent; -using mapper::V2_0::IMapper; +using V2_1::vts::NativeHandleWrapper; class GraphicsComposerHidlTest : public ::testing::TestWithParam { protected: @@ -154,7 +152,7 @@ class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest { ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown()); } - const native_handle_t* allocate() { + NativeHandleWrapper allocate() { uint64_t usage = static_cast(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN); return mGralloc->allocate(/*width*/ 64, /*height*/ 64, /*layerCount*/ 1, @@ -440,12 +438,12 @@ TEST_P(GraphicsComposerHidlTest, SetReadbackBuffer) { static_cast(BufferUsage::COMPOSER_OVERLAY | BufferUsage::CPU_READ_OFTEN); std::unique_ptr gralloc; - const native_handle_t* buffer; + std::unique_ptr buffer; ASSERT_NO_FATAL_FAILURE(gralloc = std::make_unique()); - ASSERT_NO_FATAL_FAILURE(buffer = gralloc->allocate(mDisplayWidth, mDisplayHeight, 1, - mReadbackPixelFormat, usage)); + ASSERT_NO_FATAL_FAILURE(buffer.reset(new NativeHandleWrapper( + gralloc->allocate(mDisplayWidth, mDisplayHeight, 1, mReadbackPixelFormat, usage)))); - mComposerClient->setReadbackBuffer(mPrimaryDisplay, buffer, -1); + mComposerClient->setReadbackBuffer(mPrimaryDisplay, buffer->get(), -1); } /** @@ -463,12 +461,13 @@ TEST_P(GraphicsComposerHidlTest, SetReadbackBufferBadDisplay) { static_cast(BufferUsage::COMPOSER_OVERLAY | BufferUsage::CPU_READ_OFTEN); std::unique_ptr gralloc; - const native_handle_t* buffer; + std::unique_ptr buffer; ASSERT_NO_FATAL_FAILURE(gralloc = std::make_unique()); - ASSERT_NO_FATAL_FAILURE(buffer = gralloc->allocate(mDisplayWidth, mDisplayHeight, 1, - mReadbackPixelFormat, usage)); + ASSERT_NO_FATAL_FAILURE(buffer.reset(new NativeHandleWrapper( + gralloc->allocate(mDisplayWidth, mDisplayHeight, 1, mReadbackPixelFormat, usage)))); - Error error = mComposerClient->getRaw()->setReadbackBuffer(mInvalidDisplayId, buffer, nullptr); + Error error = + mComposerClient->getRaw()->setReadbackBuffer(mInvalidDisplayId, buffer->get(), nullptr); ASSERT_EQ(Error::BAD_DISPLAY, error); } @@ -682,11 +681,13 @@ TEST_P(GraphicsComposerHidlTest, SetColorMode_2_2BadParameter) { EXPECT_EQ(Error::BAD_PARAMETER, renderIntentError); } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsComposerHidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, GraphicsComposerHidlTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames(IComposer::descriptor)), android::hardware::PrintInstanceNameToString); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsComposerHidlCommandTest); INSTANTIATE_TEST_SUITE_P( PerInstance, GraphicsComposerHidlCommandTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames(IComposer::descriptor)), diff --git a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp index 63af90055ce6aa1c921caf140fe6fee221970768..ecfe66c80d0985efafb85a759878873f8ff362ad 100644 --- a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp +++ b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp @@ -17,6 +17,7 @@ #define LOG_TAG "graphics_composer_hidl_hal_test@2.3" #include +#include #include #include @@ -38,12 +39,10 @@ namespace V2_3 { namespace vts { namespace { -using common::V1_0::BufferUsage; using common::V1_1::RenderIntent; using common::V1_2::ColorMode; using common::V1_2::Dataspace; using common::V1_2::PixelFormat; -using mapper::V2_0::IMapper; using V2_2::vts::Gralloc; class GraphicsComposerHidlTest : public ::testing::TestWithParam { @@ -140,12 +139,6 @@ class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest { ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown()); } - const native_handle_t* allocate() { - return mGralloc->allocate( - 64, 64, 1, static_cast(PixelFormat::RGBA_8888), - static_cast(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN)); - } - void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); } std::unique_ptr mWriter; @@ -163,16 +156,31 @@ class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest { TEST_P(GraphicsComposerHidlTest, GetDisplayIdentificationData) { uint8_t port0; std::vector data0; - if (mComposerClient->getDisplayIdentificationData(mPrimaryDisplay, &port0, &data0)) { - uint8_t port1; - std::vector data1; - ASSERT_TRUE(mComposerClient->getDisplayIdentificationData(mPrimaryDisplay, &port1, &data1)); - - ASSERT_EQ(port0, port1) << "ports are not stable"; - ASSERT_TRUE(data0.size() == data1.size() && - std::equal(data0.begin(), data0.end(), data1.begin())) - << "data is not stable"; + + if (!mComposerClient->getDisplayIdentificationData(mPrimaryDisplay, &port0, &data0)) { + return; } + + ASSERT_FALSE(data0.empty()); + constexpr size_t kEdidBlockSize = 128; + ASSERT_TRUE(data0.size() % kEdidBlockSize == 0) + << "EDID blob length is not a multiple of " << kEdidBlockSize; + + const uint8_t kEdidHeader[] = {0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}; + ASSERT_TRUE(std::equal(std::begin(kEdidHeader), std::end(kEdidHeader), data0.begin())) + << "EDID blob doesn't start with the fixed EDID header"; + ASSERT_EQ(0, std::accumulate(data0.begin(), data0.begin() + kEdidBlockSize, + static_cast(0))) + << "EDID base block doesn't checksum"; + + uint8_t port1; + std::vector data1; + ASSERT_TRUE(mComposerClient->getDisplayIdentificationData(mPrimaryDisplay, &port1, &data1)); + + ASSERT_EQ(port0, port1) << "ports are not stable"; + ASSERT_TRUE(data0.size() == data1.size() && + std::equal(data0.begin(), data0.end(), data1.begin())) + << "data is not stable"; } /** @@ -612,11 +620,13 @@ TEST_P(GraphicsComposerHidlTest, setDisplayBrightness) { EXPECT_EQ(mComposerClient->setDisplayBrightness(mPrimaryDisplay, -2.0f), Error::BAD_PARAMETER); } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsComposerHidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, GraphicsComposerHidlTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames(IComposer::descriptor)), android::hardware::PrintInstanceNameToString); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsComposerHidlCommandTest); INSTANTIATE_TEST_SUITE_P( PerInstance, GraphicsComposerHidlCommandTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames(IComposer::descriptor)), diff --git a/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerClient.h b/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerClient.h index c8890691431920f17114e06be2f2e6f7568eba86..34643427196389adca167beed52ae481fd9753f5 100644 --- a/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerClient.h +++ b/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerClient.h @@ -45,12 +45,21 @@ class ComposerClientImpl : public V2_3::hal::detail::ComposerClientImpl callback, + HalEventCallback(Hal* hal, const sp callback, V2_1::hal::ComposerResources* resources) - : mCallback(callback), mResources(resources) {} + : mHal(hal), mCallback(callback), mResources(resources) {} void onHotplug(Display display, IComposerCallback::Connection connected) override { if (connected == IComposerCallback::Connection::CONNECTED) { + if (mResources->hasDisplay(display)) { + // This is a subsequent hotplug "connected" for a display. This signals a + // display change and thus the framework may want to reallocate buffers. We + // need to free all cached handles, since they are holding a strong reference + // to the underlying buffers. + V2_1::hal::detail::ComposerClientImpl::cleanDisplayResources( + display, mResources, mHal); + mResources->removeDisplay(display); + } mResources->addPhysicalDisplay(display); } else if (connected == IComposerCallback::Connection::DISCONNECTED) { mResources->removeDisplay(display); @@ -91,13 +100,15 @@ class ComposerClientImpl : public V2_3::hal::detail::ComposerClientImpl mCallback; V2_1::hal::ComposerResources* const mResources; }; Return registerCallback_2_4(const sp& callback) override { // no locking as we require this function to be called only once - mHalEventCallback_2_4 = std::make_unique(callback, mResources.get()); + mHalEventCallback_2_4 = + std::make_unique(mHal, callback, mResources.get()); mHal->registerEventCallback_2_4(mHalEventCallback_2_4.get()); return Void(); } diff --git a/graphics/composer/2.4/vts/functional/AndroidTest.xml b/graphics/composer/2.4/vts/functional/AndroidTest.xml index 583aa6866c133a64d07fbd79713532b6de6b3963..773db932557ef3f097ff44a1a6131f824dcb2ef0 100644 --- a/graphics/composer/2.4/vts/functional/AndroidTest.xml +++ b/graphics/composer/2.4/vts/functional/AndroidTest.xml @@ -31,6 +31,6 @@ - + diff --git a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp index 46f95dd1c90023253d136685e0c687335aa745fe..5aceda721e7d54216c4a69e5b54b1a958169bf94 100644 --- a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp +++ b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp @@ -52,8 +52,8 @@ using common::V1_1::RenderIntent; using common::V1_2::ColorMode; using common::V1_2::Dataspace; using common::V1_2::PixelFormat; -using mapper::V2_0::IMapper; using V2_1::Layer; +using V2_1::vts::NativeHandleWrapper; using V2_2::Transform; using V2_2::vts::Gralloc; @@ -159,9 +159,9 @@ class GraphicsComposerHidlTest : public ::testing::TestWithParam { void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); } - const native_handle_t* allocate() { + NativeHandleWrapper allocate(int32_t width, int32_t height) { return mGralloc->allocate( - /*width*/ 64, /*height*/ 64, /*layerCount*/ 1, + width, height, /*layerCount*/ 1, static_cast(PixelFormat::RGBA_8888), static_cast(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN)); } @@ -490,46 +490,56 @@ void GraphicsComposerHidlTest::sendRefreshFrame(const VtsDisplay& display, mComposerClient->setPowerMode(display.get(), V2_1::IComposerClient::PowerMode::ON); mComposerClient->setColorMode_2_3(display.get(), ColorMode::NATIVE, RenderIntent::COLORIMETRIC); - auto handle = allocate(); - ASSERT_NE(nullptr, handle); - + IComposerClient::FRect displayCrop = display.getCrop(); + int32_t displayWidth = static_cast(std::ceilf(displayCrop.right - displayCrop.left)); + int32_t displayHeight = static_cast(std::ceilf(displayCrop.bottom - displayCrop.top)); Layer layer; ASSERT_NO_FATAL_FAILURE(layer = mComposerClient->createLayer(display.get(), kBufferSlotCount)); - mWriter->selectLayer(layer); - mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE); - mWriter->setLayerDisplayFrame(display.getFrameRect()); - mWriter->setLayerPlaneAlpha(1); - mWriter->setLayerSourceCrop(display.getCrop()); - mWriter->setLayerTransform(static_cast(0)); - mWriter->setLayerVisibleRegion(std::vector(1, display.getFrameRect())); - mWriter->setLayerZOrder(10); - mWriter->setLayerBlendMode(IComposerClient::BlendMode::NONE); - mWriter->setLayerSurfaceDamage(std::vector(1, display.getFrameRect())); - mWriter->setLayerBuffer(0, handle, -1); - mWriter->setLayerDataspace(Dataspace::UNKNOWN); - - mWriter->validateDisplay(); - execute(); - ASSERT_EQ(0, mReader->mErrors.size()); - mReader->mCompositionChanges.clear(); - - mWriter->presentDisplay(); - execute(); - ASSERT_EQ(0, mReader->mErrors.size()); - - mWriter->selectLayer(layer); - auto handle2 = allocate(); - ASSERT_NE(nullptr, handle2); - - mWriter->setLayerBuffer(0, handle2, -1); - mWriter->setLayerSurfaceDamage(std::vector(1, {0, 0, 10, 10})); - mWriter->validateDisplay(); - execute(); - ASSERT_EQ(0, mReader->mErrors.size()); - mReader->mCompositionChanges.clear(); - - mWriter->presentDisplay(); - execute(); + + { + auto handle = allocate(displayWidth, displayHeight); + ASSERT_NE(nullptr, handle.get()); + + mWriter->selectLayer(layer); + mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE); + mWriter->setLayerDisplayFrame(display.getFrameRect()); + mWriter->setLayerPlaneAlpha(1); + mWriter->setLayerSourceCrop(display.getCrop()); + mWriter->setLayerTransform(static_cast(0)); + mWriter->setLayerVisibleRegion( + std::vector(1, display.getFrameRect())); + mWriter->setLayerZOrder(10); + mWriter->setLayerBlendMode(IComposerClient::BlendMode::NONE); + mWriter->setLayerSurfaceDamage( + std::vector(1, display.getFrameRect())); + mWriter->setLayerBuffer(0, handle.get(), -1); + mWriter->setLayerDataspace(Dataspace::UNKNOWN); + + mWriter->validateDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + mReader->mCompositionChanges.clear(); + + mWriter->presentDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + } + + { + auto handle = allocate(displayWidth, displayHeight); + ASSERT_NE(nullptr, handle.get()); + + mWriter->selectLayer(layer); + mWriter->setLayerBuffer(0, handle.get(), -1); + mWriter->setLayerSurfaceDamage(std::vector(1, {0, 0, 10, 10})); + mWriter->validateDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + mReader->mCompositionChanges.clear(); + + mWriter->presentDisplay(); + execute(); + } ASSERT_NO_FATAL_FAILURE(mComposerClient->destroyLayer(display.get(), layer)); } @@ -558,17 +568,28 @@ void GraphicsComposerHidlTest::Test_setActiveConfigWithConstraints(const TestPar setActiveConfig(display, config1); sendRefreshFrame(display, nullptr); - int32_t vsyncPeriod1 = mComposerClient->getDisplayAttribute_2_4( + const auto vsyncPeriod1 = mComposerClient->getDisplayAttribute_2_4( display.get(), config1, IComposerClient::IComposerClient::Attribute::VSYNC_PERIOD); - int32_t vsyncPeriod2 = mComposerClient->getDisplayAttribute_2_4( + const auto configGroup1 = mComposerClient->getDisplayAttribute_2_4( + display.get(), config1, + IComposerClient::IComposerClient::Attribute::CONFIG_GROUP); + const auto vsyncPeriod2 = mComposerClient->getDisplayAttribute_2_4( display.get(), config2, IComposerClient::IComposerClient::Attribute::VSYNC_PERIOD); + const auto configGroup2 = mComposerClient->getDisplayAttribute_2_4( + display.get(), config2, + IComposerClient::IComposerClient::Attribute::CONFIG_GROUP); if (vsyncPeriod1 == vsyncPeriod2) { return; // continue } + // We don't allow delayed change when changing config groups + if (params.delayForChange > 0 && configGroup1 != configGroup2) { + return; // continue + } + VsyncPeriodChangeTimeline timeline; IComposerClient::VsyncPeriodChangeConstraints constraints = { .desiredTimeNanos = systemTime() + params.delayForChange, @@ -742,6 +763,7 @@ TEST_P(GraphicsComposerHidlTest, setGameContentType) { Test_setContentType(ContentType::GAME, "GAME"); } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsComposerHidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, GraphicsComposerHidlTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames(IComposer::descriptor)), diff --git a/health/storage/aidl/Android.bp b/health/storage/aidl/Android.bp index bf49466a9175fe4102d7c4edd13080523f164605..4cd9263b2b585aa7f415d8e02958731ee217ee10 100644 --- a/health/storage/aidl/Android.bp +++ b/health/storage/aidl/Android.bp @@ -39,4 +39,5 @@ aidl_interface { }, }, }, + versions: ["1"], } diff --git a/health/storage/aidl/aidl_api/android.hardware.health.storage/1/.hash b/health/storage/aidl/aidl_api/android.hardware.health.storage/1/.hash new file mode 100644 index 0000000000000000000000000000000000000000..b1c5f89f973e7bc2e93143da2fd3b443b04a2e17 --- /dev/null +++ b/health/storage/aidl/aidl_api/android.hardware.health.storage/1/.hash @@ -0,0 +1 @@ +3828640730cbf161d79e54dafce9470fdafcca1e diff --git a/health/storage/aidl/aidl_api/android.hardware.health.storage/1/android/hardware/health/storage/IGarbageCollectCallback.aidl b/health/storage/aidl/aidl_api/android.hardware.health.storage/1/android/hardware/health/storage/IGarbageCollectCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..dc828c75eb12c7876d84bcc1b29946a23ed06851 --- /dev/null +++ b/health/storage/aidl/aidl_api/android.hardware.health.storage/1/android/hardware/health/storage/IGarbageCollectCallback.aidl @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.health.storage; +@VintfStability +interface IGarbageCollectCallback { + oneway void onFinish(in android.hardware.health.storage.Result result); +} diff --git a/health/storage/aidl/aidl_api/android.hardware.health.storage/1/android/hardware/health/storage/IStorage.aidl b/health/storage/aidl/aidl_api/android.hardware.health.storage/1/android/hardware/health/storage/IStorage.aidl new file mode 100644 index 0000000000000000000000000000000000000000..b60cc971badd00d70de89f91f38cd11bcf32a4d2 --- /dev/null +++ b/health/storage/aidl/aidl_api/android.hardware.health.storage/1/android/hardware/health/storage/IStorage.aidl @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.health.storage; +@VintfStability +interface IStorage { + oneway void garbageCollect(in long timeoutSeconds, in android.hardware.health.storage.IGarbageCollectCallback callback); +} diff --git a/health/storage/aidl/aidl_api/android.hardware.health.storage/1/android/hardware/health/storage/Result.aidl b/health/storage/aidl/aidl_api/android.hardware.health.storage/1/android/hardware/health/storage/Result.aidl new file mode 100644 index 0000000000000000000000000000000000000000..c57a20cee8a3c7097a7ef0aea7ede5ba198999c8 --- /dev/null +++ b/health/storage/aidl/aidl_api/android.hardware.health.storage/1/android/hardware/health/storage/Result.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.health.storage; +@Backing(type="int") @VintfStability +enum Result { + SUCCESS = 0, + IO_ERROR = 1, + UNKNOWN_ERROR = 2, +} diff --git a/identity/aidl/Android.bp b/identity/aidl/Android.bp index 8da664245d36892176bebd9cb5b7c9c4210aa56c..dad3b8d74c8352a057cb9eb187cb42e0de7cc768 100644 --- a/identity/aidl/Android.bp +++ b/identity/aidl/Android.bp @@ -30,5 +30,6 @@ aidl_interface { versions: [ "1", "2", + "3", ], } diff --git a/identity/aidl/aidl_api/android.hardware.identity/3/.hash b/identity/aidl/aidl_api/android.hardware.identity/3/.hash new file mode 100644 index 0000000000000000000000000000000000000000..4f91388b575ae2a4f2d41ed1f3dc0c0c5934ae9a --- /dev/null +++ b/identity/aidl/aidl_api/android.hardware.identity/3/.hash @@ -0,0 +1 @@ +1b6d65bb827aecd66860e06a8806dc77a8d3382b diff --git a/identity/aidl/aidl_api/android.hardware.identity/3/android/hardware/identity/Certificate.aidl b/identity/aidl/aidl_api/android.hardware.identity/3/android/hardware/identity/Certificate.aidl new file mode 100644 index 0000000000000000000000000000000000000000..83e17973861f2a1df87ccb0049e3c0cfba54b5a3 --- /dev/null +++ b/identity/aidl/aidl_api/android.hardware.identity/3/android/hardware/identity/Certificate.aidl @@ -0,0 +1,38 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.identity; +@VintfStability +parcelable Certificate { + byte[] encodedCertificate; +} diff --git a/identity/aidl/aidl_api/android.hardware.identity/3/android/hardware/identity/CipherSuite.aidl b/identity/aidl/aidl_api/android.hardware.identity/3/android/hardware/identity/CipherSuite.aidl new file mode 100644 index 0000000000000000000000000000000000000000..e6ec04e805b321cfa18c4eee0cdde977577967a3 --- /dev/null +++ b/identity/aidl/aidl_api/android.hardware.identity/3/android/hardware/identity/CipherSuite.aidl @@ -0,0 +1,38 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.identity; +@Backing(type="int") @VintfStability +enum CipherSuite { + CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256 = 1, +} diff --git a/identity/aidl/aidl_api/android.hardware.identity/3/android/hardware/identity/HardwareInformation.aidl b/identity/aidl/aidl_api/android.hardware.identity/3/android/hardware/identity/HardwareInformation.aidl new file mode 100644 index 0000000000000000000000000000000000000000..cd8d56b5bd6d8cc96cd433cb9db8db97a7996c37 --- /dev/null +++ b/identity/aidl/aidl_api/android.hardware.identity/3/android/hardware/identity/HardwareInformation.aidl @@ -0,0 +1,42 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.identity; +@VintfStability +parcelable HardwareInformation { + @utf8InCpp String credentialStoreName; + @utf8InCpp String credentialStoreAuthorName; + int dataChunkSize; + boolean isDirectAccess; + @utf8InCpp String[] supportedDocTypes; +} diff --git a/identity/aidl/aidl_api/android.hardware.identity/3/android/hardware/identity/IIdentityCredential.aidl b/identity/aidl/aidl_api/android.hardware.identity/3/android/hardware/identity/IIdentityCredential.aidl new file mode 100644 index 0000000000000000000000000000000000000000..506564110909271b43d63609cc408d9fd9d28fef --- /dev/null +++ b/identity/aidl/aidl_api/android.hardware.identity/3/android/hardware/identity/IIdentityCredential.aidl @@ -0,0 +1,54 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.identity; +@VintfStability +interface IIdentityCredential { + /** + * @deprecated use deleteCredentalWithChallenge() instead. + */ + byte[] deleteCredential(); + byte[] createEphemeralKeyPair(); + void setReaderEphemeralPublicKey(in byte[] publicKey); + long createAuthChallenge(); + void startRetrieval(in android.hardware.identity.SecureAccessControlProfile[] accessControlProfiles, in android.hardware.keymaster.HardwareAuthToken authToken, in byte[] itemsRequest, in byte[] signingKeyBlob, in byte[] sessionTranscript, in byte[] readerSignature, in int[] requestCounts); + void startRetrieveEntryValue(in @utf8InCpp String nameSpace, in @utf8InCpp String name, in int entrySize, in int[] accessControlProfileIds); + byte[] retrieveEntryValue(in byte[] encryptedContent); + @SuppressWarnings(value={"out-array"}) void finishRetrieval(out byte[] mac, out byte[] deviceNameSpaces); + @SuppressWarnings(value={"out-array"}) android.hardware.identity.Certificate generateSigningKeyPair(out byte[] signingKeyBlob); + void setRequestedNamespaces(in android.hardware.identity.RequestNamespace[] requestNamespaces); + void setVerificationToken(in android.hardware.keymaster.VerificationToken verificationToken); + byte[] deleteCredentialWithChallenge(in byte[] challenge); + byte[] proveOwnership(in byte[] challenge); + android.hardware.identity.IWritableIdentityCredential updateCredential(); +} diff --git a/identity/aidl/aidl_api/android.hardware.identity/3/android/hardware/identity/IIdentityCredentialStore.aidl b/identity/aidl/aidl_api/android.hardware.identity/3/android/hardware/identity/IIdentityCredentialStore.aidl new file mode 100644 index 0000000000000000000000000000000000000000..c0eeabfd91bc430d7ae38d91053574ae807b80a5 --- /dev/null +++ b/identity/aidl/aidl_api/android.hardware.identity/3/android/hardware/identity/IIdentityCredentialStore.aidl @@ -0,0 +1,53 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.identity; +@VintfStability +interface IIdentityCredentialStore { + android.hardware.identity.HardwareInformation getHardwareInformation(); + android.hardware.identity.IWritableIdentityCredential createCredential(in @utf8InCpp String docType, in boolean testCredential); + android.hardware.identity.IIdentityCredential getCredential(in android.hardware.identity.CipherSuite cipherSuite, in byte[] credentialData); + const int STATUS_OK = 0; + const int STATUS_FAILED = 1; + const int STATUS_CIPHER_SUITE_NOT_SUPPORTED = 2; + const int STATUS_INVALID_DATA = 3; + const int STATUS_INVALID_AUTH_TOKEN = 4; + const int STATUS_INVALID_ITEMS_REQUEST_MESSAGE = 5; + const int STATUS_READER_SIGNATURE_CHECK_FAILED = 6; + const int STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND = 7; + const int STATUS_USER_AUTHENTICATION_FAILED = 8; + const int STATUS_READER_AUTHENTICATION_FAILED = 9; + const int STATUS_NO_ACCESS_CONTROL_PROFILES = 10; + const int STATUS_NOT_IN_REQUEST_MESSAGE = 11; + const int STATUS_SESSION_TRANSCRIPT_MISMATCH = 12; +} diff --git a/identity/aidl/aidl_api/android.hardware.identity/3/android/hardware/identity/IWritableIdentityCredential.aidl b/identity/aidl/aidl_api/android.hardware.identity/3/android/hardware/identity/IWritableIdentityCredential.aidl new file mode 100644 index 0000000000000000000000000000000000000000..9a0fa9e9e5e76da2ea97fd99033c5201b2aa5b93 --- /dev/null +++ b/identity/aidl/aidl_api/android.hardware.identity/3/android/hardware/identity/IWritableIdentityCredential.aidl @@ -0,0 +1,44 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.identity; +@VintfStability +interface IWritableIdentityCredential { + android.hardware.identity.Certificate[] getAttestationCertificate(in byte[] attestationApplicationId, in byte[] attestationChallenge); + void startPersonalization(in int accessControlProfileCount, in int[] entryCounts); + android.hardware.identity.SecureAccessControlProfile addAccessControlProfile(in int id, in android.hardware.identity.Certificate readerCertificate, in boolean userAuthenticationRequired, in long timeoutMillis, in long secureUserId); + void beginAddEntry(in int[] accessControlProfileIds, in @utf8InCpp String nameSpace, in @utf8InCpp String name, in int entrySize); + byte[] addEntryValue(in byte[] content); + @SuppressWarnings(value={"out-array"}) void finishAddingEntries(out byte[] credentialData, out byte[] proofOfProvisioningSignature); + void setExpectedProofOfProvisioningSize(in int expectedProofOfProvisioningSize); +} diff --git a/identity/aidl/aidl_api/android.hardware.identity/3/android/hardware/identity/RequestDataItem.aidl b/identity/aidl/aidl_api/android.hardware.identity/3/android/hardware/identity/RequestDataItem.aidl new file mode 100644 index 0000000000000000000000000000000000000000..cec8e0c94d1613c80ea5aac6770fd3f842064f07 --- /dev/null +++ b/identity/aidl/aidl_api/android.hardware.identity/3/android/hardware/identity/RequestDataItem.aidl @@ -0,0 +1,40 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.identity; +@VintfStability +parcelable RequestDataItem { + @utf8InCpp String name; + long size; + int[] accessControlProfileIds; +} diff --git a/identity/aidl/aidl_api/android.hardware.identity/3/android/hardware/identity/RequestNamespace.aidl b/identity/aidl/aidl_api/android.hardware.identity/3/android/hardware/identity/RequestNamespace.aidl new file mode 100644 index 0000000000000000000000000000000000000000..05b9ec295f15c598b0648fa72bd3278af7f8db3b --- /dev/null +++ b/identity/aidl/aidl_api/android.hardware.identity/3/android/hardware/identity/RequestNamespace.aidl @@ -0,0 +1,39 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.identity; +@VintfStability +parcelable RequestNamespace { + @utf8InCpp String namespaceName; + android.hardware.identity.RequestDataItem[] items; +} diff --git a/identity/aidl/aidl_api/android.hardware.identity/3/android/hardware/identity/SecureAccessControlProfile.aidl b/identity/aidl/aidl_api/android.hardware.identity/3/android/hardware/identity/SecureAccessControlProfile.aidl new file mode 100644 index 0000000000000000000000000000000000000000..2003594eb44e25d1c9741dc35a58a89a9f1b7959 --- /dev/null +++ b/identity/aidl/aidl_api/android.hardware.identity/3/android/hardware/identity/SecureAccessControlProfile.aidl @@ -0,0 +1,43 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.identity; +@VintfStability +parcelable SecureAccessControlProfile { + int id; + android.hardware.identity.Certificate readerCertificate; + boolean userAuthenticationRequired; + long timeoutMillis; + long secureUserId; + byte[] mac; +} diff --git a/input/classifier/1.0/vts/functional/Android.bp b/input/classifier/1.0/vts/functional/Android.bp index 5964a7ea1fef943ee73369cabc5fb3940724dbca..58945d3f631ab3981b5cd947341aeabdc7f00115 100644 --- a/input/classifier/1.0/vts/functional/Android.bp +++ b/input/classifier/1.0/vts/functional/Android.bp @@ -26,11 +26,15 @@ package { cc_test { name: "VtsHalInputClassifierV1_0TargetTest", defaults: ["VtsHalTargetTestDefaults"], - srcs: ["VtsHalInputClassifierV1_0TargetTest.cpp"], + srcs: [ + ":inputconstants_aidl", + "VtsHalInputClassifierV1_0TargetTest.cpp", + ], header_libs: ["jni_headers"], static_libs: [ "android.hardware.input.classifier@1.0", "android.hardware.input.common@1.0", + "libui-types", ], test_suites: [ "general-tests", diff --git a/input/classifier/1.0/vts/functional/VtsHalInputClassifierV1_0TargetTest.cpp b/input/classifier/1.0/vts/functional/VtsHalInputClassifierV1_0TargetTest.cpp index ee529c73b0937bb0e443d7a029a4151cebef7e91..186e406aca3ebe77fd56b6d6dfc8bd0868d79640 100644 --- a/input/classifier/1.0/vts/functional/VtsHalInputClassifierV1_0TargetTest.cpp +++ b/input/classifier/1.0/vts/functional/VtsHalInputClassifierV1_0TargetTest.cpp @@ -168,6 +168,7 @@ TEST_P(InputClassifierHidlTest_1_0, Classify_TwoVideoFrames) { classifier->reset(); } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(InputClassifierHidlTest_1_0); INSTANTIATE_TEST_SUITE_P( PerInstance, InputClassifierHidlTest_1_0, testing::ValuesIn(android::hardware::getAllHalInstanceNames(IInputClassifier::descriptor)), diff --git a/keymaster/aidl/Android.bp b/keymaster/aidl/Android.bp index b7a261c596bc8985a32ea418f4eaf5ebc62c8f30..c4b6740ed4f8290ac6b27f1702d669ff35f6511e 100644 --- a/keymaster/aidl/Android.bp +++ b/keymaster/aidl/Android.bp @@ -27,5 +27,6 @@ aidl_interface { versions: [ "1", "2", + "3", ], } diff --git a/keymaster/aidl/aidl_api/android.hardware.keymaster/3/.hash b/keymaster/aidl/aidl_api/android.hardware.keymaster/3/.hash new file mode 100644 index 0000000000000000000000000000000000000000..acec81a5eb5797ec3c9d832cd6ad73f696077391 --- /dev/null +++ b/keymaster/aidl/aidl_api/android.hardware.keymaster/3/.hash @@ -0,0 +1 @@ +38887f224e43273b344a5400e5441d6609bf8b2f diff --git a/keymaster/aidl/aidl_api/android.hardware.keymaster/3/android/hardware/keymaster/HardwareAuthToken.aidl b/keymaster/aidl/aidl_api/android.hardware.keymaster/3/android/hardware/keymaster/HardwareAuthToken.aidl new file mode 100644 index 0000000000000000000000000000000000000000..058f23ee96a2b0fa80c56ce357158bd1bd4ba94a --- /dev/null +++ b/keymaster/aidl/aidl_api/android.hardware.keymaster/3/android/hardware/keymaster/HardwareAuthToken.aidl @@ -0,0 +1,43 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.keymaster; +@VintfStability +parcelable HardwareAuthToken { + long challenge; + long userId; + long authenticatorId; + android.hardware.keymaster.HardwareAuthenticatorType authenticatorType = android.hardware.keymaster.HardwareAuthenticatorType.NONE; + android.hardware.keymaster.Timestamp timestamp; + byte[] mac; +} diff --git a/keymaster/aidl/aidl_api/android.hardware.keymaster/3/android/hardware/keymaster/HardwareAuthenticatorType.aidl b/keymaster/aidl/aidl_api/android.hardware.keymaster/3/android/hardware/keymaster/HardwareAuthenticatorType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..74535ebe87eb24f0b2c044832b1a4fb8d0d236a6 --- /dev/null +++ b/keymaster/aidl/aidl_api/android.hardware.keymaster/3/android/hardware/keymaster/HardwareAuthenticatorType.aidl @@ -0,0 +1,41 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.keymaster; +@Backing(type="int") @VintfStability +enum HardwareAuthenticatorType { + NONE = 0, + PASSWORD = 1, + FINGERPRINT = 2, + ANY = -1, +} diff --git a/keymaster/aidl/aidl_api/android.hardware.keymaster/3/android/hardware/keymaster/SecurityLevel.aidl b/keymaster/aidl/aidl_api/android.hardware.keymaster/3/android/hardware/keymaster/SecurityLevel.aidl new file mode 100644 index 0000000000000000000000000000000000000000..458303218ed4dd2df290d9095e6e122d497b3130 --- /dev/null +++ b/keymaster/aidl/aidl_api/android.hardware.keymaster/3/android/hardware/keymaster/SecurityLevel.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.keymaster; +@Backing(type="int") @VintfStability +enum SecurityLevel { + SOFTWARE = 0, + TRUSTED_ENVIRONMENT = 1, + STRONGBOX = 2, +} diff --git a/keymaster/aidl/aidl_api/android.hardware.keymaster/3/android/hardware/keymaster/Timestamp.aidl b/keymaster/aidl/aidl_api/android.hardware.keymaster/3/android/hardware/keymaster/Timestamp.aidl new file mode 100644 index 0000000000000000000000000000000000000000..e0b7c4874f07aa5fe56a61e2357abafee35e06f5 --- /dev/null +++ b/keymaster/aidl/aidl_api/android.hardware.keymaster/3/android/hardware/keymaster/Timestamp.aidl @@ -0,0 +1,38 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.keymaster; +@VintfStability +parcelable Timestamp { + long milliSeconds; +} diff --git a/keymaster/aidl/aidl_api/android.hardware.keymaster/3/android/hardware/keymaster/VerificationToken.aidl b/keymaster/aidl/aidl_api/android.hardware.keymaster/3/android/hardware/keymaster/VerificationToken.aidl new file mode 100644 index 0000000000000000000000000000000000000000..7862b5e83ca12b16ad0c313ac97f303a7bc9503c --- /dev/null +++ b/keymaster/aidl/aidl_api/android.hardware.keymaster/3/android/hardware/keymaster/VerificationToken.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.keymaster; +@VintfStability +parcelable VerificationToken { + long challenge; + android.hardware.keymaster.Timestamp timestamp; + android.hardware.keymaster.SecurityLevel securityLevel = android.hardware.keymaster.SecurityLevel.SOFTWARE; + byte[] mac; +} diff --git a/media/c2/1.2/Android.bp b/media/c2/1.2/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..6d3e74d2b17c3637f7b4ed5c3f8b225398788fbd --- /dev/null +++ b/media/c2/1.2/Android.bp @@ -0,0 +1,40 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +hidl_interface { + name: "android.hardware.media.c2@1.2", + root: "android.hardware", + srcs: [ + "types.hal", + "IComponent.hal", + "IComponentStore.hal", + ], + interfaces: [ + "android.hardware.graphics.bufferqueue@1.0", + "android.hardware.graphics.bufferqueue@2.0", + "android.hardware.graphics.common@1.0", + "android.hardware.graphics.common@1.1", + "android.hardware.graphics.common@1.2", + "android.hardware.media.bufferpool@2.0", + "android.hardware.media.c2@1.0", + "android.hardware.media.c2@1.1", + "android.hardware.media.omx@1.0", + "android.hardware.media@1.0", + "android.hidl.base@1.0", + "android.hidl.safe_union@1.0", + ], + gen_java: false, + apex_available: [ + "//apex_available:platform", + "com.android.media.swcodec", + "test_com.android.media.swcodec", + ], +} diff --git a/media/c2/1.2/IComponent.hal b/media/c2/1.2/IComponent.hal new file mode 100644 index 0000000000000000000000000000000000000000..088d810492cc7b04943ab8c78990ff52709aa1bf --- /dev/null +++ b/media/c2/1.2/IComponent.hal @@ -0,0 +1,61 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.media.c2@1.2; + +import android.hardware.graphics.bufferqueue@2.0::IGraphicBufferProducer; +import android.hardware.media.c2@1.1::IComponent; +import android.hardware.media.c2@1.0::Status; + + +/** + * Interface for a Codec2 component corresponding to API level 1.2 or below. + * Components have two states: stopped and running. The running state has three + * sub-states: executing, tripped and error. + * + * All methods in `IComponent` must not block. If a method call cannot be + * completed in a timely manner, it must return `TIMED_OUT` in the return + * status. + * + * @note This is an extension of version 1.1 of `IComponent`. The purpose of the + * extension is to add blocking allocation of output buffer from surface. + */ +interface IComponent extends @1.1::IComponent { + /** + * Starts using a surface for output with a synchronization object + * + * This method must not block. + * + * @param blockPoolId Id of the `C2BlockPool` to be associated with the + * output surface. + * @param surface Output surface. + * @param syncObject synchronization object for buffer allocation between + * Framework and Component. + * @return status Status of the call, which may be + * - `OK` - The operation completed successfully. + * - `CANNOT_DO` - The component does not support an output surface. + * - `REFUSED` - The output surface cannot be accessed. + * - `TIMED_OUT` - The operation cannot be finished in a timely manner. + * - `CORRUPTED` - Some unknown error occurred. + */ + setOutputSurfaceWithSyncObj( + uint64_t blockPoolId, + @2.0::IGraphicBufferProducer surface, + SurfaceSyncObj syncObject + ) generates ( + Status status + ); +}; diff --git a/media/c2/1.2/IComponentStore.hal b/media/c2/1.2/IComponentStore.hal new file mode 100644 index 0000000000000000000000000000000000000000..c38fc7a49998c2f84ad4763dd14241e4b059db25 --- /dev/null +++ b/media/c2/1.2/IComponentStore.hal @@ -0,0 +1,64 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.media.c2@1.2; + +import android.hardware.media.bufferpool@2.0::IClientManager; +import android.hardware.media.c2@1.0::IComponentListener; +import android.hardware.media.c2@1.1::IComponentStore; +import android.hardware.media.c2@1.0::Status; + +import IComponent; + +/** + * Entry point for Codec2 HAL. + * + * All methods in `IComponentStore` must not block. If a method call cannot be + * completed in a timely manner, it must return `TIMED_OUT` in the return + * status. The only exceptions are getPoolClientManager() and getConfigurable(), + * which must always return immediately. + * + * @note This is an extension of version 1.1 of `IComponentStore`. The purpose + * of the extension is to add support for blocking output buffer allocator. + */ +interface IComponentStore extends @1.1::IComponentStore { + /** + * Creates a component by name. + * + * @param name Name of the component to create. This must match one of the + * names returned by listComponents(). + * @param listener Callback receiver. + * @param pool `IClientManager` object of the BufferPool in the client + * process. This may be null if the client does not own a BufferPool. + * @return status Status of the call, which may be + * - `OK` - The component was created successfully. + * - `NOT_FOUND` - There is no component with the given name. + * - `NO_MEMORY` - Not enough memory to create the component. + * - `TIMED_OUT` - The operation cannot be finished in a timely manner. + * - `CORRUPTED` - Some unknown error occurred. + * @return comp The created component if @p status is `OK`. + * + * @sa IComponentListener. + */ + createComponent_1_2( + string name, + IComponentListener listener, + IClientManager pool + ) generates ( + Status status, + IComponent comp + ); +}; diff --git a/media/c2/1.2/types.hal b/media/c2/1.2/types.hal new file mode 100644 index 0000000000000000000000000000000000000000..096edbdf8cbc49c4b72da5548af1c0935def4ba8 --- /dev/null +++ b/media/c2/1.2/types.hal @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.media.c2@1.2; + +/** + * Surface(BufferQueue/IGBP) synchronization object regarding # of dequeued + * output buffers. This keeps # of dequeued buffers from Surface less than + * configured max # of dequeued buffers all the time. + */ +struct SurfaceSyncObj { + /** + * ASharedMemory for synchronization data. Layout is below + * + * |lock(futex) 4bytes| + * |conditional_variable(futex) 4bytes| + * |# of max dequeable buffer 4bytes| + * |# of dequeued buffer 4bytes| + * |Status of the surface 4bytes| + * INIT = 0, Configuring surface is not finished. + * ACTIVE = 1, Surface is ready to allocate(dequeue). + * SWITCHING = 2, Switching to the new surface. It is blocked + * to allocate(dequeue) a buffer until switching + * completes. + */ + handle syncMemory; + + // Read-only. + // The values which are tied and not changed with respect to Surface + // which is currently set up. + /** BufferQueue id. */ + uint64_t bqId; + /** Generation id. */ + uint32_t generationId; + /** Consumer usage flags. See +ndk + * libnativewindow#AHardwareBuffer_UsageFlags for possible values. + */ + uint64_t consumerUsage; +}; diff --git a/memtrack/aidl/Android.bp b/memtrack/aidl/Android.bp index 29fec2451f9eda98a42f1551f967697d499324c7..79effcb7a823537c9128d7507a051f704ba312bc 100644 --- a/memtrack/aidl/Android.bp +++ b/memtrack/aidl/Android.bp @@ -39,4 +39,5 @@ aidl_interface { }, }, }, + versions: ["1"], } diff --git a/memtrack/aidl/aidl_api/android.hardware.memtrack/1/.hash b/memtrack/aidl/aidl_api/android.hardware.memtrack/1/.hash new file mode 100644 index 0000000000000000000000000000000000000000..d2c24d0bb13f7ab0667d8f256c4de30dffc835a4 --- /dev/null +++ b/memtrack/aidl/aidl_api/android.hardware.memtrack/1/.hash @@ -0,0 +1 @@ +25438132a462bf5b6f4334d966c95b70824e66c0 diff --git a/memtrack/aidl/aidl_api/android.hardware.memtrack/1/android/hardware/memtrack/DeviceInfo.aidl b/memtrack/aidl/aidl_api/android.hardware.memtrack/1/android/hardware/memtrack/DeviceInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..671e118e9274637fa56eb61cea088218541aae85 --- /dev/null +++ b/memtrack/aidl/aidl_api/android.hardware.memtrack/1/android/hardware/memtrack/DeviceInfo.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.memtrack; +@VintfStability +parcelable DeviceInfo { + int id; + @utf8InCpp String name; +} diff --git a/memtrack/aidl/aidl_api/android.hardware.memtrack/1/android/hardware/memtrack/IMemtrack.aidl b/memtrack/aidl/aidl_api/android.hardware.memtrack/1/android/hardware/memtrack/IMemtrack.aidl new file mode 100644 index 0000000000000000000000000000000000000000..9d490c0819e180d923453e8093008789fd688bc4 --- /dev/null +++ b/memtrack/aidl/aidl_api/android.hardware.memtrack/1/android/hardware/memtrack/IMemtrack.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.memtrack; +@VintfStability +interface IMemtrack { + android.hardware.memtrack.MemtrackRecord[] getMemory(in int pid, in android.hardware.memtrack.MemtrackType type); + android.hardware.memtrack.DeviceInfo[] getGpuDeviceInfo(); +} diff --git a/memtrack/aidl/aidl_api/android.hardware.memtrack/1/android/hardware/memtrack/MemtrackRecord.aidl b/memtrack/aidl/aidl_api/android.hardware.memtrack/1/android/hardware/memtrack/MemtrackRecord.aidl new file mode 100644 index 0000000000000000000000000000000000000000..8c9109b353b03ad232b8f2f3f2929eabdca41ccf --- /dev/null +++ b/memtrack/aidl/aidl_api/android.hardware.memtrack/1/android/hardware/memtrack/MemtrackRecord.aidl @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.memtrack; +@VintfStability +parcelable MemtrackRecord { + int flags; + long sizeInBytes; + const int FLAG_SMAPS_ACCOUNTED = 2; + const int FLAG_SMAPS_UNACCOUNTED = 4; + const int FLAG_SHARED = 8; + const int FLAG_SHARED_PSS = 16; + const int FLAG_PRIVATE = 32; + const int FLAG_SYSTEM = 64; + const int FLAG_DEDICATED = 128; + const int FLAG_NONSECURE = 256; + const int FLAG_SECURE = 512; +} diff --git a/memtrack/aidl/aidl_api/android.hardware.memtrack/1/android/hardware/memtrack/MemtrackType.aidl b/memtrack/aidl/aidl_api/android.hardware.memtrack/1/android/hardware/memtrack/MemtrackType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..1458640a24aceda668663f306cf1b6bba0becb0c --- /dev/null +++ b/memtrack/aidl/aidl_api/android.hardware.memtrack/1/android/hardware/memtrack/MemtrackType.aidl @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.memtrack; +@Backing(type="int") @VintfStability +enum MemtrackType { + OTHER = 0, + GL = 1, + GRAPHICS = 2, + MULTIMEDIA = 3, + CAMERA = 4, +} diff --git a/neuralnetworks/aidl/Android.bp b/neuralnetworks/aidl/Android.bp index 4316c3127c995c1fbc819e7ab2dbe085ea7b1755..3a69936541083e8dd23e9cc574736a14781b01c8 100644 --- a/neuralnetworks/aidl/Android.bp +++ b/neuralnetworks/aidl/Android.bp @@ -35,4 +35,5 @@ aidl_interface { min_sdk_version: "30", }, }, + versions: ["1"], } diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/.hash b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/.hash new file mode 100644 index 0000000000000000000000000000000000000000..b0dfd99800df9e61d89c07d671788db2d2530973 --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/.hash @@ -0,0 +1 @@ +ae57b48403df6752d8d8d56d215c3e31db74935d diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/BufferDesc.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/BufferDesc.aidl new file mode 100644 index 0000000000000000000000000000000000000000..05cec76c886140e09456994ef809b0e3c1dcff66 --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/BufferDesc.aidl @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@VintfStability +parcelable BufferDesc { + int[] dimensions; +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/BufferRole.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/BufferRole.aidl new file mode 100644 index 0000000000000000000000000000000000000000..10a6b75ac7a3ab2eb1e0d4fea72ef7eecf1d46a7 --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/BufferRole.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@VintfStability +parcelable BufferRole { + int modelIndex; + int ioIndex; + float probability; +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/Capabilities.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/Capabilities.aidl new file mode 100644 index 0000000000000000000000000000000000000000..30877c0294f9b4fdc8a020e42d7d2d37d47f28db --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/Capabilities.aidl @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@VintfStability +parcelable Capabilities { + android.hardware.neuralnetworks.PerformanceInfo relaxedFloat32toFloat16PerformanceScalar; + android.hardware.neuralnetworks.PerformanceInfo relaxedFloat32toFloat16PerformanceTensor; + android.hardware.neuralnetworks.OperandPerformance[] operandPerformance; + android.hardware.neuralnetworks.PerformanceInfo ifPerformance; + android.hardware.neuralnetworks.PerformanceInfo whilePerformance; +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/DataLocation.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/DataLocation.aidl new file mode 100644 index 0000000000000000000000000000000000000000..db49a3897993518d4d3d4eb8acc722205d1adce5 --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/DataLocation.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@VintfStability +parcelable DataLocation { + int poolIndex; + long offset; + long length; + long padding; +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/DeviceBuffer.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/DeviceBuffer.aidl new file mode 100644 index 0000000000000000000000000000000000000000..7cdd6db742d6a1950341dd047771283be7c541c9 --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/DeviceBuffer.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@VintfStability +parcelable DeviceBuffer { + android.hardware.neuralnetworks.IBuffer buffer; + int token; +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/DeviceType.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/DeviceType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..82fe8ae3e73e952e0744cb89e852335bb3f6d02e --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/DeviceType.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@Backing(type="int") @VintfStability +enum DeviceType { + OTHER = 1, + CPU = 2, + GPU = 3, + ACCELERATOR = 4, +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/ErrorStatus.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/ErrorStatus.aidl new file mode 100644 index 0000000000000000000000000000000000000000..57d5d6e4cd1e7ded8aeb334d65bd9122a37a800d --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/ErrorStatus.aidl @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@Backing(type="int") @VintfStability +enum ErrorStatus { + NONE = 0, + DEVICE_UNAVAILABLE = 1, + GENERAL_FAILURE = 2, + OUTPUT_INSUFFICIENT_SIZE = 3, + INVALID_ARGUMENT = 4, + MISSED_DEADLINE_TRANSIENT = 5, + MISSED_DEADLINE_PERSISTENT = 6, + RESOURCE_EXHAUSTED_TRANSIENT = 7, + RESOURCE_EXHAUSTED_PERSISTENT = 8, +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/ExecutionPreference.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/ExecutionPreference.aidl new file mode 100644 index 0000000000000000000000000000000000000000..4352d8f3347c3eea7006138bb416a2bce99ff174 --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/ExecutionPreference.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@Backing(type="int") @VintfStability +enum ExecutionPreference { + LOW_POWER = 0, + FAST_SINGLE_ANSWER = 1, + SUSTAINED_SPEED = 2, +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/ExecutionResult.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/ExecutionResult.aidl new file mode 100644 index 0000000000000000000000000000000000000000..44e9922f52e9c258d299c1d2e1e007c1394e3776 --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/ExecutionResult.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@VintfStability +parcelable ExecutionResult { + boolean outputSufficientSize; + android.hardware.neuralnetworks.OutputShape[] outputShapes; + android.hardware.neuralnetworks.Timing timing; +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/Extension.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/Extension.aidl new file mode 100644 index 0000000000000000000000000000000000000000..c47028d99fcd49c399a7c3bd92047c09a402d065 --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/Extension.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@VintfStability +parcelable Extension { + String name; + android.hardware.neuralnetworks.ExtensionOperandTypeInformation[] operandTypes; +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/ExtensionNameAndPrefix.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/ExtensionNameAndPrefix.aidl new file mode 100644 index 0000000000000000000000000000000000000000..6c287fd4603b33b0c2bdaab60a730025d58236d8 --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/ExtensionNameAndPrefix.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@VintfStability +parcelable ExtensionNameAndPrefix { + String name; + char prefix; +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/ExtensionOperandTypeInformation.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/ExtensionOperandTypeInformation.aidl new file mode 100644 index 0000000000000000000000000000000000000000..a3680aa9dd57b32af09bb7fa34efe5a9053a4078 --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/ExtensionOperandTypeInformation.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@VintfStability +parcelable ExtensionOperandTypeInformation { + char type; + boolean isTensor; + int byteSize; +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/FencedExecutionResult.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/FencedExecutionResult.aidl new file mode 100644 index 0000000000000000000000000000000000000000..7952b346325df543d2d053cef59a9db60e2e71dd --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/FencedExecutionResult.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@VintfStability +parcelable FencedExecutionResult { + android.hardware.neuralnetworks.IFencedExecutionCallback callback; + @nullable ParcelFileDescriptor syncFence; +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/FusedActivationFunc.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/FusedActivationFunc.aidl new file mode 100644 index 0000000000000000000000000000000000000000..7e61bbbdb181aaf2ea58b836a53df38411373814 --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/FusedActivationFunc.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@Backing(type="int") @VintfStability +enum FusedActivationFunc { + NONE = 0, + RELU = 1, + RELU1 = 2, + RELU6 = 3, +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/IBuffer.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/IBuffer.aidl new file mode 100644 index 0000000000000000000000000000000000000000..f10e7e24cad45b658d8c31f247ed9e5ce8acdbda --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/IBuffer.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@VintfStability +interface IBuffer { + void copyFrom(in android.hardware.neuralnetworks.Memory src, in int[] dimensions); + void copyTo(in android.hardware.neuralnetworks.Memory dst); +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/IBurst.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/IBurst.aidl new file mode 100644 index 0000000000000000000000000000000000000000..eb3d0b004a4ea3312228e8d8d3606cee611a64e0 --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/IBurst.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@VintfStability +interface IBurst { + android.hardware.neuralnetworks.ExecutionResult executeSynchronously(in android.hardware.neuralnetworks.Request request, in long[] memoryIdentifierTokens, in boolean measureTiming, in long deadlineNs, in long loopTimeoutDurationNs); + void releaseMemoryResource(in long memoryIdentifierToken); +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/IDevice.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/IDevice.aidl new file mode 100644 index 0000000000000000000000000000000000000000..c9c67f2fcd75ecfae7778cda54547ee057047799 --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/IDevice.aidl @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@VintfStability +interface IDevice { + android.hardware.neuralnetworks.DeviceBuffer allocate(in android.hardware.neuralnetworks.BufferDesc desc, in android.hardware.neuralnetworks.IPreparedModelParcel[] preparedModels, in android.hardware.neuralnetworks.BufferRole[] inputRoles, in android.hardware.neuralnetworks.BufferRole[] outputRoles); + android.hardware.neuralnetworks.Capabilities getCapabilities(); + android.hardware.neuralnetworks.NumberOfCacheFiles getNumberOfCacheFilesNeeded(); + android.hardware.neuralnetworks.Extension[] getSupportedExtensions(); + boolean[] getSupportedOperations(in android.hardware.neuralnetworks.Model model); + android.hardware.neuralnetworks.DeviceType getType(); + String getVersionString(); + void prepareModel(in android.hardware.neuralnetworks.Model model, in android.hardware.neuralnetworks.ExecutionPreference preference, in android.hardware.neuralnetworks.Priority priority, in long deadlineNs, in ParcelFileDescriptor[] modelCache, in ParcelFileDescriptor[] dataCache, in byte[] token, in android.hardware.neuralnetworks.IPreparedModelCallback callback); + void prepareModelFromCache(in long deadlineNs, in ParcelFileDescriptor[] modelCache, in ParcelFileDescriptor[] dataCache, in byte[] token, in android.hardware.neuralnetworks.IPreparedModelCallback callback); + const int BYTE_SIZE_OF_CACHE_TOKEN = 32; + const int MAX_NUMBER_OF_CACHE_FILES = 32; + const int EXTENSION_TYPE_HIGH_BITS_PREFIX = 15; + const int EXTENSION_TYPE_LOW_BITS_TYPE = 16; + const int OPERAND_TYPE_BASE_MAX = 65535; + const int OPERATION_TYPE_BASE_MAX = 65535; +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/IFencedExecutionCallback.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/IFencedExecutionCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..0bfb80ac789139c897bff489f4599b2fafe7c661 --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/IFencedExecutionCallback.aidl @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@VintfStability +interface IFencedExecutionCallback { + android.hardware.neuralnetworks.ErrorStatus getExecutionInfo(out android.hardware.neuralnetworks.Timing timingLaunched, out android.hardware.neuralnetworks.Timing timingFenced); +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/IPreparedModel.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/IPreparedModel.aidl new file mode 100644 index 0000000000000000000000000000000000000000..fccb5dc98eb4d1897242fb163df698209923bcac --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/IPreparedModel.aidl @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@VintfStability +interface IPreparedModel { + android.hardware.neuralnetworks.ExecutionResult executeSynchronously(in android.hardware.neuralnetworks.Request request, in boolean measureTiming, in long deadlineNs, in long loopTimeoutDurationNs); + android.hardware.neuralnetworks.FencedExecutionResult executeFenced(in android.hardware.neuralnetworks.Request request, in ParcelFileDescriptor[] waitFor, in boolean measureTiming, in long deadlineNs, in long loopTimeoutDurationNs, in long durationNs); + android.hardware.neuralnetworks.IBurst configureExecutionBurst(); + const long DEFAULT_LOOP_TIMEOUT_DURATION_NS = 2000000000; + const long MAXIMUM_LOOP_TIMEOUT_DURATION_NS = 15000000000; +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/IPreparedModelCallback.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/IPreparedModelCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..e0c763bc2a710769dd688a2d092b799372f20598 --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/IPreparedModelCallback.aidl @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@VintfStability +interface IPreparedModelCallback { + void notify(in android.hardware.neuralnetworks.ErrorStatus status, in android.hardware.neuralnetworks.IPreparedModel preparedModel); +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/IPreparedModelParcel.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/IPreparedModelParcel.aidl new file mode 100644 index 0000000000000000000000000000000000000000..dbedf127722a4805707df3ea94748f8f659daee8 --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/IPreparedModelParcel.aidl @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@VintfStability +parcelable IPreparedModelParcel { + android.hardware.neuralnetworks.IPreparedModel preparedModel; +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/Memory.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/Memory.aidl new file mode 100644 index 0000000000000000000000000000000000000000..37fa102cf4ea828021567f29604512d185aaa9e8 --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/Memory.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@VintfStability +union Memory { + android.hardware.common.Ashmem ashmem; + android.hardware.common.MappableFile mappableFile; + android.hardware.graphics.common.HardwareBuffer hardwareBuffer; +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/Model.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/Model.aidl new file mode 100644 index 0000000000000000000000000000000000000000..30d8dda55de03ad11c2a06b8c5a8ecbb8d835b16 --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/Model.aidl @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@VintfStability +parcelable Model { + android.hardware.neuralnetworks.Subgraph main; + android.hardware.neuralnetworks.Subgraph[] referenced; + byte[] operandValues; + android.hardware.neuralnetworks.Memory[] pools; + boolean relaxComputationFloat32toFloat16; + android.hardware.neuralnetworks.ExtensionNameAndPrefix[] extensionNameToPrefix; +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/NumberOfCacheFiles.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/NumberOfCacheFiles.aidl new file mode 100644 index 0000000000000000000000000000000000000000..9314760a4397846562bc2d7c71a72eed307592d1 --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/NumberOfCacheFiles.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@VintfStability +parcelable NumberOfCacheFiles { + int numModelCache; + int numDataCache; +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/Operand.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/Operand.aidl new file mode 100644 index 0000000000000000000000000000000000000000..1d9bdd844617009ae0dc1a332d9d70dbc7463e11 --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/Operand.aidl @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@VintfStability +parcelable Operand { + android.hardware.neuralnetworks.OperandType type = android.hardware.neuralnetworks.OperandType.FLOAT32; + int[] dimensions; + float scale; + int zeroPoint; + android.hardware.neuralnetworks.OperandLifeTime lifetime = android.hardware.neuralnetworks.OperandLifeTime.TEMPORARY_VARIABLE; + android.hardware.neuralnetworks.DataLocation location; + @nullable android.hardware.neuralnetworks.OperandExtraParams extraParams; +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/OperandExtraParams.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/OperandExtraParams.aidl new file mode 100644 index 0000000000000000000000000000000000000000..14792cff089f918b3d6e6881a8568ab3709b83ac --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/OperandExtraParams.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@VintfStability +union OperandExtraParams { + android.hardware.neuralnetworks.SymmPerChannelQuantParams channelQuant; + byte[] extension; +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/OperandLifeTime.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/OperandLifeTime.aidl new file mode 100644 index 0000000000000000000000000000000000000000..40adfb1dd803dfb9e568e22ff74135a6e0212111 --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/OperandLifeTime.aidl @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@Backing(type="int") @VintfStability +enum OperandLifeTime { + TEMPORARY_VARIABLE = 0, + SUBGRAPH_INPUT = 1, + SUBGRAPH_OUTPUT = 2, + CONSTANT_COPY = 3, + CONSTANT_POOL = 4, + NO_VALUE = 5, + SUBGRAPH = 6, +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/OperandPerformance.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/OperandPerformance.aidl new file mode 100644 index 0000000000000000000000000000000000000000..ebb361b7629c7a58d07b4c104961fe31f897e55a --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/OperandPerformance.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@VintfStability +parcelable OperandPerformance { + android.hardware.neuralnetworks.OperandType type = android.hardware.neuralnetworks.OperandType.FLOAT32; + android.hardware.neuralnetworks.PerformanceInfo info; +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/OperandType.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/OperandType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..9f2c759d383b90af6737fdf790115a64aecb7443 --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/OperandType.aidl @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@Backing(type="int") @VintfStability +enum OperandType { + FLOAT32 = 0, + INT32 = 1, + UINT32 = 2, + TENSOR_FLOAT32 = 3, + TENSOR_INT32 = 4, + TENSOR_QUANT8_ASYMM = 5, + BOOL = 6, + TENSOR_QUANT16_SYMM = 7, + TENSOR_FLOAT16 = 8, + TENSOR_BOOL8 = 9, + FLOAT16 = 10, + TENSOR_QUANT8_SYMM_PER_CHANNEL = 11, + TENSOR_QUANT16_ASYMM = 12, + TENSOR_QUANT8_SYMM = 13, + TENSOR_QUANT8_ASYMM_SIGNED = 14, + SUBGRAPH = 15, +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/Operation.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/Operation.aidl new file mode 100644 index 0000000000000000000000000000000000000000..a4a3fbee60c1eb517846eccc00f060c68a58ad1a --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/Operation.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@VintfStability +parcelable Operation { + android.hardware.neuralnetworks.OperationType type = android.hardware.neuralnetworks.OperationType.ADD; + int[] inputs; + int[] outputs; +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/OperationType.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/OperationType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..de3b43811591c8fbbbd1d45441ebd6b159456fa7 --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/OperationType.aidl @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@Backing(type="int") @VintfStability +enum OperationType { + ADD = 0, + AVERAGE_POOL_2D = 1, + CONCATENATION = 2, + CONV_2D = 3, + DEPTHWISE_CONV_2D = 4, + DEPTH_TO_SPACE = 5, + DEQUANTIZE = 6, + EMBEDDING_LOOKUP = 7, + FLOOR = 8, + FULLY_CONNECTED = 9, + HASHTABLE_LOOKUP = 10, + L2_NORMALIZATION = 11, + L2_POOL_2D = 12, + LOCAL_RESPONSE_NORMALIZATION = 13, + LOGISTIC = 14, + LSH_PROJECTION = 15, + LSTM = 16, + MAX_POOL_2D = 17, + MUL = 18, + RELU = 19, + RELU1 = 20, + RELU6 = 21, + RESHAPE = 22, + RESIZE_BILINEAR = 23, + RNN = 24, + SOFTMAX = 25, + SPACE_TO_DEPTH = 26, + SVDF = 27, + TANH = 28, + BATCH_TO_SPACE_ND = 29, + DIV = 30, + MEAN = 31, + PAD = 32, + SPACE_TO_BATCH_ND = 33, + SQUEEZE = 34, + STRIDED_SLICE = 35, + SUB = 36, + TRANSPOSE = 37, + ABS = 38, + ARGMAX = 39, + ARGMIN = 40, + AXIS_ALIGNED_BBOX_TRANSFORM = 41, + BIDIRECTIONAL_SEQUENCE_LSTM = 42, + BIDIRECTIONAL_SEQUENCE_RNN = 43, + BOX_WITH_NMS_LIMIT = 44, + CAST = 45, + CHANNEL_SHUFFLE = 46, + DETECTION_POSTPROCESSING = 47, + EQUAL = 48, + EXP = 49, + EXPAND_DIMS = 50, + GATHER = 51, + GENERATE_PROPOSALS = 52, + GREATER = 53, + GREATER_EQUAL = 54, + GROUPED_CONV_2D = 55, + HEATMAP_MAX_KEYPOINT = 56, + INSTANCE_NORMALIZATION = 57, + LESS = 58, + LESS_EQUAL = 59, + LOG = 60, + LOGICAL_AND = 61, + LOGICAL_NOT = 62, + LOGICAL_OR = 63, + LOG_SOFTMAX = 64, + MAXIMUM = 65, + MINIMUM = 66, + NEG = 67, + NOT_EQUAL = 68, + PAD_V2 = 69, + POW = 70, + PRELU = 71, + QUANTIZE = 72, + QUANTIZED_16BIT_LSTM = 73, + RANDOM_MULTINOMIAL = 74, + REDUCE_ALL = 75, + REDUCE_ANY = 76, + REDUCE_MAX = 77, + REDUCE_MIN = 78, + REDUCE_PROD = 79, + REDUCE_SUM = 80, + ROI_ALIGN = 81, + ROI_POOLING = 82, + RSQRT = 83, + SELECT = 84, + SIN = 85, + SLICE = 86, + SPLIT = 87, + SQRT = 88, + TILE = 89, + TOPK_V2 = 90, + TRANSPOSE_CONV_2D = 91, + UNIDIRECTIONAL_SEQUENCE_LSTM = 92, + UNIDIRECTIONAL_SEQUENCE_RNN = 93, + RESIZE_NEAREST_NEIGHBOR = 94, + QUANTIZED_LSTM = 95, + IF = 96, + WHILE = 97, + ELU = 98, + HARD_SWISH = 99, + FILL = 100, + RANK = 101, +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/OutputShape.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/OutputShape.aidl new file mode 100644 index 0000000000000000000000000000000000000000..f7335054cfa9e8c5ad77b956cb84f43b08b2e8ef --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/OutputShape.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@VintfStability +parcelable OutputShape { + int[] dimensions; + boolean isSufficient; +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/PerformanceInfo.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/PerformanceInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..04910f54107dc7a4d1137b0fb3cffc8dcf8b82ad --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/PerformanceInfo.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@VintfStability +parcelable PerformanceInfo { + float execTime; + float powerUsage; +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/Priority.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/Priority.aidl new file mode 100644 index 0000000000000000000000000000000000000000..8f357097abf894cc94ba95dfad5a17ae4f448bec --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/Priority.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@Backing(type="int") @VintfStability +enum Priority { + LOW = 0, + MEDIUM = 1, + HIGH = 2, +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/Request.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/Request.aidl new file mode 100644 index 0000000000000000000000000000000000000000..39ec7a9acdbf2c7e79e1e2d496fb7b4f7417000e --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/Request.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@VintfStability +parcelable Request { + android.hardware.neuralnetworks.RequestArgument[] inputs; + android.hardware.neuralnetworks.RequestArgument[] outputs; + android.hardware.neuralnetworks.RequestMemoryPool[] pools; +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/RequestArgument.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/RequestArgument.aidl new file mode 100644 index 0000000000000000000000000000000000000000..e3541c0ece261a9af685c1cdcb67719248ce0077 --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/RequestArgument.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@VintfStability +parcelable RequestArgument { + boolean hasNoValue; + android.hardware.neuralnetworks.DataLocation location; + int[] dimensions; +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/RequestMemoryPool.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/RequestMemoryPool.aidl new file mode 100644 index 0000000000000000000000000000000000000000..312f5813bc0a663bd8c607e6cf8616ea4ef8ed54 --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/RequestMemoryPool.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@VintfStability +union RequestMemoryPool { + android.hardware.neuralnetworks.Memory pool; + int token; +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/Subgraph.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/Subgraph.aidl new file mode 100644 index 0000000000000000000000000000000000000000..b7d44515f45b569d0ac5f96b5e31fe175f5c2b88 --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/Subgraph.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@VintfStability +parcelable Subgraph { + android.hardware.neuralnetworks.Operand[] operands; + android.hardware.neuralnetworks.Operation[] operations; + int[] inputIndexes; + int[] outputIndexes; +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/SymmPerChannelQuantParams.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/SymmPerChannelQuantParams.aidl new file mode 100644 index 0000000000000000000000000000000000000000..02d68f9ed168b363a850144832fb1be424ccbb5b --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/SymmPerChannelQuantParams.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@VintfStability +parcelable SymmPerChannelQuantParams { + float[] scales; + int channelDim; +} diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/Timing.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/Timing.aidl new file mode 100644 index 0000000000000000000000000000000000000000..bcc83cfbee38dd38b7e415f628d7056025cb385f --- /dev/null +++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/1/android/hardware/neuralnetworks/Timing.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.neuralnetworks; +@VintfStability +parcelable Timing { + long timeOnDeviceNs; + long timeInDriverNs; +} diff --git a/nfc/1.0/default/Nfc.cpp b/nfc/1.0/default/Nfc.cpp index fcdcbbc301dda3cf837010a494a01c20529bfee4..a1e50f059c17ce020ab5a10e4c3d36faec096e07 100644 --- a/nfc/1.0/default/Nfc.cpp +++ b/nfc/1.0/default/Nfc.cpp @@ -38,7 +38,7 @@ Nfc::Nfc(nfc_nci_device_t* device) : mDevice(device) {} ::android::hardware::Return Nfc::coreInitialized(const hidl_vec& data) { hidl_vec copy = data; - if (mDevice == nullptr) { + if (mDevice == nullptr || copy.size() == 0) { return NfcStatus::FAILED; } int ret = mDevice->core_initialized(mDevice, ©[0]); diff --git a/oemlock/aidl/Android.bp b/oemlock/aidl/Android.bp index 439d43d76099a988011a6204fa81bd64604d661d..d1930f982eae82fa7c2586ee21a6ff3b05e1431f 100644 --- a/oemlock/aidl/Android.bp +++ b/oemlock/aidl/Android.bp @@ -22,4 +22,5 @@ aidl_interface { }, }, }, + versions: ["1"], } diff --git a/oemlock/aidl/aidl_api/android.hardware.oemlock/1/.hash b/oemlock/aidl/aidl_api/android.hardware.oemlock/1/.hash new file mode 100644 index 0000000000000000000000000000000000000000..79fe16561329c62698c4708bbd980841f14c9979 --- /dev/null +++ b/oemlock/aidl/aidl_api/android.hardware.oemlock/1/.hash @@ -0,0 +1 @@ +782d36d56fbdca1105672dd96b8e955b6a81dadf diff --git a/oemlock/aidl/aidl_api/android.hardware.oemlock/1/android/hardware/oemlock/IOemLock.aidl b/oemlock/aidl/aidl_api/android.hardware.oemlock/1/android/hardware/oemlock/IOemLock.aidl new file mode 100644 index 0000000000000000000000000000000000000000..977746c4dd669c404e01eec51b438731d649ec1c --- /dev/null +++ b/oemlock/aidl/aidl_api/android.hardware.oemlock/1/android/hardware/oemlock/IOemLock.aidl @@ -0,0 +1,42 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.oemlock; +@VintfStability +interface IOemLock { + String getName(); + boolean isOemUnlockAllowedByCarrier(); + boolean isOemUnlockAllowedByDevice(); + android.hardware.oemlock.OemLockSecureStatus setOemUnlockAllowedByCarrier(in boolean allowed, in byte[] signature); + void setOemUnlockAllowedByDevice(in boolean allowed); +} diff --git a/oemlock/aidl/aidl_api/android.hardware.oemlock/1/android/hardware/oemlock/OemLockSecureStatus.aidl b/oemlock/aidl/aidl_api/android.hardware.oemlock/1/android/hardware/oemlock/OemLockSecureStatus.aidl new file mode 100644 index 0000000000000000000000000000000000000000..8376744edce209ff29e9e1c49e28376a12c194b1 --- /dev/null +++ b/oemlock/aidl/aidl_api/android.hardware.oemlock/1/android/hardware/oemlock/OemLockSecureStatus.aidl @@ -0,0 +1,40 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.oemlock; +@Backing(type="int") @VintfStability +enum OemLockSecureStatus { + OK = 0, + FAILED = 1, + INVALID_SIGNATURE = 2, +} diff --git a/power/aidl/Android.bp b/power/aidl/Android.bp index 054fea546723978b2917bc7894f82b38b2ffc577..c722795a6c467e20703523289cc25aa7e0841e2c 100644 --- a/power/aidl/Android.bp +++ b/power/aidl/Android.bp @@ -29,6 +29,9 @@ aidl_interface { ], stability: "vintf", backend: { + cpp: { + enabled: true, + }, java: { platform_apis: true, }, @@ -38,5 +41,8 @@ aidl_interface { }, }, }, - versions: ["1"], + versions: [ + "1", + "2", + ], } diff --git a/power/aidl/aidl_api/android.hardware.power/2/.hash b/power/aidl/aidl_api/android.hardware.power/2/.hash new file mode 100644 index 0000000000000000000000000000000000000000..0671909ccaae14d87421c8cba1398417de737567 --- /dev/null +++ b/power/aidl/aidl_api/android.hardware.power/2/.hash @@ -0,0 +1 @@ +ef4f5ed58e39693f25c1f8fdcfe7b958c6b800bc diff --git a/power/aidl/aidl_api/android.hardware.power/2/android/hardware/power/Boost.aidl b/power/aidl/aidl_api/android.hardware.power/2/android/hardware/power/Boost.aidl new file mode 100644 index 0000000000000000000000000000000000000000..c792d4e0c21c84249e4da7adda65a34ed1150ba4 --- /dev/null +++ b/power/aidl/aidl_api/android.hardware.power/2/android/hardware/power/Boost.aidl @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.power; +@Backing(type="int") @VintfStability +enum Boost { + INTERACTION = 0, + DISPLAY_UPDATE_IMMINENT = 1, + ML_ACC = 2, + AUDIO_LAUNCH = 3, + CAMERA_LAUNCH = 4, + CAMERA_SHOT = 5, +} diff --git a/power/aidl/aidl_api/android.hardware.power/2/android/hardware/power/IPower.aidl b/power/aidl/aidl_api/android.hardware.power/2/android/hardware/power/IPower.aidl new file mode 100644 index 0000000000000000000000000000000000000000..ae03313f11ed79eede8281bb92eef1e624408ebf --- /dev/null +++ b/power/aidl/aidl_api/android.hardware.power/2/android/hardware/power/IPower.aidl @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.power; +@VintfStability +interface IPower { + oneway void setMode(in android.hardware.power.Mode type, in boolean enabled); + boolean isModeSupported(in android.hardware.power.Mode type); + oneway void setBoost(in android.hardware.power.Boost type, in int durationMs); + boolean isBoostSupported(in android.hardware.power.Boost type); + android.hardware.power.IPowerHintSession createHintSession(in int tgid, in int uid, in int[] threadIds, in long durationNanos); + long getHintSessionPreferredRate(); +} diff --git a/power/aidl/aidl_api/android.hardware.power/2/android/hardware/power/IPowerHintSession.aidl b/power/aidl/aidl_api/android.hardware.power/2/android/hardware/power/IPowerHintSession.aidl new file mode 100644 index 0000000000000000000000000000000000000000..1d3ecb7eee7dfbd24b7ccc473e7466f8621c9518 --- /dev/null +++ b/power/aidl/aidl_api/android.hardware.power/2/android/hardware/power/IPowerHintSession.aidl @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.power; +@VintfStability +interface IPowerHintSession { + oneway void updateTargetWorkDuration(long targetDurationNanos); + oneway void reportActualWorkDuration(in android.hardware.power.WorkDuration[] durations); + oneway void pause(); + oneway void resume(); + oneway void close(); +} diff --git a/power/aidl/aidl_api/android.hardware.power/2/android/hardware/power/Mode.aidl b/power/aidl/aidl_api/android.hardware.power/2/android/hardware/power/Mode.aidl new file mode 100644 index 0000000000000000000000000000000000000000..8920c014e37bf224a121ad212c78b2e82bfcde04 --- /dev/null +++ b/power/aidl/aidl_api/android.hardware.power/2/android/hardware/power/Mode.aidl @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.power; +@Backing(type="int") @VintfStability +enum Mode { + DOUBLE_TAP_TO_WAKE = 0, + LOW_POWER = 1, + SUSTAINED_PERFORMANCE = 2, + FIXED_PERFORMANCE = 3, + VR = 4, + LAUNCH = 5, + EXPENSIVE_RENDERING = 6, + INTERACTIVE = 7, + DEVICE_IDLE = 8, + DISPLAY_INACTIVE = 9, + AUDIO_STREAMING_LOW_LATENCY = 10, + CAMERA_STREAMING_SECURE = 11, + CAMERA_STREAMING_LOW = 12, + CAMERA_STREAMING_MID = 13, + CAMERA_STREAMING_HIGH = 14, +} diff --git a/power/aidl/aidl_api/android.hardware.power/2/android/hardware/power/WorkDuration.aidl b/power/aidl/aidl_api/android.hardware.power/2/android/hardware/power/WorkDuration.aidl new file mode 100644 index 0000000000000000000000000000000000000000..e86cd40ec29b431889cdfb7d1d6d824b196dd67c --- /dev/null +++ b/power/aidl/aidl_api/android.hardware.power/2/android/hardware/power/WorkDuration.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.power; +@VintfStability +parcelable WorkDuration { + long timeStampNanos; + long durationNanos; +} diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Boost.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Boost.aidl index aced215bb9de2f69e8b5fa3223e83f0155fbbad1..c792d4e0c21c84249e4da7adda65a34ed1150ba4 100644 --- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Boost.aidl +++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Boost.aidl @@ -1,14 +1,30 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ /////////////////////////////////////////////////////////////////////////////// // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // /////////////////////////////////////////////////////////////////////////////// -// This file is a snapshot of an AIDL interface (or parcelable). Do not try to -// edit this file. It looks like you are doing that because you have modified -// an AIDL interface in a backward-incompatible way, e.g., deleting a function -// from an interface or a field from a parcelable and it broke the build. That -// breakage is intended. +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. // -// You must not make a backward incompatible changes to the AIDL files built +// You must not make a backward incompatible change to any AIDL file built // with the aidl_interface module type with versions property set. The module // type is used to build AIDL files in a way that they can be used across // independently updatable components of the system. If a device is shipped diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPower.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPower.aidl index 8a06623fcab44eb35a8e08b6cb3ebeab3f878289..ae03313f11ed79eede8281bb92eef1e624408ebf 100644 --- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPower.aidl +++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPower.aidl @@ -1,14 +1,30 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ /////////////////////////////////////////////////////////////////////////////// // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // /////////////////////////////////////////////////////////////////////////////// -// This file is a snapshot of an AIDL interface (or parcelable). Do not try to -// edit this file. It looks like you are doing that because you have modified -// an AIDL interface in a backward-incompatible way, e.g., deleting a function -// from an interface or a field from a parcelable and it broke the build. That -// breakage is intended. +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. // -// You must not make a backward incompatible changes to the AIDL files built +// You must not make a backward incompatible change to any AIDL file built // with the aidl_interface module type with versions property set. The module // type is used to build AIDL files in a way that they can be used across // independently updatable components of the system. If a device is shipped @@ -22,4 +38,6 @@ interface IPower { boolean isModeSupported(in android.hardware.power.Mode type); oneway void setBoost(in android.hardware.power.Boost type, in int durationMs); boolean isBoostSupported(in android.hardware.power.Boost type); + android.hardware.power.IPowerHintSession createHintSession(in int tgid, in int uid, in int[] threadIds, in long durationNanos); + long getHintSessionPreferredRate(); } diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPowerHintSession.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPowerHintSession.aidl new file mode 100644 index 0000000000000000000000000000000000000000..1d3ecb7eee7dfbd24b7ccc473e7466f8621c9518 --- /dev/null +++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPowerHintSession.aidl @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.power; +@VintfStability +interface IPowerHintSession { + oneway void updateTargetWorkDuration(long targetDurationNanos); + oneway void reportActualWorkDuration(in android.hardware.power.WorkDuration[] durations); + oneway void pause(); + oneway void resume(); + oneway void close(); +} diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Mode.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Mode.aidl index f7c2552c8d32ee083c2cbd9f00b26da5eeae1f90..8920c014e37bf224a121ad212c78b2e82bfcde04 100644 --- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Mode.aidl +++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Mode.aidl @@ -1,14 +1,30 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ /////////////////////////////////////////////////////////////////////////////// // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // /////////////////////////////////////////////////////////////////////////////// -// This file is a snapshot of an AIDL interface (or parcelable). Do not try to -// edit this file. It looks like you are doing that because you have modified -// an AIDL interface in a backward-incompatible way, e.g., deleting a function -// from an interface or a field from a parcelable and it broke the build. That -// breakage is intended. +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. // -// You must not make a backward incompatible changes to the AIDL files built +// You must not make a backward incompatible change to any AIDL file built // with the aidl_interface module type with versions property set. The module // type is used to build AIDL files in a way that they can be used across // independently updatable components of the system. If a device is shipped diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/WorkDuration.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/WorkDuration.aidl new file mode 100644 index 0000000000000000000000000000000000000000..e86cd40ec29b431889cdfb7d1d6d824b196dd67c --- /dev/null +++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/WorkDuration.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.power; +@VintfStability +parcelable WorkDuration { + long timeStampNanos; + long durationNanos; +} diff --git a/power/aidl/android/hardware/power/IPower.aidl b/power/aidl/android/hardware/power/IPower.aidl index 2c4bd86014c003daa1ad754085d5d3a80a310481..ee8e5a3a61cd291e35ec7519def491ed4bb332f4 100644 --- a/power/aidl/android/hardware/power/IPower.aidl +++ b/power/aidl/android/hardware/power/IPower.aidl @@ -17,6 +17,7 @@ package android.hardware.power; import android.hardware.power.Boost; +import android.hardware.power.IPowerHintSession; import android.hardware.power.Mode; @VintfStability @@ -69,4 +70,37 @@ interface IPower { * @param type Boost to be queried */ boolean isBoostSupported(in Boost type); + + /** + * A Session represents a group of threads with an inter-related workload such that hints for + * their performance should be considered as a unit. The threads in a given session should be + * long-life and not created or destroyed dynamically. + * + * Each session is expected to have a periodic workload with a target duration for each + * cycle. The cycle duration is likely greater than the target work duration to allow other + * parts of the pipeline to run within the available budget. For example, a renderer thread may + * work at 60hz in order to produce frames at the display's frame but have a target work + * duration of only 6ms. + * + * Creates a session for the given set of threads and sets their initial target work + * duration. + * + * @return the new session if it is supported on this device, otherwise return with + * EX_UNSUPPORTED_OPERATION error if hint session is not supported on this device. + * @param tgid The TGID to be associated with this session. + * @param uid The UID to be associated with this session. + * @param threadIds The list of threads to be associated with this session. + * @param durationNanos The desired duration in nanoseconds for this session. + */ + IPowerHintSession createHintSession( + in int tgid, in int uid, in int[] threadIds, in long durationNanos); + + /** + * Get preferred update rate (interval) information for this device. Framework must communicate + * this rate to Apps, and also ensure the session hint sent no faster than the update rate. + * + * @return the preferred update rate in nanoseconds supported by device software. Return with + * EX_UNSUPPORTED_OPERATION if hint session is not supported. + */ + long getHintSessionPreferredRate(); } diff --git a/power/aidl/android/hardware/power/IPowerHintSession.aidl b/power/aidl/android/hardware/power/IPowerHintSession.aidl new file mode 100644 index 0000000000000000000000000000000000000000..c2894488555ac65fa1a2f51cc7baef5ef706f694 --- /dev/null +++ b/power/aidl/android/hardware/power/IPowerHintSession.aidl @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.power; + +import android.hardware.power.WorkDuration; + +@VintfStability +oneway interface IPowerHintSession { + /** + * Updates the desired duration of a previously-created thread group. + * + * See {@link IPowerHintSession#createHintSession} for more information on how + * the desired duration will be used. + * + * @param targetDurationNanos the new desired duration in nanoseconds + */ + void updateTargetWorkDuration(long targetDurationNanos); + + /** + * Reports the actual duration of a thread group. + * + * The system will attempt to adjust the core placement of the threads within + * the thread group and/or the frequency of the core on which they are run to bring + * the actual duration close to the target duration. + * + * @param actualDurationMicros how long the thread group took to complete its + * last task in nanoseconds + */ + void reportActualWorkDuration(in WorkDuration[] durations); + + /** + * Pause the session when the application is not allowed to send hint in framework. + */ + void pause(); + + /** + * Resume the session when the application is allowed to send hint in framework. + */ + void resume(); + + /** + * Close the session to release resources. + */ + void close(); +} diff --git a/power/aidl/android/hardware/power/WorkDuration.aidl b/power/aidl/android/hardware/power/WorkDuration.aidl new file mode 100644 index 0000000000000000000000000000000000000000..a06a058fb541287cee08ade0faacea30eafbc32f --- /dev/null +++ b/power/aidl/android/hardware/power/WorkDuration.aidl @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.power; + +@VintfStability +parcelable WorkDuration { + /** + * Time stamp in nanoseconds based on CLOCK_MONOTONIC when the duration + * sample was measured. + */ + long timeStampNanos; + /** + * Work duration in nanoseconds. + */ + long durationNanos; +} diff --git a/power/aidl/default/Android.bp b/power/aidl/default/Android.bp index 22dd9a2dfbb85d208dfa3c6a5ca1e4c1d79d14ed..e10d329cd55d9a7235415f095995e4aea0621204 100644 --- a/power/aidl/default/Android.bp +++ b/power/aidl/default/Android.bp @@ -30,7 +30,7 @@ cc_binary { shared_libs: [ "libbase", "libbinder_ndk", - "android.hardware.power-V1-ndk", + "android.hardware.power-V2-ndk", ], srcs: [ "main.cpp", diff --git a/power/aidl/default/Power.cpp b/power/aidl/default/Power.cpp index 8610de35b858eca39b1dd068e1d1527ed299ec6a..7f08f449267e6c910d7d180dd76546b23ae93a24 100644 --- a/power/aidl/default/Power.cpp +++ b/power/aidl/default/Power.cpp @@ -25,6 +25,10 @@ namespace power { namespace impl { namespace example { +const std::vector BOOST_RANGE{ndk::enum_range().begin(), + ndk::enum_range().end()}; +const std::vector MODE_RANGE{ndk::enum_range().begin(), ndk::enum_range().end()}; + ndk::ScopedAStatus Power::setMode(Mode type, bool enabled) { LOG(VERBOSE) << "Power setMode: " << static_cast(type) << " to: " << enabled; return ndk::ScopedAStatus::ok(); @@ -32,7 +36,7 @@ ndk::ScopedAStatus Power::setMode(Mode type, bool enabled) { ndk::ScopedAStatus Power::isModeSupported(Mode type, bool* _aidl_return) { LOG(INFO) << "Power isModeSupported: " << static_cast(type); - *_aidl_return = false; + *_aidl_return = type >= MODE_RANGE.front() && type <= MODE_RANGE.back(); return ndk::ScopedAStatus::ok(); } @@ -44,10 +48,21 @@ ndk::ScopedAStatus Power::setBoost(Boost type, int32_t durationMs) { ndk::ScopedAStatus Power::isBoostSupported(Boost type, bool* _aidl_return) { LOG(INFO) << "Power isBoostSupported: " << static_cast(type); - *_aidl_return = false; + *_aidl_return = type >= BOOST_RANGE.front() && type <= BOOST_RANGE.back(); return ndk::ScopedAStatus::ok(); } +ndk::ScopedAStatus Power::createHintSession(int32_t, int32_t, const std::vector&, int64_t, + std::shared_ptr* _aidl_return) { + *_aidl_return = nullptr; + return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); +} + +ndk::ScopedAStatus Power::getHintSessionPreferredRate(int64_t* outNanoseconds) { + *outNanoseconds = -1; + return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); +} + } // namespace example } // namespace impl } // namespace power diff --git a/power/aidl/default/Power.h b/power/aidl/default/Power.h index f7645aa527e8f41a2ac3ae83118224c5bce0b66a..ef6439dde6cf228b3681f7b768d6b791b63532d1 100644 --- a/power/aidl/default/Power.h +++ b/power/aidl/default/Power.h @@ -30,6 +30,11 @@ class Power : public BnPower { ndk::ScopedAStatus isModeSupported(Mode type, bool* _aidl_return) override; ndk::ScopedAStatus setBoost(Boost type, int32_t durationMs) override; ndk::ScopedAStatus isBoostSupported(Boost type, bool* _aidl_return) override; + ndk::ScopedAStatus createHintSession(int32_t tgid, int32_t uid, + const std::vector& threadIds, + int64_t durationNanos, + std::shared_ptr* _aidl_return) override; + ndk::ScopedAStatus getHintSessionPreferredRate(int64_t* outNanoseconds) override; }; } // namespace example diff --git a/power/aidl/default/power-default.xml b/power/aidl/default/power-default.xml index caf6ea2d5d6a71d28c49d0d389f7f31a1c32a964..9f56debdae5239484dff2a8aeb927515833e4fb8 100644 --- a/power/aidl/default/power-default.xml +++ b/power/aidl/default/power-default.xml @@ -1,6 +1,7 @@ android.hardware.power + 2 IPower/default diff --git a/power/aidl/vts/Android.bp b/power/aidl/vts/Android.bp index 1051b038234f9a138b597a61c9bdcc5e10d4b6bc..eccd87271614297f7f8e66e611181150b5afdec8 100644 --- a/power/aidl/vts/Android.bp +++ b/power/aidl/vts/Android.bp @@ -29,10 +29,10 @@ cc_test { ], srcs: ["VtsHalPowerTargetTest.cpp"], shared_libs: [ - "libbinder", + "libbinder_ndk", ], static_libs: [ - "android.hardware.power-V1-cpp", + "android.hardware.power-V2-ndk", ], test_suites: [ "vts", diff --git a/power/aidl/vts/VtsHalPowerTargetTest.cpp b/power/aidl/vts/VtsHalPowerTargetTest.cpp index d036c9099f6b9f91f78f1d66748742c77515f355..ffab66c3125b2b7a23ea0d0bf0aceac92ffdd4f4 100644 --- a/power/aidl/vts/VtsHalPowerTargetTest.cpp +++ b/power/aidl/vts/VtsHalPowerTargetTest.cpp @@ -16,29 +16,29 @@ #include #include +#include +#include #include -#include -#include -#include -#include -#include - -#include - -using android::ProcessState; -using android::sp; -using android::String16; -using android::base::GetUintProperty; -using android::binder::Status; +#include +#include +#include +#include + +#include + +namespace aidl::android::hardware::power { +namespace { + +using ::android::base::GetUintProperty; using android::hardware::power::Boost; using android::hardware::power::IPower; +using android::hardware::power::IPowerHintSession; using android::hardware::power::Mode; +using android::hardware::power::WorkDuration; -const std::vector kBoosts{android::enum_range().begin(), - android::enum_range().end()}; +const std::vector kBoosts{ndk::enum_range().begin(), ndk::enum_range().end()}; -const std::vector kModes{android::enum_range().begin(), - android::enum_range().end()}; +const std::vector kModes{ndk::enum_range().begin(), ndk::enum_range().end()}; const std::vector kInvalidBoosts = { static_cast(static_cast(kBoosts.front()) - 1), @@ -50,14 +50,53 @@ const std::vector kInvalidModes = { static_cast(static_cast(kModes.back()) + 1), }; +class DurationWrapper : public WorkDuration { + public: + DurationWrapper(int64_t dur, int64_t time) { + durationNanos = dur; + timeStampNanos = time; + } +}; + +const std::vector kSelfTids = { + gettid(), +}; + +const std::vector kEmptyTids = {}; + +const std::vector kNoDurations = {}; + +const std::vector kDurationsWithZero = { + DurationWrapper(1000L, 1L), + DurationWrapper(0L, 2L), +}; + +const std::vector kDurationsWithNegative = { + DurationWrapper(1000L, 1L), + DurationWrapper(-1000L, 2L), +}; + +const std::vector kDurations = { + DurationWrapper(1L, 1L), + DurationWrapper(1000L, 2L), + DurationWrapper(1000000L, 3L), + DurationWrapper(1000000000L, 4L), +}; + +inline bool isUnknownOrUnsupported(const ndk::ScopedAStatus& status) { + return status.getStatus() == STATUS_UNKNOWN_TRANSACTION || + status.getExceptionCode() == EX_UNSUPPORTED_OPERATION; +} + class PowerAidl : public testing::TestWithParam { public: virtual void SetUp() override { - power = android::waitForDeclaredService(String16(GetParam().c_str())); - ASSERT_NE(power, nullptr); + AIBinder* binder = AServiceManager_waitForService(GetParam().c_str()); + ASSERT_NE(binder, nullptr); + power = IPower::fromBinder(ndk::SpAIBinder(binder)); } - sp power; + std::shared_ptr power; }; TEST_P(PowerAidl, setMode) { @@ -110,6 +149,55 @@ TEST_P(PowerAidl, isBoostSupported) { } } +TEST_P(PowerAidl, getHintSessionPreferredRate) { + int64_t rate = -1; + auto status = power->getHintSessionPreferredRate(&rate); + if (!status.isOk()) { + EXPECT_TRUE(isUnknownOrUnsupported(status)); + return; + } + + // At least 1ms rate limit from HAL + ASSERT_GE(rate, 1000000); +} + +TEST_P(PowerAidl, createAndCloseHintSession) { + std::shared_ptr session; + auto status = power->createHintSession(getpid(), getuid(), kSelfTids, 16666666L, &session); + if (!status.isOk()) { + EXPECT_TRUE(isUnknownOrUnsupported(status)); + return; + } + ASSERT_NE(nullptr, session); + ASSERT_TRUE(session->pause().isOk()); + ASSERT_TRUE(session->resume().isOk()); + // Test normal destroy operation + ASSERT_TRUE(session->close().isOk()); + session.reset(); +} +TEST_P(PowerAidl, createHintSessionFailed) { + std::shared_ptr session; + auto status = power->createHintSession(getpid(), getuid(), kEmptyTids, 16666666L, &session); + ASSERT_FALSE(status.isOk()); + if (isUnknownOrUnsupported(status)) { + return; + } + ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode()); +} + +TEST_P(PowerAidl, updateAndReportDurations) { + std::shared_ptr session; + auto status = power->createHintSession(getpid(), getuid(), kSelfTids, 16666666L, &session); + if (!status.isOk()) { + EXPECT_TRUE(isUnknownOrUnsupported(status)); + return; + } + ASSERT_NE(nullptr, session); + + ASSERT_TRUE(session->updateTargetWorkDuration(16666667LL).isOk()); + ASSERT_TRUE(session->reportActualWorkDuration(kDurations).isOk()); +} + // FIXED_PERFORMANCE mode is required for all devices which ship on Android 11 // or later TEST_P(PowerAidl, hasFixedPerformance) { @@ -128,12 +216,16 @@ TEST_P(PowerAidl, hasFixedPerformance) { GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PowerAidl); INSTANTIATE_TEST_SUITE_P(Power, PowerAidl, - testing::ValuesIn(android::getAidlHalInstanceNames(IPower::descriptor)), - android::PrintInstanceNameToString); + testing::ValuesIn(::android::getAidlHalInstanceNames(IPower::descriptor)), + ::android::PrintInstanceNameToString); + +} // namespace int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); - ProcessState::self()->setThreadPoolMaxThreadCount(1); - ProcessState::self()->startThreadPool(); + ABinderProcess_setThreadPoolMaxThreadCount(1); + ABinderProcess_startThreadPool(); return RUN_ALL_TESTS(); } + +} // namespace aidl::android::hardware::power diff --git a/power/stats/aidl/Android.bp b/power/stats/aidl/Android.bp index 0dbf9b49e095e60e6689ce0e4e3335e7a95de717..48d3c51f1a1bb17cf160fcc1524820aeb11831a5 100644 --- a/power/stats/aidl/Android.bp +++ b/power/stats/aidl/Android.bp @@ -42,4 +42,5 @@ aidl_interface { }, }, host_supported: true, + versions: ["1"], } diff --git a/power/stats/aidl/aidl_api/android.hardware.power.stats/1/.hash b/power/stats/aidl/aidl_api/android.hardware.power.stats/1/.hash new file mode 100644 index 0000000000000000000000000000000000000000..c248cc300a1a162159a22b71d92a93259044be27 --- /dev/null +++ b/power/stats/aidl/aidl_api/android.hardware.power.stats/1/.hash @@ -0,0 +1 @@ +93253458fae451cf1187db6120a59fab428f7d02 diff --git a/power/stats/aidl/aidl_api/android.hardware.power.stats/1/android/hardware/power/stats/Channel.aidl b/power/stats/aidl/aidl_api/android.hardware.power.stats/1/android/hardware/power/stats/Channel.aidl new file mode 100644 index 0000000000000000000000000000000000000000..d1048a4095bede327024bf6d9ede3c21d9a5dc15 --- /dev/null +++ b/power/stats/aidl/aidl_api/android.hardware.power.stats/1/android/hardware/power/stats/Channel.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.power.stats; +@VintfStability +parcelable Channel { + int id; + @utf8InCpp String name; + @utf8InCpp String subsystem; +} diff --git a/power/stats/aidl/aidl_api/android.hardware.power.stats/1/android/hardware/power/stats/EnergyConsumer.aidl b/power/stats/aidl/aidl_api/android.hardware.power.stats/1/android/hardware/power/stats/EnergyConsumer.aidl new file mode 100644 index 0000000000000000000000000000000000000000..13f528d57b9fe716db14a3bfdbbdae3f38fc7903 --- /dev/null +++ b/power/stats/aidl/aidl_api/android.hardware.power.stats/1/android/hardware/power/stats/EnergyConsumer.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.power.stats; +@VintfStability +parcelable EnergyConsumer { + int id; + int ordinal; + android.hardware.power.stats.EnergyConsumerType type = android.hardware.power.stats.EnergyConsumerType.OTHER; + @utf8InCpp String name; +} diff --git a/power/stats/aidl/aidl_api/android.hardware.power.stats/1/android/hardware/power/stats/EnergyConsumerAttribution.aidl b/power/stats/aidl/aidl_api/android.hardware.power.stats/1/android/hardware/power/stats/EnergyConsumerAttribution.aidl new file mode 100644 index 0000000000000000000000000000000000000000..ee120685c7101cdd8c2ac48f67e451eeaf472835 --- /dev/null +++ b/power/stats/aidl/aidl_api/android.hardware.power.stats/1/android/hardware/power/stats/EnergyConsumerAttribution.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.power.stats; +@VintfStability +parcelable EnergyConsumerAttribution { + int uid; + long energyUWs; +} diff --git a/power/stats/aidl/aidl_api/android.hardware.power.stats/1/android/hardware/power/stats/EnergyConsumerResult.aidl b/power/stats/aidl/aidl_api/android.hardware.power.stats/1/android/hardware/power/stats/EnergyConsumerResult.aidl new file mode 100644 index 0000000000000000000000000000000000000000..7d8aa989cd7e2f032c179e200f10cb80282a88c7 --- /dev/null +++ b/power/stats/aidl/aidl_api/android.hardware.power.stats/1/android/hardware/power/stats/EnergyConsumerResult.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.power.stats; +@VintfStability +parcelable EnergyConsumerResult { + int id; + long timestampMs; + long energyUWs; + android.hardware.power.stats.EnergyConsumerAttribution[] attribution; +} diff --git a/power/stats/aidl/aidl_api/android.hardware.power.stats/1/android/hardware/power/stats/EnergyConsumerType.aidl b/power/stats/aidl/aidl_api/android.hardware.power.stats/1/android/hardware/power/stats/EnergyConsumerType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..fbd31970b68db0cd8010354147d22234d0b59521 --- /dev/null +++ b/power/stats/aidl/aidl_api/android.hardware.power.stats/1/android/hardware/power/stats/EnergyConsumerType.aidl @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.power.stats; +@VintfStability +enum EnergyConsumerType { + OTHER = 0, + BLUETOOTH = 1, + CPU_CLUSTER = 2, + DISPLAY = 3, + GNSS = 4, + MOBILE_RADIO = 5, + WIFI = 6, +} diff --git a/power/stats/aidl/aidl_api/android.hardware.power.stats/1/android/hardware/power/stats/EnergyMeasurement.aidl b/power/stats/aidl/aidl_api/android.hardware.power.stats/1/android/hardware/power/stats/EnergyMeasurement.aidl new file mode 100644 index 0000000000000000000000000000000000000000..ffe3aa48c5592288d65827536e6132d62f5dedb0 --- /dev/null +++ b/power/stats/aidl/aidl_api/android.hardware.power.stats/1/android/hardware/power/stats/EnergyMeasurement.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.power.stats; +@VintfStability +parcelable EnergyMeasurement { + int id; + long timestampMs; + long durationMs; + long energyUWs; +} diff --git a/power/stats/aidl/aidl_api/android.hardware.power.stats/1/android/hardware/power/stats/IPowerStats.aidl b/power/stats/aidl/aidl_api/android.hardware.power.stats/1/android/hardware/power/stats/IPowerStats.aidl new file mode 100644 index 0000000000000000000000000000000000000000..79175158e482211950ad99a14fc7ea783574c915 --- /dev/null +++ b/power/stats/aidl/aidl_api/android.hardware.power.stats/1/android/hardware/power/stats/IPowerStats.aidl @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.power.stats; +@VintfStability +interface IPowerStats { + android.hardware.power.stats.PowerEntity[] getPowerEntityInfo(); + android.hardware.power.stats.StateResidencyResult[] getStateResidency(in int[] powerEntityIds); + android.hardware.power.stats.EnergyConsumer[] getEnergyConsumerInfo(); + android.hardware.power.stats.EnergyConsumerResult[] getEnergyConsumed(in int[] energyConsumerIds); + android.hardware.power.stats.Channel[] getEnergyMeterInfo(); + android.hardware.power.stats.EnergyMeasurement[] readEnergyMeter(in int[] channelIds); +} diff --git a/power/stats/aidl/aidl_api/android.hardware.power.stats/1/android/hardware/power/stats/PowerEntity.aidl b/power/stats/aidl/aidl_api/android.hardware.power.stats/1/android/hardware/power/stats/PowerEntity.aidl new file mode 100644 index 0000000000000000000000000000000000000000..f42e715cfd6501f5c2ef19f2c9dc61120f0faee0 --- /dev/null +++ b/power/stats/aidl/aidl_api/android.hardware.power.stats/1/android/hardware/power/stats/PowerEntity.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.power.stats; +@VintfStability +parcelable PowerEntity { + int id; + @utf8InCpp String name; + android.hardware.power.stats.State[] states; +} diff --git a/power/stats/aidl/aidl_api/android.hardware.power.stats/1/android/hardware/power/stats/State.aidl b/power/stats/aidl/aidl_api/android.hardware.power.stats/1/android/hardware/power/stats/State.aidl new file mode 100644 index 0000000000000000000000000000000000000000..cf29dd714f07ddc1144b4deb9c81680bd9da95a5 --- /dev/null +++ b/power/stats/aidl/aidl_api/android.hardware.power.stats/1/android/hardware/power/stats/State.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.power.stats; +@VintfStability +parcelable State { + int id; + @utf8InCpp String name; +} diff --git a/power/stats/aidl/aidl_api/android.hardware.power.stats/1/android/hardware/power/stats/StateResidency.aidl b/power/stats/aidl/aidl_api/android.hardware.power.stats/1/android/hardware/power/stats/StateResidency.aidl new file mode 100644 index 0000000000000000000000000000000000000000..0af35b391ca0ceb6ec79625469f999462561f37c --- /dev/null +++ b/power/stats/aidl/aidl_api/android.hardware.power.stats/1/android/hardware/power/stats/StateResidency.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.power.stats; +@VintfStability +parcelable StateResidency { + int id; + long totalTimeInStateMs; + long totalStateEntryCount; + long lastEntryTimestampMs; +} diff --git a/power/stats/aidl/aidl_api/android.hardware.power.stats/1/android/hardware/power/stats/StateResidencyResult.aidl b/power/stats/aidl/aidl_api/android.hardware.power.stats/1/android/hardware/power/stats/StateResidencyResult.aidl new file mode 100644 index 0000000000000000000000000000000000000000..14358b7fed5d8f1a9444a3d44e1fc6890f10d50b --- /dev/null +++ b/power/stats/aidl/aidl_api/android.hardware.power.stats/1/android/hardware/power/stats/StateResidencyResult.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.power.stats; +@VintfStability +parcelable StateResidencyResult { + int id; + android.hardware.power.stats.StateResidency[] stateResidencyData; +} diff --git a/radio/1.0/vts/functional/sap_hidl_hal_api.cpp b/radio/1.0/vts/functional/sap_hidl_hal_api.cpp index 6c7870d39949681b10f7ce8c39b2e3984439ad00..5359a87badecaea32e0f2edf15397478b426fa73 100644 --- a/radio/1.0/vts/functional/sap_hidl_hal_api.cpp +++ b/radio/1.0/vts/functional/sap_hidl_hal_api.cpp @@ -61,10 +61,11 @@ TEST_P(SapHidlTest, apduReq) { EXPECT_EQ(std::cv_status::no_timeout, wait()); EXPECT_EQ(sapCb->sapResponseToken, token); - ASSERT_TRUE( - CheckAnyOfErrors(sapCb->sapResultCode, - {SapResultCode::GENERIC_FAILURE, SapResultCode::CARD_ALREADY_POWERED_OFF, - SapResultCode::CARD_NOT_ACCESSSIBLE, SapResultCode::CARD_REMOVED})); + ASSERT_TRUE(CheckAnyOfErrors( + sapCb->sapResultCode, + {SapResultCode::GENERIC_FAILURE, SapResultCode::CARD_ALREADY_POWERED_OFF, + SapResultCode::CARD_NOT_ACCESSSIBLE, SapResultCode::CARD_REMOVED, + SapResultCode::SUCCESS})); LOG(DEBUG) << "apduReq finished"; } @@ -79,10 +80,10 @@ TEST_P(SapHidlTest, transferAtrReq) { EXPECT_EQ(std::cv_status::no_timeout, wait()); EXPECT_EQ(sapCb->sapResponseToken, token); - ASSERT_TRUE( - CheckAnyOfErrors(sapCb->sapResultCode, - {SapResultCode::GENERIC_FAILURE, SapResultCode::DATA_NOT_AVAILABLE, - SapResultCode::CARD_ALREADY_POWERED_OFF, SapResultCode::CARD_REMOVED})); + ASSERT_TRUE(CheckAnyOfErrors(sapCb->sapResultCode, + {SapResultCode::GENERIC_FAILURE, SapResultCode::DATA_NOT_AVAILABLE, + SapResultCode::CARD_ALREADY_POWERED_OFF, + SapResultCode::CARD_REMOVED, SapResultCode::SUCCESS})); LOG(DEBUG) << "transferAtrReq finished"; } @@ -98,10 +99,11 @@ TEST_P(SapHidlTest, powerReq) { EXPECT_EQ(std::cv_status::no_timeout, wait()); EXPECT_EQ(sapCb->sapResponseToken, token); - ASSERT_TRUE(CheckAnyOfErrors( - sapCb->sapResultCode, {SapResultCode::GENERIC_FAILURE, SapResultCode::CARD_NOT_ACCESSSIBLE, - SapResultCode::CARD_ALREADY_POWERED_OFF, SapResultCode::CARD_REMOVED, - SapResultCode::CARD_ALREADY_POWERED_ON})); + ASSERT_TRUE( + CheckAnyOfErrors(sapCb->sapResultCode, + {SapResultCode::GENERIC_FAILURE, SapResultCode::CARD_NOT_ACCESSSIBLE, + SapResultCode::CARD_ALREADY_POWERED_OFF, SapResultCode::CARD_REMOVED, + SapResultCode::CARD_ALREADY_POWERED_ON, SapResultCode::SUCCESS})); LOG(DEBUG) << "powerReq finished"; } @@ -117,9 +119,10 @@ TEST_P(SapHidlTest, resetSimReq) { EXPECT_EQ(sapCb->sapResponseToken, token); ASSERT_TRUE( - CheckAnyOfErrors(sapCb->sapResultCode, - {SapResultCode::GENERIC_FAILURE, SapResultCode::CARD_NOT_ACCESSSIBLE, - SapResultCode::CARD_ALREADY_POWERED_OFF, SapResultCode::CARD_REMOVED})); + CheckAnyOfErrors(sapCb->sapResultCode, + {SapResultCode::GENERIC_FAILURE, SapResultCode::CARD_NOT_ACCESSSIBLE, + SapResultCode::CARD_ALREADY_POWERED_OFF, SapResultCode::CARD_REMOVED, + SapResultCode::SUCCESS})); LOG(DEBUG) << "resetSimReq finished"; } @@ -134,8 +137,9 @@ TEST_P(SapHidlTest, transferCardReaderStatusReq) { EXPECT_EQ(std::cv_status::no_timeout, wait()); EXPECT_EQ(sapCb->sapResponseToken, token); - ASSERT_TRUE(CheckAnyOfErrors( - sapCb->sapResultCode, {SapResultCode::GENERIC_FAILURE, SapResultCode::DATA_NOT_AVAILABLE})); + ASSERT_TRUE(CheckAnyOfErrors(sapCb->sapResultCode, + {SapResultCode::GENERIC_FAILURE, SapResultCode::DATA_NOT_AVAILABLE, + SapResultCode::SUCCESS})); LOG(DEBUG) << "transferCardReaderStatusReq finished"; } @@ -151,6 +155,7 @@ TEST_P(SapHidlTest, setTransferProtocolReq) { EXPECT_EQ(std::cv_status::no_timeout, wait()); EXPECT_EQ(sapCb->sapResponseToken, token); - EXPECT_EQ(SapResultCode::NOT_SUPPORTED, sapCb->sapResultCode); + ASSERT_TRUE(CheckAnyOfErrors(sapCb->sapResultCode, + {SapResultCode::NOT_SUPPORTED, SapResultCode::SUCCESS})); LOG(DEBUG) << "setTransferProtocolReq finished"; } diff --git a/radio/1.6/IRadioResponse.hal b/radio/1.6/IRadioResponse.hal index a1286a5f95b54065eea5d921d5486b12c961a9e1..3ee46c2a3868e9e109a5a50f3f5cfa9114380695 100644 --- a/radio/1.6/IRadioResponse.hal +++ b/radio/1.6/IRadioResponse.hal @@ -435,6 +435,7 @@ interface IRadioResponse extends @1.5::IRadioResponse { * RadioError:RADIO_NOT_AVAILABLE * RadioError:INTERNAL_ERR * RadioError:MODEM_ERR + * RadioError:REQUEST_NOT_SUPPORTED */ oneway getSlicingConfigResponse(RadioResponseInfo info, SlicingConfig slicingConfig); diff --git a/radio/1.6/types.hal b/radio/1.6/types.hal index d026589da0fd345ef8a513525a00014c8c63994a..1b697a95c7b7e65abe3c8b6dee1d1d0d0ccda188 100644 --- a/radio/1.6/types.hal +++ b/radio/1.6/types.hal @@ -765,73 +765,6 @@ struct Call { string forwardedNumber; }; -struct PhysicalChannelConfig { - /** Connection status for cell. Valid values are PRIMARY_SERVING and SECONDARY_SERVING */ - CellConnectionStatus status; - - /** The radio technology for this physical channel */ - RadioTechnology rat; - - /** Downlink Absolute Radio Frequency Channel Number */ - int32_t downlinkChannelNumber; - - /** Uplink Absolute Radio Frequency Channel Number */ - int32_t uplinkChannelNumber; - - /** Downlink cell bandwidth, in kHz */ - int32_t cellBandwidthDownlinkKhz; - - /** Uplink cell bandwidth, in kHz */ - int32_t cellBandwidthUplinkKhz; - - /** - * A list of data calls mapped to this physical channel. The context id must match the cid of - * @1.5::SetupDataCallResult. An empty list means the physical channel has no data call mapped - * to it. - */ - vec contextIds; - - /** - * The physical cell identifier for this cell. - * - * In UTRAN, this value is primary scrambling code. The range is [0, 511]. - * Reference: 3GPP TS 25.213 section 5.2.2. - * - * In EUTRAN, this value is physical layer cell identity. The range is [0, 503]. - * Reference: 3GPP TS 36.211 section 6.11. - * - * In 5G RAN, this value is physical layer cell identity. The range is [0, 1007]. - * Reference: 3GPP TS 38.211 section 7.4.2.1. - */ - uint32_t physicalCellId; - - /** - * The frequency band to scan. - */ - safe_union Band { - /** Valid only if radioAccessNetwork = GERAN. */ - GeranBands geranBand; - /** Valid only if radioAccessNetwork = UTRAN. */ - UtranBands utranBand; - /** Valid only if radioAccessNetwork = EUTRAN. */ - EutranBands eutranBand; - /** Valid only if radioAccessNetwork = NGRAN. */ - NgranBands ngranBand; - } band; -}; - -/** - * Extended from @1.5 NgranBands - * IRadio 1.6 supports NGRAN bands up to V16.5.0 - */ -enum NgranBands : @1.5::NgranBands { - /** 3GPP TS 38.101-1, Table 5.2-1: FR1 bands */ - BAND_26 = 26, - BAND_46 = 46, - BAND_53 = 53, - BAND_96 = 96, -}; - /** * This safe_union represents an optional slice info */ @@ -924,6 +857,73 @@ enum DataCallFailCause : @1.4::DataCallFailCause { ALL_MATCHING_RULES_FAILED = 0x8CE, }; +struct PhysicalChannelConfig { + /** Connection status for cell. Valid values are PRIMARY_SERVING and SECONDARY_SERVING */ + CellConnectionStatus status; + + /** The radio technology for this physical channel */ + RadioTechnology rat; + + /** Downlink Absolute Radio Frequency Channel Number */ + int32_t downlinkChannelNumber; + + /** Uplink Absolute Radio Frequency Channel Number */ + int32_t uplinkChannelNumber; + + /** Downlink cell bandwidth, in kHz */ + int32_t cellBandwidthDownlinkKhz; + + /** Uplink cell bandwidth, in kHz */ + int32_t cellBandwidthUplinkKhz; + + /** + * A list of data calls mapped to this physical channel. The context id must match the cid of + * @1.5::SetupDataCallResult. An empty list means the physical channel has no data call mapped + * to it. + */ + vec contextIds; + + /** + * The physical cell identifier for this cell. + * + * In UTRAN, this value is primary scrambling code. The range is [0, 511]. + * Reference: 3GPP TS 25.213 section 5.2.2. + * + * In EUTRAN, this value is physical layer cell identity. The range is [0, 503]. + * Reference: 3GPP TS 36.211 section 6.11. + * + * In 5G RAN, this value is physical layer cell identity. The range is [0, 1007]. + * Reference: 3GPP TS 38.211 section 7.4.2.1. + */ + uint32_t physicalCellId; + + /** + * The frequency band to scan. + */ + safe_union Band { + /** Valid only if radioAccessNetwork = GERAN. */ + GeranBands geranBand; + /** Valid only if radioAccessNetwork = UTRAN. */ + UtranBands utranBand; + /** Valid only if radioAccessNetwork = EUTRAN. */ + EutranBands eutranBand; + /** Valid only if radioAccessNetwork = NGRAN. */ + NgranBands ngranBand; + } band; +}; + +/** + * Extended from @1.5 NgranBands + * IRadio 1.6 supports NGRAN bands up to V16.5.0 + */ +enum NgranBands : @1.5::NgranBands { + /** 3GPP TS 38.101-1, Table 5.2-1: FR1 bands */ + BAND_26 = 26, + BAND_46 = 46, + BAND_53 = 53, + BAND_96 = 96, +}; + /** * This safe_union represents an optional DNN. DNN stands for Data Network Name * and represents an APN as defined in 3GPP TS 23.003. diff --git a/radio/1.6/vts/functional/radio_hidl_hal_api.cpp b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp index cd195200ff9535c7af547701688f9d063e563c31..e07d2bacd4c710e748af8c29544416e17a1cc5ca 100644 --- a/radio/1.6/vts/functional/radio_hidl_hal_api.cpp +++ b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp @@ -234,6 +234,9 @@ TEST_P(RadioHidlTest_v1_6, setupDataCall_1_6_osAppId) { {::android::hardware::radio::V1_6::RadioError::NONE, ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE, ::android::hardware::radio::V1_6::RadioError::OP_NOT_ALLOWED_BEFORE_REG_TO_NW})); + if (radioRsp_v1_6->setupDataCallResult.trafficDescriptors.size() <= 0) { + return; + } EXPECT_EQ(optionalTrafficDescriptor.value().osAppId.value().osAppId, radioRsp_v1_6->setupDataCallResult.trafficDescriptors[0].osAppId.value().osAppId); } @@ -248,7 +251,18 @@ TEST_P(RadioHidlTest_v1_6, getSlicingConfig) { EXPECT_EQ(std::cv_status::no_timeout, wait()); EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type); EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial); - EXPECT_EQ(::android::hardware::radio::V1_6::RadioError::NONE, radioRsp_v1_6->rspInfo.error); + if (getRadioHalCapabilities()) { + ASSERT_TRUE(CheckAnyOfErrors( + radioRsp_v1_6->rspInfo.error, + {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED})); + } else { + ASSERT_TRUE( + CheckAnyOfErrors(radioRsp_v1_6->rspInfo.error, + {::android::hardware::radio::V1_6::RadioError::NONE, + ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE, + ::android::hardware::radio::V1_6::RadioError::INTERNAL_ERR, + ::android::hardware::radio::V1_6::RadioError::MODEM_ERR})); + } } /* @@ -831,7 +845,7 @@ TEST_P(RadioHidlTest_v1_6, setCarrierInfoForImsiEncryption_1_6) { /* * Test IRadio.getSimPhonebookRecords() for the response returned. */ -TEST_F(RadioHidlTest_v1_6, getSimPhonebookRecords) { +TEST_P(RadioHidlTest_v1_6, getSimPhonebookRecords) { serial = GetRandomSerialNumber(); radio_v1_6->getSimPhonebookRecords(serial); EXPECT_EQ(std::cv_status::no_timeout, wait()); diff --git a/radio/config/1.3/types.hal b/radio/config/1.3/types.hal deleted file mode 100644 index 2b6c9f06c7d7b9db2702205f93c65bf4a1c1e96d..0000000000000000000000000000000000000000 --- a/radio/config/1.3/types.hal +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.hardware.radio.config@1.3; - -/** - * Contains the device capabilities with respect to the Radio HAL. - */ -struct HalDeviceCapabilities { - /** - * True indicates that the modem does NOT support the following features: - *

    - *
  • Providing either - * android.hardware.radio@1.6::LinkCapacityEstimate:secondaryDownlinkCapacityKbps - * or android.hardware.radio@1.6::LinkCapacityEstimate:secondaryUplinkCapacityKbps - * when given from android.hardware.radio@1.6::RadioIndication:currentLinkCapacityEstimate - *
  • - *
  • calling android.hardware.radio@1.6::IRadio.setNrDualConnectivityState - * or querying android.hardware.radio@1.6::IRadio.isNrDualConnectivityEnabled - *
  • - *
  • Requesting android.hardware.radio@1.6::IRadio.setDataThrottling() - *
  • - *
- */ - bool modemReducedFeatureSet1; -}; diff --git a/radio/config/1.3/vts/functional/radio_config_hidl_hal_utils.h b/radio/config/1.3/vts/functional/radio_config_hidl_hal_utils.h index 744005454645639742f0c396dfe076b5ff7c628e..7235798f436a1410f3a9766c540f58790ecbd5f9 100644 --- a/radio/config/1.3/vts/functional/radio_config_hidl_hal_utils.h +++ b/radio/config/1.3/vts/functional/radio_config_hidl_hal_utils.h @@ -36,7 +36,7 @@ #include "vts_test_util.h" -using namespace ::android::hardware::radio::config::V1_2; +using namespace ::android::hardware::radio::config::V1_3; using ::android::sp; using ::android::hardware::hidl_string; @@ -45,8 +45,10 @@ using ::android::hardware::Return; using ::android::hardware::Void; using ::android::hardware::radio::config::V1_1::ModemsConfig; using ::android::hardware::radio::config::V1_1::PhoneCapability; +using ::android::hardware::radio::config::V1_2::IRadioConfigIndication; using ::android::hardware::radio::config::V1_2::SimSlotStatus; using ::android::hardware::radio::config::V1_3::IRadioConfig; +using ::android::hardware::radio::config::V1_3::IRadioConfigResponse; using ::android::hardware::radio::V1_0::RadioResponseInfo; #define RADIO_SERVICE_NAME "slot1" diff --git a/radio/config/1.3/vts/functional/radio_config_response.cpp b/radio/config/1.3/vts/functional/radio_config_response.cpp index 6b2d27c64e999c4d8034de25bc07be8d9cadb8c7..6188733f660e8c5a36c535866379864033c3fe28 100644 --- a/radio/config/1.3/vts/functional/radio_config_response.cpp +++ b/radio/config/1.3/vts/functional/radio_config_response.cpp @@ -64,8 +64,9 @@ Return RadioConfigResponse::setModemsConfigResponse( } Return RadioConfigResponse::getHalDeviceCapabilitiesResponse( - const ::android::hardware::radio::V1_6::RadioResponseInfo& /* info */, + const ::android::hardware::radio::V1_6::RadioResponseInfo& info, bool modemReducedFeatures) { modemReducedFeatureSet1 = modemReducedFeatures; + parent.notify(info.serial); return Void(); } diff --git a/rebootescrow/aidl/vts/functional/VtsHalRebootEscrowTargetTest.cpp b/rebootescrow/aidl/vts/functional/VtsHalRebootEscrowTargetTest.cpp index 809a3b502ac95eac8d6077781e803c26e8bad94a..28357a1a1ea82b528bec42d9f289889baf91b98f 100644 --- a/rebootescrow/aidl/vts/functional/VtsHalRebootEscrowTargetTest.cpp +++ b/rebootescrow/aidl/vts/functional/VtsHalRebootEscrowTargetTest.cpp @@ -123,6 +123,7 @@ TEST_P(RebootEscrowAidlTest, Store_Success) { rebootescrow->storeKey(KEY_1); } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RebootEscrowAidlTest); INSTANTIATE_TEST_SUITE_P( RebootEscrow, RebootEscrowAidlTest, testing::ValuesIn(android::getAidlHalInstanceNames(IRebootEscrow::descriptor)), diff --git a/security/keymint/aidl/Android.bp b/security/keymint/aidl/Android.bp index 4bbfb35860955af095b17881cdd50f74446a5d16..028d297f0d924d7b0a65e6b95a9eaf4acc80c2c9 100644 --- a/security/keymint/aidl/Android.bp +++ b/security/keymint/aidl/Android.bp @@ -36,4 +36,5 @@ aidl_interface { ], }, }, + versions: ["1"], } diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/.hash b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/.hash new file mode 100644 index 0000000000000000000000000000000000000000..b712a5231b1269b41e086b1fc26620a4af469add --- /dev/null +++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/.hash @@ -0,0 +1 @@ +976674616001f714f4a4df49ee45f548de828524 diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/Algorithm.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/Algorithm.aidl new file mode 100644 index 0000000000000000000000000000000000000000..6da124f6016053d934c544550dbaa517d4e9b858 --- /dev/null +++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/Algorithm.aidl @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.keymint; +/* @hide */ +@Backing(type="int") @VintfStability +enum Algorithm { + RSA = 1, + EC = 3, + AES = 32, + TRIPLE_DES = 33, + HMAC = 128, +} diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/AttestationKey.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/AttestationKey.aidl new file mode 100644 index 0000000000000000000000000000000000000000..90f2e6ee5474d997c9302215c9cd4a25c7edb733 --- /dev/null +++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/AttestationKey.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.keymint; +/* @hide */ +@RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability +parcelable AttestationKey { + byte[] keyBlob; + android.hardware.security.keymint.KeyParameter[] attestKeyParams; + byte[] issuerSubjectName; +} diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/BeginResult.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/BeginResult.aidl new file mode 100644 index 0000000000000000000000000000000000000000..c952a3152a376bbecbe40c54e58ffa5c48d7664b --- /dev/null +++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/BeginResult.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.keymint; +/* @hide */ +@VintfStability +parcelable BeginResult { + long challenge; + android.hardware.security.keymint.KeyParameter[] params; + android.hardware.security.keymint.IKeyMintOperation operation; +} diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/BlockMode.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/BlockMode.aidl new file mode 100644 index 0000000000000000000000000000000000000000..004988326b4c19c32f3bc89e2b073fcd73e5d0b5 --- /dev/null +++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/BlockMode.aidl @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.keymint; +/* @hide */ +@Backing(type="int") @VintfStability +enum BlockMode { + ECB = 1, + CBC = 2, + CTR = 3, + GCM = 32, +} diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/Certificate.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/Certificate.aidl new file mode 100644 index 0000000000000000000000000000000000000000..645f0a72ee62bbb051260f37162d452ea7c75fd1 --- /dev/null +++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/Certificate.aidl @@ -0,0 +1,39 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.keymint; +/* @hide */ +@VintfStability +parcelable Certificate { + byte[] encodedCertificate; +} diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/DeviceInfo.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/DeviceInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..d04d49cea83d17bcf077b49a3f818b7acf6f9fcb --- /dev/null +++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/DeviceInfo.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.keymint; +/* @hide */ +@VintfStability +parcelable DeviceInfo { + byte[] deviceInfo; +} diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/Digest.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/Digest.aidl new file mode 100644 index 0000000000000000000000000000000000000000..0df709609f3778ab2818368385d3a50a9487e52f --- /dev/null +++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/Digest.aidl @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.keymint; +/* @hide */ +@Backing(type="int") @VintfStability +enum Digest { + NONE = 0, + MD5 = 1, + SHA1 = 2, + SHA_2_224 = 3, + SHA_2_256 = 4, + SHA_2_384 = 5, + SHA_2_512 = 6, +} diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/EcCurve.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/EcCurve.aidl new file mode 100644 index 0000000000000000000000000000000000000000..6b4a9aefb22e40a883af88b017f61c8cdc910e9e --- /dev/null +++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/EcCurve.aidl @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.keymint; +/* @hide */ +@Backing(type="int") @VintfStability +enum EcCurve { + P_224 = 0, + P_256 = 1, + P_384 = 2, + P_521 = 3, +} diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/ErrorCode.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/ErrorCode.aidl new file mode 100644 index 0000000000000000000000000000000000000000..b05a0f3d8352b4aa3cc8f4714bbd18adf3841035 --- /dev/null +++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/ErrorCode.aidl @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.keymint; +/* @hide */ +@Backing(type="int") @VintfStability +enum ErrorCode { + OK = 0, + ROOT_OF_TRUST_ALREADY_SET = -1, + UNSUPPORTED_PURPOSE = -2, + INCOMPATIBLE_PURPOSE = -3, + UNSUPPORTED_ALGORITHM = -4, + INCOMPATIBLE_ALGORITHM = -5, + UNSUPPORTED_KEY_SIZE = -6, + UNSUPPORTED_BLOCK_MODE = -7, + INCOMPATIBLE_BLOCK_MODE = -8, + UNSUPPORTED_MAC_LENGTH = -9, + UNSUPPORTED_PADDING_MODE = -10, + INCOMPATIBLE_PADDING_MODE = -11, + UNSUPPORTED_DIGEST = -12, + INCOMPATIBLE_DIGEST = -13, + INVALID_EXPIRATION_TIME = -14, + INVALID_USER_ID = -15, + INVALID_AUTHORIZATION_TIMEOUT = -16, + UNSUPPORTED_KEY_FORMAT = -17, + INCOMPATIBLE_KEY_FORMAT = -18, + UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM = -19, + UNSUPPORTED_KEY_VERIFICATION_ALGORITHM = -20, + INVALID_INPUT_LENGTH = -21, + KEY_EXPORT_OPTIONS_INVALID = -22, + DELEGATION_NOT_ALLOWED = -23, + KEY_NOT_YET_VALID = -24, + KEY_EXPIRED = -25, + KEY_USER_NOT_AUTHENTICATED = -26, + OUTPUT_PARAMETER_NULL = -27, + INVALID_OPERATION_HANDLE = -28, + INSUFFICIENT_BUFFER_SPACE = -29, + VERIFICATION_FAILED = -30, + TOO_MANY_OPERATIONS = -31, + UNEXPECTED_NULL_POINTER = -32, + INVALID_KEY_BLOB = -33, + IMPORTED_KEY_NOT_ENCRYPTED = -34, + IMPORTED_KEY_DECRYPTION_FAILED = -35, + IMPORTED_KEY_NOT_SIGNED = -36, + IMPORTED_KEY_VERIFICATION_FAILED = -37, + INVALID_ARGUMENT = -38, + UNSUPPORTED_TAG = -39, + INVALID_TAG = -40, + MEMORY_ALLOCATION_FAILED = -41, + IMPORT_PARAMETER_MISMATCH = -44, + SECURE_HW_ACCESS_DENIED = -45, + OPERATION_CANCELLED = -46, + CONCURRENT_ACCESS_CONFLICT = -47, + SECURE_HW_BUSY = -48, + SECURE_HW_COMMUNICATION_FAILED = -49, + UNSUPPORTED_EC_FIELD = -50, + MISSING_NONCE = -51, + INVALID_NONCE = -52, + MISSING_MAC_LENGTH = -53, + KEY_RATE_LIMIT_EXCEEDED = -54, + CALLER_NONCE_PROHIBITED = -55, + KEY_MAX_OPS_EXCEEDED = -56, + INVALID_MAC_LENGTH = -57, + MISSING_MIN_MAC_LENGTH = -58, + UNSUPPORTED_MIN_MAC_LENGTH = -59, + UNSUPPORTED_KDF = -60, + UNSUPPORTED_EC_CURVE = -61, + KEY_REQUIRES_UPGRADE = -62, + ATTESTATION_CHALLENGE_MISSING = -63, + KEYMINT_NOT_CONFIGURED = -64, + ATTESTATION_APPLICATION_ID_MISSING = -65, + CANNOT_ATTEST_IDS = -66, + ROLLBACK_RESISTANCE_UNAVAILABLE = -67, + HARDWARE_TYPE_UNAVAILABLE = -68, + PROOF_OF_PRESENCE_REQUIRED = -69, + CONCURRENT_PROOF_OF_PRESENCE_REQUESTED = -70, + NO_USER_CONFIRMATION = -71, + DEVICE_LOCKED = -72, + EARLY_BOOT_ENDED = -73, + ATTESTATION_KEYS_NOT_PROVISIONED = -74, + ATTESTATION_IDS_NOT_PROVISIONED = -75, + INVALID_OPERATION = -76, + STORAGE_KEY_UNSUPPORTED = -77, + INCOMPATIBLE_MGF_DIGEST = -78, + UNSUPPORTED_MGF_DIGEST = -79, + MISSING_NOT_BEFORE = -80, + MISSING_NOT_AFTER = -81, + MISSING_ISSUER_SUBJECT = -82, + INVALID_ISSUER_SUBJECT = -83, + BOOT_LEVEL_EXCEEDED = -84, + HARDWARE_NOT_YET_AVAILABLE = -85, + UNIMPLEMENTED = -100, + VERSION_MISMATCH = -101, + UNKNOWN_ERROR = -1000, +} diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/HardwareAuthToken.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/HardwareAuthToken.aidl new file mode 100644 index 0000000000000000000000000000000000000000..2e07924382f5045adcf1229ab5789f73abff1ef9 --- /dev/null +++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/HardwareAuthToken.aidl @@ -0,0 +1,44 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.keymint; +/* @hide */ +@RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability +parcelable HardwareAuthToken { + long challenge; + long userId; + long authenticatorId; + android.hardware.security.keymint.HardwareAuthenticatorType authenticatorType = android.hardware.security.keymint.HardwareAuthenticatorType.NONE; + android.hardware.security.secureclock.Timestamp timestamp; + byte[] mac; +} diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/HardwareAuthenticatorType.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/HardwareAuthenticatorType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..dfc98f0066808308ea9a52a2e915c9419dc9dcdf --- /dev/null +++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/HardwareAuthenticatorType.aidl @@ -0,0 +1,42 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.keymint; +/* @hide */ +@Backing(type="int") @VintfStability +enum HardwareAuthenticatorType { + NONE = 0, + PASSWORD = 1, + FINGERPRINT = 2, + ANY = -1, +} diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/IKeyMintDevice.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/IKeyMintDevice.aidl new file mode 100644 index 0000000000000000000000000000000000000000..fa643fc49431b1054968f8101a26ce5538f89852 --- /dev/null +++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/IKeyMintDevice.aidl @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.keymint; +/* @hide */ +@SensitiveData @VintfStability +interface IKeyMintDevice { + android.hardware.security.keymint.KeyMintHardwareInfo getHardwareInfo(); + void addRngEntropy(in byte[] data); + android.hardware.security.keymint.KeyCreationResult generateKey(in android.hardware.security.keymint.KeyParameter[] keyParams, in @nullable android.hardware.security.keymint.AttestationKey attestationKey); + android.hardware.security.keymint.KeyCreationResult importKey(in android.hardware.security.keymint.KeyParameter[] keyParams, in android.hardware.security.keymint.KeyFormat keyFormat, in byte[] keyData, in @nullable android.hardware.security.keymint.AttestationKey attestationKey); + android.hardware.security.keymint.KeyCreationResult importWrappedKey(in byte[] wrappedKeyData, in byte[] wrappingKeyBlob, in byte[] maskingKey, in android.hardware.security.keymint.KeyParameter[] unwrappingParams, in long passwordSid, in long biometricSid); + byte[] upgradeKey(in byte[] keyBlobToUpgrade, in android.hardware.security.keymint.KeyParameter[] upgradeParams); + void deleteKey(in byte[] keyBlob); + void deleteAllKeys(); + void destroyAttestationIds(); + android.hardware.security.keymint.BeginResult begin(in android.hardware.security.keymint.KeyPurpose purpose, in byte[] keyBlob, in android.hardware.security.keymint.KeyParameter[] params, in @nullable android.hardware.security.keymint.HardwareAuthToken authToken); + void deviceLocked(in boolean passwordOnly, in @nullable android.hardware.security.secureclock.TimeStampToken timestampToken); + void earlyBootEnded(); + byte[] convertStorageKeyToEphemeral(in byte[] storageKeyBlob); + android.hardware.security.keymint.KeyCharacteristics[] getKeyCharacteristics(in byte[] keyBlob, in byte[] appId, in byte[] appData); + const int AUTH_TOKEN_MAC_LENGTH = 32; +} diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/IKeyMintOperation.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/IKeyMintOperation.aidl new file mode 100644 index 0000000000000000000000000000000000000000..4ab4ffed1162d79ed0ee2b1a6a3be484973496be --- /dev/null +++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/IKeyMintOperation.aidl @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.keymint; +/* @hide */ +@SensitiveData @VintfStability +interface IKeyMintOperation { + void updateAad(in byte[] input, in @nullable android.hardware.security.keymint.HardwareAuthToken authToken, in @nullable android.hardware.security.secureclock.TimeStampToken timeStampToken); + byte[] update(in byte[] input, in @nullable android.hardware.security.keymint.HardwareAuthToken authToken, in @nullable android.hardware.security.secureclock.TimeStampToken timeStampToken); + byte[] finish(in @nullable byte[] input, in @nullable byte[] signature, in @nullable android.hardware.security.keymint.HardwareAuthToken authToken, in @nullable android.hardware.security.secureclock.TimeStampToken timestampToken, in @nullable byte[] confirmationToken); + void abort(); +} diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl new file mode 100644 index 0000000000000000000000000000000000000000..f56646227b9915b8f39956a66a6f3c138aafe30f --- /dev/null +++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.keymint; +/* @hide */ +@VintfStability +interface IRemotelyProvisionedComponent { + android.hardware.security.keymint.RpcHardwareInfo getHardwareInfo(); + byte[] generateEcdsaP256KeyPair(in boolean testMode, out android.hardware.security.keymint.MacedPublicKey macedPublicKey); + byte[] generateCertificateRequest(in boolean testMode, in android.hardware.security.keymint.MacedPublicKey[] keysToSign, in byte[] endpointEncryptionCertChain, in byte[] challenge, out android.hardware.security.keymint.DeviceInfo deviceInfo, out android.hardware.security.keymint.ProtectedData protectedData); + const int STATUS_FAILED = 1; + const int STATUS_INVALID_MAC = 2; + const int STATUS_PRODUCTION_KEY_IN_TEST_REQUEST = 3; + const int STATUS_TEST_KEY_IN_PRODUCTION_REQUEST = 4; + const int STATUS_INVALID_EEK = 5; +} diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/KeyCharacteristics.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/KeyCharacteristics.aidl new file mode 100644 index 0000000000000000000000000000000000000000..008381f2828f650eb6cf132c597d3585519b8aae --- /dev/null +++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/KeyCharacteristics.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.keymint; +/* @hide */ +@VintfStability +parcelable KeyCharacteristics { + android.hardware.security.keymint.SecurityLevel securityLevel = android.hardware.security.keymint.SecurityLevel.SOFTWARE; + android.hardware.security.keymint.KeyParameter[] authorizations; +} diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/KeyCreationResult.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/KeyCreationResult.aidl new file mode 100644 index 0000000000000000000000000000000000000000..9f77d3e3d55dcec73c1e02d0a1cb5a37b05e63c5 --- /dev/null +++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/KeyCreationResult.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.keymint; +/* @hide */ +@VintfStability +parcelable KeyCreationResult { + byte[] keyBlob; + android.hardware.security.keymint.KeyCharacteristics[] keyCharacteristics; + android.hardware.security.keymint.Certificate[] certificateChain; +} diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/KeyFormat.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/KeyFormat.aidl new file mode 100644 index 0000000000000000000000000000000000000000..9560d8d2b5303dc4949dbd34aa17b60e3fcba31f --- /dev/null +++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/KeyFormat.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.keymint; +/* @hide */ +@Backing(type="int") @VintfStability +enum KeyFormat { + X509 = 0, + PKCS8 = 1, + RAW = 3, +} diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/KeyMintHardwareInfo.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/KeyMintHardwareInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..2113e42a8ece6242b5cefc706ad420df53f80292 --- /dev/null +++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/KeyMintHardwareInfo.aidl @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.keymint; +/* @hide */ +@RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability +parcelable KeyMintHardwareInfo { + int versionNumber; + android.hardware.security.keymint.SecurityLevel securityLevel = android.hardware.security.keymint.SecurityLevel.SOFTWARE; + @utf8InCpp String keyMintName; + @utf8InCpp String keyMintAuthorName; + boolean timestampTokenRequired; +} diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/KeyOrigin.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/KeyOrigin.aidl new file mode 100644 index 0000000000000000000000000000000000000000..4b3c659ffe661cf74483342cc80b2e31792d8fc3 --- /dev/null +++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/KeyOrigin.aidl @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.keymint; +/* @hide */ +@Backing(type="int") @VintfStability +enum KeyOrigin { + GENERATED = 0, + DERIVED = 1, + IMPORTED = 2, + RESERVED = 3, + SECURELY_IMPORTED = 4, +} diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/KeyParameter.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/KeyParameter.aidl new file mode 100644 index 0000000000000000000000000000000000000000..c5a1e011d218f5a4fce6047e832901280cf79539 --- /dev/null +++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/KeyParameter.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.keymint; +/* @hide */ +@RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability +parcelable KeyParameter { + android.hardware.security.keymint.Tag tag = android.hardware.security.keymint.Tag.INVALID; + android.hardware.security.keymint.KeyParameterValue value; +} diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/KeyParameterValue.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/KeyParameterValue.aidl new file mode 100644 index 0000000000000000000000000000000000000000..7a0b074fe555683f84a334b03cba59413573f440 --- /dev/null +++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/KeyParameterValue.aidl @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.keymint; +/* @hide */ +@RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability +union KeyParameterValue { + int invalid; + android.hardware.security.keymint.Algorithm algorithm; + android.hardware.security.keymint.BlockMode blockMode; + android.hardware.security.keymint.PaddingMode paddingMode; + android.hardware.security.keymint.Digest digest; + android.hardware.security.keymint.EcCurve ecCurve; + android.hardware.security.keymint.KeyOrigin origin; + android.hardware.security.keymint.KeyPurpose keyPurpose; + android.hardware.security.keymint.HardwareAuthenticatorType hardwareAuthenticatorType; + android.hardware.security.keymint.SecurityLevel securityLevel; + boolean boolValue; + int integer; + long longInteger; + long dateTime; + byte[] blob; +} diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/KeyPurpose.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/KeyPurpose.aidl new file mode 100644 index 0000000000000000000000000000000000000000..b84bec1fc0b790c5811254265179eb18710cdc81 --- /dev/null +++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/KeyPurpose.aidl @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.keymint; +/* @hide */ +@Backing(type="int") @VintfStability +enum KeyPurpose { + ENCRYPT = 0, + DECRYPT = 1, + SIGN = 2, + VERIFY = 3, + WRAP_KEY = 5, + AGREE_KEY = 6, + ATTEST_KEY = 7, +} diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/MacedPublicKey.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/MacedPublicKey.aidl new file mode 100644 index 0000000000000000000000000000000000000000..8095e8ce0436344be4c0ef701a987de0b2cc695d --- /dev/null +++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/MacedPublicKey.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.keymint; +/* @hide */ +@VintfStability +parcelable MacedPublicKey { + byte[] macedKey; +} diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/PaddingMode.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/PaddingMode.aidl new file mode 100644 index 0000000000000000000000000000000000000000..dba4a8a06e2a902a64c854d960c421bab70d709f --- /dev/null +++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/PaddingMode.aidl @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.keymint; +/* @hide */ +@Backing(type="int") @VintfStability +enum PaddingMode { + NONE = 1, + RSA_OAEP = 2, + RSA_PSS = 3, + RSA_PKCS1_1_5_ENCRYPT = 4, + RSA_PKCS1_1_5_SIGN = 5, + PKCS7 = 64, +} diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/ProtectedData.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/ProtectedData.aidl new file mode 100644 index 0000000000000000000000000000000000000000..d1610b4d6fd21f01d724aa57c963b264fec4c4f2 --- /dev/null +++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/ProtectedData.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.keymint; +/* @hide */ +@VintfStability +parcelable ProtectedData { + byte[] protectedData; +} diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/RpcHardwareInfo.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/RpcHardwareInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..06bce19c822f31bb4360a9e5ad0a346ceec57fd8 --- /dev/null +++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/RpcHardwareInfo.aidl @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.keymint; +/* @hide */ +@RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability +parcelable RpcHardwareInfo { + int versionNumber; + @utf8InCpp String rpcAuthorName; + int supportedEekCurve = 0; + const int CURVE_NONE = 0; + const int CURVE_P256 = 1; + const int CURVE_25519 = 2; +} diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/SecurityLevel.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/SecurityLevel.aidl new file mode 100644 index 0000000000000000000000000000000000000000..0d278e0af9d9d38ef00d15fc936a8d158ef44feb --- /dev/null +++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/SecurityLevel.aidl @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.keymint; +/* @hide */ +@Backing(type="int") @VintfStability +enum SecurityLevel { + SOFTWARE = 0, + TRUSTED_ENVIRONMENT = 1, + STRONGBOX = 2, + KEYSTORE = 100, +} diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/Tag.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/Tag.aidl new file mode 100644 index 0000000000000000000000000000000000000000..e310b4448f8af647ad04015f64251f560a208b55 --- /dev/null +++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/Tag.aidl @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.keymint; +/* @hide */ +@Backing(type="int") @VintfStability +enum Tag { + INVALID = 0, + PURPOSE = 536870913, + ALGORITHM = 268435458, + KEY_SIZE = 805306371, + BLOCK_MODE = 536870916, + DIGEST = 536870917, + PADDING = 536870918, + CALLER_NONCE = 1879048199, + MIN_MAC_LENGTH = 805306376, + EC_CURVE = 268435466, + RSA_PUBLIC_EXPONENT = 1342177480, + INCLUDE_UNIQUE_ID = 1879048394, + RSA_OAEP_MGF_DIGEST = 536871115, + BOOTLOADER_ONLY = 1879048494, + ROLLBACK_RESISTANCE = 1879048495, + HARDWARE_TYPE = 268435760, + EARLY_BOOT_ONLY = 1879048497, + ACTIVE_DATETIME = 1610613136, + ORIGINATION_EXPIRE_DATETIME = 1610613137, + USAGE_EXPIRE_DATETIME = 1610613138, + MIN_SECONDS_BETWEEN_OPS = 805306771, + MAX_USES_PER_BOOT = 805306772, + USAGE_COUNT_LIMIT = 805306773, + USER_ID = 805306869, + USER_SECURE_ID = -1610612234, + NO_AUTH_REQUIRED = 1879048695, + USER_AUTH_TYPE = 268435960, + AUTH_TIMEOUT = 805306873, + ALLOW_WHILE_ON_BODY = 1879048698, + TRUSTED_USER_PRESENCE_REQUIRED = 1879048699, + TRUSTED_CONFIRMATION_REQUIRED = 1879048700, + UNLOCKED_DEVICE_REQUIRED = 1879048701, + APPLICATION_ID = -1879047591, + APPLICATION_DATA = -1879047492, + CREATION_DATETIME = 1610613437, + ORIGIN = 268436158, + ROOT_OF_TRUST = -1879047488, + OS_VERSION = 805307073, + OS_PATCHLEVEL = 805307074, + UNIQUE_ID = -1879047485, + ATTESTATION_CHALLENGE = -1879047484, + ATTESTATION_APPLICATION_ID = -1879047483, + ATTESTATION_ID_BRAND = -1879047482, + ATTESTATION_ID_DEVICE = -1879047481, + ATTESTATION_ID_PRODUCT = -1879047480, + ATTESTATION_ID_SERIAL = -1879047479, + ATTESTATION_ID_IMEI = -1879047478, + ATTESTATION_ID_MEID = -1879047477, + ATTESTATION_ID_MANUFACTURER = -1879047476, + ATTESTATION_ID_MODEL = -1879047475, + VENDOR_PATCHLEVEL = 805307086, + BOOT_PATCHLEVEL = 805307087, + DEVICE_UNIQUE_ATTESTATION = 1879048912, + IDENTITY_CREDENTIAL_KEY = 1879048913, + STORAGE_KEY = 1879048914, + ASSOCIATED_DATA = -1879047192, + NONCE = -1879047191, + MAC_LENGTH = 805307371, + RESET_SINCE_ID_ROTATION = 1879049196, + CONFIRMATION_TOKEN = -1879047187, + CERTIFICATE_SERIAL = -2147482642, + CERTIFICATE_SUBJECT = -1879047185, + CERTIFICATE_NOT_BEFORE = 1610613744, + CERTIFICATE_NOT_AFTER = 1610613745, + MAX_BOOT_LEVEL = 805307378, +} diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/TagType.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/TagType.aidl new file mode 100644 index 0000000000000000000000000000000000000000..a7d1de5fd406dd0c390b82f8f8748121b7a45e7e --- /dev/null +++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/TagType.aidl @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.keymint; +/* @hide */ +@Backing(type="int") @VintfStability +enum TagType { + INVALID = 0, + ENUM = 268435456, + ENUM_REP = 536870912, + UINT = 805306368, + UINT_REP = 1073741824, + ULONG = 1342177280, + DATE = 1610612736, + BOOL = 1879048192, + BIGNUM = -2147483648, + BYTES = -1879048192, + ULONG_REP = -1610612736, +} diff --git a/security/secureclock/aidl/Android.bp b/security/secureclock/aidl/Android.bp index 6a2b7530142db8a26e1ab980726b932a90b68042..5235dd5ac480388eba4c28d31f473ef89ab4d96a 100644 --- a/security/secureclock/aidl/Android.bp +++ b/security/secureclock/aidl/Android.bp @@ -32,4 +32,5 @@ aidl_interface { ], }, }, + versions: ["1"], } diff --git a/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/1/.hash b/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/1/.hash new file mode 100644 index 0000000000000000000000000000000000000000..f6b25a0a49c8c54299b8a935a8f64c4e820d56e8 --- /dev/null +++ b/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/1/.hash @@ -0,0 +1 @@ +cd55ca9963c6a57fa5f2f120a45c6e0c4fafb423 diff --git a/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/1/android/hardware/security/secureclock/ISecureClock.aidl b/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/1/android/hardware/security/secureclock/ISecureClock.aidl new file mode 100644 index 0000000000000000000000000000000000000000..4ecc1e443034bc35d593ba6a4b57117bc3c425d5 --- /dev/null +++ b/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/1/android/hardware/security/secureclock/ISecureClock.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.secureclock; +/* @hide */ +@VintfStability +interface ISecureClock { + android.hardware.security.secureclock.TimeStampToken generateTimeStamp(in long challenge); + const String TIME_STAMP_MAC_LABEL = "Auth Verification"; +} diff --git a/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/1/android/hardware/security/secureclock/TimeStampToken.aidl b/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/1/android/hardware/security/secureclock/TimeStampToken.aidl new file mode 100644 index 0000000000000000000000000000000000000000..d105ac8f6c9f2eae3a810514656c223da65d6d7b --- /dev/null +++ b/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/1/android/hardware/security/secureclock/TimeStampToken.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.secureclock; +/* @hide */ +@RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability +parcelable TimeStampToken { + long challenge; + android.hardware.security.secureclock.Timestamp timestamp; + byte[] mac; +} diff --git a/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/1/android/hardware/security/secureclock/Timestamp.aidl b/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/1/android/hardware/security/secureclock/Timestamp.aidl new file mode 100644 index 0000000000000000000000000000000000000000..2e0e389d9e5ea4bb10c203c78db96b39383f4ea8 --- /dev/null +++ b/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/1/android/hardware/security/secureclock/Timestamp.aidl @@ -0,0 +1,39 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.secureclock; +/* @hide */ +@RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability +parcelable Timestamp { + long milliSeconds; +} diff --git a/security/sharedsecret/aidl/Android.bp b/security/sharedsecret/aidl/Android.bp index 16830598f560f9799d95778b8c001e440f3c0720..f1fce7455bec0f4918ebd829b534440b16428610 100644 --- a/security/sharedsecret/aidl/Android.bp +++ b/security/sharedsecret/aidl/Android.bp @@ -27,4 +27,5 @@ aidl_interface { enabled: true, }, }, + versions: ["1"], } diff --git a/security/sharedsecret/aidl/aidl_api/android.hardware.security.sharedsecret/1/.hash b/security/sharedsecret/aidl/aidl_api/android.hardware.security.sharedsecret/1/.hash new file mode 100644 index 0000000000000000000000000000000000000000..7d22dc4e6eed96907e7e40d8757a66b2e6dcfc4c --- /dev/null +++ b/security/sharedsecret/aidl/aidl_api/android.hardware.security.sharedsecret/1/.hash @@ -0,0 +1 @@ +aea3745b559d2977f0676952e510fb0547a52140 diff --git a/security/sharedsecret/aidl/aidl_api/android.hardware.security.sharedsecret/1/android/hardware/security/sharedsecret/ISharedSecret.aidl b/security/sharedsecret/aidl/aidl_api/android.hardware.security.sharedsecret/1/android/hardware/security/sharedsecret/ISharedSecret.aidl new file mode 100644 index 0000000000000000000000000000000000000000..e76efe7f5da3bc7968a00fabd84ba268431a2ca9 --- /dev/null +++ b/security/sharedsecret/aidl/aidl_api/android.hardware.security.sharedsecret/1/android/hardware/security/sharedsecret/ISharedSecret.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.sharedsecret; +/* @hide */ +@VintfStability +interface ISharedSecret { + android.hardware.security.sharedsecret.SharedSecretParameters getSharedSecretParameters(); + byte[] computeSharedSecret(in android.hardware.security.sharedsecret.SharedSecretParameters[] params); + const String KEY_AGREEMENT_LABEL = "KeymasterSharedMac"; + const String KEY_CHECK_LABEL = "Keymaster HMAC Verification"; +} diff --git a/security/sharedsecret/aidl/aidl_api/android.hardware.security.sharedsecret/1/android/hardware/security/sharedsecret/SharedSecretParameters.aidl b/security/sharedsecret/aidl/aidl_api/android.hardware.security.sharedsecret/1/android/hardware/security/sharedsecret/SharedSecretParameters.aidl new file mode 100644 index 0000000000000000000000000000000000000000..e15fd49aa6bee2647b36d0c602b452876aacf42f --- /dev/null +++ b/security/sharedsecret/aidl/aidl_api/android.hardware.security.sharedsecret/1/android/hardware/security/sharedsecret/SharedSecretParameters.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.sharedsecret; +/* @hide */ +@RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability +parcelable SharedSecretParameters { + byte[] seed; + byte[] nonce; +} diff --git a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp index 1f579ba61e50a8bddb6790cbe1fb66347316d3c7..d46cf5a4908da348246e5448bf9daf431dc94603 100644 --- a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp +++ b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp @@ -24,7 +24,9 @@ #include #include +#include #include +#include #include using ::android::hardware::Return; @@ -149,6 +151,7 @@ std::vector SensorsHidlTest::getSensorsList() { TEST_P(SensorsHidlTest, SensorListValid) { S()->getSensorsList([&](const auto& list) { const size_t count = list.size(); + std::unordered_map> sensorTypeNameMap; for (size_t i = 0; i < count; ++i) { const auto& s = list[i]; SCOPED_TRACE(::testing::Message() @@ -167,6 +170,14 @@ TEST_P(SensorsHidlTest, SensorListValid) { EXPECT_FALSE(s.name.empty()); EXPECT_FALSE(s.vendor.empty()); + // Make sure that sensors of the same type have a unique name. + std::vector& v = sensorTypeNameMap[static_cast(s.type)]; + bool isUniqueName = std::find(v.begin(), v.end(), s.name) == v.end(); + EXPECT_TRUE(isUniqueName) << "Duplicate sensor Name: " << s.name; + if (isUniqueName) { + v.push_back(s.name); + } + // Test power > 0, maxRange > 0 EXPECT_LE(0, s.power); EXPECT_LT(0, s.maxRange); diff --git a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp index a0d436f3f967375d0c668672c60bd182e95e1362..e212423fa7a27dffc5923501828c3367334e6ab7 100644 --- a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp +++ b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp @@ -296,6 +296,7 @@ TEST_P(SensorsHidlTest, FlushNonexistentSensor) { 0 /* expectedFlushCount */, Result::BAD_VALUE); } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SensorsHidlTest); INSTANTIATE_TEST_SUITE_P(PerInstance, SensorsHidlTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames( android::hardware::sensors::V2_0::ISensors::descriptor)), diff --git a/sensors/2.1/vts/functional/VtsHalSensorsV2_1TargetTest.cpp b/sensors/2.1/vts/functional/VtsHalSensorsV2_1TargetTest.cpp index 230bb6c2f15d2d8254870872b67ea54fe5e9a919..3a866b160318374d31a157766a23a390bc80defa 100644 --- a/sensors/2.1/vts/functional/VtsHalSensorsV2_1TargetTest.cpp +++ b/sensors/2.1/vts/functional/VtsHalSensorsV2_1TargetTest.cpp @@ -16,6 +16,7 @@ #include "VtsHalSensorsV2_XTargetTest.h" +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SensorsHidlTest); INSTANTIATE_TEST_SUITE_P(PerInstance, SensorsHidlTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames( android::hardware::sensors::V2_1::ISensors::descriptor)), diff --git a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h index 47a8cc0b4aedc7dd150fabda78eb888ce9dd7ee5..ea5dc70c5b5acdba91cb23fd2b2519d522b19350 100644 --- a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h +++ b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h @@ -26,10 +26,12 @@ #include #include +#include #include #include #include #include +#include #include /** @@ -373,6 +375,7 @@ int32_t SensorsHidlTest::getInvalidSensorHandle() { TEST_P(SensorsHidlTest, SensorListValid) { getSensors()->getSensorsList([&](const auto& list) { const size_t count = list.size(); + std::unordered_map> sensorTypeNameMap; for (size_t i = 0; i < count; ++i) { const auto& s = list[i]; SCOPED_TRACE(::testing::Message() @@ -393,6 +396,14 @@ TEST_P(SensorsHidlTest, SensorListValid) { EXPECT_FALSE(s.name.empty()); EXPECT_FALSE(s.vendor.empty()); + // Make sure that sensors of the same type have a unique name. + std::vector& v = sensorTypeNameMap[static_cast(s.type)]; + bool isUniqueName = std::find(v.begin(), v.end(), s.name) == v.end(); + EXPECT_TRUE(isUniqueName) << "Duplicate sensor Name: " << s.name; + if (isUniqueName) { + v.push_back(s.name); + } + // Test power > 0, maxRange > 0 EXPECT_LE(0, s.power); EXPECT_LT(0, s.maxRange); diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h index a8e19967d5f8e73d916d268fc62910bbbfca1624..af140096b871bf7f5b1c804770c2f4a80ddfe5c8 100644 --- a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h +++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h @@ -425,7 +425,10 @@ class SensorsHidlTestBase : public testing::TestWithParam { return; } - batchingPeriodInNs = std::min(batchingPeriodInNs, maxBatchingTestTimeNs); + if (batchingPeriodInNs > maxBatchingTestTimeNs) { + batchingPeriodInNs = maxBatchingTestTimeNs; + minFifoCount = (uint32_t)(batchingPeriodInNs / minSamplingPeriodInNs); + } ALOGI("Test batching for %d ms", (int)(batchingPeriodInNs / 1000 / 1000)); @@ -448,7 +451,7 @@ class SensorsHidlTestBase : public testing::TestWithParam { false /*change collection*/); // 0.8 + 0.2 times the batching period - usleep(batchingPeriodInNs / 1000 * 8 / 10); + usleep(batchingPeriodInNs / 1000 * 2 / 10); ASSERT_EQ(flush(handle), Result::OK); // plus some time for the event to deliver diff --git a/soundtrigger/2.3/vts/functional/VtsHalSoundtriggerV2_3TargetTest.cpp b/soundtrigger/2.3/vts/functional/VtsHalSoundtriggerV2_3TargetTest.cpp index 2d147e460662ed45e3095696ec70728ca2b84a3b..50646d47c89332ae87b9a956ba6d859c74db9b4f 100644 --- a/soundtrigger/2.3/vts/functional/VtsHalSoundtriggerV2_3TargetTest.cpp +++ b/soundtrigger/2.3/vts/functional/VtsHalSoundtriggerV2_3TargetTest.cpp @@ -84,6 +84,7 @@ TEST_P(SoundTriggerHidlTest, GetProperties_2_3) { (AudioCapabilities::ECHO_CANCELLATION | AudioCapabilities::NOISE_SUPPRESSION)); } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SoundTriggerHidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, SoundTriggerHidlTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames(ISoundTriggerHw::descriptor)), diff --git a/tests/extension/vibrator/aidl/Android.bp b/tests/extension/vibrator/aidl/Android.bp index 75d1193dc4fbd29bd2e49a9df9f3016c322472c6..20df5bb34808cba97829d8699f6350a894558db7 100644 --- a/tests/extension/vibrator/aidl/Android.bp +++ b/tests/extension/vibrator/aidl/Android.bp @@ -30,7 +30,7 @@ aidl_interface { // This happens to use types from a core interface, so we import it, but // this won't always be needed. imports: [ - "android.hardware.vibrator", + "android.hardware.vibrator-V2", ], backend: { diff --git a/tests/extension/vibrator/aidl/client/Android.bp b/tests/extension/vibrator/aidl/client/Android.bp index 20b03448e0e8f26959f860cab20c7b68e84d8881..284ac7459b09f1cc925213d08bc178605cf7ae89 100644 --- a/tests/extension/vibrator/aidl/client/Android.bp +++ b/tests/extension/vibrator/aidl/client/Android.bp @@ -23,11 +23,11 @@ cc_test { shared_libs: [ "libbinder", "libutils", - "android.hardware.vibrator-V1-cpp", + "android.hardware.vibrator-V2-cpp", "android.hardware.tests.extension.vibrator-V1-cpp", "libbinder_ndk", - "android.hardware.vibrator-V1-ndk", + "android.hardware.vibrator-V2-ndk", "android.hardware.tests.extension.vibrator-V1-ndk", ], } diff --git a/tests/extension/vibrator/aidl/default/Android.bp b/tests/extension/vibrator/aidl/default/Android.bp index f489ed92c486c20a246af8f65e60636cdbd5f759..0f3895f8de2d3d055b28f825dec4f70344237468 100644 --- a/tests/extension/vibrator/aidl/default/Android.bp +++ b/tests/extension/vibrator/aidl/default/Android.bp @@ -28,7 +28,7 @@ cc_binary { shared_libs: [ "libbase", "libbinder_ndk", - "android.hardware.vibrator-V1-ndk", - "android.hardware.tests.extension.vibrator-V1-ndk", + "android.hardware.vibrator-V2-ndk", + "android.hardware.tests.extension.vibrator-V2-ndk", ], } diff --git a/tv/cec/1.1/Android.bp b/tv/cec/1.1/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..27b4f03767fdf2bda102443f21924fe232a0449c --- /dev/null +++ b/tv/cec/1.1/Android.bp @@ -0,0 +1,25 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +hidl_interface { + name: "android.hardware.tv.cec@1.1", + root: "android.hardware", + srcs: [ + "types.hal", + "IHdmiCec.hal", + "IHdmiCecCallback.hal", + ], + interfaces: [ + "android.hardware.tv.cec@1.0", + "android.hidl.base@1.0", + ], + gen_java: true, +} diff --git a/tv/cec/1.1/IHdmiCec.hal b/tv/cec/1.1/IHdmiCec.hal new file mode 100644 index 0000000000000000000000000000000000000000..fe7bedf1959391a79de09429b186314a8712897b --- /dev/null +++ b/tv/cec/1.1/IHdmiCec.hal @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.tv.cec@1.1; + +import @1.0::IHdmiCec; +import @1.0::Result; +import @1.0::SendMessageResult; + +import IHdmiCecCallback; + +/** + * HDMI-CEC HAL interface definition. + */ +interface IHdmiCec extends @1.0::IHdmiCec { + /** + * Passes the logical address that must be used in this system. + * + * HAL must use it to configure the hardware so that the CEC commands + * addressed the given logical address can be filtered in. This method must + * be able to be called as many times as necessary in order to support + * multiple logical devices. + * + * @param addr Logical address that must be used in this system. It must be + * in the range of valid logical addresses for the call to succeed. + * @return result Result status of the operation. SUCCESS if successful, + * FAILURE_INVALID_ARGS if the given logical address is invalid, + * FAILURE_BUSY if device or resource is busy + */ + addLogicalAddress_1_1(CecLogicalAddress addr) generates (Result result); + + /** + * Transmits HDMI-CEC message to other HDMI device. + * + * The method must be designed to return in a certain amount of time and not + * hanging forever which may happen if CEC signal line is pulled low for + * some reason. + * + * It must try retransmission at least once as specified in the section '7.1 + * Frame Re-transmissions' of the CEC Spec 1.4b. + * + * @param message CEC message to be sent to other HDMI device. + * @return result Result status of the operation. SUCCESS if successful, + * NACK if the sent message is not acknowledged, + * BUSY if the CEC bus is busy. + */ + sendMessage_1_1(CecMessage message) generates (SendMessageResult result); + + /** + * Sets a callback that HDMI-CEC HAL must later use for incoming CEC + * messages or internal HDMI events. + * + * @param callback Callback object to pass hdmi events to the system. The + * previously registered callback must be replaced with this one. + */ + setCallback_1_1(IHdmiCecCallback callback); +}; diff --git a/tv/cec/1.1/IHdmiCecCallback.hal b/tv/cec/1.1/IHdmiCecCallback.hal new file mode 100644 index 0000000000000000000000000000000000000000..3928f186cc81e99d719124b1142f9e8173215872 --- /dev/null +++ b/tv/cec/1.1/IHdmiCecCallback.hal @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.tv.cec@1.1; + +import @1.0::IHdmiCecCallback; + +/** + * Callbacks from the HAL implementation to notify the system of new events. + */ +interface IHdmiCecCallback extends @1.0::IHdmiCecCallback { + /** + * The callback function that must be called by HAL implementation to notify + * the system of new CEC message arrival. + */ + oneway onCecMessage_1_1(CecMessage message); +}; diff --git a/tv/cec/1.1/default/Android.bp b/tv/cec/1.1/default/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..b536d23b29bd47a55e6591b4a5330ea5b1fe4695 --- /dev/null +++ b/tv/cec/1.1/default/Android.bp @@ -0,0 +1,32 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_binary { + name: "android.hardware.tv.cec@1.1-service", + defaults: ["hidl_defaults"], + vintf_fragments: ["android.hardware.tv.cec@1.1-service.xml"], + relative_install_path: "hw", + vendor: true, + init_rc: ["android.hardware.tv.cec@1.1-service.rc"], + srcs: [ + "serviceMock.cpp", + "HdmiCecMock.cpp", + ], + + shared_libs: [ + "liblog", + "libcutils", + "libbase", + "libutils", + "libhardware", + "libhidlbase", + "android.hardware.tv.cec@1.0", + "android.hardware.tv.cec@1.1", + ], +} diff --git a/tv/cec/1.1/default/HdmiCecMock.cpp b/tv/cec/1.1/default/HdmiCecMock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f65bab9865512ac1c25f44f4bd964fab4c5f403e --- /dev/null +++ b/tv/cec/1.1/default/HdmiCecMock.cpp @@ -0,0 +1,371 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "android.hardware.tv.cec@1.1" +#include +#include + +#include +#include +#include "HdmiCecMock.h" + +namespace android { +namespace hardware { +namespace tv { +namespace cec { +namespace V1_1 { +namespace implementation { + +class WrappedCallback : public ::android::hardware::tv::cec::V1_1::IHdmiCecCallback { + public: + WrappedCallback(sp<::android::hardware::tv::cec::V1_0::IHdmiCecCallback> callback) { + mCallback = callback; + } + + Return onCecMessage(const ::android::hardware::tv::cec::V1_0::CecMessage& message) { + mCallback->onCecMessage(message); + return Void(); + } + Return onCecMessage_1_1(const ::android::hardware::tv::cec::V1_1::CecMessage& message) { + ::android::hardware::tv::cec::V1_0::CecMessage cecMessage; + cecMessage.initiator = + ::android::hardware::tv::cec::V1_0::CecLogicalAddress(message.initiator); + cecMessage.destination = + ::android::hardware::tv::cec::V1_0::CecLogicalAddress(message.destination); + cecMessage.body = message.body; + mCallback->onCecMessage(cecMessage); + return Void(); + } + Return onHotplugEvent(const ::android::hardware::tv::cec::V1_0::HotplugEvent& event) { + mCallback->onHotplugEvent(event); + return Void(); + } + + private: + sp<::android::hardware::tv::cec::V1_0::IHdmiCecCallback> mCallback; +}; + +/* + * (*set_option)() passes flags controlling the way HDMI-CEC service works down + * to HAL implementation. Those flags will be used in case the feature needs + * update in HAL itself, firmware or microcontroller. + */ +void HdmiCecMock::cec_set_option(int flag, int value) { + // maintain options and set them accordingly + switch (flag) { + case HDMI_OPTION_WAKEUP: + mOptionWakeUp = value; + break; + case HDMI_OPTION_ENABLE_CEC: + mOptionEnableCec = value; + break; + case HDMI_OPTION_SYSTEM_CEC_CONTROL: + mOptionSystemCecControl = value; + break; + case HDMI_OPTION_SET_LANG: + mOptionLanguage = value; + break; + } +} + +// Methods from ::android::hardware::tv::cec::V1_0::IHdmiCec follow. +Return HdmiCecMock::addLogicalAddress(CecLogicalAddress addr) { + return addLogicalAddress_1_1(::android::hardware::tv::cec::V1_1::CecLogicalAddress(addr)); +} + +Return HdmiCecMock::clearLogicalAddress() { + // remove logical address from the list + mLogicalAddresses = {}; + return Void(); +} + +Return HdmiCecMock::getPhysicalAddress(getPhysicalAddress_cb _hidl_cb) { + // maintain a physical address and return it + // default 0xFFFF, update on hotplug event + _hidl_cb(Result::SUCCESS, mPhysicalAddress); + return Void(); +} + +Return HdmiCecMock::sendMessage(const CecMessage& message) { + ::android::hardware::tv::cec::V1_1::CecMessage cecMessage; + cecMessage.initiator = ::android::hardware::tv::cec::V1_1::CecLogicalAddress(message.initiator); + cecMessage.destination = + ::android::hardware::tv::cec::V1_1::CecLogicalAddress(message.destination); + cecMessage.body = message.body; + return sendMessage_1_1(cecMessage); +} + +Return HdmiCecMock::setCallback(const sp& callback) { + return setCallback_1_1(new WrappedCallback(callback)); +} + +Return HdmiCecMock::getCecVersion() { + // maintain a cec version and return it + return mCecVersion; +} + +Return HdmiCecMock::getVendorId() { + return mCecVendorId; +} + +Return HdmiCecMock::getPortInfo(getPortInfo_cb _hidl_cb) { + // TODO ready port info from device specific config + _hidl_cb(mPortInfo); + return Void(); +} + +Return HdmiCecMock::setOption(OptionKey key, bool value) { + cec_set_option(static_cast(key), value ? 1 : 0); + return Void(); +} + +Return HdmiCecMock::setLanguage(const hidl_string& language) { + if (language.size() != 3) { + LOG(ERROR) << "Wrong language code: expected 3 letters, but it was " << language.size() + << "."; + return Void(); + } + // TODO validate if language is a valid language code + const char* languageStr = language.c_str(); + int convertedLanguage = ((languageStr[0] & 0xFF) << 16) | ((languageStr[1] & 0xFF) << 8) | + (languageStr[2] & 0xFF); + cec_set_option(HDMI_OPTION_SET_LANG, convertedLanguage); + return Void(); +} + +Return HdmiCecMock::enableAudioReturnChannel(int32_t portId __unused, bool enable __unused) { + // Maintain ARC status + return Void(); +} + +Return HdmiCecMock::isConnected(int32_t portId) { + // maintain port connection status and update on hotplug event + if (portId < mTotalPorts && portId >= 0) { + return mPortConnectionStatus[portId]; + } + return false; +} + +// Methods from ::android::hardware::tv::cec::V1_1::IHdmiCec follow. +Return HdmiCecMock::addLogicalAddress_1_1( + ::android::hardware::tv::cec::V1_1::CecLogicalAddress addr) { + // have a list to maintain logical addresses + int size = mLogicalAddresses.size(); + mLogicalAddresses.resize(size + 1); + mLogicalAddresses[size + 1] = addr; + return Result::SUCCESS; +} + +Return HdmiCecMock::sendMessage_1_1( + const ::android::hardware::tv::cec::V1_1::CecMessage& message) { + if (message.body.size() == 0) { + return SendMessageResult::NACK; + } + sendMessageToFifo(message); + return SendMessageResult::SUCCESS; +} + +Return HdmiCecMock::setCallback_1_1( + const sp<::android::hardware::tv::cec::V1_1::IHdmiCecCallback>& callback) { + if (mCallback != nullptr) { + mCallback = nullptr; + } + + if (callback != nullptr) { + mCallback = callback; + mCallback->linkToDeath(this, 0 /*cookie*/); + + mInputFile = open(CEC_MSG_IN_FIFO, O_RDWR); + mOutputFile = open(CEC_MSG_OUT_FIFO, O_RDWR); + pthread_create(&mThreadId, NULL, __threadLoop, this); + pthread_setname_np(mThreadId, "hdmi_cec_loop"); + } + return Void(); +} + +void* HdmiCecMock::__threadLoop(void* user) { + HdmiCecMock* const self = static_cast(user); + self->threadLoop(); + return 0; +} + +int HdmiCecMock::readMessageFromFifo(unsigned char* buf, int msgCount) { + if (msgCount <= 0 || !buf) { + return 0; + } + + int ret = -1; + /* maybe blocked at driver */ + ret = read(mInputFile, buf, msgCount); + if (ret < 0) { + ALOGE("[halimp] read :%s failed, ret:%d\n", CEC_MSG_IN_FIFO, ret); + return -1; + } + + return ret; +} + +int HdmiCecMock::sendMessageToFifo(const ::android::hardware::tv::cec::V1_1::CecMessage& message) { + unsigned char msgBuf[CEC_MESSAGE_BODY_MAX_LENGTH]; + int ret = -1; + + memset(msgBuf, 0, sizeof(msgBuf)); + msgBuf[0] = ((static_cast(message.initiator) & 0xf) << 4) | + (static_cast(message.destination) & 0xf); + + size_t length = std::min(static_cast(message.body.size()), + static_cast(MaxLength::MESSAGE_BODY)); + for (size_t i = 0; i < length; ++i) { + msgBuf[i + 1] = static_cast(message.body[i]); + } + + // open the output pipe for writing outgoing cec message + mOutputFile = open(CEC_MSG_OUT_FIFO, O_WRONLY); + if (mOutputFile < 0) { + ALOGD("[halimp] file open failed for writing"); + return -1; + } + + // write message into the output pipe + ret = write(mOutputFile, msgBuf, length + 1); + close(mOutputFile); + if (ret < 0) { + ALOGE("[halimp] write :%s failed, ret:%d\n", CEC_MSG_OUT_FIFO, ret); + return -1; + } + return ret; +} + +void HdmiCecMock::printCecMsgBuf(const char* msg_buf, int len) { + char buf[64] = {}; + int i, size = 0; + memset(buf, 0, sizeof(buf)); + for (i = 0; i < len; i++) { + size += sprintf(buf + size, " %02x", msg_buf[i]); + } + ALOGD("[halimp] %s, msg:%s", __FUNCTION__, buf); +} + +void HdmiCecMock::handleHotplugMessage(unsigned char* msgBuf) { + HotplugEvent hotplugEvent{.connected = ((msgBuf[3]) & 0xf) > 0, + .portId = static_cast(msgBuf[0] & 0xf)}; + + if (hotplugEvent.portId >= mPortInfo.size()) { + ALOGD("[halimp] ignore hot plug message, id %x does not exist", hotplugEvent.portId); + return; + } + + ALOGD("[halimp] hot plug port id %x, is connected %x", (msgBuf[0] & 0xf), (msgBuf[3] & 0xf)); + if (mPortInfo[hotplugEvent.portId].type == HdmiPortType::OUTPUT) { + mPhysicalAddress = + ((hotplugEvent.connected == 0) ? 0xffff : ((msgBuf[1] << 8) | (msgBuf[2]))); + mPortInfo[hotplugEvent.portId].physicalAddress = mPhysicalAddress; + ALOGD("[halimp] hot plug physical address %x", mPhysicalAddress); + } + + // todo update connection status + + if (mCallback != nullptr) { + mCallback->onHotplugEvent(hotplugEvent); + } +} + +void HdmiCecMock::handleCecMessage(unsigned char* msgBuf, int megSize) { + ::android::hardware::tv::cec::V1_1::CecMessage message; + size_t length = std::min(static_cast(megSize - 1), + static_cast(MaxLength::MESSAGE_BODY)); + message.body.resize(length); + + for (size_t i = 0; i < length; ++i) { + message.body[i] = static_cast(msgBuf[i + 1]); + ALOGD("[halimp] msg body %x", message.body[i]); + } + + message.initiator = static_cast<::android::hardware::tv::cec::V1_1::CecLogicalAddress>( + (msgBuf[0] >> 4) & 0xf); + ALOGD("[halimp] msg init %x", message.initiator); + message.destination = static_cast<::android::hardware::tv::cec::V1_1::CecLogicalAddress>( + (msgBuf[0] >> 0) & 0xf); + ALOGD("[halimp] msg dest %x", message.destination); + + // messageValidateAndHandle(&event); + + if (mCallback != nullptr) { + mCallback->onCecMessage_1_1(message); + } +} + +void HdmiCecMock::threadLoop() { + ALOGD("[halimp] threadLoop start."); + unsigned char msgBuf[CEC_MESSAGE_BODY_MAX_LENGTH]; + int r = -1; + + // open the input pipe + while (mInputFile < 0) { + usleep(1000 * 1000); + mInputFile = open(CEC_MSG_IN_FIFO, O_RDONLY); + } + ALOGD("[halimp] file open ok, fd = %d.", mInputFile); + + while (mCecThreadRun) { + if (!mOptionSystemCecControl) { + usleep(1000 * 1000); + continue; + } + + memset(msgBuf, 0, sizeof(msgBuf)); + // try to get a message from dev. + // echo -n -e '\x04\x83' >> /dev/cec + r = readMessageFromFifo(msgBuf, CEC_MESSAGE_BODY_MAX_LENGTH); + if (r <= 1) { + // ignore received ping messages + continue; + } + + printCecMsgBuf((const char*)msgBuf, r); + + if (((msgBuf[0] >> 4) & 0xf) == 0xf) { + // the message is a hotplug event + handleHotplugMessage(msgBuf); + continue; + } + + handleCecMessage(msgBuf, r); + } + + ALOGD("[halimp] thread end."); + // mCecDevice.mExited = true; +} + +HdmiCecMock::HdmiCecMock() { + ALOGE("[halimp] Opening a virtual HAL for testing and virtual machine."); + mCallback = nullptr; + mPortInfo.resize(mTotalPorts); + mPortConnectionStatus.resize(mTotalPorts); + mPortInfo[0] = {.type = HdmiPortType::OUTPUT, + .portId = static_cast(1), + .cecSupported = true, + .arcSupported = false, + .physicalAddress = mPhysicalAddress}; + mPortConnectionStatus[0] = false; +} + +} // namespace implementation +} // namespace V1_1 +} // namespace cec +} // namespace tv +} // namespace hardware +} // namespace android \ No newline at end of file diff --git a/tv/cec/1.1/default/HdmiCecMock.h b/tv/cec/1.1/default/HdmiCecMock.h new file mode 100644 index 0000000000000000000000000000000000000000..0205f8d95f12b6e730bcf1a622f32e8d68fd1102 --- /dev/null +++ b/tv/cec/1.1/default/HdmiCecMock.h @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +using namespace std; + +namespace android { +namespace hardware { +namespace tv { +namespace cec { +namespace V1_1 { +namespace implementation { + +using ::android::sp; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::tv::cec::V1_0::CecLogicalAddress; +using ::android::hardware::tv::cec::V1_0::CecMessage; +using ::android::hardware::tv::cec::V1_0::HdmiPortInfo; +using ::android::hardware::tv::cec::V1_0::HdmiPortType; +using ::android::hardware::tv::cec::V1_0::HotplugEvent; +using ::android::hardware::tv::cec::V1_0::IHdmiCecCallback; +using ::android::hardware::tv::cec::V1_0::MaxLength; +using ::android::hardware::tv::cec::V1_0::OptionKey; +using ::android::hardware::tv::cec::V1_0::Result; +using ::android::hardware::tv::cec::V1_0::SendMessageResult; +using ::android::hardware::tv::cec::V1_1::IHdmiCec; + +#define CEC_MSG_IN_FIFO "/dev/cec_in_pipe" +#define CEC_MSG_OUT_FIFO "/dev/cec_out_pipe" + +struct HdmiCecMock : public IHdmiCec, public hidl_death_recipient { + HdmiCecMock(); + // Methods from ::android::hardware::tv::cec::V1_0::IHdmiCec follow. + Return addLogicalAddress(CecLogicalAddress addr) override; + Return clearLogicalAddress() override; + Return getPhysicalAddress(getPhysicalAddress_cb _hidl_cb) override; + Return sendMessage(const CecMessage& message) override; + Return setCallback( + const sp<::android::hardware::tv::cec::V1_0::IHdmiCecCallback>& callback) override; + Return getCecVersion() override; + Return getVendorId() override; + Return getPortInfo(getPortInfo_cb _hidl_cb) override; + Return setOption(OptionKey key, bool value) override; + Return setLanguage(const hidl_string& language) override; + Return enableAudioReturnChannel(int32_t portId, bool enable) override; + Return isConnected(int32_t portId) override; + + // Methods from ::android::hardware::tv::cec::V1_1::IHdmiCec follow. + Return addLogicalAddress_1_1( + ::android::hardware::tv::cec::V1_1::CecLogicalAddress addr) override; + Return sendMessage_1_1( + const ::android::hardware::tv::cec::V1_1::CecMessage& message) override; + Return setCallback_1_1( + const sp<::android::hardware::tv::cec::V1_1::IHdmiCecCallback>& callback) override; + + virtual void serviceDied(uint64_t /*cookie*/, + const wp<::android::hidl::base::V1_0::IBase>& /*who*/) { + setCallback(nullptr); + } + + void cec_set_option(int flag, int value); + void printCecMsgBuf(const char* msg_buf, int len); + + private: + static void* __threadLoop(void* data); + void threadLoop(); + int readMessageFromFifo(unsigned char* buf, int msgCount); + int sendMessageToFifo(const ::android::hardware::tv::cec::V1_1::CecMessage& message); + void handleHotplugMessage(unsigned char* msgBuf); + void handleCecMessage(unsigned char* msgBuf, int length); + + private: + sp<::android::hardware::tv::cec::V1_1::IHdmiCecCallback> mCallback; + + // Variables for the virtual cec hal impl + uint16_t mPhysicalAddress = 0xFFFF; + vector<::android::hardware::tv::cec::V1_1::CecLogicalAddress> mLogicalAddresses; + int32_t mCecVersion = 0x06; + uint32_t mCecVendorId = 0x01; + + // Port configuration + int mTotalPorts = 1; + hidl_vec mPortInfo; + hidl_vec mPortConnectionStatus; + + // CEC Option value + int mOptionWakeUp = 0; + int mOptionEnableCec = 0; + int mOptionSystemCecControl = 0; + int mOptionLanguage = 0; + + // Testing variables + // Input file descriptor + int mInputFile; + // Output file descriptor + int mOutputFile; + bool mCecThreadRun = true; + pthread_t mThreadId = 0; +}; +} // namespace implementation +} // namespace V1_1 +} // namespace cec +} // namespace tv +} // namespace hardware +} // namespace android \ No newline at end of file diff --git a/tv/cec/1.1/default/android.hardware.tv.cec@1.1-service.rc b/tv/cec/1.1/default/android.hardware.tv.cec@1.1-service.rc new file mode 100644 index 0000000000000000000000000000000000000000..e150c91cc7a2b6d31c85d53913d60b5cfbca5040 --- /dev/null +++ b/tv/cec/1.1/default/android.hardware.tv.cec@1.1-service.rc @@ -0,0 +1,6 @@ +service vendor.cec-hal-1-1 /vendor/bin/hw/android.hardware.tv.cec@1.1-service + interface android.hardware.tv.cec@1.0::IHdmiCec default + interface android.hardware.tv.cec@1.1::IHdmiCec default + class hal + user system + group system \ No newline at end of file diff --git a/tv/cec/1.1/default/android.hardware.tv.cec@1.1-service.xml b/tv/cec/1.1/default/android.hardware.tv.cec@1.1-service.xml new file mode 100644 index 0000000000000000000000000000000000000000..492369e67ffe368abdf9582ae68e411eea3d1de2 --- /dev/null +++ b/tv/cec/1.1/default/android.hardware.tv.cec@1.1-service.xml @@ -0,0 +1,11 @@ + + + android.hardware.tv.cec + hwbinder + 1.1 + + IHdmiCec + default + + + diff --git a/tv/cec/1.1/default/serviceMock.cpp b/tv/cec/1.1/default/serviceMock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..72fc311ddcf23e103029c1ad75d672c62027b253 --- /dev/null +++ b/tv/cec/1.1/default/serviceMock.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "android.hardware.tv.cec@1.1-service-shim" + +#include +#include +#include "HdmiCecMock.h" + +using android::hardware::configureRpcThreadpool; +using android::hardware::joinRpcThreadpool; +using android::hardware::tv::cec::V1_1::IHdmiCec; +using android::hardware::tv::cec::V1_1::implementation::HdmiCecMock; + +int main() { + configureRpcThreadpool(8, true /* callerWillJoin */); + + // Setup hwbinder service + android::sp service = new HdmiCecMock(); + android::status_t status; + status = service->registerAsService(); + LOG_ALWAYS_FATAL_IF(status != android::OK, "Error while registering mock cec service: %d", + status); + + joinRpcThreadpool(); + return 0; +} diff --git a/tv/cec/1.1/types.hal b/tv/cec/1.1/types.hal new file mode 100644 index 0000000000000000000000000000000000000000..a117519ed0a430f98a5e626ba6409041a7282aed --- /dev/null +++ b/tv/cec/1.1/types.hal @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.tv.cec@1.1; + +import @1.0::CecLogicalAddress; +import @1.0::CecMessageType; + +enum CecLogicalAddress : @1.0::CecLogicalAddress { + BACKUP_1 = 12, + BACKUP_2 = 13, +}; + +enum CecMessageType : @1.0::CecMessageType { + GIVE_FEATURES = 0xA5, + REPORT_FEATURES = 0xA6, + REQUEST_CURRENT_LATENCY = 0xA7, + REPORT_CURRENT_LATENCY = 0xA8, +}; + +struct CecMessage { + /** logical address of the initiator */ + CecLogicalAddress initiator; + + /** logical address of destination */ + CecLogicalAddress destination; + + /** + * The maximum size of body is 15 (MaxLength::MESSAGE_BODY) as specified in + * the section 6 of the CEC Spec 1.4b. Overflowed data must be ignored. */ + vec body; +}; diff --git a/tv/cec/1.1/vts/functional/Android.bp b/tv/cec/1.1/vts/functional/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..5a6548d4dc9e2365a8d9adc0d906ae5d0aef97d5 --- /dev/null +++ b/tv/cec/1.1/vts/functional/Android.bp @@ -0,0 +1,23 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_test { + name: "VtsHalTvCecV1_1TargetTest", + defaults: ["VtsHalTargetTestDefaults"], + srcs: ["VtsHalTvCecV1_1TargetTest.cpp"], + static_libs: [ + "android.hardware.tv.cec@1.1", + "android.hardware.tv.cec@1.0", + ], + test_suites: [ + "general-tests", + "vts", + ], + disable_framework: true, +} diff --git a/tv/cec/1.1/vts/functional/VtsHalTvCecV1_1TargetTest.cpp b/tv/cec/1.1/vts/functional/VtsHalTvCecV1_1TargetTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c5b4b2fe58fd8c4849d205792252c78b621c1748 --- /dev/null +++ b/tv/cec/1.1/vts/functional/VtsHalTvCecV1_1TargetTest.cpp @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "HdmiCec_hal_test" +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +using ::android::sp; +using ::android::hardware::hidl_death_recipient; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::tv::cec::V1_0::CecDeviceType; +using ::android::hardware::tv::cec::V1_0::HdmiPortInfo; +using ::android::hardware::tv::cec::V1_0::HdmiPortType; +using ::android::hardware::tv::cec::V1_0::HotplugEvent; +using ::android::hardware::tv::cec::V1_0::OptionKey; +using ::android::hardware::tv::cec::V1_0::Result; +using ::android::hardware::tv::cec::V1_0::SendMessageResult; +using ::android::hardware::tv::cec::V1_1::CecLogicalAddress; +using ::android::hardware::tv::cec::V1_1::CecMessage; +using ::android::hardware::tv::cec::V1_1::IHdmiCec; +using ::android::hardware::tv::cec::V1_1::IHdmiCecCallback; + +#define CEC_VERSION 0x05 +#define INCORRECT_VENDOR_ID 0x00 +#define TV_PHYSICAL_ADDRESS 0x0000 + +// The main test class for TV CEC HAL. +class HdmiCecTest : public ::testing::TestWithParam { + public: + void SetUp() override { + hdmiCec = IHdmiCec::getService(GetParam()); + ASSERT_NE(hdmiCec, nullptr); + ALOGI("%s: getService() for hdmiCec is %s", __func__, + hdmiCec->isRemote() ? "remote" : "local"); + + hdmiCec_death_recipient = new HdmiCecDeathRecipient(); + hdmiCecCallback = new CecCallback(); + ASSERT_NE(hdmiCec_death_recipient, nullptr); + ASSERT_TRUE(hdmiCec->linkToDeath(hdmiCec_death_recipient, 0).isOk()); + } + + std::vector getDeviceTypes() { + std::vector deviceTypes; + FILE* p = popen("getprop ro.hdmi.device_type", "re"); + if (p) { + char* line = NULL; + size_t len = 0; + if (getline(&line, &len, p) > 0) { + std::istringstream stream(line); + std::string number{}; + while (std::getline(stream, number, ',')) { + deviceTypes.push_back(stoi(number)); + } + } + pclose(p); + } + return deviceTypes; + } + + bool hasDeviceType(CecDeviceType type) { + std::vector deviceTypes = getDeviceTypes(); + return std::find(deviceTypes.begin(), deviceTypes.end(), (int)type) != deviceTypes.end(); + } + + class CecCallback : public IHdmiCecCallback { + public: + Return onCecMessage( + const ::android::hardware::tv::cec::V1_0::CecMessage& /* message */) { + return Void(); + } + Return onCecMessage_1_1( + const ::android::hardware::tv::cec::V1_1::CecMessage& /* message */) { + return Void(); + } + Return onHotplugEvent( + const ::android::hardware::tv::cec::V1_0::HotplugEvent& /* event */) { + return Void(); + } + }; + + class HdmiCecDeathRecipient : public hidl_death_recipient { + public: + void serviceDied(uint64_t /*cookie*/, + const android::wp<::android::hidl::base::V1_0::IBase>& /*who*/) override { + FAIL(); + } + }; + + sp hdmiCec; + sp hdmiCecCallback; + sp hdmiCec_death_recipient; +}; + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HdmiCecTest); +INSTANTIATE_TEST_SUITE_P( + PerInstance, HdmiCecTest, + testing::ValuesIn(android::hardware::getAllHalInstanceNames(IHdmiCec::descriptor)), + android::hardware::PrintInstanceNameToString); + +TEST_P(HdmiCecTest, ClearAddLogicalAddress) { + hdmiCec->clearLogicalAddress(); + Return ret = hdmiCec->addLogicalAddress_1_1(CecLogicalAddress::PLAYBACK_3); + EXPECT_EQ(ret, Result::SUCCESS); +} + +TEST_P(HdmiCecTest, PhysicalAddress) { + Result result; + uint16_t addr; + Return ret = hdmiCec->getPhysicalAddress([&result, &addr](Result res, uint16_t paddr) { + result = res; + addr = paddr; + }); + EXPECT_EQ(result, Result::SUCCESS); + if (!hasDeviceType(CecDeviceType::TV)) { + EXPECT_NE(addr, TV_PHYSICAL_ADDRESS); + } +} + +TEST_P(HdmiCecTest, SendMessage) { + CecMessage message; + message.initiator = CecLogicalAddress::PLAYBACK_1; + message.destination = CecLogicalAddress::BROADCAST; + message.body.resize(1); + message.body[0] = 131; + SendMessageResult ret = hdmiCec->sendMessage_1_1(message); + EXPECT_EQ(ret, SendMessageResult::SUCCESS); +} + +TEST_P(HdmiCecTest, CecVersion) { + Return ret = hdmiCec->getCecVersion(); + EXPECT_GE(ret, CEC_VERSION); +} + +TEST_P(HdmiCecTest, SetCallback) { + Return ret = hdmiCec->setCallback_1_1(new CecCallback()); + ASSERT_TRUE(ret.isOk()); +} + +TEST_P(HdmiCecTest, VendorId) { + Return ret = hdmiCec->getVendorId(); + EXPECT_NE(ret, INCORRECT_VENDOR_ID); +} + +TEST_P(HdmiCecTest, GetPortInfo) { + hidl_vec ports; + Return ret = + hdmiCec->getPortInfo([&ports](hidl_vec list) { ports = list; }); + ASSERT_TRUE(ret.isOk()); + bool cecSupportedOnDevice = false; + for (size_t i = 0; i < ports.size(); ++i) { + EXPECT_TRUE((ports[i].type == HdmiPortType::OUTPUT) || + (ports[i].type == HdmiPortType::INPUT)); + if (ports[i].portId == 0) { + ALOGW("%s: Port id should start from 1", __func__); + } + cecSupportedOnDevice = cecSupportedOnDevice | ports[i].cecSupported; + } + EXPECT_NE(cecSupportedOnDevice, false) << "At least one port should support CEC"; +} + +TEST_P(HdmiCecTest, SetOption) { + Return wakeup = hdmiCec->setOption(OptionKey::WAKEUP, false); + ASSERT_TRUE(wakeup.isOk()); + Return enableCec = hdmiCec->setOption(OptionKey::ENABLE_CEC, false); + ASSERT_TRUE(enableCec.isOk()); + Return systemCecControl = hdmiCec->setOption(OptionKey::SYSTEM_CEC_CONTROL, true); + ASSERT_TRUE(systemCecControl.isOk()); + // Restore option keys to their default values + hdmiCec->setOption(OptionKey::WAKEUP, true); + hdmiCec->setOption(OptionKey::ENABLE_CEC, true); + hdmiCec->setOption(OptionKey::SYSTEM_CEC_CONTROL, false); +} + +TEST_P(HdmiCecTest, SetLanguage) { + Return ret = hdmiCec->setLanguage("eng"); + ASSERT_TRUE(ret.isOk()); +} + +TEST_P(HdmiCecTest, EnableAudioReturnChannel) { + hidl_vec ports; + Return ret = + hdmiCec->getPortInfo([&ports](hidl_vec list) { ports = list; }); + for (size_t i = 0; i < ports.size(); ++i) { + if (ports[i].arcSupported) { + Return ret = hdmiCec->enableAudioReturnChannel(ports[i].portId, true); + ASSERT_TRUE(ret.isOk()); + } + } +} + +TEST_P(HdmiCecTest, IsConnected) { + hidl_vec ports; + Return ret = + hdmiCec->getPortInfo([&ports](hidl_vec list) { ports = list; }); + for (size_t i = 0; i < ports.size(); ++i) { + Return ret = hdmiCec->isConnected(ports[i].portId); + EXPECT_TRUE(ret.isOk()); + } +} diff --git a/tv/tuner/1.0/default/Demux.cpp b/tv/tuner/1.0/default/Demux.cpp index 67eff1bd633052fef09149a98e09ba682f9b8b9d..9055a43bd801a25dbaa6019584afbb5cfb6633c0 100644 --- a/tv/tuner/1.0/default/Demux.cpp +++ b/tv/tuner/1.0/default/Demux.cpp @@ -163,6 +163,7 @@ Return Demux::close() { mRecordFilterIds.clear(); mFilters.clear(); mLastUsedFilterId = -1; + mTunerService->removeDemux(mDemuxId); return Result::SUCCESS; } @@ -294,6 +295,11 @@ void Demux::updateFilterOutput(uint16_t filterId, vector data) { mFilters[filterId]->updateFilterOutput(data); } +void Demux::updateMediaFilterOutput(uint16_t filterId, vector data, uint64_t pts) { + updateFilterOutput(filterId, data); + mFilters[filterId]->updatePts(pts); +} + uint16_t Demux::getFilterTpid(uint32_t filterId) { return mFilters[filterId]->getTpid(); } @@ -313,6 +319,12 @@ void Demux::frontendInputThreadLoop() { std::lock_guard lock(mFrontendInputThreadLock); mFrontendInputThreadRunning = true; + if (!mDvrPlayback) { + ALOGW("[Demux] No software Frontend input configured. Ending Frontend thread loop."); + mFrontendInputThreadRunning = false; + return; + } + while (mFrontendInputThreadRunning) { uint32_t efState = 0; status_t status = mDvrPlayback->getDvrEventFlag()->wait( @@ -322,6 +334,12 @@ void Demux::frontendInputThreadLoop() { ALOGD("[Demux] wait for data ready on the playback FMQ"); continue; } + if (mDvrPlayback->getSettings().playback().dataFormat == DataFormat::ES) { + if (!mDvrPlayback->processEsDataOnPlayback(true /*isVirtualFrontend*/, mIsRecording)) { + ALOGE("[Demux] playback es data failed to be filtered. Ending thread"); + break; + } + } // Our current implementation filter the data and write it into the filter FMQ immediately // after the DATA_READY from the VTS/framework if (!mDvrPlayback->readPlaybackFMQ(true /*isVirtualFrontend*/, mIsRecording) || diff --git a/tv/tuner/1.0/default/Demux.h b/tv/tuner/1.0/default/Demux.h index 7f282b250f8902c0f441c6fc4139201b3f96a720..6e93ea32f84f9f06ac52456f1349b786e6488ea3 100644 --- a/tv/tuner/1.0/default/Demux.h +++ b/tv/tuner/1.0/default/Demux.h @@ -87,6 +87,7 @@ class Demux : public IDemux { bool detachRecordFilter(int filterId); Result startFilterHandler(uint32_t filterId); void updateFilterOutput(uint16_t filterId, vector data); + void updateMediaFilterOutput(uint16_t filterId, vector data, uint64_t pts); uint16_t getFilterTpid(uint32_t filterId); void setIsRecording(bool isRecording); void startFrontendInputLoop(); diff --git a/tv/tuner/1.0/default/Dvr.cpp b/tv/tuner/1.0/default/Dvr.cpp index 68e175c17d5b04acfd8f1c1d3d13de645351e4eb..c3edac973eb40168fc68d6c29a1083036c80b5f4 100644 --- a/tv/tuner/1.0/default/Dvr.cpp +++ b/tv/tuner/1.0/default/Dvr.cpp @@ -129,7 +129,7 @@ Return Dvr::stop() { mDvrThreadRunning = false; - std::lock_guard lock(mDvrThreadLock); + lock_guard lock(mDvrThreadLock); mIsRecordStarted = false; mDemux->setIsRecording(false); @@ -155,14 +155,13 @@ bool Dvr::createDvrMQ() { ALOGV("%s", __FUNCTION__); // Create a synchronized FMQ that supports blocking read/write - std::unique_ptr tmpDvrMQ = - std::unique_ptr(new (std::nothrow) DvrMQ(mBufferSize, true)); + unique_ptr tmpDvrMQ = unique_ptr(new (nothrow) DvrMQ(mBufferSize, true)); if (!tmpDvrMQ->isValid()) { ALOGW("[Dvr] Failed to create FMQ of DVR"); return false; } - mDvrMQ = std::move(tmpDvrMQ); + mDvrMQ = move(tmpDvrMQ); if (EventFlag::createEventFlag(mDvrMQ->getEventFlagWord(), &mDvrEventFlag) != OK) { return false; @@ -183,7 +182,7 @@ void* Dvr::__threadLoopPlayback(void* user) { void Dvr::playbackThreadLoop() { ALOGD("[Dvr] playback threadLoop start."); - std::lock_guard lock(mDvrThreadLock); + lock_guard lock(mDvrThreadLock); mDvrThreadRunning = true; while (mDvrThreadRunning) { @@ -195,6 +194,14 @@ void Dvr::playbackThreadLoop() { ALOGD("[Dvr] wait for data ready on the playback FMQ"); continue; } + + if (mDvrSettings.playback().dataFormat == DataFormat::ES) { + if (!processEsDataOnPlayback(false /*isVirtualFrontend*/, false /*isRecording*/)) { + ALOGE("[Dvr] playback es data failed to be filtered. Ending thread"); + break; + } + maySendPlaybackStatusCallback(); + } // Our current implementation filter the data and write it into the filter FMQ immediately // after the DATA_READY from the VTS/framework if (!readPlaybackFMQ(false /*isVirtualFrontend*/, false /*isRecording*/) || @@ -211,7 +218,7 @@ void Dvr::playbackThreadLoop() { } void Dvr::maySendPlaybackStatusCallback() { - std::lock_guard lock(mPlaybackStatusLock); + lock_guard lock(mPlaybackStatusLock); int availableToRead = mDvrMQ->availableToRead(); int availableToWrite = mDvrMQ->availableToWrite(); @@ -263,8 +270,128 @@ bool Dvr::readPlaybackFMQ(bool isVirtualFrontend, bool isRecording) { return true; } +bool Dvr::processEsDataOnPlayback(bool isVirtualFrontend, bool isRecording) { + // Read ES from the DVR FMQ + // Note that currently we only provides ES with metaData in a specific format to be parsed. + // The ES size should be smaller than the Playback FMQ size to avoid reading truncated data. + int size = mDvrMQ->availableToRead(); + vector dataOutputBuffer; + dataOutputBuffer.resize(size); + if (!mDvrMQ->read(dataOutputBuffer.data(), size)) { + return false; + } + + int metaDataSize = size; + int totalFrames = 0; + int videoEsDataSize = 0; + int audioEsDataSize = 0; + int audioPid = 0; + int videoPid = 0; + + vector esMeta; + int videoReadPointer = 0; + int audioReadPointer = 0; + int frameCount = 0; + // Get meta data from the es + for (int i = 0; i < metaDataSize; i++) { + switch (dataOutputBuffer[i]) { + case 'm': + metaDataSize = 0; + getMetaDataValue(i, dataOutputBuffer.data(), metaDataSize); + videoReadPointer = metaDataSize; + continue; + case 'l': + getMetaDataValue(i, dataOutputBuffer.data(), totalFrames); + esMeta.resize(totalFrames); + continue; + case 'V': + getMetaDataValue(i, dataOutputBuffer.data(), videoEsDataSize); + audioReadPointer = metaDataSize + videoEsDataSize; + continue; + case 'A': + getMetaDataValue(i, dataOutputBuffer.data(), audioEsDataSize); + continue; + case 'p': + if (dataOutputBuffer[++i] == 'a') { + getMetaDataValue(i, dataOutputBuffer.data(), audioPid); + } else if (dataOutputBuffer[i] == 'v') { + getMetaDataValue(i, dataOutputBuffer.data(), videoPid); + } + continue; + case 'v': + case 'a': + if (dataOutputBuffer[i + 1] != ',') { + ALOGE("[Dvr] Invalid format meta data."); + return false; + } + esMeta[frameCount] = { + .isAudio = dataOutputBuffer[i] == 'a' ? true : false, + }; + i += 5; // Move to Len + getMetaDataValue(i, dataOutputBuffer.data(), esMeta[frameCount].len); + if (esMeta[frameCount].isAudio) { + esMeta[frameCount].startIndex = audioReadPointer; + audioReadPointer += esMeta[frameCount].len; + } else { + esMeta[frameCount].startIndex = videoReadPointer; + videoReadPointer += esMeta[frameCount].len; + } + i += 4; // move to PTS + getMetaDataValue(i, dataOutputBuffer.data(), esMeta[frameCount].pts); + frameCount++; + continue; + default: + continue; + } + } + + if (frameCount != totalFrames) { + ALOGE("[Dvr] Invalid meta data, frameCount=%d, totalFrames reported=%d", frameCount, + totalFrames); + return false; + } + + if (metaDataSize + audioEsDataSize + videoEsDataSize != size) { + ALOGE("[Dvr] Invalid meta data, metaSize=%d, videoSize=%d, audioSize=%d, totolSize=%d", + metaDataSize, videoEsDataSize, audioEsDataSize, size); + return false; + } + + // Read es raw data from the FMQ per meta data built previously + vector frameData; + map>::iterator it; + int pid = 0; + for (int i = 0; i < totalFrames; i++) { + frameData.resize(esMeta[i].len); + pid = esMeta[i].isAudio ? audioPid : videoPid; + memcpy(frameData.data(), dataOutputBuffer.data() + esMeta[i].startIndex, esMeta[i].len); + // Send to the media filter + if (isVirtualFrontend && isRecording) { + // TODO validate record + mDemux->sendFrontendInputToRecord(frameData); + } else { + for (it = mFilters.begin(); it != mFilters.end(); it++) { + if (pid == mDemux->getFilterTpid(it->first)) { + mDemux->updateMediaFilterOutput(it->first, frameData, + static_cast(esMeta[i].pts)); + startFilterDispatcher(isVirtualFrontend, isRecording); + } + } + } + } + + return true; +} + +void Dvr::getMetaDataValue(int& index, uint8_t* dataOutputBuffer, int& value) { + index += 2; // Move the pointer across the ":" to the value + while (dataOutputBuffer[index] != ',' && dataOutputBuffer[index] != '\n') { + value = ((dataOutputBuffer[index++] - 48) + value * 10); + } +} + void Dvr::startTpidFilter(vector data) { - std::map>::iterator it; + map>::iterator it; for (it = mFilters.begin(); it != mFilters.end(); it++) { uint16_t pid = ((data[1] & 0x1f) << 8) | ((data[2] & 0xff)); if (DEBUG_DVR) { @@ -285,7 +412,7 @@ bool Dvr::startFilterDispatcher(bool isVirtualFrontend, bool isRecording) { } } - std::map>::iterator it; + map>::iterator it; // Handle the output data per filter type for (it = mFilters.begin(); it != mFilters.end(); it++) { if (mDemux->startFilterHandler(it->first) != Result::SUCCESS) { @@ -296,8 +423,8 @@ bool Dvr::startFilterDispatcher(bool isVirtualFrontend, bool isRecording) { return true; } -bool Dvr::writeRecordFMQ(const std::vector& data) { - std::lock_guard lock(mWriteLock); +bool Dvr::writeRecordFMQ(const vector& data) { + lock_guard lock(mWriteLock); if (mRecordStatus == RecordStatus::OVERFLOW) { ALOGW("[Dvr] stops writing and wait for the client side flushing."); return true; @@ -313,7 +440,7 @@ bool Dvr::writeRecordFMQ(const std::vector& data) { } void Dvr::maySendRecordStatusCallback() { - std::lock_guard lock(mRecordStatusLock); + lock_guard lock(mRecordStatusLock); int availableToRead = mDvrMQ->availableToRead(); int availableToWrite = mDvrMQ->availableToWrite(); @@ -352,4 +479,4 @@ bool Dvr::removePlaybackFilter(uint32_t filterId) { } // namespace tuner } // namespace tv } // namespace hardware -} // namespace android \ No newline at end of file +} // namespace android diff --git a/tv/tuner/1.0/default/Dvr.h b/tv/tuner/1.0/default/Dvr.h index a63a25670cc6b7b3f247c88416999e7e37d85534..30695866ca7d2c0c39d0c9e69e890c77a4d6a6b7 100644 --- a/tv/tuner/1.0/default/Dvr.h +++ b/tv/tuner/1.0/default/Dvr.h @@ -44,6 +44,13 @@ using ::android::hardware::tv::tuner::V1_0::Result; using DvrMQ = MessageQueue; +struct MediaEsMetaData { + bool isAudio; + int startIndex; + int len; + int pts; +}; + class Demux; class Filter; class Frontend; @@ -84,8 +91,10 @@ class Dvr : public IDvr { bool addPlaybackFilter(uint32_t filterId, sp filter); bool removePlaybackFilter(uint32_t filterId); bool readPlaybackFMQ(bool isVirtualFrontend, bool isRecording); + bool processEsDataOnPlayback(bool isVirtualFrontend, bool isRecording); bool startFilterDispatcher(bool isVirtualFrontend, bool isRecording); EventFlag* getDvrEventFlag(); + DvrSettings getSettings() { return mDvrSettings; } private: // Demux service @@ -98,6 +107,7 @@ class Dvr : public IDvr { void deleteEventFlag(); bool readDataFromMQ(); + void getMetaDataValue(int& index, uint8_t* dataOutputBuffer, int& value); void maySendPlaybackStatusCallback(); void maySendRecordStatusCallback(); PlaybackStatus checkPlaybackStatusChange(uint32_t availableToWrite, uint32_t availableToRead, diff --git a/tv/tuner/1.0/default/Filter.cpp b/tv/tuner/1.0/default/Filter.cpp index a124a606ee16291482531842471bbe429928c704..7b50f8ce3807032b016e7785c4c30ffad897c987 100644 --- a/tv/tuner/1.0/default/Filter.cpp +++ b/tv/tuner/1.0/default/Filter.cpp @@ -319,6 +319,11 @@ void Filter::updateFilterOutput(vector data) { mFilterOutput.insert(mFilterOutput.end(), data.begin(), data.end()); } +void Filter::updatePts(uint64_t pts) { + std::lock_guard lock(mFilterOutputLock); + mPts = pts; +} + void Filter::updateRecordOutput(vector data) { std::lock_guard lock(mRecordFilterOutputLock); mRecordFilterOutput.insert(mRecordFilterOutput.end(), data.begin(), data.end()); @@ -462,6 +467,11 @@ Result Filter::startMediaFilterHandler() { if (mFilterOutput.empty()) { return Result::SUCCESS; } + + if (mPts) { + return createMediaFilterEventWithIon(mFilterOutput); + } + for (int i = 0; i < mFilterOutput.size(); i += 188) { if (mPesSizeLeft == 0) { uint32_t prefix = (mFilterOutput[i + 4] << 16) | (mFilterOutput[i + 5] << 8) | @@ -495,46 +505,7 @@ Result Filter::startMediaFilterHandler() { continue; } - int av_fd = createAvIonFd(mPesOutput.size()); - if (av_fd == -1) { - return Result::UNKNOWN_ERROR; - } - // copy the filtered data to the buffer - uint8_t* avBuffer = getIonBuffer(av_fd, mPesOutput.size()); - if (avBuffer == NULL) { - return Result::UNKNOWN_ERROR; - } - memcpy(avBuffer, mPesOutput.data(), mPesOutput.size() * sizeof(uint8_t)); - - native_handle_t* nativeHandle = createNativeHandle(av_fd); - if (nativeHandle == NULL) { - return Result::UNKNOWN_ERROR; - } - hidl_handle handle; - handle.setTo(nativeHandle, /*shouldOwn=*/true); - - // Create a dataId and add a pair into the dataId2Avfd map - uint64_t dataId = mLastUsedDataId++ /*createdUID*/; - mDataId2Avfd[dataId] = dup(av_fd); - - // Create mediaEvent and send callback - DemuxFilterMediaEvent mediaEvent; - mediaEvent = { - .avMemory = std::move(handle), - .dataLength = static_cast(mPesOutput.size()), - .avDataId = dataId, - }; - int size = mFilterEvent.events.size(); - mFilterEvent.events.resize(size + 1); - mFilterEvent.events[size].media(mediaEvent); - - // Clear and log - mPesOutput.clear(); - mAvBufferCopyCount = 0; - ::close(av_fd); - if (DEBUG_FILTER) { - ALOGD("[Filter] assembled av data length %d", mediaEvent.dataLength); - } + createMediaFilterEventWithIon(mPesOutput); } mFilterOutput.clear(); @@ -542,6 +513,54 @@ Result Filter::startMediaFilterHandler() { return Result::SUCCESS; } +Result Filter::createMediaFilterEventWithIon(vector output) { + int av_fd = createAvIonFd(output.size()); + if (av_fd == -1) { + return Result::UNKNOWN_ERROR; + } + // copy the filtered data to the buffer + uint8_t* avBuffer = getIonBuffer(av_fd, output.size()); + if (avBuffer == NULL) { + return Result::UNKNOWN_ERROR; + } + memcpy(avBuffer, output.data(), output.size() * sizeof(uint8_t)); + + native_handle_t* nativeHandle = createNativeHandle(av_fd); + if (nativeHandle == NULL) { + return Result::UNKNOWN_ERROR; + } + hidl_handle handle; + handle.setTo(nativeHandle, /*shouldOwn=*/true); + + // Create a dataId and add a pair into the dataId2Avfd map + uint64_t dataId = mLastUsedDataId++ /*createdUID*/; + mDataId2Avfd[dataId] = dup(av_fd); + + // Create mediaEvent and send callback + DemuxFilterMediaEvent mediaEvent; + mediaEvent = { + .avMemory = std::move(handle), + .dataLength = static_cast(output.size()), + .avDataId = dataId, + }; + if (mPts) { + mediaEvent.pts = mPts; + mPts = 0; + } + int size = mFilterEvent.events.size(); + mFilterEvent.events.resize(size + 1); + mFilterEvent.events[size].media(mediaEvent); + + // Clear and log + output.clear(); + mAvBufferCopyCount = 0; + ::close(av_fd); + if (DEBUG_FILTER) { + ALOGD("[Filter] av data length %d", mediaEvent.dataLength); + } + return Result::SUCCESS; +} + Result Filter::startRecordFilterHandler() { std::lock_guard lock(mRecordFilterOutputLock); if (mRecordFilterOutput.empty()) { diff --git a/tv/tuner/1.0/default/Filter.h b/tv/tuner/1.0/default/Filter.h index 9386dca1a21d9c9d2a66614466b091f086e2d17e..9b18a66c077b3df5c5e9141a8c1eb9f13df550ff 100644 --- a/tv/tuner/1.0/default/Filter.h +++ b/tv/tuner/1.0/default/Filter.h @@ -84,6 +84,7 @@ class Filter : public IFilter { uint16_t getTpid(); void updateFilterOutput(vector data); void updateRecordOutput(vector data); + void updatePts(uint64_t pts); Result startFilterHandler(); Result startRecordFilterHandler(); void attachFilterToRecord(const sp dvr); @@ -116,6 +117,7 @@ class Filter : public IFilter { bool mIsDataSourceDemux = true; vector mFilterOutput; vector mRecordFilterOutput; + uint64_t mPts = 0; unique_ptr mFilterMQ; bool mIsUsingFMQ = false; EventFlag* mFilterEventFlag; @@ -172,6 +174,7 @@ class Filter : public IFilter { int createAvIonFd(int size); uint8_t* getIonBuffer(int fd, int size); native_handle_t* createNativeHandle(int fd); + Result createMediaFilterEventWithIon(vector output); /** * Lock to protect writes to the FMQs diff --git a/tv/tuner/1.0/default/Frontend.cpp b/tv/tuner/1.0/default/Frontend.cpp index 8bf0ec5353d6a81e5c5b980b69f17b76cff9de10..6561c92cafdc06f40e31d10288ef9a2bbfa01b79 100644 --- a/tv/tuner/1.0/default/Frontend.cpp +++ b/tv/tuner/1.0/default/Frontend.cpp @@ -42,6 +42,7 @@ Return Frontend::close() { // Reset callback mCallback = nullptr; mIsLocked = false; + mTunerService->removeFrontend(mId); return Result::SUCCESS; } diff --git a/tv/tuner/1.0/default/Tuner.cpp b/tv/tuner/1.0/default/Tuner.cpp index 0430646d982d9332e3288eed33ef6fc934dfea23..c4f610ee23c7b35cf049318cf2d69d74f4b7c426 100644 --- a/tv/tuner/1.0/default/Tuner.cpp +++ b/tv/tuner/1.0/default/Tuner.cpp @@ -37,7 +37,6 @@ Tuner::Tuner() { // Static Frontends array to maintain local frontends information // Array index matches their FrontendId in the default impl mFrontendSize = 8; - mFrontends.resize(mFrontendSize); mFrontends[0] = new Frontend(FrontendType::DVBT, 0, this); mFrontends[1] = new Frontend(FrontendType::ATSC, 1, this); mFrontends[2] = new Frontend(FrontendType::DVBC, 2, this); @@ -48,7 +47,6 @@ Tuner::Tuner() { mFrontends[7] = new Frontend(FrontendType::ATSC, 7, this); FrontendInfo::FrontendCapabilities caps; - mFrontendCaps.resize(mFrontendSize); caps = FrontendInfo::FrontendCapabilities(); caps.dvbtCaps(FrontendDvbtCapabilities()); mFrontendCaps[0] = caps; @@ -238,6 +236,21 @@ void Tuner::setFrontendAsDemuxSource(uint32_t frontendId, uint32_t demuxId) { } } +void Tuner::removeDemux(uint32_t demuxId) { + map::iterator it; + for (it = mFrontendToDemux.begin(); it != mFrontendToDemux.end(); it++) { + if (it->second == demuxId) { + it = mFrontendToDemux.erase(it); + break; + } + } + mDemuxes.erase(demuxId); +} + +void Tuner::removeFrontend(uint32_t frontendId) { + mFrontendToDemux.erase(frontendId); +} + void Tuner::frontendStopTune(uint32_t frontendId) { map::iterator it = mFrontendToDemux.find(frontendId); uint32_t demuxId; diff --git a/tv/tuner/1.0/default/Tuner.h b/tv/tuner/1.0/default/Tuner.h index 5de568f0720d9805e478d1594fcb83eb234c7735..1c09d6c68419ed5910e62834e608d7d4259b197a 100644 --- a/tv/tuner/1.0/default/Tuner.h +++ b/tv/tuner/1.0/default/Tuner.h @@ -65,14 +65,16 @@ class Tuner : public ITuner { void frontendStartTune(uint32_t frontendId); void frontendStopTune(uint32_t frontendId); + void removeDemux(uint32_t demuxId); + void removeFrontend(uint32_t frontendId); private: virtual ~Tuner(); // Static mFrontends array to maintain local frontends information - vector> mFrontends; - vector mFrontendCaps; - std::map mFrontendToDemux; - std::map> mDemuxes; + map> mFrontends; + map mFrontendCaps; + map mFrontendToDemux; + map> mDemuxes; // To maintain how many Frontends we have int mFrontendSize; // The last used demux id. Initial value is -1. diff --git a/tv/tuner/1.0/vts/functional/AndroidTest.xml b/tv/tuner/1.0/vts/functional/AndroidTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..18c2b590939d42c549ddd875a2a0f56e48edcb5c --- /dev/null +++ b/tv/tuner/1.0/vts/functional/AndroidTest.xml @@ -0,0 +1,35 @@ + + + + diff --git a/tv/tuner/1.0/vts/functional/FilterTests.cpp b/tv/tuner/1.0/vts/functional/FilterTests.cpp index a354c785a5ef15859155e8a0cc84dd4b72ced28d..f47024526da636d238eef304220ce13bbb1fbfbf 100644 --- a/tv/tuner/1.0/vts/functional/FilterTests.cpp +++ b/tv/tuner/1.0/vts/functional/FilterTests.cpp @@ -70,45 +70,40 @@ void FilterCallback::filterThreadLoop(DemuxFilterEvent& /* event */) { } bool FilterCallback::readFilterEventData() { - if (mFilterMQ == NULL) { - ALOGW("[vts] FMQ is not configured and does not need to be tested."); - return true; - } bool result = false; DemuxFilterEvent filterEvent = mFilterEvent; ALOGW("[vts] reading from filter FMQ or buffer %d", mFilterId); // todo separate filter handlers - for (int i = 0; i < filterEvent.events.size(); i++) { - switch (mFilterEventType) { - case FilterEventType::SECTION: - mDataLength = filterEvent.events[i].section().dataLength; - break; - case FilterEventType::PES: - mDataLength = filterEvent.events[i].pes().dataLength; - break; - case FilterEventType::MEDIA: - return dumpAvData(filterEvent.events[i].media()); - case FilterEventType::RECORD: - break; - case FilterEventType::MMTPRECORD: + for (auto event : filterEvent.events) { + switch (event.getDiscriminator()) { + case DemuxFilterEvent::Event::hidl_discriminator::section: + mDataLength = event.section().dataLength; break; - case FilterEventType::DOWNLOAD: + case DemuxFilterEvent::Event::hidl_discriminator::pes: + mDataLength = event.pes().dataLength; break; + case DemuxFilterEvent::Event::hidl_discriminator::media: + return dumpAvData(event.media()); + case DemuxFilterEvent::Event::hidl_discriminator::tsRecord: + return readRecordData(event.tsRecord()); default: - break; + continue; } // EXPECT_TRUE(mDataLength == goldenDataOutputBuffer.size()) << "buffer size does not // match"; - - mDataOutputBuffer.resize(mDataLength); - result = mFilterMQ->read(mDataOutputBuffer.data(), mDataLength); - EXPECT_TRUE(result) << "can't read from Filter MQ"; + if (mFilterMQ != NULL) { + mDataOutputBuffer.resize(mDataLength); + result = mFilterMQ->read(mDataOutputBuffer.data(), mDataLength); + EXPECT_TRUE(result) << "can't read from Filter MQ"; + } /*for (int i = 0; i < mDataLength; i++) { EXPECT_TRUE(goldenDataOutputBuffer[i] == mDataOutputBuffer[i]) << "data does not match"; }*/ } - mFilterMQEventFlag->wake(static_cast(DemuxQueueNotifyBits::DATA_CONSUMED)); + if (mFilterMQ != NULL) { + mFilterMQEventFlag->wake(static_cast(DemuxQueueNotifyBits::DATA_CONSUMED)); + } return result; } @@ -132,6 +127,11 @@ bool FilterCallback::dumpAvData(DemuxFilterMediaEvent event) { return true; } +bool FilterCallback::readRecordData(DemuxFilterTsRecordEvent event) { + ALOGD("[vts] got DemuxFilterTsRecordEvent with pid=%d.", event.pid.tPid()); + return true; +} + AssertionResult FilterTests::openFilterInDemux(DemuxFilterType type, uint32_t bufferSize) { Result status; EXPECT_TRUE(mDemux) << "Test with openDemux first."; @@ -145,11 +145,6 @@ AssertionResult FilterTests::openFilterInDemux(DemuxFilterType type, uint32_t bu mFilter = filter; status = result; }); - - if (status == Result::SUCCESS) { - mFilterCallback->setFilterEventType(getFilterEventType(type)); - } - return AssertionResult(status == Result::SUCCESS); } diff --git a/tv/tuner/1.0/vts/functional/FilterTests.h b/tv/tuner/1.0/vts/functional/FilterTests.h index 75c59b3670f20f0ee78b2a966a7f05427c166de2..7bc4832171fc63c138db9d5b05880b0f2397d744 100644 --- a/tv/tuner/1.0/vts/functional/FilterTests.h +++ b/tv/tuner/1.0/vts/functional/FilterTests.h @@ -50,6 +50,7 @@ using android::hardware::tv::tuner::V1_0::DemuxFilterSectionEvent; using android::hardware::tv::tuner::V1_0::DemuxFilterSectionSettings; using android::hardware::tv::tuner::V1_0::DemuxFilterSettings; using android::hardware::tv::tuner::V1_0::DemuxFilterStatus; +using android::hardware::tv::tuner::V1_0::DemuxFilterTsRecordEvent; using android::hardware::tv::tuner::V1_0::DemuxFilterType; using android::hardware::tv::tuner::V1_0::DemuxQueueNotifyBits; using android::hardware::tv::tuner::V1_0::DemuxTsFilterSettings; @@ -65,17 +66,6 @@ using ::testing::AssertionResult; using namespace std; -enum FilterEventType : uint8_t { - UNDEFINED, - SECTION, - MEDIA, - PES, - RECORD, - MMTPRECORD, - DOWNLOAD, - TEMI, -}; - using FilterMQ = MessageQueue; using MQDesc = MQDescriptorSync; @@ -103,7 +93,6 @@ class FilterCallback : public IFilterCallback { void setFilterId(uint32_t filterId) { mFilterId = filterId; } void setFilterInterface(sp filter) { mFilter = filter; } - void setFilterEventType(FilterEventType type) { mFilterEventType = type; } void testFilterDataOutput(); @@ -115,6 +104,7 @@ class FilterCallback : public IFilterCallback { void updateGoldenOutputMap(string goldenOutputFile); bool readFilterEventData(); bool dumpAvData(DemuxFilterMediaEvent event); + bool readRecordData(DemuxFilterTsRecordEvent event); private: struct FilterThreadArgs { @@ -128,7 +118,6 @@ class FilterCallback : public IFilterCallback { uint32_t mFilterId; sp mFilter; - FilterEventType mFilterEventType; std::unique_ptr mFilterMQ; EventFlag* mFilterMQEventFlag; DemuxFilterEvent mFilterEvent; @@ -166,53 +155,6 @@ class FilterTests { AssertionResult closeFilter(uint32_t filterId); AssertionResult closeTimeFilter(); - FilterEventType getFilterEventType(DemuxFilterType type) { - FilterEventType eventType = FilterEventType::UNDEFINED; - switch (type.mainType) { - case DemuxFilterMainType::TS: - switch (type.subType.tsFilterType()) { - case DemuxTsFilterType::UNDEFINED: - break; - case DemuxTsFilterType::SECTION: - eventType = FilterEventType::SECTION; - break; - case DemuxTsFilterType::PES: - eventType = FilterEventType::PES; - break; - case DemuxTsFilterType::TS: - break; - case DemuxTsFilterType::AUDIO: - case DemuxTsFilterType::VIDEO: - eventType = FilterEventType::MEDIA; - break; - case DemuxTsFilterType::PCR: - break; - case DemuxTsFilterType::RECORD: - eventType = FilterEventType::RECORD; - break; - case DemuxTsFilterType::TEMI: - eventType = FilterEventType::TEMI; - break; - } - break; - case DemuxFilterMainType::MMTP: - /*mmtpSettings*/ - break; - case DemuxFilterMainType::IP: - /*ipSettings*/ - break; - case DemuxFilterMainType::TLV: - /*tlvSettings*/ - break; - case DemuxFilterMainType::ALP: - /*alpSettings*/ - break; - default: - break; - } - return eventType; - } - protected: static AssertionResult failure() { return ::testing::AssertionFailure(); } diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h index e2406042df708144576d22f7df515334be7df96b..7243a42c60384b14bf1e0463054b1b18672cac18 100644 --- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h +++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h @@ -32,7 +32,8 @@ static AssertionResult success() { namespace { bool initConfiguration() { - if (!TunerTestingConfigReader::checkConfigFileExists()) { + TunerTestingConfigReader1_0::setConfigFilePath(configFilePath); + if (!TunerTestingConfigReader1_0::checkConfigFileExists()) { return false; } initFrontendConfig(); @@ -78,7 +79,6 @@ class TunerFrontendHidlTest : public testing::TestWithParam { FrontendTests mFrontendTests; }; -// TODO remove from the allow list once the cf tv target is enabled for testing GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerFrontendHidlTest); class TunerLnbHidlTest : public testing::TestWithParam { @@ -100,7 +100,6 @@ class TunerLnbHidlTest : public testing::TestWithParam { LnbTests mLnbTests; }; -// TODO remove from the allow list once the cf tv target is enabled for testing GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerLnbHidlTest); class TunerDemuxHidlTest : public testing::TestWithParam { @@ -126,7 +125,6 @@ class TunerDemuxHidlTest : public testing::TestWithParam { FilterTests mFilterTests; }; -// TODO remove from the allow list once the cf tv target is enabled for testing GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerDemuxHidlTest); class TunerFilterHidlTest : public testing::TestWithParam { @@ -178,7 +176,6 @@ class TunerFilterHidlTest : public testing::TestWithParam { FilterTests mFilterTests; }; -// TODO remove from the allow list once the cf tv target is enabled for testing GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerFilterHidlTest); class TunerBroadcastHidlTest : public testing::TestWithParam { @@ -217,7 +214,6 @@ class TunerBroadcastHidlTest : public testing::TestWithParam { uint32_t* mLnbId = nullptr; }; -// TODO remove from the allow list once the cf tv target is enabled for testing GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerBroadcastHidlTest); class TunerPlaybackHidlTest : public testing::TestWithParam { @@ -249,7 +245,6 @@ class TunerPlaybackHidlTest : public testing::TestWithParam { void playbackSingleFilterTest(FilterConfig filterConf, DvrConfig dvrConf); }; -// TODO remove from the allow list once the cf tv target is enabled for testing GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerPlaybackHidlTest); class TunerRecordHidlTest : public testing::TestWithParam { @@ -289,7 +284,6 @@ class TunerRecordHidlTest : public testing::TestWithParam { uint32_t* mLnbId = nullptr; }; -// TODO remove from the allow list once the cf tv target is enabled for testing GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerRecordHidlTest); class TunerDescramblerHidlTest : public testing::TestWithParam { @@ -326,6 +320,5 @@ class TunerDescramblerHidlTest : public testing::TestWithParam { DvrTests mDvrTests; }; -// TODO remove from the allow list once the cf tv target is enabled for testing GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerDescramblerHidlTest); } // namespace diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h index 8328e0c6c8fd67bf419748bf674d0a23cf309bbd..2cea18126821e60c7040a1b20c87be29d44e1844 100644 --- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h +++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h @@ -21,7 +21,7 @@ #include #include -#include "../../../config/TunerTestingConfigReader.h" +#include "../../../config/TunerTestingConfigReaderV1_0.h" using android::hardware::tv::tuner::V1_0::DemuxFilterMainType; using android::hardware::tv::tuner::V1_0::DemuxTsFilterType; @@ -39,6 +39,8 @@ using namespace android::media::tuner::testing::configuration::V1_0; const uint32_t FMQ_SIZE_4M = 0x400000; const uint32_t FMQ_SIZE_16M = 0x1000000; +const string configFilePath = "/vendor/etc/tuner_vts_config_1_0.xml"; + #define FILTER_MAIN_TYPE_BIT_COUNT 5 // Hardware configs @@ -85,7 +87,7 @@ inline void initFrontendConfig() { frontendMap[defaultFeId].isSoftwareFe = true; // Read customized config - TunerTestingConfigReader::readFrontendConfig1_0(frontendMap); + TunerTestingConfigReader1_0::readFrontendConfig1_0(frontendMap); }; inline void initFilterConfig() { @@ -107,44 +109,44 @@ inline void initFilterConfig() { filterMap[defaultAudioFilterId].settings.ts().filterSettings.av({.isPassthrough = false}); // Read customized config - TunerTestingConfigReader::readFilterConfig1_0(filterMap); + TunerTestingConfigReader1_0::readFilterConfig1_0(filterMap); }; /** Config all the dvrs that would be used in the tests */ inline void initDvrConfig() { // Read customized config - TunerTestingConfigReader::readDvrConfig1_0(dvrMap); + TunerTestingConfigReader1_0::readDvrConfig1_0(dvrMap); }; /** Config all the lnbs that would be used in the tests */ inline void initLnbConfig() { // Read customized config - TunerTestingConfigReader::readLnbConfig1_0(lnbMap); - TunerTestingConfigReader::readDiseqcMessages(diseqcMsgMap); + TunerTestingConfigReader1_0::readLnbConfig1_0(lnbMap); + TunerTestingConfigReader1_0::readDiseqcMessages(diseqcMsgMap); }; /** Config all the time filters that would be used in the tests */ inline void initTimeFilterConfig() { // Read customized config - TunerTestingConfigReader::readTimeFilterConfig1_0(timeFilterMap); + TunerTestingConfigReader1_0::readTimeFilterConfig1_0(timeFilterMap); }; /** Config all the descramblers that would be used in the tests */ inline void initDescramblerConfig() { // Read customized config - TunerTestingConfigReader::readDescramblerConfig1_0(descramblerMap); + TunerTestingConfigReader1_0::readDescramblerConfig1_0(descramblerMap); }; /** Read the vendor configurations of which hardware to use for each test cases/data flows */ inline void connectHardwaresToTestCases() { - TunerTestingConfigReader::connectLiveBroadcast(live); - TunerTestingConfigReader::connectScan(scan); - TunerTestingConfigReader::connectDvrPlayback(playback); - TunerTestingConfigReader::connectDvrRecord(record); - TunerTestingConfigReader::connectDescrambling(descrambling); - TunerTestingConfigReader::connectLnbLive(lnbLive); - TunerTestingConfigReader::connectLnbRecord(lnbRecord); - TunerTestingConfigReader::connectTimeFilter(timeFilter); + TunerTestingConfigReader1_0::connectLiveBroadcast(live); + TunerTestingConfigReader1_0::connectScan(scan); + TunerTestingConfigReader1_0::connectDvrPlayback(playback); + TunerTestingConfigReader1_0::connectDvrRecord(record); + TunerTestingConfigReader1_0::connectDescrambling(descrambling); + TunerTestingConfigReader1_0::connectLnbLive(lnbLive); + TunerTestingConfigReader1_0::connectLnbRecord(lnbRecord); + TunerTestingConfigReader1_0::connectTimeFilter(timeFilter); }; inline bool validateConnections() { @@ -215,9 +217,9 @@ inline bool validateConnections() { } bool filterIsValid = (live.hasFrontendConnection) - ? filterMap.find(live.audioFilterId) != filterMap.end() && - filterMap.find(live.videoFilterId) != filterMap.end() - : true; + ? filterMap.find(live.audioFilterId) != filterMap.end() && + filterMap.find(live.videoFilterId) != filterMap.end() + : true; filterIsValid &= playback.support ? (filterMap.find(playback.audioFilterId) != filterMap.end() && filterMap.find(playback.videoFilterId) != filterMap.end()) diff --git a/tv/tuner/1.1/Android.bp b/tv/tuner/1.1/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..40bea6f7c81704938c534714f0bb8c2b633cb21d --- /dev/null +++ b/tv/tuner/1.1/Android.bp @@ -0,0 +1,30 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +hidl_interface { + name: "android.hardware.tv.tuner@1.1", + root: "android.hardware", + srcs: [ + "IFilter.hal", + "IFrontend.hal", + "IFilterCallback.hal", + "IFrontendCallback.hal", + "ITuner.hal", + "types.hal", + ], + interfaces: [ + "android.hidl.base@1.0", + "android.hidl.safe_union@1.0", + "android.hardware.tv.tuner@1.0", + ], + gen_java: false, + gen_java_constants: true, +} diff --git a/tv/tuner/1.1/IFilter.hal b/tv/tuner/1.1/IFilter.hal new file mode 100644 index 0000000000000000000000000000000000000000..1e941143dfd8d7d57914d6b28d40ece28fcc598c --- /dev/null +++ b/tv/tuner/1.1/IFilter.hal @@ -0,0 +1,107 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.tv.tuner@1.1; + +import @1.0::IFilter; +import @1.0::Result; + +/** + * The Filter is used to filter wanted data according to the filter's + * configuration. + * + * To access the v1.1 IFilter APIs, the implementation can cast the IFilter + * interface returned from the @1.0::IDemux openFilter into a v1.1 IFiler + * using V1_1::IFilter::castFrom(V1_0::IFilter). + * + * Note that reconfiguring Filter must happen after the Filter is stopped. + */ +interface IFilter extends @1.0::IFilter { + /** + * Get the 64-bit filter Id. This id is 32-bit in Tuner HAL 1.0. + * + * It is used by the client to ask the hardware resource id for the filter. + * + * @return result Result status of the operation. + * SUCCESS if successful, + * INVALID_STATE if failed for wrong state. + * UNKNOWN_ERROR if failed for other reasons. + * @return filterId the hardware resource Id for the filter. + */ + getId64Bit() generates (Result result, uint64_t filterId); + + /** + * Configure additional Context ID on the IP filter. + * + * @param ipCid Context Id of the IP filter. + * @return result Result status of the operation. + * SUCCESS if successful, + * INVALID_STATE if failed for wrong state. + * UNKNOWN_ERROR if failed for other reasons. + */ + configureIpCid(uint32_t ipCid) generates (Result result); + + /** + * Get the shared AV memory handle. Use IFilter.releaseAvHandle to release the handle. + * + * When media filters are opened, call this API to initialize the share memory handle if it's + * needed. + * + * If DemuxFilterMediaEvent.avMemory contains file descriptor, share memory should be ignored. + * + * @return avMemory A handle associated to the shared memory for audio or video. + * avMemory.data[0] is normally an fd for ION memory. When the avMemory->numFd is 0, the + * share memory is not initialized and does not contain valid fd. + * avMemory.data[avMemory.numFds] is an index used as a parameter of + * C2DataIdInfo to build C2 buffer in Codec. No C2 buffer would be created if the index + * does not exist. + * @return avMemSize the size of the shared av memory. It should be ignored when the share + * memory is not initialized. + */ + getAvSharedHandle() generates (Result result, handle avMemory, uint64_t avMemSize); + + /** + * Configure A/V filter’s stream type. This API only applies to A/V filters. + * + * @param avStreamType the stream type for A/V. + * @return return result Result status of the operation. + * SUCCESS if successful, + * INVALID_STATE if configure can't be applied, + * UNKNOWN_ERROR if failed for other reasons. + */ + configureAvStreamType(AvStreamType avStreamType) generates (Result result); + + /** + * Configure the monitor event. + * + * The event for Scrambling Status should be sent at the following two scenarios: + * 1. When this method is called, the first detected scrambling status should be sent. + * 2. When the Scrambling status transits into different status, event should be sent. + * + * The event for IP CID change should be sent at the following two scenarios: + * 1. When this method is called, the first detected CID for the IP should be sent. + * 2. When the CID is changed to different value for the IP filter, event should be sent. + * + * @param monitorEventypes the events to monitor. Set corresponding bit of the event to monitor. + * Reset to stop monitoring. + * @return result Result status of the operation. + * SUCCESS if successful, + * INVALID_STATE if configure can't be applied, + * UNKNOWN_ERROR if failed for other reasons. + */ + configureMonitorEvent(bitfield monitorEventTypes) + generates (Result result); +}; diff --git a/tv/tuner/1.1/IFilterCallback.hal b/tv/tuner/1.1/IFilterCallback.hal new file mode 100644 index 0000000000000000000000000000000000000000..23ae84435410d6fc22535189e744c26f84654dc0 --- /dev/null +++ b/tv/tuner/1.1/IFilterCallback.hal @@ -0,0 +1,32 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.tv.tuner@1.1; + +import @1.0::IFilterCallback; +import @1.0::DemuxFilterEvent; +import DemuxFilterEventExt; + +interface IFilterCallback extends @1.0::IFilterCallback { + /** + * Notify the client that a new filter event happened. + * + * @param filterEvent a v1_0 filter event. + * @param filterEventExt a v1_1 extended filter event. Send an empty filterEvent along with + * startId or scramblingStatus filterEventExt + */ + oneway onFilterEvent_1_1(DemuxFilterEvent filterEvent, DemuxFilterEventExt filterEventExt); +}; diff --git a/tv/tuner/1.1/IFrontend.hal b/tv/tuner/1.1/IFrontend.hal new file mode 100644 index 0000000000000000000000000000000000000000..63f06558d54cbf5a132aa7b7b9023b3159a599d5 --- /dev/null +++ b/tv/tuner/1.1/IFrontend.hal @@ -0,0 +1,112 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.tv.tuner@1.1; + +import @1.0::FrontendScanType; +import @1.0::FrontendSettings; +import @1.0::IFrontend; +import @1.0::Result; + +/** + * A Tuner Frontend is used to tune to a frequency and lock signal. + * + * IFrontend provides a bit stream to the Tuner Demux interface. + */ +interface IFrontend extends @1.0::IFrontend { + /** + * Tunes the frontend to using the settings given. + * + * This locks the frontend to a frequency by providing signal + * delivery information. If previous tuning isn't completed, this call MUST + * stop previous tuning, and start a new tuning. + * Tune is an async call, with LOCKED or NO_SIGNAL events sent via callback. + * + * @param settings Signal delivery information the frontend uses to + * search and lock the signal. + * @param settingsExt1_1 v1_1 Extended information that would be used in the 1.1 Frontend to + * search and lock the signal in a better way. + * + * @return result Result status of the operation. + * SUCCESS if successful, + * INVALID_STATE if tuning can't be applied at current stage, + * UNKNOWN_ERROR if tuning failed for other reasons. + */ + tune_1_1(FrontendSettings settings, FrontendSettingsExt1_1 settingsExt1_1) + generates (Result result); + + /** + * Scan the frontend to use the settings given. + * + * This uses the frontend to start a scan from signal delivery information. + * If previous scan isn't completed, this call MUST stop previous scan, + * and start a new scan. + * Scan is an async call, with FrontendScanMessage sent via callback. + * + * @param settings Signal delivery information which the frontend uses to + * scan the signal. + * @param type the type which the frontend uses to scan the signal. + * @param settingsExt1_1 v1_1 Extended information that would be used in the 1.1 Frontend to + * search and lock the signal in a better way. + * @return result Result status of the operation. + * SUCCESS if successful, + * INVALID_STATE if tuning can't be applied at current stage, + * UNKNOWN_ERROR if tuning failed for other reasons. + */ + scan_1_1(FrontendSettings settings, FrontendScanType type, + FrontendSettingsExt1_1 settingsExt1_1) generates (Result result); + + /** + * Link Conditional Access Modules (CAM) to Frontend support Common Interface (CI) bypass mode. + * + * The client may use this to link CI-CAM to a frontend. CI bypass mode requires that the + * CICAM also receives the TS concurrently from the frontend when the Demux is receiving the TS + * directly from the frontend. + * + * @param ciCamId specify CI-CAM Id to link. + * @return ltsId Local Transport Stream Id. + * @return result Result status of the operation. + * SUCCESS if successful, + * UNKNOWN_ERROR if failed for other reasons. + */ + linkCiCam(uint32_t ciCamId) generates (Result result, uint32_t ltsId); + + /** + * Unlink Conditional Access Modules (CAM) to Frontend. + * + * @param ciCamId specify CI-CAM Id to unlink. + * @return result Result status of the operation. + * SUCCESS if successful, + * UNKNOWN_ERROR if failed for other reasons. + */ + unlinkCiCam(uint32_t ciCamId) generates (Result result); + + /** + * Get the v1_1 extended statuses of the frontend. + * + * This retrieve the extended statuses of the frontend for given extended status types. + * + * @param statusTypes an array of the extended status types which the caller request. + * + * @return result Result status of the operation. + * SUCCESS if successful, + * INVALID_STATE if tuning can't be applied at current stage, + * UNKNOWN_ERROR if tuning failed for other reasons. + * @return statuses an array of extended statuses the caller requests for. + */ + getStatusExt1_1(vec statusTypes) + generates (Result result, vec statuses); +}; diff --git a/tv/tuner/1.1/IFrontendCallback.hal b/tv/tuner/1.1/IFrontendCallback.hal new file mode 100644 index 0000000000000000000000000000000000000000..e148b1ef480795c84130ba1b4a3422ac0d163609 --- /dev/null +++ b/tv/tuner/1.1/IFrontendCallback.hal @@ -0,0 +1,32 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.tv.tuner@1.1; + +import @1.0::IFrontendCallback; +import FrontendScanMessageExt1_1; +import FrontendScanMessageTypeExt1_1; + +interface IFrontendCallback extends @1.0::IFrontendCallback { + /** + * The callback function that must be called by HAL implementation to notify + * the client of the v1_1 extended scan messages. + * + * @param type the type of v1_1 extended scan message. + * @param message the v1_1 extended scan message sent by HAL to the client. + */ + onScanMessageExt1_1(FrontendScanMessageTypeExt1_1 type, FrontendScanMessageExt1_1 messageExt); +}; diff --git a/tv/tuner/1.1/ITuner.hal b/tv/tuner/1.1/ITuner.hal new file mode 100644 index 0000000000000000000000000000000000000000..d59c425257ccc6461b405cc2a7738a683da57d6b --- /dev/null +++ b/tv/tuner/1.1/ITuner.hal @@ -0,0 +1,33 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.tv.tuner@1.1; + +import @1.0::FrontendId; +import @1.0::ITuner; +import @1.0::Result; + +/** + * Top level interface to manage Frontend, Demux and Decrambler hardware + * resources which are needed for Android TV. + */ +interface ITuner extends @1.0::ITuner { + /** + * Get Dtmb Frontend Capabilities. If no dtmb exists, Result::UNAVAILABLE would be returned. + */ + getFrontendDtmbCapabilities(FrontendId frontendId) + generates (Result result, FrontendDtmbCapabilities caps); +}; diff --git a/tv/tuner/1.1/TEST_MAPPING b/tv/tuner/1.1/TEST_MAPPING new file mode 100644 index 0000000000000000000000000000000000000000..7c91b8fe6c3ea63d11f0ffce2aa1edc6b221235d --- /dev/null +++ b/tv/tuner/1.1/TEST_MAPPING @@ -0,0 +1,7 @@ +{ + "presubmit": [ + { + "name": "VtsHalTvTunerV1_1TargetTest" + } + ] +} \ No newline at end of file diff --git a/tv/tuner/1.1/default/Android.bp b/tv/tuner/1.1/default/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..a612802527f76b7277d6e19dd7588987c255eb9a --- /dev/null +++ b/tv/tuner/1.1/default/Android.bp @@ -0,0 +1,62 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_defaults { + name: "tuner_service_defaults@1.1", + defaults: ["hidl_defaults"], + vendor: true, + relative_install_path: "hw", + srcs: [ + "Demux.cpp", + "Descrambler.cpp", + "Dvr.cpp", + "Filter.cpp", + "Frontend.cpp", + "Lnb.cpp", + "TimeFilter.cpp", + "Tuner.cpp", + "service.cpp", + ], + + compile_multilib: "first", + + shared_libs: [ + "android.hardware.tv.tuner@1.0", + "android.hardware.tv.tuner@1.1", + "android.hidl.memory@1.0", + "libcutils", + "libdmabufheap", + "libfmq", + "libhidlbase", + "libhidlmemory", + "libion", + "liblog", + "libstagefright_foundation", + "libutils", + ], + header_libs: [ + "media_plugin_headers", + ], +} + +cc_binary { + name: "android.hardware.tv.tuner@1.1-service", + vintf_fragments: ["android.hardware.tv.tuner@1.1-service.xml"], + defaults: ["tuner_service_defaults@1.1"], + init_rc: ["android.hardware.tv.tuner@1.1-service.rc"], +} + +cc_binary { + name: "android.hardware.tv.tuner@1.1-service-lazy", + vintf_fragments: ["android.hardware.tv.tuner@1.1-service-lazy.xml"], + overrides: ["android.hardware.tv.tuner@1.1-service"], + defaults: ["tuner_service_defaults@1.1"], + init_rc: ["android.hardware.tv.tuner@1.1-service-lazy.rc"], + cflags: ["-DLAZY_SERVICE"], +} diff --git a/tv/tuner/1.1/default/Demux.cpp b/tv/tuner/1.1/default/Demux.cpp new file mode 100644 index 0000000000000000000000000000000000000000..15b8e6c82a35319529bde5185bfcbe9105bcf15e --- /dev/null +++ b/tv/tuner/1.1/default/Demux.cpp @@ -0,0 +1,427 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "android.hardware.tv.tuner@1.1-Demux" + +#include "Demux.h" +#include + +namespace android { +namespace hardware { +namespace tv { +namespace tuner { +namespace V1_0 { +namespace implementation { + +#define WAIT_TIMEOUT 3000000000 + +Demux::Demux(uint32_t demuxId, sp tuner) { + mDemuxId = demuxId; + mTunerService = tuner; +} + +Demux::~Demux() { + mFrontendInputThreadRunning = false; + std::lock_guard lock(mFrontendInputThreadLock); +} + +Return Demux::setFrontendDataSource(uint32_t frontendId) { + ALOGV("%s", __FUNCTION__); + + if (mTunerService == nullptr) { + return Result::NOT_INITIALIZED; + } + + mFrontend = mTunerService->getFrontendById(frontendId); + + if (mFrontend == nullptr) { + return Result::INVALID_STATE; + } + + mTunerService->setFrontendAsDemuxSource(frontendId, mDemuxId); + + return Result::SUCCESS; +} + +Return Demux::openFilter(const DemuxFilterType& type, uint32_t bufferSize, + const sp& cb, openFilter_cb _hidl_cb) { + ALOGV("%s", __FUNCTION__); + + uint64_t filterId; + filterId = ++mLastUsedFilterId; + + if (cb == nullptr) { + ALOGW("[Demux] callback can't be null"); + _hidl_cb(Result::INVALID_ARGUMENT, new Filter()); + return Void(); + } + + sp filter = new Filter(type, filterId, bufferSize, cb, this); + + if (!filter->createFilterMQ()) { + _hidl_cb(Result::UNKNOWN_ERROR, filter); + return Void(); + } + + mFilters[filterId] = filter; + if (filter->isPcrFilter()) { + mPcrFilterIds.insert(filterId); + } + bool result = true; + if (!filter->isRecordFilter()) { + // Only save non-record filters for now. Record filters are saved when the + // IDvr.attacheFilter is called. + mPlaybackFilterIds.insert(filterId); + if (mDvrPlayback != nullptr) { + result = mDvrPlayback->addPlaybackFilter(filterId, filter); + } + } + + _hidl_cb(result ? Result::SUCCESS : Result::INVALID_ARGUMENT, filter); + return Void(); +} + +Return Demux::openTimeFilter(openTimeFilter_cb _hidl_cb) { + ALOGV("%s", __FUNCTION__); + + mTimeFilter = new TimeFilter(this); + + _hidl_cb(Result::SUCCESS, mTimeFilter); + return Void(); +} + +Return Demux::getAvSyncHwId(const sp& filter, getAvSyncHwId_cb _hidl_cb) { + ALOGV("%s", __FUNCTION__); + + uint32_t avSyncHwId = -1; + uint64_t id; + Result status; + + sp filter_v1_1 = V1_1::IFilter::castFrom(filter); + if (filter_v1_1 != NULL) { + filter_v1_1->getId64Bit([&](Result result, uint64_t filterId) { + id = filterId; + status = result; + }); + } else { + filter->getId([&](Result result, uint32_t filterId) { + id = filterId; + status = result; + }); + } + + if (status != Result::SUCCESS) { + ALOGE("[Demux] Can't get filter Id."); + _hidl_cb(Result::INVALID_STATE, avSyncHwId); + return Void(); + } + + if (!mFilters[id]->isMediaFilter()) { + ALOGE("[Demux] Given filter is not a media filter."); + _hidl_cb(Result::INVALID_ARGUMENT, avSyncHwId); + return Void(); + } + + if (!mPcrFilterIds.empty()) { + // Return the lowest pcr filter id in the default implementation as the av sync id + _hidl_cb(Result::SUCCESS, *mPcrFilterIds.begin()); + return Void(); + } + + ALOGE("[Demux] No PCR filter opened."); + _hidl_cb(Result::INVALID_STATE, avSyncHwId); + return Void(); +} + +Return Demux::getAvSyncTime(AvSyncHwId avSyncHwId, getAvSyncTime_cb _hidl_cb) { + ALOGV("%s", __FUNCTION__); + + uint64_t avSyncTime = -1; + if (mPcrFilterIds.empty()) { + _hidl_cb(Result::INVALID_STATE, avSyncTime); + return Void(); + } + if (avSyncHwId != *mPcrFilterIds.begin()) { + _hidl_cb(Result::INVALID_ARGUMENT, avSyncTime); + return Void(); + } + + _hidl_cb(Result::SUCCESS, avSyncTime); + return Void(); +} + +Return Demux::close() { + ALOGV("%s", __FUNCTION__); + + set::iterator it; + for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) { + mDvrPlayback->removePlaybackFilter(*it); + } + mPlaybackFilterIds.clear(); + mRecordFilterIds.clear(); + mFilters.clear(); + mLastUsedFilterId = -1; + mTunerService->removeDemux(mDemuxId); + mFrontendInputThreadRunning = false; + std::lock_guard lock(mFrontendInputThreadLock); + + return Result::SUCCESS; +} + +Return Demux::openDvr(DvrType type, uint32_t bufferSize, const sp& cb, + openDvr_cb _hidl_cb) { + ALOGV("%s", __FUNCTION__); + + if (cb == nullptr) { + ALOGW("[Demux] DVR callback can't be null"); + _hidl_cb(Result::INVALID_ARGUMENT, new Dvr()); + return Void(); + } + + set::iterator it; + switch (type) { + case DvrType::PLAYBACK: + mDvrPlayback = new Dvr(type, bufferSize, cb, this); + if (!mDvrPlayback->createDvrMQ()) { + _hidl_cb(Result::UNKNOWN_ERROR, mDvrPlayback); + return Void(); + } + + for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) { + if (!mDvrPlayback->addPlaybackFilter(*it, mFilters[*it])) { + ALOGE("[Demux] Can't get filter info for DVR playback"); + _hidl_cb(Result::UNKNOWN_ERROR, mDvrPlayback); + return Void(); + } + } + + _hidl_cb(Result::SUCCESS, mDvrPlayback); + return Void(); + case DvrType::RECORD: + mDvrRecord = new Dvr(type, bufferSize, cb, this); + if (!mDvrRecord->createDvrMQ()) { + _hidl_cb(Result::UNKNOWN_ERROR, mDvrRecord); + return Void(); + } + + _hidl_cb(Result::SUCCESS, mDvrRecord); + return Void(); + default: + _hidl_cb(Result::INVALID_ARGUMENT, nullptr); + return Void(); + } +} + +Return Demux::connectCiCam(uint32_t ciCamId) { + ALOGV("%s", __FUNCTION__); + + mCiCamId = ciCamId; + + return Result::SUCCESS; +} + +Return Demux::disconnectCiCam() { + ALOGV("%s", __FUNCTION__); + + return Result::SUCCESS; +} + +Result Demux::removeFilter(uint64_t filterId) { + ALOGV("%s", __FUNCTION__); + + if (mDvrPlayback != nullptr) { + mDvrPlayback->removePlaybackFilter(filterId); + } + mPlaybackFilterIds.erase(filterId); + mRecordFilterIds.erase(filterId); + mFilters.erase(filterId); + + return Result::SUCCESS; +} + +void Demux::startBroadcastTsFilter(vector data) { + set::iterator it; + uint16_t pid = ((data[1] & 0x1f) << 8) | ((data[2] & 0xff)); + if (DEBUG_DEMUX) { + ALOGW("[Demux] start ts filter pid: %d", pid); + } + for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) { + if (pid == mFilters[*it]->getTpid()) { + mFilters[*it]->updateFilterOutput(data); + } + } +} + +void Demux::sendFrontendInputToRecord(vector data) { + set::iterator it; + if (DEBUG_DEMUX) { + ALOGW("[Demux] update record filter output"); + } + for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) { + mFilters[*it]->updateRecordOutput(data); + } +} + +void Demux::sendFrontendInputToRecord(vector data, uint16_t pid, uint64_t pts) { + sendFrontendInputToRecord(data); + set::iterator it; + for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) { + if (pid == mFilters[*it]->getTpid()) { + mFilters[*it]->updatePts(pts); + } + } +} + +bool Demux::startBroadcastFilterDispatcher() { + set::iterator it; + + // Handle the output data per filter type + for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) { + if (mFilters[*it]->startFilterHandler() != Result::SUCCESS) { + return false; + } + } + + return true; +} + +bool Demux::startRecordFilterDispatcher() { + set::iterator it; + + for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) { + if (mFilters[*it]->startRecordFilterHandler() != Result::SUCCESS) { + return false; + } + } + + return true; +} + +Result Demux::startFilterHandler(uint64_t filterId) { + return mFilters[filterId]->startFilterHandler(); +} + +void Demux::updateFilterOutput(uint64_t filterId, vector data) { + mFilters[filterId]->updateFilterOutput(data); +} + +void Demux::updateMediaFilterOutput(uint64_t filterId, vector data, uint64_t pts) { + updateFilterOutput(filterId, data); + mFilters[filterId]->updatePts(pts); +} + +uint16_t Demux::getFilterTpid(uint64_t filterId) { + return mFilters[filterId]->getTpid(); +} + +void Demux::startFrontendInputLoop() { + mFrontendInputThreadRunning = true; + pthread_create(&mFrontendInputThread, NULL, __threadLoopFrontend, this); + pthread_setname_np(mFrontendInputThread, "frontend_input_thread"); +} + +void* Demux::__threadLoopFrontend(void* user) { + Demux* const self = static_cast(user); + self->frontendInputThreadLoop(); + return 0; +} + +void Demux::frontendInputThreadLoop() { + if (!mFrontendInputThreadRunning) { + return; + } + + std::lock_guard lock(mFrontendInputThreadLock); + if (!mDvrPlayback) { + ALOGW("[Demux] No software Frontend input configured. Ending Frontend thread loop."); + mFrontendInputThreadRunning = false; + return; + } + + while (mFrontendInputThreadRunning) { + uint32_t efState = 0; + status_t status = mDvrPlayback->getDvrEventFlag()->wait( + static_cast(DemuxQueueNotifyBits::DATA_READY), &efState, WAIT_TIMEOUT, + true /* retry on spurious wake */); + if (status != OK) { + ALOGD("[Demux] wait for data ready on the playback FMQ"); + continue; + } + if (mDvrPlayback->getSettings().playback().dataFormat == DataFormat::ES) { + if (!mDvrPlayback->processEsDataOnPlayback(true /*isVirtualFrontend*/, mIsRecording)) { + ALOGE("[Demux] playback es data failed to be filtered. Ending thread"); + break; + } + continue; + } + // Our current implementation filter the data and write it into the filter FMQ immediately + // after the DATA_READY from the VTS/framework + // This is for the non-ES data source, real playback use case handling. + if (!mDvrPlayback->readPlaybackFMQ(true /*isVirtualFrontend*/, mIsRecording) || + !mDvrPlayback->startFilterDispatcher(true /*isVirtualFrontend*/, mIsRecording)) { + ALOGE("[Demux] playback data failed to be filtered. Ending thread"); + break; + } + } + + mFrontendInputThreadRunning = false; + ALOGW("[Demux] Frontend Input thread end."); +} + +void Demux::stopFrontendInput() { + ALOGD("[Demux] stop frontend on demux"); + mKeepFetchingDataFromFrontend = false; + mFrontendInputThreadRunning = false; + std::lock_guard lock(mFrontendInputThreadLock); +} + +void Demux::setIsRecording(bool isRecording) { + mIsRecording = isRecording; +} + +bool Demux::isRecording() { + return mIsRecording; +} + +bool Demux::attachRecordFilter(uint64_t filterId) { + if (mFilters[filterId] == nullptr || mDvrRecord == nullptr || + !mFilters[filterId]->isRecordFilter()) { + return false; + } + + mRecordFilterIds.insert(filterId); + mFilters[filterId]->attachFilterToRecord(mDvrRecord); + + return true; +} + +bool Demux::detachRecordFilter(uint64_t filterId) { + if (mFilters[filterId] == nullptr || mDvrRecord == nullptr) { + return false; + } + + mRecordFilterIds.erase(filterId); + mFilters[filterId]->detachFilterFromRecord(); + + return true; +} + +} // namespace implementation +} // namespace V1_0 +} // namespace tuner +} // namespace tv +} // namespace hardware +} // namespace android diff --git a/tv/tuner/1.1/default/Demux.h b/tv/tuner/1.1/default/Demux.h new file mode 100644 index 0000000000000000000000000000000000000000..ce46f9c10c50599efd87521beac05ed34cea21d8 --- /dev/null +++ b/tv/tuner/1.1/default/Demux.h @@ -0,0 +1,199 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_TV_TUNER_V1_1_DEMUX_H_ +#define ANDROID_HARDWARE_TV_TUNER_V1_1_DEMUX_H_ + +#include +#include +#include +#include "Dvr.h" +#include "Filter.h" +#include "Frontend.h" +#include "TimeFilter.h" +#include "Tuner.h" + +using namespace std; + +namespace android { +namespace hardware { +namespace tv { +namespace tuner { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::EventFlag; +using ::android::hardware::kSynchronizedReadWrite; +using ::android::hardware::MessageQueue; +using ::android::hardware::MQDescriptorSync; + +using FilterMQ = MessageQueue; + +class Dvr; +class Filter; +class Frontend; +class TimeFilter; +class Tuner; + +class Demux : public IDemux { + public: + Demux(uint32_t demuxId, sp tuner); + + ~Demux(); + + virtual Return setFrontendDataSource(uint32_t frontendId) override; + + virtual Return openFilter(const DemuxFilterType& type, uint32_t bufferSize, + const sp& cb, openFilter_cb _hidl_cb) override; + + virtual Return openTimeFilter(openTimeFilter_cb _hidl_cb) override; + + virtual Return getAvSyncHwId(const sp& filter, + getAvSyncHwId_cb _hidl_cb) override; + + virtual Return getAvSyncTime(AvSyncHwId avSyncHwId, getAvSyncTime_cb _hidl_cb) override; + + virtual Return close() override; + + virtual Return openDvr(DvrType type, uint32_t bufferSize, const sp& cb, + openDvr_cb _hidl_cb) override; + + virtual Return connectCiCam(uint32_t ciCamId) override; + + virtual Return disconnectCiCam() override; + + // Functions interacts with Tuner Service + void stopFrontendInput(); + Result removeFilter(uint64_t filterId); + bool attachRecordFilter(uint64_t filterId); + bool detachRecordFilter(uint64_t filterId); + Result startFilterHandler(uint64_t filterId); + void updateFilterOutput(uint64_t filterId, vector data); + void updateMediaFilterOutput(uint64_t filterId, vector data, uint64_t pts); + uint16_t getFilterTpid(uint64_t filterId); + void setIsRecording(bool isRecording); + bool isRecording(); + void startFrontendInputLoop(); + + /** + * A dispatcher to read and dispatch input data to all the started filters. + * Each filter handler handles the data filtering/output writing/filterEvent updating. + * Note that recording filters are not included. + */ + bool startBroadcastFilterDispatcher(); + void startBroadcastTsFilter(vector data); + + void sendFrontendInputToRecord(vector data); + void sendFrontendInputToRecord(vector data, uint16_t pid, uint64_t pts); + bool startRecordFilterDispatcher(); + + private: + // Tuner service + sp mTunerService; + + // Frontend source + sp mFrontend; + + // A struct that passes the arguments to a newly created filter thread + struct ThreadArgs { + Demux* user; + uint64_t filterId; + }; + + static void* __threadLoopFrontend(void* user); + void frontendInputThreadLoop(); + + /** + * To create a FilterMQ with the next available Filter ID. + * Creating Event Flag at the same time. + * Add the successfully created/saved FilterMQ into the local list. + * + * Return false is any of the above processes fails. + */ + void deleteEventFlag(); + bool readDataFromMQ(); + + uint32_t mDemuxId = -1; + uint32_t mCiCamId; + set mPcrFilterIds; + /** + * Record the last used filter id. Initial value is -1. + * Filter Id starts with 0. + */ + uint64_t mLastUsedFilterId = -1; + /** + * Record all the used playback filter Ids. + * Any removed filter id should be removed from this set. + */ + set mPlaybackFilterIds; + /** + * Record all the attached record filter Ids. + * Any removed filter id should be removed from this set. + */ + set mRecordFilterIds; + /** + * A list of created Filter sp. + * The array number is the filter ID. + */ + std::map> mFilters; + + /** + * Local reference to the opened Timer Filter instance. + */ + sp mTimeFilter; + + /** + * Local reference to the opened DVR object. + */ + sp mDvrPlayback; + sp mDvrRecord; + + // Thread handlers + pthread_t mFrontendInputThread; + /** + * If a specific filter's writing loop is still running + */ + bool mFrontendInputThreadRunning; + bool mKeepFetchingDataFromFrontend; + /** + * If the dvr recording is running. + */ + bool mIsRecording = false; + /** + * Lock to protect writes to the FMQs + */ + std::mutex mWriteLock; + /** + * Lock to protect writes to the input status + */ + std::mutex mFrontendInputThreadLock; + + // temp handle single PES filter + // TODO handle mulptiple Pes filters + int mPesSizeLeft = 0; + vector mPesOutput; + + const bool DEBUG_DEMUX = false; +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace tuner +} // namespace tv +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_TV_TUNER_V1_1_DEMUX_H_ diff --git a/tv/tuner/1.1/default/Descrambler.cpp b/tv/tuner/1.1/default/Descrambler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1fbc780c342f1ee1b927a232d96acc022abc856b --- /dev/null +++ b/tv/tuner/1.1/default/Descrambler.cpp @@ -0,0 +1,80 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "android.hardware.tv.tuner@1.1-Descrambler" + +#include +#include + +#include "Descrambler.h" + +namespace android { +namespace hardware { +namespace tv { +namespace tuner { +namespace V1_0 { +namespace implementation { + +Descrambler::Descrambler() {} + +Descrambler::~Descrambler() {} + +Return Descrambler::setDemuxSource(uint32_t demuxId) { + ALOGV("%s", __FUNCTION__); + if (mDemuxSet) { + ALOGW("[ WARN ] Descrambler has already been set with a demux id %" PRIu32, + mSourceDemuxId); + return Result::INVALID_STATE; + } + mDemuxSet = true; + mSourceDemuxId = static_cast(demuxId); + + return Result::SUCCESS; +} + +Return Descrambler::setKeyToken(const hidl_vec& /* keyToken */) { + ALOGV("%s", __FUNCTION__); + + return Result::SUCCESS; +} + +Return Descrambler::addPid(const DemuxPid& /* pid */, + const sp& /* optionalSourceFilter */) { + ALOGV("%s", __FUNCTION__); + + return Result::SUCCESS; +} + +Return Descrambler::removePid(const DemuxPid& /* pid */, + const sp& /* optionalSourceFilter */) { + ALOGV("%s", __FUNCTION__); + + return Result::SUCCESS; +} + +Return Descrambler::close() { + ALOGV("%s", __FUNCTION__); + mDemuxSet = false; + + return Result::SUCCESS; +} + +} // namespace implementation +} // namespace V1_0 +} // namespace tuner +} // namespace tv +} // namespace hardware +} // namespace android diff --git a/tv/tuner/1.1/default/Descrambler.h b/tv/tuner/1.1/default/Descrambler.h new file mode 100644 index 0000000000000000000000000000000000000000..ffc284dddee5260fc151140db822e8da1bea355a --- /dev/null +++ b/tv/tuner/1.1/default/Descrambler.h @@ -0,0 +1,62 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_TV_TUNER_V1_1_DESCRAMBLER_H_ +#define ANDROID_HARDWARE_TV_TUNER_V1_1_DESCRAMBLER_H_ + +#include +#include +#include + +using namespace std; + +namespace android { +namespace hardware { +namespace tv { +namespace tuner { +namespace V1_0 { +namespace implementation { + +class Descrambler : public IDescrambler { + public: + Descrambler(); + + virtual Return setDemuxSource(uint32_t demuxId) override; + + virtual Return setKeyToken(const hidl_vec& keyToken) override; + + virtual Return addPid(const DemuxPid& pid, + const sp& optionalSourceFilter) override; + + virtual Return removePid(const DemuxPid& pid, + const sp& optionalSourceFilter) override; + + virtual Return close() override; + + private: + virtual ~Descrambler(); + uint32_t mSourceDemuxId; + bool mDemuxSet = false; +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace tuner +} // namespace tv +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_TV_TUNER_V1_DESCRAMBLER_H_ diff --git a/tv/tuner/1.1/default/Dvr.cpp b/tv/tuner/1.1/default/Dvr.cpp new file mode 100644 index 0000000000000000000000000000000000000000..93f4519f1013d57b47230deb2dcfb0f31add6a7b --- /dev/null +++ b/tv/tuner/1.1/default/Dvr.cpp @@ -0,0 +1,513 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "android.hardware.tv.tuner@1.1-Dvr" + +#include "Dvr.h" +#include + +namespace android { +namespace hardware { +namespace tv { +namespace tuner { +namespace V1_0 { +namespace implementation { + +#define WAIT_TIMEOUT 3000000000 + +Dvr::Dvr() {} + +Dvr::Dvr(DvrType type, uint32_t bufferSize, const sp& cb, sp demux) { + mType = type; + mBufferSize = bufferSize; + mCallback = cb; + mDemux = demux; +} + +Dvr::~Dvr() { + mDvrThreadRunning = false; + lock_guard lock(mDvrThreadLock); +} + +Return Dvr::getQueueDesc(getQueueDesc_cb _hidl_cb) { + ALOGV("%s", __FUNCTION__); + + _hidl_cb(Result::SUCCESS, *mDvrMQ->getDesc()); + return Void(); +} + +Return Dvr::configure(const DvrSettings& settings) { + ALOGV("%s", __FUNCTION__); + + mDvrSettings = settings; + mDvrConfigured = true; + + return Result::SUCCESS; +} + +Return Dvr::attachFilter(const sp& filter) { + ALOGV("%s", __FUNCTION__); + + uint64_t filterId; + Result status; + + sp filter_v1_1 = V1_1::IFilter::castFrom(filter); + if (filter_v1_1 != NULL) { + filter_v1_1->getId64Bit([&](Result result, uint64_t id) { + filterId = id; + status = result; + }); + } else { + filter->getId([&](Result result, uint32_t id) { + filterId = id; + status = result; + }); + } + + if (status != Result::SUCCESS) { + return status; + } + + if (!mDemux->attachRecordFilter(filterId)) { + return Result::INVALID_ARGUMENT; + } + + return Result::SUCCESS; +} + +Return Dvr::detachFilter(const sp& filter) { + ALOGV("%s", __FUNCTION__); + + uint64_t filterId; + Result status; + + sp filter_v1_1 = V1_1::IFilter::castFrom(filter); + if (filter_v1_1 != NULL) { + filter_v1_1->getId64Bit([&](Result result, uint64_t id) { + filterId = id; + status = result; + }); + } else { + filter->getId([&](Result result, uint32_t id) { + filterId = id; + status = result; + }); + } + + if (status != Result::SUCCESS) { + return status; + } + + if (!mDemux->detachRecordFilter(filterId)) { + return Result::INVALID_ARGUMENT; + } + + return Result::SUCCESS; +} + +Return Dvr::start() { + ALOGV("%s", __FUNCTION__); + if (mDvrThreadRunning) { + return Result::SUCCESS; + } + + if (!mCallback) { + return Result::NOT_INITIALIZED; + } + + if (!mDvrConfigured) { + return Result::INVALID_STATE; + } + + if (mType == DvrType::PLAYBACK) { + mDvrThreadRunning = true; + pthread_create(&mDvrThread, NULL, __threadLoopPlayback, this); + pthread_setname_np(mDvrThread, "playback_waiting_loop"); + } else if (mType == DvrType::RECORD) { + mRecordStatus = RecordStatus::DATA_READY; + mDemux->setIsRecording(mType == DvrType::RECORD); + } + + // TODO start another thread to send filter status callback to the framework + + return Result::SUCCESS; +} + +Return Dvr::stop() { + ALOGV("%s", __FUNCTION__); + + mDvrThreadRunning = false; + lock_guard lock(mDvrThreadLock); + + mIsRecordStarted = false; + mDemux->setIsRecording(false); + + return Result::SUCCESS; +} + +Return Dvr::flush() { + ALOGV("%s", __FUNCTION__); + + mRecordStatus = RecordStatus::DATA_READY; + + return Result::SUCCESS; +} + +Return Dvr::close() { + ALOGV("%s", __FUNCTION__); + + mDvrThreadRunning = false; + lock_guard lock(mDvrThreadLock); + return Result::SUCCESS; +} + +bool Dvr::createDvrMQ() { + ALOGV("%s", __FUNCTION__); + + // Create a synchronized FMQ that supports blocking read/write + unique_ptr tmpDvrMQ = unique_ptr(new (nothrow) DvrMQ(mBufferSize, true)); + if (!tmpDvrMQ->isValid()) { + ALOGW("[Dvr] Failed to create FMQ of DVR"); + return false; + } + + mDvrMQ = move(tmpDvrMQ); + + if (EventFlag::createEventFlag(mDvrMQ->getEventFlagWord(), &mDvrEventFlag) != OK) { + return false; + } + + return true; +} + +EventFlag* Dvr::getDvrEventFlag() { + return mDvrEventFlag; +} + +void* Dvr::__threadLoopPlayback(void* user) { + Dvr* const self = static_cast(user); + self->playbackThreadLoop(); + return 0; +} + +void Dvr::playbackThreadLoop() { + ALOGD("[Dvr] playback threadLoop start."); + lock_guard lock(mDvrThreadLock); + + while (mDvrThreadRunning) { + uint32_t efState = 0; + status_t status = + mDvrEventFlag->wait(static_cast(DemuxQueueNotifyBits::DATA_READY), + &efState, WAIT_TIMEOUT, true /* retry on spurious wake */); + if (status != OK) { + ALOGD("[Dvr] wait for data ready on the playback FMQ"); + continue; + } + + // If the both dvr playback and dvr record are created, the playback will be treated as + // the source of the record. isVirtualFrontend set to true would direct the dvr playback + // input to the demux record filters or live broadcast filters. + bool isRecording = mDemux->isRecording(); + bool isVirtualFrontend = isRecording; + + if (mDvrSettings.playback().dataFormat == DataFormat::ES) { + if (!processEsDataOnPlayback(isVirtualFrontend, isRecording)) { + ALOGE("[Dvr] playback es data failed to be filtered. Ending thread"); + break; + } + maySendPlaybackStatusCallback(); + continue; + } + + // Our current implementation filter the data and write it into the filter FMQ immediately + // after the DATA_READY from the VTS/framework + // This is for the non-ES data source, real playback use case handling. + if (!readPlaybackFMQ(isVirtualFrontend, isRecording) || + !startFilterDispatcher(isVirtualFrontend, isRecording)) { + ALOGE("[Dvr] playback data failed to be filtered. Ending thread"); + break; + } + + maySendPlaybackStatusCallback(); + } + + mDvrThreadRunning = false; + ALOGD("[Dvr] playback thread ended."); +} + +void Dvr::maySendPlaybackStatusCallback() { + lock_guard lock(mPlaybackStatusLock); + int availableToRead = mDvrMQ->availableToRead(); + int availableToWrite = mDvrMQ->availableToWrite(); + + PlaybackStatus newStatus = checkPlaybackStatusChange(availableToWrite, availableToRead, + mDvrSettings.playback().highThreshold, + mDvrSettings.playback().lowThreshold); + if (mPlaybackStatus != newStatus) { + mCallback->onPlaybackStatus(newStatus); + mPlaybackStatus = newStatus; + } +} + +PlaybackStatus Dvr::checkPlaybackStatusChange(uint32_t availableToWrite, uint32_t availableToRead, + uint32_t highThreshold, uint32_t lowThreshold) { + if (availableToWrite == 0) { + return PlaybackStatus::SPACE_FULL; + } else if (availableToRead > highThreshold) { + return PlaybackStatus::SPACE_ALMOST_FULL; + } else if (availableToRead < lowThreshold) { + return PlaybackStatus::SPACE_ALMOST_EMPTY; + } else if (availableToRead == 0) { + return PlaybackStatus::SPACE_EMPTY; + } + return mPlaybackStatus; +} + +bool Dvr::readPlaybackFMQ(bool isVirtualFrontend, bool isRecording) { + // Read playback data from the input FMQ + int size = mDvrMQ->availableToRead(); + int playbackPacketSize = mDvrSettings.playback().packetSize; + vector dataOutputBuffer; + dataOutputBuffer.resize(playbackPacketSize); + // Dispatch the packet to the PID matching filter output buffer + for (int i = 0; i < size / playbackPacketSize; i++) { + if (!mDvrMQ->read(dataOutputBuffer.data(), playbackPacketSize)) { + return false; + } + if (isVirtualFrontend) { + if (isRecording) { + mDemux->sendFrontendInputToRecord(dataOutputBuffer); + } else { + mDemux->startBroadcastTsFilter(dataOutputBuffer); + } + } else { + startTpidFilter(dataOutputBuffer); + } + } + + return true; +} + +bool Dvr::processEsDataOnPlayback(bool isVirtualFrontend, bool isRecording) { + // Read ES from the DVR FMQ + // Note that currently we only provides ES with metaData in a specific format to be parsed. + // The ES size should be smaller than the Playback FMQ size to avoid reading truncated data. + int size = mDvrMQ->availableToRead(); + vector dataOutputBuffer; + dataOutputBuffer.resize(size); + if (!mDvrMQ->read(dataOutputBuffer.data(), size)) { + return false; + } + + int metaDataSize = size; + int totalFrames = 0; + int videoEsDataSize = 0; + int audioEsDataSize = 0; + int audioPid = 0; + int videoPid = 0; + + vector esMeta; + int videoReadPointer = 0; + int audioReadPointer = 0; + int frameCount = 0; + // Get meta data from the es + for (int i = 0; i < metaDataSize; i++) { + switch (dataOutputBuffer[i]) { + case 'm': + metaDataSize = 0; + getMetaDataValue(i, dataOutputBuffer.data(), metaDataSize); + videoReadPointer = metaDataSize; + continue; + case 'l': + getMetaDataValue(i, dataOutputBuffer.data(), totalFrames); + esMeta.resize(totalFrames); + continue; + case 'V': + getMetaDataValue(i, dataOutputBuffer.data(), videoEsDataSize); + audioReadPointer = metaDataSize + videoEsDataSize; + continue; + case 'A': + getMetaDataValue(i, dataOutputBuffer.data(), audioEsDataSize); + continue; + case 'p': + if (dataOutputBuffer[++i] == 'a') { + getMetaDataValue(i, dataOutputBuffer.data(), audioPid); + } else if (dataOutputBuffer[i] == 'v') { + getMetaDataValue(i, dataOutputBuffer.data(), videoPid); + } + continue; + case 'v': + case 'a': + if (dataOutputBuffer[i + 1] != ',') { + ALOGE("[Dvr] Invalid format meta data."); + return false; + } + esMeta[frameCount] = { + .isAudio = dataOutputBuffer[i] == 'a' ? true : false, + }; + i += 5; // Move to Len + getMetaDataValue(i, dataOutputBuffer.data(), esMeta[frameCount].len); + if (esMeta[frameCount].isAudio) { + esMeta[frameCount].startIndex = audioReadPointer; + audioReadPointer += esMeta[frameCount].len; + } else { + esMeta[frameCount].startIndex = videoReadPointer; + videoReadPointer += esMeta[frameCount].len; + } + i += 4; // move to PTS + getMetaDataValue(i, dataOutputBuffer.data(), esMeta[frameCount].pts); + frameCount++; + continue; + default: + continue; + } + } + + if (frameCount != totalFrames) { + ALOGE("[Dvr] Invalid meta data, frameCount=%d, totalFrames reported=%d", frameCount, + totalFrames); + return false; + } + + if (metaDataSize + audioEsDataSize + videoEsDataSize != size) { + ALOGE("[Dvr] Invalid meta data, metaSize=%d, videoSize=%d, audioSize=%d, totolSize=%d", + metaDataSize, videoEsDataSize, audioEsDataSize, size); + return false; + } + + // Read es raw data from the FMQ per meta data built previously + vector frameData; + map>::iterator it; + int pid = 0; + for (int i = 0; i < totalFrames; i++) { + frameData.resize(esMeta[i].len); + pid = esMeta[i].isAudio ? audioPid : videoPid; + memcpy(frameData.data(), dataOutputBuffer.data() + esMeta[i].startIndex, esMeta[i].len); + // Send to the media filters or record filters + if (!isRecording) { + for (it = mFilters.begin(); it != mFilters.end(); it++) { + if (pid == mDemux->getFilterTpid(it->first)) { + mDemux->updateMediaFilterOutput(it->first, frameData, + static_cast(esMeta[i].pts)); + } + } + } else { + mDemux->sendFrontendInputToRecord(frameData, pid, static_cast(esMeta[i].pts)); + } + startFilterDispatcher(isVirtualFrontend, isRecording); + frameData.clear(); + } + + return true; +} + +void Dvr::getMetaDataValue(int& index, uint8_t* dataOutputBuffer, int& value) { + index += 2; // Move the pointer across the ":" to the value + while (dataOutputBuffer[index] != ',' && dataOutputBuffer[index] != '\n') { + value = ((dataOutputBuffer[index++] - 48) + value * 10); + } +} + +void Dvr::startTpidFilter(vector data) { + map>::iterator it; + for (it = mFilters.begin(); it != mFilters.end(); it++) { + uint16_t pid = ((data[1] & 0x1f) << 8) | ((data[2] & 0xff)); + if (DEBUG_DVR) { + ALOGW("[Dvr] start ts filter pid: %d", pid); + } + if (pid == mDemux->getFilterTpid(it->first)) { + mDemux->updateFilterOutput(it->first, data); + } + } +} + +bool Dvr::startFilterDispatcher(bool isVirtualFrontend, bool isRecording) { + if (isVirtualFrontend) { + if (isRecording) { + return mDemux->startRecordFilterDispatcher(); + } else { + return mDemux->startBroadcastFilterDispatcher(); + } + } + + map>::iterator it; + // Handle the output data per filter type + for (it = mFilters.begin(); it != mFilters.end(); it++) { + if (mDemux->startFilterHandler(it->first) != Result::SUCCESS) { + return false; + } + } + + return true; +} + +bool Dvr::writeRecordFMQ(const vector& data) { + lock_guard lock(mWriteLock); + if (mRecordStatus == RecordStatus::OVERFLOW) { + ALOGW("[Dvr] stops writing and wait for the client side flushing."); + return true; + } + if (mDvrMQ->write(data.data(), data.size())) { + mDvrEventFlag->wake(static_cast(DemuxQueueNotifyBits::DATA_READY)); + maySendRecordStatusCallback(); + return true; + } + + maySendRecordStatusCallback(); + return false; +} + +void Dvr::maySendRecordStatusCallback() { + lock_guard lock(mRecordStatusLock); + int availableToRead = mDvrMQ->availableToRead(); + int availableToWrite = mDvrMQ->availableToWrite(); + + RecordStatus newStatus = checkRecordStatusChange(availableToWrite, availableToRead, + mDvrSettings.record().highThreshold, + mDvrSettings.record().lowThreshold); + if (mRecordStatus != newStatus) { + mCallback->onRecordStatus(newStatus); + mRecordStatus = newStatus; + } +} + +RecordStatus Dvr::checkRecordStatusChange(uint32_t availableToWrite, uint32_t availableToRead, + uint32_t highThreshold, uint32_t lowThreshold) { + if (availableToWrite == 0) { + return DemuxFilterStatus::OVERFLOW; + } else if (availableToRead > highThreshold) { + return DemuxFilterStatus::HIGH_WATER; + } else if (availableToRead < lowThreshold) { + return DemuxFilterStatus::LOW_WATER; + } + return mRecordStatus; +} + +bool Dvr::addPlaybackFilter(uint64_t filterId, sp filter) { + mFilters[filterId] = filter; + return true; +} + +bool Dvr::removePlaybackFilter(uint64_t filterId) { + mFilters.erase(filterId); + return true; +} +} // namespace implementation +} // namespace V1_0 +} // namespace tuner +} // namespace tv +} // namespace hardware +} // namespace android diff --git a/tv/tuner/1.1/default/Dvr.h b/tv/tuner/1.1/default/Dvr.h new file mode 100644 index 0000000000000000000000000000000000000000..7b7efefada155f495e028ea170ff887b09003fe9 --- /dev/null +++ b/tv/tuner/1.1/default/Dvr.h @@ -0,0 +1,167 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_TV_TUNER_V1_1_DVR_H_ +#define ANDROID_HARDWARE_TV_TUNER_V1_1_DVR_H_ + +#include +#include +#include +#include "Demux.h" +#include "Frontend.h" +#include "Tuner.h" + +using namespace std; + +namespace android { +namespace hardware { +namespace tv { +namespace tuner { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::EventFlag; +using ::android::hardware::kSynchronizedReadWrite; +using ::android::hardware::MessageQueue; +using ::android::hardware::MQDescriptorSync; + +using DvrMQ = MessageQueue; + +struct MediaEsMetaData { + bool isAudio; + int startIndex; + int len; + int pts; +}; + +class Demux; +class Filter; +class Frontend; +class Tuner; + +class Dvr : public IDvr { + public: + Dvr(); + + Dvr(DvrType type, uint32_t bufferSize, const sp& cb, sp demux); + + ~Dvr(); + + virtual Return getQueueDesc(getQueueDesc_cb _hidl_cb) override; + + virtual Return configure(const DvrSettings& settings) override; + + virtual Return attachFilter(const sp& filter) override; + + virtual Return detachFilter(const sp& filter) override; + + virtual Return start() override; + + virtual Return stop() override; + + virtual Return flush() override; + + virtual Return close() override; + + /** + * To create a DvrMQ and its Event Flag. + * + * Return false is any of the above processes fails. + */ + bool createDvrMQ(); + void sendBroadcastInputToDvrRecord(vector byteBuffer); + bool writeRecordFMQ(const std::vector& data); + bool addPlaybackFilter(uint64_t filterId, sp filter); + bool removePlaybackFilter(uint64_t filterId); + bool readPlaybackFMQ(bool isVirtualFrontend, bool isRecording); + bool processEsDataOnPlayback(bool isVirtualFrontend, bool isRecording); + bool startFilterDispatcher(bool isVirtualFrontend, bool isRecording); + EventFlag* getDvrEventFlag(); + DvrSettings getSettings() { return mDvrSettings; } + + private: + // Demux service + sp mDemux; + + DvrType mType; + uint32_t mBufferSize; + sp mCallback; + std::map> mFilters; + + void deleteEventFlag(); + bool readDataFromMQ(); + void getMetaDataValue(int& index, uint8_t* dataOutputBuffer, int& value); + void maySendPlaybackStatusCallback(); + void maySendRecordStatusCallback(); + PlaybackStatus checkPlaybackStatusChange(uint32_t availableToWrite, uint32_t availableToRead, + uint32_t highThreshold, uint32_t lowThreshold); + RecordStatus checkRecordStatusChange(uint32_t availableToWrite, uint32_t availableToRead, + uint32_t highThreshold, uint32_t lowThreshold); + /** + * A dispatcher to read and dispatch input data to all the started filters. + * Each filter handler handles the data filtering/output writing/filterEvent updating. + */ + void startTpidFilter(vector data); + static void* __threadLoopPlayback(void* user); + static void* __threadLoopRecord(void* user); + void playbackThreadLoop(); + void recordThreadLoop(); + + unique_ptr mDvrMQ; + EventFlag* mDvrEventFlag; + /** + * Demux callbacks used on filter events or IO buffer status + */ + bool mDvrConfigured = false; + DvrSettings mDvrSettings; + + // Thread handlers + pthread_t mDvrThread; + + // FMQ status local records + PlaybackStatus mPlaybackStatus; + RecordStatus mRecordStatus; + /** + * If a specific filter's writing loop is still running + */ + bool mDvrThreadRunning; + bool mKeepFetchingDataFromFrontend; + /** + * Lock to protect writes to the FMQs + */ + std::mutex mWriteLock; + /** + * Lock to protect writes to the input status + */ + std::mutex mPlaybackStatusLock; + std::mutex mRecordStatusLock; + std::mutex mDvrThreadLock; + + const bool DEBUG_DVR = false; + + // Booleans to check if recording is running. + // Recording is ready when both of the following are set to true. + bool mIsRecordStarted = false; +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace tuner +} // namespace tv +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_TV_TUNER_V1_1_DVR_H_ \ No newline at end of file diff --git a/tv/tuner/1.1/default/Filter.cpp b/tv/tuner/1.1/default/Filter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7d609ea3dc456ce267d14df7910e3122ddd59faa --- /dev/null +++ b/tv/tuner/1.1/default/Filter.cpp @@ -0,0 +1,1154 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "android.hardware.tv.tuner@1.1-Filter" + +#include +#include + +#include "Filter.h" + +namespace android { +namespace hardware { +namespace tv { +namespace tuner { +namespace V1_0 { +namespace implementation { + +#define WAIT_TIMEOUT 3000000000 + +Filter::Filter() {} + +Filter::Filter(DemuxFilterType type, uint64_t filterId, uint32_t bufferSize, + const sp& cb, sp demux) { + mType = type; + mFilterId = filterId; + mBufferSize = bufferSize; + mDemux = demux; + + switch (mType.mainType) { + case DemuxFilterMainType::TS: + if (mType.subType.tsFilterType() == DemuxTsFilterType::AUDIO || + mType.subType.tsFilterType() == DemuxTsFilterType::VIDEO) { + mIsMediaFilter = true; + } + if (mType.subType.tsFilterType() == DemuxTsFilterType::PCR) { + mIsPcrFilter = true; + } + if (mType.subType.tsFilterType() == DemuxTsFilterType::RECORD) { + mIsRecordFilter = true; + } + break; + case DemuxFilterMainType::MMTP: + if (mType.subType.mmtpFilterType() == DemuxMmtpFilterType::AUDIO || + mType.subType.mmtpFilterType() == DemuxMmtpFilterType::VIDEO) { + mIsMediaFilter = true; + } + if (mType.subType.mmtpFilterType() == DemuxMmtpFilterType::RECORD) { + mIsRecordFilter = true; + } + break; + case DemuxFilterMainType::IP: + break; + case DemuxFilterMainType::TLV: + break; + case DemuxFilterMainType::ALP: + break; + default: + break; + } + + sp filterCallback_v1_1 = V1_1::IFilterCallback::castFrom(cb); + if (filterCallback_v1_1 != NULL) { + mCallback_1_1 = filterCallback_v1_1; + } + mCallback = cb; +} + +Filter::~Filter() { + mFilterThreadRunning = false; + std::lock_guard lock(mFilterThreadLock); +} + +Return Filter::getId64Bit(getId64Bit_cb _hidl_cb) { + ALOGV("%s", __FUNCTION__); + + _hidl_cb(Result::SUCCESS, mFilterId); + return Void(); +} + +Return Filter::getId(getId_cb _hidl_cb) { + ALOGV("%s", __FUNCTION__); + + _hidl_cb(Result::SUCCESS, static_cast(mFilterId)); + return Void(); +} + +Return Filter::setDataSource(const sp& filter) { + ALOGV("%s", __FUNCTION__); + + mDataSource = filter; + mIsDataSourceDemux = false; + + return Result::SUCCESS; +} + +Return Filter::getQueueDesc(getQueueDesc_cb _hidl_cb) { + ALOGV("%s", __FUNCTION__); + + mIsUsingFMQ = mIsRecordFilter ? false : true; + + _hidl_cb(Result::SUCCESS, *mFilterMQ->getDesc()); + return Void(); +} + +Return Filter::configure(const DemuxFilterSettings& settings) { + ALOGV("%s", __FUNCTION__); + + mFilterSettings = settings; + switch (mType.mainType) { + case DemuxFilterMainType::TS: + mTpid = settings.ts().tpid; + break; + case DemuxFilterMainType::MMTP: + break; + case DemuxFilterMainType::IP: + break; + case DemuxFilterMainType::TLV: + break; + case DemuxFilterMainType::ALP: + break; + default: + break; + } + + mConfigured = true; + return Result::SUCCESS; +} + +Return Filter::start() { + ALOGV("%s", __FUNCTION__); + mFilterThreadRunning = true; + // All the filter event callbacks in start are for testing purpose. + switch (mType.mainType) { + case DemuxFilterMainType::TS: + mCallback->onFilterEvent(createMediaEvent()); + mCallback->onFilterEvent(createTsRecordEvent()); + mCallback->onFilterEvent(createTemiEvent()); + // clients could still pass 1.0 callback + if (mCallback_1_1 != NULL) { + mCallback_1_1->onFilterEvent_1_1(createTsRecordEvent(), createTsRecordEventExt()); + } + break; + case DemuxFilterMainType::MMTP: + mCallback->onFilterEvent(createDownloadEvent()); + mCallback->onFilterEvent(createMmtpRecordEvent()); + if (mCallback_1_1 != NULL) { + mCallback_1_1->onFilterEvent_1_1(createMmtpRecordEvent(), + createMmtpRecordEventExt()); + } + break; + case DemuxFilterMainType::IP: + mCallback->onFilterEvent(createSectionEvent()); + mCallback->onFilterEvent(createIpPayloadEvent()); + break; + case DemuxFilterMainType::TLV: { + if (mCallback_1_1 != NULL) { + DemuxFilterEvent emptyFilterEvent; + mCallback_1_1->onFilterEvent_1_1(emptyFilterEvent, createMonitorEvent()); + } + break; + } + case DemuxFilterMainType::ALP: { + if (mCallback_1_1 != NULL) { + DemuxFilterEvent emptyFilterEvent; + mCallback_1_1->onFilterEvent_1_1(emptyFilterEvent, createRestartEvent()); + } + break; + } + default: + break; + } + return startFilterLoop(); +} + +Return Filter::stop() { + ALOGV("%s", __FUNCTION__); + mFilterThreadRunning = false; + std::lock_guard lock(mFilterThreadLock); + return Result::SUCCESS; +} + +Return Filter::flush() { + ALOGV("%s", __FUNCTION__); + + // temp implementation to flush the FMQ + int size = mFilterMQ->availableToRead(); + char* buffer = new char[size]; + mFilterMQ->read((unsigned char*)&buffer[0], size); + delete[] buffer; + mFilterStatus = DemuxFilterStatus::DATA_READY; + + return Result::SUCCESS; +} + +Return Filter::releaseAvHandle(const hidl_handle& avMemory, uint64_t avDataId) { + ALOGV("%s", __FUNCTION__); + + if (mSharedAvMemHandle != NULL && avMemory != NULL && + (mSharedAvMemHandle.getNativeHandle()->numFds > 0) && + (avMemory.getNativeHandle()->numFds > 0) && + (sameFile(avMemory.getNativeHandle()->data[0], + mSharedAvMemHandle.getNativeHandle()->data[0]))) { + freeSharedAvHandle(); + return Result::SUCCESS; + } + + if (mDataId2Avfd.find(avDataId) == mDataId2Avfd.end()) { + return Result::INVALID_ARGUMENT; + } + + ::close(mDataId2Avfd[avDataId]); + return Result::SUCCESS; +} + +Return Filter::close() { + ALOGV("%s", __FUNCTION__); + + mFilterThreadRunning = false; + std::lock_guard lock(mFilterThreadLock); + return mDemux->removeFilter(mFilterId); +} + +Return Filter::configureIpCid(uint32_t ipCid) { + ALOGV("%s", __FUNCTION__); + + if (mType.mainType != DemuxFilterMainType::IP) { + return Result::INVALID_STATE; + } + + mCid = ipCid; + return Result::SUCCESS; +} + +Return Filter::getAvSharedHandle(getAvSharedHandle_cb _hidl_cb) { + ALOGV("%s", __FUNCTION__); + + if (!mIsMediaFilter) { + _hidl_cb(Result::INVALID_STATE, NULL, BUFFER_SIZE_16M); + return Void(); + } + + if (mSharedAvMemHandle.getNativeHandle() != nullptr) { + _hidl_cb(Result::SUCCESS, mSharedAvMemHandle, BUFFER_SIZE_16M); + mUsingSharedAvMem = true; + return Void(); + } + + int av_fd = createAvIonFd(BUFFER_SIZE_16M); + if (av_fd == -1) { + _hidl_cb(Result::UNKNOWN_ERROR, NULL, 0); + return Void(); + } + + native_handle_t* nativeHandle = createNativeHandle(av_fd); + if (nativeHandle == NULL) { + ::close(av_fd); + _hidl_cb(Result::UNKNOWN_ERROR, NULL, 0); + return Void(); + } + mSharedAvMemHandle.setTo(nativeHandle, /*shouldOwn=*/true); + ::close(av_fd); + + _hidl_cb(Result::SUCCESS, mSharedAvMemHandle, BUFFER_SIZE_16M); + mUsingSharedAvMem = true; + return Void(); +} + +Return Filter::configureAvStreamType(const V1_1::AvStreamType& avStreamType) { + ALOGV("%s", __FUNCTION__); + + if (!mIsMediaFilter) { + return Result::UNAVAILABLE; + } + + switch (avStreamType.getDiscriminator()) { + case V1_1::AvStreamType::hidl_discriminator::audio: + mAudioStreamType = static_cast(avStreamType.audio()); + break; + case V1_1::AvStreamType::hidl_discriminator::video: + mVideoStreamType = static_cast(avStreamType.video()); + break; + default: + break; + } + + return Result::SUCCESS; +} + +Return Filter::configureMonitorEvent(uint32_t monitorEventTypes) { + ALOGV("%s", __FUNCTION__); + + DemuxFilterEvent emptyFilterEvent; + V1_1::DemuxFilterMonitorEvent monitorEvent; + V1_1::DemuxFilterEventExt eventExt; + + uint32_t newScramblingStatus = + monitorEventTypes & V1_1::DemuxFilterMonitorEventType::SCRAMBLING_STATUS; + uint32_t newIpCid = monitorEventTypes & V1_1::DemuxFilterMonitorEventType::IP_CID_CHANGE; + + // if scrambling status monitoring flipped, record the new state and send msg on enabling + if (newScramblingStatus ^ mScramblingStatusMonitored) { + mScramblingStatusMonitored = newScramblingStatus; + if (mScramblingStatusMonitored) { + if (mCallback_1_1 != nullptr) { + // Assuming current status is always NOT_SCRAMBLED + monitorEvent.scramblingStatus(V1_1::ScramblingStatus::NOT_SCRAMBLED); + eventExt.events.resize(1); + eventExt.events[0].monitorEvent(monitorEvent); + mCallback_1_1->onFilterEvent_1_1(emptyFilterEvent, eventExt); + } else { + return Result::INVALID_STATE; + } + } + } + + // if ip cid monitoring flipped, record the new state and send msg on enabling + if (newIpCid ^ mIpCidMonitored) { + mIpCidMonitored = newIpCid; + if (mIpCidMonitored) { + if (mCallback_1_1 != nullptr) { + // Return random cid + monitorEvent.cid(1); + eventExt.events.resize(1); + eventExt.events[0].monitorEvent(monitorEvent); + mCallback_1_1->onFilterEvent_1_1(emptyFilterEvent, eventExt); + } else { + return Result::INVALID_STATE; + } + } + } + + return Result::SUCCESS; +} + +bool Filter::createFilterMQ() { + ALOGV("%s", __FUNCTION__); + + // Create a synchronized FMQ that supports blocking read/write + std::unique_ptr tmpFilterMQ = + std::unique_ptr(new (std::nothrow) FilterMQ(mBufferSize, true)); + if (!tmpFilterMQ->isValid()) { + ALOGW("[Filter] Failed to create FMQ of filter with id: %" PRIu64, mFilterId); + return false; + } + + mFilterMQ = std::move(tmpFilterMQ); + + if (EventFlag::createEventFlag(mFilterMQ->getEventFlagWord(), &mFilterEventFlag) != OK) { + return false; + } + + return true; +} + +Result Filter::startFilterLoop() { + pthread_create(&mFilterThread, NULL, __threadLoopFilter, this); + pthread_setname_np(mFilterThread, "filter_waiting_loop"); + + return Result::SUCCESS; +} + +void* Filter::__threadLoopFilter(void* user) { + Filter* const self = static_cast(user); + self->filterThreadLoop(); + return 0; +} + +void Filter::filterThreadLoop() { + if (!mFilterThreadRunning) { + return; + } + std::lock_guard lock(mFilterThreadLock); + ALOGD("[Filter] filter %" PRIu64 " threadLoop start.", mFilterId); + + // For the first time of filter output, implementation needs to send the filter + // Event Callback without waiting for the DATA_CONSUMED to init the process. + while (mFilterThreadRunning) { + if (mFilterEvent.events.size() == 0 && mFilterEventExt.events.size() == 0) { + if (DEBUG_FILTER) { + ALOGD("[Filter] wait for filter data output."); + } + usleep(1000 * 1000); + continue; + } + + // After successfully write, send a callback and wait for the read to be done + if (mCallback_1_1 != nullptr) { + if (mConfigured) { + DemuxFilterEvent emptyEvent; + V1_1::DemuxFilterEventExt startEvent; + startEvent.events.resize(1); + startEvent.events[0].startId(mStartId++); + mCallback_1_1->onFilterEvent_1_1(emptyEvent, startEvent); + mConfigured = false; + } + mCallback_1_1->onFilterEvent_1_1(mFilterEvent, mFilterEventExt); + mFilterEventExt.events.resize(0); + } else if (mCallback != nullptr) { + mCallback->onFilterEvent(mFilterEvent); + } else { + ALOGD("[Filter] filter callback is not configured yet."); + mFilterThreadRunning = false; + return; + } + mFilterEvent.events.resize(0); + + freeAvHandle(); + mFilterStatus = DemuxFilterStatus::DATA_READY; + if (mCallback != nullptr) { + mCallback->onFilterStatus(mFilterStatus); + } else if (mCallback_1_1 != nullptr) { + mCallback_1_1->onFilterStatus(mFilterStatus); + } + break; + } + + while (mFilterThreadRunning) { + uint32_t efState = 0; + // We do not wait for the last round of written data to be read to finish the thread + // because the VTS can verify the reading itself. + for (int i = 0; i < SECTION_WRITE_COUNT; i++) { + if (!mFilterThreadRunning) { + break; + } + while (mFilterThreadRunning && mIsUsingFMQ) { + status_t status = mFilterEventFlag->wait( + static_cast(DemuxQueueNotifyBits::DATA_CONSUMED), &efState, + WAIT_TIMEOUT, true /* retry on spurious wake */); + if (status != OK) { + ALOGD("[Filter] wait for data consumed"); + continue; + } + break; + } + + maySendFilterStatusCallback(); + + while (mFilterThreadRunning) { + std::lock_guard lock(mFilterEventLock); + if (mFilterEvent.events.size() == 0 && mFilterEventExt.events.size() == 0) { + continue; + } + // After successfully write, send a callback and wait for the read to be done + if (mCallback_1_1 != nullptr) { + mCallback_1_1->onFilterEvent_1_1(mFilterEvent, mFilterEventExt); + mFilterEventExt.events.resize(0); + } else if (mCallback != nullptr) { + mCallback->onFilterEvent(mFilterEvent); + } + mFilterEvent.events.resize(0); + break; + } + // We do not wait for the last read to be done + // VTS can verify the read result itself. + if (i == SECTION_WRITE_COUNT - 1) { + ALOGD("[Filter] filter %" PRIu64 " writing done. Ending thread", mFilterId); + break; + } + } + break; + } + ALOGD("[Filter] filter thread ended."); +} + +void Filter::freeAvHandle() { + if (!mIsMediaFilter) { + return; + } + for (int i = 0; i < mFilterEvent.events.size(); i++) { + ::close(mFilterEvent.events[i].media().avMemory.getNativeHandle()->data[0]); + native_handle_delete(const_cast( + mFilterEvent.events[i].media().avMemory.getNativeHandle())); + } +} + +void Filter::freeSharedAvHandle() { + if (!mIsMediaFilter) { + return; + } + ::close(mSharedAvMemHandle.getNativeHandle()->data[0]); + native_handle_delete(const_cast(mSharedAvMemHandle.getNativeHandle())); +} + +void Filter::maySendFilterStatusCallback() { + if (!mIsUsingFMQ) { + return; + } + std::lock_guard lock(mFilterStatusLock); + int availableToRead = mFilterMQ->availableToRead(); + int availableToWrite = mFilterMQ->availableToWrite(); + int fmqSize = mFilterMQ->getQuantumCount(); + + DemuxFilterStatus newStatus = checkFilterStatusChange( + availableToWrite, availableToRead, ceil(fmqSize * 0.75), ceil(fmqSize * 0.25)); + if (mFilterStatus != newStatus) { + if (mCallback != nullptr) { + mCallback->onFilterStatus(newStatus); + } else if (mCallback_1_1 != nullptr) { + mCallback_1_1->onFilterStatus(newStatus); + } + mFilterStatus = newStatus; + } +} + +DemuxFilterStatus Filter::checkFilterStatusChange(uint32_t availableToWrite, + uint32_t availableToRead, uint32_t highThreshold, + uint32_t lowThreshold) { + if (availableToWrite == 0) { + return DemuxFilterStatus::OVERFLOW; + } else if (availableToRead > highThreshold) { + return DemuxFilterStatus::HIGH_WATER; + } else if (availableToRead < lowThreshold) { + return DemuxFilterStatus::LOW_WATER; + } + return mFilterStatus; +} + +uint16_t Filter::getTpid() { + return mTpid; +} + +void Filter::updateFilterOutput(vector data) { + std::lock_guard lock(mFilterOutputLock); + mFilterOutput.insert(mFilterOutput.end(), data.begin(), data.end()); +} + +void Filter::updatePts(uint64_t pts) { + std::lock_guard lock(mFilterOutputLock); + mPts = pts; +} + +void Filter::updateRecordOutput(vector data) { + std::lock_guard lock(mRecordFilterOutputLock); + mRecordFilterOutput.insert(mRecordFilterOutput.end(), data.begin(), data.end()); +} + +Result Filter::startFilterHandler() { + std::lock_guard lock(mFilterOutputLock); + switch (mType.mainType) { + case DemuxFilterMainType::TS: + switch (mType.subType.tsFilterType()) { + case DemuxTsFilterType::UNDEFINED: + break; + case DemuxTsFilterType::SECTION: + startSectionFilterHandler(); + break; + case DemuxTsFilterType::PES: + startPesFilterHandler(); + break; + case DemuxTsFilterType::TS: + startTsFilterHandler(); + break; + case DemuxTsFilterType::AUDIO: + case DemuxTsFilterType::VIDEO: + startMediaFilterHandler(); + break; + case DemuxTsFilterType::PCR: + startPcrFilterHandler(); + break; + case DemuxTsFilterType::TEMI: + startTemiFilterHandler(); + break; + default: + break; + } + break; + case DemuxFilterMainType::MMTP: + /*mmtpSettings*/ + break; + case DemuxFilterMainType::IP: + /*ipSettings*/ + break; + case DemuxFilterMainType::TLV: + /*tlvSettings*/ + break; + case DemuxFilterMainType::ALP: + /*alpSettings*/ + break; + default: + break; + } + return Result::SUCCESS; +} + +Result Filter::startSectionFilterHandler() { + if (mFilterOutput.empty()) { + return Result::SUCCESS; + } + if (!writeSectionsAndCreateEvent(mFilterOutput)) { + ALOGD("[Filter] filter %" PRIu64 " fails to write into FMQ. Ending thread", mFilterId); + return Result::UNKNOWN_ERROR; + } + + mFilterOutput.clear(); + + return Result::SUCCESS; +} + +Result Filter::startPesFilterHandler() { + std::lock_guard lock(mFilterEventLock); + if (mFilterOutput.empty()) { + return Result::SUCCESS; + } + + for (int i = 0; i < mFilterOutput.size(); i += 188) { + if (mPesSizeLeft == 0) { + uint32_t prefix = (mFilterOutput[i + 4] << 16) | (mFilterOutput[i + 5] << 8) | + mFilterOutput[i + 6]; + if (DEBUG_FILTER) { + ALOGD("[Filter] prefix %d", prefix); + } + if (prefix == 0x000001) { + // TODO handle mulptiple Pes filters + mPesSizeLeft = (mFilterOutput[i + 8] << 8) | mFilterOutput[i + 9]; + mPesSizeLeft += 6; + if (DEBUG_FILTER) { + ALOGD("[Filter] pes data length %d", mPesSizeLeft); + } + } else { + continue; + } + } + + int endPoint = min(184, mPesSizeLeft); + // append data and check size + vector::const_iterator first = mFilterOutput.begin() + i + 4; + vector::const_iterator last = mFilterOutput.begin() + i + 4 + endPoint; + mPesOutput.insert(mPesOutput.end(), first, last); + // size does not match then continue + mPesSizeLeft -= endPoint; + if (DEBUG_FILTER) { + ALOGD("[Filter] pes data left %d", mPesSizeLeft); + } + if (mPesSizeLeft > 0) { + continue; + } + // size match then create event + if (!writeDataToFilterMQ(mPesOutput)) { + ALOGD("[Filter] pes data write failed"); + mFilterOutput.clear(); + return Result::INVALID_STATE; + } + maySendFilterStatusCallback(); + DemuxFilterPesEvent pesEvent; + pesEvent = { + // temp dump meta data + .streamId = mPesOutput[3], + .dataLength = static_cast(mPesOutput.size()), + }; + if (DEBUG_FILTER) { + ALOGD("[Filter] assembled pes data length %d", pesEvent.dataLength); + } + + int size = mFilterEvent.events.size(); + mFilterEvent.events.resize(size + 1); + mFilterEvent.events[size].pes(pesEvent); + mPesOutput.clear(); + } + + mFilterOutput.clear(); + + return Result::SUCCESS; +} + +Result Filter::startTsFilterHandler() { + // TODO handle starting TS filter + return Result::SUCCESS; +} + +Result Filter::startMediaFilterHandler() { + std::lock_guard lock(mFilterEventLock); + if (mFilterOutput.empty()) { + return Result::SUCCESS; + } + + Result result; + if (mPts) { + result = createMediaFilterEventWithIon(mFilterOutput); + if (result == Result::SUCCESS) { + mFilterOutput.clear(); + } + return result; + } + + for (int i = 0; i < mFilterOutput.size(); i += 188) { + if (mPesSizeLeft == 0) { + uint32_t prefix = (mFilterOutput[i + 4] << 16) | (mFilterOutput[i + 5] << 8) | + mFilterOutput[i + 6]; + if (DEBUG_FILTER) { + ALOGD("[Filter] prefix %d", prefix); + } + if (prefix == 0x000001) { + // TODO handle mulptiple Pes filters + mPesSizeLeft = (mFilterOutput[i + 8] << 8) | mFilterOutput[i + 9]; + mPesSizeLeft += 6; + if (DEBUG_FILTER) { + ALOGD("[Filter] pes data length %d", mPesSizeLeft); + } + } else { + continue; + } + } + + int endPoint = min(184, mPesSizeLeft); + // append data and check size + vector::const_iterator first = mFilterOutput.begin() + i + 4; + vector::const_iterator last = mFilterOutput.begin() + i + 4 + endPoint; + mPesOutput.insert(mPesOutput.end(), first, last); + // size does not match then continue + mPesSizeLeft -= endPoint; + if (DEBUG_FILTER) { + ALOGD("[Filter] pes data left %d", mPesSizeLeft); + } + if (mPesSizeLeft > 0 || mAvBufferCopyCount++ < 10) { + continue; + } + + result = createMediaFilterEventWithIon(mPesOutput); + if (result != Result::SUCCESS) { + return result; + } + } + + mFilterOutput.clear(); + + return Result::SUCCESS; +} + +Result Filter::createMediaFilterEventWithIon(vector output) { + if (mUsingSharedAvMem) { + if (mSharedAvMemHandle.getNativeHandle() == nullptr) { + return Result::UNKNOWN_ERROR; + } + return createShareMemMediaEvents(output); + } + + return createIndependentMediaEvents(output); +} + +Result Filter::startRecordFilterHandler() { + std::lock_guard lock(mRecordFilterOutputLock); + if (mRecordFilterOutput.empty()) { + return Result::SUCCESS; + } + + if (mDvr == nullptr || !mDvr->writeRecordFMQ(mRecordFilterOutput)) { + ALOGD("[Filter] dvr fails to write into record FMQ."); + return Result::UNKNOWN_ERROR; + } + + V1_0::DemuxFilterTsRecordEvent recordEvent; + recordEvent = { + .byteNumber = mRecordFilterOutput.size(), + }; + V1_1::DemuxFilterTsRecordEventExt recordEventExt; + recordEventExt = { + .pts = (mPts == 0) ? time(NULL) * 900000 : mPts, + .firstMbInSlice = 0, // random address + }; + + int size; + size = mFilterEventExt.events.size(); + mFilterEventExt.events.resize(size + 1); + mFilterEventExt.events[size].tsRecord(recordEventExt); + size = mFilterEvent.events.size(); + mFilterEvent.events.resize(size + 1); + mFilterEvent.events[size].tsRecord(recordEvent); + + mRecordFilterOutput.clear(); + return Result::SUCCESS; +} + +Result Filter::startPcrFilterHandler() { + // TODO handle starting PCR filter + return Result::SUCCESS; +} + +Result Filter::startTemiFilterHandler() { + // TODO handle starting TEMI filter + return Result::SUCCESS; +} + +bool Filter::writeSectionsAndCreateEvent(vector data) { + // TODO check how many sections has been read + ALOGD("[Filter] section handler"); + std::lock_guard lock(mFilterEventLock); + if (!writeDataToFilterMQ(data)) { + return false; + } + int size = mFilterEvent.events.size(); + mFilterEvent.events.resize(size + 1); + DemuxFilterSectionEvent secEvent; + secEvent = { + // temp dump meta data + .tableId = 0, + .version = 1, + .sectionNum = 1, + .dataLength = static_cast(data.size()), + }; + mFilterEvent.events[size].section(secEvent); + return true; +} + +bool Filter::writeDataToFilterMQ(const std::vector& data) { + std::lock_guard lock(mWriteLock); + if (mFilterMQ->write(data.data(), data.size())) { + return true; + } + return false; +} + +void Filter::attachFilterToRecord(const sp dvr) { + mDvr = dvr; +} + +void Filter::detachFilterFromRecord() { + mDvr = nullptr; +} + +int Filter::createAvIonFd(int size) { + // Create an DMA-BUF fd and allocate an av fd mapped to a buffer to it. + auto buffer_allocator = std::make_unique(); + if (!buffer_allocator) { + ALOGE("[Filter] Unable to create BufferAllocator object"); + return -1; + } + int av_fd = -1; + av_fd = buffer_allocator->Alloc("system-uncached", size); + if (av_fd < 0) { + ALOGE("[Filter] Failed to create av fd %d", errno); + return -1; + } + return av_fd; +} + +uint8_t* Filter::getIonBuffer(int fd, int size) { + uint8_t* avBuf = static_cast( + mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 /*offset*/)); + if (avBuf == MAP_FAILED) { + ALOGE("[Filter] fail to allocate buffer %d", errno); + return NULL; + } + return avBuf; +} + +native_handle_t* Filter::createNativeHandle(int fd) { + native_handle_t* nativeHandle; + if (fd < 0) { + nativeHandle = native_handle_create(/*numFd*/ 0, 0); + } else { + // Create a native handle to pass the av fd via the callback event. + nativeHandle = native_handle_create(/*numFd*/ 1, 0); + } + if (nativeHandle == NULL) { + ALOGE("[Filter] Failed to create native_handle %d", errno); + return NULL; + } + if (nativeHandle->numFds > 0) { + nativeHandle->data[0] = dup(fd); + } + return nativeHandle; +} + +Result Filter::createIndependentMediaEvents(vector output) { + int av_fd = createAvIonFd(output.size()); + if (av_fd == -1) { + return Result::UNKNOWN_ERROR; + } + // copy the filtered data to the buffer + uint8_t* avBuffer = getIonBuffer(av_fd, output.size()); + if (avBuffer == NULL) { + return Result::UNKNOWN_ERROR; + } + memcpy(avBuffer, output.data(), output.size() * sizeof(uint8_t)); + + native_handle_t* nativeHandle = createNativeHandle(av_fd); + if (nativeHandle == NULL) { + return Result::UNKNOWN_ERROR; + } + hidl_handle handle; + handle.setTo(nativeHandle, /*shouldOwn=*/true); + + // Create a dataId and add a pair into the dataId2Avfd map + uint64_t dataId = mLastUsedDataId++ /*createdUID*/; + mDataId2Avfd[dataId] = dup(av_fd); + + // Create mediaEvent and send callback + DemuxFilterMediaEvent mediaEvent; + mediaEvent = { + .avMemory = std::move(handle), + .dataLength = static_cast(output.size()), + .avDataId = dataId, + }; + if (mPts) { + mediaEvent.pts = mPts; + mPts = 0; + } + int size = mFilterEvent.events.size(); + mFilterEvent.events.resize(size + 1); + mFilterEvent.events[size].media(mediaEvent); + + // Clear and log + output.clear(); + mAvBufferCopyCount = 0; + ::close(av_fd); + if (DEBUG_FILTER) { + ALOGD("[Filter] av data length %d", mediaEvent.dataLength); + } + return Result::SUCCESS; +} + +Result Filter::createShareMemMediaEvents(vector output) { + // copy the filtered data to the shared buffer + uint8_t* sharedAvBuffer = getIonBuffer(mSharedAvMemHandle.getNativeHandle()->data[0], + output.size() + mSharedAvMemOffset); + if (sharedAvBuffer == NULL) { + return Result::UNKNOWN_ERROR; + } + memcpy(sharedAvBuffer + mSharedAvMemOffset, output.data(), output.size() * sizeof(uint8_t)); + + // Create a memory handle with numFds == 0 + native_handle_t* nativeHandle = createNativeHandle(-1); + if (nativeHandle == NULL) { + return Result::UNKNOWN_ERROR; + } + hidl_handle handle; + handle.setTo(nativeHandle, /*shouldOwn=*/true); + + // Create mediaEvent and send callback + DemuxFilterMediaEvent mediaEvent; + mediaEvent = { + .offset = static_cast(mSharedAvMemOffset), + .dataLength = static_cast(output.size()), + .avMemory = handle, + }; + mSharedAvMemOffset += output.size(); + if (mPts) { + mediaEvent.pts = mPts; + mPts = 0; + } + int size = mFilterEvent.events.size(); + mFilterEvent.events.resize(size + 1); + mFilterEvent.events[size].media(mediaEvent); + + // Clear and log + output.clear(); + if (DEBUG_FILTER) { + ALOGD("[Filter] shared av data length %d", mediaEvent.dataLength); + } + return Result::SUCCESS; +} + +bool Filter::sameFile(int fd1, int fd2) { + struct stat stat1, stat2; + if (fstat(fd1, &stat1) < 0 || fstat(fd2, &stat2) < 0) { + return false; + } + return (stat1.st_dev == stat2.st_dev) && (stat1.st_ino == stat2.st_ino); +} + +DemuxFilterEvent Filter::createMediaEvent() { + DemuxFilterEvent event; + event.events.resize(1); + + event.events[0].media({ + .streamId = 1, + .isPtsPresent = true, + .pts = 2, + .dataLength = 3, + .offset = 4, + .isSecureMemory = true, + .mpuSequenceNumber = 6, + .isPesPrivateData = true, + }); + + event.events[0].media().extraMetaData.audio({ + .adFade = 1, + .adPan = 2, + .versionTextTag = 3, + .adGainCenter = 4, + .adGainFront = 5, + .adGainSurround = 6, + }); + + int av_fd = createAvIonFd(BUFFER_SIZE_16M); + if (av_fd == -1) { + return event; + } + + native_handle_t* nativeHandle = createNativeHandle(av_fd); + if (nativeHandle == NULL) { + ::close(av_fd); + ALOGE("[Filter] Failed to create native_handle %d", errno); + return event; + } + + // Create a dataId and add a pair into the dataId2Avfd map + uint64_t dataId = mLastUsedDataId++ /*createdUID*/; + mDataId2Avfd[dataId] = dup(av_fd); + event.events[0].media().avDataId = dataId; + + hidl_handle handle; + handle.setTo(nativeHandle, /*shouldOwn=*/true); + event.events[0].media().avMemory = std::move(handle); + ::close(av_fd); + + return event; +} + +DemuxFilterEvent Filter::createTsRecordEvent() { + DemuxFilterEvent event; + event.events.resize(1); + + DemuxPid pid; + pid.tPid(1); + DemuxFilterTsRecordEvent::ScIndexMask mask; + mask.sc(1); + event.events[0].tsRecord({ + .pid = pid, + .tsIndexMask = 1, + .scIndexMask = mask, + .byteNumber = 2, + }); + return event; +} + +V1_1::DemuxFilterEventExt Filter::createTsRecordEventExt() { + V1_1::DemuxFilterEventExt event; + event.events.resize(1); + + event.events[0].tsRecord({ + .pts = 1, + .firstMbInSlice = 2, // random address + }); + return event; +} + +DemuxFilterEvent Filter::createMmtpRecordEvent() { + DemuxFilterEvent event; + event.events.resize(1); + + event.events[0].mmtpRecord({ + .scHevcIndexMask = 1, + .byteNumber = 2, + }); + return event; +} + +V1_1::DemuxFilterEventExt Filter::createMmtpRecordEventExt() { + V1_1::DemuxFilterEventExt event; + event.events.resize(1); + + event.events[0].mmtpRecord({ + .pts = 1, + .mpuSequenceNumber = 2, + .firstMbInSlice = 3, + .tsIndexMask = 4, + }); + return event; +} + +DemuxFilterEvent Filter::createSectionEvent() { + DemuxFilterEvent event; + event.events.resize(1); + + event.events[0].section({ + .tableId = 1, + .version = 2, + .sectionNum = 3, + .dataLength = 0, + }); + return event; +} + +DemuxFilterEvent Filter::createPesEvent() { + DemuxFilterEvent event; + event.events.resize(1); + + event.events[0].pes({ + .streamId = static_cast(1), + .dataLength = 1, + .mpuSequenceNumber = 2, + }); + return event; +} + +DemuxFilterEvent Filter::createDownloadEvent() { + DemuxFilterEvent event; + event.events.resize(1); + + event.events[0].download({ + .itemId = 1, + .mpuSequenceNumber = 2, + .itemFragmentIndex = 3, + .lastItemFragmentIndex = 4, + .dataLength = 0, + }); + return event; +} + +DemuxFilterEvent Filter::createIpPayloadEvent() { + DemuxFilterEvent event; + event.events.resize(1); + + event.events[0].ipPayload({ + .dataLength = 0, + }); + return event; +} + +DemuxFilterEvent Filter::createTemiEvent() { + DemuxFilterEvent event; + event.events.resize(1); + + event.events[0].temi({.pts = 1, .descrTag = 2, .descrData = {3}}); + return event; +} + +V1_1::DemuxFilterEventExt Filter::createMonitorEvent() { + V1_1::DemuxFilterEventExt event; + event.events.resize(1); + + V1_1::DemuxFilterMonitorEvent monitor; + monitor.scramblingStatus(V1_1::ScramblingStatus::SCRAMBLED); + event.events[0].monitorEvent(monitor); + return event; +} + +V1_1::DemuxFilterEventExt Filter::createRestartEvent() { + V1_1::DemuxFilterEventExt event; + event.events.resize(1); + + event.events[0].startId(1); + return event; +} +} // namespace implementation +} // namespace V1_0 +} // namespace tuner +} // namespace tv +} // namespace hardware +} // namespace android diff --git a/tv/tuner/1.1/default/Filter.h b/tv/tuner/1.1/default/Filter.h new file mode 100644 index 0000000000000000000000000000000000000000..659bebf1781ef0a087691ce2ba6cbbf7a15aa88f --- /dev/null +++ b/tv/tuner/1.1/default/Filter.h @@ -0,0 +1,264 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_TV_TUNER_V1_1_FILTER_H_ +#define ANDROID_HARDWARE_TV_TUNER_V1_1_FILTER_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "Demux.h" +#include "Dvr.h" +#include "Frontend.h" + +using namespace std; + +namespace android { +namespace hardware { +namespace tv { +namespace tuner { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::EventFlag; +using ::android::hardware::kSynchronizedReadWrite; +using ::android::hardware::MessageQueue; +using ::android::hardware::MQDescriptorSync; + +using FilterMQ = MessageQueue; +const uint32_t BUFFER_SIZE_16M = 0x1000000; + +class Demux; +class Dvr; + +class Filter : public V1_1::IFilter { + public: + Filter(); + + Filter(DemuxFilterType type, uint64_t filterId, uint32_t bufferSize, + const sp& cb, sp demux); + + ~Filter(); + + virtual Return getId64Bit(getId64Bit_cb _hidl_cb) override; + + virtual Return getId(getId_cb _hidl_cb) override; + + virtual Return setDataSource(const sp& filter) override; + + virtual Return getQueueDesc(getQueueDesc_cb _hidl_cb) override; + + virtual Return configure(const DemuxFilterSettings& settings) override; + + virtual Return start() override; + + virtual Return stop() override; + + virtual Return flush() override; + + virtual Return releaseAvHandle(const hidl_handle& avMemory, uint64_t avDataId) override; + + virtual Return close() override; + + virtual Return configureIpCid(uint32_t ipCid) override; + + virtual Return getAvSharedHandle(getAvSharedHandle_cb _hidl_cb) override; + + virtual Return configureAvStreamType(const V1_1::AvStreamType& avStreamType) override; + + virtual Return configureMonitorEvent(uint32_t monitorEventTypes) override; + + /** + * To create a FilterMQ and its Event Flag. + * + * Return false is any of the above processes fails. + */ + bool createFilterMQ(); + uint16_t getTpid(); + void updateFilterOutput(vector data); + void updateRecordOutput(vector data); + void updatePts(uint64_t pts); + Result startFilterHandler(); + Result startRecordFilterHandler(); + void attachFilterToRecord(const sp dvr); + void detachFilterFromRecord(); + void freeAvHandle(); + void freeSharedAvHandle(); + bool isMediaFilter() { return mIsMediaFilter; }; + bool isPcrFilter() { return mIsPcrFilter; }; + bool isRecordFilter() { return mIsRecordFilter; }; + + private: + // Tuner service + sp mDemux; + // Dvr reference once the filter is attached to any + sp mDvr = nullptr; + /** + * Filter callbacks used on filter events or FMQ status + */ + sp mCallback = nullptr; + + /** + * V1_1 Filter callbacks used on filter events or FMQ status + */ + sp mCallback_1_1 = nullptr; + + uint64_t mFilterId; + uint32_t mCid = static_cast(V1_1::Constant::INVALID_IP_FILTER_CONTEXT_ID); + uint32_t mBufferSize; + DemuxFilterType mType; + bool mIsMediaFilter = false; + bool mIsPcrFilter = false; + bool mIsRecordFilter = false; + DemuxFilterSettings mFilterSettings; + + uint16_t mTpid; + sp mDataSource; + bool mIsDataSourceDemux = true; + vector mFilterOutput; + vector mRecordFilterOutput; + uint64_t mPts = 0; + unique_ptr mFilterMQ; + bool mIsUsingFMQ = false; + EventFlag* mFilterEventFlag; + DemuxFilterEvent mFilterEvent; + V1_1::DemuxFilterEventExt mFilterEventExt; + + // Thread handlers + pthread_t mFilterThread; + + // FMQ status local records + DemuxFilterStatus mFilterStatus; + /** + * If a specific filter's writing loop is still running + */ + bool mFilterThreadRunning; + bool mKeepFetchingDataFromFrontend; + + /** + * How many times a filter should write + * TODO make this dynamic/random/can take as a parameter + */ + const uint16_t SECTION_WRITE_COUNT = 10; + + bool DEBUG_FILTER = false; + + /** + * Filter handlers to handle the data filtering. + * They are also responsible to write the filtered output into the filter FMQ + * and update the filterEvent bound with the same filterId. + */ + Result startSectionFilterHandler(); + Result startPesFilterHandler(); + Result startTsFilterHandler(); + Result startMediaFilterHandler(); + Result startPcrFilterHandler(); + Result startTemiFilterHandler(); + Result startFilterLoop(); + + void deleteEventFlag(); + bool writeDataToFilterMQ(const std::vector& data); + bool readDataFromMQ(); + bool writeSectionsAndCreateEvent(vector data); + void maySendFilterStatusCallback(); + DemuxFilterStatus checkFilterStatusChange(uint32_t availableToWrite, uint32_t availableToRead, + uint32_t highThreshold, uint32_t lowThreshold); + /** + * A dispatcher to read and dispatch input data to all the started filters. + * Each filter handler handles the data filtering/output writing/filterEvent updating. + */ + void startTsFilter(vector data); + bool startFilterDispatcher(); + static void* __threadLoopFilter(void* user); + void filterThreadLoop(); + + int createAvIonFd(int size); + uint8_t* getIonBuffer(int fd, int size); + native_handle_t* createNativeHandle(int fd); + Result createMediaFilterEventWithIon(vector output); + Result createIndependentMediaEvents(vector output); + Result createShareMemMediaEvents(vector output); + bool sameFile(int fd1, int fd2); + + DemuxFilterEvent createMediaEvent(); + DemuxFilterEvent createTsRecordEvent(); + V1_1::DemuxFilterEventExt createTsRecordEventExt(); + DemuxFilterEvent createMmtpRecordEvent(); + V1_1::DemuxFilterEventExt createMmtpRecordEventExt(); + DemuxFilterEvent createSectionEvent(); + DemuxFilterEvent createPesEvent(); + DemuxFilterEvent createDownloadEvent(); + DemuxFilterEvent createIpPayloadEvent(); + DemuxFilterEvent createTemiEvent(); + V1_1::DemuxFilterEventExt createMonitorEvent(); + V1_1::DemuxFilterEventExt createRestartEvent(); + /** + * Lock to protect writes to the FMQs + */ + std::mutex mWriteLock; + /** + * Lock to protect writes to the filter event + */ + // TODO make each filter separate event lock + std::mutex mFilterEventLock; + /** + * Lock to protect writes to the input status + */ + std::mutex mFilterStatusLock; + std::mutex mFilterThreadLock; + std::mutex mFilterOutputLock; + std::mutex mRecordFilterOutputLock; + + // temp handle single PES filter + // TODO handle mulptiple Pes filters + int mPesSizeLeft = 0; + vector mPesOutput; + + // A map from data id to ion handle + std::map mDataId2Avfd; + uint64_t mLastUsedDataId = 1; + int mAvBufferCopyCount = 0; + + // Shared A/V memory handle + hidl_handle mSharedAvMemHandle; + bool mUsingSharedAvMem = false; + uint32_t mSharedAvMemOffset = 0; + + uint32_t mAudioStreamType; + uint32_t mVideoStreamType; + + // Scrambling status to be monitored + uint32_t mStatuses = 0; + + bool mConfigured = false; + int mStartId = 0; + uint8_t mScramblingStatusMonitored = 0; + uint8_t mIpCidMonitored = 0; +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace tuner +} // namespace tv +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_TV_TUNER_V1_1_FILTER_H_ diff --git a/tv/tuner/1.1/default/Frontend.cpp b/tv/tuner/1.1/default/Frontend.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e3fbdadc3f0cf14aa690fd2f8c675e1b878684a0 --- /dev/null +++ b/tv/tuner/1.1/default/Frontend.cpp @@ -0,0 +1,699 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "android.hardware.tv.tuner@1.1-Frontend" + +#include "Frontend.h" +#include +#include + +namespace android { +namespace hardware { +namespace tv { +namespace tuner { +namespace V1_0 { +namespace implementation { + +Frontend::Frontend(FrontendType type, FrontendId id, sp tuner) { + mType = type; + mId = id; + mTunerService = tuner; + // Init callback to nullptr + mCallback = nullptr; +} + +Frontend::~Frontend() {} + +Return Frontend::close() { + ALOGV("%s", __FUNCTION__); + // Reset callback + mCallback = nullptr; + mIsLocked = false; + mTunerService->removeFrontend(mId); + + return Result::SUCCESS; +} + +Return Frontend::setCallback(const sp& callback) { + ALOGV("%s", __FUNCTION__); + if (callback == nullptr) { + ALOGW("[ WARN ] Set Frontend callback with nullptr"); + return Result::INVALID_ARGUMENT; + } + + mCallback = callback; + return Result::SUCCESS; +} + +Return Frontend::tune(const FrontendSettings& /* settings */) { + ALOGV("%s", __FUNCTION__); + if (mCallback == nullptr) { + ALOGW("[ WARN ] Frontend callback is not set when tune"); + return Result::INVALID_STATE; + } + + mTunerService->frontendStartTune(mId); + mCallback->onEvent(FrontendEventType::LOCKED); + mIsLocked = true; + return Result::SUCCESS; +} + +Return Frontend::tune_1_1(const FrontendSettings& settings, + const V1_1::FrontendSettingsExt1_1& /*settingsExt1_1*/) { + ALOGV("%s", __FUNCTION__); + return tune(settings); +} + +Return Frontend::stopTune() { + ALOGV("%s", __FUNCTION__); + + mTunerService->frontendStopTune(mId); + mIsLocked = false; + + return Result::SUCCESS; +} + +Return Frontend::scan(const FrontendSettings& settings, FrontendScanType type) { + ALOGV("%s", __FUNCTION__); + FrontendScanMessage msg; + + if (mIsLocked) { + msg.isEnd(true); + mCallback->onScanMessage(FrontendScanMessageType::END, msg); + return Result::SUCCESS; + } + + uint32_t frequency; + switch (settings.getDiscriminator()) { + case FrontendSettings::hidl_discriminator::analog: + frequency = settings.analog().frequency; + break; + case FrontendSettings::hidl_discriminator::atsc: + frequency = settings.atsc().frequency; + break; + case FrontendSettings::hidl_discriminator::atsc3: + frequency = settings.atsc3().frequency; + break; + case FrontendSettings::hidl_discriminator::dvbs: + frequency = settings.dvbs().frequency; + break; + case FrontendSettings::hidl_discriminator::dvbc: + frequency = settings.dvbc().frequency; + break; + case FrontendSettings::hidl_discriminator::dvbt: + frequency = settings.dvbt().frequency; + break; + case FrontendSettings::hidl_discriminator::isdbs: + frequency = settings.isdbs().frequency; + break; + case FrontendSettings::hidl_discriminator::isdbs3: + frequency = settings.isdbs3().frequency; + break; + case FrontendSettings::hidl_discriminator::isdbt: + frequency = settings.isdbt().frequency; + break; + } + + if (type == FrontendScanType::SCAN_BLIND) { + frequency += 100; + } + + msg.frequencies({frequency}); + mCallback->onScanMessage(FrontendScanMessageType::FREQUENCY, msg); + + msg.progressPercent(20); + mCallback->onScanMessage(FrontendScanMessageType::PROGRESS_PERCENT, msg); + + msg.symbolRates({30}); + mCallback->onScanMessage(FrontendScanMessageType::SYMBOL_RATE, msg); + + if (mType == FrontendType::DVBT) { + msg.hierarchy(FrontendDvbtHierarchy::HIERARCHY_NON_NATIVE); + mCallback->onScanMessage(FrontendScanMessageType::HIERARCHY, msg); + } + + if (mType == FrontendType::ANALOG) { + msg.analogType(FrontendAnalogType::PAL); + mCallback->onScanMessage(FrontendScanMessageType::ANALOG_TYPE, msg); + } + + msg.plpIds({3}); + mCallback->onScanMessage(FrontendScanMessageType::PLP_IDS, msg); + + msg.groupIds({2}); + mCallback->onScanMessage(FrontendScanMessageType::GROUP_IDS, msg); + + msg.inputStreamIds({1}); + mCallback->onScanMessage(FrontendScanMessageType::INPUT_STREAM_IDS, msg); + + FrontendScanMessage::Standard s; + switch (mType) { + case FrontendType::DVBT: + s.tStd(FrontendDvbtStandard::AUTO); + msg.std(s); + mCallback->onScanMessage(FrontendScanMessageType::STANDARD, msg); + break; + case FrontendType::DVBS: + s.sStd(FrontendDvbsStandard::AUTO); + msg.std(s); + mCallback->onScanMessage(FrontendScanMessageType::STANDARD, msg); + break; + case FrontendType::ANALOG: + s.sifStd(FrontendAnalogSifStandard::AUTO); + msg.std(s); + mCallback->onScanMessage(FrontendScanMessageType::STANDARD, msg); + break; + default: + break; + } + + FrontendScanAtsc3PlpInfo info{ + .plpId = 1, + .bLlsFlag = false, + }; + msg.atsc3PlpInfos({info}); + mCallback->onScanMessage(FrontendScanMessageType::ATSC3_PLP_INFO, msg); + + sp frontendCallback_v1_1 = + V1_1::IFrontendCallback::castFrom(mCallback); + if (frontendCallback_v1_1 != NULL) { + V1_1::FrontendScanMessageExt1_1 msg; + msg.modulation().dvbc(FrontendDvbcModulation::MOD_16QAM); + frontendCallback_v1_1->onScanMessageExt1_1(V1_1::FrontendScanMessageTypeExt1_1::MODULATION, + msg); + msg.isHighPriority(true); + frontendCallback_v1_1->onScanMessageExt1_1( + V1_1::FrontendScanMessageTypeExt1_1::HIGH_PRIORITY, msg); + } else { + ALOGD("[Frontend] Couldn't cast to V1_1 IFrontendCallback"); + } + + msg.isLocked(true); + mCallback->onScanMessage(FrontendScanMessageType::LOCKED, msg); + mIsLocked = true; + + return Result::SUCCESS; +} + +Return Frontend::scan_1_1(const FrontendSettings& settings, FrontendScanType type, + const V1_1::FrontendSettingsExt1_1& settingsExt1_1) { + ALOGV("%s", __FUNCTION__); + ALOGD("[Frontend] scan_1_1 end frequency %d", settingsExt1_1.endFrequency); + return scan(settings, type); +} + +Return Frontend::stopScan() { + ALOGV("%s", __FUNCTION__); + + mIsLocked = false; + return Result::SUCCESS; +} + +Return Frontend::getStatus(const hidl_vec& statusTypes, + getStatus_cb _hidl_cb) { + ALOGV("%s", __FUNCTION__); + + vector statuses; + for (int i = 0; i < statusTypes.size(); i++) { + FrontendStatusType type = statusTypes[i]; + FrontendStatus status; + // assign randomly selected values for testing. + switch (type) { + case FrontendStatusType::DEMOD_LOCK: { + status.isDemodLocked(true); + break; + } + case FrontendStatusType::SNR: { + status.snr(221); + break; + } + case FrontendStatusType::BER: { + status.ber(1); + break; + } + case FrontendStatusType::PER: { + status.per(2); + break; + } + case FrontendStatusType::PRE_BER: { + status.preBer(3); + break; + } + case FrontendStatusType::SIGNAL_QUALITY: { + status.signalQuality(4); + break; + } + case FrontendStatusType::SIGNAL_STRENGTH: { + status.signalStrength(5); + break; + } + case FrontendStatusType::SYMBOL_RATE: { + status.symbolRate(6); + break; + } + case FrontendStatusType::FEC: { + status.innerFec(FrontendInnerFec::FEC_2_9); // value = 1 << 7 + break; + } + case FrontendStatusType::MODULATION: { + FrontendModulationStatus modulationStatus; + switch (mType) { + case FrontendType::ISDBS: { + modulationStatus.isdbs( + FrontendIsdbsModulation::MOD_BPSK); // value = 1 << 1 + status.modulation(modulationStatus); + break; + } + case FrontendType::DVBC: { + modulationStatus.dvbc(FrontendDvbcModulation::MOD_16QAM); // value = 1 << 1 + status.modulation(modulationStatus); + break; + } + case FrontendType::DVBS: { + modulationStatus.dvbs(FrontendDvbsModulation::MOD_QPSK); // value = 1 << 1 + status.modulation(modulationStatus); + break; + } + case FrontendType::ISDBS3: { + modulationStatus.isdbs3( + FrontendIsdbs3Modulation::MOD_BPSK); // value = 1 << 1 + status.modulation(modulationStatus); + break; + } + case FrontendType::ISDBT: { + modulationStatus.isdbt( + FrontendIsdbtModulation::MOD_DQPSK); // value = 1 << 1 + status.modulation(modulationStatus); + break; + } + default: + break; + } + break; + } + case FrontendStatusType::SPECTRAL: { + status.inversion(FrontendDvbcSpectralInversion::NORMAL); + break; + } + case FrontendStatusType::LNB_VOLTAGE: { + status.lnbVoltage(LnbVoltage::VOLTAGE_5V); + break; + } + case FrontendStatusType::PLP_ID: { + status.plpId(101); // type uint8_t + break; + } + case FrontendStatusType::EWBS: { + status.isEWBS(false); + break; + } + case FrontendStatusType::AGC: { + status.agc(7); + break; + } + case FrontendStatusType::LNA: { + status.isLnaOn(false); + break; + } + case FrontendStatusType::LAYER_ERROR: { + vector v = {false, true, true}; + status.isLayerError(v); + break; + } + case FrontendStatusType::MER: { + status.mer(8); + break; + } + case FrontendStatusType::FREQ_OFFSET: { + status.freqOffset(9); + break; + } + case FrontendStatusType::HIERARCHY: { + status.hierarchy(FrontendDvbtHierarchy::HIERARCHY_1_NATIVE); + break; + } + case FrontendStatusType::RF_LOCK: { + status.isRfLocked(false); + break; + } + case FrontendStatusType::ATSC3_PLP_INFO: { + vector v; + FrontendStatusAtsc3PlpInfo info1{ + .plpId = 3, + .isLocked = false, + .uec = 313, + }; + FrontendStatusAtsc3PlpInfo info2{ + .plpId = 5, + .isLocked = true, + .uec = 515, + }; + v.push_back(info1); + v.push_back(info2); + status.plpInfo(v); + break; + } + default: { + continue; + } + } + statuses.push_back(status); + } + _hidl_cb(Result::SUCCESS, statuses); + + return Void(); +} + +Return Frontend::getStatusExt1_1(const hidl_vec& statusTypes, + V1_1::IFrontend::getStatusExt1_1_cb _hidl_cb) { + ALOGV("%s", __FUNCTION__); + + vector statuses; + for (int i = 0; i < statusTypes.size(); i++) { + V1_1::FrontendStatusTypeExt1_1 type = statusTypes[i]; + V1_1::FrontendStatusExt1_1 status; + + switch (type) { + case V1_1::FrontendStatusTypeExt1_1::MODULATIONS: { + vector modulations; + V1_1::FrontendModulation modulation; + switch ((int)mType) { + case (int)FrontendType::ISDBS: { + modulation.isdbs(FrontendIsdbsModulation::MOD_BPSK); // value = 1 << 1 + modulations.push_back(modulation); + status.modulations(modulations); + break; + } + case (int)FrontendType::DVBC: { + modulation.dvbc(FrontendDvbcModulation::MOD_16QAM); // value = 1 << 1 + modulations.push_back(modulation); + status.modulations(modulations); + break; + } + case (int)FrontendType::DVBS: { + modulation.dvbs(FrontendDvbsModulation::MOD_QPSK); // value = 1 << 1 + modulations.push_back(modulation); + status.modulations(modulations); + break; + } + case (int)FrontendType::DVBT: { + // value = 1 << 16 + modulation.dvbt(V1_1::FrontendDvbtConstellation::CONSTELLATION_16QAM_R); + modulations.push_back(modulation); + status.modulations(modulations); + break; + } + case (int)FrontendType::ISDBS3: { + modulation.isdbs3(FrontendIsdbs3Modulation::MOD_BPSK); // value = 1 << 1 + modulations.push_back(modulation); + status.modulations(modulations); + break; + } + case (int)FrontendType::ISDBT: { + modulation.isdbt(FrontendIsdbtModulation::MOD_DQPSK); // value = 1 << 1 + modulations.push_back(modulation); + status.modulations(modulations); + break; + } + case (int)FrontendType::ATSC: { + modulation.atsc(FrontendAtscModulation::MOD_8VSB); // value = 1 << 2 + modulations.push_back(modulation); + status.modulations(modulations); + break; + } + case (int)FrontendType::ATSC3: { + modulation.atsc3(FrontendAtsc3Modulation::MOD_QPSK); // value = 1 << 1 + modulations.push_back(modulation); + status.modulations(modulations); + break; + } + case (int)V1_1::FrontendType::DTMB: { + // value = 1 << 1 + modulation.dtmb(V1_1::FrontendDtmbModulation::CONSTELLATION_4QAM); + modulations.push_back(modulation); + status.modulations(modulations); + break; + } + default: + break; + } + break; + } + case V1_1::FrontendStatusTypeExt1_1::BERS: { + vector bers = {1}; + status.bers(bers); + break; + } + case V1_1::FrontendStatusTypeExt1_1::CODERATES: { + // value = 1 << 39 + vector codeRates = {V1_1::FrontendInnerFec::FEC_6_15}; + status.codeRates(codeRates); + break; + } + case V1_1::FrontendStatusTypeExt1_1::BANDWIDTH: { + V1_1::FrontendBandwidth bandwidth; + switch ((int)mType) { + case (int)FrontendType::DVBC: { + // value = 1 << 1 + bandwidth.dvbc(V1_1::FrontendDvbcBandwidth::BANDWIDTH_6MHZ); + status.bandwidth(bandwidth); + break; + } + case (int)FrontendType::DVBT: { + // value = 1 << 1 + bandwidth.dvbt(FrontendDvbtBandwidth::BANDWIDTH_8MHZ); + status.bandwidth(bandwidth); + break; + } + case (int)FrontendType::ISDBT: { + bandwidth.isdbt(FrontendIsdbtBandwidth::BANDWIDTH_8MHZ); // value = 1 << 1 + status.bandwidth(bandwidth); + break; + } + case (int)FrontendType::ATSC3: { + bandwidth.atsc3(FrontendAtsc3Bandwidth::BANDWIDTH_6MHZ); // value = 1 << 1 + status.bandwidth(bandwidth); + break; + } + case (int)V1_1::FrontendType::DTMB: { + // value = 1 << 1 + bandwidth.dtmb(V1_1::FrontendDtmbBandwidth::BANDWIDTH_8MHZ); + status.bandwidth(bandwidth); + break; + } + default: + break; + } + break; + } + case V1_1::FrontendStatusTypeExt1_1::GUARD_INTERVAL: { + V1_1::FrontendGuardInterval interval; + switch ((int)mType) { + case (int)FrontendType::DVBT: { + interval.dvbt(FrontendDvbtGuardInterval::INTERVAL_1_32); // value = 1 << 1 + status.interval(interval); + break; + } + case (int)FrontendType::ISDBT: { + interval.isdbt(FrontendDvbtGuardInterval::INTERVAL_1_32); // value = 1 << 1 + status.interval(interval); + break; + } + case (int)V1_1::FrontendType::DTMB: { + // value = 1 << 1 + interval.dtmb(V1_1::FrontendDtmbGuardInterval::PN_420_VARIOUS); + status.interval(interval); + break; + } + default: + break; + } + break; + } + case V1_1::FrontendStatusTypeExt1_1::TRANSMISSION_MODE: { + V1_1::FrontendTransmissionMode transMode; + switch ((int)mType) { + case (int)FrontendType::DVBT: { + // value = 1 << 8 + transMode.dvbt(V1_1::FrontendDvbtTransmissionMode::MODE_16K_E); + status.transmissionMode(transMode); + break; + } + case (int)FrontendType::ISDBT: { + transMode.isdbt(FrontendIsdbtMode::MODE_1); // value = 1 << 1 + status.transmissionMode(transMode); + break; + } + case (int)V1_1::FrontendType::DTMB: { + transMode.dtmb(V1_1::FrontendDtmbTransmissionMode::C1); // value = 1 << 1 + status.transmissionMode(transMode); + break; + } + default: + break; + } + break; + } + case V1_1::FrontendStatusTypeExt1_1::UEC: { + status.uec(4); + break; + } + case V1_1::FrontendStatusTypeExt1_1::T2_SYSTEM_ID: { + status.systemId(5); + break; + } + case V1_1::FrontendStatusTypeExt1_1::INTERLEAVINGS: { + V1_1::FrontendInterleaveMode interleave; + switch ((int)mType) { + case (int)FrontendType::DVBC: { + // value = 1 << 1 + interleave.dvbc( + V1_1::FrontendCableTimeInterleaveMode::INTERLEAVING_128_1_0); + vector interleaving = {interleave}; + status.interleaving(interleaving); + break; + } + case (int)FrontendType::ATSC3: { + // value = 1 << 1 + interleave.atsc3(FrontendAtsc3TimeInterleaveMode::CTI); + vector interleaving = {interleave}; + status.interleaving(interleaving); + break; + } + case (int)V1_1::FrontendType::DTMB: { + // value = 1 << 1 + interleave.dtmb(V1_1::FrontendDtmbTimeInterleaveMode::TIMER_INT_240); + vector interleaving = {interleave}; + status.interleaving(interleaving); + break; + } + default: + break; + } + break; + } + case V1_1::FrontendStatusTypeExt1_1::ISDBT_SEGMENTS: { + vector segments = {2, 3}; + status.isdbtSegment(segments); + break; + } + case V1_1::FrontendStatusTypeExt1_1::TS_DATA_RATES: { + vector dataRates = {4, 5}; + status.tsDataRate(dataRates); + break; + } + case V1_1::FrontendStatusTypeExt1_1::ROLL_OFF: { + V1_1::FrontendRollOff rollOff; + switch (mType) { + case FrontendType::DVBS: { + // value = 1 + rollOff.dvbs(FrontendDvbsRolloff::ROLLOFF_0_35); + status.rollOff(rollOff); + break; + } + case FrontendType::ISDBS: { + // value = 1 + rollOff.isdbs(FrontendIsdbsRolloff::ROLLOFF_0_35); + status.rollOff(rollOff); + break; + } + case FrontendType::ISDBS3: { + // value = 1 + rollOff.isdbs3(FrontendIsdbs3Rolloff::ROLLOFF_0_03); + status.rollOff(rollOff); + break; + } + default: + break; + } + break; + } + case V1_1::FrontendStatusTypeExt1_1::IS_MISO: { + status.isMiso(true); + break; + } + case V1_1::FrontendStatusTypeExt1_1::IS_LINEAR: { + status.isLinear(true); + break; + } + case V1_1::FrontendStatusTypeExt1_1::IS_SHORT_FRAMES: { + status.isShortFrames(true); + break; + } + default: { + continue; + } + } + statuses.push_back(status); + } + _hidl_cb(Result::SUCCESS, statuses); + + return Void(); +} + +Return Frontend::setLna(bool /* bEnable */) { + ALOGV("%s", __FUNCTION__); + + return Result::SUCCESS; +} + +Return Frontend::setLnb(uint32_t /* lnb */) { + ALOGV("%s", __FUNCTION__); + if (!supportsSatellite()) { + return Result::INVALID_STATE; + } + return Result::SUCCESS; +} + +Return Frontend::linkCiCam(uint32_t ciCamId, linkCiCam_cb _hidl_cb) { + ALOGV("%s", __FUNCTION__); + + mCiCamId = ciCamId; + _hidl_cb(Result::SUCCESS, 0 /*ltsId*/); + + return Void(); +} + +Return Frontend::unlinkCiCam(uint32_t /*ciCamId*/) { + ALOGV("%s", __FUNCTION__); + + mCiCamId = -1; + + return Result::SUCCESS; +} + +FrontendType Frontend::getFrontendType() { + return mType; +} + +FrontendId Frontend::getFrontendId() { + return mId; +} + +bool Frontend::supportsSatellite() { + return mType == FrontendType::DVBS || mType == FrontendType::ISDBS || + mType == FrontendType::ISDBS3; +} + +bool Frontend::isLocked() { + return mIsLocked; +} +} // namespace implementation +} // namespace V1_0 +} // namespace tuner +} // namespace tv +} // namespace hardware +} // namespace android diff --git a/tv/tuner/1.1/default/Frontend.h b/tv/tuner/1.1/default/Frontend.h new file mode 100644 index 0000000000000000000000000000000000000000..a28fb6483bff786b20d15e77c7c5d85832a00e2c --- /dev/null +++ b/tv/tuner/1.1/default/Frontend.h @@ -0,0 +1,101 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_TV_TUNER_V1_1_FRONTEND_H_ +#define ANDROID_HARDWARE_TV_TUNER_V1_1_FRONTEND_H_ + +#include +#include +#include +#include "Tuner.h" + +using namespace std; + +namespace android { +namespace hardware { +namespace tv { +namespace tuner { +namespace V1_0 { +namespace implementation { + +class Tuner; + +class Frontend : public V1_1::IFrontend { + public: + Frontend(FrontendType type, FrontendId id, sp tuner); + + virtual Return close() override; + + virtual Return setCallback(const sp& callback) override; + + virtual Return tune(const FrontendSettings& settings) override; + + virtual Return tune_1_1(const FrontendSettings& settings, + const V1_1::FrontendSettingsExt1_1& settingsExt1_1) override; + + virtual Return stopTune() override; + + virtual Return scan(const FrontendSettings& settings, FrontendScanType type) override; + + virtual Return scan_1_1(const FrontendSettings& settings, FrontendScanType type, + const V1_1::FrontendSettingsExt1_1& settingsExt1_1) override; + + virtual Return stopScan() override; + + virtual Return getStatus(const hidl_vec& statusTypes, + getStatus_cb _hidl_cb) override; + + virtual Return getStatusExt1_1( + const hidl_vec& statusTypes, + V1_1::IFrontend::getStatusExt1_1_cb _hidl_cb) override; + + virtual Return setLna(bool bEnable) override; + + virtual Return setLnb(uint32_t lnb) override; + + virtual Return linkCiCam(uint32_t ciCamId, linkCiCam_cb _hidl_cb) override; + + virtual Return unlinkCiCam(uint32_t ciCamId) override; + + FrontendType getFrontendType(); + + FrontendId getFrontendId(); + + string getSourceFile(); + + bool isLocked(); + + private: + virtual ~Frontend(); + bool supportsSatellite(); + sp mCallback; + sp mTunerService; + FrontendType mType = FrontendType::UNDEFINED; + FrontendId mId = 0; + bool mIsLocked = false; + uint32_t mCiCamId; + + std::ifstream mFrontendData; +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace tuner +} // namespace tv +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_TV_TUNER_V1_1_FRONTEND_H_ diff --git a/tv/tuner/1.1/default/Lnb.cpp b/tv/tuner/1.1/default/Lnb.cpp new file mode 100644 index 0000000000000000000000000000000000000000..044727ff544b1042e6056cf0d1c735694751e0b8 --- /dev/null +++ b/tv/tuner/1.1/default/Lnb.cpp @@ -0,0 +1,81 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "android.hardware.tv.tuner@1.1-Lnb" + +#include "Lnb.h" +#include + +namespace android { +namespace hardware { +namespace tv { +namespace tuner { +namespace V1_0 { +namespace implementation { + +Lnb::Lnb() {} +Lnb::Lnb(int id) { + mId = id; +} + +Lnb::~Lnb() {} + +Return Lnb::setCallback(const sp& /* callback */) { + ALOGV("%s", __FUNCTION__); + + return Result::SUCCESS; +} + +Return Lnb::setVoltage(LnbVoltage /* voltage */) { + ALOGV("%s", __FUNCTION__); + + return Result::SUCCESS; +} + +Return Lnb::setTone(LnbTone /* tone */) { + ALOGV("%s", __FUNCTION__); + + return Result::SUCCESS; +} + +Return Lnb::setSatellitePosition(LnbPosition /* position */) { + ALOGV("%s", __FUNCTION__); + + return Result::SUCCESS; +} + +Return Lnb::sendDiseqcMessage(const hidl_vec& /* diseqcMessage */) { + ALOGV("%s", __FUNCTION__); + + return Result::SUCCESS; +} + +Return Lnb::close() { + ALOGV("%s", __FUNCTION__); + + return Result::SUCCESS; +} + +int Lnb::getId() { + return mId; +} + +} // namespace implementation +} // namespace V1_0 +} // namespace tuner +} // namespace tv +} // namespace hardware +} // namespace android diff --git a/tv/tuner/1.1/default/Lnb.h b/tv/tuner/1.1/default/Lnb.h new file mode 100644 index 0000000000000000000000000000000000000000..70a8e41b8b9ab27157a0424cbe910b407f817e6c --- /dev/null +++ b/tv/tuner/1.1/default/Lnb.h @@ -0,0 +1,63 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_TV_TUNER_V1_1_LNB_H_ +#define ANDROID_HARDWARE_TV_TUNER_V1_1_LNB_H_ + +#include +#include + +using namespace std; + +namespace android { +namespace hardware { +namespace tv { +namespace tuner { +namespace V1_0 { +namespace implementation { + +class Lnb : public ILnb { + public: + Lnb(); + Lnb(int id); + + virtual Return setCallback(const sp& callback) override; + + virtual Return setVoltage(LnbVoltage voltage) override; + + virtual Return setTone(LnbTone tone) override; + + virtual Return setSatellitePosition(LnbPosition position) override; + + virtual Return sendDiseqcMessage(const hidl_vec& diseqcMessage) override; + + virtual Return close() override; + + int getId(); + + private: + int mId; + virtual ~Lnb(); +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace tuner +} // namespace tv +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_TV_TUNER_V1_1_LNB_H_ diff --git a/tv/tuner/1.1/default/OWNERS b/tv/tuner/1.1/default/OWNERS new file mode 100644 index 0000000000000000000000000000000000000000..1b3d095f9ce88cdeecf2a9da0f2fb45bb793369e --- /dev/null +++ b/tv/tuner/1.1/default/OWNERS @@ -0,0 +1,4 @@ +nchalko@google.com +amyjojo@google.com +shubang@google.com +quxiangfang@google.com diff --git a/tv/tuner/1.1/default/TimeFilter.cpp b/tv/tuner/1.1/default/TimeFilter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bb243a66bcaef3667f15f4234302a164ba14c243 --- /dev/null +++ b/tv/tuner/1.1/default/TimeFilter.cpp @@ -0,0 +1,87 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "android.hardware.tv.tuner@1.1-TimeFilter" + +#include "TimeFilter.h" +#include + +namespace android { +namespace hardware { +namespace tv { +namespace tuner { +namespace V1_0 { +namespace implementation { + +TimeFilter::TimeFilter() {} + +TimeFilter::TimeFilter(sp demux) { + mDemux = demux; +} + +TimeFilter::~TimeFilter() {} + +Return TimeFilter::setTimeStamp(uint64_t timeStamp) { + ALOGV("%s", __FUNCTION__); + if (timeStamp == INVALID_TIME_STAMP) { + return Result::INVALID_ARGUMENT; + } + mTimeStamp = timeStamp; + mBeginTime = time(NULL); + + return Result::SUCCESS; +} + +Return TimeFilter::clearTimeStamp() { + ALOGV("%s", __FUNCTION__); + mTimeStamp = INVALID_TIME_STAMP; + + return Result::SUCCESS; +} + +Return TimeFilter::getTimeStamp(getTimeStamp_cb _hidl_cb) { + ALOGV("%s", __FUNCTION__); + if (mTimeStamp == INVALID_TIME_STAMP) { + _hidl_cb(Result::INVALID_STATE, mTimeStamp); + } + + uint64_t currentTimeStamp = mTimeStamp + difftime(time(NULL), mBeginTime) * 900000; + _hidl_cb(Result::SUCCESS, currentTimeStamp); + return Void(); +} + +Return TimeFilter::getSourceTime(getSourceTime_cb _hidl_cb) { + ALOGV("%s", __FUNCTION__); + + uint64_t time = 0; + + _hidl_cb(Result::SUCCESS, time); + return Void(); +} + +Return TimeFilter::close() { + ALOGV("%s", __FUNCTION__); + mTimeStamp = INVALID_TIME_STAMP; + + return Result::SUCCESS; +} + +} // namespace implementation +} // namespace V1_0 +} // namespace tuner +} // namespace tv +} // namespace hardware +} // namespace android \ No newline at end of file diff --git a/tv/tuner/1.1/default/TimeFilter.h b/tv/tuner/1.1/default/TimeFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..d53ad2c90066edf0ba45f37a8fcfdb22bf79fd6f --- /dev/null +++ b/tv/tuner/1.1/default/TimeFilter.h @@ -0,0 +1,70 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_TV_TUNER_V1_1_TIMEFILTER_H_ +#define ANDROID_HARDWARE_TV_TUNER_V1_1_TIMEFILTER_H_ + +#include +#include "Demux.h" +#include "time.h" + +using namespace std; + +namespace android { +namespace hardware { +namespace tv { +namespace tuner { +namespace V1_0 { +namespace implementation { + +using FilterMQ = MessageQueue; + +#define INVALID_TIME_STAMP -1 + +class Demux; + +class TimeFilter : public ITimeFilter { + public: + TimeFilter(); + + TimeFilter(sp demux); + + ~TimeFilter(); + + virtual Return setTimeStamp(uint64_t timeStamp) override; + + virtual Return clearTimeStamp() override; + + virtual Return getTimeStamp(getTimeStamp_cb _hidl_cb) override; + + virtual Return getSourceTime(getSourceTime_cb _hidl_cb) override; + + virtual Return close() override; + + private: + sp mDemux; + uint64_t mTimeStamp = INVALID_TIME_STAMP; + time_t mBeginTime; +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace tuner +} // namespace tv +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_TV_TUNER_V1_1_TIMEFILTER_H_ \ No newline at end of file diff --git a/tv/tuner/1.1/default/Tuner.cpp b/tv/tuner/1.1/default/Tuner.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1e940ba0987bf31ce913e2ba4bafa3b04af732b1 --- /dev/null +++ b/tv/tuner/1.1/default/Tuner.cpp @@ -0,0 +1,380 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "android.hardware.tv.tuner@1.1-Tuner" + +#include "Tuner.h" +#include +#include "Demux.h" +#include "Descrambler.h" +#include "Frontend.h" +#include "Lnb.h" + +namespace android { +namespace hardware { +namespace tv { +namespace tuner { +namespace V1_0 { +namespace implementation { + +Tuner::Tuner() { + // Static Frontends array to maintain local frontends information + // Array index matches their FrontendId in the default impl + mFrontendSize = 10; + mFrontends[0] = new Frontend(FrontendType::ISDBS, 0, this); + mFrontends[1] = new Frontend(FrontendType::ATSC3, 1, this); + mFrontends[2] = new Frontend(FrontendType::DVBC, 2, this); + mFrontends[3] = new Frontend(FrontendType::DVBS, 3, this); + mFrontends[4] = new Frontend(FrontendType::DVBT, 4, this); + mFrontends[5] = new Frontend(FrontendType::ISDBT, 5, this); + mFrontends[6] = new Frontend(FrontendType::ANALOG, 6, this); + mFrontends[7] = new Frontend(FrontendType::ATSC, 7, this); + mFrontends[8] = new Frontend(FrontendType::ISDBS3, 8, this); + mFrontends[9] = + new Frontend(static_cast(V1_1::FrontendType::DTMB), 9, this); + + FrontendInfo::FrontendCapabilities caps; + vector statusCaps; + + caps = FrontendInfo::FrontendCapabilities(); + caps.isdbsCaps(FrontendIsdbsCapabilities()); + mFrontendCaps[0] = caps; + statusCaps = { + FrontendStatusType::DEMOD_LOCK, + FrontendStatusType::SNR, + FrontendStatusType::FEC, + FrontendStatusType::MODULATION, + static_cast(V1_1::FrontendStatusTypeExt1_1::MODULATIONS), + static_cast(V1_1::FrontendStatusTypeExt1_1::ROLL_OFF), + }; + mFrontendStatusCaps[0] = statusCaps; + + caps = FrontendInfo::FrontendCapabilities(); + caps.atsc3Caps(FrontendAtsc3Capabilities()); + mFrontendCaps[1] = caps; + statusCaps = { + FrontendStatusType::BER, + FrontendStatusType::PER, + FrontendStatusType::ATSC3_PLP_INFO, + static_cast(V1_1::FrontendStatusTypeExt1_1::MODULATIONS), + static_cast(V1_1::FrontendStatusTypeExt1_1::BERS), + static_cast(V1_1::FrontendStatusTypeExt1_1::INTERLEAVINGS), + static_cast(V1_1::FrontendStatusTypeExt1_1::BANDWIDTH), + }; + mFrontendStatusCaps[1] = statusCaps; + + caps = FrontendInfo::FrontendCapabilities(); + caps.dvbcCaps(FrontendDvbcCapabilities()); + mFrontendCaps[2] = caps; + statusCaps = { + FrontendStatusType::PRE_BER, + FrontendStatusType::SIGNAL_QUALITY, + FrontendStatusType::MODULATION, + FrontendStatusType::SPECTRAL, + static_cast(V1_1::FrontendStatusTypeExt1_1::MODULATIONS), + static_cast(V1_1::FrontendStatusTypeExt1_1::CODERATES), + static_cast(V1_1::FrontendStatusTypeExt1_1::INTERLEAVINGS), + static_cast(V1_1::FrontendStatusTypeExt1_1::BANDWIDTH), + }; + mFrontendStatusCaps[2] = statusCaps; + + caps = FrontendInfo::FrontendCapabilities(); + caps.dvbsCaps(FrontendDvbsCapabilities()); + mFrontendCaps[3] = caps; + statusCaps = { + FrontendStatusType::SIGNAL_STRENGTH, + FrontendStatusType::SYMBOL_RATE, + FrontendStatusType::MODULATION, + static_cast(V1_1::FrontendStatusTypeExt1_1::MODULATIONS), + static_cast(V1_1::FrontendStatusTypeExt1_1::ROLL_OFF), + static_cast(V1_1::FrontendStatusTypeExt1_1::IS_MISO), + }; + mFrontendStatusCaps[3] = statusCaps; + + caps = FrontendInfo::FrontendCapabilities(); + caps.dvbtCaps(FrontendDvbtCapabilities()); + mFrontendCaps[4] = caps; + statusCaps = { + FrontendStatusType::EWBS, + FrontendStatusType::PLP_ID, + FrontendStatusType::HIERARCHY, + static_cast(V1_1::FrontendStatusTypeExt1_1::MODULATIONS), + static_cast(V1_1::FrontendStatusTypeExt1_1::BANDWIDTH), + static_cast(V1_1::FrontendStatusTypeExt1_1::GUARD_INTERVAL), + static_cast(V1_1::FrontendStatusTypeExt1_1::TRANSMISSION_MODE), + static_cast(V1_1::FrontendStatusTypeExt1_1::T2_SYSTEM_ID), + }; + mFrontendStatusCaps[4] = statusCaps; + + caps = FrontendInfo::FrontendCapabilities(); + FrontendIsdbtCapabilities isdbtCaps{ + .modeCap = FrontendIsdbtMode::MODE_1 | FrontendIsdbtMode::MODE_2, + .bandwidthCap = (unsigned int)FrontendIsdbtBandwidth::BANDWIDTH_6MHZ, + .modulationCap = (unsigned int)FrontendIsdbtModulation::MOD_16QAM, + // ISDBT shares coderate and guard interval with DVBT + .coderateCap = FrontendDvbtCoderate::CODERATE_4_5 | FrontendDvbtCoderate::CODERATE_6_7, + .guardIntervalCap = (unsigned int)FrontendDvbtGuardInterval::INTERVAL_1_128, + }; + caps.isdbtCaps(isdbtCaps); + mFrontendCaps[5] = caps; + statusCaps = { + FrontendStatusType::AGC, + FrontendStatusType::LNA, + FrontendStatusType::MODULATION, + static_cast(V1_1::FrontendStatusTypeExt1_1::MODULATIONS), + static_cast(V1_1::FrontendStatusTypeExt1_1::BANDWIDTH), + static_cast(V1_1::FrontendStatusTypeExt1_1::GUARD_INTERVAL), + static_cast(V1_1::FrontendStatusTypeExt1_1::TRANSMISSION_MODE), + static_cast(V1_1::FrontendStatusTypeExt1_1::ISDBT_SEGMENTS), + }; + mFrontendStatusCaps[5] = statusCaps; + + caps = FrontendInfo::FrontendCapabilities(); + caps.analogCaps(FrontendAnalogCapabilities()); + mFrontendCaps[6] = caps; + statusCaps = { + FrontendStatusType::LAYER_ERROR, + FrontendStatusType::MER, + static_cast(V1_1::FrontendStatusTypeExt1_1::UEC), + static_cast(V1_1::FrontendStatusTypeExt1_1::TS_DATA_RATES), + }; + mFrontendStatusCaps[6] = statusCaps; + + caps = FrontendInfo::FrontendCapabilities(); + caps.atscCaps(FrontendAtscCapabilities()); + mFrontendCaps[7] = caps; + statusCaps = { + FrontendStatusType::FREQ_OFFSET, + FrontendStatusType::RF_LOCK, + static_cast(V1_1::FrontendStatusTypeExt1_1::MODULATIONS), + static_cast(V1_1::FrontendStatusTypeExt1_1::IS_LINEAR), + }; + mFrontendStatusCaps[7] = statusCaps; + + caps = FrontendInfo::FrontendCapabilities(); + caps.isdbs3Caps(FrontendIsdbs3Capabilities()); + mFrontendCaps[8] = caps; + statusCaps = { + FrontendStatusType::DEMOD_LOCK, + FrontendStatusType::MODULATION, + static_cast(V1_1::FrontendStatusTypeExt1_1::MODULATIONS), + static_cast(V1_1::FrontendStatusTypeExt1_1::ROLL_OFF), + static_cast(V1_1::FrontendStatusTypeExt1_1::IS_SHORT_FRAMES), + }; + mFrontendStatusCaps[8] = statusCaps; + + statusCaps = { + static_cast(V1_1::FrontendStatusTypeExt1_1::MODULATIONS), + static_cast(V1_1::FrontendStatusTypeExt1_1::INTERLEAVINGS), + static_cast(V1_1::FrontendStatusTypeExt1_1::BANDWIDTH), + static_cast(V1_1::FrontendStatusTypeExt1_1::GUARD_INTERVAL), + static_cast(V1_1::FrontendStatusTypeExt1_1::TRANSMISSION_MODE), + }; + mFrontendStatusCaps[9] = statusCaps; + + mLnbs.resize(2); + mLnbs[0] = new Lnb(0); + mLnbs[1] = new Lnb(1); +} + +Tuner::~Tuner() {} + +Return Tuner::getFrontendIds(getFrontendIds_cb _hidl_cb) { + ALOGV("%s", __FUNCTION__); + + vector frontendIds; + frontendIds.resize(mFrontendSize); + for (int i = 0; i < mFrontendSize; i++) { + frontendIds[i] = mFrontends[i]->getFrontendId(); + } + + _hidl_cb(Result::SUCCESS, frontendIds); + return Void(); +} + +Return Tuner::openFrontendById(uint32_t frontendId, openFrontendById_cb _hidl_cb) { + ALOGV("%s", __FUNCTION__); + + if (frontendId >= mFrontendSize || frontendId < 0) { + ALOGW("[ WARN ] Frontend with id %d isn't available", frontendId); + _hidl_cb(Result::UNAVAILABLE, nullptr); + return Void(); + } + + _hidl_cb(Result::SUCCESS, mFrontends[frontendId]); + return Void(); +} + +Return Tuner::openDemux(openDemux_cb _hidl_cb) { + ALOGV("%s", __FUNCTION__); + + uint32_t demuxId = mLastUsedId + 1; + mLastUsedId += 1; + sp demux = new Demux(demuxId, this); + mDemuxes[demuxId] = demux; + + _hidl_cb(Result::SUCCESS, demuxId, demux); + return Void(); +} + +Return Tuner::getDemuxCaps(getDemuxCaps_cb _hidl_cb) { + ALOGV("%s", __FUNCTION__); + + DemuxCapabilities caps; + + // IP filter can be an MMTP filter's data source. + caps.linkCaps = {0x00, 0x00, 0x02, 0x00, 0x00}; + // Support time filter testing + caps.bTimeFilter = true; + _hidl_cb(Result::SUCCESS, caps); + return Void(); +} + +Return Tuner::openDescrambler(openDescrambler_cb _hidl_cb) { + ALOGV("%s", __FUNCTION__); + + sp descrambler = new Descrambler(); + + _hidl_cb(Result::SUCCESS, descrambler); + return Void(); +} + +Return Tuner::getFrontendInfo(FrontendId frontendId, getFrontendInfo_cb _hidl_cb) { + ALOGV("%s", __FUNCTION__); + + FrontendInfo info; + if (frontendId >= mFrontendSize) { + _hidl_cb(Result::INVALID_ARGUMENT, info); + return Void(); + } + + // assign randomly selected values for testing. + info = { + .type = mFrontends[frontendId]->getFrontendType(), + .minFrequency = 139, + .maxFrequency = 1139, + .minSymbolRate = 45, + .maxSymbolRate = 1145, + .acquireRange = 30, + .exclusiveGroupId = 57, + .statusCaps = mFrontendStatusCaps[frontendId], + .frontendCaps = mFrontendCaps[frontendId], + }; + + _hidl_cb(Result::SUCCESS, info); + return Void(); +} + +Return Tuner::getLnbIds(getLnbIds_cb _hidl_cb) { + ALOGV("%s", __FUNCTION__); + + vector lnbIds; + lnbIds.resize(mLnbs.size()); + for (int i = 0; i < lnbIds.size(); i++) { + lnbIds[i] = mLnbs[i]->getId(); + } + + _hidl_cb(Result::SUCCESS, lnbIds); + return Void(); +} + +Return Tuner::openLnbById(V1_0::LnbId lnbId, openLnbById_cb _hidl_cb) { + ALOGV("%s", __FUNCTION__); + + if (lnbId >= mLnbs.size()) { + _hidl_cb(Result::INVALID_ARGUMENT, nullptr); + return Void(); + } + + _hidl_cb(Result::SUCCESS, mLnbs[lnbId]); + return Void(); +} + +sp Tuner::getFrontendById(uint32_t frontendId) { + ALOGV("%s", __FUNCTION__); + + return mFrontends[frontendId]; +} + +Return Tuner::openLnbByName(const hidl_string& /*lnbName*/, openLnbByName_cb _hidl_cb) { + ALOGV("%s", __FUNCTION__); + + sp lnb = new Lnb(); + + _hidl_cb(Result::SUCCESS, 1234, lnb); + return Void(); +} + +Return Tuner::getFrontendDtmbCapabilities(uint32_t frontendId, + getFrontendDtmbCapabilities_cb _hidl_cb) { + ALOGV("%s", __FUNCTION__); + + if (mFrontends[frontendId] != nullptr && + (mFrontends[frontendId]->getFrontendType() == + static_cast(V1_1::FrontendType::DTMB))) { + _hidl_cb(Result::SUCCESS, mDtmbCaps); + } else { + _hidl_cb(Result::UNAVAILABLE, mDtmbCaps); + } + return Void(); +} + +void Tuner::setFrontendAsDemuxSource(uint32_t frontendId, uint32_t demuxId) { + mFrontendToDemux[frontendId] = demuxId; + if (mFrontends[frontendId] != nullptr && mFrontends[frontendId]->isLocked()) { + mDemuxes[demuxId]->startFrontendInputLoop(); + } +} + +void Tuner::removeDemux(uint32_t demuxId) { + map::iterator it; + for (it = mFrontendToDemux.begin(); it != mFrontendToDemux.end(); it++) { + if (it->second == demuxId) { + it = mFrontendToDemux.erase(it); + break; + } + } + mDemuxes.erase(demuxId); +} + +void Tuner::removeFrontend(uint32_t frontendId) { + mFrontendToDemux.erase(frontendId); +} + +void Tuner::frontendStopTune(uint32_t frontendId) { + map::iterator it = mFrontendToDemux.find(frontendId); + uint32_t demuxId; + if (it != mFrontendToDemux.end()) { + demuxId = it->second; + mDemuxes[demuxId]->stopFrontendInput(); + } +} + +void Tuner::frontendStartTune(uint32_t frontendId) { + map::iterator it = mFrontendToDemux.find(frontendId); + uint32_t demuxId; + if (it != mFrontendToDemux.end()) { + demuxId = it->second; + mDemuxes[demuxId]->startFrontendInputLoop(); + } +} + +} // namespace implementation +} // namespace V1_0 +} // namespace tuner +} // namespace tv +} // namespace hardware +} // namespace android diff --git a/tv/tuner/1.1/default/Tuner.h b/tv/tuner/1.1/default/Tuner.h new file mode 100644 index 0000000000000000000000000000000000000000..97bc99544a458db8a079eb6cf3e18b2fdd748f1c --- /dev/null +++ b/tv/tuner/1.1/default/Tuner.h @@ -0,0 +1,101 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_TV_TUNER_V1_1_TUNER_H_ +#define ANDROID_HARDWARE_TV_TUNER_V1_1_TUNER_H_ + +#include +#include +#include "Demux.h" +#include "Frontend.h" +#include "Lnb.h" + +using namespace std; + +namespace android { +namespace hardware { +namespace tv { +namespace tuner { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::tv::tuner::V1_1::ITuner; + +class Frontend; +class Demux; +class Lnb; + +class Tuner : public ITuner { + public: + Tuner(); + + virtual Return getFrontendIds(getFrontendIds_cb _hidl_cb) override; + + virtual Return openFrontendById(uint32_t frontendId, + openFrontendById_cb _hidl_cb) override; + + virtual Return openDemux(openDemux_cb _hidl_cb) override; + + virtual Return getDemuxCaps(getDemuxCaps_cb _hidl_cb) override; + + virtual Return openDescrambler(openDescrambler_cb _hidl_cb) override; + + virtual Return getFrontendInfo(uint32_t frontendId, getFrontendInfo_cb _hidl_cb) override; + + virtual Return getLnbIds(getLnbIds_cb _hidl_cb) override; + + virtual Return openLnbById(uint32_t lnbId, openLnbById_cb _hidl_cb) override; + + virtual Return openLnbByName(const hidl_string& lnbName, + openLnbByName_cb _hidl_cb) override; + + virtual Return getFrontendDtmbCapabilities( + uint32_t frontendId, getFrontendDtmbCapabilities_cb _hidl_cb) override; + + sp getFrontendById(uint32_t frontendId); + + void setFrontendAsDemuxSource(uint32_t frontendId, uint32_t demuxId); + + void frontendStartTune(uint32_t frontendId); + void frontendStopTune(uint32_t frontendId); + void removeDemux(uint32_t demuxId); + void removeFrontend(uint32_t frontendId); + + private: + virtual ~Tuner(); + // Static mFrontends array to maintain local frontends information + map> mFrontends; + map mFrontendCaps; + map> mFrontendStatusCaps; + V1_1::FrontendDtmbCapabilities mDtmbCaps; + map mFrontendToDemux; + map> mDemuxes; + // To maintain how many Frontends we have + int mFrontendSize; + // The last used demux id. Initial value is -1. + // First used id will be 0. + uint32_t mLastUsedId = -1; + vector> mLnbs; +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace tuner +} // namespace tv +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_TV_TUNER_V1_1_TUNER_H_ diff --git a/tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service-lazy.rc b/tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service-lazy.rc new file mode 100644 index 0000000000000000000000000000000000000000..abff430d3c50a7efb1460523d66c3e0a056ce6b0 --- /dev/null +++ b/tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service-lazy.rc @@ -0,0 +1,10 @@ +service vendor.tuner-hal-1-1 /vendor/bin/hw/android.hardware.tv.tuner@1.1-service-lazy + interface android.hardware.tv.tuner@1.0::ITuner default + interface android.hardware.tv.tuner@1.1::ITuner default + oneshot + disabled + class hal + user media + group mediadrm drmrpc + ioprio rt 4 + writepid /dev/cpuset/foreground/tasks \ No newline at end of file diff --git a/tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service-lazy.xml b/tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service-lazy.xml new file mode 100644 index 0000000000000000000000000000000000000000..86b044525f43b07cbfdc06974e7cd3dafeac69d7 --- /dev/null +++ b/tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service-lazy.xml @@ -0,0 +1,11 @@ + + + android.hardware.tv.tuner + hwbinder + 1.1 + + ITuner + default + + + \ No newline at end of file diff --git a/tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service.rc b/tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service.rc new file mode 100644 index 0000000000000000000000000000000000000000..3718a9388f509868a7c691a2d4afe0cf9434f603 --- /dev/null +++ b/tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service.rc @@ -0,0 +1,6 @@ +service vendor.tuner-hal-1-1 /vendor/bin/hw/android.hardware.tv.tuner@1.1-service + class hal + user media + group mediadrm drmrpc + ioprio rt 4 + writepid /dev/cpuset/foreground/tasks \ No newline at end of file diff --git a/tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service.xml b/tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service.xml new file mode 100644 index 0000000000000000000000000000000000000000..86b044525f43b07cbfdc06974e7cd3dafeac69d7 --- /dev/null +++ b/tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service.xml @@ -0,0 +1,11 @@ + + + android.hardware.tv.tuner + hwbinder + 1.1 + + ITuner + default + + + \ No newline at end of file diff --git a/tv/tuner/1.1/default/service.cpp b/tv/tuner/1.1/default/service.cpp new file mode 100644 index 0000000000000000000000000000000000000000..232030850d420f2dc39a124dff77c1aac50d534b --- /dev/null +++ b/tv/tuner/1.1/default/service.cpp @@ -0,0 +1,57 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#ifdef LAZY_SERVICE +#define LOG_TAG "android.hardware.tv.tuner@1.1-service-lazy" +#else +#define LOG_TAG "android.hardware.tv.tuner@1.1-service" +#endif + +#include +#include + +#include "Tuner.h" + +using android::hardware::configureRpcThreadpool; +using android::hardware::joinRpcThreadpool; +using android::hardware::LazyServiceRegistrar; +using android::hardware::tv::tuner::V1_0::implementation::Tuner; +using android::hardware::tv::tuner::V1_1::ITuner; + +#ifdef LAZY_SERVICE +const bool kLazyService = true; +#else +const bool kLazyService = false; +#endif + +int main() { + configureRpcThreadpool(8, true /* callerWillJoin */); + + // Setup hwbinder service + android::sp service = new Tuner(); + android::status_t status; + if (kLazyService) { + auto serviceRegistrar = LazyServiceRegistrar::getInstance(); + status = serviceRegistrar.registerService(service); + } else { + status = service->registerAsService(); + } + LOG_ALWAYS_FATAL_IF(status != android::OK, "Error while registering tuner service: %d", status); + + joinRpcThreadpool(); + return 0; +} diff --git a/tv/tuner/1.1/types.hal b/tv/tuner/1.1/types.hal new file mode 100644 index 0000000000000000000000000000000000000000..938cb6e49357a1355e08a9c468015e5460d6a2e9 --- /dev/null +++ b/tv/tuner/1.1/types.hal @@ -0,0 +1,922 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.tv.tuner@1.1; + +import @1.0::Constant; +import @1.0::DemuxFilterMmtpRecordEvent; +import @1.0::DemuxFilterTsRecordEvent; +import @1.0::DemuxScIndex; +import @1.0::DemuxTsIndex; +import @1.0::FrontendIsdbs3Rolloff; +import @1.0::FrontendAtsc3Bandwidth; +import @1.0::FrontendAtsc3Modulation; +import @1.0::FrontendAtsc3TimeInterleaveMode; +import @1.0::FrontendIsdbsRolloff; +import @1.0::FrontendAtscModulation; +import @1.0::FrontendDvbcAnnex; +import @1.0::FrontendDvbcModulation; +import @1.0::FrontendDvbcSpectralInversion; +import @1.0::FrontendDvbsModulation; +import @1.0::FrontendDvbsRolloff; +import @1.0::FrontendDvbtBandwidth; +import @1.0::FrontendDvbtConstellation; +import @1.0::FrontendDvbtTransmissionMode; +import @1.0::FrontendDvbtGuardInterval; +import @1.0::FrontendInnerFec; +import @1.0::FrontendIsdbs3Modulation; +import @1.0::FrontendIsdbsModulation; +import @1.0::FrontendIsdbtBandwidth; +import @1.0::FrontendIsdbtGuardInterval; +import @1.0::FrontendIsdbtMode; +import @1.0::FrontendIsdbtModulation; +import @1.0::FrontendScanMessageType; +import @1.0::FrontendStatusType; +import @1.0::FrontendType; +import android.hidl.safe_union@1.0; +import android.hidl.safe_union@1.0::Monostate; + +@export +enum Constant : @1.0::Constant { + /** + * An invalid mpuSequenceNumber. + */ + INVALID_MMTP_RECORD_EVENT_MPT_SEQUENCE_NUM = 0xFFFFFFFF, + /** + * An invalid first macroblock address. + */ + INVALID_FIRST_MACROBLOCK_IN_SLICE = 0xFFFFFFFF, + /** + * An invalid frenquency that can be used as the default value of the frontend setting. + */ + INVALID_FRONTEND_SETTING_FREQUENCY = 0xFFFFFFFF, + /** + * An invalid context id that can be used as the default value of the unconfigured id. It can + * be used to reset the configured ip context id. + */ + INVALID_IP_FILTER_CONTEXT_ID = 0xFFFFFFFF, + /** + * An invalid local transport stream id used as the return value on a failed operation of + * IFrontend.linkCiCam. + */ + INVALID_LTS_ID = 0xFFFFFFFF, + /** + * An invalid frontend ID. + */ + INVALID_FRONTEND_ID = 0xFFFFFFFF, + /** + * An invalid LNB ID. + */ + INVALID_LNB_ID = 0xFFFFFFFF, + /** + * An invalid key token. It is used to remove the current key from the descrambler. + */ + INVALID_KEYTOKEN = 0x00, +}; + +@export +enum Constant64Bit : uint64_t { + /** + * An invalid 64-bit Filter ID. + */ + INVALID_FILTER_ID_64BIT = 0xFFFFFFFFFFFFFFFF, + /** + * An invalid 64-bit AV sync hardware ID. + */ + INVALID_AV_SYNC_ID_64BIT = 0xFFFFFFFFFFFFFFFF, + /** + * An invalid pts. + */ + INVALID_PRESENTATION_TIME_STAMP = 0xFFFFFFFFFFFFFFFF, +}; + +/** + * Extended Demux Filter TS Record Event. + */ +struct DemuxFilterTsRecordEventExt { + /** + * The Presentation Time Stamp(PTS) for the audio or video frame. It is based on 90KHz + * and has the same format as the PTS in ISO/IEC 13818-1. + */ + uint64_t pts; + + /** + * Specifies the address of the first macroblock in the slice defined in ITU-T Rec. H.264. + */ + uint32_t firstMbInSlice; +}; + +/** + * Extended Demux Filter MMTP Record Event. + */ +struct DemuxFilterMmtpRecordEventExt { + /** + * The Presentation Time Stamp(PTS) for the audio or video frame. It is based on 90KHz + * and has the same format as the PTS in ISO/IEC 13818-1. + */ + uint64_t pts; + + /** + * MPU sequence number of the filtered data. This is only used for MMTP. + */ + uint32_t mpuSequenceNumber; + + /** + * Specifies the address of the first macroblock in the slice defined in ITU-T Rec. H.264. + */ + uint32_t firstMbInSlice; + + /** + * TS index mask. + */ + bitfield<@1.1::DemuxTsIndex> tsIndexMask; +}; + +/** + * Extended Demux Filter Event. + */ +struct DemuxFilterEventExt { + safe_union Event { + /** + * No extended filter Event. + */ + Monostate noinit; + + /** + * Extended TS Record event sent along with @1.0::DemuxFilterEvent::Event::tsRecord. + * DemuxFilterEventExt.events[i] is corresponding to @1.0::DemuxFilterEvent.events[i]. If + * @1.0::DemuxFilterEvent.events[i] does not have extended event, + * DemuxFilterEventExt.events[i] should use Monostate. + */ + DemuxFilterTsRecordEventExt tsRecord; + + /** + * Extended MMTP Record event sent along with @1.0::DemuxFilterEvent::Event::mmtpRecord. + * DemuxFilterEventExt.events[i] is corresponding to @1.0::DemuxFilterEvent.events[i]. If + * @1.0::DemuxFilterEvent.events[i] does not have extended event, + * DemuxFilterEventExt.events[i] should use Monostate. + */ + DemuxFilterMmtpRecordEventExt mmtpRecord; + + /** + * Monitor event to notify monitored status change. + * + * When sending monitorEvent, DemuxFilterEventExt.events should only contain one + * monitorEvent. MonitorEvent should be sent with an empty @1.0::DemuxFilterEvent. + */ + DemuxFilterMonitorEvent monitorEvent; + + /** + * An unique ID to mark the start point of receiving the valid filter events after + * reconfiguring the filter. It must be sent at least once in the first event after the + * filter is restarted. 0 is reserved for the newly opened filter's first start, which is + * optional for HAL to send. + * + * When sending starId, DemuxFilterEventExt.events should only contain one startId event. + * StardId event should be sent with an empty @1.0::DemuxFilterEvent. + */ + uint32_t startId; + }; + + /** + * An array of events + */ + vec events; +}; + +/** + * Scrambling Status Type. + */ +@export +enum ScramblingStatus : uint32_t { + /** + * Content’s scrambling status is unknown + */ + UNKNOWN = 1 << 0, + /** + * Content is not scrambled. + */ + NOT_SCRAMBLED = 1 << 1, + /** + * Content is scrambled. + */ + SCRAMBLED = 1 << 2, +}; + +@export +enum DemuxFilterMonitorEventType : uint32_t { + SCRAMBLING_STATUS = 1 << 0, + IP_CID_CHANGE = 1 << 1, +}; + +safe_union DemuxFilterMonitorEvent { + /** + * New scrambling status. + */ + ScramblingStatus scramblingStatus; + + /** + * New cid for the IP filter. + */ + uint32_t cid; +}; + +typedef FrontendDvbcSpectralInversion FrontendSpectralInversion; + +/** + * Scan type for a DVBS Frontend. + */ +@export +enum FrontendDvbsScanType : uint32_t { + UNDEFINED = 0, + DIRECT, + DISEQC, + UNICABLE, + JESS, +}; + +/** + * AFT flag for an Analog Frontend. + */ +@export +enum FrontendAnalogAftFlag : uint32_t { + UNDEFINED, + AFT_TRUE, + AFT_FALSE, +}; + +/** + * Time Interleave Mode for DVBC Frontend. + */ +@export +enum FrontendCableTimeInterleaveMode : uint32_t { + UNDEFINED = 0, + AUTO = 1 << 0, + INTERLEAVING_128_1_0 = 1 << 1, + INTERLEAVING_128_1_1 = 1 << 2, + INTERLEAVING_64_2 = 1 << 3, + INTERLEAVING_32_4 = 1 << 4, + INTERLEAVING_16_8 = 1 << 5, + INTERLEAVING_8_16 = 1 << 6, + INTERLEAVING_128_2 = 1 << 7, + INTERLEAVING_128_3 = 1 << 8, + INTERLEAVING_128_4 = 1 << 9, +}; + +/** + * Extended Transmission Mode for DVBT. + */ +@export +enum FrontendDvbtTransmissionMode : @1.0::FrontendDvbtTransmissionMode { + MODE_8K_E = 1 << 7, + MODE_16K_E = 1 << 8, + MODE_32K_E = 1 << 9, +}; + +/** + * Extended Constellation for DVBT. + */ +@export +enum FrontendDvbtConstellation : @1.0::FrontendDvbtConstellation { + CONSTELLATION_QPSK_R = 1 << 5, + CONSTELLATION_16QAM_R = 1 << 6, + CONSTELLATION_64QAM_R = 1 << 7, + CONSTELLATION_256QAM_R = 1 << 8, +}; + +/** + * Extended Signal Settings for a DVBS Frontend. + */ +struct FrontendDvbsSettingsExt1_1 { + FrontendDvbsScanType scanType; + + bool isDiseqcRxMessage; +}; + +/** + * Extended Signal Settings for a DVBT Frontend. + */ +struct FrontendDvbtSettingsExt1_1 { + FrontendDvbtConstellation constellation; + + FrontendDvbtTransmissionMode transmissionMode; +}; + +/** + * Extended Signal Settings for an Analog Frontend. + */ +struct FrontendAnalogSettingsExt1_1 { + FrontendAnalogAftFlag aftFlag; +}; + +/** + * Extended Signal Settings for DVBC Frontend. + */ +struct FrontendDvbcSettingsExt1_1 { + FrontendCableTimeInterleaveMode interleaveMode; + + FrontendDvbcBandwidth bandwidth; +}; + +/** + * Extended Signal Settings for Frontend. + */ +struct FrontendSettingsExt1_1 { + uint32_t endFrequency; + + FrontendSpectralInversion inversion; + + safe_union SettingsExt { + Monostate noinit; + + FrontendAnalogSettingsExt1_1 analog; + + FrontendDvbcSettingsExt1_1 dvbc; + + FrontendDvbsSettingsExt1_1 dvbs; + + FrontendDvbtSettingsExt1_1 dvbt; + + FrontendDtmbSettings dtmb; + } settingExt; +}; + +/** + * Extended Frontend Type. + */ +@export +enum FrontendType : @1.0::FrontendType { + /** + * DTMB (Digital Terrestrial Multimedia Broadcast) standard. + */ + DTMB, +}; + +/** + * Bandwidth Type for Cable Frontend. + */ +@export +enum FrontendDvbcBandwidth : uint32_t { + UNDEFINED = 0, + BANDWIDTH_5MHZ = 1 << 0, + BANDWIDTH_6MHZ = 1 << 1, + BANDWIDTH_7MHZ = 1 << 2, + BANDWIDTH_8MHZ = 1 << 3, +}; + +/** + * Bandwidth Type for DTMB. + */ +@export +enum FrontendDtmbBandwidth : uint32_t { + UNDEFINED = 0, + /** + * hardware is able to detect and set Bandwidth automatically + */ + AUTO = 1 << 0, + BANDWIDTH_8MHZ = 1 << 1, + BANDWIDTH_6MHZ = 1 << 2, +}; + +/** + * TimeInterleaveMode Type for DTMB. + */ +@export +enum FrontendDtmbTimeInterleaveMode : uint32_t { + UNDEFINED = 0, + /** + * hardware is able to detect and set time interleave mode automatically + */ + AUTO = 1 << 0, + TIMER_INT_240 = 1 << 1, + TIMER_INT_720 = 1 << 2, +}; + +/** + * FrontendDtmbModulation Type for DTMB. + */ +@export +enum FrontendDtmbModulation : uint32_t { + UNDEFINED = 0, + /** + * hardware is able to detect and set Constellation automatically + */ + AUTO = 1 << 0, + CONSTELLATION_4QAM = 1 << 1, + CONSTELLATION_4QAM_NR = 1 << 2, + CONSTELLATION_16QAM = 1 << 3, + CONSTELLATION_32QAM = 1 << 4, + CONSTELLATION_64QAM = 1 << 5, +}; + +/** + * CODERATE Type for DTMB. + */ +@export +enum FrontendDtmbCodeRate : uint32_t { + UNDEFINED = 0, + /** + * hardware is able to detect and set code rate automatically + */ + AUTO = 1 << 0, + CODERATE_2_5 = 1 << 1, + CODERATE_3_5 = 1 << 2, + CODERATE_4_5 = 1 << 3, +}; + +/** + * Guard Interval Type for DTMB. + */ +@export +enum FrontendDtmbGuardInterval : uint32_t { + UNDEFINED = 0, + /** + * hardware is able to detect and set Guard Interval automatically + */ + AUTO = 1 << 0, + PN_420_VARIOUS = 1 << 1, + PN_595_CONST = 1 << 2, + PN_945_VARIOUS = 1 << 3, + PN_420_CONST = 1 << 4, + PN_945_CONST = 1 << 5, + PN_RESERVED = 1 << 6, +}; + +/** + * Transmission Mode for DTMB. + */ +@export +enum FrontendDtmbTransmissionMode : uint32_t { + UNDEFINED = 0, + /** + * hardware is able to detect and set Transmission Mode automatically + */ + AUTO = 1 << 0, + C1 = 1 << 1, + C3780 = 1 << 2, +}; + +/** + * Signal Setting for DTMB Frontend. + */ +struct FrontendDtmbSettings { + uint32_t frequency; + + FrontendDtmbTransmissionMode transmissionMode; + + FrontendDtmbBandwidth bandwidth; + + FrontendDtmbModulation modulation; + + FrontendDtmbCodeRate codeRate; + + FrontendDtmbGuardInterval guardInterval; + + FrontendDtmbTimeInterleaveMode interleaveMode; +}; + +/** + * Capabilities for DTMB Frontend. + */ +struct FrontendDtmbCapabilities { + bitfield transmissionModeCap; + + bitfield bandwidthCap; + + bitfield modulationCap; + + bitfield codeRateCap; + + bitfield guardIntervalCap; + + bitfield interleaveModeCap; +}; + +safe_union FrontendModulation { + @1.0::FrontendDvbcModulation dvbc; + + @1.0::FrontendDvbsModulation dvbs; + + FrontendDvbtConstellation dvbt; + + @1.0::FrontendIsdbsModulation isdbs; + + @1.0::FrontendIsdbs3Modulation isdbs3; + + @1.0::FrontendIsdbtModulation isdbt; + + @1.0::FrontendAtscModulation atsc; + + @1.0::FrontendAtsc3Modulation atsc3; + + FrontendDtmbModulation dtmb; +}; + +safe_union FrontendInterleaveMode { + @1.0::FrontendAtsc3TimeInterleaveMode atsc3; + + FrontendCableTimeInterleaveMode dvbc; + + FrontendDtmbTimeInterleaveMode dtmb; +}; + +@export +enum FrontendInnerFec : @1.0::FrontendInnerFec { + FEC_2_15 = 1 << 36, + FEC_3_15 = 1 << 37, + FEC_5_15 = 1 << 38, + FEC_6_15 = 1 << 39, + FEC_9_15 = 1 << 40, + FEC_10_15 = 1 << 41, + FEC_12_15 = 1 << 42, + FEC_13_15 = 1 << 43, + FEC_18_30 = 1 << 44, + FEC_20_30 = 1 << 45, + FEC_90_180 = 1 << 46, + FEC_96_180 = 1 << 47, + FEC_104_180 = 1 << 48, + FEC_128_180 = 1 << 49, + FEC_132_180 = 1 << 50, + FEC_135_180 = 1 << 51, + FEC_140_180 = 1 << 52, +}; + +safe_union FrontendBandwidth { + @1.0::FrontendAtsc3Bandwidth atsc3; + + FrontendDvbcBandwidth dvbc; + + @1.0::FrontendDvbtBandwidth dvbt; + + @1.0::FrontendIsdbtBandwidth isdbt; + + FrontendDtmbBandwidth dtmb; +}; + +safe_union FrontendGuardInterval { + @1.0::FrontendDvbtGuardInterval dvbt; + + @1.0::FrontendIsdbtGuardInterval isdbt; + + FrontendDtmbGuardInterval dtmb; +}; + +safe_union FrontendTransmissionMode { + FrontendDvbtTransmissionMode dvbt; + + @1.0::FrontendIsdbtMode isdbt; + + FrontendDtmbTransmissionMode dtmb; +}; + +safe_union FrontendRollOff { + @1.0::FrontendDvbsRolloff dvbs; + + @1.0::FrontendIsdbsRolloff isdbs; + + @1.0::FrontendIsdbs3Rolloff isdbs3; +}; + +@export +enum FrontendStatusTypeExt1_1 : uint32_t { + /** + * Modulation Types. + */ + MODULATIONS = @1.0::FrontendStatusType:ATSC3_PLP_INFO + 1, + /** + * Bit Error Ratios. + */ + BERS, + /** + * Code Rates. + */ + CODERATES, + /** + * Extended Bandwidth. + */ + BANDWIDTH, + /** + * Extended Guard Intervals. + */ + GUARD_INTERVAL, + /** + * Extended Transmission Mode. + */ + TRANSMISSION_MODE, + /** + * Uncorrectable Error Counts of the frontend's Physical Layer Pipe (PLP) + * since the last tune operation. + */ + UEC, + /** + * DVB-T2 System Id. + */ + T2_SYSTEM_ID, + /** + * Frontend Interleaving Modes. + */ + INTERLEAVINGS, + /** + * Segments in ISDB-T Specification of all the channels. + */ + ISDBT_SEGMENTS, + /** + * Transport Stream Data Rate in BPS of the current channel. + */ + TS_DATA_RATES, + /** + * Roll Off Type status of the frontend. + */ + ROLL_OFF, + /** + * If the frontend currently supports MISO or not. + */ + IS_MISO, + /** + * If the frontend code rate is linear or not. + */ + IS_LINEAR, + /** + * If short frames is enabled or not. + */ + IS_SHORT_FRAMES, +}; + +safe_union FrontendStatusExt1_1 { + /** + * Extended modulation status. + */ + vec modulations; + + /** + * Extended bit error ratio status. + */ + vec bers; + + /** + * Extended code rate status. + */ + vec codeRates; + + /** + * Extended bandwidth status. + */ + FrontendBandwidth bandwidth; + + /** + * Extended guard interval status. + */ + FrontendGuardInterval interval; + + /** + * Extended transmission mode status. + */ + FrontendTransmissionMode transmissionMode; + + /** + * Uncorrectable Error Counts of the frontend's Physical Layer Pipe (PLP) + * since the last tune operation. + */ + uint32_t uec; + + /** + * The current DVB-T2 system id status. + */ + uint16_t systemId; + + /** + * Frontend Interleaving Modes. + */ + vec interleaving; + + /** + * Segments in ISDB-T Specification of all the channels. + */ + vec isdbtSegment; + + /** + * Transport Stream Data Rate in BPS of the current channel. + */ + vec tsDataRate; + /** + * Roll Off Type status of the frontend. + */ + FrontendRollOff rollOff; + /** + * If the frontend currently supports MISO or not. + */ + bool isMiso; + /** + * If the frontend code rate is linear or not. + */ + bool isLinear; + /** + * If short frames is enabled or not. + */ + bool isShortFrames; +}; + +enum FrontendScanMessageTypeExt1_1 : uint32_t { + MODULATION = @1.0::FrontendScanMessageType:ATSC3_PLP_INFO + 1, + DVBC_ANNEX, + HIGH_PRIORITY, +}; + +safe_union FrontendScanMessageExt1_1 { + FrontendModulation modulation; + + @1.0::FrontendDvbcAnnex annex; + + bool isHighPriority; +}; + +@export +enum VideoStreamType : uint32_t { + UNDEFINED, + /* + * ITU-T | ISO/IEC Reserved + */ + RESERVED, + /* + * ISO/IEC 11172 + */ + MPEG1, + /* + * ITU-T Rec.H.262 and ISO/IEC 13818-2 + */ + MPEG2, + /* + * ISO/IEC 14496-2 (MPEG-4 H.263 based video) + */ + MPEG4P2, + /* + * ITU-T Rec.H.264 and ISO/IEC 14496-10 + */ + AVC, + /* + * ITU-T Rec. H.265 and ISO/IEC 23008-2 + */ + HEVC, + /* + * Microsoft VC.1 + */ + VC1, + /* + * Google VP8 + */ + VP8, + /* + * Google VP9 + */ + VP9, + /* + * AOMedia Video 1 + */ + AV1, + /* + * Chinese Standard + */ + AVS, + /* + * New Chinese Standard + */ + AVS2, +}; + +@export +enum AudioStreamType : uint32_t { + UNDEFINED, + /* + * Uncompressed Audio + */ + PCM, + /* + * MPEG Audio Layer III versions + */ + MP3, + /* + * ISO/IEC 11172 Audio + */ + MPEG1, + /* + * ISO/IEC 13818-3 + */ + MPEG2, + /* + * ISO/IEC 23008-3 (MPEG-H Part 3) + */ + MPEGH, + /* + * ISO/IEC 14496-3 + */ + AAC, + /* + * Dolby Digital + */ + AC3, + /* + * Dolby Digital Plus + */ + EAC3, + /* + * Dolby AC-4 + */ + AC4, + /* + * Basic DTS + */ + DTS, + /* + * High Resolution DTS + */ + DTS_HD, + /* + * Windows Media Audio + */ + WMA, + /* + * Opus Interactive Audio Codec + */ + OPUS, + /* + * VORBIS Interactive Audio Codec + */ + VORBIS, + /* + * SJ/T 11368-2006 + */ + DRA, +}; + +/** + * Stream type for A/V filter. + */ +safe_union AvStreamType { + VideoStreamType video; + + AudioStreamType audio; +}; + +/** + * Indexes can be tagged by start point of slice groups according to ISO/IEC 14496-10. + */ +@export +enum DemuxScIndex : @1.0::DemuxScIndex { + /** + * All blocks are coded as I blocks. + */ + I_SLICE = 1 << 4, + /** + * Blocks are coded as I or P blocks. + */ + P_SLICE = 1 << 5, + /** + * Blocks are coded as I, P or B blocks. + */ + B_SLICE = 1 << 6, + /** + * A so-called switching I slice that is coded. + */ + SI_SLICE = 1 << 7, + /** + * A so-called switching P slice that is coded. + */ + SP_SLICE = 1 << 8, +}; + +@export +enum DemuxTsIndex : @1.0::DemuxTsIndex { + /** + * Index the address of MMT Packet Table(MPT). + */ + MPT_INDEX_MPT = 1 << 16, + /** + * Index the address of Video. + */ + MPT_INDEX_VIDEO = 1 << 17, + /** + * Index the address of Audio. + */ + MPT_INDEX_AUDIO = 1 << 18, + /** + * Index to indicate this is a target of timestamp extraction for video. + */ + MPT_INDEX_TIMESTAMP_TARGET_VIDEO = 1 << 19, + /** + * Index to indicate this is a target of timestamp extraction for audio. + */ + MPT_INDEX_TIMESTAMP_TARGET_AUDIO = 1 << 20, +}; diff --git a/tv/tuner/1.1/vts/OWNERS b/tv/tuner/1.1/vts/OWNERS new file mode 100644 index 0000000000000000000000000000000000000000..1b3d095f9ce88cdeecf2a9da0f2fb45bb793369e --- /dev/null +++ b/tv/tuner/1.1/vts/OWNERS @@ -0,0 +1,4 @@ +nchalko@google.com +amyjojo@google.com +shubang@google.com +quxiangfang@google.com diff --git a/tv/tuner/1.1/vts/functional/Android.bp b/tv/tuner/1.1/vts/functional/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..ac835a4382cb7fca628f4b8d5d4fbe622cc0d667 --- /dev/null +++ b/tv/tuner/1.1/vts/functional/Android.bp @@ -0,0 +1,73 @@ +// +// Copyright 2020 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_test { + name: "VtsHalTvTunerV1_1TargetTest", + defaults: ["VtsHalTargetTestDefaults"], + srcs: [ + "DemuxTests.cpp", + "DvrTests.cpp", + "FilterTests.cpp", + "FrontendTests.cpp", + "VtsHalTvTunerV1_1TargetTest.cpp", + ], + generated_headers: [ + "tuner_testing_dynamic_configuration_V1_0_enums", + "tuner_testing_dynamic_configuration_V1_0_parser", + ], + generated_sources: [ + "tuner_testing_dynamic_configuration_V1_0_enums", + "tuner_testing_dynamic_configuration_V1_0_parser", + ], + header_libs: ["libxsdc-utils"], + static_libs: [ + "android.hardware.cas@1.0", + "android.hardware.cas@1.1", + "android.hardware.cas@1.2", + "android.hardware.tv.tuner@1.0", + "android.hardware.tv.tuner@1.1", + "android.hidl.allocator@1.0", + "android.hidl.memory@1.0", + "libhidlallocatorutils", + "libhidlmemory", + "libcutils", + "libfmq", + ], + shared_libs: [ + "libbinder", + "libxml2", + ], + data: [ + ":tuner_frontend_input_ts", + ":tuner_frontend_input_es", + ":tuner_testing_dynamic_configuration_V1_0", + ], + test_suites: [ + "general-tests", + "vts", + ], + + require_root: true, +} diff --git a/tv/tuner/1.1/vts/functional/AndroidTest.xml b/tv/tuner/1.1/vts/functional/AndroidTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..3e6878ce39f4e7ff058ab7e56e728da7765095bb --- /dev/null +++ b/tv/tuner/1.1/vts/functional/AndroidTest.xml @@ -0,0 +1,34 @@ + + + + diff --git a/tv/tuner/1.1/vts/functional/DemuxTests.cpp b/tv/tuner/1.1/vts/functional/DemuxTests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b1d8a0a0b2148c0f22991ded3e2a58662e82ac95 --- /dev/null +++ b/tv/tuner/1.1/vts/functional/DemuxTests.cpp @@ -0,0 +1,41 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "DemuxTests.h" + +AssertionResult DemuxTests::openDemux(sp& demux, uint32_t& demuxId) { + Result status; + mService->openDemux([&](Result result, uint32_t id, const sp& demuxSp) { + mDemux = demuxSp; + demux = demuxSp; + demuxId = id; + status = result; + }); + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult DemuxTests::setDemuxFrontendDataSource(uint32_t frontendId) { + EXPECT_TRUE(mDemux) << "Test with openDemux first."; + auto status = mDemux->setFrontendDataSource(frontendId); + return AssertionResult(status.isOk()); +} + +AssertionResult DemuxTests::closeDemux() { + EXPECT_TRUE(mDemux) << "Test with openDemux first."; + auto status = mDemux->close(); + mDemux = nullptr; + return AssertionResult(status.isOk()); +} \ No newline at end of file diff --git a/tv/tuner/1.1/vts/functional/DemuxTests.h b/tv/tuner/1.1/vts/functional/DemuxTests.h new file mode 100644 index 0000000000000000000000000000000000000000..c28d6ca5246a8cdc974c86ae653253daee1740e0 --- /dev/null +++ b/tv/tuner/1.1/vts/functional/DemuxTests.h @@ -0,0 +1,56 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using android::sp; +using android::hardware::Return; +using android::hardware::Void; +using android::hardware::tv::tuner::V1_0::IDemux; +using android::hardware::tv::tuner::V1_0::IFilter; +using android::hardware::tv::tuner::V1_0::Result; +using android::hardware::tv::tuner::V1_1::ITuner; + +using ::testing::AssertionResult; + +class DemuxTests { + public: + void setService(sp tuner) { mService = tuner; } + + AssertionResult openDemux(sp& demux, uint32_t& demuxId); + AssertionResult setDemuxFrontendDataSource(uint32_t frontendId); + AssertionResult closeDemux(); + + protected: + static AssertionResult failure() { return ::testing::AssertionFailure(); } + + static AssertionResult success() { return ::testing::AssertionSuccess(); } + + sp mService; + sp mDemux; +}; diff --git a/tv/tuner/1.1/vts/functional/DvrTests.cpp b/tv/tuner/1.1/vts/functional/DvrTests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1e478f56dcfd41c4d57b4eb3be93f4a16a975214 --- /dev/null +++ b/tv/tuner/1.1/vts/functional/DvrTests.cpp @@ -0,0 +1,349 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "DvrTests.h" + +void DvrCallback::startPlaybackInputThread(string& dataInputFile, PlaybackSettings& settings, + MQDesc& playbackMQDescriptor) { + mInputDataFile = dataInputFile; + mPlaybackSettings = settings; + mPlaybackMQ = std::make_unique(playbackMQDescriptor, true /* resetPointers */); + EXPECT_TRUE(mPlaybackMQ); + pthread_create(&mPlaybackThread, NULL, __threadLoopPlayback, this); + pthread_setname_np(mPlaybackThread, "test_playback_input_loop"); +} + +void DvrCallback::stopPlaybackThread() { + mPlaybackThreadRunning = false; + mKeepWritingPlaybackFMQ = false; + + android::Mutex::Autolock autoLock(mPlaybackThreadLock); +} + +void* DvrCallback::__threadLoopPlayback(void* user) { + DvrCallback* const self = static_cast(user); + self->playbackThreadLoop(); + return 0; +} + +void DvrCallback::playbackThreadLoop() { + android::Mutex::Autolock autoLock(mPlaybackThreadLock); + mPlaybackThreadRunning = true; + + // Create the EventFlag that is used to signal the HAL impl that data have been + // written into the Playback FMQ + EventFlag* playbackMQEventFlag; + EXPECT_TRUE(EventFlag::createEventFlag(mPlaybackMQ->getEventFlagWord(), &playbackMQEventFlag) == + android::OK); + + int fd = open(mInputDataFile.c_str(), O_RDONLY | O_LARGEFILE); + int readBytes; + uint32_t regionSize = 0; + uint8_t* buffer; + ALOGW("[vts] playback thread loop start %s", mInputDataFile.c_str()); + if (fd < 0) { + mPlaybackThreadRunning = false; + ALOGW("[vts] Error %s", strerror(errno)); + } + + while (mPlaybackThreadRunning) { + while (mKeepWritingPlaybackFMQ) { + int totalWrite = mPlaybackMQ->availableToWrite(); + if (totalWrite * 4 < mPlaybackMQ->getQuantumCount()) { + // Wait for the HAL implementation to read more data then write. + continue; + } + MessageQueue::MemTransaction memTx; + if (!mPlaybackMQ->beginWrite(totalWrite, &memTx)) { + ALOGW("[vts] Fail to write into Playback fmq."); + mPlaybackThreadRunning = false; + break; + } + auto first = memTx.getFirstRegion(); + buffer = first.getAddress(); + regionSize = first.getLength(); + + if (regionSize > 0) { + readBytes = read(fd, buffer, regionSize); + if (readBytes <= 0) { + if (readBytes < 0) { + ALOGW("[vts] Read from %s failed.", mInputDataFile.c_str()); + } else { + ALOGW("[vts] playback input EOF."); + } + mPlaybackThreadRunning = false; + break; + } + } + if (regionSize == 0 || (readBytes == regionSize && regionSize < totalWrite)) { + auto second = memTx.getSecondRegion(); + buffer = second.getAddress(); + regionSize = second.getLength(); + int ret = read(fd, buffer, regionSize); + if (ret <= 0) { + if (ret < 0) { + ALOGW("[vts] Read from %s failed.", mInputDataFile.c_str()); + } else { + ALOGW("[vts] playback input EOF."); + } + mPlaybackThreadRunning = false; + break; + } + readBytes += ret; + } + if (!mPlaybackMQ->commitWrite(readBytes)) { + ALOGW("[vts] Failed to commit write playback fmq."); + mPlaybackThreadRunning = false; + break; + } + playbackMQEventFlag->wake(static_cast(DemuxQueueNotifyBits::DATA_READY)); + } + } + + mPlaybackThreadRunning = false; + ALOGW("[vts] Playback thread end."); + close(fd); +} + +void DvrCallback::testRecordOutput() { + android::Mutex::Autolock autoLock(mMsgLock); + while (mDataOutputBuffer.empty()) { + if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) { + EXPECT_TRUE(false) << "record output matching pid does not output within timeout"; + stopRecordThread(); + return; + } + } + stopRecordThread(); + ALOGW("[vts] record pass and stop"); +} + +void DvrCallback::startRecordOutputThread(RecordSettings recordSettings, + MQDesc& recordMQDescriptor) { + mRecordMQ = std::make_unique(recordMQDescriptor, true /* resetPointers */); + EXPECT_TRUE(mRecordMQ); + struct RecordThreadArgs* threadArgs = + (struct RecordThreadArgs*)malloc(sizeof(struct RecordThreadArgs)); + threadArgs->user = this; + threadArgs->recordSettings = &recordSettings; + threadArgs->keepReadingRecordFMQ = &mKeepReadingRecordFMQ; + + pthread_create(&mRecordThread, NULL, __threadLoopRecord, (void*)threadArgs); + pthread_setname_np(mRecordThread, "test_record_input_loop"); +} + +void* DvrCallback::__threadLoopRecord(void* threadArgs) { + DvrCallback* const self = + static_cast(((struct RecordThreadArgs*)threadArgs)->user); + self->recordThreadLoop(((struct RecordThreadArgs*)threadArgs)->recordSettings, + ((struct RecordThreadArgs*)threadArgs)->keepReadingRecordFMQ); + return 0; +} + +void DvrCallback::recordThreadLoop(RecordSettings* /*recordSettings*/, bool* keepReadingRecordFMQ) { + ALOGD("[vts] DvrCallback record threadLoop start."); + android::Mutex::Autolock autoLock(mRecordThreadLock); + mRecordThreadRunning = true; + mKeepReadingRecordFMQ = true; + + // Create the EventFlag that is used to signal the HAL impl that data have been + // read from the Record FMQ + EventFlag* recordMQEventFlag; + EXPECT_TRUE(EventFlag::createEventFlag(mRecordMQ->getEventFlagWord(), &recordMQEventFlag) == + android::OK); + + while (mRecordThreadRunning) { + while (*keepReadingRecordFMQ) { + uint32_t efState = 0; + android::status_t status = recordMQEventFlag->wait( + static_cast(DemuxQueueNotifyBits::DATA_READY), &efState, WAIT_TIMEOUT, + true /* retry on spurious wake */); + if (status != android::OK) { + ALOGD("[vts] wait for data ready on the record FMQ"); + continue; + } + // Our current implementation filter the data and write it into the filter FMQ + // immediately after the DATA_READY from the VTS/framework + if (!readRecordFMQ()) { + ALOGD("[vts] record data failed to be filtered. Ending thread"); + mRecordThreadRunning = false; + break; + } + } + } + + mRecordThreadRunning = false; + ALOGD("[vts] record thread ended."); +} + +bool DvrCallback::readRecordFMQ() { + android::Mutex::Autolock autoLock(mMsgLock); + bool result = false; + int readSize = mRecordMQ->availableToRead(); + mDataOutputBuffer.clear(); + mDataOutputBuffer.resize(readSize); + result = mRecordMQ->read(mDataOutputBuffer.data(), readSize); + EXPECT_TRUE(result) << "can't read from Record MQ"; + mMsgCondition.signal(); + return result; +} + +void DvrCallback::stopRecordThread() { + mKeepReadingRecordFMQ = false; + mRecordThreadRunning = false; +} + +AssertionResult DvrTests::openDvrInDemux(DvrType type, uint32_t bufferSize) { + Result status; + EXPECT_TRUE(mDemux) << "Test with openDemux first."; + + // Create dvr callback + if (type == DvrType::PLAYBACK) { + mDvrPlaybackCallback = new DvrCallback(); + mDemux->openDvr(type, bufferSize, mDvrPlaybackCallback, + [&](Result result, const sp& dvr) { + mDvrPlayback = dvr; + status = result; + }); + if (status == Result::SUCCESS) { + mDvrPlaybackCallback->setDvr(mDvrPlayback); + } + } + + if (type == DvrType::RECORD) { + mDvrRecordCallback = new DvrCallback(); + mDemux->openDvr(type, bufferSize, mDvrRecordCallback, + [&](Result result, const sp& dvr) { + mDvrRecord = dvr; + status = result; + }); + if (status == Result::SUCCESS) { + mDvrRecordCallback->setDvr(mDvrRecord); + } + } + + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult DvrTests::configDvrPlayback(DvrSettings setting) { + Result status = mDvrPlayback->configure(setting); + + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult DvrTests::configDvrRecord(DvrSettings setting) { + Result status = mDvrRecord->configure(setting); + + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult DvrTests::getDvrPlaybackMQDescriptor() { + Result status; + EXPECT_TRUE(mDemux) << "Test with openDemux first."; + EXPECT_TRUE(mDvrPlayback) << "Test with openDvr first."; + + mDvrPlayback->getQueueDesc([&](Result result, const MQDesc& dvrMQDesc) { + mDvrPlaybackMQDescriptor = dvrMQDesc; + status = result; + }); + + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult DvrTests::getDvrRecordMQDescriptor() { + Result status; + EXPECT_TRUE(mDemux) << "Test with openDemux first."; + EXPECT_TRUE(mDvrRecord) << "Test with openDvr first."; + + mDvrRecord->getQueueDesc([&](Result result, const MQDesc& dvrMQDesc) { + mDvrRecordMQDescriptor = dvrMQDesc; + status = result; + }); + + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult DvrTests::attachFilterToDvr(sp filter) { + Result status; + EXPECT_TRUE(mDemux) << "Test with openDemux first."; + EXPECT_TRUE(mDvrRecord) << "Test with openDvr first."; + + status = mDvrRecord->attachFilter(filter); + + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult DvrTests::detachFilterToDvr(sp filter) { + Result status; + EXPECT_TRUE(mDemux) << "Test with openDemux first."; + EXPECT_TRUE(mDvrRecord) << "Test with openDvr first."; + + status = mDvrRecord->detachFilter(filter); + + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult DvrTests::startDvrPlayback() { + Result status; + EXPECT_TRUE(mDemux) << "Test with openDemux first."; + EXPECT_TRUE(mDvrPlayback) << "Test with openDvr first."; + + status = mDvrPlayback->start(); + + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult DvrTests::stopDvrPlayback() { + Result status; + EXPECT_TRUE(mDemux) << "Test with openDemux first."; + EXPECT_TRUE(mDvrPlayback) << "Test with openDvr first."; + + status = mDvrPlayback->stop(); + + return AssertionResult(status == Result::SUCCESS); +} + +void DvrTests::closeDvrPlayback() { + ASSERT_TRUE(mDemux); + ASSERT_TRUE(mDvrPlayback); + ASSERT_TRUE(mDvrPlayback->close() == Result::SUCCESS); +} + +AssertionResult DvrTests::startDvrRecord() { + Result status; + EXPECT_TRUE(mDemux) << "Test with openDemux first."; + EXPECT_TRUE(mDvrRecord) << "Test with openDvr first."; + + status = mDvrRecord->start(); + + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult DvrTests::stopDvrRecord() { + Result status; + EXPECT_TRUE(mDemux) << "Test with openDemux first."; + EXPECT_TRUE(mDvrRecord) << "Test with openDvr first."; + + status = mDvrRecord->stop(); + + return AssertionResult(status == Result::SUCCESS); +} + +void DvrTests::closeDvrRecord() { + ASSERT_TRUE(mDemux); + ASSERT_TRUE(mDvrRecord); + ASSERT_TRUE(mDvrRecord->close() == Result::SUCCESS); +} diff --git a/tv/tuner/1.1/vts/functional/DvrTests.h b/tv/tuner/1.1/vts/functional/DvrTests.h new file mode 100644 index 0000000000000000000000000000000000000000..289ddf6d7db29093429fce287b399193ffa48e7d --- /dev/null +++ b/tv/tuner/1.1/vts/functional/DvrTests.h @@ -0,0 +1,195 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "FilterTests.h" + +using android::Condition; +using android::Mutex; +using android::sp; +using android::hardware::EventFlag; +using android::hardware::kSynchronizedReadWrite; +using android::hardware::MessageQueue; +using android::hardware::MQDescriptorSync; +using android::hardware::Return; +using android::hardware::Void; +using android::hardware::tv::tuner::V1_0::DemuxFilterStatus; +using android::hardware::tv::tuner::V1_0::DemuxQueueNotifyBits; +using android::hardware::tv::tuner::V1_0::DvrSettings; +using android::hardware::tv::tuner::V1_0::DvrType; +using android::hardware::tv::tuner::V1_0::IDvr; +using android::hardware::tv::tuner::V1_0::IDvrCallback; +using android::hardware::tv::tuner::V1_0::PlaybackSettings; +using android::hardware::tv::tuner::V1_0::PlaybackStatus; +using android::hardware::tv::tuner::V1_0::RecordSettings; +using android::hardware::tv::tuner::V1_0::RecordStatus; +using android::hardware::tv::tuner::V1_0::Result; +using android::hardware::tv::tuner::V1_1::ITuner; + +using namespace std; + +#define WAIT_TIMEOUT 3000000000 + +class DvrCallback : public IDvrCallback { + public: + virtual Return onRecordStatus(DemuxFilterStatus status) override { + ALOGD("[vts] record status %hhu", status); + switch (status) { + case DemuxFilterStatus::DATA_READY: + break; + case DemuxFilterStatus::LOW_WATER: + break; + case DemuxFilterStatus::HIGH_WATER: + case DemuxFilterStatus::OVERFLOW: + ALOGD("[vts] record overflow. Flushing."); + EXPECT_TRUE(mDvr) << "Dvr callback is not set with an IDvr"; + if (mDvr) { + Result result = mDvr->flush(); + ALOGD("[vts] Flushing result %d.", result); + } + break; + } + return Void(); + } + + virtual Return onPlaybackStatus(PlaybackStatus status) override { + // android::Mutex::Autolock autoLock(mMsgLock); + ALOGD("[vts] playback status %d", status); + switch (status) { + case PlaybackStatus::SPACE_EMPTY: + case PlaybackStatus::SPACE_ALMOST_EMPTY: + ALOGD("[vts] keep playback inputing %d", status); + mKeepWritingPlaybackFMQ = true; + break; + case PlaybackStatus::SPACE_ALMOST_FULL: + case PlaybackStatus::SPACE_FULL: + ALOGD("[vts] stop playback inputing %d", status); + mKeepWritingPlaybackFMQ = false; + break; + } + return Void(); + } + + void stopPlaybackThread(); + void testRecordOutput(); + void stopRecordThread(); + + void startPlaybackInputThread(string& dataInputFile, PlaybackSettings& settings, + MQDesc& playbackMQDescriptor); + void startRecordOutputThread(RecordSettings recordSettings, MQDesc& recordMQDescriptor); + static void* __threadLoopPlayback(void* user); + static void* __threadLoopRecord(void* threadArgs); + void playbackThreadLoop(); + void recordThreadLoop(RecordSettings* recordSetting, bool* keepWritingPlaybackFMQ); + + bool readRecordFMQ(); + + void setDvr(sp dvr) { mDvr = dvr; } + + private: + struct RecordThreadArgs { + DvrCallback* user; + RecordSettings* recordSettings; + bool* keepReadingRecordFMQ; + }; + // uint16_t mDataLength = 0; + std::vector mDataOutputBuffer; + + std::map> mFilterMQ; + std::unique_ptr mPlaybackMQ; + std::unique_ptr mRecordMQ; + std::map mFilterMQEventFlag; + + android::Mutex mMsgLock; + android::Mutex mPlaybackThreadLock; + android::Mutex mRecordThreadLock; + android::Condition mMsgCondition; + + bool mKeepWritingPlaybackFMQ = true; + bool mKeepReadingRecordFMQ = true; + bool mPlaybackThreadRunning; + bool mRecordThreadRunning; + pthread_t mPlaybackThread; + pthread_t mRecordThread; + string mInputDataFile; + PlaybackSettings mPlaybackSettings; + + sp mDvr = nullptr; + + // int mPidFilterOutputCount = 0; +}; + +class DvrTests { + public: + void setService(sp tuner) { mService = tuner; } + void setDemux(sp demux) { mDemux = demux; } + + void startPlaybackInputThread(string& dataInputFile, PlaybackSettings& settings) { + mDvrPlaybackCallback->startPlaybackInputThread(dataInputFile, settings, + mDvrPlaybackMQDescriptor); + }; + + void startRecordOutputThread(RecordSettings settings) { + mDvrRecordCallback->startRecordOutputThread(settings, mDvrRecordMQDescriptor); + }; + + void stopPlaybackThread() { mDvrPlaybackCallback->stopPlaybackThread(); } + void testRecordOutput() { mDvrRecordCallback->testRecordOutput(); } + void stopRecordThread() { mDvrRecordCallback->stopRecordThread(); } + + AssertionResult openDvrInDemux(DvrType type, uint32_t bufferSize); + AssertionResult configDvrPlayback(DvrSettings setting); + AssertionResult configDvrRecord(DvrSettings setting); + AssertionResult getDvrPlaybackMQDescriptor(); + AssertionResult getDvrRecordMQDescriptor(); + AssertionResult attachFilterToDvr(sp filter); + AssertionResult detachFilterToDvr(sp filter); + AssertionResult stopDvrPlayback(); + AssertionResult startDvrPlayback(); + AssertionResult stopDvrRecord(); + AssertionResult startDvrRecord(); + void closeDvrPlayback(); + void closeDvrRecord(); + + protected: + static AssertionResult failure() { return ::testing::AssertionFailure(); } + + static AssertionResult success() { return ::testing::AssertionSuccess(); } + + sp mService; + sp mDvrPlayback; + sp mDvrRecord; + sp mDemux; + sp mDvrPlaybackCallback; + sp mDvrRecordCallback; + MQDesc mDvrPlaybackMQDescriptor; + MQDesc mDvrRecordMQDescriptor; +}; diff --git a/tv/tuner/1.1/vts/functional/FilterTests.cpp b/tv/tuner/1.1/vts/functional/FilterTests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4dff8533f31038fa124e2d0e1a55efdb95a4279c --- /dev/null +++ b/tv/tuner/1.1/vts/functional/FilterTests.cpp @@ -0,0 +1,326 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "FilterTests.h" + +void FilterCallback::testFilterDataOutput() { + android::Mutex::Autolock autoLock(mMsgLock); + while (mPidFilterOutputCount < 1) { + if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) { + EXPECT_TRUE(false) << "filter output matching pid does not output within timeout"; + return; + } + } + mPidFilterOutputCount = 0; + ALOGW("[vts] pass and stop"); +} + +void FilterCallback::testFilterScramblingEvent() { + android::Mutex::Autolock autoLock(mMsgLock); + while (mScramblingStatusEvent < 1) { + if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) { + EXPECT_TRUE(false) << "scrambling event does not output within timeout"; + return; + } + } + mScramblingStatusEvent = 0; + ALOGW("[vts] pass and stop"); +} + +void FilterCallback::testFilterIpCidEvent() { + android::Mutex::Autolock autoLock(mMsgLock); + while (mIpCidEvent < 1) { + if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) { + EXPECT_TRUE(false) << "ip cid change event does not output within timeout"; + return; + } + } + mIpCidEvent = 0; + ALOGW("[vts] pass and stop"); +} + +void FilterCallback::testStartIdAfterReconfigure() { + android::Mutex::Autolock autoLock(mMsgLock); + while (!mStartIdReceived) { + if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) { + EXPECT_TRUE(false) << "does not receive start id within timeout"; + return; + } + } + mStartIdReceived = false; + ALOGW("[vts] pass and stop"); +} + +void FilterCallback::readFilterEventData() { + ALOGW("[vts] reading filter event"); + // todo separate filter handlers + for (int i = 0; i < mFilterEvent.events.size(); i++) { + auto event = mFilterEvent.events[i]; + switch (event.getDiscriminator()) { + case DemuxFilterEvent::Event::hidl_discriminator::media: + ALOGD("[vts] Media filter event, avMemHandle numFds=%d.", + event.media().avMemory.getNativeHandle()->numFds); + dumpAvData(event.media()); + break; + default: + break; + } + } + for (int i = 0; i < mFilterEventExt.events.size(); i++) { + auto eventExt = mFilterEventExt.events[i]; + switch (eventExt.getDiscriminator()) { + case DemuxFilterEventExt::Event::hidl_discriminator::tsRecord: + ALOGD("[vts] Extended TS record filter event, pts=%" PRIu64 ", firstMbInSlice=%d", + eventExt.tsRecord().pts, eventExt.tsRecord().firstMbInSlice); + break; + case DemuxFilterEventExt::Event::hidl_discriminator::mmtpRecord: + ALOGD("[vts] Extended MMTP record filter event, pts=%" PRIu64 + ", firstMbInSlice=%d, mpuSequenceNumber=%d, tsIndexMask=%d", + eventExt.mmtpRecord().pts, eventExt.mmtpRecord().firstMbInSlice, + eventExt.mmtpRecord().mpuSequenceNumber, eventExt.mmtpRecord().tsIndexMask); + break; + case DemuxFilterEventExt::Event::hidl_discriminator::monitorEvent: + switch (eventExt.monitorEvent().getDiscriminator()) { + case DemuxFilterMonitorEvent::hidl_discriminator::scramblingStatus: + mScramblingStatusEvent++; + break; + case DemuxFilterMonitorEvent::hidl_discriminator::cid: + mIpCidEvent++; + break; + default: + break; + } + break; + case DemuxFilterEventExt::Event::hidl_discriminator::startId: + ALOGD("[vts] Extended restart filter event, startId=%d", eventExt.startId()); + mStartIdReceived = true; + break; + default: + break; + } + } +} + +bool FilterCallback::dumpAvData(DemuxFilterMediaEvent event) { + uint32_t length = event.dataLength; + uint32_t offset = event.offset; + // read data from buffer pointed by a handle + hidl_handle handle = event.avMemory; + if (handle.getNativeHandle()->numFds == 0) { + if (mAvSharedHandle == NULL) { + return false; + } + handle = mAvSharedHandle; + } + + int av_fd = handle.getNativeHandle()->data[0]; + uint8_t* buffer = static_cast( + mmap(NULL, length + offset, PROT_READ | PROT_WRITE, MAP_SHARED, av_fd, 0)); + if (buffer == MAP_FAILED) { + ALOGE("[vts] fail to allocate av buffer, errno=%d", errno); + return false; + } + uint8_t output[length + 1]; + memcpy(output, buffer + offset, length); + // print buffer and check with golden output. + ::close(av_fd); + return true; +} + +AssertionResult FilterTests::openFilterInDemux(DemuxFilterType type, uint32_t bufferSize) { + Result status; + EXPECT_TRUE(mDemux) << "Test with openDemux first."; + + // Create demux callback + mFilterCallback = new FilterCallback(); + + // Add filter to the local demux + mDemux->openFilter(type, bufferSize, mFilterCallback, + [&](Result result, const sp& filter) { + mFilter = filter; + status = result; + }); + + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult FilterTests::getNewlyOpenedFilterId_64bit(uint64_t& filterId) { + Result status; + EXPECT_TRUE(mDemux) << "Test with openDemux first."; + EXPECT_TRUE(mFilter) << "Test with openFilterInDemux first."; + EXPECT_TRUE(mFilterCallback) << "Test with openFilterInDemux first."; + + sp filter_v1_1 = + android::hardware::tv::tuner::V1_1::IFilter::castFrom(mFilter); + if (filter_v1_1 != NULL) { + filter_v1_1->getId64Bit([&](Result result, uint64_t filterId) { + mFilterId = filterId; + status = result; + }); + } else { + ALOGW("[vts] Can't cast IFilter into v1_1."); + return failure(); + } + + if (status == Result::SUCCESS) { + mFilterCallback->setFilterId(mFilterId); + mFilterCallback->setFilterInterface(mFilter); + mUsedFilterIds.insert(mUsedFilterIds.end(), mFilterId); + mFilters[mFilterId] = mFilter; + mFilterCallbacks[mFilterId] = mFilterCallback; + filterId = mFilterId; + } + + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult FilterTests::getSharedAvMemoryHandle(uint64_t filterId) { + EXPECT_TRUE(mFilters[filterId]) << "Open media filter first."; + Result status = Result::UNKNOWN_ERROR; + sp filter_v1_1 = + android::hardware::tv::tuner::V1_1::IFilter::castFrom(mFilters[filterId]); + if (filter_v1_1 != NULL) { + filter_v1_1->getAvSharedHandle([&](Result r, hidl_handle avMemory, uint64_t avMemSize) { + status = r; + if (status == Result::SUCCESS) { + mFilterCallbacks[mFilterId]->setSharedHandle(avMemory); + mFilterCallbacks[mFilterId]->setMemSize(avMemSize); + mAvSharedHandle = avMemory; + } + }); + } + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult FilterTests::releaseShareAvHandle(uint64_t filterId) { + Result status; + EXPECT_TRUE(mFilters[filterId]) << "Open media filter first."; + EXPECT_TRUE(mAvSharedHandle) << "No shared av handle to release."; + status = mFilters[filterId]->releaseAvHandle(mAvSharedHandle, 0 /*dataId*/); + + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult FilterTests::configFilter(DemuxFilterSettings setting, uint64_t filterId) { + Result status; + EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first."; + status = mFilters[filterId]->configure(setting); + + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult FilterTests::configAvFilterStreamType(AvStreamType type, uint64_t filterId) { + Result status; + EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first."; + sp filter_v1_1 = + android::hardware::tv::tuner::V1_1::IFilter::castFrom(mFilters[filterId]); + if (filter_v1_1 != NULL) { + status = filter_v1_1->configureAvStreamType(type); + } else { + ALOGW("[vts] Can't cast IFilter into v1_1."); + return failure(); + } + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult FilterTests::configIpFilterCid(uint32_t ipCid, uint64_t filterId) { + Result status; + EXPECT_TRUE(mFilters[filterId]) << "Open Ip filter first."; + + sp filter_v1_1 = + android::hardware::tv::tuner::V1_1::IFilter::castFrom(mFilters[filterId]); + if (filter_v1_1 != NULL) { + status = filter_v1_1->configureIpCid(ipCid); + } else { + ALOGW("[vts] Can't cast IFilter into v1_1."); + return failure(); + } + + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult FilterTests::getFilterMQDescriptor(uint64_t filterId, bool getMqDesc) { + if (!getMqDesc) { + ALOGE("[vts] Filter does not need FMQ."); + return success(); + } + Result status; + EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first."; + EXPECT_TRUE(mFilterCallbacks[filterId]) << "Test with getNewlyOpenedFilterId first."; + + mFilter->getQueueDesc([&](Result result, const MQDesc& filterMQDesc) { + mFilterMQDescriptor = filterMQDesc; + status = result; + }); + + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult FilterTests::startFilter(uint64_t filterId) { + EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first."; + Result status = mFilters[filterId]->start(); + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult FilterTests::stopFilter(uint64_t filterId) { + EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first."; + Result status = mFilters[filterId]->stop(); + + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult FilterTests::closeFilter(uint64_t filterId) { + EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first."; + Result status = mFilters[filterId]->close(); + if (status == Result::SUCCESS) { + for (int i = 0; i < mUsedFilterIds.size(); i++) { + if (mUsedFilterIds[i] == filterId) { + mUsedFilterIds.erase(mUsedFilterIds.begin() + i); + break; + } + } + mFilterCallbacks.erase(filterId); + mFilters.erase(filterId); + } + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult FilterTests::configureMonitorEvent(uint64_t filterId, uint32_t monitorEventTypes) { + EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first."; + Result status; + + sp filter_v1_1 = + android::hardware::tv::tuner::V1_1::IFilter::castFrom(mFilters[filterId]); + if (filter_v1_1 != NULL) { + status = filter_v1_1->configureMonitorEvent(monitorEventTypes); + if (monitorEventTypes & DemuxFilterMonitorEventType::SCRAMBLING_STATUS) { + mFilterCallbacks[filterId]->testFilterScramblingEvent(); + } + if (monitorEventTypes & DemuxFilterMonitorEventType::IP_CID_CHANGE) { + mFilterCallbacks[filterId]->testFilterIpCidEvent(); + } + } else { + ALOGW("[vts] Can't cast IFilter into v1_1."); + return failure(); + } + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult FilterTests::startIdTest(uint64_t filterId) { + EXPECT_TRUE(mFilterCallbacks[filterId]) << "Test with getNewlyOpenedFilterId first."; + mFilterCallbacks[filterId]->testStartIdAfterReconfigure(); + return AssertionResult(true); +} diff --git a/tv/tuner/1.1/vts/functional/FilterTests.h b/tv/tuner/1.1/vts/functional/FilterTests.h new file mode 100644 index 0000000000000000000000000000000000000000..72c8129f4aab6f16d52a555407c95268fe146e31 --- /dev/null +++ b/tv/tuner/1.1/vts/functional/FilterTests.h @@ -0,0 +1,236 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using android::Condition; +using android::Mutex; +using android::sp; +using android::hardware::EventFlag; +using android::hardware::hidl_handle; +using android::hardware::hidl_string; +using android::hardware::hidl_vec; +using android::hardware::kSynchronizedReadWrite; +using android::hardware::MessageQueue; +using android::hardware::MQDescriptorSync; +using android::hardware::Return; +using android::hardware::Void; +using android::hardware::tv::tuner::V1_0::DemuxFilterEvent; +using android::hardware::tv::tuner::V1_0::DemuxFilterMainType; +using android::hardware::tv::tuner::V1_0::DemuxFilterMediaEvent; +using android::hardware::tv::tuner::V1_0::DemuxFilterSettings; +using android::hardware::tv::tuner::V1_0::DemuxFilterStatus; +using android::hardware::tv::tuner::V1_0::DemuxFilterType; +using android::hardware::tv::tuner::V1_0::DemuxTsFilterType; +using android::hardware::tv::tuner::V1_0::IDemux; +using android::hardware::tv::tuner::V1_0::IFilter; +using android::hardware::tv::tuner::V1_0::Result; +using android::hardware::tv::tuner::V1_1::AvStreamType; +using android::hardware::tv::tuner::V1_1::DemuxFilterEventExt; +using android::hardware::tv::tuner::V1_1::DemuxFilterMonitorEvent; +using android::hardware::tv::tuner::V1_1::DemuxFilterMonitorEventType; +using android::hardware::tv::tuner::V1_1::IFilterCallback; +using android::hardware::tv::tuner::V1_1::ITuner; + +using ::testing::AssertionResult; + +using namespace std; + +enum FilterEventType : uint8_t { + UNDEFINED, + SECTION, + MEDIA, + PES, + RECORD, + MMTPRECORD, + DOWNLOAD, + TEMI, +}; + +using FilterMQ = MessageQueue; +using MQDesc = MQDescriptorSync; + +#define WAIT_TIMEOUT 3000000000 + +class FilterCallback : public IFilterCallback { + public: + virtual Return onFilterEvent_1_1(const DemuxFilterEvent& filterEvent, + const DemuxFilterEventExt& filterEventExt) override { + android::Mutex::Autolock autoLock(mMsgLock); + // Temprarily we treat the first coming back filter data on the matching pid a success + // once all of the MQ are cleared, means we got all the expected output + mFilterEvent = filterEvent; + mFilterEventExt = filterEventExt; + readFilterEventData(); + mPidFilterOutputCount++; + mMsgCondition.signal(); + return Void(); + } + + virtual Return onFilterEvent( + const android::hardware::tv::tuner::V1_0::DemuxFilterEvent& filterEvent) override { + android::Mutex::Autolock autoLock(mMsgLock); + // Temprarily we treat the first coming back filter data on the matching pid a success + // once all of the MQ are cleared, means we got all the expected output + mFilterEvent = filterEvent; + readFilterEventData(); + mPidFilterOutputCount++; + mMsgCondition.signal(); + return Void(); + } + + virtual Return onFilterStatus(const DemuxFilterStatus /*status*/) override { + return Void(); + } + + void setFilterId(uint32_t filterId) { mFilterId = filterId; } + void setFilterInterface(sp filter) { mFilter = filter; } + void setFilterEventType(FilterEventType type) { mFilterEventType = type; } + void setSharedHandle(hidl_handle sharedHandle) { mAvSharedHandle = sharedHandle; } + void setMemSize(uint64_t size) { mAvSharedMemSize = size; } + + void testFilterDataOutput(); + void testFilterScramblingEvent(); + void testFilterIpCidEvent(); + void testStartIdAfterReconfigure(); + + void readFilterEventData(); + bool dumpAvData(DemuxFilterMediaEvent event); + + private: + uint32_t mFilterId; + sp mFilter; + FilterEventType mFilterEventType; + DemuxFilterEvent mFilterEvent; + DemuxFilterEventExt mFilterEventExt; + + hidl_handle mAvSharedHandle = NULL; + uint64_t mAvSharedMemSize = -1; + + android::Mutex mMsgLock; + android::Mutex mFilterOutputLock; + android::Condition mMsgCondition; + + int mPidFilterOutputCount = 0; + int mScramblingStatusEvent = 0; + int mIpCidEvent = 0; + bool mStartIdReceived = false; +}; + +class FilterTests { + public: + void setService(sp tuner) { mService = tuner; } + void setDemux(sp demux) { mDemux = demux; } + sp getFilterById(uint64_t filterId) { return mFilters[filterId]; } + + map> getFilterCallbacks() { return mFilterCallbacks; } + + AssertionResult openFilterInDemux(DemuxFilterType type, uint32_t bufferSize); + AssertionResult getNewlyOpenedFilterId_64bit(uint64_t& filterId); + AssertionResult getSharedAvMemoryHandle(uint64_t filterId); + AssertionResult releaseShareAvHandle(uint64_t filterId); + AssertionResult configFilter(DemuxFilterSettings setting, uint64_t filterId); + AssertionResult configAvFilterStreamType(AvStreamType type, uint64_t filterId); + AssertionResult configIpFilterCid(uint32_t ipCid, uint64_t filterId); + AssertionResult configureMonitorEvent(uint64_t filterId, uint32_t monitorEventTypes); + AssertionResult getFilterMQDescriptor(uint64_t filterId, bool getMqDesc); + AssertionResult startFilter(uint64_t filterId); + AssertionResult stopFilter(uint64_t filterId); + AssertionResult closeFilter(uint64_t filterId); + AssertionResult startIdTest(uint64_t filterId); + + FilterEventType getFilterEventType(DemuxFilterType type) { + FilterEventType eventType = FilterEventType::UNDEFINED; + switch (type.mainType) { + case DemuxFilterMainType::TS: + switch (type.subType.tsFilterType()) { + case DemuxTsFilterType::UNDEFINED: + break; + case DemuxTsFilterType::SECTION: + eventType = FilterEventType::SECTION; + break; + case DemuxTsFilterType::PES: + eventType = FilterEventType::PES; + break; + case DemuxTsFilterType::TS: + break; + case DemuxTsFilterType::AUDIO: + case DemuxTsFilterType::VIDEO: + eventType = FilterEventType::MEDIA; + break; + case DemuxTsFilterType::PCR: + break; + case DemuxTsFilterType::RECORD: + eventType = FilterEventType::RECORD; + break; + case DemuxTsFilterType::TEMI: + eventType = FilterEventType::TEMI; + break; + } + break; + case DemuxFilterMainType::MMTP: + /*mmtpSettings*/ + break; + case DemuxFilterMainType::IP: + /*ipSettings*/ + break; + case DemuxFilterMainType::TLV: + /*tlvSettings*/ + break; + case DemuxFilterMainType::ALP: + /*alpSettings*/ + break; + default: + break; + } + return eventType; + } + + protected: + static AssertionResult failure() { return ::testing::AssertionFailure(); } + + static AssertionResult success() { return ::testing::AssertionSuccess(); } + + sp mService; + sp mFilter; + sp mDemux; + map> mFilters; + map> mFilterCallbacks; + + sp mFilterCallback; + MQDesc mFilterMQDescriptor; + vector mUsedFilterIds; + + hidl_handle mAvSharedHandle = NULL; + + uint64_t mFilterId = -1; +}; diff --git a/tv/tuner/1.1/vts/functional/FrontendTests.cpp b/tv/tuner/1.1/vts/functional/FrontendTests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9c575ff78291b6e626fd004ee97b166ea0d48e47 --- /dev/null +++ b/tv/tuner/1.1/vts/functional/FrontendTests.cpp @@ -0,0 +1,524 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "FrontendTests.h" + +Return FrontendCallback::onEvent(FrontendEventType frontendEventType) { + android::Mutex::Autolock autoLock(mMsgLock); + ALOGD("[vts] frontend event received. Type: %d", frontendEventType); + mEventReceived = true; + mMsgCondition.signal(); + switch (frontendEventType) { + case FrontendEventType::LOCKED: + mLockMsgReceived = true; + mLockMsgCondition.signal(); + return Void(); + default: + // do nothing + return Void(); + } +} + +Return FrontendCallback::onScanMessage(FrontendScanMessageType type, + const FrontendScanMessage& message) { + android::Mutex::Autolock autoLock(mMsgLock); + while (!mScanMsgProcessed) { + mMsgCondition.wait(mMsgLock); + } + ALOGD("[vts] frontend scan message. Type: %d", type); + mScanMessageReceived = true; + mScanMsgProcessed = false; + mScanMessageType = type; + mScanMessage = message; + mMsgCondition.signal(); + return Void(); +} + +Return FrontendCallback::onScanMessageExt1_1(FrontendScanMessageTypeExt1_1 type, + const FrontendScanMessageExt1_1& message) { + android::Mutex::Autolock autoLock(mMsgLock); + ALOGD("[vts] frontend ext1_1 scan message. Type: %d", type); + switch (message.getDiscriminator()) { + case FrontendScanMessageExt1_1::hidl_discriminator::modulation: + readFrontendScanMessageExt1_1Modulation(message.modulation()); + break; + case FrontendScanMessageExt1_1::hidl_discriminator::isHighPriority: + ALOGD("[vts] frontend ext1_1 scan message high priority: %d", message.isHighPriority()); + break; + case FrontendScanMessageExt1_1::hidl_discriminator::annex: + ALOGD("[vts] frontend ext1_1 scan message dvbc annex: %hhu", message.annex()); + break; + default: + break; + } + return Void(); +} + +void FrontendCallback::readFrontendScanMessageExt1_1Modulation(FrontendModulation modulation) { + switch (modulation.getDiscriminator()) { + case FrontendModulation::hidl_discriminator::dvbc: + ALOGD("[vts] frontend ext1_1 scan message modulation dvbc: %d", modulation.dvbc()); + break; + case FrontendModulation::hidl_discriminator::dvbs: + ALOGD("[vts] frontend ext1_1 scan message modulation dvbs: %d", modulation.dvbs()); + break; + case FrontendModulation::hidl_discriminator::isdbs: + ALOGD("[vts] frontend ext1_1 scan message modulation isdbs: %d", modulation.isdbs()); + break; + case FrontendModulation::hidl_discriminator::isdbs3: + ALOGD("[vts] frontend ext1_1 scan message modulation isdbs3: %d", modulation.isdbs3()); + break; + case FrontendModulation::hidl_discriminator::isdbt: + ALOGD("[vts] frontend ext1_1 scan message modulation isdbt: %d", modulation.isdbt()); + break; + case FrontendModulation::hidl_discriminator::atsc: + ALOGD("[vts] frontend ext1_1 scan message modulation atsc: %d", modulation.atsc()); + break; + case FrontendModulation::hidl_discriminator::atsc3: + ALOGD("[vts] frontend ext1_1 scan message modulation atsc3: %d", modulation.atsc3()); + break; + case FrontendModulation::hidl_discriminator::dvbt: + ALOGD("[vts] frontend ext1_1 scan message modulation dvbt: %d", modulation.dvbt()); + break; + default: + break; + } +} + +void FrontendCallback::tuneTestOnLock(sp& frontend, FrontendSettings settings, + FrontendSettingsExt1_1 settingsExt1_1) { + sp frontend_1_1; + frontend_1_1 = android::hardware::tv::tuner::V1_1::IFrontend::castFrom(frontend); + if (frontend_1_1 == nullptr) { + EXPECT_TRUE(false) << "Couldn't get 1.1 IFrontend from the Hal implementation."; + return; + } + + Result result = frontend_1_1->tune_1_1(settings, settingsExt1_1); + EXPECT_TRUE(result == Result::SUCCESS); + + android::Mutex::Autolock autoLock(mMsgLock); + while (!mLockMsgReceived) { + if (-ETIMEDOUT == mLockMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) { + EXPECT_TRUE(false) << "Event LOCKED not received within timeout"; + mLockMsgReceived = false; + return; + } + } + mLockMsgReceived = false; +} + +void FrontendCallback::scanTest(sp& frontend, FrontendConfig1_1 config, + FrontendScanType type) { + sp frontend_1_1; + frontend_1_1 = android::hardware::tv::tuner::V1_1::IFrontend::castFrom(frontend); + if (frontend_1_1 == nullptr) { + EXPECT_TRUE(false) << "Couldn't get 1.1 IFrontend from the Hal implementation."; + return; + } + + uint32_t targetFrequency = getTargetFrequency(config.config1_0.settings); + if (type == FrontendScanType::SCAN_BLIND) { + // reset the frequency in the scan configuration to test blind scan. The settings param of + // passed in means the real input config on the transponder connected to the DUT. + // We want the blind the test to start from lower frequency than this to check the blind + // scan implementation. + resetBlindScanStartingFrequency(config, targetFrequency - 100); + } + + Result result = frontend_1_1->scan_1_1(config.config1_0.settings, type, config.settingsExt1_1); + EXPECT_TRUE(result == Result::SUCCESS); + + bool scanMsgLockedReceived = false; + bool targetFrequencyReceived = false; + + android::Mutex::Autolock autoLock(mMsgLock); +wait: + while (!mScanMessageReceived) { + if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) { + EXPECT_TRUE(false) << "Scan message not received within timeout"; + mScanMessageReceived = false; + mScanMsgProcessed = true; + return; + } + } + + if (mScanMessageType != FrontendScanMessageType::END) { + if (mScanMessageType == FrontendScanMessageType::LOCKED) { + scanMsgLockedReceived = true; + Result result = + frontend_1_1->scan_1_1(config.config1_0.settings, type, config.settingsExt1_1); + EXPECT_TRUE(result == Result::SUCCESS); + } + + if (mScanMessageType == FrontendScanMessageType::FREQUENCY) { + targetFrequencyReceived = mScanMessage.frequencies().size() > 0 && + mScanMessage.frequencies()[0] == targetFrequency; + } + + if (mScanMessageType == FrontendScanMessageType::PROGRESS_PERCENT) { + ALOGD("[vts] Scan in progress...[%d%%]", mScanMessage.progressPercent()); + } + + mScanMessageReceived = false; + mScanMsgProcessed = true; + mMsgCondition.signal(); + goto wait; + } + + EXPECT_TRUE(scanMsgLockedReceived) << "Scan message LOCKED not received before END"; + EXPECT_TRUE(targetFrequencyReceived) << "frequency not received before LOCKED on blindScan"; + mScanMessageReceived = false; + mScanMsgProcessed = true; +} + +uint32_t FrontendCallback::getTargetFrequency(FrontendSettings settings) { + switch (settings.getDiscriminator()) { + case FrontendSettings::hidl_discriminator::analog: + return settings.analog().frequency; + case FrontendSettings::hidl_discriminator::atsc: + return settings.atsc().frequency; + case FrontendSettings::hidl_discriminator::atsc3: + return settings.atsc3().frequency; + case FrontendSettings::hidl_discriminator::dvbc: + return settings.dvbc().frequency; + case FrontendSettings::hidl_discriminator::dvbs: + return settings.dvbs().frequency; + case FrontendSettings::hidl_discriminator::dvbt: + return settings.dvbt().frequency; + case FrontendSettings::hidl_discriminator::isdbs: + return settings.isdbs().frequency; + case FrontendSettings::hidl_discriminator::isdbs3: + return settings.isdbs3().frequency; + case FrontendSettings::hidl_discriminator::isdbt: + return settings.isdbt().frequency; + } +} + +void FrontendCallback::resetBlindScanStartingFrequency(FrontendConfig1_1& config, + uint32_t resetingFreq) { + switch (config.config1_0.settings.getDiscriminator()) { + case FrontendSettings::hidl_discriminator::analog: + config.config1_0.settings.analog().frequency = resetingFreq; + break; + case FrontendSettings::hidl_discriminator::atsc: + config.config1_0.settings.atsc().frequency = resetingFreq; + break; + case FrontendSettings::hidl_discriminator::atsc3: + config.config1_0.settings.atsc3().frequency = resetingFreq; + break; + case FrontendSettings::hidl_discriminator::dvbc: + config.config1_0.settings.dvbc().frequency = resetingFreq; + break; + case FrontendSettings::hidl_discriminator::dvbs: + config.config1_0.settings.dvbs().frequency = resetingFreq; + break; + case FrontendSettings::hidl_discriminator::dvbt: + config.config1_0.settings.dvbt().frequency = resetingFreq; + break; + case FrontendSettings::hidl_discriminator::isdbs: + config.config1_0.settings.isdbs().frequency = resetingFreq; + break; + case FrontendSettings::hidl_discriminator::isdbs3: + config.config1_0.settings.isdbs3().frequency = resetingFreq; + break; + case FrontendSettings::hidl_discriminator::isdbt: + config.config1_0.settings.isdbt().frequency = resetingFreq; + break; + } +} + +AssertionResult FrontendTests::getFrontendIds() { + Result status; + mService->getFrontendIds([&](Result result, const hidl_vec& frontendIds) { + status = result; + mFeIds = frontendIds; + }); + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult FrontendTests::getFrontendInfo(uint32_t frontendId) { + Result status; + mService->getFrontendInfo(frontendId, [&](Result result, const FrontendInfo& frontendInfo) { + mFrontendInfo = frontendInfo; + status = result; + }); + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult FrontendTests::openFrontendById(uint32_t frontendId) { + Result status; + mService->openFrontendById(frontendId, [&](Result result, const sp& frontend) { + mFrontend = frontend; + status = result; + }); + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult FrontendTests::setFrontendCallback() { + EXPECT_TRUE(mFrontend) << "Test with openFrontendById first."; + mFrontendCallback = new FrontendCallback(); + auto callbackStatus = mFrontend->setCallback(mFrontendCallback); + return AssertionResult(callbackStatus.isOk()); +} + +AssertionResult FrontendTests::scanFrontend(FrontendConfig1_1 config, FrontendScanType type) { + EXPECT_TRUE(mFrontendCallback) + << "test with openFrontendById/setFrontendCallback/getFrontendInfo first."; + + EXPECT_TRUE(mFrontendInfo.type == config.config1_0.type) + << "FrontendConfig does not match the frontend info of the given id."; + + mFrontendCallback->scanTest(mFrontend, config, type); + return AssertionResult(true); +} + +AssertionResult FrontendTests::stopScanFrontend() { + EXPECT_TRUE(mFrontend) << "Test with openFrontendById first."; + Result status; + status = mFrontend->stopScan(); + + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult FrontendTests::getFrontendDtmbCaps(uint32_t id) { + Result status; + mService->getFrontendDtmbCapabilities( + id, [&](Result result, const FrontendDtmbCapabilities& /*caps*/) { status = result; }); + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult FrontendTests::linkCiCam(uint32_t ciCamId) { + sp frontend_1_1; + frontend_1_1 = android::hardware::tv::tuner::V1_1::IFrontend::castFrom(mFrontend); + if (frontend_1_1 == nullptr) { + EXPECT_TRUE(false) << "Couldn't get 1.1 IFrontend from the Hal implementation."; + return failure(); + } + + Result status; + uint32_t ltsId; + frontend_1_1->linkCiCam(ciCamId, [&](Result r, uint32_t id) { + status = r; + ltsId = id; + }); + + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult FrontendTests::unlinkCiCam(uint32_t ciCamId) { + sp frontend_1_1; + frontend_1_1 = android::hardware::tv::tuner::V1_1::IFrontend::castFrom(mFrontend); + if (frontend_1_1 == nullptr) { + EXPECT_TRUE(false) << "Couldn't get 1.1 IFrontend from the Hal implementation."; + return failure(); + } + + Result status = frontend_1_1->unlinkCiCam(ciCamId); + return AssertionResult(status == Result::SUCCESS); +} + +void FrontendTests::verifyFrontendStatusExt1_1(vector statusTypes, + vector expectStatuses) { + ASSERT_TRUE(mFrontend) << "Frontend is not opened yet."; + Result status; + vector realStatuses; + + sp frontend_1_1; + frontend_1_1 = android::hardware::tv::tuner::V1_1::IFrontend::castFrom(mFrontend); + if (frontend_1_1 == nullptr) { + EXPECT_TRUE(false) << "Couldn't get 1.1 IFrontend from the Hal implementation."; + return; + } + + frontend_1_1->getStatusExt1_1( + statusTypes, [&](Result result, const hidl_vec& statuses) { + status = result; + realStatuses = statuses; + }); + + ASSERT_TRUE(realStatuses.size() == statusTypes.size()); + for (int i = 0; i < statusTypes.size(); i++) { + FrontendStatusTypeExt1_1 type = statusTypes[i]; + switch (type) { + case FrontendStatusTypeExt1_1::MODULATIONS: { + // TODO: verify modulations + break; + } + case FrontendStatusTypeExt1_1::BERS: { + ASSERT_TRUE(std::equal(realStatuses[i].bers().begin(), realStatuses[i].bers().end(), + expectStatuses[i].bers().begin())); + break; + } + case FrontendStatusTypeExt1_1::CODERATES: { + ASSERT_TRUE(std::equal(realStatuses[i].codeRates().begin(), + realStatuses[i].codeRates().end(), + expectStatuses[i].codeRates().begin())); + break; + } + case FrontendStatusTypeExt1_1::GUARD_INTERVAL: { + // TODO: verify interval + break; + } + case FrontendStatusTypeExt1_1::TRANSMISSION_MODE: { + // TODO: verify tranmission mode + break; + } + case FrontendStatusTypeExt1_1::UEC: { + ASSERT_TRUE(realStatuses[i].uec() == expectStatuses[i].uec()); + break; + } + case FrontendStatusTypeExt1_1::T2_SYSTEM_ID: { + ASSERT_TRUE(realStatuses[i].systemId() == expectStatuses[i].systemId()); + break; + } + case FrontendStatusTypeExt1_1::INTERLEAVINGS: { + ASSERT_TRUE(std::equal(realStatuses[i].interleaving().begin(), + realStatuses[i].interleaving().end(), + expectStatuses[i].interleaving().begin())); + break; + } + case FrontendStatusTypeExt1_1::ISDBT_SEGMENTS: { + ASSERT_TRUE(std::equal(realStatuses[i].isdbtSegment().begin(), + realStatuses[i].isdbtSegment().end(), + expectStatuses[i].isdbtSegment().begin())); + break; + } + case FrontendStatusTypeExt1_1::TS_DATA_RATES: { + ASSERT_TRUE(std::equal(realStatuses[i].tsDataRate().begin(), + realStatuses[i].tsDataRate().end(), + expectStatuses[i].tsDataRate().begin())); + break; + } + case FrontendStatusTypeExt1_1::ROLL_OFF: { + // TODO: verify roll off + break; + } + case FrontendStatusTypeExt1_1::IS_MISO: { + ASSERT_TRUE(realStatuses[i].isMiso() == expectStatuses[i].isMiso()); + break; + } + case FrontendStatusTypeExt1_1::IS_LINEAR: { + ASSERT_TRUE(realStatuses[i].isLinear() == expectStatuses[i].isLinear()); + break; + } + case FrontendStatusTypeExt1_1::IS_SHORT_FRAMES: { + ASSERT_TRUE(realStatuses[i].isShortFrames() == expectStatuses[i].isShortFrames()); + break; + } + default: { + continue; + } + } + } + ASSERT_TRUE(status == Result::SUCCESS); +} + +AssertionResult FrontendTests::tuneFrontend(FrontendConfig1_1 config, bool testWithDemux) { + EXPECT_TRUE(mFrontendCallback) + << "test with openFrontendById/setFrontendCallback/getFrontendInfo first."; + + EXPECT_TRUE(mFrontendInfo.type == config.config1_0.type) + << "FrontendConfig does not match the frontend info of the given id."; + + mIsSoftwareFe = config.config1_0.isSoftwareFe; + bool result = true; + if (mIsSoftwareFe && testWithDemux) { + result &= mDvrTests.openDvrInDemux(mDvrConfig.type, mDvrConfig.bufferSize) == success(); + result &= mDvrTests.configDvrPlayback(mDvrConfig.settings) == success(); + result &= mDvrTests.getDvrPlaybackMQDescriptor() == success(); + mDvrTests.startPlaybackInputThread(mDvrConfig.playbackInputFile, + mDvrConfig.settings.playback()); + if (!result) { + ALOGW("[vts] Software frontend dvr configure failed."); + return failure(); + } + } + mFrontendCallback->tuneTestOnLock(mFrontend, config.config1_0.settings, config.settingsExt1_1); + return AssertionResult(true); +} + +AssertionResult FrontendTests::stopTuneFrontend(bool testWithDemux) { + EXPECT_TRUE(mFrontend) << "Test with openFrontendById first."; + Result status; + status = mFrontend->stopTune(); + if (mIsSoftwareFe && testWithDemux) { + mDvrTests.stopPlaybackThread(); + mDvrTests.closeDvrPlayback(); + } + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult FrontendTests::closeFrontend() { + EXPECT_TRUE(mFrontend) << "Test with openFrontendById first."; + Result status; + status = mFrontend->close(); + mFrontend = nullptr; + mFrontendCallback = nullptr; + return AssertionResult(status == Result::SUCCESS); +} + +void FrontendTests::getFrontendIdByType(FrontendType feType, uint32_t& feId) { + ASSERT_TRUE(getFrontendIds()); + ASSERT_TRUE(mFeIds.size() > 0); + for (size_t i = 0; i < mFeIds.size(); i++) { + ASSERT_TRUE(getFrontendInfo(mFeIds[i])); + if (mFrontendInfo.type != feType) { + continue; + } + feId = mFeIds[i]; + return; + } + feId = INVALID_ID; +} + +void FrontendTests::tuneTest(FrontendConfig1_1 frontendConf) { + uint32_t feId; + getFrontendIdByType(frontendConf.config1_0.type, feId); + ASSERT_TRUE(feId != INVALID_ID); + ASSERT_TRUE(openFrontendById(feId)); + ASSERT_TRUE(setFrontendCallback()); + if (frontendConf.canConnectToCiCam) { + ASSERT_TRUE(linkCiCam(frontendConf.ciCamId)); + ASSERT_TRUE(unlinkCiCam(frontendConf.ciCamId)); + } + ASSERT_TRUE(tuneFrontend(frontendConf, false /*testWithDemux*/)); + verifyFrontendStatusExt1_1(frontendConf.tuneStatusTypes, frontendConf.expectTuneStatuses); + ASSERT_TRUE(stopTuneFrontend(false /*testWithDemux*/)); + ASSERT_TRUE(closeFrontend()); +} + +void FrontendTests::scanTest(FrontendConfig1_1 frontendConf, FrontendScanType scanType) { + uint32_t feId; + getFrontendIdByType(frontendConf.config1_0.type, feId); + ASSERT_TRUE(feId != INVALID_ID); + ASSERT_TRUE(openFrontendById(feId)); + ASSERT_TRUE(setFrontendCallback()); + ASSERT_TRUE(scanFrontend(frontendConf, scanType)); + ASSERT_TRUE(stopScanFrontend()); + ASSERT_TRUE(closeFrontend()); +} + +void FrontendTests::getFrontendDtmbCapsTest() { + uint32_t feId; + getFrontendIdByType( + static_cast(android::hardware::tv::tuner::V1_1::FrontendType::DTMB), + feId); + if (feId != INVALID_ID) { + ALOGD("[vts] Found DTMB Frontend"); + ASSERT_TRUE(getFrontendDtmbCaps(feId)); + } +} diff --git a/tv/tuner/1.1/vts/functional/FrontendTests.h b/tv/tuner/1.1/vts/functional/FrontendTests.h new file mode 100644 index 0000000000000000000000000000000000000000..36873895715a2323f8e4a09674c5988cc5c232c3 --- /dev/null +++ b/tv/tuner/1.1/vts/functional/FrontendTests.h @@ -0,0 +1,164 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "DvrTests.h" +#include "VtsHalTvTunerV1_1TestConfigurations.h" + +#define WAIT_TIMEOUT 3000000000 +#define INVALID_ID -1 + +using android::Condition; +using android::IMemory; +using android::IMemoryHeap; +using android::MemoryDealer; +using android::Mutex; +using android::sp; +using android::hardware::fromHeap; +using android::hardware::hidl_vec; +using android::hardware::Return; +using android::hardware::Void; +using android::hardware::tv::tuner::V1_0::FrontendEventType; +using android::hardware::tv::tuner::V1_0::FrontendId; +using android::hardware::tv::tuner::V1_0::FrontendInfo; +using android::hardware::tv::tuner::V1_0::FrontendScanMessage; +using android::hardware::tv::tuner::V1_0::FrontendScanMessageType; +using android::hardware::tv::tuner::V1_0::FrontendScanType; +using android::hardware::tv::tuner::V1_0::IFrontend; +using android::hardware::tv::tuner::V1_0::Result; +using android::hardware::tv::tuner::V1_1::FrontendDtmbCapabilities; +using android::hardware::tv::tuner::V1_1::FrontendModulation; +using android::hardware::tv::tuner::V1_1::FrontendScanMessageExt1_1; +using android::hardware::tv::tuner::V1_1::FrontendScanMessageTypeExt1_1; +using android::hardware::tv::tuner::V1_1::IFrontendCallback; +using android::hardware::tv::tuner::V1_1::ITuner; + +using ::testing::AssertionResult; + +using namespace std; + +#define INVALID_ID -1 +#define WAIT_TIMEOUT 3000000000 + +class FrontendCallback : public IFrontendCallback { + public: + virtual Return onEvent(FrontendEventType frontendEventType) override; + virtual Return onScanMessage(FrontendScanMessageType type, + const FrontendScanMessage& message) override; + virtual Return onScanMessageExt1_1(FrontendScanMessageTypeExt1_1 type, + const FrontendScanMessageExt1_1& message) override; + + void tuneTestOnLock(sp& frontend, FrontendSettings settings, + FrontendSettingsExt1_1 settingsExt1_1); + void scanTest(sp& frontend, FrontendConfig1_1 config, FrontendScanType type); + + // Helper methods + uint32_t getTargetFrequency(FrontendSettings settings); + void resetBlindScanStartingFrequency(FrontendConfig1_1& config, uint32_t resetingFreq); + + private: + void readFrontendScanMessageExt1_1Modulation(FrontendModulation modulation); + + bool mEventReceived = false; + bool mScanMessageReceived = false; + bool mLockMsgReceived = false; + bool mScanMsgProcessed = true; + FrontendScanMessageType mScanMessageType; + FrontendScanMessage mScanMessage; + hidl_vec mEventMessage; + android::Mutex mMsgLock; + android::Condition mMsgCondition; + android::Condition mLockMsgCondition; +}; + +class FrontendTests { + public: + sp mService; + + void setService(sp tuner) { + mService = tuner; + mDvrTests.setService(tuner); + getDefaultSoftwareFrontendPlaybackConfig(mDvrConfig); + } + + AssertionResult getFrontendIds(); + AssertionResult getFrontendInfo(uint32_t frontendId); + AssertionResult openFrontendById(uint32_t frontendId); + AssertionResult setFrontendCallback(); + AssertionResult scanFrontend(FrontendConfig1_1 config, FrontendScanType type); + AssertionResult stopScanFrontend(); + AssertionResult tuneFrontend(FrontendConfig1_1 config, bool testWithDemux); + void verifyFrontendStatusExt1_1(vector statusTypes, + vector expectStatuses); + AssertionResult stopTuneFrontend(bool testWithDemux); + AssertionResult closeFrontend(); + AssertionResult getFrontendDtmbCaps(uint32_t); + + AssertionResult linkCiCam(uint32_t ciCamId); + AssertionResult unlinkCiCam(uint32_t ciCamId); + + void getFrontendIdByType(FrontendType feType, uint32_t& feId); + void tuneTest(FrontendConfig1_1 frontendConf); + void scanTest(FrontendConfig1_1 frontend, FrontendScanType type); + void getFrontendDtmbCapsTest(); + + void setDvrTests(DvrTests dvrTests) { mDvrTests = dvrTests; } + void setDemux(sp demux) { mDvrTests.setDemux(demux); } + void setSoftwareFrontendDvrConfig(DvrConfig conf) { mDvrConfig = conf; } + + protected: + static AssertionResult failure() { return ::testing::AssertionFailure(); } + static AssertionResult success() { return ::testing::AssertionSuccess(); } + + void getDefaultSoftwareFrontendPlaybackConfig(DvrConfig& dvrConfig) { + PlaybackSettings playbackSettings{ + .statusMask = 0xf, + .lowThreshold = 0x1000, + .highThreshold = 0x07fff, + .dataFormat = DataFormat::ES, + .packetSize = 188, + }; + dvrConfig.type = DvrType::PLAYBACK; + dvrConfig.playbackInputFile = "/data/local/tmp/test.es"; + dvrConfig.bufferSize = FMQ_SIZE_4M; + dvrConfig.settings.playback(playbackSettings); + } + + sp mFrontend; + FrontendInfo mFrontendInfo; + sp mFrontendCallback; + hidl_vec mFeIds; + + DvrTests mDvrTests; + bool mIsSoftwareFe = false; + DvrConfig mDvrConfig; +}; diff --git a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1a9def83b1b66d4ac60b6edddeb27124482c5820 --- /dev/null +++ b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp @@ -0,0 +1,309 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "VtsHalTvTunerV1_1TargetTest.h" + +namespace { + +AssertionResult TunerBroadcastHidlTest::filterDataOutputTest() { + return filterDataOutputTestBase(mFilterTests); +} + +void TunerFilterHidlTest::configSingleFilterInDemuxTest(FilterConfig1_1 filterConf, + FrontendConfig1_1 frontendConf) { + uint32_t feId; + uint32_t demuxId; + sp demux; + uint64_t filterId; + + mFrontendTests.getFrontendIdByType(frontendConf.config1_0.type, feId); + ASSERT_TRUE(feId != INVALID_ID); + ASSERT_TRUE(mFrontendTests.openFrontendById(feId)); + ASSERT_TRUE(mFrontendTests.setFrontendCallback()); + ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId)); + ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId)); + mFilterTests.setDemux(demux); + ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.config1_0.type, + filterConf.config1_0.bufferSize)); + ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId_64bit(filterId)); + ASSERT_TRUE(mFilterTests.configFilter(filterConf.config1_0.settings, filterId)); + if (filterConf.config1_0.type.mainType == DemuxFilterMainType::IP) { + ASSERT_TRUE(mFilterTests.configIpFilterCid(filterConf.ipCid, filterId)); + } + if (filterConf.monitorEventTypes > 0) { + ASSERT_TRUE(mFilterTests.configureMonitorEvent(filterId, filterConf.monitorEventTypes)); + } + ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterConf.config1_0.getMqDesc)); + ASSERT_TRUE(mFilterTests.startFilter(filterId)); + ASSERT_TRUE(mFilterTests.stopFilter(filterId)); + ASSERT_TRUE(mFilterTests.closeFilter(filterId)); + ASSERT_TRUE(mDemuxTests.closeDemux()); + ASSERT_TRUE(mFrontendTests.closeFrontend()); +} + +void TunerFilterHidlTest::reconfigSingleFilterInDemuxTest(FilterConfig1_1 filterConf, + FilterConfig1_1 filterReconf, + FrontendConfig1_1 frontendConf) { + uint32_t feId; + uint32_t demuxId; + sp demux; + uint64_t filterId; + + mFrontendTests.getFrontendIdByType(frontendConf.config1_0.type, feId); + ASSERT_TRUE(feId != INVALID_ID); + ASSERT_TRUE(mFrontendTests.openFrontendById(feId)); + ASSERT_TRUE(mFrontendTests.setFrontendCallback()); + if (frontendConf.config1_0.isSoftwareFe) { + mFrontendTests.setSoftwareFrontendDvrConfig(dvrMap[live.dvrSoftwareFeId]); + } + ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId)); + ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId)); + mFrontendTests.setDemux(demux); + mFilterTests.setDemux(demux); + ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.config1_0.type, + filterConf.config1_0.bufferSize)); + ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId_64bit(filterId)); + ASSERT_TRUE(mFilterTests.configFilter(filterConf.config1_0.settings, filterId)); + ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterConf.config1_0.getMqDesc)); + ASSERT_TRUE(mFilterTests.startFilter(filterId)); + ASSERT_TRUE(mFilterTests.stopFilter(filterId)); + ASSERT_TRUE(mFilterTests.configFilter(filterReconf.config1_0.settings, filterId)); + ASSERT_TRUE(mFilterTests.startFilter(filterId)); + ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/)); + ASSERT_TRUE(mFilterTests.startIdTest(filterId)); + ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/)); + ASSERT_TRUE(mFilterTests.stopFilter(filterId)); + ASSERT_TRUE(mFilterTests.closeFilter(filterId)); + ASSERT_TRUE(mDemuxTests.closeDemux()); + ASSERT_TRUE(mFrontendTests.closeFrontend()); +} + +void TunerBroadcastHidlTest::mediaFilterUsingSharedMemoryTest(FilterConfig1_1 filterConf, + FrontendConfig1_1 frontendConf) { + uint32_t feId; + uint32_t demuxId; + sp demux; + uint64_t filterId; + + mFrontendTests.getFrontendIdByType(frontendConf.config1_0.type, feId); + ASSERT_TRUE(feId != INVALID_ID); + ASSERT_TRUE(mFrontendTests.openFrontendById(feId)); + ASSERT_TRUE(mFrontendTests.setFrontendCallback()); + if (frontendConf.config1_0.isSoftwareFe) { + mFrontendTests.setSoftwareFrontendDvrConfig(dvrMap[live.dvrSoftwareFeId]); + } + ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId)); + ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId)); + mFrontendTests.setDemux(demux); + mFilterTests.setDemux(demux); + ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.config1_0.type, + filterConf.config1_0.bufferSize)); + ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId_64bit(filterId)); + ASSERT_TRUE(mFilterTests.configFilter(filterConf.config1_0.settings, filterId)); + ASSERT_TRUE(mFilterTests.getSharedAvMemoryHandle(filterId)); + ASSERT_TRUE(mFilterTests.configAvFilterStreamType(filterConf.streamType, filterId)); + ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterConf.config1_0.getMqDesc)); + ASSERT_TRUE(mFilterTests.startFilter(filterId)); + // tune test + ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/)); + ASSERT_TRUE(filterDataOutputTest()); + ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/)); + ASSERT_TRUE(mFilterTests.stopFilter(filterId)); + ASSERT_TRUE(mFilterTests.releaseShareAvHandle(filterId)); + ASSERT_TRUE(mFilterTests.closeFilter(filterId)); + ASSERT_TRUE(mDemuxTests.closeDemux()); + ASSERT_TRUE(mFrontendTests.closeFrontend()); +} + +void TunerRecordHidlTest::recordSingleFilterTest(FilterConfig1_1 filterConf, + FrontendConfig1_1 frontendConf, + DvrConfig dvrConf) { + uint32_t demuxId; + sp demux; + ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId)); + mDvrTests.setDemux(demux); + + DvrConfig dvrSourceConfig; + if (record.hasFrontendConnection) { + uint32_t feId; + mFrontendTests.getFrontendIdByType(frontendConf.config1_0.type, feId); + ASSERT_TRUE(feId != INVALID_ID); + ASSERT_TRUE(mFrontendTests.openFrontendById(feId)); + ASSERT_TRUE(mFrontendTests.setFrontendCallback()); + if (frontendConf.config1_0.isSoftwareFe) { + mFrontendTests.setSoftwareFrontendDvrConfig(dvrMap[record.dvrSoftwareFeId]); + } + ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId)); + mFrontendTests.setDvrTests(mDvrTests); + } else { + dvrSourceConfig = dvrMap[record.dvrSourceId]; + ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrSourceConfig.type, dvrSourceConfig.bufferSize)); + ASSERT_TRUE(mDvrTests.configDvrPlayback(dvrSourceConfig.settings)); + ASSERT_TRUE(mDvrTests.getDvrPlaybackMQDescriptor()); + } + + uint64_t filterId; + sp filter; + mFilterTests.setDemux(demux); + ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrConf.type, dvrConf.bufferSize)); + ASSERT_TRUE(mDvrTests.configDvrRecord(dvrConf.settings)); + ASSERT_TRUE(mDvrTests.getDvrRecordMQDescriptor()); + ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.config1_0.type, + filterConf.config1_0.bufferSize)); + ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId_64bit(filterId)); + ASSERT_TRUE(mFilterTests.configFilter(filterConf.config1_0.settings, filterId)); + ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterConf.config1_0.getMqDesc)); + filter = mFilterTests.getFilterById(filterId); + ASSERT_TRUE(filter != nullptr); + mDvrTests.startRecordOutputThread(dvrConf.settings.record()); + ASSERT_TRUE(mDvrTests.attachFilterToDvr(filter)); + ASSERT_TRUE(mDvrTests.startDvrRecord()); + ASSERT_TRUE(mFilterTests.startFilter(filterId)); + + if (record.hasFrontendConnection) { + ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/)); + } else { + // Start DVR Source + mDvrTests.startPlaybackInputThread(dvrSourceConfig.playbackInputFile, + dvrSourceConfig.settings.playback()); + ASSERT_TRUE(mDvrTests.startDvrPlayback()); + } + + mDvrTests.testRecordOutput(); + mDvrTests.stopRecordThread(); + + if (record.hasFrontendConnection) { + ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/)); + } else { + mDvrTests.stopPlaybackThread(); + ASSERT_TRUE(mDvrTests.stopDvrPlayback()); + } + + ASSERT_TRUE(mFilterTests.stopFilter(filterId)); + ASSERT_TRUE(mDvrTests.stopDvrRecord()); + ASSERT_TRUE(mDvrTests.detachFilterToDvr(filter)); + ASSERT_TRUE(mFilterTests.closeFilter(filterId)); + mDvrTests.closeDvrRecord(); + + if (record.hasFrontendConnection) { + ASSERT_TRUE(mFrontendTests.closeFrontend()); + } else { + mDvrTests.closeDvrPlayback(); + } + + ASSERT_TRUE(mDemuxTests.closeDemux()); +} + +TEST_P(TunerFilterHidlTest, StartFilterInDemux) { + description("Open and start a filter in Demux."); + if (!live.hasFrontendConnection) { + return; + } + // TODO use parameterized tests + configSingleFilterInDemuxTest(filterMap[live.videoFilterId], frontendMap[live.frontendId]); +} + +TEST_P(TunerFilterHidlTest, ConfigIpFilterInDemuxWithCid) { + description("Open and configure an ip filter in Demux."); + // TODO use parameterized tests + if (!live.hasFrontendConnection) { + return; + } + if (live.ipFilterId.compare(emptyHardwareId) == 0) { + return; + } + configSingleFilterInDemuxTest(filterMap[live.ipFilterId], frontendMap[live.frontendId]); +} + +TEST_P(TunerFilterHidlTest, ReconfigFilterToReceiveStartId) { + description("Recofigure and restart a filter to test start id."); + if (!live.hasFrontendConnection) { + return; + } + // TODO use parameterized tests + reconfigSingleFilterInDemuxTest(filterMap[live.videoFilterId], filterMap[live.videoFilterId], + frontendMap[live.frontendId]); +} + +TEST_P(TunerRecordHidlTest, RecordDataFlowWithTsRecordFilterTest) { + description("Feed ts data from frontend to recording and test with ts record filter"); + if (!record.support) { + return; + } + recordSingleFilterTest(filterMap[record.recordFilterId], frontendMap[record.frontendId], + dvrMap[record.dvrRecordId]); +} + +TEST_P(TunerFrontendHidlTest, TuneFrontendWithFrontendSettingsExt1_1) { + description("Tune one Frontend with v1_1 extended setting and check Lock event"); + if (!live.hasFrontendConnection) { + return; + } + mFrontendTests.tuneTest(frontendMap[live.frontendId]); +} + +TEST_P(TunerFrontendHidlTest, BlindScanFrontendWithEndFrequency) { + description("Run an blind frontend scan with v1_1 extended setting and check lock scanMessage"); + if (!scan.hasFrontendConnection) { + return; + } + mFrontendTests.scanTest(frontendMap[scan.frontendId], FrontendScanType::SCAN_BLIND); +} + +TEST_P(TunerBroadcastHidlTest, MediaFilterWithSharedMemoryHandle) { + description("Test the Media Filter with shared memory handle"); + if (!live.hasFrontendConnection) { + return; + } + mediaFilterUsingSharedMemoryTest(filterMap[live.videoFilterId], frontendMap[live.frontendId]); +} + +TEST_P(TunerFrontendHidlTest, GetFrontendDtmbCaps) { + description("Test to query Dtmb frontend caps if exists"); + mFrontendTests.getFrontendDtmbCapsTest(); +} + +TEST_P(TunerFrontendHidlTest, LinkToCiCam) { + description("Test Frontend link to CiCam"); + if (!live.hasFrontendConnection) { + return; + } + if (!frontendMap[live.frontendId].canConnectToCiCam) { + return; + } + mFrontendTests.tuneTest(frontendMap[live.frontendId]); +} + +INSTANTIATE_TEST_SUITE_P( + PerInstance, TunerBroadcastHidlTest, + testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)), + android::hardware::PrintInstanceNameToString); + +INSTANTIATE_TEST_SUITE_P( + PerInstance, TunerFrontendHidlTest, + testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)), + android::hardware::PrintInstanceNameToString); + +INSTANTIATE_TEST_SUITE_P( + PerInstance, TunerFilterHidlTest, + testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)), + android::hardware::PrintInstanceNameToString); + +INSTANTIATE_TEST_SUITE_P( + PerInstance, TunerRecordHidlTest, + testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)), + android::hardware::PrintInstanceNameToString); +} // namespace diff --git a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h new file mode 100644 index 0000000000000000000000000000000000000000..13b9640749f290ce5dfe05133660bbfbb4971861 --- /dev/null +++ b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h @@ -0,0 +1,160 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "DemuxTests.h" +#include "FrontendTests.h" + +namespace { + +bool initConfiguration() { + TunerTestingConfigReader1_0::setConfigFilePath(configFilePath); + if (!TunerTestingConfigReader1_0::checkConfigFileExists()) { + return false; + } + initFrontendConfig(); + initFilterConfig(); + initDvrConfig(); + connectHardwaresToTestCases(); + if (!validateConnections()) { + ALOGW("[vts] failed to validate connections."); + return false; + } + return true; +} + +static AssertionResult success() { + return ::testing::AssertionSuccess(); +} + +AssertionResult filterDataOutputTestBase(FilterTests tests) { + // Data Verify Module + std::map>::iterator it; + std::map> filterCallbacks = tests.getFilterCallbacks(); + for (it = filterCallbacks.begin(); it != filterCallbacks.end(); it++) { + it->second->testFilterDataOutput(); + } + return success(); +} + +class TunerFilterHidlTest : public testing::TestWithParam { + public: + virtual void SetUp() override { + mService = ITuner::getService(GetParam()); + ASSERT_NE(mService, nullptr); + initConfiguration(); + + mFrontendTests.setService(mService); + mDemuxTests.setService(mService); + mFilterTests.setService(mService); + } + + protected: + static void description(const std::string& description) { + RecordProperty("description", description); + } + + void configSingleFilterInDemuxTest(FilterConfig1_1 filterConf, FrontendConfig1_1 frontendConf); + void reconfigSingleFilterInDemuxTest(FilterConfig1_1 filterConf, FilterConfig1_1 filterReconf, + FrontendConfig1_1 frontendConf); + sp mService; + FrontendTests mFrontendTests; + DemuxTests mDemuxTests; + FilterTests mFilterTests; +}; + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerFilterHidlTest); + +class TunerRecordHidlTest : public testing::TestWithParam { + public: + virtual void SetUp() override { + mService = ITuner::getService(GetParam()); + ASSERT_NE(mService, nullptr); + initConfiguration(); + + mFrontendTests.setService(mService); + mDemuxTests.setService(mService); + mFilterTests.setService(mService); + mDvrTests.setService(mService); + } + + protected: + static void description(const std::string& description) { + RecordProperty("description", description); + } + + void recordSingleFilterTest(FilterConfig1_1 filterConf, FrontendConfig1_1 frontendConf, + DvrConfig dvrConf); + + sp mService; + FrontendTests mFrontendTests; + DemuxTests mDemuxTests; + FilterTests mFilterTests; + DvrTests mDvrTests; +}; + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerRecordHidlTest); + +class TunerFrontendHidlTest : public testing::TestWithParam { + public: + virtual void SetUp() override { + mService = ITuner::getService(GetParam()); + ASSERT_NE(mService, nullptr); + initConfiguration(); + + mFrontendTests.setService(mService); + } + + protected: + static void description(const std::string& description) { + RecordProperty("description", description); + } + + sp mService; + FrontendTests mFrontendTests; +}; + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerFrontendHidlTest); + +class TunerBroadcastHidlTest : public testing::TestWithParam { + public: + virtual void SetUp() override { + mService = ITuner::getService(GetParam()); + ASSERT_NE(mService, nullptr); + initConfiguration(); + + mFrontendTests.setService(mService); + mDemuxTests.setService(mService); + mFilterTests.setService(mService); + } + + protected: + static void description(const std::string& description) { + RecordProperty("description", description); + } + + sp mService; + FrontendTests mFrontendTests; + DemuxTests mDemuxTests; + FilterTests mFilterTests; + + AssertionResult filterDataOutputTest(); + + void mediaFilterUsingSharedMemoryTest(FilterConfig1_1 filterConf, + FrontendConfig1_1 frontendConf); +}; + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerBroadcastHidlTest); +} // namespace diff --git a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TestConfigurations.h b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TestConfigurations.h new file mode 100644 index 0000000000000000000000000000000000000000..2b5ad466b87cd2e5727f487745ad542a51486b7d --- /dev/null +++ b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TestConfigurations.h @@ -0,0 +1,196 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +#include "../../../config/TunerTestingConfigReaderV1_1.h" + +using android::hardware::tv::tuner::V1_0::DataFormat; +using android::hardware::tv::tuner::V1_0::DemuxAlpFilterType; +using android::hardware::tv::tuner::V1_0::DemuxFilterMainType; +using android::hardware::tv::tuner::V1_0::DemuxFilterSettings; +using android::hardware::tv::tuner::V1_0::DemuxFilterType; +using android::hardware::tv::tuner::V1_0::DemuxIpAddress; +using android::hardware::tv::tuner::V1_0::DemuxIpFilterSettings; +using android::hardware::tv::tuner::V1_0::DemuxIpFilterType; +using android::hardware::tv::tuner::V1_0::DemuxMmtpFilterType; +using android::hardware::tv::tuner::V1_0::DemuxRecordScIndexType; +using android::hardware::tv::tuner::V1_0::DemuxTsFilterType; +using android::hardware::tv::tuner::V1_0::DvrSettings; +using android::hardware::tv::tuner::V1_0::DvrType; +using android::hardware::tv::tuner::V1_0::FrontendDvbtBandwidth; +using android::hardware::tv::tuner::V1_0::FrontendDvbtCoderate; +using android::hardware::tv::tuner::V1_0::FrontendDvbtConstellation; +using android::hardware::tv::tuner::V1_0::FrontendDvbtGuardInterval; +using android::hardware::tv::tuner::V1_0::FrontendDvbtHierarchy; +using android::hardware::tv::tuner::V1_0::FrontendDvbtSettings; +using android::hardware::tv::tuner::V1_0::FrontendDvbtStandard; +using android::hardware::tv::tuner::V1_0::FrontendDvbtTransmissionMode; +using android::hardware::tv::tuner::V1_0::FrontendSettings; +using android::hardware::tv::tuner::V1_0::FrontendType; +using android::hardware::tv::tuner::V1_0::PlaybackSettings; +using android::hardware::tv::tuner::V1_0::RecordSettings; + +using namespace std; +using namespace android::media::tuner::testing::configuration::V1_0; + +const uint32_t FMQ_SIZE_4M = 0x400000; +const uint32_t FMQ_SIZE_16M = 0x1000000; + +const string configFilePath = "/vendor/etc/tuner_vts_config_1_1.xml"; + +// Hardware configs +static map frontendMap; +static map filterMap; +static map dvrMap; + +// Hardware and test cases connections +static LiveBroadcastHardwareConnections live; +static ScanHardwareConnections scan; +static DvrRecordHardwareConnections record; + +/** Config all the frontends that would be used in the tests */ +inline void initFrontendConfig() { + // The test will use the internal default fe when default fe is connected to any data flow + // without overriding in the xml config. + string defaultFeId = "FE_DEFAULT"; + FrontendDvbtSettings dvbtSettings{ + .frequency = 578000, + .transmissionMode = FrontendDvbtTransmissionMode::AUTO, + .bandwidth = FrontendDvbtBandwidth::BANDWIDTH_8MHZ, + .isHighPriority = true, + }; + frontendMap[defaultFeId].config1_0.type = FrontendType::DVBT; + frontendMap[defaultFeId].config1_0.settings.dvbt(dvbtSettings); + + vector types; + types.push_back(FrontendStatusTypeExt1_1::UEC); + types.push_back(FrontendStatusTypeExt1_1::IS_MISO); + vector statuses; + FrontendStatusExt1_1 status; + status.uec(4); + statuses.push_back(status); + status.isMiso(true); + statuses.push_back(status); + frontendMap[defaultFeId].tuneStatusTypes = types; + frontendMap[defaultFeId].expectTuneStatuses = statuses; + frontendMap[defaultFeId].config1_0.isSoftwareFe = true; + frontendMap[defaultFeId].canConnectToCiCam = true; + frontendMap[defaultFeId].ciCamId = 0; + frontendMap[defaultFeId].settingsExt1_1.settingExt.dvbt({ + .transmissionMode = + android::hardware::tv::tuner::V1_1::FrontendDvbtTransmissionMode::MODE_8K_E, + }); + // Read customized config + TunerTestingConfigReader1_1::readFrontendConfig1_1(frontendMap); +}; + +inline void initFilterConfig() { + // The test will use the internal default filter when default filter is connected to any + // data flow without overriding in the xml config. + string defaultAudioFilterId = "FILTER_AUDIO_DEFAULT"; + string defaultVideoFilterId = "FILTER_VIDEO_DEFAULT"; + + filterMap[defaultVideoFilterId].config1_0.type.mainType = DemuxFilterMainType::TS; + filterMap[defaultVideoFilterId].config1_0.type.subType.tsFilterType(DemuxTsFilterType::VIDEO); + filterMap[defaultVideoFilterId].config1_0.bufferSize = FMQ_SIZE_16M; + filterMap[defaultVideoFilterId].config1_0.settings.ts().tpid = 256; + filterMap[defaultVideoFilterId].config1_0.settings.ts().filterSettings.av( + {.isPassthrough = false}); + filterMap[defaultVideoFilterId].monitorEventTypes = + android::hardware::tv::tuner::V1_1::DemuxFilterMonitorEventType::SCRAMBLING_STATUS | + android::hardware::tv::tuner::V1_1::DemuxFilterMonitorEventType::IP_CID_CHANGE; + filterMap[defaultVideoFilterId].streamType.video(VideoStreamType::MPEG1); + + filterMap[defaultAudioFilterId].config1_0.type.mainType = DemuxFilterMainType::TS; + filterMap[defaultAudioFilterId].config1_0.type.subType.tsFilterType(DemuxTsFilterType::AUDIO); + filterMap[defaultAudioFilterId].config1_0.bufferSize = FMQ_SIZE_16M; + filterMap[defaultAudioFilterId].config1_0.settings.ts().tpid = 256; + filterMap[defaultAudioFilterId].config1_0.settings.ts().filterSettings.av( + {.isPassthrough = false}); + filterMap[defaultAudioFilterId].monitorEventTypes = + android::hardware::tv::tuner::V1_1::DemuxFilterMonitorEventType::SCRAMBLING_STATUS | + android::hardware::tv::tuner::V1_1::DemuxFilterMonitorEventType::IP_CID_CHANGE; + filterMap[defaultAudioFilterId].streamType.audio(AudioStreamType::MP3); + // Read customized config + TunerTestingConfigReader1_1::readFilterConfig1_1(filterMap); +}; + +/** Config all the dvrs that would be used in the tests */ +inline void initDvrConfig() { + // Read customized config + TunerTestingConfigReader1_0::readDvrConfig1_0(dvrMap); +}; + +/** Read the vendor configurations of which hardware to use for each test cases/data flows */ +inline void connectHardwaresToTestCases() { + TunerTestingConfigReader1_0::connectLiveBroadcast(live); + TunerTestingConfigReader1_0::connectScan(scan); + TunerTestingConfigReader1_0::connectDvrRecord(record); +}; + +inline bool validateConnections() { + if (record.support && !record.hasFrontendConnection && + record.dvrSourceId.compare(emptyHardwareId) == 0) { + ALOGW("[vts config] Record must support either a DVR source or a Frontend source."); + return false; + } + bool feIsValid = frontendMap.find(live.frontendId) != frontendMap.end() && + frontendMap.find(scan.frontendId) != frontendMap.end(); + feIsValid &= record.support ? frontendMap.find(record.frontendId) != frontendMap.end() : true; + + if (!feIsValid) { + ALOGW("[vts config] dynamic config fe connection is invalid."); + return false; + } + + bool dvrIsValid = frontendMap[live.frontendId].config1_0.isSoftwareFe + ? dvrMap.find(live.dvrSoftwareFeId) != dvrMap.end() + : true; + + if (record.support) { + if (record.hasFrontendConnection) { + if (frontendMap[record.frontendId].config1_0.isSoftwareFe) { + dvrIsValid &= dvrMap.find(record.dvrSoftwareFeId) != dvrMap.end(); + } + } else { + dvrIsValid &= dvrMap.find(record.dvrSourceId) != dvrMap.end(); + } + dvrIsValid &= dvrMap.find(record.dvrRecordId) != dvrMap.end(); + } + + if (!dvrIsValid) { + ALOGW("[vts config] dynamic config dvr connection is invalid."); + return false; + } + + bool filterIsValid = filterMap.find(live.audioFilterId) != filterMap.end() && + filterMap.find(live.videoFilterId) != filterMap.end(); + filterIsValid &= + record.support ? filterMap.find(record.recordFilterId) != filterMap.end() : true; + + if (!filterIsValid) { + ALOGW("[vts config] dynamic config filter connection is invalid."); + return false; + } + + return true; +} diff --git a/tv/tuner/config/TunerTestingConfigReader.h b/tv/tuner/config/TunerTestingConfigReaderV1_0.h similarity index 84% rename from tv/tuner/config/TunerTestingConfigReader.h rename to tv/tuner/config/TunerTestingConfigReaderV1_0.h index e1f5695bbbb5f0898836bfbaf27eb37219cabfd2..d049b07232adeba92aa792374850e3c73415f34c 100644 --- a/tv/tuner/config/TunerTestingConfigReader.h +++ b/tv/tuner/config/TunerTestingConfigReaderV1_0.h @@ -36,6 +36,8 @@ using android::hardware::tv::tuner::V1_0::DemuxFilterRecordSettings; using android::hardware::tv::tuner::V1_0::DemuxFilterSectionSettings; using android::hardware::tv::tuner::V1_0::DemuxFilterSettings; using android::hardware::tv::tuner::V1_0::DemuxFilterType; +using android::hardware::tv::tuner::V1_0::DemuxIpAddress; +using android::hardware::tv::tuner::V1_0::DemuxIpFilterSettings; using android::hardware::tv::tuner::V1_0::DemuxIpFilterType; using android::hardware::tv::tuner::V1_0::DemuxMmtpFilterType; using android::hardware::tv::tuner::V1_0::DemuxRecordScIndexType; @@ -64,9 +66,10 @@ using android::hardware::tv::tuner::V1_0::LnbVoltage; using android::hardware::tv::tuner::V1_0::PlaybackSettings; using android::hardware::tv::tuner::V1_0::RecordSettings; -const string configFilePath = "/vendor/etc/tuner_vts_config.xml"; const string emptyHardwareId = ""; +static string mConfigFilePath; + #define PROVISION_STR \ "{ " \ " \"id\": 21140844, " \ @@ -127,6 +130,7 @@ struct LiveBroadcastHardwareConnections { string audioFilterId; string videoFilterId; string sectionFilterId; + string ipFilterId; string pcrFilterId; /* list string of extra filters; */ }; @@ -193,14 +197,17 @@ struct TimeFilterHardwareConnections { string timeFilterId; }; -struct TunerTestingConfigReader { +struct TunerTestingConfigReader1_0 { public: + static void setConfigFilePath(string path) { mConfigFilePath = path; } + static bool checkConfigFileExists() { - auto res = read(configFilePath.c_str()); + auto res = read(mConfigFilePath.c_str()); if (res == nullopt) { - ALOGW("[ConfigReader] Couldn't read /vendor/etc/tuner_vts_config.xml." + ALOGW("[ConfigReader] Couldn't read %s." "Please check tuner_testing_dynamic_configuration.xsd" - "and sample_tuner_vts_config.xml for more details on how to config Tune VTS."); + "and sample_tuner_vts_config.xml for more details on how to config Tune VTS.", + mConfigFilePath.c_str()); } return (res != nullopt); } @@ -369,6 +376,8 @@ struct TunerTestingConfigReader { int size = privateData.size(); descramblerMap[id].hidlPvtData.resize(size); memcpy(descramblerMap[id].hidlPvtData.data(), privateData.data(), size); + } else { + descramblerMap[id].hidlPvtData.resize(256); } } } @@ -425,6 +434,11 @@ struct TunerTestingConfigReader { if (liveConfig.hasDvrSoftwareFeConnection()) { live.dvrSoftwareFeId = liveConfig.getDvrSoftwareFeConnection(); } + if (liveConfig.hasIpFilterConnection()) { + live.ipFilterId = liveConfig.getIpFilterConnection(); + } else { + live.ipFilterId = emptyHardwareId; + } } static void connectScan(ScanHardwareConnections& scan) { @@ -559,6 +573,10 @@ struct TunerTestingConfigReader { timeFilter.timeFilterId = timeFilterConfig.getTimeFilterConnection(); } + static HardwareConfiguration getHardwareConfig() { + return *getTunerConfig().getFirstHardwareConfiguration(); + } + private: static FrontendDvbtSettings readDvbtFrontendSettings(Frontend feConfig) { ALOGW("[ConfigReader] fe type is dvbt"); @@ -569,30 +587,27 @@ struct TunerTestingConfigReader { ALOGW("[ConfigReader] no more dvbt settings"); return dvbtSettings; } - dvbtSettings.transmissionMode = static_cast( - feConfig.getFirstDvbtFrontendSettings_optional()->getTransmissionMode()); - dvbtSettings.bandwidth = static_cast( - feConfig.getFirstDvbtFrontendSettings_optional()->getBandwidth()); - dvbtSettings.constellation = static_cast( - feConfig.getFirstDvbtFrontendSettings_optional()->getConstellation()); - dvbtSettings.hierarchy = static_cast( - feConfig.getFirstDvbtFrontendSettings_optional()->getHierarchy()); - dvbtSettings.hpCoderate = static_cast( - feConfig.getFirstDvbtFrontendSettings_optional()->getHpCoderate()); - dvbtSettings.lpCoderate = static_cast( - feConfig.getFirstDvbtFrontendSettings_optional()->getLpCoderate()); - dvbtSettings.guardInterval = static_cast( - feConfig.getFirstDvbtFrontendSettings_optional()->getGuardInterval()); - dvbtSettings.isHighPriority = - feConfig.getFirstDvbtFrontendSettings_optional()->getIsHighPriority(); - dvbtSettings.standard = static_cast( - feConfig.getFirstDvbtFrontendSettings_optional()->getStandard()); - dvbtSettings.isMiso = feConfig.getFirstDvbtFrontendSettings_optional()->getIsMiso(); - dvbtSettings.plpMode = static_cast( - feConfig.getFirstDvbtFrontendSettings_optional()->getPlpMode()); - dvbtSettings.plpId = feConfig.getFirstDvbtFrontendSettings_optional()->getPlpId(); - dvbtSettings.plpGroupId = feConfig.getFirstDvbtFrontendSettings_optional()->getPlpGroupId(); - + auto dvbt = feConfig.getFirstDvbtFrontendSettings_optional(); + uint32_t trans = static_cast(dvbt->getTransmissionMode()); + if (trans <= (uint32_t)FrontendDvbtTransmissionMode::MODE_32K) { + dvbtSettings.transmissionMode = static_cast(trans); + } + dvbtSettings.bandwidth = static_cast(dvbt->getBandwidth()); + dvbtSettings.isHighPriority = dvbt->getIsHighPriority(); + dvbtSettings.hierarchy = static_cast(dvbt->getHierarchy()); + dvbtSettings.hpCoderate = static_cast(dvbt->getHpCoderate()); + dvbtSettings.lpCoderate = static_cast(dvbt->getLpCoderate()); + dvbtSettings.guardInterval = + static_cast(dvbt->getGuardInterval()); + dvbtSettings.standard = static_cast(dvbt->getStandard()); + dvbtSettings.isMiso = dvbt->getIsMiso(); + dvbtSettings.plpMode = static_cast(dvbt->getPlpMode()); + dvbtSettings.plpId = dvbt->getPlpId(); + dvbtSettings.plpGroupId = dvbt->getPlpGroupId(); + if (dvbt->hasConstellation()) { + dvbtSettings.constellation = + static_cast(dvbt->getConstellation()); + } return dvbtSettings; } @@ -616,13 +631,13 @@ struct TunerTestingConfigReader { DemuxFilterSettings& settings) { auto mainType = filterConfig.getMainType(); auto subType = filterConfig.getSubType(); - uint32_t pid = static_cast(filterConfig.getPid()); switch (mainType) { case FilterMainTypeEnum::TS: { ALOGW("[ConfigReader] filter main type is ts"); type.mainType = DemuxFilterMainType::TS; switch (subType) { case FilterSubTypeEnum::UNDEFINED: + type.subType.tsFilterType(DemuxTsFilterType::UNDEFINED); break; case FilterSubTypeEnum::SECTION: type.subType.tsFilterType(DemuxTsFilterType::SECTION); @@ -663,7 +678,9 @@ struct TunerTestingConfigReader { ALOGW("[ConfigReader] ts subtype is not supported"); return false; } - settings.ts().tpid = pid; + if (filterConfig.hasPid()) { + settings.ts().tpid = static_cast(filterConfig.getPid()); + } break; } case FilterMainTypeEnum::MMTP: { @@ -671,6 +688,7 @@ struct TunerTestingConfigReader { type.mainType = DemuxFilterMainType::MMTP; switch (subType) { case FilterSubTypeEnum::UNDEFINED: + type.subType.mmtpFilterType(DemuxMmtpFilterType::UNDEFINED); break; case FilterSubTypeEnum::SECTION: type.subType.mmtpFilterType(DemuxMmtpFilterType::SECTION); @@ -709,7 +727,47 @@ struct TunerTestingConfigReader { ALOGW("[ConfigReader] mmtp subtype is not supported"); return false; } - settings.mmtp().mmtpPid = pid; + if (filterConfig.hasPid()) { + settings.mmtp().mmtpPid = static_cast(filterConfig.getPid()); + } + break; + } + case FilterMainTypeEnum::IP: { + ALOGW("[ConfigReader] filter main type is ip"); + type.mainType = DemuxFilterMainType::IP; + switch (subType) { + case FilterSubTypeEnum::UNDEFINED: + type.subType.ipFilterType(DemuxIpFilterType::UNDEFINED); + break; + case FilterSubTypeEnum::SECTION: + type.subType.ipFilterType(DemuxIpFilterType::SECTION); + settings.ip().filterSettings.section( + readSectionFilterSettings(filterConfig)); + break; + case FilterSubTypeEnum::NTP: + type.subType.ipFilterType(DemuxIpFilterType::NTP); + settings.ip().filterSettings.noinit(); + break; + case FilterSubTypeEnum::IP: { + DemuxIpFilterSettings ip{ + .ipAddr = readIpAddress(filterConfig), + }; + ip.filterSettings.bPassthrough(readPassthroughSettings(filterConfig)); + settings.ip(ip); + break; + } + case FilterSubTypeEnum::IP_PAYLOAD: + type.subType.ipFilterType(DemuxIpFilterType::IP_PAYLOAD); + settings.ip().filterSettings.noinit(); + break; + case FilterSubTypeEnum::PAYLOAD_THROUGH: + type.subType.ipFilterType(DemuxIpFilterType::PAYLOAD_THROUGH); + settings.ip().filterSettings.noinit(); + break; + default: + ALOGW("[ConfigReader] mmtp subtype is not supported"); + return false; + } break; } default: @@ -720,6 +778,46 @@ struct TunerTestingConfigReader { return true; } + static DemuxIpAddress readIpAddress(Filter filterConfig) { + DemuxIpAddress ipAddress; + if (!filterConfig.hasIpFilterConfig_optional()) { + return ipAddress; + } + auto ipFilterConfig = filterConfig.getFirstIpFilterConfig_optional(); + if (ipFilterConfig->hasSrcPort()) { + ipAddress.srcPort = ipFilterConfig->getSrcPort(); + } + if (ipFilterConfig->hasDestPort()) { + ipAddress.dstPort = ipFilterConfig->getDestPort(); + } + if (ipFilterConfig->getFirstSrcIpAddress()->getIsIpV4()) { + memcpy(ipAddress.srcIpAddress.v4().data(), + ipFilterConfig->getFirstSrcIpAddress()->getIp().data(), 4); + } else { + memcpy(ipAddress.srcIpAddress.v6().data(), + ipFilterConfig->getFirstSrcIpAddress()->getIp().data(), 6); + } + if (ipFilterConfig->getFirstDestIpAddress()->getIsIpV4()) { + memcpy(ipAddress.dstIpAddress.v4().data(), + ipFilterConfig->getFirstDestIpAddress()->getIp().data(), 4); + } else { + memcpy(ipAddress.dstIpAddress.v6().data(), + ipFilterConfig->getFirstDestIpAddress()->getIp().data(), 6); + } + return ipAddress; + } + + static bool readPassthroughSettings(Filter filterConfig) { + if (!filterConfig.hasIpFilterConfig_optional()) { + return false; + } + auto ipFilterConfig = filterConfig.getFirstIpFilterConfig_optional(); + if (ipFilterConfig->hasDataPassthrough()) { + return ipFilterConfig->getDataPassthrough(); + } + return false; + } + static DemuxFilterSectionSettings readSectionFilterSettings(Filter filterConfig) { DemuxFilterSectionSettings settings; if (!filterConfig.hasSectionFilterSettings_optional()) { @@ -777,11 +875,7 @@ struct TunerTestingConfigReader { return recordSettings; } - static TunerConfiguration getTunerConfig() { return *read(configFilePath.c_str()); } - - static HardwareConfiguration getHardwareConfig() { - return *getTunerConfig().getFirstHardwareConfiguration(); - } + static TunerConfiguration getTunerConfig() { return *read(mConfigFilePath.c_str()); } static DataFlowConfiguration getDataFlowConfiguration() { return *getTunerConfig().getFirstDataFlowConfiguration(); diff --git a/tv/tuner/config/TunerTestingConfigReaderV1_1.h b/tv/tuner/config/TunerTestingConfigReaderV1_1.h new file mode 100644 index 0000000000000000000000000000000000000000..13d5303230aa56cde085a835819355628bf3bdb1 --- /dev/null +++ b/tv/tuner/config/TunerTestingConfigReaderV1_1.h @@ -0,0 +1,185 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "TunerTestingConfigReaderV1_0.h" + +using android::hardware::tv::tuner::V1_1::AudioStreamType; +using android::hardware::tv::tuner::V1_1::AvStreamType; +using android::hardware::tv::tuner::V1_1::FrontendDvbsScanType; +using android::hardware::tv::tuner::V1_1::FrontendDvbsSettingsExt1_1; +using android::hardware::tv::tuner::V1_1::FrontendDvbtSettingsExt1_1; +using android::hardware::tv::tuner::V1_1::FrontendSettingsExt1_1; +using android::hardware::tv::tuner::V1_1::FrontendStatusExt1_1; +using android::hardware::tv::tuner::V1_1::FrontendStatusTypeExt1_1; +using android::hardware::tv::tuner::V1_1::VideoStreamType; + +struct FrontendConfig1_1 { + FrontendConfig config1_0; + bool canConnectToCiCam; + uint32_t ciCamId; + FrontendSettingsExt1_1 settingsExt1_1; + vector tuneStatusTypes; + vector expectTuneStatuses; +}; + +struct FilterConfig1_1 { + FilterConfig config1_0; + AvStreamType streamType; + uint32_t ipCid; + uint32_t monitorEventTypes; + + bool operator<(const FilterConfig& /*c*/) const { return false; } +}; + +struct TunerTestingConfigReader1_1 { + public: + static void readFrontendConfig1_1(map& frontendMap) { + map frontendMap1_0; + TunerTestingConfigReader1_0::readFrontendConfig1_0(frontendMap1_0); + for (auto it = frontendMap1_0.begin(); it != frontendMap1_0.end(); it++) { + frontendMap[it->first].config1_0 = it->second; + } + + auto hardwareConfig = TunerTestingConfigReader1_0::getHardwareConfig(); + if (hardwareConfig.hasFrontends()) { + // TODO: b/182519645 complete the tune status config + vector types; + types.push_back(FrontendStatusTypeExt1_1::UEC); + types.push_back(FrontendStatusTypeExt1_1::IS_MISO); + vector statuses; + FrontendStatusExt1_1 status; + status.uec(4); + statuses.push_back(status); + status.isMiso(true); + statuses.push_back(status); + + auto frontends = *hardwareConfig.getFirstFrontends(); + + for (auto feConfig : frontends.getFrontend()) { + string id = feConfig.getId(); + switch (feConfig.getType()) { + case FrontendTypeEnum::DVBS: + frontendMap[id].settingsExt1_1.settingExt.dvbs( + readDvbsFrontendSettings1_1(feConfig)); + break; + case FrontendTypeEnum::DVBT: { + frontendMap[id].settingsExt1_1.settingExt.dvbt( + readDvbtFrontendSettings1_1(feConfig)); + break; + } + case FrontendTypeEnum::DTMB: + frontendMap[id].config1_0.type = static_cast( + android::hardware::tv::tuner::V1_1::FrontendType::DTMB); + break; + case FrontendTypeEnum::UNKNOWN: + ALOGW("[ConfigReader] invalid frontend type"); + return; + default: + ALOGW("[ConfigReader] fe already handled in 1_0 reader."); + break; + } + if (feConfig.hasEndFrequency()) { + frontendMap[id].settingsExt1_1.endFrequency = + (uint32_t)feConfig.getEndFrequency(); + } + // TODO: b/182519645 complete the tune status config + frontendMap[id].tuneStatusTypes = types; + frontendMap[id].expectTuneStatuses = statuses; + getCiCamInfo(feConfig, frontendMap[id].canConnectToCiCam, frontendMap[id].ciCamId); + } + } + } + + static void readFilterConfig1_1(map& filterMap) { + map filterMap1_0; + TunerTestingConfigReader1_0::readFilterConfig1_0(filterMap1_0); + for (auto it = filterMap1_0.begin(); it != filterMap1_0.end(); it++) { + filterMap[it->first].config1_0 = it->second; + } + auto hardwareConfig = TunerTestingConfigReader1_0::getHardwareConfig(); + if (hardwareConfig.hasFilters()) { + auto filters = *hardwareConfig.getFirstFilters(); + for (auto filterConfig : filters.getFilter()) { + string id = filterConfig.getId(); + if (filterConfig.hasMonitorEventTypes()) { + filterMap[id].monitorEventTypes = (uint32_t)filterConfig.getMonitorEventTypes(); + } + if (filterConfig.hasAvFilterSettings_optional()) { + AvStreamType type; + auto av = filterConfig.getFirstAvFilterSettings_optional(); + if (av->hasAudioStreamType_optional()) { + type.audio(static_cast(av->getAudioStreamType_optional())); + filterMap[id].streamType = type; + } + if (av->hasVideoStreamType_optional()) { + type.video(static_cast(av->getVideoStreamType_optional())); + filterMap[id].streamType = type; + } + } + if (filterConfig.hasIpFilterConfig_optional()) { + auto ip = filterConfig.getFirstIpFilterConfig_optional(); + if (ip->hasIpCid()) { + filterMap[id].ipCid = ip->getIpCid(); + } + } + } + } + } + + private: + static void getCiCamInfo(Frontend feConfig, bool& canConnectToCiCam, uint32_t& ciCamId) { + if (!feConfig.hasConnectToCicamId()) { + canConnectToCiCam = false; + ciCamId = -1; + } + canConnectToCiCam = true; + ciCamId = static_cast(feConfig.getConnectToCicamId()); + } + + static FrontendDvbsSettingsExt1_1 readDvbsFrontendSettings1_1(Frontend feConfig) { + FrontendDvbsSettingsExt1_1 dvbsSettings; + if (!feConfig.hasDvbsFrontendSettings_optional()) { + return dvbsSettings; + } + auto dvbs = feConfig.getFirstDvbsFrontendSettings_optional(); + if (dvbs->hasScanType()) { + dvbsSettings.scanType = static_cast(dvbs->getScanType()); + } + if (dvbs->hasIsDiseqcRxMessage()) { + dvbsSettings.isDiseqcRxMessage = dvbs->getIsDiseqcRxMessage(); + } + return dvbsSettings; + } + + static FrontendDvbtSettingsExt1_1 readDvbtFrontendSettings1_1(Frontend feConfig) { + FrontendDvbtSettingsExt1_1 dvbtSettings; + if (!feConfig.hasDvbtFrontendSettings_optional()) { + return dvbtSettings; + } + auto dvbt = feConfig.getFirstDvbtFrontendSettings_optional(); + auto trans = dvbt->getTransmissionMode(); + dvbtSettings.transmissionMode = + static_cast( + trans); + if (dvbt->hasConstellation()) { + dvbtSettings.constellation = + static_cast( + dvbt->getConstellation()); + } + return dvbtSettings; + } +}; \ No newline at end of file diff --git a/tv/tuner/config/api/current.txt b/tv/tuner/config/api/current.txt index 3476414b1684a0a1253c1f08be8e1109ec099072..d026bf9e4011d67aaa00ceb985fa1a787c7cc5f2 100644 --- a/tv/tuner/config/api/current.txt +++ b/tv/tuner/config/api/current.txt @@ -3,8 +3,12 @@ package android.media.tuner.testing.configuration.V1_0 { public class AvFilterSettings { ctor public AvFilterSettings(); + method @Nullable public short getAudioStreamType_optional(); method @Nullable public boolean getIsPassthrough(); + method @Nullable public short getVideoStreamType_optional(); + method public void setAudioStreamType_optional(@Nullable short); method public void setIsPassthrough(@Nullable boolean); + method public void setVideoStreamType_optional(@Nullable short); } public class DataFlowConfiguration { @@ -32,12 +36,14 @@ package android.media.tuner.testing.configuration.V1_0 { method @Nullable public String getAudioFilterConnection(); method @Nullable public String getDvrSoftwareFeConnection(); method @Nullable public String getFrontendConnection(); + method @Nullable public String getIpFilterConnection(); method @Nullable public String getPcrFilterConnection(); method @Nullable public String getSectionFilterConnection(); method @Nullable public String getVideoFilterConnection(); method public void setAudioFilterConnection(@Nullable String); method public void setDvrSoftwareFeConnection(@Nullable String); method public void setFrontendConnection(@Nullable String); + method public void setIpFilterConnection(@Nullable String); method public void setPcrFilterConnection(@Nullable String); method public void setSectionFilterConnection(@Nullable String); method public void setVideoFilterConnection(@Nullable String); @@ -152,11 +158,24 @@ package android.media.tuner.testing.configuration.V1_0 { public class DvbsFrontendSettings { ctor public DvbsFrontendSettings(); method @Nullable public java.math.BigInteger getInputStreamId(); + method @Nullable public boolean getIsDiseqcRxMessage(); + method @Nullable public android.media.tuner.testing.configuration.V1_0.DvbsScanType getScanType(); method @Nullable public java.math.BigInteger getSymbolRate(); method public void setInputStreamId(@Nullable java.math.BigInteger); + method public void setIsDiseqcRxMessage(@Nullable boolean); + method public void setScanType(@Nullable android.media.tuner.testing.configuration.V1_0.DvbsScanType); method public void setSymbolRate(@Nullable java.math.BigInteger); } + public enum DvbsScanType { + method @NonNull public String getRawName(); + enum_constant public static final android.media.tuner.testing.configuration.V1_0.DvbsScanType DIRECT; + enum_constant public static final android.media.tuner.testing.configuration.V1_0.DvbsScanType DISEQC; + enum_constant public static final android.media.tuner.testing.configuration.V1_0.DvbsScanType JESS; + enum_constant public static final android.media.tuner.testing.configuration.V1_0.DvbsScanType UNDEFINED; + enum_constant public static final android.media.tuner.testing.configuration.V1_0.DvbsScanType UNICABLE; + } + public class DvbtFrontendSettings { ctor public DvbtFrontendSettings(); method @Nullable public java.math.BigInteger getBandwidth(); @@ -236,7 +255,9 @@ package android.media.tuner.testing.configuration.V1_0 { method @Nullable public android.media.tuner.testing.configuration.V1_0.AvFilterSettings getAvFilterSettings_optional(); method @Nullable public java.math.BigInteger getBufferSize(); method @Nullable public String getId(); + method @Nullable public android.media.tuner.testing.configuration.V1_0.IpFilterConfig getIpFilterConfig_optional(); method @Nullable public android.media.tuner.testing.configuration.V1_0.FilterMainTypeEnum getMainType(); + method @Nullable public java.math.BigInteger getMonitorEventTypes(); method @Nullable public java.math.BigInteger getPid(); method @Nullable public android.media.tuner.testing.configuration.V1_0.RecordFilterSettings getRecordFilterSettings_optional(); method @Nullable public android.media.tuner.testing.configuration.V1_0.SectionFilterSettings getSectionFilterSettings_optional(); @@ -245,7 +266,9 @@ package android.media.tuner.testing.configuration.V1_0 { method public void setAvFilterSettings_optional(@Nullable android.media.tuner.testing.configuration.V1_0.AvFilterSettings); method public void setBufferSize(@Nullable java.math.BigInteger); method public void setId(@Nullable String); + method public void setIpFilterConfig_optional(@Nullable android.media.tuner.testing.configuration.V1_0.IpFilterConfig); method public void setMainType(@Nullable android.media.tuner.testing.configuration.V1_0.FilterMainTypeEnum); + method public void setMonitorEventTypes(@Nullable java.math.BigInteger); method public void setPid(@Nullable java.math.BigInteger); method public void setRecordFilterSettings_optional(@Nullable android.media.tuner.testing.configuration.V1_0.RecordFilterSettings); method public void setSectionFilterSettings_optional(@Nullable android.media.tuner.testing.configuration.V1_0.SectionFilterSettings); @@ -255,6 +278,7 @@ package android.media.tuner.testing.configuration.V1_0 { public enum FilterMainTypeEnum { method @NonNull public String getRawName(); + enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterMainTypeEnum IP; enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterMainTypeEnum MMTP; enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterMainTypeEnum TS; } @@ -263,7 +287,11 @@ package android.media.tuner.testing.configuration.V1_0 { method @NonNull public String getRawName(); enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum AUDIO; enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum DOWNLOAD; + enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum IP; + enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum IP_PAYLOAD; enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum MMTP; + enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum NTP; + enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum PAYLOAD_THROUGH; enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum PCR; enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum PES; enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum RECORD; @@ -362,6 +390,30 @@ package android.media.tuner.testing.configuration.V1_0 { method @Nullable public java.util.List getTimeFilter(); } + public class IpAddress { + ctor public IpAddress(); + method @Nullable public java.util.List getIp(); + method @Nullable public boolean getIsIpV4(); + method public void setIp(@Nullable java.util.List); + method public void setIsIpV4(@Nullable boolean); + } + + public class IpFilterConfig { + ctor public IpFilterConfig(); + method @Nullable public boolean getDataPassthrough(); + method @Nullable public android.media.tuner.testing.configuration.V1_0.IpAddress getDestIpAddress(); + method @Nullable public long getDestPort(); + method @Nullable public java.math.BigInteger getIpCid(); + method @Nullable public android.media.tuner.testing.configuration.V1_0.IpAddress getSrcIpAddress(); + method @Nullable public long getSrcPort(); + method public void setDataPassthrough(@Nullable boolean); + method public void setDestIpAddress(@Nullable android.media.tuner.testing.configuration.V1_0.IpAddress); + method public void setDestPort(@Nullable long); + method public void setIpCid(@Nullable java.math.BigInteger); + method public void setSrcIpAddress(@Nullable android.media.tuner.testing.configuration.V1_0.IpAddress); + method public void setSrcPort(@Nullable long); + } + public class Lnb { ctor public Lnb(); method @Nullable public String getId(); diff --git a/tv/tuner/config/sample_tuner_vts_config.xml b/tv/tuner/config/sample_tuner_vts_config_1_0.xml similarity index 100% rename from tv/tuner/config/sample_tuner_vts_config.xml rename to tv/tuner/config/sample_tuner_vts_config_1_0.xml diff --git a/tv/tuner/config/sample_tuner_vts_config_1_1.xml b/tv/tuner/config/sample_tuner_vts_config_1_1.xml new file mode 100644 index 0000000000000000000000000000000000000000..8c99207a693a5d309afacfd51a96e22b07041182 --- /dev/null +++ b/tv/tuner/config/sample_tuner_vts_config_1_1.xml @@ -0,0 +1,159 @@ + + + + + + + + + + + + + + + + + + + + 2 + + + + + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tv/tuner/config/tuner_testing_dynamic_configuration.xsd b/tv/tuner/config/tuner_testing_dynamic_configuration.xsd index 7f31a11535e87696871f1c66f2da1faf68077717..6a04b7ebe10ff60e44c3559902e6e4fbbf0b454d 100644 --- a/tv/tuner/config/tuner_testing_dynamic_configuration.xsd +++ b/tv/tuner/config/tuner_testing_dynamic_configuration.xsd @@ -49,6 +49,15 @@ + + + + + + + + + @@ -68,6 +77,8 @@ + + @@ -147,13 +158,19 @@ + + + + + + - @@ -171,10 +188,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -207,20 +251,28 @@ config only to the hal. - - - - - - - + + + + + + + + + + + + + + + @@ -406,7 +458,7 @@ - + @@ -553,6 +605,7 @@ + diff --git a/usb/1.2/vts/functional/VtsHalUsbV1_2TargetTest.cpp b/usb/1.2/vts/functional/VtsHalUsbV1_2TargetTest.cpp index 5f901cd4f61e6c882e94a50b0ee90c53ef8bcf14..0123d58d84c7394bb7b6b19c9b6760ab9b0097b1 100644 --- a/usb/1.2/vts/functional/VtsHalUsbV1_2TargetTest.cpp +++ b/usb/1.2/vts/functional/VtsHalUsbV1_2TargetTest.cpp @@ -360,6 +360,7 @@ TEST_P(UsbHidlTest, contaminantPresenceProtectionStability) { if (!supported) EXPECT_GE(successCount, 9); } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UsbHidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, UsbHidlTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames(IUsb::descriptor)), diff --git a/usb/1.3/Android.bp b/usb/1.3/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..c48da3793455a55d0fab1f596f391ec64dc792b5 --- /dev/null +++ b/usb/1.3/Android.bp @@ -0,0 +1,25 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +hidl_interface { + name: "android.hardware.usb@1.3", + root: "android.hardware", + srcs: [ + "IUsb.hal", + ], + interfaces: [ + "android.hardware.usb@1.0", + "android.hardware.usb@1.1", + "android.hardware.usb@1.2", + "android.hidl.base@1.0", + ], + gen_java: true, +} diff --git a/usb/1.3/IUsb.hal b/usb/1.3/IUsb.hal new file mode 100644 index 0000000000000000000000000000000000000000..3d1d380578cd4ba113ad98a55970c261c9c1c618 --- /dev/null +++ b/usb/1.3/IUsb.hal @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.usb@1.3; + +import android.hardware.usb@1.2::IUsb; + +interface IUsb extends @1.2::IUsb { + /** + * This function is used to enable/disable USB controller when some + * scenarios need. This function can stop and restore USB data signaling. + * + * @param enable true Enable USB data signaling. + * false Disable USB data signaling. + * @return true enable or disable USB data successfully + * false if something wrong + */ + enableUsbDataSignal(bool enable) generates(bool result); +}; diff --git a/usb/1.3/vts/OWNERS b/usb/1.3/vts/OWNERS new file mode 100644 index 0000000000000000000000000000000000000000..a6a1e5416a97d682dd071c36841a20ff06ba67bd --- /dev/null +++ b/usb/1.3/vts/OWNERS @@ -0,0 +1,2 @@ +albertccwang@google.com +badhri@google.com diff --git a/usb/1.3/vts/functional/Android.bp b/usb/1.3/vts/functional/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..6a1ce1e1ce4162eb5dfa8f19f8be03282b6cdf70 --- /dev/null +++ b/usb/1.3/vts/functional/Android.bp @@ -0,0 +1,40 @@ +// +// Copyright (C) 2021 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_test { + name: "VtsHalUsbV1_3TargetTest", + defaults: ["VtsHalTargetTestDefaults"], + srcs: ["VtsHalUsbV1_3TargetTest.cpp"], + static_libs: [ + "android.hardware.usb@1.0", + "android.hardware.usb@1.1", + "android.hardware.usb@1.2", + "android.hardware.usb@1.3", + ], + test_suites: [ + "general-tests", + "vts", + ], +} diff --git a/usb/1.3/vts/functional/VtsHalUsbV1_3TargetTest.cpp b/usb/1.3/vts/functional/VtsHalUsbV1_3TargetTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ed35d4223ecfa15df86590a74ecdbd33dc8a2a95 --- /dev/null +++ b/usb/1.3/vts/functional/VtsHalUsbV1_3TargetTest.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "VtsHalUsbV1_3TargetTest" +#include + +#include + +#include +#include +#include + +#include +#include +#include + +using ::android::sp; +using ::android::hardware::hidl_array; +using ::android::hardware::hidl_memory; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::usb::V1_0::Status; +using ::android::hardware::usb::V1_3::IUsb; +using ::android::hidl::base::V1_0::IBase; + +// The main test class for the USB hidl HAL +class UsbHidlTest : public ::testing::TestWithParam { + public: + virtual void SetUp() override { + ALOGI(__FUNCTION__); + usb = IUsb::getService(GetParam()); + ASSERT_NE(usb, nullptr); + } + + virtual void TearDown() override { ALOGI("Teardown"); } + + // USB hidl hal Proxy + sp usb; +}; + +/* + * Check to see if enable usb data signal succeeds. + * HAL service should call enableUsbDataSignal. + */ +TEST_P(UsbHidlTest, enableUsbDataSignal) { + Return ret = usb->enableUsbDataSignal(true); + ASSERT_TRUE(ret.isOk()); +} + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UsbHidlTest); +INSTANTIATE_TEST_SUITE_P( + PerInstance, UsbHidlTest, + testing::ValuesIn(android::hardware::getAllHalInstanceNames(IUsb::descriptor)), + android::hardware::PrintInstanceNameToString); diff --git a/usb/gadget/1.2/Android.bp b/usb/gadget/1.2/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..dc3589708dcd7dd1b31b83c196996b4566a88bd5 --- /dev/null +++ b/usb/gadget/1.2/Android.bp @@ -0,0 +1,26 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +hidl_interface { + name: "android.hardware.usb.gadget@1.2", + root: "android.hardware", + srcs: [ + "types.hal", + "IUsbGadget.hal", + "IUsbGadgetCallback.hal", + ], + interfaces: [ + "android.hardware.usb.gadget@1.0", + "android.hardware.usb.gadget@1.1", + "android.hidl.base@1.0", + ], + gen_java: true, +} diff --git a/usb/gadget/1.2/IUsbGadget.hal b/usb/gadget/1.2/IUsbGadget.hal new file mode 100644 index 0000000000000000000000000000000000000000..5c6e930b39a4ce03e271a9c11c7f6e6817ec41e5 --- /dev/null +++ b/usb/gadget/1.2/IUsbGadget.hal @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.usb.gadget@1.2; + +import IUsbGadgetCallback; +import android.hardware.usb.gadget@1.1::IUsbGadget; + +interface IUsbGadget extends @1.1::IUsbGadget { + /** + * The function is used to query current USB speed. + * + * @param callback IUsbGadgetCallback::getUsbSpeedCb used to propagate + * current USB speed. + */ + oneway getUsbSpeed(IUsbGadgetCallback callback); +}; diff --git a/usb/gadget/1.2/IUsbGadgetCallback.hal b/usb/gadget/1.2/IUsbGadgetCallback.hal new file mode 100644 index 0000000000000000000000000000000000000000..41705736fb27cb05df12ba0e33626d0c3339b019 --- /dev/null +++ b/usb/gadget/1.2/IUsbGadgetCallback.hal @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.usb.gadget@1.2; + +import UsbSpeed; +import android.hardware.usb.gadget@1.0::IUsbGadgetCallback; + +interface IUsbGadgetCallback extends @1.0::IUsbGadgetCallback { + /** + * Used to convey the current USB speed to the caller. + * Must be called either when USB state changes due to USB enumeration or + * when caller requested for USB speed through getUsbSpeed. + * + * @param speed USB Speed defined by UsbSpeed showed current USB + * connection speed. + */ + oneway getUsbSpeedCb(UsbSpeed speed); +}; + diff --git a/usb/gadget/1.2/default/Android.bp b/usb/gadget/1.2/default/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..713ce83046e2c6aa6ef6794efb57480bfc4898ff --- /dev/null +++ b/usb/gadget/1.2/default/Android.bp @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_binary { + name: "android.hardware.usb.gadget@1.2-service", + defaults: ["hidl_defaults"], + relative_install_path: "hw", + init_rc: ["android.hardware.usb.gadget@1.2-service.rc"], + vintf_fragments: ["android.hardware.usb.gadget@1.2-service.xml"], + vendor: true, + srcs: [ + "service.cpp", + "UsbGadget.cpp", + ], + shared_libs: [ + "android.hardware.usb.gadget@1.0", + "android.hardware.usb.gadget@1.1", + "android.hardware.usb.gadget@1.2", + "libbase", + "libcutils", + "libhardware", + "libhidlbase", + "liblog", + "libutils", + ], + static_libs: ["libusbconfigfs-2"], +} diff --git a/usb/gadget/1.2/default/UsbGadget.cpp b/usb/gadget/1.2/default/UsbGadget.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8dd229e0fdb8708150ab0930601c859c6a756379 --- /dev/null +++ b/usb/gadget/1.2/default/UsbGadget.cpp @@ -0,0 +1,286 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "android.hardware.usb.gadget@1.2-service" + +#include "UsbGadget.h" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace usb { +namespace gadget { +namespace V1_2 { +namespace implementation { + +UsbGadget::UsbGadget() { + if (access(OS_DESC_PATH, R_OK) != 0) { + ALOGE("configfs setup not done yet"); + abort(); + } +} + +void currentFunctionsAppliedCallback(bool functionsApplied, void* payload) { + UsbGadget* gadget = (UsbGadget*)payload; + gadget->mCurrentUsbFunctionsApplied = functionsApplied; +} + +Return UsbGadget::getCurrentUsbFunctions(const sp& callback) { + Return ret = callback->getCurrentUsbFunctionsCb( + mCurrentUsbFunctions, mCurrentUsbFunctionsApplied ? Status::FUNCTIONS_APPLIED + : Status::FUNCTIONS_NOT_APPLIED); + if (!ret.isOk()) ALOGE("Call to getCurrentUsbFunctionsCb failed %s", ret.description().c_str()); + + return Void(); +} + +Return UsbGadget::getUsbSpeed(const sp& callback) { + std::string current_speed; + if (ReadFileToString(SPEED_PATH, ¤t_speed)) { + current_speed = Trim(current_speed); + ALOGI("current USB speed is %s", current_speed.c_str()); + if (current_speed == "low-speed") + mUsbSpeed = UsbSpeed::LOWSPEED; + else if (current_speed == "full-speed") + mUsbSpeed = UsbSpeed::FULLSPEED; + else if (current_speed == "high-speed") + mUsbSpeed = UsbSpeed::HIGHSPEED; + else if (current_speed == "super-speed") + mUsbSpeed = UsbSpeed::SUPERSPEED; + else if (current_speed == "super-speed-plus") + mUsbSpeed = UsbSpeed::SUPERSPEED_10Gb; + else if (current_speed == "UNKNOWN") + mUsbSpeed = UsbSpeed::UNKNOWN; + else { + /** + * This part is used for USB4 or reserved speed. + * + * If reserved speed is detected, it needs to convert to other speeds. + * For example: + * If the bandwidth of new speed is 7G, adding new if + * statement and set mUsbSpeed to SUPERSPEED. + * If the bandwidth of new speed is 80G, adding new if + * statement and set mUsbSpeed to USB4_GEN3_40Gb. + */ + mUsbSpeed = UsbSpeed::RESERVED_SPEED; + } + } else { + ALOGE("Fail to read current speed"); + mUsbSpeed = UsbSpeed::UNKNOWN; + } + + if (callback) { + Return ret = callback->getUsbSpeedCb(mUsbSpeed); + + if (!ret.isOk()) ALOGE("Call to getUsbSpeedCb failed %s", ret.description().c_str()); + } + + return Void(); +} + +V1_0::Status UsbGadget::tearDownGadget() { + if (resetGadget() != V1_0::Status::SUCCESS) return V1_0::Status::ERROR; + + if (monitorFfs.isMonitorRunning()) { + monitorFfs.reset(); + } else { + ALOGI("mMonitor not running"); + } + return V1_0::Status::SUCCESS; +} + +Return UsbGadget::reset() { + if (!WriteStringToFile("none", PULLUP_PATH)) { + ALOGI("Gadget cannot be pulled down"); + return Status::ERROR; + } + + usleep(kDisconnectWaitUs); + + if (!WriteStringToFile(kGadgetName, PULLUP_PATH)) { + ALOGI("Gadget cannot be pulled up"); + return Status::ERROR; + } + + return Status::SUCCESS; +} + +static V1_0::Status validateAndSetVidPid(uint64_t functions) { + V1_0::Status ret = V1_0::Status::SUCCESS; + + switch (functions) { + case static_cast(V1_2::GadgetFunction::MTP): + ret = setVidPid("0x18d1", "0x4ee1"); + break; + case V1_2::GadgetFunction::ADB | V1_2::GadgetFunction::MTP: + ret = setVidPid("0x18d1", "0x4ee2"); + break; + case static_cast(V1_2::GadgetFunction::RNDIS): + ret = setVidPid("0x18d1", "0x4ee3"); + break; + case V1_2::GadgetFunction::ADB | V1_2::GadgetFunction::RNDIS: + ret = setVidPid("0x18d1", "0x4ee4"); + break; + case static_cast(V1_2::GadgetFunction::PTP): + ret = setVidPid("0x18d1", "0x4ee5"); + break; + case V1_2::GadgetFunction::ADB | V1_2::GadgetFunction::PTP: + ret = setVidPid("0x18d1", "0x4ee6"); + break; + case static_cast(V1_2::GadgetFunction::ADB): + ret = setVidPid("0x18d1", "0x4ee7"); + break; + case static_cast(V1_2::GadgetFunction::MIDI): + ret = setVidPid("0x18d1", "0x4ee8"); + break; + case V1_2::GadgetFunction::ADB | V1_2::GadgetFunction::MIDI: + ret = setVidPid("0x18d1", "0x4ee9"); + break; + case static_cast(V1_2::GadgetFunction::NCM): + ret = setVidPid("0x18d1", "0x4eeb"); + break; + case V1_2::GadgetFunction::ADB | V1_2::GadgetFunction::NCM: + ret = setVidPid("0x18d1", "0x4eec"); + break; + case static_cast(V1_2::GadgetFunction::ACCESSORY): + ret = setVidPid("0x18d1", "0x2d00"); + break; + case V1_2::GadgetFunction::ADB | V1_2::GadgetFunction::ACCESSORY: + ret = setVidPid("0x18d1", "0x2d01"); + break; + case static_cast(V1_2::GadgetFunction::AUDIO_SOURCE): + ret = setVidPid("0x18d1", "0x2d02"); + break; + case V1_2::GadgetFunction::ADB | V1_2::GadgetFunction::AUDIO_SOURCE: + ret = setVidPid("0x18d1", "0x2d03"); + break; + case V1_2::GadgetFunction::ACCESSORY | V1_2::GadgetFunction::AUDIO_SOURCE: + ret = setVidPid("0x18d1", "0x2d04"); + break; + case V1_2::GadgetFunction::ADB | V1_2::GadgetFunction::ACCESSORY | + V1_2::GadgetFunction::AUDIO_SOURCE: + ret = setVidPid("0x18d1", "0x2d05"); + break; + default: + ALOGE("Combination not supported"); + ret = V1_0::Status::CONFIGURATION_NOT_SUPPORTED; + } + return ret; +} + +V1_0::Status UsbGadget::setupFunctions(uint64_t functions, + const sp& callback, + uint64_t timeout) { + bool ffsEnabled = false; + int i = 0; + + if (addGenericAndroidFunctions(&monitorFfs, functions, &ffsEnabled, &i) != + V1_0::Status::SUCCESS) + return V1_0::Status::ERROR; + + if ((functions & V1_2::GadgetFunction::ADB) != 0) { + ffsEnabled = true; + if (addAdb(&monitorFfs, &i) != V1_0::Status::SUCCESS) return V1_0::Status::ERROR; + } + + // Pull up the gadget right away when there are no ffs functions. + if (!ffsEnabled) { + if (!WriteStringToFile(kGadgetName, PULLUP_PATH)) return V1_0::Status::ERROR; + mCurrentUsbFunctionsApplied = true; + if (callback) callback->setCurrentUsbFunctionsCb(functions, V1_0::Status::SUCCESS); + return V1_0::Status::SUCCESS; + } + + monitorFfs.registerFunctionsAppliedCallback(¤tFunctionsAppliedCallback, this); + // Monitors the ffs paths to pull up the gadget when descriptors are written. + // Also takes of the pulling up the gadget again if the userspace process + // dies and restarts. + monitorFfs.startMonitor(); + + if (kDebug) ALOGI("Mainthread in Cv"); + + if (callback) { + bool pullup = monitorFfs.waitForPullUp(timeout); + Return ret = callback->setCurrentUsbFunctionsCb( + functions, pullup ? V1_0::Status::SUCCESS : V1_0::Status::ERROR); + if (!ret.isOk()) ALOGE("setCurrentUsbFunctionsCb error %s", ret.description().c_str()); + } + + return V1_0::Status::SUCCESS; +} + +Return UsbGadget::setCurrentUsbFunctions(uint64_t functions, + const sp& callback, + uint64_t timeout) { + std::unique_lock lk(mLockSetCurrentFunction); + + mCurrentUsbFunctions = functions; + mCurrentUsbFunctionsApplied = false; + + // Unlink the gadget and stop the monitor if running. + V1_0::Status status = tearDownGadget(); + if (status != V1_0::Status::SUCCESS) { + goto error; + } + + ALOGI("Returned from tearDown gadget"); + + // Leave the gadget pulled down to give time for the host to sense disconnect. + usleep(kDisconnectWaitUs); + + if (functions == static_cast(V1_2::GadgetFunction::NONE)) { + if (callback == NULL) return Void(); + Return ret = callback->setCurrentUsbFunctionsCb(functions, V1_0::Status::SUCCESS); + if (!ret.isOk()) + ALOGE("Error while calling setCurrentUsbFunctionsCb %s", ret.description().c_str()); + return Void(); + } + + status = validateAndSetVidPid(functions); + + if (status != V1_0::Status::SUCCESS) { + goto error; + } + + status = setupFunctions(functions, callback, timeout); + if (status != V1_0::Status::SUCCESS) { + goto error; + } + + ALOGI("Usb Gadget setcurrent functions called successfully"); + return Void(); + +error: + ALOGI("Usb Gadget setcurrent functions failed"); + if (callback == NULL) return Void(); + Return ret = callback->setCurrentUsbFunctionsCb(functions, status); + if (!ret.isOk()) + ALOGE("Error while calling setCurrentUsbFunctionsCb %s", ret.description().c_str()); + return Void(); +} +} // namespace implementation +} // namespace V1_2 +} // namespace gadget +} // namespace usb +} // namespace hardware +} // namespace android diff --git a/usb/gadget/1.2/default/UsbGadget.h b/usb/gadget/1.2/default/UsbGadget.h new file mode 100644 index 0000000000000000000000000000000000000000..12ad8eed6110bf7ebcd1b1e11670803d5b308f1b --- /dev/null +++ b/usb/gadget/1.2/default/UsbGadget.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_USB_GADGET_V1_2_USBGADGET_H +#define ANDROID_HARDWARE_USB_GADGET_V1_2_USBGADGET_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace usb { +namespace gadget { +namespace V1_2 { +namespace implementation { + +using ::android::sp; +using ::android::base::GetProperty; +using ::android::base::ReadFileToString; +using ::android::base::SetProperty; +using ::android::base::Trim; +using ::android::base::unique_fd; +using ::android::base::WriteStringToFile; +using ::android::hardware::hidl_array; +using ::android::hardware::hidl_memory; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::usb::gadget::addAdb; +using ::android::hardware::usb::gadget::addEpollFd; +using ::android::hardware::usb::gadget::getVendorFunctions; +using ::android::hardware::usb::gadget::kDebug; +using ::android::hardware::usb::gadget::kDisconnectWaitUs; +using ::android::hardware::usb::gadget::linkFunction; +using ::android::hardware::usb::gadget::MonitorFfs; +using ::android::hardware::usb::gadget::resetGadget; +using ::android::hardware::usb::gadget::setVidPid; +using ::android::hardware::usb::gadget::unlinkFunctions; +using ::std::string; + +constexpr char kGadgetName[] = "11110000.usb"; +static MonitorFfs monitorFfs(kGadgetName); + +#define UDC_PATH "/sys/class/udc/11110000.usb/" +#define SPEED_PATH UDC_PATH "current_speed" + +struct UsbGadget : public IUsbGadget { + UsbGadget(); + + // Makes sure that only one request is processed at a time. + std::mutex mLockSetCurrentFunction; + uint64_t mCurrentUsbFunctions; + bool mCurrentUsbFunctionsApplied; + UsbSpeed mUsbSpeed; + + Return setCurrentUsbFunctions(uint64_t functions, + const sp& callback, + uint64_t timeout) override; + + Return getCurrentUsbFunctions(const sp& callback) override; + + Return reset() override; + + Return getUsbSpeed(const sp& callback) override; + + private: + V1_0::Status tearDownGadget(); + V1_0::Status setupFunctions(uint64_t functions, const sp& callback, + uint64_t timeout); +}; + +} // namespace implementation +} // namespace V1_2 +} // namespace gadget +} // namespace usb +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_USB_V1_2_USBGADGET_H diff --git a/usb/gadget/1.2/default/android.hardware.usb.gadget@1.2-service.rc b/usb/gadget/1.2/default/android.hardware.usb.gadget@1.2-service.rc new file mode 100644 index 0000000000000000000000000000000000000000..650b0850cd898dacbdbe4690749e49ed68d5a3e7 --- /dev/null +++ b/usb/gadget/1.2/default/android.hardware.usb.gadget@1.2-service.rc @@ -0,0 +1,7 @@ +service vendor.usb-gadget-hal-1-2 /vendor/bin/hw/android.hardware.usb.gadget@1.2-service + interface android.hardware.usb.gadget@1.0::IUsbGadget default + interface android.hardware.usb.gadget@1.1::IUsbGadget default + interface android.hardware.usb.gadget@1.2::IUsbGadget default + class hal + user system + group system shell mtp diff --git a/usb/gadget/1.2/default/android.hardware.usb.gadget@1.2-service.xml b/usb/gadget/1.2/default/android.hardware.usb.gadget@1.2-service.xml new file mode 100644 index 0000000000000000000000000000000000000000..8557f6ff50dbd5c722c5ce9f2d231164aa5e742e --- /dev/null +++ b/usb/gadget/1.2/default/android.hardware.usb.gadget@1.2-service.xml @@ -0,0 +1,11 @@ + + + android.hardware.usb.gadget + hwbinder + 1.2 + + IUsbGadget + default + + + diff --git a/usb/gadget/1.2/default/lib/Android.bp b/usb/gadget/1.2/default/lib/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..3bf46e36a8617031e684f40d69ecff013539333b --- /dev/null +++ b/usb/gadget/1.2/default/lib/Android.bp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_library_static { + name: "libusbconfigfs-2", + vendor_available: true, + export_include_dirs: ["include"], + + srcs: [ + "UsbGadgetUtils.cpp", + "MonitorFfs.cpp", + ], + + cflags: [ + "-Wall", + "-Werror", + ], + + shared_libs: [ + "android.hardware.usb.gadget@1.0", + "android.hardware.usb.gadget@1.1", + "android.hardware.usb.gadget@1.2", + "libbase", + "libcutils", + "libhidlbase", + "libutils", + ], +} diff --git a/usb/gadget/1.2/default/lib/MonitorFfs.cpp b/usb/gadget/1.2/default/lib/MonitorFfs.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0cdf038de19a8f8a4e43f3b5f8508fb8566ed7f2 --- /dev/null +++ b/usb/gadget/1.2/default/lib/MonitorFfs.cpp @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "libusbconfigfs" + +#include "include/UsbGadgetCommon.h" + +namespace android { +namespace hardware { +namespace usb { +namespace gadget { + +static volatile bool gadgetPullup; + +MonitorFfs::MonitorFfs(const char* const gadget) + : mWatchFd(), + mEndpointList(), + mLock(), + mCv(), + mLockFd(), + mCurrentUsbFunctionsApplied(false), + mMonitor(), + mCallback(NULL), + mPayload(NULL), + mGadgetName(gadget), + mMonitorRunning(false) { + unique_fd eventFd(eventfd(0, 0)); + if (eventFd == -1) { + ALOGE("mEventFd failed to create %d", errno); + abort(); + } + + unique_fd epollFd(epoll_create(2)); + if (epollFd == -1) { + ALOGE("mEpollFd failed to create %d", errno); + abort(); + } + + unique_fd inotifyFd(inotify_init()); + if (inotifyFd < 0) { + ALOGE("inotify init failed"); + abort(); + } + + if (addEpollFd(epollFd, inotifyFd) == -1) abort(); + + if (addEpollFd(epollFd, eventFd) == -1) abort(); + + mEpollFd = move(epollFd); + mInotifyFd = move(inotifyFd); + mEventFd = move(eventFd); + gadgetPullup = false; +} + +static void displayInotifyEvent(struct inotify_event* i) { + ALOGE(" wd =%2d; ", i->wd); + if (i->cookie > 0) ALOGE("cookie =%4d; ", i->cookie); + + ALOGE("mask = "); + if (i->mask & IN_ACCESS) ALOGE("IN_ACCESS "); + if (i->mask & IN_ATTRIB) ALOGE("IN_ATTRIB "); + if (i->mask & IN_CLOSE_NOWRITE) ALOGE("IN_CLOSE_NOWRITE "); + if (i->mask & IN_CLOSE_WRITE) ALOGE("IN_CLOSE_WRITE "); + if (i->mask & IN_CREATE) ALOGE("IN_CREATE "); + if (i->mask & IN_DELETE) ALOGE("IN_DELETE "); + if (i->mask & IN_DELETE_SELF) ALOGE("IN_DELETE_SELF "); + if (i->mask & IN_IGNORED) ALOGE("IN_IGNORED "); + if (i->mask & IN_ISDIR) ALOGE("IN_ISDIR "); + if (i->mask & IN_MODIFY) ALOGE("IN_MODIFY "); + if (i->mask & IN_MOVE_SELF) ALOGE("IN_MOVE_SELF "); + if (i->mask & IN_MOVED_FROM) ALOGE("IN_MOVED_FROM "); + if (i->mask & IN_MOVED_TO) ALOGE("IN_MOVED_TO "); + if (i->mask & IN_OPEN) ALOGE("IN_OPEN "); + if (i->mask & IN_Q_OVERFLOW) ALOGE("IN_Q_OVERFLOW "); + if (i->mask & IN_UNMOUNT) ALOGE("IN_UNMOUNT "); + ALOGE("\n"); + + if (i->len > 0) ALOGE(" name = %s\n", i->name); +} + +void* MonitorFfs::startMonitorFd(void* param) { + MonitorFfs* monitorFfs = (MonitorFfs*)param; + char buf[kBufferSize]; + bool writeUdc = true, stopMonitor = false; + struct epoll_event events[kEpollEvents]; + steady_clock::time_point disconnect; + + bool descriptorWritten = true; + for (int i = 0; i < static_cast(monitorFfs->mEndpointList.size()); i++) { + if (access(monitorFfs->mEndpointList.at(i).c_str(), R_OK)) { + descriptorWritten = false; + break; + } + } + + // notify here if the endpoints are already present. + if (descriptorWritten) { + usleep(kPullUpDelay); + if (!!WriteStringToFile(monitorFfs->mGadgetName, PULLUP_PATH)) { + lock_guard lock(monitorFfs->mLock); + monitorFfs->mCurrentUsbFunctionsApplied = true; + monitorFfs->mCallback(monitorFfs->mCurrentUsbFunctionsApplied, monitorFfs->mPayload); + gadgetPullup = true; + writeUdc = false; + ALOGI("GADGET pulled up"); + monitorFfs->mCv.notify_all(); + } + } + + while (!stopMonitor) { + int nrEvents = epoll_wait(monitorFfs->mEpollFd, events, kEpollEvents, -1); + + if (nrEvents <= 0) { + ALOGE("epoll wait did not return descriptor number"); + continue; + } + + for (int i = 0; i < nrEvents; i++) { + ALOGI("event=%u on fd=%d\n", events[i].events, events[i].data.fd); + + if (events[i].data.fd == monitorFfs->mInotifyFd) { + // Process all of the events in buffer returned by read(). + int numRead = read(monitorFfs->mInotifyFd, buf, kBufferSize); + for (char* p = buf; p < buf + numRead;) { + struct inotify_event* event = (struct inotify_event*)p; + if (kDebug) displayInotifyEvent(event); + + p += sizeof(struct inotify_event) + event->len; + + bool descriptorPresent = true; + for (int j = 0; j < static_cast(monitorFfs->mEndpointList.size()); j++) { + if (access(monitorFfs->mEndpointList.at(j).c_str(), R_OK)) { + if (kDebug) ALOGI("%s absent", monitorFfs->mEndpointList.at(j).c_str()); + descriptorPresent = false; + break; + } + } + + if (!descriptorPresent && !writeUdc) { + if (kDebug) ALOGI("endpoints not up"); + writeUdc = true; + disconnect = std::chrono::steady_clock::now(); + } else if (descriptorPresent && writeUdc) { + steady_clock::time_point temp = steady_clock::now(); + + if (std::chrono::duration_cast(temp - disconnect).count() < + kPullUpDelay) + usleep(kPullUpDelay); + + if (!!WriteStringToFile(monitorFfs->mGadgetName, PULLUP_PATH)) { + lock_guard lock(monitorFfs->mLock); + monitorFfs->mCurrentUsbFunctionsApplied = true; + monitorFfs->mCallback(monitorFfs->mCurrentUsbFunctionsApplied, + monitorFfs->mPayload); + ALOGI("GADGET pulled up"); + writeUdc = false; + gadgetPullup = true; + // notify the main thread to signal userspace. + monitorFfs->mCv.notify_all(); + } + } + } + } else { + uint64_t flag; + read(monitorFfs->mEventFd, &flag, sizeof(flag)); + if (flag == 100) { + stopMonitor = true; + break; + } + } + } + } + return NULL; +} + +void MonitorFfs::reset() { + lock_guard lock(mLockFd); + uint64_t flag = 100; + unsigned long ret; + + if (mMonitorRunning) { + // Stop the monitor thread by writing into signal fd. + ret = TEMP_FAILURE_RETRY(write(mEventFd, &flag, sizeof(flag))); + if (ret < 0) ALOGE("Error writing eventfd errno=%d", errno); + + ALOGI("mMonitor signalled to exit"); + mMonitor->join(); + ALOGI("mMonitor destroyed"); + mMonitorRunning = false; + } + + for (std::vector::size_type i = 0; i != mWatchFd.size(); i++) + inotify_rm_watch(mInotifyFd, mWatchFd[i]); + + mEndpointList.clear(); + gadgetPullup = false; + mCallback = NULL; + mPayload = NULL; +} + +bool MonitorFfs::startMonitor() { + mMonitor = unique_ptr(new thread(this->startMonitorFd, this)); + mMonitorRunning = true; + return true; +} + +bool MonitorFfs::isMonitorRunning() { + return mMonitorRunning; +} + +bool MonitorFfs::waitForPullUp(int timeout_ms) { + std::unique_lock lk(mLock); + + if (gadgetPullup) return true; + + if (mCv.wait_for(lk, timeout_ms * 1ms, [] { return gadgetPullup; })) { + ALOGI("monitorFfs signalled true"); + return true; + } else { + ALOGI("monitorFfs signalled error"); + // continue monitoring as the descriptors might be written at a later + // point. + return false; + } +} + +bool MonitorFfs::addInotifyFd(string fd) { + lock_guard lock(mLockFd); + int wfd; + + wfd = inotify_add_watch(mInotifyFd, fd.c_str(), IN_ALL_EVENTS); + if (wfd == -1) + return false; + else + mWatchFd.push_back(wfd); + + return true; +} + +void MonitorFfs::addEndPoint(string ep) { + lock_guard lock(mLockFd); + + mEndpointList.push_back(ep); +} + +void MonitorFfs::registerFunctionsAppliedCallback(void (*callback)(bool functionsApplied, + void* payload), + void* payload) { + mCallback = callback; + mPayload = payload; +} + +} // namespace gadget +} // namespace usb +} // namespace hardware +} // namespace android diff --git a/usb/gadget/1.2/default/lib/UsbGadgetUtils.cpp b/usb/gadget/1.2/default/lib/UsbGadgetUtils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..898655651c63e0eb6e711d519972c78f8959b2ca --- /dev/null +++ b/usb/gadget/1.2/default/lib/UsbGadgetUtils.cpp @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "libusbconfigfs" + +#include "include/UsbGadgetCommon.h" + +namespace android { +namespace hardware { +namespace usb { +namespace gadget { + +int unlinkFunctions(const char* path) { + DIR* config = opendir(path); + struct dirent* function; + char filepath[kMaxFilePathLength]; + int ret = 0; + + if (config == NULL) return -1; + + // d_type does not seems to be supported in /config + // so filtering by name. + while (((function = readdir(config)) != NULL)) { + if ((strstr(function->d_name, FUNCTION_NAME) == NULL)) continue; + // build the path for each file in the folder. + sprintf(filepath, "%s/%s", path, function->d_name); + ret = remove(filepath); + if (ret) { + ALOGE("Unable remove file %s errno:%d", filepath, errno); + break; + } + } + + closedir(config); + return ret; +} + +int addEpollFd(const unique_fd& epfd, const unique_fd& fd) { + struct epoll_event event; + int ret; + + event.data.fd = fd; + event.events = EPOLLIN; + + ret = epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event); + if (ret) ALOGE("epoll_ctl error %d", errno); + + return ret; +} + +int linkFunction(const char* function, int index) { + char functionPath[kMaxFilePathLength]; + char link[kMaxFilePathLength]; + + sprintf(functionPath, "%s%s", FUNCTIONS_PATH, function); + sprintf(link, "%s%d", FUNCTION_PATH, index); + if (symlink(functionPath, link)) { + ALOGE("Cannot create symlink %s -> %s errno:%d", link, functionPath, errno); + return -1; + } + return 0; +} + +Status setVidPid(const char* vid, const char* pid) { + if (!WriteStringToFile(vid, VENDOR_ID_PATH)) return Status::ERROR; + + if (!WriteStringToFile(pid, PRODUCT_ID_PATH)) return Status::ERROR; + + return Status::SUCCESS; +} + +std::string getVendorFunctions() { + if (GetProperty(kBuildType, "") == "user") return "user"; + + std::string bootMode = GetProperty(PERSISTENT_BOOT_MODE, ""); + std::string persistVendorFunctions = GetProperty(kPersistentVendorConfig, ""); + std::string vendorFunctions = GetProperty(kVendorConfig, ""); + std::string ret = ""; + + if (vendorFunctions != "") { + ret = vendorFunctions; + } else if (bootMode == "usbradio" || bootMode == "factory" || bootMode == "ffbm-00" || + bootMode == "ffbm-01") { + if (persistVendorFunctions != "") + ret = persistVendorFunctions; + else + ret = "diag"; + // vendor.usb.config will reflect the current configured functions + SetProperty(kVendorConfig, ret); + } + + return ret; +} + +Status resetGadget() { + ALOGI("setCurrentUsbFunctions None"); + + if (!WriteStringToFile("none", PULLUP_PATH)) ALOGI("Gadget cannot be pulled down"); + + if (!WriteStringToFile("0", DEVICE_CLASS_PATH)) return Status::ERROR; + + if (!WriteStringToFile("0", DEVICE_SUB_CLASS_PATH)) return Status::ERROR; + + if (!WriteStringToFile("0", DEVICE_PROTOCOL_PATH)) return Status::ERROR; + + if (!WriteStringToFile("0", DESC_USE_PATH)) return Status::ERROR; + + if (unlinkFunctions(CONFIG_PATH)) return Status::ERROR; + + return Status::SUCCESS; +} + +Status addGenericAndroidFunctions(MonitorFfs* monitorFfs, uint64_t functions, bool* ffsEnabled, + int* functionCount) { + if (((functions & GadgetFunction::MTP) != 0)) { + *ffsEnabled = true; + ALOGI("setCurrentUsbFunctions mtp"); + if (!WriteStringToFile("1", DESC_USE_PATH)) return Status::ERROR; + + if (!monitorFfs->addInotifyFd("/dev/usb-ffs/mtp/")) return Status::ERROR; + + if (linkFunction("ffs.mtp", (*functionCount)++)) return Status::ERROR; + + // Add endpoints to be monitored. + monitorFfs->addEndPoint("/dev/usb-ffs/mtp/ep1"); + monitorFfs->addEndPoint("/dev/usb-ffs/mtp/ep2"); + monitorFfs->addEndPoint("/dev/usb-ffs/mtp/ep3"); + } else if (((functions & GadgetFunction::PTP) != 0)) { + *ffsEnabled = true; + ALOGI("setCurrentUsbFunctions ptp"); + if (!WriteStringToFile("1", DESC_USE_PATH)) return Status::ERROR; + + if (!monitorFfs->addInotifyFd("/dev/usb-ffs/ptp/")) return Status::ERROR; + + if (linkFunction("ffs.ptp", (*functionCount)++)) return Status::ERROR; + + // Add endpoints to be monitored. + monitorFfs->addEndPoint("/dev/usb-ffs/ptp/ep1"); + monitorFfs->addEndPoint("/dev/usb-ffs/ptp/ep2"); + monitorFfs->addEndPoint("/dev/usb-ffs/ptp/ep3"); + } + + if ((functions & GadgetFunction::MIDI) != 0) { + ALOGI("setCurrentUsbFunctions MIDI"); + if (linkFunction("midi.gs5", (*functionCount)++)) return Status::ERROR; + } + + if ((functions & GadgetFunction::ACCESSORY) != 0) { + ALOGI("setCurrentUsbFunctions Accessory"); + if (linkFunction("accessory.gs2", (*functionCount)++)) return Status::ERROR; + } + + if ((functions & GadgetFunction::AUDIO_SOURCE) != 0) { + ALOGI("setCurrentUsbFunctions Audio Source"); + if (linkFunction("audio_source.gs3", (*functionCount)++)) return Status::ERROR; + } + + if ((functions & GadgetFunction::RNDIS) != 0) { + ALOGI("setCurrentUsbFunctions rndis"); + if (linkFunction("gsi.rndis", (*functionCount)++)) return Status::ERROR; + std::string rndisFunction = GetProperty(kVendorRndisConfig, ""); + if (rndisFunction != "") { + if (linkFunction(rndisFunction.c_str(), (*functionCount)++)) return Status::ERROR; + } else { + // link gsi.rndis for older pixel projects + if (linkFunction("gsi.rndis", (*functionCount)++)) return Status::ERROR; + } + } + + if ((functions & GadgetFunction::NCM) != 0) { + ALOGI("setCurrentUsbFunctions ncm"); + if (linkFunction("ncm.gs6", (*functionCount)++)) return Status::ERROR; + } + + return Status::SUCCESS; +} + +Status addAdb(MonitorFfs* monitorFfs, int* functionCount) { + ALOGI("setCurrentUsbFunctions Adb"); + if (!monitorFfs->addInotifyFd("/dev/usb-ffs/adb/")) return Status::ERROR; + + if (linkFunction("ffs.adb", (*functionCount)++)) return Status::ERROR; + monitorFfs->addEndPoint("/dev/usb-ffs/adb/ep1"); + monitorFfs->addEndPoint("/dev/usb-ffs/adb/ep2"); + ALOGI("Service started"); + return Status::SUCCESS; +} + +} // namespace gadget +} // namespace usb +} // namespace hardware +} // namespace android diff --git a/usb/gadget/1.2/default/lib/include/UsbGadgetCommon.h b/usb/gadget/1.2/default/lib/include/UsbGadgetCommon.h new file mode 100644 index 0000000000000000000000000000000000000000..18b8101ebe1bc799db61e56cea7346a9601325c3 --- /dev/null +++ b/usb/gadget/1.2/default/lib/include/UsbGadgetCommon.h @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HARDWARE_USB_USBGADGETCOMMON_H +#define HARDWARE_USB_USBGADGETCOMMON_H + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace usb { +namespace gadget { + +constexpr int kBufferSize = 512; +constexpr int kMaxFilePathLength = 256; +constexpr int kEpollEvents = 10; +constexpr bool kDebug = false; +constexpr int kDisconnectWaitUs = 100000; +constexpr int kPullUpDelay = 500000; +constexpr int kShutdownMonitor = 100; + +constexpr char kBuildType[] = "ro.build.type"; +constexpr char kPersistentVendorConfig[] = "persist.vendor.usb.usbradio.config"; +constexpr char kVendorConfig[] = "vendor.usb.config"; +constexpr char kVendorRndisConfig[] = "vendor.usb.rndis.config"; + +#define GADGET_PATH "/config/usb_gadget/g1/" +#define PULLUP_PATH GADGET_PATH "UDC" +#define PERSISTENT_BOOT_MODE "ro.bootmode" +#define VENDOR_ID_PATH GADGET_PATH "idVendor" +#define PRODUCT_ID_PATH GADGET_PATH "idProduct" +#define DEVICE_CLASS_PATH GADGET_PATH "bDeviceClass" +#define DEVICE_SUB_CLASS_PATH GADGET_PATH "bDeviceSubClass" +#define DEVICE_PROTOCOL_PATH GADGET_PATH "bDeviceProtocol" +#define DESC_USE_PATH GADGET_PATH "os_desc/use" +#define OS_DESC_PATH GADGET_PATH "os_desc/b.1" +#define CONFIG_PATH GADGET_PATH "configs/b.1/" +#define FUNCTIONS_PATH GADGET_PATH "functions/" +#define FUNCTION_NAME "function" +#define FUNCTION_PATH CONFIG_PATH FUNCTION_NAME +#define RNDIS_PATH FUNCTIONS_PATH "gsi.rndis" + +using ::android::base::GetProperty; +using ::android::base::SetProperty; +using ::android::base::unique_fd; +using ::android::base::WriteStringToFile; +using ::android::hardware::usb::gadget::V1_0::Status; +using ::android::hardware::usb::gadget::V1_2::GadgetFunction; + +using ::std::lock_guard; +using ::std::move; +using ::std::mutex; +using ::std::string; +using ::std::thread; +using ::std::unique_ptr; +using ::std::vector; +using ::std::chrono::microseconds; +using ::std::chrono::steady_clock; +using ::std::literals::chrono_literals::operator""ms; + +// MonitorFfs automously manages gadget pullup by monitoring +// the ep file status. Restarts the usb gadget when the ep +// owner restarts. +class MonitorFfs { + private: + // Monitors the endpoints Inotify events. + unique_fd mInotifyFd; + // Control pipe for shutting down the mMonitor thread. + // mMonitor exits when SHUTDOWN_MONITOR is written into + // mEventFd/ + unique_fd mEventFd; + // Pools on mInotifyFd and mEventFd. + unique_fd mEpollFd; + vector mWatchFd; + + // Maintains the list of Endpoints. + vector mEndpointList; + // protects the CV. + std::mutex mLock; + std::condition_variable mCv; + // protects mInotifyFd, mEpollFd. + std::mutex mLockFd; + + // Flag to maintain the current status of gadget pullup. + bool mCurrentUsbFunctionsApplied; + + // Thread object that executes the ep monitoring logic. + unique_ptr mMonitor; + // Callback to be invoked when gadget is pulled up. + void (*mCallback)(bool functionsApplied, void* payload); + void* mPayload; + // Name of the USB gadget. Used for pullup. + const char* const mGadgetName; + // Monitor State + bool mMonitorRunning; + + public: + MonitorFfs(const char* const gadget); + // Inits all the UniqueFds. + void reset(); + // Starts monitoring endpoints and pullup the gadget when + // the descriptors are written. + bool startMonitor(); + // Waits for timeout_ms for gadget pull up to happen. + // Returns immediately if the gadget is already pulled up. + bool waitForPullUp(int timeout_ms); + // Adds the given fd to the watch list. + bool addInotifyFd(string fd); + // Adds the given endpoint to the watch list. + void addEndPoint(string ep); + // Registers the async callback from the caller to notify the caller + // when the gadget pull up happens. + void registerFunctionsAppliedCallback(void (*callback)(bool functionsApplied, void*(payload)), + void* payload); + bool isMonitorRunning(); + // Ep monitoring and the gadget pull up logic. + static void* startMonitorFd(void* param); +}; + +//**************** Helper functions ************************// + +// Adds the given fd to the epollfd(epfd). +int addEpollFd(const unique_fd& epfd, const unique_fd& fd); +// Removes all the usb functions link in the specified path. +int unlinkFunctions(const char* path); +// Craetes a configfs link for the function. +int linkFunction(const char* function, int index); +// Sets the USB VID and PID. +Status setVidPid(const char* vid, const char* pid); +// Extracts vendor functions from the vendor init properties. +std::string getVendorFunctions(); +// Adds Adb to the usb configuration. +Status addAdb(MonitorFfs* monitorFfs, int* functionCount); +// Adds all applicable generic android usb functions other than ADB. +Status addGenericAndroidFunctions(MonitorFfs* monitorFfs, uint64_t functions, bool* ffsEnabled, + int* functionCount); +// Pulls down USB gadget. +Status resetGadget(); + +} // namespace gadget +} // namespace usb +} // namespace hardware +} // namespace android +#endif diff --git a/usb/gadget/1.2/default/service.cpp b/usb/gadget/1.2/default/service.cpp new file mode 100644 index 0000000000000000000000000000000000000000..80c56a653f15bb3e0ec74f18330cf84d35cb6835 --- /dev/null +++ b/usb/gadget/1.2/default/service.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "android.hardware.usb.gadget@1.2-service" + +#include +#include "UsbGadget.h" + +using android::sp; + +// libhwbinder: +using android::hardware::configureRpcThreadpool; +using android::hardware::joinRpcThreadpool; + +// Generated HIDL files +using android::hardware::usb::gadget::V1_2::IUsbGadget; +using android::hardware::usb::gadget::V1_2::implementation::UsbGadget; + +using android::OK; +using android::status_t; + +int main() { + configureRpcThreadpool(1, true /*callerWillJoin*/); + + android::sp service = new UsbGadget(); + + status_t status = service->registerAsService(); + + if (status != OK) { + ALOGE("Cannot register USB Gadget HAL service"); + return 1; + } + + ALOGI("USB Gadget HAL Ready."); + joinRpcThreadpool(); + // Under noraml cases, execution will not reach this line. + ALOGI("USB Gadget HAL failed to join thread pool."); + return 1; +} diff --git a/usb/gadget/1.2/types.hal b/usb/gadget/1.2/types.hal new file mode 100644 index 0000000000000000000000000000000000000000..a5c079d9c63224ca56bc4bb61b308ccc47fc25ba --- /dev/null +++ b/usb/gadget/1.2/types.hal @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.usb.gadget@1.2; + +import android.hardware.usb.gadget@1.0::GadgetFunction; + +enum GadgetFunction : @1.0::GadgetFunction { + /** + * NCM - NCM function. + */ + NCM = 1 << 10, +}; + +enum UsbSpeed : uint32_t { + /** + * UNKNOWN - Not Connected or Unsupported Speed + */ + UNKNOWN = -1, + + /** + * USB Low Speed + */ + LOWSPEED = 0, + + /** + * USB Full Speed + */ + FULLSPEED = 1, + + /** + * USB High Speed + */ + HIGHSPEED = 2, + + /** + * USB Super Speed + */ + SUPERSPEED = 3, + + /** + * USB Super Speed 10Gbps + */ + SUPERSPEED_10Gb = 4, + + /** + * USB Super Speed 20Gbps + */ + SUPERSPEED_20Gb = 5, + + /** + * USB4 Gen2 x 1 (10Gbps) + */ + USB4_GEN2_10Gb = 6, + + /** + * USB4 Gen2 x 2 (20Gbps) + */ + USB4_GEN2_20Gb = 7, + + /** + * USB4 Gen3 x 1 (20Gbps) + */ + USB4_GEN3_20Gb = 8, + + /** + * USB4 Gen3 x 2 (40Gbps) + */ + USB4_GEN3_40Gb = 9, + + /** + * This is a suggestion if needed. + * + * Reserved Speed -- It is a newer speed after USB4 v1.0 announcement. + * If this speed is detected, the HAL implementation should convert current + * speed to above speeds which is lower and the closest. + */ + RESERVED_SPEED = 64, +}; diff --git a/vibrator/aidl/Android.bp b/vibrator/aidl/Android.bp index 9bad971724f337468aaedf97454562e3601687a9..22219b0f73182b32f08e07a7c6626c42a3cb3a9b 100644 --- a/vibrator/aidl/Android.bp +++ b/vibrator/aidl/Android.bp @@ -16,7 +16,7 @@ aidl_interface { stability: "vintf", backend: { java: { - platform_apis: true, + sdk_version: "module_current", }, ndk: { vndk: { @@ -24,5 +24,8 @@ aidl_interface { }, }, }, - versions: ["1"], + versions: [ + "1", + "2", + ], } diff --git a/vibrator/aidl/OWNERS b/vibrator/aidl/OWNERS new file mode 100644 index 0000000000000000000000000000000000000000..4bd56146ca3ebfcc87f04be9d40065f04dfc1e19 --- /dev/null +++ b/vibrator/aidl/OWNERS @@ -0,0 +1,4 @@ +chasewu@google.com +leungv@google.com +lsandrade@google.com +michaelwr@google.com diff --git a/vibrator/aidl/TEST_MAPPING b/vibrator/aidl/TEST_MAPPING index 5ae32e744c85a2423130c772806bc67e53396fa6..2414b8464f1dc70a0a67b4dcf76921ea47f81a89 100644 --- a/vibrator/aidl/TEST_MAPPING +++ b/vibrator/aidl/TEST_MAPPING @@ -2,6 +2,9 @@ "presubmit": [ { "name": "VtsHalVibratorTargetTest" + }, + { + "name": "VtsHalVibratorManagerTargetTest" } ] } diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/2/.hash b/vibrator/aidl/aidl_api/android.hardware.vibrator/2/.hash new file mode 100644 index 0000000000000000000000000000000000000000..cf5edcc89a688313dde505c239f91dee781e41da --- /dev/null +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/2/.hash @@ -0,0 +1 @@ +ea8742d6993e1a82917da38b9938e537aa7fcb54 diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/2/android/hardware/vibrator/ActivePwle.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/2/android/hardware/vibrator/ActivePwle.aidl new file mode 100644 index 0000000000000000000000000000000000000000..de3ad3c032a48d29417ce096862b85b33097e3d7 --- /dev/null +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/2/android/hardware/vibrator/ActivePwle.aidl @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.vibrator; +@VintfStability +parcelable ActivePwle { + float startAmplitude; + float startFrequency; + float endAmplitude; + float endFrequency; + int duration; +} diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/2/android/hardware/vibrator/Braking.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/2/android/hardware/vibrator/Braking.aidl new file mode 100644 index 0000000000000000000000000000000000000000..d38c584d76e9b8524b14bf56780036da831061a6 --- /dev/null +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/2/android/hardware/vibrator/Braking.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.vibrator; +@Backing(type="int") @VintfStability +enum Braking { + NONE = 0, + CLAB = 1, +} diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/2/android/hardware/vibrator/BrakingPwle.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/2/android/hardware/vibrator/BrakingPwle.aidl new file mode 100644 index 0000000000000000000000000000000000000000..fa7b43abd09cb4be2dcbb47b641a1e0459b00b43 --- /dev/null +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/2/android/hardware/vibrator/BrakingPwle.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.vibrator; +@VintfStability +parcelable BrakingPwle { + android.hardware.vibrator.Braking braking; + int duration; +} diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/2/android/hardware/vibrator/CompositeEffect.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/2/android/hardware/vibrator/CompositeEffect.aidl new file mode 100644 index 0000000000000000000000000000000000000000..679c82cc3bab7fe8956147a8c8a3a99d8d4719e7 --- /dev/null +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/2/android/hardware/vibrator/CompositeEffect.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.vibrator; +@VintfStability +parcelable CompositeEffect { + int delayMs; + android.hardware.vibrator.CompositePrimitive primitive = android.hardware.vibrator.CompositePrimitive.NOOP; + float scale; +} diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/2/android/hardware/vibrator/CompositePrimitive.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/2/android/hardware/vibrator/CompositePrimitive.aidl new file mode 100644 index 0000000000000000000000000000000000000000..50de13fc27b674560fe360681c35c62db067e961 --- /dev/null +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/2/android/hardware/vibrator/CompositePrimitive.aidl @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.vibrator; +@Backing(type="int") @VintfStability +enum CompositePrimitive { + NOOP = 0, + CLICK = 1, + THUD = 2, + SPIN = 3, + QUICK_RISE = 4, + SLOW_RISE = 5, + QUICK_FALL = 6, + LIGHT_TICK = 7, + LOW_TICK = 8, +} diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/2/android/hardware/vibrator/Effect.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/2/android/hardware/vibrator/Effect.aidl new file mode 100644 index 0000000000000000000000000000000000000000..adf0f2009f702ff0cfabaab0f74b2ef2c619f66d --- /dev/null +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/2/android/hardware/vibrator/Effect.aidl @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.vibrator; +@Backing(type="int") @VintfStability +enum Effect { + CLICK = 0, + DOUBLE_CLICK = 1, + TICK = 2, + THUD = 3, + POP = 4, + HEAVY_CLICK = 5, + RINGTONE_1 = 6, + RINGTONE_2 = 7, + RINGTONE_3 = 8, + RINGTONE_4 = 9, + RINGTONE_5 = 10, + RINGTONE_6 = 11, + RINGTONE_7 = 12, + RINGTONE_8 = 13, + RINGTONE_9 = 14, + RINGTONE_10 = 15, + RINGTONE_11 = 16, + RINGTONE_12 = 17, + RINGTONE_13 = 18, + RINGTONE_14 = 19, + RINGTONE_15 = 20, + TEXTURE_TICK = 21, +} diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/2/android/hardware/vibrator/EffectStrength.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/2/android/hardware/vibrator/EffectStrength.aidl new file mode 100644 index 0000000000000000000000000000000000000000..af5e15871b466e08e24acb8ee09e397d768b23cd --- /dev/null +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/2/android/hardware/vibrator/EffectStrength.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.vibrator; +@Backing(type="byte") @VintfStability +enum EffectStrength { + LIGHT = 0, + MEDIUM = 1, + STRONG = 2, +} diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/2/android/hardware/vibrator/IVibrator.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/2/android/hardware/vibrator/IVibrator.aidl new file mode 100644 index 0000000000000000000000000000000000000000..b7afb663cf7414d09c7272b4f0e2295f37f9e40d --- /dev/null +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/2/android/hardware/vibrator/IVibrator.aidl @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.vibrator; +@VintfStability +interface IVibrator { + int getCapabilities(); + void off(); + void on(in int timeoutMs, in android.hardware.vibrator.IVibratorCallback callback); + int perform(in android.hardware.vibrator.Effect effect, in android.hardware.vibrator.EffectStrength strength, in android.hardware.vibrator.IVibratorCallback callback); + android.hardware.vibrator.Effect[] getSupportedEffects(); + void setAmplitude(in float amplitude); + void setExternalControl(in boolean enabled); + int getCompositionDelayMax(); + int getCompositionSizeMax(); + android.hardware.vibrator.CompositePrimitive[] getSupportedPrimitives(); + int getPrimitiveDuration(android.hardware.vibrator.CompositePrimitive primitive); + void compose(in android.hardware.vibrator.CompositeEffect[] composite, in android.hardware.vibrator.IVibratorCallback callback); + android.hardware.vibrator.Effect[] getSupportedAlwaysOnEffects(); + void alwaysOnEnable(in int id, in android.hardware.vibrator.Effect effect, in android.hardware.vibrator.EffectStrength strength); + void alwaysOnDisable(in int id); + float getResonantFrequency(); + float getQFactor(); + float getFrequencyResolution(); + float getFrequencyMinimum(); + float[] getBandwidthAmplitudeMap(); + int getPwlePrimitiveDurationMax(); + int getPwleCompositionSizeMax(); + android.hardware.vibrator.Braking[] getSupportedBraking(); + void composePwle(in android.hardware.vibrator.PrimitivePwle[] composite, in android.hardware.vibrator.IVibratorCallback callback); + const int CAP_ON_CALLBACK = 1; + const int CAP_PERFORM_CALLBACK = 2; + const int CAP_AMPLITUDE_CONTROL = 4; + const int CAP_EXTERNAL_CONTROL = 8; + const int CAP_EXTERNAL_AMPLITUDE_CONTROL = 16; + const int CAP_COMPOSE_EFFECTS = 32; + const int CAP_ALWAYS_ON_CONTROL = 64; + const int CAP_GET_RESONANT_FREQUENCY = 128; + const int CAP_GET_Q_FACTOR = 256; + const int CAP_FREQUENCY_CONTROL = 512; + const int CAP_COMPOSE_PWLE_EFFECTS = 1024; +} diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/2/android/hardware/vibrator/IVibratorCallback.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/2/android/hardware/vibrator/IVibratorCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..99d6d2290d11e46b386bfaadc99e6dbffc361215 --- /dev/null +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/2/android/hardware/vibrator/IVibratorCallback.aidl @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.vibrator; +@VintfStability +interface IVibratorCallback { + oneway void onComplete(); +} diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/2/android/hardware/vibrator/IVibratorManager.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/2/android/hardware/vibrator/IVibratorManager.aidl new file mode 100644 index 0000000000000000000000000000000000000000..290c68d8777c496fcfd4f8becdaf8d29ce282f99 --- /dev/null +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/2/android/hardware/vibrator/IVibratorManager.aidl @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.vibrator; +@VintfStability +interface IVibratorManager { + int getCapabilities(); + int[] getVibratorIds(); + android.hardware.vibrator.IVibrator getVibrator(in int vibratorId); + void prepareSynced(in int[] vibratorIds); + void triggerSynced(in android.hardware.vibrator.IVibratorCallback callback); + void cancelSynced(); + const int CAP_SYNC = 1; + const int CAP_PREPARE_ON = 2; + const int CAP_PREPARE_PERFORM = 4; + const int CAP_PREPARE_COMPOSE = 8; + const int CAP_MIXED_TRIGGER_ON = 16; + const int CAP_MIXED_TRIGGER_PERFORM = 32; + const int CAP_MIXED_TRIGGER_COMPOSE = 64; + const int CAP_TRIGGER_CALLBACK = 128; +} diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/2/android/hardware/vibrator/PrimitivePwle.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/2/android/hardware/vibrator/PrimitivePwle.aidl new file mode 100644 index 0000000000000000000000000000000000000000..584bcf4a4746779ebd782258aa69ee433df460ec --- /dev/null +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/2/android/hardware/vibrator/PrimitivePwle.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.vibrator; +@VintfStability +union PrimitivePwle { + android.hardware.vibrator.ActivePwle active; + android.hardware.vibrator.BrakingPwle braking; +} diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/ActivePwle.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/ActivePwle.aidl new file mode 100644 index 0000000000000000000000000000000000000000..de3ad3c032a48d29417ce096862b85b33097e3d7 --- /dev/null +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/ActivePwle.aidl @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.vibrator; +@VintfStability +parcelable ActivePwle { + float startAmplitude; + float startFrequency; + float endAmplitude; + float endFrequency; + int duration; +} diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/Braking.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/Braking.aidl new file mode 100644 index 0000000000000000000000000000000000000000..d38c584d76e9b8524b14bf56780036da831061a6 --- /dev/null +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/Braking.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.vibrator; +@Backing(type="int") @VintfStability +enum Braking { + NONE = 0, + CLAB = 1, +} diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/BrakingPwle.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/BrakingPwle.aidl new file mode 100644 index 0000000000000000000000000000000000000000..fa7b43abd09cb4be2dcbb47b641a1e0459b00b43 --- /dev/null +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/BrakingPwle.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.vibrator; +@VintfStability +parcelable BrakingPwle { + android.hardware.vibrator.Braking braking; + int duration; +} diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositeEffect.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositeEffect.aidl index 7431804b34fdcfa8aec89850a969a638aadd0515..679c82cc3bab7fe8956147a8c8a3a99d8d4719e7 100644 --- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositeEffect.aidl +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositeEffect.aidl @@ -1,14 +1,30 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ /////////////////////////////////////////////////////////////////////////////// // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // /////////////////////////////////////////////////////////////////////////////// -// This file is a snapshot of an AIDL interface (or parcelable). Do not try to -// edit this file. It looks like you are doing that because you have modified -// an AIDL interface in a backward-incompatible way, e.g., deleting a function -// from an interface or a field from a parcelable and it broke the build. That -// breakage is intended. +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. // -// You must not make a backward incompatible changes to the AIDL files built +// You must not make a backward incompatible change to any AIDL file built // with the aidl_interface module type with versions property set. The module // type is used to build AIDL files in a way that they can be used across // independently updatable components of the system. If a device is shipped diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositePrimitive.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositePrimitive.aidl index 6ab7ac5b209711356582a6f1a9b37ae65cf55603..50de13fc27b674560fe360681c35c62db067e961 100644 --- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositePrimitive.aidl +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositePrimitive.aidl @@ -1,14 +1,30 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ /////////////////////////////////////////////////////////////////////////////// // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // /////////////////////////////////////////////////////////////////////////////// -// This file is a snapshot of an AIDL interface (or parcelable). Do not try to -// edit this file. It looks like you are doing that because you have modified -// an AIDL interface in a backward-incompatible way, e.g., deleting a function -// from an interface or a field from a parcelable and it broke the build. That -// breakage is intended. +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. // -// You must not make a backward incompatible changes to the AIDL files built +// You must not make a backward incompatible change to any AIDL file built // with the aidl_interface module type with versions property set. The module // type is used to build AIDL files in a way that they can be used across // independently updatable components of the system. If a device is shipped @@ -26,4 +42,5 @@ enum CompositePrimitive { SLOW_RISE = 5, QUICK_FALL = 6, LIGHT_TICK = 7, + LOW_TICK = 8, } diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/Effect.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/Effect.aidl index 5ed4dc5ad6a7115d9c95b6d5ffae325eb42c4b91..adf0f2009f702ff0cfabaab0f74b2ef2c619f66d 100644 --- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/Effect.aidl +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/Effect.aidl @@ -1,14 +1,30 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ /////////////////////////////////////////////////////////////////////////////// // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // /////////////////////////////////////////////////////////////////////////////// -// This file is a snapshot of an AIDL interface (or parcelable). Do not try to -// edit this file. It looks like you are doing that because you have modified -// an AIDL interface in a backward-incompatible way, e.g., deleting a function -// from an interface or a field from a parcelable and it broke the build. That -// breakage is intended. +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. // -// You must not make a backward incompatible changes to the AIDL files built +// You must not make a backward incompatible change to any AIDL file built // with the aidl_interface module type with versions property set. The module // type is used to build AIDL files in a way that they can be used across // independently updatable components of the system. If a device is shipped diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/EffectStrength.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/EffectStrength.aidl index 802d23630910deadf0b652adec915fa3ad75a9df..af5e15871b466e08e24acb8ee09e397d768b23cd 100644 --- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/EffectStrength.aidl +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/EffectStrength.aidl @@ -1,14 +1,30 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ /////////////////////////////////////////////////////////////////////////////// // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // /////////////////////////////////////////////////////////////////////////////// -// This file is a snapshot of an AIDL interface (or parcelable). Do not try to -// edit this file. It looks like you are doing that because you have modified -// an AIDL interface in a backward-incompatible way, e.g., deleting a function -// from an interface or a field from a parcelable and it broke the build. That -// breakage is intended. +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. // -// You must not make a backward incompatible changes to the AIDL files built +// You must not make a backward incompatible change to any AIDL file built // with the aidl_interface module type with versions property set. The module // type is used to build AIDL files in a way that they can be used across // independently updatable components of the system. If a device is shipped diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl index 2de1d7bde7d7e74a3c7f324e5afdd51ecc666f1c..b7afb663cf7414d09c7272b4f0e2295f37f9e40d 100644 --- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl @@ -1,14 +1,30 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ /////////////////////////////////////////////////////////////////////////////// // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // /////////////////////////////////////////////////////////////////////////////// -// This file is a snapshot of an AIDL interface (or parcelable). Do not try to -// edit this file. It looks like you are doing that because you have modified -// an AIDL interface in a backward-incompatible way, e.g., deleting a function -// from an interface or a field from a parcelable and it broke the build. That -// breakage is intended. +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. // -// You must not make a backward incompatible changes to the AIDL files built +// You must not make a backward incompatible change to any AIDL file built // with the aidl_interface module type with versions property set. The module // type is used to build AIDL files in a way that they can be used across // independently updatable components of the system. If a device is shipped @@ -33,6 +49,15 @@ interface IVibrator { android.hardware.vibrator.Effect[] getSupportedAlwaysOnEffects(); void alwaysOnEnable(in int id, in android.hardware.vibrator.Effect effect, in android.hardware.vibrator.EffectStrength strength); void alwaysOnDisable(in int id); + float getResonantFrequency(); + float getQFactor(); + float getFrequencyResolution(); + float getFrequencyMinimum(); + float[] getBandwidthAmplitudeMap(); + int getPwlePrimitiveDurationMax(); + int getPwleCompositionSizeMax(); + android.hardware.vibrator.Braking[] getSupportedBraking(); + void composePwle(in android.hardware.vibrator.PrimitivePwle[] composite, in android.hardware.vibrator.IVibratorCallback callback); const int CAP_ON_CALLBACK = 1; const int CAP_PERFORM_CALLBACK = 2; const int CAP_AMPLITUDE_CONTROL = 4; @@ -40,4 +65,8 @@ interface IVibrator { const int CAP_EXTERNAL_AMPLITUDE_CONTROL = 16; const int CAP_COMPOSE_EFFECTS = 32; const int CAP_ALWAYS_ON_CONTROL = 64; + const int CAP_GET_RESONANT_FREQUENCY = 128; + const int CAP_GET_Q_FACTOR = 256; + const int CAP_FREQUENCY_CONTROL = 512; + const int CAP_COMPOSE_PWLE_EFFECTS = 1024; } diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorCallback.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorCallback.aidl index 3a1e7d865b0b6c94ed9183dc3852e8b5a24a94e1..99d6d2290d11e46b386bfaadc99e6dbffc361215 100644 --- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorCallback.aidl +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorCallback.aidl @@ -1,14 +1,30 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ /////////////////////////////////////////////////////////////////////////////// // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // /////////////////////////////////////////////////////////////////////////////// -// This file is a snapshot of an AIDL interface (or parcelable). Do not try to -// edit this file. It looks like you are doing that because you have modified -// an AIDL interface in a backward-incompatible way, e.g., deleting a function -// from an interface or a field from a parcelable and it broke the build. That -// breakage is intended. +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. // -// You must not make a backward incompatible changes to the AIDL files built +// You must not make a backward incompatible change to any AIDL file built // with the aidl_interface module type with versions property set. The module // type is used to build AIDL files in a way that they can be used across // independently updatable components of the system. If a device is shipped diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorManager.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorManager.aidl new file mode 100644 index 0000000000000000000000000000000000000000..290c68d8777c496fcfd4f8becdaf8d29ce282f99 --- /dev/null +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorManager.aidl @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.vibrator; +@VintfStability +interface IVibratorManager { + int getCapabilities(); + int[] getVibratorIds(); + android.hardware.vibrator.IVibrator getVibrator(in int vibratorId); + void prepareSynced(in int[] vibratorIds); + void triggerSynced(in android.hardware.vibrator.IVibratorCallback callback); + void cancelSynced(); + const int CAP_SYNC = 1; + const int CAP_PREPARE_ON = 2; + const int CAP_PREPARE_PERFORM = 4; + const int CAP_PREPARE_COMPOSE = 8; + const int CAP_MIXED_TRIGGER_ON = 16; + const int CAP_MIXED_TRIGGER_PERFORM = 32; + const int CAP_MIXED_TRIGGER_COMPOSE = 64; + const int CAP_TRIGGER_CALLBACK = 128; +} diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PrimitivePwle.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PrimitivePwle.aidl new file mode 100644 index 0000000000000000000000000000000000000000..584bcf4a4746779ebd782258aa69ee433df460ec --- /dev/null +++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PrimitivePwle.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.vibrator; +@VintfStability +union PrimitivePwle { + android.hardware.vibrator.ActivePwle active; + android.hardware.vibrator.BrakingPwle braking; +} diff --git a/vibrator/aidl/android/hardware/vibrator/ActivePwle.aidl b/vibrator/aidl/android/hardware/vibrator/ActivePwle.aidl new file mode 100644 index 0000000000000000000000000000000000000000..6757476e01d74ff0f588a8b8e7c56111e07fda1e --- /dev/null +++ b/vibrator/aidl/android/hardware/vibrator/ActivePwle.aidl @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.vibrator; + +@VintfStability +parcelable ActivePwle { + /** + * Amplitude ranging from 0.0 (inclusive) to 1.0 (inclusive) + * in units of output acceleration amplitude, not voltage amplitude. + * + * Values should fall within the range of 0.0 (inclusive) to the maximum defined + * by the corresponding entries in IVibrator#getBandwidthAmplitudeMap (inclusive). + * If startFrequency falls between two entries, the value will not exceed the + * largest amplitude of the two bounding frequencies. + * + * 0.0 represents no output acceleration amplitude + * 1.0 represents maximum output acceleration amplitude + * across all supported frequencies + */ + float startAmplitude; + + /** + * Absolute frequency point in the units of hertz + * + * Values are within the continuous inclusive frequency range defined by + * IVibrator#getBandwidthAmplitudeMap, and not limited by the + * IVibrator#getFrequencyResolution. + */ + float startFrequency; + + /** + * Amplitude ranging from 0.0 (inclusive) to 1.0 (inclusive) + * in units of output acceleration amplitude, not voltage amplitude. + * + * Values should fall within the range of 0.0 (inclusive) to the maximum defined + * by the corresponding entries in IVibrator#getBandwidthAmplitudeMap (inclusive). + * If endFrequency falls between two entries, the value will not exceed the + * largest amplitude of the two bounding frequencies. + * + * 0.0 represents no output acceleration amplitude + * 1.0 represents maximum output acceleration amplitude + * across all supported frequencies + */ + float endAmplitude; + + /** + * Absolute frequency point in the units of hertz + * + * Values are within the continuous inclusive frequency range defined by + * IVibrator#getBandwidthAmplitudeMap, and not limited by the + * IVibrator#getFrequencyResolution. + */ + float endFrequency; + + /** + * Total duration from start point to end point in the units of milliseconds + */ + int duration; +} diff --git a/vibrator/aidl/android/hardware/vibrator/Braking.aidl b/vibrator/aidl/android/hardware/vibrator/Braking.aidl new file mode 100644 index 0000000000000000000000000000000000000000..2bc51db3f6fe8e056e5091a3c4703aa17fd25096 --- /dev/null +++ b/vibrator/aidl/android/hardware/vibrator/Braking.aidl @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.vibrator; + +@VintfStability +@Backing(type="int") +enum Braking { + /** + * No braking mechanism used. + * This is the default if the hardware does not support any braking mechanism. + */ + NONE, + /** + * Closed-loop active braking. + * + * This effect should produce a sharp, crisp end to the waveform + * Support is optional. + */ + CLAB, +} diff --git a/vibrator/aidl/android/hardware/vibrator/BrakingPwle.aidl b/vibrator/aidl/android/hardware/vibrator/BrakingPwle.aidl new file mode 100644 index 0000000000000000000000000000000000000000..00675ed0fcc78cb0f66cbdb88b75bd5bb68fce4b --- /dev/null +++ b/vibrator/aidl/android/hardware/vibrator/BrakingPwle.aidl @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.vibrator; + +import android.hardware.vibrator.Braking; + +/** + * BrakingPwle is defined as a segment of zero output acceleration amplitude of duration length. + * + * There should be no output acceleration and the vibrator should be off for the entire duration. + * If the hardware supports braking mechanism(s), they can be set here. + */ +@VintfStability +parcelable BrakingPwle { + /** + * Braking mechanism applied to adjacent segments + */ + Braking braking; + /** + * Total duration of zero output acceleration in the units of milliseconds. + */ + int duration; +} diff --git a/vibrator/aidl/android/hardware/vibrator/CompositePrimitive.aidl b/vibrator/aidl/android/hardware/vibrator/CompositePrimitive.aidl index 8e82db076b1e2baedb6d55b71f0bed6a910d1a31..531489824bed3560e2bcc573b7acaed8aa9bdb0d 100644 --- a/vibrator/aidl/android/hardware/vibrator/CompositePrimitive.aidl +++ b/vibrator/aidl/android/hardware/vibrator/CompositePrimitive.aidl @@ -70,4 +70,11 @@ enum CompositePrimitive { * Support is required. */ LIGHT_TICK, + /** + * This very short low frequency effect should produce a light crisp sensation intended + * to be used repetitively for dynamic feedback. + * + * Support is required. + */ + LOW_TICK, } diff --git a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl index cd7b60340cdf0566b356bba605d3fe8be6dfb822..b4e7e44fe0f4b128d53b32ab37f0107aa2d0a3d1 100644 --- a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl +++ b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl @@ -17,10 +17,12 @@ package android.hardware.vibrator; import android.hardware.vibrator.IVibratorCallback; +import android.hardware.vibrator.Braking; import android.hardware.vibrator.Effect; import android.hardware.vibrator.EffectStrength; import android.hardware.vibrator.CompositeEffect; import android.hardware.vibrator.CompositePrimitive; +import android.hardware.vibrator.PrimitivePwle; @VintfStability interface IVibrator { @@ -52,6 +54,22 @@ interface IVibrator { * Whether alwaysOnEnable/alwaysOnDisable is supported. */ const int CAP_ALWAYS_ON_CONTROL = 1 << 6; + /** + * Whether getResonantFrequency is supported. + */ + const int CAP_GET_RESONANT_FREQUENCY = 1 << 7; + /** + * Whether getQFactor is supported. + */ + const int CAP_GET_Q_FACTOR = 1 << 8; + /** + * Whether frequency control is supported. + */ + const int CAP_FREQUENCY_CONTROL = 1 << 9; + /** + * Whether composePwle is supported. + */ + const int CAP_COMPOSE_PWLE_EFFECTS = 1 << 10; /** * Determine capabilities of the vibrator HAL (CAP_* mask) @@ -230,4 +248,115 @@ interface IVibrator { * @param id The device-specific always-on source ID to disable. */ void alwaysOnDisable(in int id); + + /** + * Retrieve the measured resonant frequency of the actuator. + * + * This may not be supported and this support is reflected in + * getCapabilities (CAP_GET_RESONANT_FREQUENCY) + * + * @return Measured resonant frequency in Hz. Non-zero value if supported, + * or value should be ignored if not supported. + */ + float getResonantFrequency(); + + /** + * Retrieve the measured Q factor. + * + * This may not be supported and this support is reflected in + * getCapabilities (CAP_GET_Q_FACTOR) + * + * @return Measured Q factor. Non-zero value if supported, or value should be + * ignored if not supported. + */ + float getQFactor(); + + /** + * Retrieve the frequency resolution used in getBandwidthAmplitudeMap() in units of hertz + * + * This may not be supported and this support is reflected in + * getCapabilities (CAP_FREQUENCY_CONTROL). + * + * @return The frequency resolution of the bandwidth amplitude map. + * Non-zero value if supported, or value should be ignored if not supported. + */ + float getFrequencyResolution(); + + /** + * Retrieve the minimum allowed frequency in units of hertz + * + * This may not be supported and this support is reflected in + * getCapabilities (CAP_FREQUENCY_CONTROL). + * + * @return The minimum frequency allowed. Non-zero value if supported, + * or value should be ignored if not supported. + */ + float getFrequencyMinimum(); + + /** + * Retrieve the output acceleration amplitude values per frequency supported + * + * This may not be supported and this support is reflected in + * getCapabilities (CAP_FREQUENCY_CONTROL). + * + * The mapping is represented as a list of amplitude values in the inclusive range [0.0, 1.0]. + * The first value represents the amplitude at the frequency returned by getFrequencyMinimum(). + * Each subsequent element is the amplitude at the next supported frequency, in increments + * of getFrequencyResolution(). The value returned by getResonantFrequency() must be + * represented in the returned list. + * + * The amplitude values represent the maximum output acceleration amplitude supported for each + * given frequency. Equal amplitude values for different frequencies represent equal output + * accelerations. + * + * @return The maximum output acceleration amplitude for each supported frequency, + * starting at getMinimumFrequency() + */ + float[] getBandwidthAmplitudeMap(); + + /** + * Retrieve the maximum duration allowed for any primitive PWLE in units of milliseconds. + * + * This may not be supported and this support is reflected in + * getCapabilities (CAP_COMPOSE_PWLE_EFFECTS). + * + * @return The maximum duration allowed for a single PrimitivePwle. + * Non-zero value if supported, or value should be ignored if not supported. + */ + int getPwlePrimitiveDurationMax(); + + /** + * Retrieve the maximum count for allowed PWLEs in one composition. + * + * This may not be supported and this support is reflected in + * getCapabilities (CAP_COMPOSE_PWLE_EFFECTS). + * + * @return The maximum count allowed. Non-zero value if supported, + * or value should be ignored if not supported. + */ + int getPwleCompositionSizeMax(); + + /** + * List of supported braking mechanism. + * + * This may not be supported and this support is reflected in + * getCapabilities (CAP_COMPOSE_PWLE_EFFECTS). + * Implementations are optional but encouraged if available. + * + * @return The braking mechanisms which are supported by the composePwle API. + */ + Braking[] getSupportedBraking(); + + /** + * Fire off a string of PWLEs. + * + * This may not be supported and this support is reflected in + * getCapabilities (CAP_COMPOSE_PWLE_EFFECTS). + * + * Doing this operation while the vibrator is already on is undefined behavior. Clients should + * explicitly call off. IVibratorCallback.onComplete() support is required for this API. + * + * @param composite Array of PWLEs. + */ + void composePwle(in PrimitivePwle[] composite, in IVibratorCallback callback); } diff --git a/vibrator/aidl/android/hardware/vibrator/IVibratorManager.aidl b/vibrator/aidl/android/hardware/vibrator/IVibratorManager.aidl new file mode 100644 index 0000000000000000000000000000000000000000..eb5e9ccd3f20192f32b3ec1fca0e33ce003f92e6 --- /dev/null +++ b/vibrator/aidl/android/hardware/vibrator/IVibratorManager.aidl @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.vibrator; + +import android.hardware.vibrator.IVibrator; +import android.hardware.vibrator.IVibratorCallback; + +@VintfStability +interface IVibratorManager { + /** + * Whether prepare/trigger synced are supported. + */ + const int CAP_SYNC = 1 << 0; + /** + * Whether IVibrator 'on' can be used with 'prepareSynced' function. + */ + const int CAP_PREPARE_ON = 1 << 1; + /** + * Whether IVibrator 'perform' can be used with 'prepareSynced' function. + */ + const int CAP_PREPARE_PERFORM = 1 << 2; + /** + * Whether IVibrator 'compose' can be used with 'prepareSynced' function. + */ + const int CAP_PREPARE_COMPOSE = 1 << 3; + /** + * Whether IVibrator 'on' can be triggered with other functions in sync with 'triggerSynced'. + */ + const int CAP_MIXED_TRIGGER_ON = 1 << 4; + /** + * Whether IVibrator 'perform' can be triggered with other functions in sync with 'triggerSynced'. + */ + const int CAP_MIXED_TRIGGER_PERFORM = 1 << 5; + /** + * Whether IVibrator 'compose' can be triggered with other functions in sync with 'triggerSynced'. + */ + const int CAP_MIXED_TRIGGER_COMPOSE = 1 << 6; + /** + * Whether on w/ IVibratorCallback can be used w/ 'trigerSynced' function. + */ + const int CAP_TRIGGER_CALLBACK = 1 << 7; + + /** + * Determine capabilities of the vibrator manager HAL (CAP_* mask) + */ + int getCapabilities(); + + /** + * List the id of available vibrators. This result should be static and not change. + */ + int[] getVibratorIds(); + + /** + * Return an available vibrator identified with given id. + */ + IVibrator getVibrator(in int vibratorId); + + /** + * Start preparation for a synced vibration + * + * This function must only be called after the previous synced vibration was triggered or + * canceled (through cancelSynced()). + * + * Doing this operation while any of the specified vibrators is already on is undefined behavior. + * Clients should explicitly call off in each vibrator. + * + * @param vibratorIds ids of the vibrators to play vibrations in sync. + */ + void prepareSynced(in int[] vibratorIds); + + /** + * Trigger a prepared synced vibration + * + * Trigger a previously-started preparation for synced vibration, if any. + * A callback is only expected to be supported when getCapabilities CAP_TRIGGER_CALLBACK + * is specified. + * + * @param callback A callback used to inform Frameworks of state change, if supported. + */ + void triggerSynced(in IVibratorCallback callback); + + /** + * Cancel preparation of synced vibration + * + * Cancel a previously-started preparation for synced vibration, if any. + */ + void cancelSynced(); +} diff --git a/vibrator/aidl/android/hardware/vibrator/PrimitivePwle.aidl b/vibrator/aidl/android/hardware/vibrator/PrimitivePwle.aidl new file mode 100644 index 0000000000000000000000000000000000000000..813c7dcb335b15e1d54134fee53de4fb2777e91a --- /dev/null +++ b/vibrator/aidl/android/hardware/vibrator/PrimitivePwle.aidl @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.vibrator; + +import android.hardware.vibrator.ActivePwle; +import android.hardware.vibrator.BrakingPwle; + +@VintfStability +union PrimitivePwle { + ActivePwle active; + BrakingPwle braking; +} diff --git a/vibrator/aidl/default/Android.bp b/vibrator/aidl/default/Android.bp index bedc94d7f2da801341a698591606b332e8fb92e6..2e12dfb2dde6f5e9945557e3c1526be735aa6772 100644 --- a/vibrator/aidl/default/Android.bp +++ b/vibrator/aidl/default/Android.bp @@ -13,10 +13,13 @@ cc_library_static { shared_libs: [ "libbase", "libbinder_ndk", - "android.hardware.vibrator-V1-ndk", + "android.hardware.vibrator-V2-ndk", ], export_include_dirs: ["include"], - srcs: ["Vibrator.cpp"], + srcs: [ + "Vibrator.cpp", + "VibratorManager.cpp", + ], visibility: [ ":__subpackages__", "//hardware/interfaces/tests/extension/vibrator:__subpackages__", @@ -37,7 +40,7 @@ cc_binary { shared_libs: [ "libbase", "libbinder_ndk", - "android.hardware.vibrator-V1-ndk", + "android.hardware.vibrator-V2-ndk", ], static_libs: [ "libvibratorexampleimpl", diff --git a/vibrator/aidl/default/Vibrator.cpp b/vibrator/aidl/default/Vibrator.cpp index 322833b395ab6b93d12f03af8086f1427d5fb901..5755ce55b60d85b9cdf480c1eb87a76efa6af563 100644 --- a/vibrator/aidl/default/Vibrator.cpp +++ b/vibrator/aidl/default/Vibrator.cpp @@ -26,13 +26,25 @@ namespace vibrator { static constexpr int32_t kComposeDelayMaxMs = 1000; static constexpr int32_t kComposeSizeMax = 256; +static constexpr int32_t kComposePwleSizeMax = 127; + +static constexpr float kResonantFrequency = 150.0; +static constexpr float kQFactor = 11.0; +static constexpr int32_t COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS = 16383; +static constexpr float PWLE_LEVEL_MIN = 0.0; +static constexpr float PWLE_LEVEL_MAX = 0.98256; +static constexpr float PWLE_FREQUENCY_RESOLUTION_HZ = 1.0; +static constexpr float PWLE_FREQUENCY_MIN_HZ = 140.0; +static constexpr float PWLE_FREQUENCY_MAX_HZ = 160.0; ndk::ScopedAStatus Vibrator::getCapabilities(int32_t* _aidl_return) { LOG(INFO) << "Vibrator reporting capabilities"; *_aidl_return = IVibrator::CAP_ON_CALLBACK | IVibrator::CAP_PERFORM_CALLBACK | IVibrator::CAP_AMPLITUDE_CONTROL | IVibrator::CAP_EXTERNAL_CONTROL | IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL | IVibrator::CAP_COMPOSE_EFFECTS | - IVibrator::CAP_ALWAYS_ON_CONTROL; + IVibrator::CAP_ALWAYS_ON_CONTROL | IVibrator::CAP_GET_RESONANT_FREQUENCY | + IVibrator::CAP_GET_Q_FACTOR | IVibrator::CAP_FREQUENCY_CONTROL | + IVibrator::CAP_COMPOSE_PWLE_EFFECTS; return ndk::ScopedAStatus::ok(); } @@ -119,6 +131,7 @@ ndk::ScopedAStatus Vibrator::getSupportedPrimitives(std::vector *_aidl_return) { + // A valid array should be of size: + // (PWLE_FREQUENCY_MAX_HZ - PWLE_FREQUENCY_MIN_HZ) / PWLE_FREQUENCY_RESOLUTION_HZ + *_aidl_return = {0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.10, + 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.20}; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Vibrator::getPwlePrimitiveDurationMax(int32_t *durationMs) { + *durationMs = COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Vibrator::getPwleCompositionSizeMax(int32_t *maxSize) { + *maxSize = kComposePwleSizeMax; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Vibrator::getSupportedBraking(std::vector *supported) { + *supported = { + Braking::NONE, + Braking::CLAB, + }; + return ndk::ScopedAStatus::ok(); +} + +void resetPreviousEndAmplitudeEndFrequency(float &prevEndAmplitude, float &prevEndFrequency) { + const float reset = -1.0; + prevEndAmplitude = reset; + prevEndFrequency = reset; +} + +void incrementIndex(int &index) { + index += 1; +} + +void constructActiveDefaults(std::ostringstream &pwleBuilder, const int &segmentIdx) { + pwleBuilder << ",C" << segmentIdx << ":1"; + pwleBuilder << ",B" << segmentIdx << ":0"; + pwleBuilder << ",AR" << segmentIdx << ":0"; + pwleBuilder << ",V" << segmentIdx << ":0"; +} + +void constructActiveSegment(std::ostringstream &pwleBuilder, const int &segmentIdx, int duration, + float amplitude, float frequency) { + pwleBuilder << ",T" << segmentIdx << ":" << duration; + pwleBuilder << ",L" << segmentIdx << ":" << amplitude; + pwleBuilder << ",F" << segmentIdx << ":" << frequency; + constructActiveDefaults(pwleBuilder, segmentIdx); +} + +void constructBrakingSegment(std::ostringstream &pwleBuilder, const int &segmentIdx, int duration, + Braking brakingType) { + pwleBuilder << ",T" << segmentIdx << ":" << duration; + pwleBuilder << ",L" << segmentIdx << ":" << 0; + pwleBuilder << ",F" << segmentIdx << ":" << 0; + pwleBuilder << ",C" << segmentIdx << ":0"; + pwleBuilder << ",B" << segmentIdx << ":" + << static_cast::type>(brakingType); + pwleBuilder << ",AR" << segmentIdx << ":0"; + pwleBuilder << ",V" << segmentIdx << ":0"; +} + +ndk::ScopedAStatus Vibrator::composePwle(const std::vector &composite, + const std::shared_ptr &callback) { + std::ostringstream pwleBuilder; + std::string pwleQueue; + + int compositionSizeMax; + getPwleCompositionSizeMax(&compositionSizeMax); + if (composite.size() <= 0 || composite.size() > compositionSizeMax) { + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + + float prevEndAmplitude; + float prevEndFrequency; + resetPreviousEndAmplitudeEndFrequency(prevEndAmplitude, prevEndFrequency); + + int segmentIdx = 0; + uint32_t totalDuration = 0; + + pwleBuilder << "S:0,WF:4,RP:0,WT:0"; + + for (auto &e : composite) { + switch (e.getTag()) { + case PrimitivePwle::active: { + auto active = e.get(); + if (active.duration < 0 || + active.duration > COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS) { + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + if (active.startAmplitude < PWLE_LEVEL_MIN || + active.startAmplitude > PWLE_LEVEL_MAX || + active.endAmplitude < PWLE_LEVEL_MIN || active.endAmplitude > PWLE_LEVEL_MAX) { + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + if (active.startFrequency < PWLE_FREQUENCY_MIN_HZ || + active.startFrequency > PWLE_FREQUENCY_MAX_HZ || + active.endFrequency < PWLE_FREQUENCY_MIN_HZ || + active.endFrequency > PWLE_FREQUENCY_MAX_HZ) { + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + + if (!((active.startAmplitude == prevEndAmplitude) && + (active.startFrequency == prevEndFrequency))) { + constructActiveSegment(pwleBuilder, segmentIdx, 0, active.startAmplitude, + active.startFrequency); + incrementIndex(segmentIdx); + } + + constructActiveSegment(pwleBuilder, segmentIdx, active.duration, + active.endAmplitude, active.endFrequency); + incrementIndex(segmentIdx); + + prevEndAmplitude = active.endAmplitude; + prevEndFrequency = active.endFrequency; + totalDuration += active.duration; + break; + } + case PrimitivePwle::braking: { + auto braking = e.get(); + if (braking.braking > Braking::CLAB) { + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + if (braking.duration > COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS) { + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + + constructBrakingSegment(pwleBuilder, segmentIdx, 0, braking.braking); + incrementIndex(segmentIdx); + + constructBrakingSegment(pwleBuilder, segmentIdx, braking.duration, braking.braking); + incrementIndex(segmentIdx); + + resetPreviousEndAmplitudeEndFrequency(prevEndAmplitude, prevEndFrequency); + totalDuration += braking.duration; + break; + } + } + } + + std::thread([=] { + LOG(INFO) << "Starting composePwle on another thread"; + usleep(totalDuration * 1000); + if (callback != nullptr) { + LOG(INFO) << "Notifying compose PWLE complete"; + callback->onComplete(); + } + }).detach(); + + return ndk::ScopedAStatus::ok(); +} + } // namespace vibrator } // namespace hardware } // namespace android diff --git a/vibrator/aidl/default/VibratorManager.cpp b/vibrator/aidl/default/VibratorManager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7cf9e6a5d8b652c2f2d65457d0ea28520175f71d --- /dev/null +++ b/vibrator/aidl/default/VibratorManager.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "vibrator-impl/VibratorManager.h" + +#include +#include + +namespace aidl { +namespace android { +namespace hardware { +namespace vibrator { + +static constexpr int32_t kDefaultVibratorId = 1; + +ndk::ScopedAStatus VibratorManager::getCapabilities(int32_t* _aidl_return) { + LOG(INFO) << "Vibrator manager reporting capabilities"; + *_aidl_return = + IVibratorManager::CAP_SYNC | IVibratorManager::CAP_PREPARE_ON | + IVibratorManager::CAP_PREPARE_PERFORM | IVibratorManager::CAP_PREPARE_COMPOSE | + IVibratorManager::CAP_MIXED_TRIGGER_ON | IVibratorManager::CAP_MIXED_TRIGGER_PERFORM | + IVibratorManager::CAP_MIXED_TRIGGER_COMPOSE | IVibratorManager::CAP_TRIGGER_CALLBACK; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus VibratorManager::getVibratorIds(std::vector* _aidl_return) { + LOG(INFO) << "Vibrator manager getting vibrator ids"; + *_aidl_return = {kDefaultVibratorId}; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus VibratorManager::getVibrator(int32_t vibratorId, + std::shared_ptr* _aidl_return) { + LOG(INFO) << "Vibrator manager getting vibrator " << vibratorId; + if (vibratorId == kDefaultVibratorId) { + *_aidl_return = mDefaultVibrator; + return ndk::ScopedAStatus::ok(); + } else { + *_aidl_return = nullptr; + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } +} + +ndk::ScopedAStatus VibratorManager::prepareSynced(const std::vector& vibratorIds) { + LOG(INFO) << "Vibrator Manager prepare synced"; + if (vibratorIds.size() == 1 && vibratorIds[0] == kDefaultVibratorId) { + return ndk::ScopedAStatus::ok(); + } else { + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } +} + +ndk::ScopedAStatus VibratorManager::triggerSynced( + const std::shared_ptr& callback) { + LOG(INFO) << "Vibrator Manager trigger synced"; + std::thread([=] { + if (callback != nullptr) { + LOG(INFO) << "Notifying perform complete"; + callback->onComplete(); + } + }).detach(); + + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus VibratorManager::cancelSynced() { + LOG(INFO) << "Vibrator Manager cancel synced"; + return ndk::ScopedAStatus::ok(); +} + +} // namespace vibrator +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/vibrator/aidl/default/android.hardware.vibrator.xml b/vibrator/aidl/default/android.hardware.vibrator.xml index 49b11ec8da56c647dcd018ba8213454f402149a0..b5bd3ddd1ed6a196e0ffc50888112064f24f3aab 100644 --- a/vibrator/aidl/default/android.hardware.vibrator.xml +++ b/vibrator/aidl/default/android.hardware.vibrator.xml @@ -1,6 +1,12 @@ android.hardware.vibrator + 2 IVibrator/default + + android.hardware.vibrator + 2 + IVibratorManager/default + diff --git a/vibrator/aidl/default/include/vibrator-impl/Vibrator.h b/vibrator/aidl/default/include/vibrator-impl/Vibrator.h index c3f36168762c229350ba25c6e5d53a4394580f5d..4203bf212c0093be9b615a77b4453f43dd457497 100644 --- a/vibrator/aidl/default/include/vibrator-impl/Vibrator.h +++ b/vibrator/aidl/default/include/vibrator-impl/Vibrator.h @@ -44,6 +44,17 @@ class Vibrator : public BnVibrator { ndk::ScopedAStatus getSupportedAlwaysOnEffects(std::vector* _aidl_return) override; ndk::ScopedAStatus alwaysOnEnable(int32_t id, Effect effect, EffectStrength strength) override; ndk::ScopedAStatus alwaysOnDisable(int32_t id) override; + ndk::ScopedAStatus getResonantFrequency(float *resonantFreqHz) override; + ndk::ScopedAStatus getQFactor(float *qFactor) override; + ndk::ScopedAStatus getFrequencyResolution(float *freqResolutionHz) override; + ndk::ScopedAStatus getFrequencyMinimum(float *freqMinimumHz) override; + ndk::ScopedAStatus getBandwidthAmplitudeMap(std::vector *_aidl_return) override; + ndk::ScopedAStatus getPwlePrimitiveDurationMax(int32_t *durationMs) override; + ndk::ScopedAStatus getPwleCompositionSizeMax(int32_t *maxSize) override; + ndk::ScopedAStatus getSupportedBraking(std::vector* supported) override; + ndk::ScopedAStatus composePwle(const std::vector &composite, + const std::shared_ptr &callback) override; + }; } // namespace vibrator diff --git a/vibrator/aidl/default/include/vibrator-impl/VibratorManager.h b/vibrator/aidl/default/include/vibrator-impl/VibratorManager.h new file mode 100644 index 0000000000000000000000000000000000000000..319eb05c1f9495eafcf881aa1ce388b9d4582ad8 --- /dev/null +++ b/vibrator/aidl/default/include/vibrator-impl/VibratorManager.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +namespace aidl { +namespace android { +namespace hardware { +namespace vibrator { + +class VibratorManager : public BnVibratorManager { + public: + VibratorManager(std::shared_ptr vibrator) : mDefaultVibrator(std::move(vibrator)){}; + ndk::ScopedAStatus getCapabilities(int32_t* _aidl_return) override; + ndk::ScopedAStatus getVibratorIds(std::vector* _aidl_return) override; + ndk::ScopedAStatus getVibrator(int32_t vibratorId, + std::shared_ptr* _aidl_return) override; + ndk::ScopedAStatus prepareSynced(const std::vector& vibratorIds) override; + ndk::ScopedAStatus triggerSynced(const std::shared_ptr& callback) override; + ndk::ScopedAStatus cancelSynced() override; + + private: + std::shared_ptr mDefaultVibrator; +}; + +} // namespace vibrator +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/vibrator/aidl/default/main.cpp b/vibrator/aidl/default/main.cpp index ebb0905a3a4c81d51d5d60b7cd499d94cb9047e8..bd834d2a2115be94cb0f06e278956f8a87c79d3c 100644 --- a/vibrator/aidl/default/main.cpp +++ b/vibrator/aidl/default/main.cpp @@ -15,19 +15,29 @@ */ #include "vibrator-impl/Vibrator.h" +#include "vibrator-impl/VibratorManager.h" #include #include #include using aidl::android::hardware::vibrator::Vibrator; +using aidl::android::hardware::vibrator::VibratorManager; int main() { ABinderProcess_setThreadPoolMaxThreadCount(0); - std::shared_ptr vib = ndk::SharedRefBase::make(); - const std::string instance = std::string() + Vibrator::descriptor + "/default"; - binder_status_t status = AServiceManager_addService(vib->asBinder().get(), instance.c_str()); + // make a default vibrator service + auto vib = ndk::SharedRefBase::make(); + const std::string vibName = std::string() + Vibrator::descriptor + "/default"; + binder_status_t status = AServiceManager_addService(vib->asBinder().get(), vibName.c_str()); + CHECK(status == STATUS_OK); + + // make the vibrator manager service with a different vibrator + auto managedVib = ndk::SharedRefBase::make(); + auto vibManager = ndk::SharedRefBase::make(std::move(managedVib)); + const std::string vibManagerName = std::string() + VibratorManager::descriptor + "/default"; + status = AServiceManager_addService(vibManager->asBinder().get(), vibManagerName.c_str()); CHECK(status == STATUS_OK); ABinderProcess_joinThreadPool(); diff --git a/vibrator/aidl/vts/Android.bp b/vibrator/aidl/vts/Android.bp index 1b6e56d06852ad2bb2190c0abdfebd2cb9c729fd..3f328fa736682407b6e354c3987494b7023e562b 100644 --- a/vibrator/aidl/vts/Android.bp +++ b/vibrator/aidl/vts/Android.bp @@ -18,7 +18,26 @@ cc_test { "libbinder", ], static_libs: [ - "android.hardware.vibrator-V1-cpp", + "android.hardware.vibrator-V2-cpp", + ], + test_suites: [ + "general-tests", + "vts", + ], +} + +cc_test { + name: "VtsHalVibratorManagerTargetTest", + defaults: [ + "VtsHalTargetTestDefaults", + "use_libaidlvintf_gtest_helper_static", + ], + srcs: ["VtsHalVibratorManagerTargetTest.cpp"], + shared_libs: [ + "libbinder", + ], + static_libs: [ + "android.hardware.vibrator-V2-cpp", ], test_suites: [ "general-tests", diff --git a/vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..44fa3be7aba2bf8c7b1f0445f41d431d8a218d33 --- /dev/null +++ b/vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +using android::ProcessState; +using android::sp; +using android::String16; +using android::binder::Status; +using android::hardware::vibrator::BnVibratorCallback; +using android::hardware::vibrator::CompositeEffect; +using android::hardware::vibrator::CompositePrimitive; +using android::hardware::vibrator::Effect; +using android::hardware::vibrator::EffectStrength; +using android::hardware::vibrator::IVibrator; +using android::hardware::vibrator::IVibratorManager; +using std::chrono::high_resolution_clock; + +const std::vector kEffects{android::enum_range().begin(), + android::enum_range().end()}; +const std::vector kEffectStrengths{android::enum_range().begin(), + android::enum_range().end()}; +const std::vector kPrimitives{android::enum_range().begin(), + android::enum_range().end()}; + +class CompletionCallback : public BnVibratorCallback { + public: + CompletionCallback(const std::function& callback) : mCallback(callback) {} + Status onComplete() override { + mCallback(); + return Status::ok(); + } + + private: + std::function mCallback; +}; + +class VibratorAidl : public testing::TestWithParam { + public: + virtual void SetUp() override { + manager = android::waitForDeclaredService(String16(GetParam().c_str())); + ASSERT_NE(manager, nullptr); + ASSERT_TRUE(manager->getCapabilities(&capabilities).isOk()); + EXPECT_TRUE(manager->getVibratorIds(&vibratorIds).isOk()); + } + + sp manager; + int32_t capabilities; + std::vector vibratorIds; +}; + +inline bool isUnknownOrUnsupported(Status status) { + return status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION || + status.transactionError() == android::UNKNOWN_TRANSACTION; +} + +TEST_P(VibratorAidl, ValidateExistingVibrators) { + sp vibrator; + for (auto& id : vibratorIds) { + EXPECT_TRUE(manager->getVibrator(id, &vibrator).isOk()); + ASSERT_NE(vibrator, nullptr); + } +} + +TEST_P(VibratorAidl, GetVibratorWithInvalidId) { + int32_t invalidId = *max_element(vibratorIds.begin(), vibratorIds.end()) + 1; + sp vibrator; + EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, + manager->getVibrator(invalidId, &vibrator).exceptionCode()); + ASSERT_EQ(vibrator, nullptr); +} + +TEST_P(VibratorAidl, ValidatePrepareSyncedExistingVibrators) { + if (!(capabilities & IVibratorManager::CAP_SYNC)) return; + if (vibratorIds.empty()) return; + EXPECT_TRUE(manager->prepareSynced(vibratorIds).isOk()); +} + +TEST_P(VibratorAidl, PrepareSyncedEmptySetIsInvalid) { + if (!(capabilities & IVibratorManager::CAP_SYNC)) return; + std::vector emptyIds; + EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, manager->prepareSynced(emptyIds).exceptionCode()); +} + +TEST_P(VibratorAidl, PrepareSyncedNotSupported) { + if (!(capabilities & IVibratorManager::CAP_SYNC)) { + Status status = manager->prepareSynced(vibratorIds); + EXPECT_TRUE(isUnknownOrUnsupported(status)) << status; + } +} + +TEST_P(VibratorAidl, PrepareOnNotSupported) { + if (vibratorIds.empty()) return; + if (!(capabilities & IVibratorManager::CAP_SYNC)) return; + if (!(capabilities & IVibratorManager::CAP_PREPARE_ON)) { + uint32_t durationMs = 250; + EXPECT_TRUE(manager->prepareSynced(vibratorIds).isOk()); + sp vibrator; + for (auto& id : vibratorIds) { + EXPECT_TRUE(manager->getVibrator(id, &vibrator).isOk()); + ASSERT_NE(vibrator, nullptr); + Status status = vibrator->on(durationMs, nullptr); + EXPECT_TRUE(isUnknownOrUnsupported(status)) << status; + } + EXPECT_TRUE(manager->cancelSynced().isOk()); + } +} + +TEST_P(VibratorAidl, PreparePerformNotSupported) { + if (vibratorIds.empty()) return; + if (!(capabilities & IVibratorManager::CAP_SYNC)) return; + if (!(capabilities & IVibratorManager::CAP_PREPARE_ON)) { + EXPECT_TRUE(manager->prepareSynced(vibratorIds).isOk()); + sp vibrator; + for (auto& id : vibratorIds) { + EXPECT_TRUE(manager->getVibrator(id, &vibrator).isOk()); + ASSERT_NE(vibrator, nullptr); + int32_t lengthMs = 0; + Status status = vibrator->perform(kEffects[0], kEffectStrengths[0], nullptr, &lengthMs); + EXPECT_TRUE(isUnknownOrUnsupported(status)) << status; + } + EXPECT_TRUE(manager->cancelSynced().isOk()); + } +} + +TEST_P(VibratorAidl, PrepareComposeNotSupported) { + if (vibratorIds.empty()) return; + if (!(capabilities & IVibratorManager::CAP_SYNC)) return; + if (!(capabilities & IVibratorManager::CAP_PREPARE_ON)) { + std::vector composite; + CompositeEffect effect; + effect.delayMs = 10; + effect.primitive = kPrimitives[0]; + effect.scale = 1.0f; + composite.emplace_back(effect); + + EXPECT_TRUE(manager->prepareSynced(vibratorIds).isOk()); + sp vibrator; + for (auto& id : vibratorIds) { + EXPECT_TRUE(manager->getVibrator(id, &vibrator).isOk()); + ASSERT_NE(vibrator, nullptr); + Status status = vibrator->compose(composite, nullptr); + EXPECT_TRUE(isUnknownOrUnsupported(status)) << status; + } + EXPECT_TRUE(manager->cancelSynced().isOk()); + } +} + +TEST_P(VibratorAidl, TriggerWithCallback) { + if (!(capabilities & IVibratorManager::CAP_SYNC)) return; + if (!(capabilities & IVibratorManager::CAP_PREPARE_ON)) return; + if (!(capabilities & IVibratorManager::CAP_TRIGGER_CALLBACK)) return; + if (vibratorIds.empty()) return; + + std::promise completionPromise; + std::future completionFuture{completionPromise.get_future()}; + sp callback = + new CompletionCallback([&completionPromise] { completionPromise.set_value(); }); + uint32_t durationMs = 250; + std::chrono::milliseconds timeout{durationMs * 2}; + + EXPECT_TRUE(manager->prepareSynced(vibratorIds).isOk()); + sp vibrator; + for (auto& id : vibratorIds) { + EXPECT_TRUE(manager->getVibrator(id, &vibrator).isOk()); + ASSERT_NE(vibrator, nullptr); + EXPECT_TRUE(vibrator->on(durationMs, nullptr).isOk()); + } + + EXPECT_TRUE(manager->triggerSynced(callback).isOk()); + EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready); + EXPECT_TRUE(manager->cancelSynced().isOk()); +} + +TEST_P(VibratorAidl, TriggerSyncNotSupported) { + if (!(capabilities & IVibratorManager::CAP_SYNC)) { + Status status = manager->triggerSynced(nullptr); + EXPECT_TRUE(isUnknownOrUnsupported(status)) << status; + } +} + +TEST_P(VibratorAidl, TriggerCallbackNotSupported) { + if (!(capabilities & IVibratorManager::CAP_SYNC)) return; + if (!(capabilities & IVibratorManager::CAP_TRIGGER_CALLBACK)) { + sp callback = new CompletionCallback([] {}); + EXPECT_TRUE(manager->prepareSynced(vibratorIds).isOk()); + Status status = manager->triggerSynced(callback); + EXPECT_TRUE(isUnknownOrUnsupported(status)) << status; + } +} + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VibratorAidl); +INSTANTIATE_TEST_SUITE_P( + Vibrator, VibratorAidl, + testing::ValuesIn(android::getAidlHalInstanceNames(IVibratorManager::descriptor)), + android::PrintInstanceNameToString); + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + ProcessState::self()->setThreadPoolMaxThreadCount(1); + ProcessState::self()->startThreadPool(); + return RUN_ALL_TESTS(); +} diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp index 4364df2a6c039aea1032ac56c068764bb33d7741..53f8c0ef24243bc65f5c75f74dce5d38a5bad46e 100644 --- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp +++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp @@ -15,9 +15,9 @@ */ #include #include - #include #include +#include #include #include @@ -28,12 +28,17 @@ using android::ProcessState; using android::sp; using android::String16; using android::binder::Status; +using android::hardware::vibrator::ActivePwle; using android::hardware::vibrator::BnVibratorCallback; +using android::hardware::vibrator::Braking; +using android::hardware::vibrator::BrakingPwle; using android::hardware::vibrator::CompositeEffect; using android::hardware::vibrator::CompositePrimitive; using android::hardware::vibrator::Effect; using android::hardware::vibrator::EffectStrength; using android::hardware::vibrator::IVibrator; +using android::hardware::vibrator::IVibratorManager; +using android::hardware::vibrator::PrimitivePwle; using std::chrono::high_resolution_clock; const std::vector kEffects{android::enum_range().begin(), @@ -42,35 +47,33 @@ const std::vector kEffectStrengths{android::enum_range().end()}; const std::vector kInvalidEffects = { - static_cast(static_cast(kEffects.front()) - 1), - static_cast(static_cast(kEffects.back()) + 1), + static_cast(static_cast(kEffects.front()) - 1), + static_cast(static_cast(kEffects.back()) + 1), }; const std::vector kInvalidEffectStrengths = { - static_cast(static_cast(kEffectStrengths.front()) - 1), - static_cast(static_cast(kEffectStrengths.back()) + 1), + static_cast(static_cast(kEffectStrengths.front()) - 1), + static_cast(static_cast(kEffectStrengths.back()) + 1), }; const std::vector kCompositePrimitives{ - android::enum_range().begin(), - android::enum_range().end()}; + android::enum_range().begin(), + android::enum_range().end()}; const std::vector kRequiredPrimitives = { - CompositePrimitive::CLICK, - CompositePrimitive::LIGHT_TICK, - CompositePrimitive::QUICK_RISE, - CompositePrimitive::SLOW_RISE, + CompositePrimitive::CLICK, CompositePrimitive::LIGHT_TICK, + CompositePrimitive::QUICK_RISE, CompositePrimitive::SLOW_RISE, CompositePrimitive::QUICK_FALL, }; const std::vector kInvalidPrimitives = { - static_cast(static_cast(kCompositePrimitives.front()) - 1), - static_cast(static_cast(kCompositePrimitives.back()) + 1), + static_cast(static_cast(kCompositePrimitives.front()) - 1), + static_cast(static_cast(kCompositePrimitives.back()) + 1), }; class CompletionCallback : public BnVibratorCallback { public: - CompletionCallback(const std::function& callback) : mCallback(callback) {} + CompletionCallback(const std::function &callback) : mCallback(callback) {} Status onComplete() override { mCallback(); return Status::ok(); @@ -80,10 +83,28 @@ class CompletionCallback : public BnVibratorCallback { std::function mCallback; }; -class VibratorAidl : public testing::TestWithParam { +class VibratorAidl : public testing::TestWithParam> { public: virtual void SetUp() override { - vibrator = android::waitForDeclaredService(String16(GetParam().c_str())); + int32_t managerIdx = std::get<0>(GetParam()); + int32_t vibratorId = std::get<1>(GetParam()); + auto managerAidlNames = android::getAidlHalInstanceNames(IVibratorManager::descriptor); + + if (managerIdx < 0) { + // Testing a unmanaged vibrator, using vibratorId as index from registered HALs + auto vibratorAidlNames = android::getAidlHalInstanceNames(IVibrator::descriptor); + ASSERT_LT(vibratorId, vibratorAidlNames.size()); + auto vibratorName = String16(vibratorAidlNames[vibratorId].c_str()); + vibrator = android::waitForDeclaredService(vibratorName); + } else { + // Testing a managed vibrator, using vibratorId to retrieve it from the manager + ASSERT_LT(managerIdx, managerAidlNames.size()); + auto managerName = String16(managerAidlNames[managerIdx].c_str()); + auto vibratorManager = android::waitForDeclaredService(managerName); + auto vibratorResult = vibratorManager->getVibrator(vibratorId, &vibrator); + ASSERT_TRUE(vibratorResult.isOk()); + } + ASSERT_NE(vibrator, nullptr); ASSERT_TRUE(vibrator->getCapabilities(&capabilities).isOk()); } @@ -92,6 +113,94 @@ class VibratorAidl : public testing::TestWithParam { int32_t capabilities; }; +inline bool isUnknownOrUnsupported(Status status) { + return status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION || + status.transactionError() == android::UNKNOWN_TRANSACTION; +} + +static float getResonantFrequencyHz(sp vibrator, int32_t capabilities) { + float resonantFrequencyHz; + Status status = vibrator->getResonantFrequency(&resonantFrequencyHz); + if (capabilities & IVibrator::CAP_GET_RESONANT_FREQUENCY) { + EXPECT_GT(resonantFrequencyHz, 0); + EXPECT_EQ(status.exceptionCode(), Status::EX_NONE); + } else { + EXPECT_TRUE(isUnknownOrUnsupported(status)) << status; + } + return resonantFrequencyHz; +} + +static float getFrequencyResolutionHz(sp vibrator, int32_t capabilities) { + float freqResolutionHz; + Status status = vibrator->getFrequencyResolution(&freqResolutionHz); + if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) { + EXPECT_GT(freqResolutionHz, 0); + EXPECT_EQ(status.exceptionCode(), Status::EX_NONE); + } else { + EXPECT_TRUE(isUnknownOrUnsupported(status)) << status; + } + return freqResolutionHz; +} + +static float getFrequencyMinimumHz(sp vibrator, int32_t capabilities) { + float freqMinimumHz; + Status status = vibrator->getFrequencyMinimum(&freqMinimumHz); + if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) { + EXPECT_EQ(status.exceptionCode(), Status::EX_NONE); + + float resonantFrequencyHz = getResonantFrequencyHz(vibrator, capabilities); + + EXPECT_GT(freqMinimumHz, 0); + EXPECT_LE(freqMinimumHz, resonantFrequencyHz); + } else { + EXPECT_TRUE(isUnknownOrUnsupported(status)) << status; + } + return freqMinimumHz; +} + +static float getFrequencyMaximumHz(sp vibrator, int32_t capabilities) { + std::vector bandwidthAmplitudeMap; + Status status = vibrator->getBandwidthAmplitudeMap(&bandwidthAmplitudeMap); + if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) { + EXPECT_EQ(status.exceptionCode(), Status::EX_NONE); + } else { + EXPECT_TRUE(isUnknownOrUnsupported(status)) << status; + } + + float freqMaximumHz = + (bandwidthAmplitudeMap.size() * getFrequencyResolutionHz(vibrator, capabilities)) + + getFrequencyMinimumHz(vibrator, capabilities); + return freqMaximumHz; +} + +static float getAmplitudeMin() { + return 0.0; +} + +static float getAmplitudeMax() { + return 1.0; +} + +static ActivePwle composeValidActivePwle(sp vibrator, int32_t capabilities) { + float frequencyHz; + if (capabilities & IVibrator::CAP_GET_RESONANT_FREQUENCY) { + frequencyHz = getResonantFrequencyHz(vibrator, capabilities); + } else if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) { + frequencyHz = getFrequencyMinimumHz(vibrator, capabilities); + } else { + frequencyHz = 150.0; // default value commonly used + } + + ActivePwle active; + active.startAmplitude = (getAmplitudeMin() + getAmplitudeMax()) / 2; + active.startFrequency = frequencyHz; + active.endAmplitude = (getAmplitudeMin() + getAmplitudeMax()) / 2; + active.endFrequency = frequencyHz; + active.duration = 1000; + + return active; +} + TEST_P(VibratorAidl, OnThenOffBeforeTimeout) { EXPECT_TRUE(vibrator->on(2000, nullptr /*callback*/).isOk()); sleep(1); @@ -99,12 +208,13 @@ TEST_P(VibratorAidl, OnThenOffBeforeTimeout) { } TEST_P(VibratorAidl, OnWithCallback) { - if (!(capabilities & IVibrator::CAP_ON_CALLBACK)) return; + if (!(capabilities & IVibrator::CAP_ON_CALLBACK)) + return; std::promise completionPromise; std::future completionFuture{completionPromise.get_future()}; sp callback = - new CompletionCallback([&completionPromise] { completionPromise.set_value(); }); + new CompletionCallback([&completionPromise] { completionPromise.set_value(); }); uint32_t durationMs = 250; std::chrono::milliseconds timeout{durationMs * 2}; EXPECT_TRUE(vibrator->on(durationMs, callback).isOk()); @@ -115,7 +225,8 @@ TEST_P(VibratorAidl, OnWithCallback) { TEST_P(VibratorAidl, OnCallbackNotSupported) { if (!(capabilities & IVibrator::CAP_ON_CALLBACK)) { sp callback = new CompletionCallback([] {}); - EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, vibrator->on(250, callback).exceptionCode()); + Status status = vibrator->on(250, callback); + EXPECT_TRUE(isUnknownOrUnsupported(status)) << status; } } @@ -125,7 +236,7 @@ TEST_P(VibratorAidl, ValidateEffect) { for (Effect effect : kEffects) { bool isEffectSupported = - std::find(supported.begin(), supported.end(), effect) != supported.end(); + std::find(supported.begin(), supported.end(), effect) != supported.end(); for (EffectStrength strength : kEffectStrengths) { int32_t lengthMs = 0; @@ -136,28 +247,29 @@ TEST_P(VibratorAidl, ValidateEffect) { EXPECT_GT(lengthMs, 0); usleep(lengthMs * 1000); } else { - EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION) - << toString(effect) << " " << toString(strength); + EXPECT_TRUE(isUnknownOrUnsupported(status)) + << status << " " << toString(effect) << " " << toString(strength); } } } } TEST_P(VibratorAidl, ValidateEffectWithCallback) { - if (!(capabilities & IVibrator::CAP_PERFORM_CALLBACK)) return; + if (!(capabilities & IVibrator::CAP_PERFORM_CALLBACK)) + return; std::vector supported; ASSERT_TRUE(vibrator->getSupportedEffects(&supported).isOk()); for (Effect effect : kEffects) { bool isEffectSupported = - std::find(supported.begin(), supported.end(), effect) != supported.end(); + std::find(supported.begin(), supported.end(), effect) != supported.end(); for (EffectStrength strength : kEffectStrengths) { std::promise completionPromise; std::future completionFuture{completionPromise.get_future()}; sp callback = - new CompletionCallback([&completionPromise] { completionPromise.set_value(); }); + new CompletionCallback([&completionPromise] { completionPromise.set_value(); }); int lengthMs = 0; Status status = vibrator->perform(effect, strength, callback, &lengthMs); @@ -165,26 +277,30 @@ TEST_P(VibratorAidl, ValidateEffectWithCallback) { EXPECT_TRUE(status.isOk()); EXPECT_GT(lengthMs, 0); } else { - EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION); + EXPECT_TRUE(isUnknownOrUnsupported(status)) << status; } - if (!status.isOk()) continue; + if (!status.isOk()) + continue; - std::chrono::milliseconds timeout{lengthMs * 2}; + //TODO(b/187207798): revert back to conservative timeout values once + //latencies have been fixed + std::chrono::milliseconds timeout{lengthMs * 8}; EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready); } } } TEST_P(VibratorAidl, ValidateEffectWithCallbackNotSupported) { - if (capabilities & IVibrator::CAP_PERFORM_CALLBACK) return; + if (capabilities & IVibrator::CAP_PERFORM_CALLBACK) + return; for (Effect effect : kEffects) { for (EffectStrength strength : kEffectStrengths) { sp callback = new CompletionCallback([] {}); int lengthMs; Status status = vibrator->perform(effect, strength, callback, &lengthMs); - EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, status.exceptionCode()); + EXPECT_TRUE(isUnknownOrUnsupported(status)) << status; } } } @@ -194,16 +310,16 @@ TEST_P(VibratorAidl, InvalidEffectsUnsupported) { for (EffectStrength strength : kEffectStrengths) { int32_t lengthMs; Status status = vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs); - EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION) - << toString(effect) << " " << toString(strength); + EXPECT_TRUE(isUnknownOrUnsupported(status)) + << status << toString(effect) << " " << toString(strength); } } for (Effect effect : kEffects) { for (EffectStrength strength : kInvalidEffectStrengths) { int32_t lengthMs; Status status = vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs); - EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION) - << toString(effect) << " " << toString(strength); + EXPECT_TRUE(isUnknownOrUnsupported(status)) + << status << " " << toString(effect) << " " << toString(strength); } } } @@ -229,7 +345,8 @@ TEST_P(VibratorAidl, AmplitudeOutsideRangeFails) { TEST_P(VibratorAidl, AmplitudeReturnsUnsupportedMatchingCapabilities) { if ((capabilities & IVibrator::CAP_AMPLITUDE_CONTROL) == 0) { - EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, vibrator->setAmplitude(1).exceptionCode()); + Status status = vibrator->setAmplitude(1); + EXPECT_TRUE(isUnknownOrUnsupported(status)) << status; } } @@ -244,7 +361,7 @@ TEST_P(VibratorAidl, ChangeVibrationExternalControl) { TEST_P(VibratorAidl, ExternalAmplitudeControl) { const bool supportsExternalAmplitudeControl = - (capabilities & IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL) > 0; + (capabilities & IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL) > 0; if (capabilities & IVibrator::CAP_EXTERNAL_CONTROL) { EXPECT_TRUE(vibrator->setExternalControl(true).isOk()); @@ -253,7 +370,7 @@ TEST_P(VibratorAidl, ExternalAmplitudeControl) { if (supportsExternalAmplitudeControl) { EXPECT_TRUE(amplitudeStatus.isOk()); } else { - EXPECT_EQ(amplitudeStatus.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION); + EXPECT_TRUE(isUnknownOrUnsupported(amplitudeStatus)) << amplitudeStatus; } EXPECT_TRUE(vibrator->setExternalControl(false).isOk()); } else { @@ -263,8 +380,8 @@ TEST_P(VibratorAidl, ExternalAmplitudeControl) { TEST_P(VibratorAidl, ExternalControlUnsupportedMatchingCapabilities) { if ((capabilities & IVibrator::CAP_EXTERNAL_CONTROL) == 0) { - EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, - vibrator->setExternalControl(true).exceptionCode()); + Status status = vibrator->setExternalControl(true); + EXPECT_TRUE(isUnknownOrUnsupported(status)) << status; } } @@ -276,7 +393,7 @@ TEST_P(VibratorAidl, GetSupportedPrimitives) { for (auto primitive : kCompositePrimitives) { bool isPrimitiveSupported = - std::find(supported.begin(), supported.end(), primitive) != supported.end(); + std::find(supported.begin(), supported.end(), primitive) != supported.end(); bool isPrimitiveRequired = std::find(kRequiredPrimitives.begin(), kRequiredPrimitives.end(), primitive) != kRequiredPrimitives.end(); @@ -293,7 +410,7 @@ TEST_P(VibratorAidl, GetPrimitiveDuration) { for (auto primitive : kCompositePrimitives) { bool isPrimitiveSupported = - std::find(supported.begin(), supported.end(), primitive) != supported.end(); + std::find(supported.begin(), supported.end(), primitive) != supported.end(); int32_t duration; Status status = vibrator->getPrimitiveDuration(primitive, &duration); @@ -301,7 +418,7 @@ TEST_P(VibratorAidl, GetPrimitiveDuration) { if (isPrimitiveSupported) { EXPECT_EQ(Status::EX_NONE, status.exceptionCode()); } else { - EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, status.exceptionCode()); + EXPECT_TRUE(isUnknownOrUnsupported(status)) << status; } } } @@ -349,7 +466,7 @@ TEST_P(VibratorAidl, ComposeUnsupportedPrimitives) { for (auto primitive : kCompositePrimitives) { bool isPrimitiveSupported = - std::find(supported.begin(), supported.end(), primitive) != supported.end(); + std::find(supported.begin(), supported.end(), primitive) != supported.end(); if (!isPrimitiveSupported) { unsupported.push_back(primitive); @@ -359,13 +476,13 @@ TEST_P(VibratorAidl, ComposeUnsupportedPrimitives) { for (auto primitive : unsupported) { std::vector composite(1); - for (auto& effect : composite) { + for (auto &effect : composite) { effect.delayMs = 0; effect.primitive = primitive; effect.scale = 1.0f; } - EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, - vibrator->compose(composite, nullptr).exceptionCode()); + Status status = vibrator->compose(composite, nullptr); + EXPECT_TRUE(isUnknownOrUnsupported(status)) << status; vibrator->off(); } } @@ -374,7 +491,7 @@ TEST_P(VibratorAidl, ComposeUnsupportedPrimitives) { TEST_P(VibratorAidl, ComposeScaleBoundary) { if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) { std::vector composite(1); - CompositeEffect& effect = composite[0]; + CompositeEffect &effect = composite[0]; effect.delayMs = 0; effect.primitive = CompositePrimitive::CLICK; @@ -446,8 +563,6 @@ TEST_P(VibratorAidl, ComposeSizeBoundary) { } TEST_P(VibratorAidl, ComposeCallback) { - constexpr std::chrono::milliseconds allowedLatency{10}; - if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) { std::vector supported; @@ -461,7 +576,7 @@ TEST_P(VibratorAidl, ComposeCallback) { std::promise completionPromise; std::future completionFuture{completionPromise.get_future()}; sp callback = - new CompletionCallback([&completionPromise] { completionPromise.set_value(); }); + new CompletionCallback([&completionPromise] { completionPromise.set_value(); }); CompositeEffect effect; std::vector composite; int32_t durationMs; @@ -476,21 +591,21 @@ TEST_P(VibratorAidl, ComposeCallback) { EXPECT_EQ(Status::EX_NONE, vibrator->getPrimitiveDuration(primitive, &durationMs).exceptionCode()) - << toString(primitive); + << toString(primitive); duration = std::chrono::milliseconds(durationMs); - EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, callback).exceptionCode()) - << toString(primitive); start = high_resolution_clock::now(); + EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, callback).exceptionCode()) + << toString(primitive); - EXPECT_EQ(completionFuture.wait_for(duration + allowedLatency), - std::future_status::ready) - << toString(primitive); + //TODO(b/187207798): revert back to conservative timeout values once + //latencies have been fixed + EXPECT_EQ(completionFuture.wait_for(duration * 4), std::future_status::ready) + << toString(primitive); end = high_resolution_clock::now(); elapsed = std::chrono::duration_cast(end - start); - EXPECT_LE(elapsed.count(), (duration + allowedLatency).count()) << toString(primitive); - EXPECT_GE(elapsed.count(), (duration - allowedLatency).count()) << toString(primitive); + EXPECT_GE(elapsed.count(), duration.count()) << toString(primitive); } } } @@ -502,17 +617,17 @@ TEST_P(VibratorAidl, AlwaysOn) { for (Effect effect : kEffects) { bool isEffectSupported = - std::find(supported.begin(), supported.end(), effect) != supported.end(); + std::find(supported.begin(), supported.end(), effect) != supported.end(); for (EffectStrength strength : kEffectStrengths) { Status status = vibrator->alwaysOnEnable(0, effect, strength); if (isEffectSupported) { EXPECT_EQ(Status::EX_NONE, status.exceptionCode()) - << toString(effect) << " " << toString(strength); + << toString(effect) << " " << toString(strength); } else { - EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, status.exceptionCode()) - << toString(effect) << " " << toString(strength); + EXPECT_TRUE(isUnknownOrUnsupported(status)) + << status << " " << toString(effect) << " " << toString(strength); } } } @@ -521,12 +636,279 @@ TEST_P(VibratorAidl, AlwaysOn) { } } +TEST_P(VibratorAidl, GetResonantFrequency) { + getResonantFrequencyHz(vibrator, capabilities); +} + +TEST_P(VibratorAidl, GetQFactor) { + float qFactor; + Status status = vibrator->getQFactor(&qFactor); + if (capabilities & IVibrator::CAP_GET_Q_FACTOR) { + ASSERT_GT(qFactor, 0); + EXPECT_EQ(status.exceptionCode(), Status::EX_NONE); + } else { + EXPECT_TRUE(isUnknownOrUnsupported(status)) << status; + } +} + +TEST_P(VibratorAidl, GetFrequencyResolution) { + getFrequencyResolutionHz(vibrator, capabilities); +} + +TEST_P(VibratorAidl, GetFrequencyMinimum) { + getFrequencyMinimumHz(vibrator, capabilities); +} + +TEST_P(VibratorAidl, GetBandwidthAmplitudeMap) { + std::vector bandwidthAmplitudeMap; + Status status = vibrator->getBandwidthAmplitudeMap(&bandwidthAmplitudeMap); + if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) { + EXPECT_EQ(status.exceptionCode(), Status::EX_NONE); + ASSERT_FALSE(bandwidthAmplitudeMap.empty()); + + int minMapSize = (getResonantFrequencyHz(vibrator, capabilities) - + getFrequencyMinimumHz(vibrator, capabilities)) / + getFrequencyResolutionHz(vibrator, capabilities); + ASSERT_GT(bandwidthAmplitudeMap.size(), minMapSize); + + for (float e : bandwidthAmplitudeMap) { + ASSERT_GE(e, 0.0); + ASSERT_LE(e, 1.0); + } + } else { + EXPECT_TRUE(isUnknownOrUnsupported(status)) << status; + } +} + +TEST_P(VibratorAidl, GetPwlePrimitiveDurationMax) { + int32_t durationMs; + Status status = vibrator->getPwlePrimitiveDurationMax(&durationMs); + if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) { + ASSERT_NE(durationMs, 0); + EXPECT_EQ(status.exceptionCode(), Status::EX_NONE); + } else { + EXPECT_TRUE(isUnknownOrUnsupported(status)) << status; + } +} + +TEST_P(VibratorAidl, GetPwleCompositionSizeMax) { + int32_t maxSize; + Status status = vibrator->getPwleCompositionSizeMax(&maxSize); + if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) { + ASSERT_NE(maxSize, 0); + EXPECT_EQ(status.exceptionCode(), Status::EX_NONE); + } else { + EXPECT_TRUE(isUnknownOrUnsupported(status)) << status; + } +} + +TEST_P(VibratorAidl, GetSupportedBraking) { + std::vector supported; + Status status = vibrator->getSupportedBraking(&supported); + if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) { + bool isDefaultNoneSupported = + std::find(supported.begin(), supported.end(), Braking::NONE) != supported.end(); + ASSERT_TRUE(isDefaultNoneSupported); + EXPECT_EQ(status.exceptionCode(), Status::EX_NONE); + } else { + EXPECT_TRUE(isUnknownOrUnsupported(status)) << status; + } +} + +TEST_P(VibratorAidl, ComposeValidPwle) { + if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) { + ActivePwle firstActive = composeValidActivePwle(vibrator, capabilities); + + std::vector supported; + ASSERT_TRUE(vibrator->getSupportedBraking(&supported).isOk()); + bool isClabSupported = + std::find(supported.begin(), supported.end(), Braking::CLAB) != supported.end(); + BrakingPwle firstBraking; + firstBraking.braking = isClabSupported ? Braking::CLAB : Braking::NONE; + firstBraking.duration = 100; + + ActivePwle secondActive = composeValidActivePwle(vibrator, capabilities); + if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) { + float minFrequencyHz = getFrequencyMinimumHz(vibrator, capabilities); + float maxFrequencyHz = getFrequencyMaximumHz(vibrator, capabilities); + float freqResolutionHz = getFrequencyResolutionHz(vibrator, capabilities); + secondActive.startFrequency = minFrequencyHz + (freqResolutionHz / 2.0f); + secondActive.endFrequency = maxFrequencyHz - (freqResolutionHz / 3.0f); + } + BrakingPwle secondBraking; + secondBraking.braking = Braking::NONE; + secondBraking.duration = 10; + + auto pwleQueue = + std::vector{firstActive, firstBraking, secondActive, secondBraking}; + + EXPECT_EQ(Status::EX_NONE, vibrator->composePwle(pwleQueue, nullptr).exceptionCode()); + EXPECT_TRUE(vibrator->off().isOk()); + } +} + +TEST_P(VibratorAidl, ComposeValidPwleWithCallback) { + if (!((capabilities & IVibrator::CAP_ON_CALLBACK) && + (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS))) + return; + + std::promise completionPromise; + std::future completionFuture{completionPromise.get_future()}; + sp callback = + new CompletionCallback([&completionPromise] { completionPromise.set_value(); }); + uint32_t durationMs = 2100; // Sum of 2 active and 1 braking below + //TODO(b/187207798): revert back to conservative timeout values once + //latencies have been fixed + std::chrono::milliseconds timeout{durationMs * 4}; + + ActivePwle active = composeValidActivePwle(vibrator, capabilities); + + std::vector supported; + ASSERT_TRUE(vibrator->getSupportedBraking(&supported).isOk()); + bool isClabSupported = + std::find(supported.begin(), supported.end(), Braking::CLAB) != supported.end(); + BrakingPwle braking; + braking.braking = isClabSupported ? Braking::CLAB : Braking::NONE; + braking.duration = 100; + + auto pwleQueue = std::vector{active, braking, active}; + + EXPECT_TRUE(vibrator->composePwle(pwleQueue, callback).isOk()); + EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready); + EXPECT_TRUE(vibrator->off().isOk()); +} + +TEST_P(VibratorAidl, ComposePwleSegmentBoundary) { + if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) { + std::vector pwleQueue; + // test empty queue + EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, + vibrator->composePwle(pwleQueue, nullptr).exceptionCode()); + EXPECT_TRUE(vibrator->off().isOk()); + + ActivePwle active = composeValidActivePwle(vibrator, capabilities); + + PrimitivePwle pwle; + pwle = active; + int segmentCountMax; + vibrator->getPwleCompositionSizeMax(&segmentCountMax); + + // Create PWLE queue with more segments than allowed + for (int i = 0; i < segmentCountMax + 10; i++) { + pwleQueue.emplace_back(std::move(pwle)); + } + + EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, + vibrator->composePwle(pwleQueue, nullptr).exceptionCode()); + EXPECT_TRUE(vibrator->off().isOk()); + } +} + +TEST_P(VibratorAidl, ComposePwleAmplitudeParameterBoundary) { + if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) { + ActivePwle active = composeValidActivePwle(vibrator, capabilities); + active.startAmplitude = getAmplitudeMax() + 1.0; // Amplitude greater than allowed + active.endAmplitude = getAmplitudeMax() + 1.0; // Amplitude greater than allowed + + auto pwleQueueGreater = std::vector{active}; + + EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, + vibrator->composePwle(pwleQueueGreater, nullptr).exceptionCode()); + EXPECT_TRUE(vibrator->off().isOk()); + + active.startAmplitude = getAmplitudeMin() - 1.0; // Amplitude less than allowed + active.endAmplitude = getAmplitudeMin() - 1.0; // Amplitude less than allowed + + auto pwleQueueLess = std::vector{active}; + + EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, + vibrator->composePwle(pwleQueueLess, nullptr).exceptionCode()); + EXPECT_TRUE(vibrator->off().isOk()); + } +} + +TEST_P(VibratorAidl, ComposePwleFrequencyParameterBoundary) { + if ((capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) && + (capabilities & IVibrator::CAP_FREQUENCY_CONTROL)) { + float freqMinimumHz = getFrequencyMinimumHz(vibrator, capabilities); + float freqMaximumHz = getFrequencyMaximumHz(vibrator, capabilities); + float freqResolutionHz = getFrequencyResolutionHz(vibrator, capabilities); + + ActivePwle active = composeValidActivePwle(vibrator, capabilities); + active.startFrequency = + freqMaximumHz + freqResolutionHz; // Frequency greater than allowed + active.endFrequency = freqMaximumHz + freqResolutionHz; // Frequency greater than allowed + + auto pwleQueueGreater = std::vector{active}; + + EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, + vibrator->composePwle(pwleQueueGreater, nullptr).exceptionCode()); + EXPECT_TRUE(vibrator->off().isOk()); + + active.startFrequency = freqMinimumHz - freqResolutionHz; // Frequency less than allowed + active.endFrequency = freqMinimumHz - freqResolutionHz; // Frequency less than allowed + + auto pwleQueueLess = std::vector{active}; + + EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, + vibrator->composePwle(pwleQueueLess, nullptr).exceptionCode()); + EXPECT_TRUE(vibrator->off().isOk()); + } +} + +TEST_P(VibratorAidl, ComposePwleSegmentDurationBoundary) { + if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) { + ActivePwle active = composeValidActivePwle(vibrator, capabilities); + + int segmentDurationMaxMs; + vibrator->getPwlePrimitiveDurationMax(&segmentDurationMaxMs); + active.duration = segmentDurationMaxMs + 10; // Segment duration greater than allowed + + auto pwleQueue = std::vector{active}; + + EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, + vibrator->composePwle(pwleQueue, nullptr).exceptionCode()); + EXPECT_TRUE(vibrator->off().isOk()); + } +} + +std::vector> GenerateVibratorMapping() { + std::vector> tuples; + auto managerAidlNames = android::getAidlHalInstanceNames(IVibratorManager::descriptor); + std::vector vibratorIds; + + for (int i = 0; i < managerAidlNames.size(); i++) { + auto managerName = String16(managerAidlNames[i].c_str()); + auto vibratorManager = android::waitForDeclaredService(managerName); + if (vibratorManager->getVibratorIds(&vibratorIds).isOk()) { + for (auto &vibratorId : vibratorIds) { + tuples.push_back(std::make_tuple(i, vibratorId)); + } + } + } + + auto vibratorAidlNames = android::getAidlHalInstanceNames(IVibrator::descriptor); + for (int i = 0; i < vibratorAidlNames.size(); i++) { + tuples.push_back(std::make_tuple(-1, i)); + } + + return tuples; +} + +std::string PrintGeneratedTest(const testing::TestParamInfo &info) { + const auto &[managerIdx, vibratorId] = info.param; + if (managerIdx < 0) { + return std::string("TOP_LEVEL_VIBRATOR_") + std::to_string(vibratorId); + } + return std::string("MANAGER_") + std::to_string(managerIdx) + "_VIBRATOR_ID_" + + std::to_string(vibratorId); +} + GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VibratorAidl); -INSTANTIATE_TEST_SUITE_P(Vibrator, VibratorAidl, - testing::ValuesIn(android::getAidlHalInstanceNames(IVibrator::descriptor)), - android::PrintInstanceNameToString); +INSTANTIATE_TEST_SUITE_P(Vibrator, VibratorAidl, testing::ValuesIn(GenerateVibratorMapping()), + PrintGeneratedTest); -int main(int argc, char** argv) { +int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); ProcessState::self()->setThreadPoolMaxThreadCount(1); ProcessState::self()->startThreadPool(); diff --git a/vibrator/bench/Android.bp b/vibrator/bench/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..e4c9cfb33dcf758e06a47104c1f23814cca820de --- /dev/null +++ b/vibrator/bench/Android.bp @@ -0,0 +1,43 @@ +// +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_benchmark { + name: "VibratorHalIntegrationBenchmark", + defaults: ["hidl_defaults"], + srcs: [ + "benchmark.cpp", + ], + shared_libs: [ + "android.hardware.vibrator-V1-cpp", + "android.hardware.vibrator@1.0", + "android.hardware.vibrator@1.1", + "android.hardware.vibrator@1.2", + "android.hardware.vibrator@1.3", + "libbinder", + "libhardware", + "libhidlbase", + "libutils", + ], + test_suites: ["device-tests"], +} diff --git a/vibrator/bench/benchmark.cpp b/vibrator/bench/benchmark.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e19dc6f215fbccd0d835f2e4d945432ab600be3d --- /dev/null +++ b/vibrator/bench/benchmark.cpp @@ -0,0 +1,577 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "benchmark/benchmark.h" + +#include +#include +#include +#include + +using ::android::enum_range; +using ::android::sp; +using ::android::hardware::hidl_enum_range; +using ::android::hardware::Return; +using ::android::hardware::details::hidl_enum_values; +using ::benchmark::Counter; +using ::benchmark::Fixture; +using ::benchmark::kMicrosecond; +using ::benchmark::State; +using ::benchmark::internal::Benchmark; +using ::std::chrono::duration; +using ::std::chrono::duration_cast; +using ::std::chrono::high_resolution_clock; + +namespace Aidl = ::android::hardware::vibrator; +namespace V1_0 = ::android::hardware::vibrator::V1_0; +namespace V1_1 = ::android::hardware::vibrator::V1_1; +namespace V1_2 = ::android::hardware::vibrator::V1_2; +namespace V1_3 = ::android::hardware::vibrator::V1_3; + +template +class BaseBench : public Fixture { + public: + void TearDown(State& /*state*/) override { + if (!mVibrator) { + return; + } + mVibrator->off(); + } + + static void DefaultConfig(Benchmark* b) { b->Unit(kMicrosecond); } + + static void DefaultArgs(Benchmark* /*b*/) { /* none */ + } + + protected: + auto getOtherArg(const State& state, std::size_t index) const { return state.range(index + 0); } + + protected: + sp mVibrator; +}; + +template +class VibratorBench : public BaseBench { + public: + void SetUp(State& /*state*/) override { this->mVibrator = I::getService(); } +}; + +enum class EmptyEnum : uint32_t; +template <> +inline constexpr std::array hidl_enum_values = {}; + +template +std::set difference(const hidl_enum_range& t, const hidl_enum_range& u) { + class Compare { + public: + bool operator()(const T& a, const U& b) { return a < static_cast(b); } + bool operator()(const U& a, const T& b) { return static_cast(a) < b; } + }; + std::set ret; + + std::set_difference(t.begin(), t.end(), u.begin(), u.end(), + std::insert_iterator(ret, ret.begin()), Compare()); + + return ret; +} + +template +class VibratorEffectsBench : public VibratorBench { + public: + using Effect = E1; + using EffectStrength = V1_0::EffectStrength; + using Status = V1_0::Status; + + public: + static void DefaultArgs(Benchmark* b) { + b->ArgNames({"Effect", "Strength"}); + for (const auto& effect : difference(hidl_enum_range(), hidl_enum_range())) { + for (const auto& strength : hidl_enum_range()) { + b->Args({static_cast(effect), static_cast(strength)}); + } + } + } + + void performBench(State* state, Return (I::*performApi)(Effect, EffectStrength, + typename I::perform_cb)) { + auto effect = getEffect(*state); + auto strength = getStrength(*state); + bool supported = true; + + (*this->mVibrator.*performApi)(effect, strength, [&](Status status, uint32_t /*lengthMs*/) { + if (status == Status::UNSUPPORTED_OPERATION) { + supported = false; + } + }); + + if (!supported) { + return; + } + + for (auto _ : *state) { + state->ResumeTiming(); + (*this->mVibrator.*performApi)(effect, strength, + [](Status /*status*/, uint32_t /*lengthMs*/) {}); + state->PauseTiming(); + this->mVibrator->off(); + } + } + + protected: + auto getEffect(const State& state) const { + return static_cast(this->getOtherArg(state, 0)); + } + + auto getStrength(const State& state) const { + return static_cast(this->getOtherArg(state, 1)); + } +}; + +#define BENCHMARK_WRAPPER(fixt, test, code) \ + BENCHMARK_DEFINE_F(fixt, test) \ + /* NOLINTNEXTLINE */ \ + (State & state) { \ + if (!mVibrator) { \ + return; \ + } \ + \ + code \ + } \ + BENCHMARK_REGISTER_F(fixt, test)->Apply(fixt::DefaultConfig)->Apply(fixt::DefaultArgs) + +using VibratorBench_V1_0 = VibratorBench; + +BENCHMARK_WRAPPER(VibratorBench_V1_0, on, { + uint32_t ms = UINT32_MAX; + + for (auto _ : state) { + state.ResumeTiming(); + mVibrator->on(ms); + state.PauseTiming(); + mVibrator->off(); + } +}); + +BENCHMARK_WRAPPER(VibratorBench_V1_0, off, { + uint32_t ms = UINT32_MAX; + + for (auto _ : state) { + state.PauseTiming(); + mVibrator->on(ms); + state.ResumeTiming(); + mVibrator->off(); + } +}); + +BENCHMARK_WRAPPER(VibratorBench_V1_0, supportsAmplitudeControl, { + for (auto _ : state) { + mVibrator->supportsAmplitudeControl(); + } +}); + +BENCHMARK_WRAPPER(VibratorBench_V1_0, setAmplitude, { + uint8_t amplitude = UINT8_MAX; + + if (!mVibrator->supportsAmplitudeControl()) { + return; + } + + mVibrator->on(UINT32_MAX); + + for (auto _ : state) { + mVibrator->setAmplitude(amplitude); + } + + mVibrator->off(); +}); + +using VibratorEffectsBench_V1_0 = VibratorEffectsBench; + +BENCHMARK_WRAPPER(VibratorEffectsBench_V1_0, perform, + { performBench(&state, &V1_0::IVibrator::perform); }); + +using VibratorEffectsBench_V1_1 = + VibratorEffectsBench; + +BENCHMARK_WRAPPER(VibratorEffectsBench_V1_1, perform_1_1, + { performBench(&state, &V1_1::IVibrator::perform_1_1); }); + +using VibratorEffectsBench_V1_2 = + VibratorEffectsBench; + +BENCHMARK_WRAPPER(VibratorEffectsBench_V1_2, perform_1_2, + { performBench(&state, &V1_2::IVibrator::perform_1_2); }); + +using VibratorBench_V1_3 = VibratorBench; + +BENCHMARK_WRAPPER(VibratorBench_V1_3, supportsExternalControl, { + for (auto _ : state) { + mVibrator->supportsExternalControl(); + } +}); + +BENCHMARK_WRAPPER(VibratorBench_V1_3, setExternalControl, { + bool enable = true; + + if (!mVibrator->supportsExternalControl()) { + return; + } + + for (auto _ : state) { + state.ResumeTiming(); + mVibrator->setExternalControl(enable); + state.PauseTiming(); + mVibrator->setExternalControl(false); + } +}); + +BENCHMARK_WRAPPER(VibratorBench_V1_3, supportsExternalAmplitudeControl, { + if (!mVibrator->supportsExternalControl()) { + return; + } + + mVibrator->setExternalControl(true); + + for (auto _ : state) { + mVibrator->supportsAmplitudeControl(); + } + + mVibrator->setExternalControl(false); +}); + +BENCHMARK_WRAPPER(VibratorBench_V1_3, setExternalAmplitude, { + uint8_t amplitude = UINT8_MAX; + + if (!mVibrator->supportsExternalControl()) { + return; + } + + mVibrator->setExternalControl(true); + + if (!mVibrator->supportsAmplitudeControl()) { + return; + } + + for (auto _ : state) { + mVibrator->setAmplitude(amplitude); + } + + mVibrator->setExternalControl(false); +}); + +using VibratorEffectsBench_V1_3 = VibratorEffectsBench; + +BENCHMARK_WRAPPER(VibratorEffectsBench_V1_3, perform_1_3, + { performBench(&state, &V1_3::IVibrator::perform_1_3); }); + +class VibratorBench_Aidl : public BaseBench { + public: + void SetUp(State& /*state*/) override { + this->mVibrator = android::waitForVintfService(); + } +}; + +class HalCallback : public Aidl::BnVibratorCallback { + public: + HalCallback() = default; + ~HalCallback() = default; + + android::binder::Status onComplete() override { return android::binder::Status::ok(); } +}; + +BENCHMARK_WRAPPER(VibratorBench_Aidl, on, { + int32_t capabilities = 0; + mVibrator->getCapabilities(&capabilities); + + int32_t ms = INT32_MAX; + auto cb = (capabilities & Aidl::IVibrator::CAP_ON_CALLBACK) ? new HalCallback() : nullptr; + + for (auto _ : state) { + state.ResumeTiming(); + mVibrator->on(ms, cb); + state.PauseTiming(); + mVibrator->off(); + } +}); + +BENCHMARK_WRAPPER(VibratorBench_Aidl, off, { + for (auto _ : state) { + state.PauseTiming(); + mVibrator->on(INT32_MAX, nullptr); + state.ResumeTiming(); + mVibrator->off(); + } +}); + +BENCHMARK_WRAPPER(VibratorBench_Aidl, getCapabilities, { + int32_t capabilities = 0; + + for (auto _ : state) { + mVibrator->getCapabilities(&capabilities); + } +}); + +BENCHMARK_WRAPPER(VibratorBench_Aidl, setAmplitude, { + int32_t capabilities = 0; + mVibrator->getCapabilities(&capabilities); + if ((capabilities & Aidl::IVibrator::CAP_AMPLITUDE_CONTROL) == 0) { + return; + } + + float amplitude = 1.0f; + mVibrator->on(INT32_MAX, nullptr); + + for (auto _ : state) { + mVibrator->setAmplitude(amplitude); + } + + mVibrator->off(); +}); + +BENCHMARK_WRAPPER(VibratorBench_Aidl, setExternalControl, { + int32_t capabilities = 0; + mVibrator->getCapabilities(&capabilities); + if ((capabilities & Aidl::IVibrator::CAP_EXTERNAL_CONTROL) == 0) { + return; + } + + for (auto _ : state) { + state.ResumeTiming(); + mVibrator->setExternalControl(true); + state.PauseTiming(); + mVibrator->setExternalControl(false); + } +}); + +BENCHMARK_WRAPPER(VibratorBench_Aidl, setExternalAmplitude, { + int32_t capabilities = 0; + mVibrator->getCapabilities(&capabilities); + if ((capabilities & Aidl::IVibrator::CAP_EXTERNAL_CONTROL) == 0 || + (capabilities & Aidl::IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL) == 0) { + return; + } + + float amplitude = 1.0f; + mVibrator->setExternalControl(true); + + for (auto _ : state) { + mVibrator->setAmplitude(amplitude); + } + + mVibrator->setExternalControl(false); +}); + +BENCHMARK_WRAPPER(VibratorBench_Aidl, getSupportedEffects, { + std::vector supportedEffects; + + for (auto _ : state) { + mVibrator->getSupportedEffects(&supportedEffects); + } +}); + +BENCHMARK_WRAPPER(VibratorBench_Aidl, getSupportedAlwaysOnEffects, { + std::vector supportedEffects; + + for (auto _ : state) { + mVibrator->getSupportedAlwaysOnEffects(&supportedEffects); + } +}); + +BENCHMARK_WRAPPER(VibratorBench_Aidl, getSupportedPrimitives, { + std::vector supportedPrimitives; + + for (auto _ : state) { + mVibrator->getSupportedPrimitives(&supportedPrimitives); + } +}); + +class VibratorEffectsBench_Aidl : public VibratorBench_Aidl { + public: + static void DefaultArgs(Benchmark* b) { + b->ArgNames({"Effect", "Strength"}); + for (const auto& effect : enum_range()) { + for (const auto& strength : enum_range()) { + b->Args({static_cast(effect), static_cast(strength)}); + } + } + } + + protected: + auto getEffect(const State& state) const { + return static_cast(this->getOtherArg(state, 0)); + } + + auto getStrength(const State& state) const { + return static_cast(this->getOtherArg(state, 1)); + } +}; + +BENCHMARK_WRAPPER(VibratorEffectsBench_Aidl, alwaysOnEnable, { + int32_t capabilities = 0; + mVibrator->getCapabilities(&capabilities); + if ((capabilities & Aidl::IVibrator::CAP_ALWAYS_ON_CONTROL) == 0) { + return; + } + + int32_t id = 1; + auto effect = getEffect(state); + auto strength = getStrength(state); + + std::vector supported; + mVibrator->getSupportedAlwaysOnEffects(&supported); + if (std::find(supported.begin(), supported.end(), effect) == supported.end()) { + return; + } + + for (auto _ : state) { + state.ResumeTiming(); + mVibrator->alwaysOnEnable(id, effect, strength); + state.PauseTiming(); + mVibrator->alwaysOnDisable(id); + } +}); + +BENCHMARK_WRAPPER(VibratorEffectsBench_Aidl, alwaysOnDisable, { + int32_t capabilities = 0; + mVibrator->getCapabilities(&capabilities); + if ((capabilities & Aidl::IVibrator::CAP_ALWAYS_ON_CONTROL) == 0) { + return; + } + + int32_t id = 1; + auto effect = getEffect(state); + auto strength = getStrength(state); + + std::vector supported; + mVibrator->getSupportedAlwaysOnEffects(&supported); + if (std::find(supported.begin(), supported.end(), effect) == supported.end()) { + return; + } + + for (auto _ : state) { + state.PauseTiming(); + mVibrator->alwaysOnEnable(id, effect, strength); + state.ResumeTiming(); + mVibrator->alwaysOnDisable(id); + } +}); + +BENCHMARK_WRAPPER(VibratorEffectsBench_Aidl, perform, { + int32_t capabilities = 0; + mVibrator->getCapabilities(&capabilities); + + auto effect = getEffect(state); + auto strength = getStrength(state); + auto cb = (capabilities & Aidl::IVibrator::CAP_PERFORM_CALLBACK) ? new HalCallback() : nullptr; + int32_t lengthMs = 0; + + std::vector supported; + mVibrator->getSupportedEffects(&supported); + if (std::find(supported.begin(), supported.end(), effect) == supported.end()) { + return; + } + + for (auto _ : state) { + state.ResumeTiming(); + mVibrator->perform(effect, strength, cb, &lengthMs); + state.PauseTiming(); + mVibrator->off(); + } +}); + +class VibratorPrimitivesBench_Aidl : public VibratorBench_Aidl { + public: + static void DefaultArgs(Benchmark* b) { + b->ArgNames({"Primitive"}); + for (const auto& primitive : enum_range()) { + b->Args({static_cast(primitive)}); + } + } + + protected: + auto getPrimitive(const State& state) const { + return static_cast(this->getOtherArg(state, 0)); + } +}; + +BENCHMARK_WRAPPER(VibratorBench_Aidl, getCompositionDelayMax, { + int32_t ms = 0; + + for (auto _ : state) { + mVibrator->getCompositionDelayMax(&ms); + } +}); + +BENCHMARK_WRAPPER(VibratorBench_Aidl, getCompositionSizeMax, { + int32_t size = 0; + + for (auto _ : state) { + mVibrator->getCompositionSizeMax(&size); + } +}); + +BENCHMARK_WRAPPER(VibratorPrimitivesBench_Aidl, getPrimitiveDuration, { + int32_t capabilities = 0; + mVibrator->getCapabilities(&capabilities); + if ((capabilities & Aidl::IVibrator::CAP_COMPOSE_EFFECTS) == 0) { + return; + } + + auto primitive = getPrimitive(state); + int32_t ms = 0; + + std::vector supported; + mVibrator->getSupportedPrimitives(&supported); + if (std::find(supported.begin(), supported.end(), primitive) == supported.end()) { + return; + } + + for (auto _ : state) { + mVibrator->getPrimitiveDuration(primitive, &ms); + } +}); + +BENCHMARK_WRAPPER(VibratorPrimitivesBench_Aidl, compose, { + int32_t capabilities = 0; + mVibrator->getCapabilities(&capabilities); + if ((capabilities & Aidl::IVibrator::CAP_COMPOSE_EFFECTS) == 0) { + return; + } + + Aidl::CompositeEffect effect; + effect.primitive = getPrimitive(state); + effect.scale = 1.0f; + effect.delayMs = 0; + + std::vector supported; + mVibrator->getSupportedPrimitives(&supported); + if (std::find(supported.begin(), supported.end(), effect.primitive) == supported.end()) { + return; + } + + auto cb = new HalCallback(); + std::vector effects; + effects.push_back(effect); + + for (auto _ : state) { + state.ResumeTiming(); + mVibrator->compose(effects, cb); + state.PauseTiming(); + mVibrator->off(); + } +}); + +BENCHMARK_MAIN(); diff --git a/weaver/aidl/Android.bp b/weaver/aidl/Android.bp index 60925ecb89a18f2aac7dba001ef94fb7d739f25f..8b4306f3f10e9567301f47b2b326eb8c2c16249a 100644 --- a/weaver/aidl/Android.bp +++ b/weaver/aidl/Android.bp @@ -22,4 +22,5 @@ aidl_interface { }, }, }, + versions: ["1"], } diff --git a/weaver/aidl/aidl_api/android.hardware.weaver/1/.hash b/weaver/aidl/aidl_api/android.hardware.weaver/1/.hash new file mode 100644 index 0000000000000000000000000000000000000000..84288bb9f51e726b0563b2ab3f3de5e2b4eb3f0d --- /dev/null +++ b/weaver/aidl/aidl_api/android.hardware.weaver/1/.hash @@ -0,0 +1 @@ +c2ea8ac04f236492c02b992dc46ae904db0acc7e diff --git a/weaver/aidl/aidl_api/android.hardware.weaver/1/android/hardware/weaver/IWeaver.aidl b/weaver/aidl/aidl_api/android.hardware.weaver/1/android/hardware/weaver/IWeaver.aidl new file mode 100644 index 0000000000000000000000000000000000000000..61627d95c4285d3416e4728e829d32d443016c78 --- /dev/null +++ b/weaver/aidl/aidl_api/android.hardware.weaver/1/android/hardware/weaver/IWeaver.aidl @@ -0,0 +1,43 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.weaver; +@VintfStability +interface IWeaver { + android.hardware.weaver.WeaverConfig getConfig(); + android.hardware.weaver.WeaverReadResponse read(in int slotId, in byte[] key); + void write(in int slotId, in byte[] key, in byte[] value); + const int STATUS_FAILED = 1; + const int STATUS_INCORRECT_KEY = 2; + const int STATUS_THROTTLE = 3; +} diff --git a/weaver/aidl/aidl_api/android.hardware.weaver/1/android/hardware/weaver/WeaverConfig.aidl b/weaver/aidl/aidl_api/android.hardware.weaver/1/android/hardware/weaver/WeaverConfig.aidl new file mode 100644 index 0000000000000000000000000000000000000000..7491f3287289e7ba0369dc9adc40743bf0866e82 --- /dev/null +++ b/weaver/aidl/aidl_api/android.hardware.weaver/1/android/hardware/weaver/WeaverConfig.aidl @@ -0,0 +1,40 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.weaver; +@VintfStability +parcelable WeaverConfig { + int slots; + int keySize; + int valueSize; +} diff --git a/weaver/aidl/aidl_api/android.hardware.weaver/1/android/hardware/weaver/WeaverReadResponse.aidl b/weaver/aidl/aidl_api/android.hardware.weaver/1/android/hardware/weaver/WeaverReadResponse.aidl new file mode 100644 index 0000000000000000000000000000000000000000..47ee4c8a13a5c722d70036aaa2afb30927ff8734 --- /dev/null +++ b/weaver/aidl/aidl_api/android.hardware.weaver/1/android/hardware/weaver/WeaverReadResponse.aidl @@ -0,0 +1,39 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.weaver; +@VintfStability +parcelable WeaverReadResponse { + long timeout; + byte[] value; +} diff --git a/wifi/1.0/vts/OWNERS b/wifi/1.0/vts/OWNERS index 8bfb14882c8466954bd971a4603ab82e62077c61..cf81c798925338533dcb4d1968ea7de942b367f3 100644 --- a/wifi/1.0/vts/OWNERS +++ b/wifi/1.0/vts/OWNERS @@ -1,2 +1,2 @@ -rpius@google.com +arabawy@google.com etancohen@google.com diff --git a/wifi/1.0/vts/functional/Android.bp b/wifi/1.0/vts/functional/Android.bp index bc9541e3aa96d4f4177c6a2bae28ee13407407bc..e4948b4cc2462025dc041831861aba70b4244f18 100644 --- a/wifi/1.0/vts/functional/Android.bp +++ b/wifi/1.0/vts/functional/Android.bp @@ -39,6 +39,8 @@ cc_library_static { ], static_libs: [ "android.hardware.wifi@1.0", + "android.hardware.wifi@1.3", + "android.hardware.wifi@1.5", "libwifi-system-iface", ], } @@ -58,6 +60,8 @@ cc_test { "android.hardware.wifi@1.1", "android.hardware.wifi@1.2", "android.hardware.wifi@1.3", + "android.hardware.wifi@1.4", + "android.hardware.wifi@1.5", "libwifi-system-iface", ], test_suites: [ @@ -78,6 +82,11 @@ cc_test { static_libs: [ "VtsHalWifiV1_0TargetTestUtil", "android.hardware.wifi@1.0", + "android.hardware.wifi@1.1", + "android.hardware.wifi@1.2", + "android.hardware.wifi@1.3", + "android.hardware.wifi@1.4", + "android.hardware.wifi@1.5", "libwifi-system-iface", ], test_suites: [ diff --git a/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp index 3599b94075d6d56761406323a3c0469fce6ad25e..96b4501360b1a0885f4219412074841f535a355d 100644 --- a/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp +++ b/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp @@ -94,6 +94,7 @@ TEST_P(WifiApIfaceHidlTest, GetValidFrequenciesForBand) { EXPECT_GT(status_and_freqs.second.size(), 0u); } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiApIfaceHidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, WifiApIfaceHidlTest, testing::ValuesIn( diff --git a/wifi/1.0/vts/functional/wifi_chip_hidl_ap_test.cpp b/wifi/1.0/vts/functional/wifi_chip_hidl_ap_test.cpp index 5a2c6a740e298eb1cbe394f17b7d37bf41d88a0a..2e6ad32d6468766215cb7866fd70ea93f4b62728 100644 --- a/wifi/1.0/vts/functional/wifi_chip_hidl_ap_test.cpp +++ b/wifi/1.0/vts/functional/wifi_chip_hidl_ap_test.cpp @@ -176,6 +176,7 @@ TEST_P(WifiChipHidlApTest, RemoveApIface) { EXPECT_EQ(WifiStatusCode::ERROR_INVALID_ARGS, removeApIface(iface_name)); } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiChipHidlApTest); INSTANTIATE_TEST_SUITE_P( PerInstance, WifiChipHidlApTest, testing::ValuesIn( diff --git a/wifi/1.0/vts/functional/wifi_chip_hidl_nan_test.cpp b/wifi/1.0/vts/functional/wifi_chip_hidl_nan_test.cpp index bb7a3a679749f4b30cb11774cf602c95abca7678..49a25e5cfa4507111925b9bd30441bfb56ff2796 100644 --- a/wifi/1.0/vts/functional/wifi_chip_hidl_nan_test.cpp +++ b/wifi/1.0/vts/functional/wifi_chip_hidl_nan_test.cpp @@ -181,6 +181,7 @@ TEST_P(WifiChipHidlNanTest, RemoveNanIface) { EXPECT_EQ(WifiStatusCode::ERROR_INVALID_ARGS, removeNanIface(iface_name)); } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiChipHidlNanTest); INSTANTIATE_TEST_SUITE_P( PerInstance, WifiChipHidlNanTest, testing::ValuesIn( diff --git a/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp index 53131cee784f9302a958d80b69499227f2387325..6c8f56076991dc9bb8dd2322d24e10f07c15b628 100644 --- a/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp +++ b/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp @@ -18,7 +18,6 @@ #include #include -#include #include #include #include @@ -94,23 +93,7 @@ class WifiChipHidlTest : public ::testing::TestWithParam { uint32_t configureChipForStaIfaceAndGetCapabilities() { configureChipForIfaceType(IfaceType::STA, true); - sp<::android::hardware::wifi::V1_3::IWifiChip> chip_converted = - ::android::hardware::wifi::V1_3::IWifiChip::castFrom(wifi_chip_); - - std::pair status_and_caps; - - if (chip_converted != nullptr) { - // Call the newer HAL version - status_and_caps = HIDL_INVOKE(chip_converted, getCapabilities_1_3); - } else { - status_and_caps = HIDL_INVOKE(wifi_chip_, getCapabilities); - } - - if (status_and_caps.first.code != WifiStatusCode::SUCCESS) { - EXPECT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED, status_and_caps.first.code); - return 0; - } - return status_and_caps.second; + return getChipCapabilitiesLatest(wifi_chip_); } std::string getIfaceName(const sp& iface) { @@ -552,6 +535,7 @@ TEST_P(WifiChipHidlTest, CreateRttController) { } } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiChipHidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, WifiChipHidlTest, testing::ValuesIn( diff --git a/wifi/1.0/vts/functional/wifi_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_hidl_test.cpp index f3c82da3e96eabe8003b25cbcff86ce87aa9c108..109d116011b281ed244b51d0e9c354ef921a50d7 100644 --- a/wifi/1.0/vts/functional/wifi_hidl_test.cpp +++ b/wifi/1.0/vts/functional/wifi_hidl_test.cpp @@ -52,6 +52,7 @@ TEST_P(WifiHidlTest, Create) { // The creation of a proxy object is tested as part of SetUp method. } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiHidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, WifiHidlTest, testing::ValuesIn( diff --git a/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp b/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp index 5b11dd3fc496ce65bbc04f8acd1d5237d65360d6..e6e61cf8b75452daacc05429a57e3cfbe0a72733 100644 --- a/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp +++ b/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp @@ -16,6 +16,8 @@ #include +#include +#include #include #include "wifi_hidl_call_util.h" @@ -112,7 +114,7 @@ sp getWifiChip(const std::string& instance_name) { const auto& status_and_chip_ids = HIDL_INVOKE(wifi, getChipIds); const auto& chip_ids = status_and_chip_ids.second; if (status_and_chip_ids.first.code != WifiStatusCode::SUCCESS || - chip_ids.size() != 1) { + chip_ids.size() < 1) { return nullptr; } const auto& status_and_chip = HIDL_INVOKE(wifi, getChip, chip_ids[0]); @@ -208,3 +210,24 @@ void stopWifi(const std::string& instance_name) { ASSERT_NE(wifi, nullptr); HIDL_INVOKE(wifi, stop); } + +uint32_t getChipCapabilitiesLatest(const sp& wifi_chip) { + sp<::android::hardware::wifi::V1_5::IWifiChip> chip_converted15 = + ::android::hardware::wifi::V1_5::IWifiChip::castFrom(wifi_chip); + sp<::android::hardware::wifi::V1_3::IWifiChip> chip_converted13 = + ::android::hardware::wifi::V1_3::IWifiChip::castFrom(wifi_chip); + std::pair status_and_caps; + + if (chip_converted15 != nullptr) { + // Call the newer HAL 1.5 version + status_and_caps = HIDL_INVOKE(chip_converted15, getCapabilities_1_5); + } else if (chip_converted13 != nullptr) { + // Call the newer HAL 1.3 version + status_and_caps = HIDL_INVOKE(chip_converted13, getCapabilities_1_3); + } else { + status_and_caps = HIDL_INVOKE(wifi_chip, getCapabilities); + } + + EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code); + return status_and_caps.second; +} diff --git a/wifi/1.0/vts/functional/wifi_hidl_test_utils.h b/wifi/1.0/vts/functional/wifi_hidl_test_utils.h index 5c7863740d19cc2ea92aaa5890104f87d23bc96c..62c015cb39288383dbccbbda881f276e90ba16b3 100644 --- a/wifi/1.0/vts/functional/wifi_hidl_test_utils.h +++ b/wifi/1.0/vts/functional/wifi_hidl_test_utils.h @@ -51,3 +51,5 @@ bool configureChipToSupportIfaceType( android::hardware::wifi::V1_0::ChipModeId* configured_mode_id); // Used to trigger IWifi.stop() at the end of every test. void stopWifi(const std::string& instance_name); +uint32_t getChipCapabilitiesLatest( + const android::sp& wifi_chip); diff --git a/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp index 2b63ddc4cf0e40ac768f022a46401def089ec800..a74987cf2404888e39521335c1d796afb47aae0b 100644 --- a/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp +++ b/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -483,6 +484,16 @@ TEST_P(WifiNanIfaceHidlTest, FailOnIfaceInvalid) { TEST_P(WifiNanIfaceHidlTest, getCapabilitiesRequest) { uint16_t inputCmdId = 10; callbackType = INVALID; + sp<::android::hardware::wifi::V1_5::IWifiNanIface> iface_converted = + ::android::hardware::wifi::V1_5::IWifiNanIface::castFrom(iwifiNanIface); + if (iface_converted != nullptr) { + ASSERT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED, + HIDL_INVOKE(iwifiNanIface, getCapabilitiesRequest, inputCmdId) + .code); + // Skip this test since this API is deprecated in this newer HAL version + return; + } + ASSERT_EQ( WifiStatusCode::SUCCESS, HIDL_INVOKE(iwifiNanIface, getCapabilitiesRequest, inputCmdId).code); @@ -509,6 +520,7 @@ TEST_P(WifiNanIfaceHidlTest, getCapabilitiesRequest) { EXPECT_NE(capabilities.supportedCipherSuites, (unsigned int)0); } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiNanIfaceHidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, WifiNanIfaceHidlTest, testing::ValuesIn( diff --git a/wifi/1.0/vts/functional/wifi_p2p_iface_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_p2p_iface_hidl_test.cpp index fd175f5218efce6b2e4da6cb71bb5b9a2b4b4958..ce525f00e9bb1490c0e034c5d86e357955824dbb 100644 --- a/wifi/1.0/vts/functional/wifi_p2p_iface_hidl_test.cpp +++ b/wifi/1.0/vts/functional/wifi_p2p_iface_hidl_test.cpp @@ -54,6 +54,7 @@ TEST_P(WifiP2pIfaceHidlTest, Create) { EXPECT_NE(nullptr, getWifiP2pIface(GetInstanceName()).get()); } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiP2pIfaceHidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, WifiP2pIfaceHidlTest, testing::ValuesIn( diff --git a/wifi/1.0/vts/functional/wifi_rtt_controller_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_rtt_controller_hidl_test.cpp index 3c9ed9ee233e0f072aa0d6884efec2dd39e10a33..b1a918d545dd7f3035110b1924b6da22ab2fc3e1 100644 --- a/wifi/1.0/vts/functional/wifi_rtt_controller_hidl_test.cpp +++ b/wifi/1.0/vts/functional/wifi_rtt_controller_hidl_test.cpp @@ -76,6 +76,7 @@ TEST_P(WifiRttControllerHidlTest, Create) { } } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiRttControllerHidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, WifiRttControllerHidlTest, testing::ValuesIn( diff --git a/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp index e311c846e8f71c4b9cb43d70ee31cde500a6e83b..08d81ff3d810ed2c43018d3e6e41346c900292cd 100644 --- a/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp +++ b/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp @@ -298,6 +298,7 @@ TEST_P(WifiStaIfaceHidlTest, PacketFateMonitoring) { HIDL_INVOKE(wifi_sta_iface_, getDebugRxPacketFates).first.code); } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiStaIfaceHidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, WifiStaIfaceHidlTest, testing::ValuesIn( diff --git a/wifi/1.1/vts/OWNERS b/wifi/1.1/vts/OWNERS index 8bfb14882c8466954bd971a4603ab82e62077c61..cf81c798925338533dcb4d1968ea7de942b367f3 100644 --- a/wifi/1.1/vts/OWNERS +++ b/wifi/1.1/vts/OWNERS @@ -1,2 +1,2 @@ -rpius@google.com +arabawy@google.com etancohen@google.com diff --git a/wifi/1.1/vts/functional/Android.bp b/wifi/1.1/vts/functional/Android.bp index cd87dcbb303877a0c4efd145f8b5031776b06b8c..80486425c1cdb336a4d6b9d2b000c78dadc80931 100644 --- a/wifi/1.1/vts/functional/Android.bp +++ b/wifi/1.1/vts/functional/Android.bp @@ -35,6 +35,8 @@ cc_test { "android.hardware.wifi@1.1", "android.hardware.wifi@1.2", "android.hardware.wifi@1.3", + "android.hardware.wifi@1.4", + "android.hardware.wifi@1.5", "libwifi-system-iface", ], test_suites: [ diff --git a/wifi/1.1/vts/functional/wifi_chip_hidl_test.cpp b/wifi/1.1/vts/functional/wifi_chip_hidl_test.cpp index 4b94acb258edfe50e9fbe5d9bbbcd375dffee052..874aa83584f0ed8bfd21ef48136369f080c97960 100644 --- a/wifi/1.1/vts/functional/wifi_chip_hidl_test.cpp +++ b/wifi/1.1/vts/functional/wifi_chip_hidl_test.cpp @@ -18,7 +18,6 @@ #include #include -#include #include #include #include @@ -64,20 +63,7 @@ class WifiChipHidlTest : public ::testing::TestWithParam { EXPECT_TRUE(configureChipToSupportIfaceType( wifi_chip_, IfaceType::STA, &mode_id)); - sp<::android::hardware::wifi::V1_3::IWifiChip> chip_converted = - ::android::hardware::wifi::V1_3::IWifiChip::castFrom(wifi_chip_); - - std::pair status_and_caps; - - if (chip_converted != nullptr) { - // Call the newer HAL version - status_and_caps = HIDL_INVOKE(chip_converted, getCapabilities_1_3); - } else { - status_and_caps = HIDL_INVOKE(wifi_chip_, getCapabilities); - } - - EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code); - return status_and_caps.second; + return getChipCapabilitiesLatest(wifi_chip_); } sp wifi_chip_; @@ -114,6 +100,7 @@ TEST_P(WifiChipHidlTest, ResetTxPowerScenario) { } } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiChipHidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, WifiChipHidlTest, testing::ValuesIn( diff --git a/wifi/1.2/vts/OWNERS b/wifi/1.2/vts/OWNERS index 8bfb14882c8466954bd971a4603ab82e62077c61..cf81c798925338533dcb4d1968ea7de942b367f3 100644 --- a/wifi/1.2/vts/OWNERS +++ b/wifi/1.2/vts/OWNERS @@ -1,2 +1,2 @@ -rpius@google.com +arabawy@google.com etancohen@google.com diff --git a/wifi/1.2/vts/functional/Android.bp b/wifi/1.2/vts/functional/Android.bp index 410c961ec61bb6faea2bb25d0ec88ebcc0aab4cd..f43892bb32d8cf08bb4dc1532823203ab12bff69 100644 --- a/wifi/1.2/vts/functional/Android.bp +++ b/wifi/1.2/vts/functional/Android.bp @@ -36,6 +36,8 @@ cc_test { "android.hardware.wifi@1.1", "android.hardware.wifi@1.2", "android.hardware.wifi@1.3", + "android.hardware.wifi@1.4", + "android.hardware.wifi@1.5", "libwifi-system-iface", ], disable_framework: true, @@ -56,6 +58,9 @@ cc_test { "android.hardware.wifi@1.0", "android.hardware.wifi@1.1", "android.hardware.wifi@1.2", + "android.hardware.wifi@1.3", + "android.hardware.wifi@1.4", + "android.hardware.wifi@1.5", "libwifi-system-iface", ], test_suites: [ diff --git a/wifi/1.2/vts/functional/wifi_chip_hidl_test.cpp b/wifi/1.2/vts/functional/wifi_chip_hidl_test.cpp index b04acadef91704c5f3cc76564cf50dbbe6c21a25..6113fbf1f9e0ee891b9f878df034cedb60c2d376 100644 --- a/wifi/1.2/vts/functional/wifi_chip_hidl_test.cpp +++ b/wifi/1.2/vts/functional/wifi_chip_hidl_test.cpp @@ -111,20 +111,7 @@ class WifiChipHidlTest : public ::testing::TestWithParam { EXPECT_TRUE( configureChipToSupportIfaceType(wifi_chip_, IfaceType::STA, &mode_id)); - sp<::android::hardware::wifi::V1_3::IWifiChip> chip_converted = - ::android::hardware::wifi::V1_3::IWifiChip::castFrom(wifi_chip_); - - std::pair status_and_caps; - - if (chip_converted != nullptr) { - // Call the newer HAL version - status_and_caps = HIDL_INVOKE(chip_converted, getCapabilities_1_3); - } else { - status_and_caps = HIDL_INVOKE(wifi_chip_, getCapabilities); - } - - EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code); - return status_and_caps.second; + return getChipCapabilitiesLatest(wifi_chip_); } sp wifi_chip_; @@ -186,6 +173,7 @@ TEST_P(WifiChipHidlTest, registerEventCallback_1_2) { } } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiChipHidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, WifiChipHidlTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames( diff --git a/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp b/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp index bc392a91ec5c61f9eda0baf183bae5e52e5a731f..f1c751eea16ce0fe64defd48cd5105166a9f1e3e 100644 --- a/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp +++ b/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp @@ -559,6 +559,7 @@ TEST_P(WifiNanIfaceHidlTest, configRequest_1_2ShimInvalidArgs) { } } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiNanIfaceHidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, WifiNanIfaceHidlTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames( diff --git a/wifi/1.2/vts/functional/wifi_sta_iface_hidl_test.cpp b/wifi/1.2/vts/functional/wifi_sta_iface_hidl_test.cpp index 066dcaae872c37d03aa32109603d9c85c7710954..cfa67d43bbb775ad26e00de2f54a8cf6cbe4a510 100644 --- a/wifi/1.2/vts/functional/wifi_sta_iface_hidl_test.cpp +++ b/wifi/1.2/vts/functional/wifi_sta_iface_hidl_test.cpp @@ -117,6 +117,7 @@ TEST_P(WifiStaIfaceHidlTest, DISABLED_ReadApfPacketFilterData) { EXPECT_EQ(status_and_data.second, data); } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiStaIfaceHidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, WifiStaIfaceHidlTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames( diff --git a/wifi/1.3/vts/OWNERS b/wifi/1.3/vts/OWNERS index 8bfb14882c8466954bd971a4603ab82e62077c61..cf81c798925338533dcb4d1968ea7de942b367f3 100644 --- a/wifi/1.3/vts/OWNERS +++ b/wifi/1.3/vts/OWNERS @@ -1,2 +1,2 @@ -rpius@google.com +arabawy@google.com etancohen@google.com diff --git a/wifi/1.3/vts/functional/Android.bp b/wifi/1.3/vts/functional/Android.bp index 0dc0f4cc63f355a2450fae16b914dfe698fee272..16f84ef4951d75d368487d9e91f68a759af2fd62 100644 --- a/wifi/1.3/vts/functional/Android.bp +++ b/wifi/1.3/vts/functional/Android.bp @@ -36,8 +36,13 @@ cc_test { "android.hardware.wifi@1.1", "android.hardware.wifi@1.2", "android.hardware.wifi@1.3", - "libwifi-system-iface" + "android.hardware.wifi@1.4", + "android.hardware.wifi@1.5", + "libwifi-system-iface", ], disable_framework: true, - test_suites: ["general-tests", "vts"], + test_suites: [ + "general-tests", + "vts", + ], } diff --git a/wifi/1.3/vts/functional/wifi_chip_hidl_test.cpp b/wifi/1.3/vts/functional/wifi_chip_hidl_test.cpp index e99b34a7f83aee836627a67424c4ad67e0f4d8ec..f2c2beac507a9a07b4645d3a0049547dfdc019f1 100644 --- a/wifi/1.3/vts/functional/wifi_chip_hidl_test.cpp +++ b/wifi/1.3/vts/functional/wifi_chip_hidl_test.cpp @@ -68,10 +68,7 @@ class WifiChipHidlTest : public ::testing::TestWithParam { ChipModeId mode_id; EXPECT_TRUE(configureChipToSupportIfaceType(wifi_chip_, IfaceType::STA, &mode_id)); - const auto& status_and_caps = - HIDL_INVOKE(wifi_chip_, getCapabilities_1_3); - EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code); - return status_and_caps.second; + return getChipCapabilitiesLatest(wifi_chip_); } sp wifi_chip_; @@ -125,6 +122,7 @@ TEST_P(WifiChipHidlTest, GetCapabilities_1_3) { EXPECT_NE(0u, status_and_caps.second); } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiChipHidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, WifiChipHidlTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames( diff --git a/wifi/1.3/vts/functional/wifi_sta_iface_hidl_test.cpp b/wifi/1.3/vts/functional/wifi_sta_iface_hidl_test.cpp index 41d4ebbcb1e997cdafece5adbd5a5e6c9e35da0e..78e62390eb727ce7d6ee98ebbff2b034a3813118 100644 --- a/wifi/1.3/vts/functional/wifi_sta_iface_hidl_test.cpp +++ b/wifi/1.3/vts/functional/wifi_sta_iface_hidl_test.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -88,7 +89,6 @@ TEST_P(WifiStaIfaceHidlTest, GetLinkLayerStats_1_3) { // No-op if link layer stats is not supported. return; } - // Enable link layer stats collection. EXPECT_EQ(WifiStatusCode::SUCCESS, HIDL_INVOKE(wifi_sta_iface_, enableLinkLayerStatsCollection, true) @@ -96,14 +96,24 @@ TEST_P(WifiStaIfaceHidlTest, GetLinkLayerStats_1_3) { // Retrieve link layer stats. const auto& status_and_stats = HIDL_INVOKE(wifi_sta_iface_, getLinkLayerStats_1_3); - EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_stats.first.code); - EXPECT_GT(status_and_stats.second.timeStampInMs, 0u); + sp staIface1_5 = + android::hardware::wifi::V1_5::IWifiStaIface::castFrom(wifi_sta_iface_); + if (staIface1_5.get() == nullptr) { + EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_stats.first.code); + EXPECT_GT(status_and_stats.second.timeStampInMs, 0u); + } else { + // not supported on 1.5 HAL. + EXPECT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED, + status_and_stats.first.code); + } + // Disable link layer stats collection. EXPECT_EQ( WifiStatusCode::SUCCESS, HIDL_INVOKE(wifi_sta_iface_, disableLinkLayerStatsCollection).code); } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiStaIfaceHidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, WifiStaIfaceHidlTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames( diff --git a/wifi/1.4/vts/OWNERS b/wifi/1.4/vts/OWNERS index 8bfb14882c8466954bd971a4603ab82e62077c61..cf81c798925338533dcb4d1968ea7de942b367f3 100644 --- a/wifi/1.4/vts/OWNERS +++ b/wifi/1.4/vts/OWNERS @@ -1,2 +1,2 @@ -rpius@google.com +arabawy@google.com etancohen@google.com diff --git a/wifi/1.4/vts/functional/Android.bp b/wifi/1.4/vts/functional/Android.bp index ad4df2d81d34dee38d77edeff0d960827caa29ea..14ebbe3bb8fc3cec690f7a24b9f64ea3f670b8e9 100644 --- a/wifi/1.4/vts/functional/Android.bp +++ b/wifi/1.4/vts/functional/Android.bp @@ -61,6 +61,7 @@ cc_test { "android.hardware.wifi@1.2", "android.hardware.wifi@1.3", "android.hardware.wifi@1.4", + "android.hardware.wifi@1.5", "libwifi-system-iface", ], test_suites: [ diff --git a/wifi/1.4/vts/functional/wifi_ap_iface_hidl_test.cpp b/wifi/1.4/vts/functional/wifi_ap_iface_hidl_test.cpp index aff0ef741fcbbc1e9346955f7315f15bf41b5069..5b0f1736ea8062682c2a3c69ee1a65e04f67833d 100644 --- a/wifi/1.4/vts/functional/wifi_ap_iface_hidl_test.cpp +++ b/wifi/1.4/vts/functional/wifi_ap_iface_hidl_test.cpp @@ -59,7 +59,7 @@ class WifiApIfaceHidlTest : public ::testing::TestWithParam { * code. */ TEST_P(WifiApIfaceHidlTest, SetMacAddress) { - const hidl_array kMac{{0x12, 0x22, 0x33, 0x52, 0x10, 0x41}}; + const hidl_array kMac{{0x12, 0x22, 0x33, 0x52, 0x10, 0x44}}; EXPECT_EQ(WifiStatusCode::SUCCESS, HIDL_INVOKE(wifi_ap_iface_, setMacAddress, kMac).code); } @@ -77,6 +77,7 @@ TEST_P(WifiApIfaceHidlTest, GetFactoryMacAddress) { EXPECT_NE(all_zero, status_and_mac.second); } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiApIfaceHidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, WifiApIfaceHidlTest, testing::ValuesIn( diff --git a/wifi/1.4/vts/functional/wifi_chip_hidl_test.cpp b/wifi/1.4/vts/functional/wifi_chip_hidl_test.cpp index be5c3bde9e0c86b8d20106063c7b8934034ffc4e..e8a2d0a4d6644769965da2d88c0d8dc2e8df4cb9 100644 --- a/wifi/1.4/vts/functional/wifi_chip_hidl_test.cpp +++ b/wifi/1.4/vts/functional/wifi_chip_hidl_test.cpp @@ -150,6 +150,7 @@ TEST_P(WifiChipHidlTest, registerEventCallback_1_4) { } } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiChipHidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, WifiChipHidlTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames( diff --git a/wifi/1.4/vts/functional/wifi_nan_iface_hidl_test.cpp b/wifi/1.4/vts/functional/wifi_nan_iface_hidl_test.cpp index f6a1147e0d0b007b10f5aa53b53cdfa9dc7b8796..3ac047d2c88956f04db0952069365d9c434f2729 100644 --- a/wifi/1.4/vts/functional/wifi_nan_iface_hidl_test.cpp +++ b/wifi/1.4/vts/functional/wifi_nan_iface_hidl_test.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -488,6 +489,17 @@ TEST_P(WifiNanIfaceHidlTest, enableRequest_1_4InvalidArgs) { callbackType = INVALID; ::android::hardware::wifi::V1_4::NanEnableRequest nanEnableRequest = {}; NanConfigRequestSupplemental nanConfigRequestSupp = {}; + + sp<::android::hardware::wifi::V1_5::IWifiNanIface> iface_converted = + ::android::hardware::wifi::V1_5::IWifiNanIface::castFrom(iwifiNanIface); + if (iface_converted != nullptr) { + ASSERT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED, + HIDL_INVOKE(iwifiNanIface, enableRequest_1_4, inputCmdId, + nanEnableRequest, nanConfigRequestSupp) + .code); + // Skip this test since this API is deprecated in this newer HAL version + return; + } ASSERT_EQ(WifiStatusCode::SUCCESS, HIDL_INVOKE(iwifiNanIface, enableRequest_1_4, inputCmdId, nanEnableRequest, nanConfigRequestSupp) @@ -509,6 +521,17 @@ TEST_P(WifiNanIfaceHidlTest, enableRequest_1_4ShimInvalidArgs) { nanEnableRequest.configParams.numberOfPublishServiceIdsInBeacon = 128; // must be <= 127 NanConfigRequestSupplemental nanConfigRequestSupp = {}; + + sp<::android::hardware::wifi::V1_5::IWifiNanIface> iface_converted = + ::android::hardware::wifi::V1_5::IWifiNanIface::castFrom(iwifiNanIface); + if (iface_converted != nullptr) { + ASSERT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED, + HIDL_INVOKE(iwifiNanIface, enableRequest_1_4, inputCmdId, + nanEnableRequest, nanConfigRequestSupp) + .code); + // Skip this test since this API is deprecated in this newer HAL version + return; + } ASSERT_EQ(WifiStatusCode::ERROR_INVALID_ARGS, HIDL_INVOKE(iwifiNanIface, enableRequest_1_4, inputCmdId, nanEnableRequest, nanConfigRequestSupp) @@ -523,6 +546,17 @@ TEST_P(WifiNanIfaceHidlTest, configRequest_1_4InvalidArgs) { callbackType = INVALID; ::android::hardware::wifi::V1_4::NanConfigRequest nanConfigRequest = {}; NanConfigRequestSupplemental nanConfigRequestSupp = {}; + + sp<::android::hardware::wifi::V1_5::IWifiNanIface> iface_converted = + ::android::hardware::wifi::V1_5::IWifiNanIface::castFrom(iwifiNanIface); + if (iface_converted != nullptr) { + ASSERT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED, + HIDL_INVOKE(iwifiNanIface, configRequest_1_4, inputCmdId, + nanConfigRequest, nanConfigRequestSupp) + .code); + // Skip this test since this API is deprecated in this newer HAL version + return; + } ASSERT_EQ(WifiStatusCode::SUCCESS, HIDL_INVOKE(iwifiNanIface, configRequest_1_4, inputCmdId, nanConfigRequest, nanConfigRequestSupp) @@ -543,12 +577,25 @@ TEST_P(WifiNanIfaceHidlTest, configRequest_1_4ShimInvalidArgs) { ::android::hardware::wifi::V1_4::NanConfigRequest nanConfigRequest = {}; nanConfigRequest.numberOfPublishServiceIdsInBeacon = 128; // must be <= 127 NanConfigRequestSupplemental nanConfigRequestSupp = {}; + + sp<::android::hardware::wifi::V1_5::IWifiNanIface> iface_converted = + ::android::hardware::wifi::V1_5::IWifiNanIface::castFrom(iwifiNanIface); + if (iface_converted != nullptr) { + ASSERT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED, + HIDL_INVOKE(iwifiNanIface, configRequest_1_4, inputCmdId, + nanConfigRequest, nanConfigRequestSupp) + .code); + // Skip this test since this API is deprecated in this newer HAL version + return; + } + ASSERT_EQ(WifiStatusCode::ERROR_INVALID_ARGS, HIDL_INVOKE(iwifiNanIface, configRequest_1_4, inputCmdId, nanConfigRequest, nanConfigRequestSupp) .code); } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiNanIfaceHidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, WifiNanIfaceHidlTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames( diff --git a/wifi/1.4/vts/functional/wifi_rtt_controller_hidl_test.cpp b/wifi/1.4/vts/functional/wifi_rtt_controller_hidl_test.cpp index 3efb8f4c6698b78539939ee9ceb38a0ea62a45b7..72cde3ca7156cb3cfa981652cfab6c5deecc3c1e 100644 --- a/wifi/1.4/vts/functional/wifi_rtt_controller_hidl_test.cpp +++ b/wifi/1.4/vts/functional/wifi_rtt_controller_hidl_test.cpp @@ -191,6 +191,8 @@ TEST_P(WifiRttControllerHidlTest, Request2SidedRangeMeasurement) { const auto& status = HIDL_INVOKE(wifi_rtt_controller_, rangeRequest_1_4, cmdId, configs); EXPECT_EQ(WifiStatusCode::SUCCESS, status.code); + // sleep for 2 seconds to wait for driver/firmware to complete RTT + sleep(2); } /* * rangeRequest_1_4 @@ -242,6 +244,8 @@ TEST_P(WifiRttControllerHidlTest, RangeRequest_1_4) { const auto& status = HIDL_INVOKE(wifi_rtt_controller_, rangeRequest_1_4, cmdId, configs); EXPECT_EQ(WifiStatusCode::SUCCESS, status.code); + // sleep for 2 seconds to wait for driver/firmware to complete RTT + sleep(2); } /* @@ -289,6 +293,7 @@ TEST_P(WifiRttControllerHidlTest, EnableResponder_1_4) { EXPECT_EQ(WifiStatusCode::SUCCESS, status.code); } +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiRttControllerHidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, WifiRttControllerHidlTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames( diff --git a/wifi/1.5/Android.bp b/wifi/1.5/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..0887c6b5c1edf02e0e4d50c649c519f0f76a31f9 --- /dev/null +++ b/wifi/1.5/Android.bp @@ -0,0 +1,38 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +hidl_interface { + name: "android.hardware.wifi@1.5", + root: "android.hardware", + srcs: [ + "types.hal", + "IWifi.hal", + "IWifiChip.hal", + "IWifiApIface.hal", + "IWifiNanIface.hal", + "IWifiNanIfaceEventCallback.hal", + "IWifiStaIface.hal", + "IWifiEventCallback.hal", + ], + interfaces: [ + "android.hardware.wifi@1.0", + "android.hardware.wifi@1.1", + "android.hardware.wifi@1.2", + "android.hardware.wifi@1.3", + "android.hardware.wifi@1.4", + "android.hidl.base@1.0", + ], + gen_java: true, + apex_available: [ + "//apex_available:platform", + "com.android.wifi", + ], +} diff --git a/wifi/1.5/IWifi.hal b/wifi/1.5/IWifi.hal new file mode 100644 index 0000000000000000000000000000000000000000..28b808ed324699b615f1614bd927e9ed50ff14b2 --- /dev/null +++ b/wifi/1.5/IWifi.hal @@ -0,0 +1,46 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.wifi@1.5; + +import @1.4::IWifi; +import IWifiEventCallback; +import @1.0::WifiStatus; + +/** + * This is the root of the HAL module and is the interface returned when + * loading an implementation of the Wi-Fi HAL. There must be at most one + * module loaded in the system. + * IWifi.getChip() must return @1.5::IWifiChip + */ +interface IWifi extends @1.4::IWifi { + /** + * Requests notifications of significant events for the HAL. Multiple calls to + * this must register multiple callbacks each of which must receive all + * events. |IWifiEventCallback| object registration must be independent of the + * state of the rest of the HAL and must persist though stops/starts. These + * objects must be deleted when the corresponding client process is dead. + * + * @param callback An instance of the |IWifiEventCallback| HIDL interface + * object. + * @return status WifiStatus of the operation. + * Possible status codes: + * |WifiStatusCode.SUCCESS|, + * |WifiStatusCode.UNKNOWN| + */ + registerEventCallback_1_5(IWifiEventCallback callback) + generates (WifiStatus status); +}; diff --git a/wifi/1.5/IWifiApIface.hal b/wifi/1.5/IWifiApIface.hal new file mode 100644 index 0000000000000000000000000000000000000000..c638f1d570f6267d810ccd7f7a660543eae8fe3b --- /dev/null +++ b/wifi/1.5/IWifiApIface.hal @@ -0,0 +1,54 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.wifi@1.5; + +import @1.4::IWifiApIface; +import @1.0::MacAddress; +import @1.0::WifiStatus; + +/** + * Represents a network interface in AP mode. + * + * This can be obtained through @1.0::IWifiChip.getApIface() and casting + * IWifiApIface up to 1.5. + */ +interface IWifiApIface extends @1.4::IWifiApIface { + /** + * Reset all of the AP interfaces MAC address to the factory MAC address. + * + * @return status WifiStatus of the operation + * Possible status codes: + * |WifiStatusCode.SUCCESS|, + * |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|, + * |WifiStatusCode.ERROR_UNKNOWN| + */ + resetToFactoryMacAddress() generates (WifiStatus status); + + /** + * Get the names of the bridged AP instances. + * + * @return status WifiStatus of the operation + * Possible status codes: + * |WifiStatusCode.SUCCESS|, + * |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|, + * |WifiStatusCode.ERROR_UNKNOWN| + * + * @return instances A vector which contains the names of the bridged AP + * instances. Note: Returns an empty vector for a non-bridged AP. + */ + getBridgedInstances() generates (WifiStatus status, vec instances); +}; diff --git a/wifi/1.5/IWifiChip.hal b/wifi/1.5/IWifiChip.hal new file mode 100644 index 0000000000000000000000000000000000000000..8d7a36e285f2b68948ea9ace7ed275cd646e394b --- /dev/null +++ b/wifi/1.5/IWifiChip.hal @@ -0,0 +1,339 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.wifi@1.5; + +import @1.0::WifiStatus; +import @1.5::IWifiApIface; +import @1.0::IWifiIface; +import @1.3::IWifiChip; +import @1.4::IWifiChip; + +/** + * Interface that represents a chip that must be configured as a single unit. + */ +interface IWifiChip extends @1.4::IWifiChip { + /** + * Capabilities exposed by this chip. + */ + enum ChipCapabilityMask : @1.3::IWifiChip.ChipCapabilityMask { + /** + * chip can operate in the 60GHz band(WiGig chip) + */ + WIGIG = 1 << 14, + }; + + /** + * When there are 2 or more simultaneous STA connections, this use case hint indicates what + * use-case is being enabled by the framework. This use case hint can be used by the firmware + * to modify various firmware configurations like: + * - Allowed BSSIDs the firmware can choose for the initial connection/roaming attempts. + * - Duty cycle to choose for the 2 STA connections if the radio is in MCC mode. + * - Whether roaming, APF and other offloads needs to be enabled or not. + * Note: + * - This will be invoked before an active wifi connection is established on the second + * interface. + * - This use-case hint is implicitly void when the second STA interface is brought down. + * - When there is only 1 STA interface, the must should still retain the last use case + * set, which must become active the next time multi STA is enabled. + * 1. Initialize with single STA. + * 2. Framework creates second STA. + * 3. Framework sets use case to DUAL_STA_NON_TRANSIENT_UNBIASED. + * 4. Framework destroys second STA. Only 1 STA remains. + * 5. Framework recreates second STA. + * 6. The active use case remains DUAL_STA_NON_TRANSIENT_UNBIASED (i.e. firmware should not + * automatically change it during period of single STA unless requested by framework). + */ + enum MultiStaUseCase : uint8_t { + /** + * Usage: + * - This will be sent down for make before break use-case. + * - Platform is trying to speculatively connect to a second network and evaluate it without + * disrupting the primary connection. + * Requirements for Firmware: + * - Do not reduce the number of tx/rx chains of primary connection. + * - If using MCC, should set the MCC duty cycle of the primary connection to be higher than + * the secondary connection (maybe 70/30 split). + * - Should pick the best BSSID for the secondary STA (disregard the chip mode) independent + * of the primary STA: + * - Don’t optimize for DBS vs MCC/SCC + * - Should not impact the primary connection’s bssid selection: + * - Don’t downgrade chains of the existing primary connection. + * - Don’t optimize for DBS vs MCC/SCC. + */ + DUAL_STA_TRANSIENT_PREFER_PRIMARY = 0, + /** + * Usage: + * - This will be sent down for any app requested peer to peer connections. + * - In this case, both the connections needs to be allocated equal resources. + * - For the peer to peer use case, BSSID for the secondary connection will be chosen by the + * framework. + * + * Requirements for Firmware: + * - Can choose MCC or DBS mode depending on the MCC efficiency and HW capability. + * - If using MCC, set the MCC duty cycle of the primary connection to be equal to the + * secondary connection. + * - Prefer BSSID candidates which will help provide the best "overall" performance for both + * the connections. + */ + DUAL_STA_NON_TRANSIENT_UNBIASED = 1, + }; + + /** + * Get the capabilities supported by this chip. + * + * @return status WifiStatus of the operation. + * Possible status codes: + * |WifiStatusCode.SUCCESS|, + * |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|, + * |WifiStatusCode.ERROR_NOT_AVAILABLE|, + * |WifiStatusCode.ERROR_UNKNOWN| + * @return capabilities Bitset of |ChipCapabilityMask| values. + */ + getCapabilities_1_5() + generates (WifiStatus status, bitfield capabilities); + + /** + * Invoked to indicate that the provided iface is the primary STA iface when there are more + * than 1 STA iface concurrently active. + * Notes: + * - If the wifi firmware/chip cannot support multiple instances of any offload + * (like roaming, APF, rssi threshold, etc), the firmware should ensure that these + * offloads are at least enabled for the primary interface. If the new primary interface is + * already connected to a network, the firmware must switch all the offloads on + * this new interface without disconnecting. + * - When there is only 1 STA interface, the firmware must still retain the last primary + * connection, which must become active the next time multi STA is enabled. + * + * @param ifname Name of the STA iface. + * @return status WifiStatus of the operation. + * Possible status codes: + * |WifiStatusCode.SUCCESS|, + * |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|, + * |WifiStatusCode.ERROR_INVALID_ARGS| + */ + setMultiStaPrimaryConnection(string ifName) generates (WifiStatus status); + + /** + * Invoked to indicate the STA + STA use-case that is active. + * + * Refer to documentation of |MultiStaUseCase| for details. + * + * @param useCase Use case that is active. + * @return status WifiStatus of the operation. + * Possible status codes: + * |WifiStatusCode.SUCCESS|, + * |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|, + * |WifiStatusCode.ERROR_INVALID_ARGS| + */ + setMultiStaUseCase(MultiStaUseCase useCase) generates (WifiStatus status); + + /** + * Create bridged IWifiApIface. + * + * Depending on the mode the chip is configured in, the interface creation + * may fail (code: |ERROR_NOT_AVAILABLE|) if we've already reached the maximum + * allowed (specified in |ChipIfaceCombination|) number of ifaces of the AP + * type. + * + * @return status WifiStatus of the operation. + * Possible status codes: + * |WifiStatusCode.SUCCESS|, + * |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|, + * |WifiStatusCode.ERROR_NOT_SUPPORTED|, + * |WifiStatusCode.ERROR_NOT_AVAILABLE| + * @return iface HIDL interface object representing the iface if + * successful, null otherwise. + */ + createBridgedApIface() generates (WifiStatus status, IWifiApIface iface); + + /** + * Removes one of the instance on the AP Iface with the provided ifaceName and + * ifaceInstanceName. + * + * Use the API: removeApIface with brIfaceName in the V1_0::WifiChip.hal to remove bridge Iface. + * + * @param brIfaceName Name of the bridged AP iface. + * @param ifaceInstanceName Name of the instance. The empty instance is + * invalid. + * @return status WifiStatus of the operation. + * Possible status codes: + * |WifiStatusCode.SUCCESS|, + * |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|, + * |WifiStatusCode.ERROR_INVALID_ARGS|, + * |WifiStatusCode.ERROR_NOT_AVAILABLE| + */ + removeIfaceInstanceFromBridgedApIface(string brIfaceName, string ifaceInstanceName) + generates (WifiStatus status); + + /** + * Representation of a Wi-Fi channel for Wi-Fi coex channel avoidance. + */ + struct CoexUnsafeChannel { + /* The band of the channel */ + WifiBand band; + /* The channel number */ + uint32_t channel; + /** The power cap will be a maximum power value in dbm that is allowed to be transmitted by + the chip on this channel. A value of PowerCapConstant.NO_POWER_CAP means no limitation + on transmitted power is needed by the chip for this channel. + */ + int32_t powerCapDbm; + }; + + enum PowerCapConstant : int32_t { + NO_POWER_CAP = 0x7FFFFFFF, + }; + + enum CoexRestriction : uint32_t { + WIFI_DIRECT = 1 << 0, + SOFTAP = 1 << 1, + WIFI_AWARE = 1 << 2 + }; + + /** + * Invoked to indicate that the provided |CoexUnsafeChannels| should be avoided with the + * specified restrictions. + * + * Channel avoidance is a suggestion and should be done on a best-effort approach. If a provided + * channel is used, then the specified power cap should be applied. + * + * In addition, hard restrictions on the Wifi modes may be indicated by |CoexRestriction| bits + * (WIFI_DIRECT, SOFTAP, WIFI_AWARE) in the |restrictions| bitfield. If a hard restriction is + * provided, then the channels should be completely avoided for the provided Wifi modes instead + * of by best-effort. + * + * @param unsafeChannels List of |CoexUnsafeChannels| to avoid. + * @param restrictions Bitset of |CoexRestriction| values indicating Wifi interfaces to + * completely avoid. + * @return status WifiStatus of the operation. + * Possible status codes: + * |WifiStatusCode.SUCCESS|, + * |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|, + * |WifiStatusCode.ERROR_INVALID_ARGS|, + */ + setCoexUnsafeChannels( + vec unsafeChannels, bitfield restrictions) + generates (WifiStatus status); + + /** + * Set country code for this Wifi chip. + * + * Country code is global setting across the Wifi chip and not Wifi + * interface (STA or AP) specific. Legacy HAL API's for country code in + * @1.0::ISupplicantStaIface::setCountryCode & + * @1.0::IWifiApIface:setCountryCode are deprecated in favor of this + * chip level API. + * + * @param code 2 byte country code (as defined in ISO 3166) to set. + * @return status Status of the operation. + * Possible status codes: + * |WifiStatusCode.SUCCESS|, + * |WifiStatusCode.FAILURE_UNKNOWN|, + * |WifiStatusCode.FAILURE_IFACE_INVALID| + */ + setCountryCode(int8_t[2] code) generates (WifiStatus status); + + /** + * Usable Wifi channels filter masks. + */ + enum UsableChannelFilter : uint32_t { + /** + * Filter Wifi channels that should be avoided due to extreme + * cellular coexistence restrictions. Some Wifi channels can have + * extreme interference from/to cellular due to short frequency + * seperation with neighboring cellular channels or when there + * is harmonic and intermodulation interference. Channels which + * only have some performance degradation (e.g. power back off is + * sufficient to deal with coexistence issue) can be included and + * should not be filtered out. + */ + CELLULAR_COEXISTENCE = 1 << 0, + /** + * Filter based on concurrency state. + * Examples: + * - 5GHz SAP operation may be supported in standalone mode, but if + * there is STA connection on 5GHz DFS channel, none of the 5GHz + * channels are usable for SAP if device does not support DFS SAP mode. + * - P2P GO may not be supported on indoor channels in EU during + * standalone mode but if there is a STA connection on indoor channel, + * P2P GO may be supported by some vendors on the same STA channel. + */ + CONCURRENCY = 1 << 1, + }; + + /** + * Retrieve list of usable Wifi channels for the specified band & + * operational modes. + * + * The list of usable Wifi channels in a given band depends on factors + * like current country code, operational mode (e.g. STA, SAP, WFD-CLI, + * WFD-GO, TDLS, NAN) and other restrictons due to DFS, cellular coexistence + * and conncurency state of the device. + * + * @param band |WifiBand| for which list of usable channels is requested. + * @param ifaceModeMask Bitmask of the modes represented by |WifiIfaceMode| + * Bitmask respresents all the modes that the caller is interested + * in (e.g. STA, SAP, CLI, GO, TDLS, NAN). E.g. If the caller is + * interested in knowing usable channels for P2P CLI, P2P GO & NAN, + * ifaceModeMask would be set to + * IFACE_MODE_P2P_CLIENT|IFACE_MODE_P2P_GO|IFACE_MODE_NAN. + * @param filterMask Bitmask of filters represented by + * |UsableChannelFilter|. Specifies whether driver should filter + * channels based on additional criteria. If no filter is specified + * driver should return usable channels purely based on regulatory + * constraints. + * @return status WifiStatus of the operation. + * Possible status codes: + * |WifiStatusCode.SUCCESS|, + * |WifiStatusCode.ERROR_NOT_SUPPORTED|, + * |WifiStatusCode.ERROR_INVALID_ARGS|, + * |WifiStatusCode.FAILURE_UNKNOWN| + * @return channels List of channels represented by |WifiUsableChannel| + * Each entry represents a channel frequency, bandwidth and + * bitmask of modes (e.g. STA, SAP, CLI, GO, TDLS, NAN) that are + * allowed on that channel. E.g. If only STA mode can be supported + * on an indoor channel, only the IFACE_MODE_STA bit would be set + * for that channel. If 5GHz SAP cannot be supported, then none of + * the 5GHz channels will have IFACE_MODE_SOFTAP bit set. + * Note: Bits do not represent concurrency state. Each bit only + * represents whether particular mode is allowed on that channel. + */ + getUsableChannels(WifiBand band, bitfield ifaceModeMask, + bitfield filterMask) + generates (WifiStatus status, vec channels); + + /** + * Trigger subsystem restart + * + * If the framework detects a problem (e.g. connection failure), + * it must call this function to attempt recovery. + * + * When the wifi HAL receiveds triggerSubsystemRestart(), it must restart + * the wlan subsystem, especially the wlan firmware. + * + * Regarding the callback function for subsystem restart, refer to documentation of + * |IWifiEventCallback.onSubsystemRestart| for details. + * + * @return status WifiStatus of the operation. + * Possible status codes: + * |WifiStatusCode.SUCCESS|, + * |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|, + * |WifiStatusCode.ERROR_NOT_AVAILABLE|, + * |WifiStatusCode.ERROR_UNKNOWN| + */ + triggerSubsystemRestart() generates (WifiStatus status); +}; diff --git a/wifi/1.5/IWifiEventCallback.hal b/wifi/1.5/IWifiEventCallback.hal new file mode 100644 index 0000000000000000000000000000000000000000..ff276306fddaa3662ae77856dc1b83d4b3a5621f --- /dev/null +++ b/wifi/1.5/IWifiEventCallback.hal @@ -0,0 +1,28 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.wifi@1.5; + +import @1.0::IWifiEventCallback; +import @1.0::WifiStatus; + +interface IWifiEventCallback extends @1.0::IWifiEventCallback { + /** + * Must be called when the Wi-Fi subsystem restart completes. + * Once this event is received, framework must fully reset the Wi-Fi stack state. + */ + oneway onSubsystemRestart(WifiStatus status); +}; diff --git a/wifi/1.5/IWifiNanIface.hal b/wifi/1.5/IWifiNanIface.hal new file mode 100644 index 0000000000000000000000000000000000000000..d7c15de9d8c31ff2917b516a5d10cb28ddf4cdc1 --- /dev/null +++ b/wifi/1.5/IWifiNanIface.hal @@ -0,0 +1,112 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.wifi@1.5; + +import @1.0::CommandIdShort; +import @1.0::WifiStatus; +import @1.4::IWifiNanIface; +import @1.4::NanConfigRequest; +import @1.4::NanEnableRequest; +import IWifiNanIfaceEventCallback; +import NanConfigRequestSupplemental; + +/** + * Interface used to represent a single NAN (Neighbour Aware Network) iface. + * + * References to "NAN Spec" are to the Wi-Fi Alliance "Wi-Fi Neighbor Awareness + * Networking (NAN) Technical Specification". + */ +interface IWifiNanIface extends @1.4::IWifiNanIface { + /** + * Enable NAN: configures and activates NAN clustering (does not start + * a discovery session or set up data-interfaces or data-paths). Use the + * |IWifiNanIface.configureRequest| method to change the configuration of an already enabled + * NAN interface. + * Asynchronous response is with |IWifiNanIfaceEventCallback.notifyEnableResponse|. + * + * Note: supersedes the @1.4::IWifiNanIface.enableRequest() method which is deprecated as of + * HAL version 1.5. + * + * @param cmdId command Id to use for this invocation. + * @param msg1 Instance of |NanEnableRequest|. + * @param msg2 Instance of |NanConfigRequestSupplemental|. + * @return status WifiStatus of the operation. + * Possible status codes: + * |WifiStatusCode.SUCCESS|, + * |WifiStatusCode.ERROR_NOT_SUPPORTED|, + * |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|, + * |WifiStatusCode.ERROR_INVALID_ARGS|, + * |WifiStatusCode.ERROR_UNKNOWN| + */ + enableRequest_1_5(CommandIdShort cmdId, NanEnableRequest msg1, + NanConfigRequestSupplemental msg2) generates (WifiStatus status); + + /** + * Configure NAN: configures an existing NAN functionality (i.e. assumes + * |IWifiNanIface.enableRequest| already submitted and succeeded). + * Asynchronous response is with |IWifiNanIfaceEventCallback.notifyConfigResponse|. + * + * Note: supersedes the @1.4::IWifiNanIface.configRequest() method which is deprecated as of + * HAL version 1.5. + * + * @param cmdId command Id to use for this invocation. + * @param msg1 Instance of |NanConfigRequest|. + * @param msg2 Instance of |NanConfigRequestSupplemental|. + * @return status WifiStatus of the operation. + * Possible status codes: + * |WifiStatusCode.SUCCESS|, + * |WifiStatusCode.ERROR_NOT_SUPPORTED|, + * |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|, + * |WifiStatusCode.ERROR_INVALID_ARGS|, + * |WifiStatusCode.ERROR_UNKNOWN| + */ + configRequest_1_5(CommandIdShort cmdId, NanConfigRequest msg1, + NanConfigRequestSupplemental msg2) generates (WifiStatus status); + + /** + * Requests notifications of significant events on this iface. Multiple calls + * to this must register multiple callbacks each of which must receive all + * events. + * + * Note: supersedes the @1.2::IWifiNanIface.registerEventCallback() method which is deprecated + * as of HAL version 1.5. + * + * @param callback An instance of the |IWifiNanIfaceEventCallback| HIDL interface + * object. + * @return status WifiStatus of the operation. + * Possible status codes: + * |WifiStatusCode.SUCCESS|, + * |WifiStatusCode.ERROR_WIFI_IFACE_INVALID| + */ + registerEventCallback_1_5(IWifiNanIfaceEventCallback callback) generates (WifiStatus status); + + /** + * Get NAN capabilities. Asynchronous response is with + * |IWifiNanIfaceEventCallback.notifyCapabilitiesResponse|. + * + * Note: supersedes the @1.0::IWifiNanIface.getCapabilitiesRequest() method which is deprecated + * as of HAL version 1.5. + * + * @param cmdId command Id to use for this invocation. + * @return status WifiStatus of the operation. + * Possible status codes: + * |WifiStatusCode.SUCCESS|, + * |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|, + * |WifiStatusCode.ERROR_UNKNOWN| + */ + getCapabilitiesRequest_1_5(CommandIdShort cmdId) generates (WifiStatus status); +}; diff --git a/wifi/1.5/IWifiNanIfaceEventCallback.hal b/wifi/1.5/IWifiNanIfaceEventCallback.hal new file mode 100644 index 0000000000000000000000000000000000000000..046b702f4f1047a0b00a865955cd15fd1ba69730 --- /dev/null +++ b/wifi/1.5/IWifiNanIfaceEventCallback.hal @@ -0,0 +1,44 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.wifi@1.5; + +import @1.0::CommandIdShort; +import @1.0::WifiNanStatus; +import @1.2::IWifiNanIfaceEventCallback; + +/** + * NAN Response and Asynchronous Event Callbacks. + * + * References to "NAN Spec" are to the Wi-Fi Alliance "Wi-Fi Neighbor Awareness + * Networking (NAN) Technical Specification". + */ +interface IWifiNanIfaceEventCallback extends @1.2::IWifiNanIfaceEventCallback { + /** + * Asynchronous callback invoked in response to a capability request + * |IWifiNanIface.getCapabilitiesRequest|. + * + * Note: supersedes the @1.2::IWifiNanIfaceEventCallback.notifyCapabilitiesResponse() method + * which is deprecated as of HAL version 1.5. + * + * @param cmdId command Id corresponding to the original request. + * @param status WifiNanStatus of the operation. Possible status codes are: + * |NanStatusType.SUCCESS| + * @param capabilities Capability data. + */ + oneway notifyCapabilitiesResponse_1_5(CommandIdShort id, WifiNanStatus status, + NanCapabilities capabilities); +}; diff --git a/wifi/1.5/IWifiStaIface.hal b/wifi/1.5/IWifiStaIface.hal new file mode 100644 index 0000000000000000000000000000000000000000..daf545eb9c6a7261e1bba087b571a31f71ac9d33 --- /dev/null +++ b/wifi/1.5/IWifiStaIface.hal @@ -0,0 +1,57 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.wifi@1.5; + +import @1.0::WifiStatus; +import @1.3::IWifiStaIface; + +/** + * Interface used to represent a single STA iface. + * + * IWifiChip.createStaIface() must return a @1.5::IWifiStaIface when supported. + */ +interface IWifiStaIface extends @1.3::IWifiStaIface { + /** + * Retrieve the latest link layer stats. + * Must fail if |StaIfaceCapabilityMask.LINK_LAYER_STATS| is not set or if + * link layer stats collection hasn't been explicitly enabled. + * + * @return status WifiStatus of the operation. + * Possible status codes: + * |WifiStatusCode.SUCCESS|, + * |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|, + * |WifiStatusCode.ERROR_NOT_SUPPORTED|, + * |WifiStatusCode.ERROR_NOT_STARTED|, + * |WifiStatusCode.ERROR_NOT_AVAILABLE|, + * |WifiStatusCode.ERROR_UNKNOWN| + * @return stats Instance of |LinkLayerStats|. + */ + getLinkLayerStats_1_5() generates (WifiStatus status, StaLinkLayerStats stats); + + /** + * Turn on/off scan only mode for the interface. + * + * @param enable Indicate if scan only mode is to be turned on/off. + * @return status Status of the operation. + * Possible status codes: + * |WifiStatusCode.SUCCESS|, + * |WifiStatusCode.ERROR_NOT_SUPPORTED|, + * |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|, + * |WifiStatusCode.FAILURE_UNKNOWN| + */ + setScanMode(bool enable) generates (WifiStatus status); +}; diff --git a/wifi/1.4/default/Android.mk b/wifi/1.5/default/Android.mk similarity index 94% rename from wifi/1.4/default/Android.mk rename to wifi/1.5/default/Android.mk index 9cdf84c81cf48d12e56d026eb1fd14571812a564..1997b2209f9042dc865f7319c4b33c762de30b79 100644 --- a/wifi/1.4/default/Android.mk +++ b/wifi/1.5/default/Android.mk @@ -54,6 +54,7 @@ LOCAL_SRC_FILES := \ wifi_feature_flags.cpp \ wifi_iface_util.cpp \ wifi_legacy_hal.cpp \ + wifi_legacy_hal_factory.cpp \ wifi_legacy_hal_stubs.cpp \ wifi_mode_controller.cpp \ wifi_nan_iface.cpp \ @@ -70,11 +71,14 @@ LOCAL_SHARED_LIBRARIES := \ libutils \ libwifi-hal \ libwifi-system-iface \ + libxml2 \ android.hardware.wifi@1.0 \ android.hardware.wifi@1.1 \ android.hardware.wifi@1.2 \ android.hardware.wifi@1.3 \ - android.hardware.wifi@1.4 + android.hardware.wifi@1.4 \ + android.hardware.wifi@1.5 +LOCAL_C_INCLUDES += $(TOP)/external/libxml2/include LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH) include $(BUILD_STATIC_LIBRARY) @@ -101,11 +105,13 @@ LOCAL_SHARED_LIBRARIES := \ libutils \ libwifi-hal \ libwifi-system-iface \ + libxml2 \ android.hardware.wifi@1.0 \ android.hardware.wifi@1.1 \ android.hardware.wifi@1.2 \ android.hardware.wifi@1.3 \ - android.hardware.wifi@1.4 + android.hardware.wifi@1.4 \ + android.hardware.wifi@1.5 LOCAL_STATIC_LIBRARIES := \ android.hardware.wifi@1.0-service-lib LOCAL_INIT_RC := android.hardware.wifi@1.0-service.rc @@ -136,11 +142,13 @@ LOCAL_SHARED_LIBRARIES := \ libutils \ libwifi-hal \ libwifi-system-iface \ + libxml2 \ android.hardware.wifi@1.0 \ android.hardware.wifi@1.1 \ android.hardware.wifi@1.2 \ android.hardware.wifi@1.3 \ - android.hardware.wifi@1.4 + android.hardware.wifi@1.4 \ + android.hardware.wifi@1.5 LOCAL_STATIC_LIBRARIES := \ android.hardware.wifi@1.0-service-lib LOCAL_INIT_RC := android.hardware.wifi@1.0-service-lazy.rc @@ -176,6 +184,7 @@ LOCAL_STATIC_LIBRARIES := \ android.hardware.wifi@1.2 \ android.hardware.wifi@1.3 \ android.hardware.wifi@1.4 \ + android.hardware.wifi@1.5 \ android.hardware.wifi@1.0-service-lib LOCAL_SHARED_LIBRARIES := \ libbase \ diff --git a/wifi/1.4/default/OWNERS b/wifi/1.5/default/OWNERS similarity index 52% rename from wifi/1.4/default/OWNERS rename to wifi/1.5/default/OWNERS index 8bfb14882c8466954bd971a4603ab82e62077c61..cf81c798925338533dcb4d1968ea7de942b367f3 100644 --- a/wifi/1.4/default/OWNERS +++ b/wifi/1.5/default/OWNERS @@ -1,2 +1,2 @@ -rpius@google.com +arabawy@google.com etancohen@google.com diff --git a/wifi/1.4/default/THREADING.README b/wifi/1.5/default/THREADING.README similarity index 100% rename from wifi/1.4/default/THREADING.README rename to wifi/1.5/default/THREADING.README diff --git a/wifi/1.4/default/android.hardware.wifi@1.0-service-lazy.rc b/wifi/1.5/default/android.hardware.wifi@1.0-service-lazy.rc similarity index 89% rename from wifi/1.4/default/android.hardware.wifi@1.0-service-lazy.rc rename to wifi/1.5/default/android.hardware.wifi@1.0-service-lazy.rc index 061689dbe539d8acd79b839f2690a7cfbbad5a4d..bc6bb6a7e68cde9e7a2a315ac084066f76b22c0f 100644 --- a/wifi/1.4/default/android.hardware.wifi@1.0-service-lazy.rc +++ b/wifi/1.5/default/android.hardware.wifi@1.0-service-lazy.rc @@ -4,6 +4,7 @@ service vendor.wifi_hal_legacy /vendor/bin/hw/android.hardware.wifi@1.0-service- interface android.hardware.wifi@1.2::IWifi default interface android.hardware.wifi@1.3::IWifi default interface android.hardware.wifi@1.4::IWifi default + interface android.hardware.wifi@1.5::IWifi default oneshot disabled class hal diff --git a/wifi/1.4/default/android.hardware.wifi@1.0-service.rc b/wifi/1.5/default/android.hardware.wifi@1.0-service.rc similarity index 89% rename from wifi/1.4/default/android.hardware.wifi@1.0-service.rc rename to wifi/1.5/default/android.hardware.wifi@1.0-service.rc index 64a51b0ae85471eaf2a891b3607312556feed341..05706ef4f49d6ad5787f9166eeab74f008100de9 100644 --- a/wifi/1.4/default/android.hardware.wifi@1.0-service.rc +++ b/wifi/1.5/default/android.hardware.wifi@1.0-service.rc @@ -4,6 +4,7 @@ service vendor.wifi_hal_legacy /vendor/bin/hw/android.hardware.wifi@1.0-service interface android.hardware.wifi@1.2::IWifi default interface android.hardware.wifi@1.3::IWifi default interface android.hardware.wifi@1.4::IWifi default + interface android.hardware.wifi@1.5::IWifi default class hal capabilities NET_ADMIN NET_RAW SYS_MODULE user wifi diff --git a/wifi/1.4/default/android.hardware.wifi@1.0-service.xml b/wifi/1.5/default/android.hardware.wifi@1.0-service.xml similarity index 90% rename from wifi/1.4/default/android.hardware.wifi@1.0-service.xml rename to wifi/1.5/default/android.hardware.wifi@1.0-service.xml index b5d25cd140352550b14b48a2b2bd332060898b90..88dd1e32857f8023a89d3029f150c9813349fe2a 100644 --- a/wifi/1.4/default/android.hardware.wifi@1.0-service.xml +++ b/wifi/1.5/default/android.hardware.wifi@1.0-service.xml @@ -2,7 +2,7 @@ android.hardware.wifi hwbinder - 1.4 + 1.5 IWifi default diff --git a/wifi/1.4/default/hidl_callback_util.h b/wifi/1.5/default/hidl_callback_util.h similarity index 99% rename from wifi/1.4/default/hidl_callback_util.h rename to wifi/1.5/default/hidl_callback_util.h index fc601b804a1bd9229186f71e281b04ca4688356d..d14465875054884e34450fa29c05968f9e5c31d9 100644 --- a/wifi/1.4/default/hidl_callback_util.h +++ b/wifi/1.5/default/hidl_callback_util.h @@ -52,7 +52,7 @@ class HidlDeathHandler : public android::hardware::hidl_death_recipient { namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { namespace hidl_callback_util { template @@ -117,7 +117,7 @@ class HidlCallbackHandler { } // namespace hidl_callback_util } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/hidl_return_util.h b/wifi/1.5/default/hidl_return_util.h similarity index 99% rename from wifi/1.4/default/hidl_return_util.h rename to wifi/1.5/default/hidl_return_util.h index 99c70928b786026cd2eecfe21d9bbc2b33e4aadf..4455185283c471802e68ab1d5aef7675c52bffca 100644 --- a/wifi/1.4/default/hidl_return_util.h +++ b/wifi/1.5/default/hidl_return_util.h @@ -23,7 +23,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { namespace hidl_return_util { using namespace android::hardware::wifi::V1_0; @@ -113,7 +113,7 @@ Return validateAndCall( } // namespace hidl_return_util } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/hidl_struct_util.cpp b/wifi/1.5/default/hidl_struct_util.cpp similarity index 84% rename from wifi/1.4/default/hidl_struct_util.cpp rename to wifi/1.5/default/hidl_struct_util.cpp index fd1d5b11212e9501ebc894d82f7e0936aa7fbb29..338a8f13c1bd7eeefb7b8f79211dcbca782e07aa 100644 --- a/wifi/1.4/default/hidl_struct_util.cpp +++ b/wifi/1.5/default/hidl_struct_util.cpp @@ -22,7 +22,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { namespace hidl_struct_util { @@ -69,9 +69,9 @@ convertLegacyLoggerFeatureToHidlStaIfaceCapability(uint32_t feature) { return {}; } -V1_3::IWifiChip::ChipCapabilityMask convertLegacyFeatureToHidlChipCapability( - uint32_t feature) { - using HidlChipCaps = V1_3::IWifiChip::ChipCapabilityMask; +V1_5::IWifiChip::ChipCapabilityMask convertLegacyFeatureToHidlChipCapability( + uint64_t feature) { + using HidlChipCaps = V1_5::IWifiChip::ChipCapabilityMask; switch (feature) { case WIFI_FEATURE_SET_TX_POWER_LIMIT: return HidlChipCaps::SET_TX_POWER_LIMIT; @@ -81,6 +81,8 @@ V1_3::IWifiChip::ChipCapabilityMask convertLegacyFeatureToHidlChipCapability( return HidlChipCaps::D2D_RTT; case WIFI_FEATURE_D2AP_RTT: return HidlChipCaps::D2AP_RTT; + case WIFI_FEATURE_INFRA_60G: + return HidlChipCaps::WIGIG; case WIFI_FEATURE_SET_LATENCY_MODE: return HidlChipCaps::SET_LATENCY_MODE; case WIFI_FEATURE_P2P_RAND_MAC: @@ -126,7 +128,7 @@ convertLegacyFeatureToHidlStaIfaceCapability(uint64_t feature) { } bool convertLegacyFeaturesToHidlChipCapabilities( - uint32_t legacy_feature_set, uint32_t legacy_logger_feature_set, + uint64_t legacy_feature_set, uint32_t legacy_logger_feature_set, uint32_t* hidl_caps) { if (!hidl_caps) { return false; @@ -143,10 +145,11 @@ bool convertLegacyFeaturesToHidlChipCapabilities( convertLegacyLoggerFeatureToHidlChipCapability(feature); } } - std::vector features = {WIFI_FEATURE_SET_TX_POWER_LIMIT, + std::vector features = {WIFI_FEATURE_SET_TX_POWER_LIMIT, WIFI_FEATURE_USE_BODY_HEAD_SAR, WIFI_FEATURE_D2D_RTT, WIFI_FEATURE_D2AP_RTT, + WIFI_FEATURE_INFRA_60G, WIFI_FEATURE_SET_LATENCY_MODE, WIFI_FEATURE_P2P_RAND_MAC}; for (const auto feature : features) { @@ -314,7 +317,7 @@ legacy_hal::wifi_latency_mode convertHidlLatencyModeToLegacy( bool convertLegacyWifiMacInfoToHidl( const legacy_hal::WifiMacInfo& legacy_mac_info, - IWifiChipEventCallback::RadioModeInfo* hidl_radio_mode_info) { + V1_4::IWifiChipEventCallback::RadioModeInfo* hidl_radio_mode_info) { if (!hidl_radio_mode_info) { return false; } @@ -326,21 +329,21 @@ bool convertLegacyWifiMacInfoToHidl( if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_6_0_BAND && legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_5_0_BAND && legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_2_4_BAND) { - hidl_radio_mode_info->bandInfo = WifiBand::BAND_24GHZ_5GHZ_6GHZ; + hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_24GHZ_5GHZ_6GHZ; } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_6_0_BAND && legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_5_0_BAND) { - hidl_radio_mode_info->bandInfo = WifiBand::BAND_5GHZ_6GHZ; + hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_5GHZ_6GHZ; } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_6_0_BAND) { - hidl_radio_mode_info->bandInfo = WifiBand::BAND_6GHZ; + hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_6GHZ; } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_2_4_BAND && legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_5_0_BAND) { - hidl_radio_mode_info->bandInfo = WifiBand::BAND_24GHZ_5GHZ; + hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_24GHZ_5GHZ; } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_2_4_BAND) { - hidl_radio_mode_info->bandInfo = WifiBand::BAND_24GHZ; + hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_24GHZ; } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_5_0_BAND) { - hidl_radio_mode_info->bandInfo = WifiBand::BAND_5GHZ; + hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_5GHZ; } else { - hidl_radio_mode_info->bandInfo = WifiBand::BAND_UNSPECIFIED; + hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_UNSPECIFIED; } std::vector iface_info_vec; for (const auto& legacy_iface_info : legacy_mac_info.iface_infos) { @@ -353,16 +356,154 @@ bool convertLegacyWifiMacInfoToHidl( return true; } +uint32_t convertHidlWifiBandToLegacyMacBand(V1_5::WifiBand hidl_band) { + switch (hidl_band) { + case V1_5::WifiBand::BAND_24GHZ: + return legacy_hal::WLAN_MAC_2_4_BAND; + case V1_5::WifiBand::BAND_5GHZ: + case V1_5::WifiBand::BAND_5GHZ_DFS: + case V1_5::WifiBand::BAND_5GHZ_WITH_DFS: + return legacy_hal::WLAN_MAC_5_0_BAND; + case V1_5::WifiBand::BAND_24GHZ_5GHZ: + case V1_5::WifiBand::BAND_24GHZ_5GHZ_WITH_DFS: + return (legacy_hal::WLAN_MAC_2_4_BAND | + legacy_hal::WLAN_MAC_5_0_BAND); + case V1_5::WifiBand::BAND_6GHZ: + return legacy_hal::WLAN_MAC_6_0_BAND; + case V1_5::WifiBand::BAND_5GHZ_6GHZ: + return (legacy_hal::WLAN_MAC_5_0_BAND | + legacy_hal::WLAN_MAC_6_0_BAND); + case V1_5::WifiBand::BAND_24GHZ_5GHZ_6GHZ: + case V1_5::WifiBand::BAND_24GHZ_5GHZ_WITH_DFS_6GHZ: + return (legacy_hal::WLAN_MAC_2_4_BAND | + legacy_hal::WLAN_MAC_5_0_BAND | + legacy_hal::WLAN_MAC_6_0_BAND); + case V1_5::WifiBand::BAND_60GHZ: + return legacy_hal::WLAN_MAC_60_0_BAND; + default: + return ( + legacy_hal::WLAN_MAC_2_4_BAND | legacy_hal::WLAN_MAC_5_0_BAND | + legacy_hal::WLAN_MAC_6_0_BAND | legacy_hal::WLAN_MAC_60_0_BAND); + } +} + +uint32_t convertHidlWifiIfaceModeToLegacy(uint32_t hidl_iface_mask) { + uint32_t legacy_iface_mask = 0; + if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_STA) { + legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_STA); + } + if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_SOFTAP) { + legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_SOFTAP); + } + if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_P2P_CLIENT) { + legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_P2P_CLIENT); + } + if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_P2P_GO) { + legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_P2P_GO); + } + if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_NAN) { + legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_NAN); + } + if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_TDLS) { + legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_TDLS); + } + if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_MESH) { + legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_MESH); + } + if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_IBSS) { + legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_IBSS); + } + return legacy_iface_mask; +} + +uint32_t convertLegacyWifiInterfaceModeToHidl(uint32_t legacy_iface_mask) { + uint32_t hidl_iface_mask = 0; + if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_STA)) { + hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_STA; + } + if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_SOFTAP)) { + hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_SOFTAP; + } + if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_P2P_CLIENT)) { + hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_P2P_CLIENT; + } + if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_P2P_GO)) { + hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_P2P_GO; + } + if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_NAN)) { + hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_NAN; + } + if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_TDLS)) { + hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_TDLS; + } + if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_MESH)) { + hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_MESH; + } + if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_IBSS)) { + hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_IBSS; + } + return hidl_iface_mask; +} + +uint32_t convertHidlUsableChannelFilterToLegacy(uint32_t hidl_filter_mask) { + uint32_t legacy_filter_mask = 0; + if (hidl_filter_mask & + IWifiChip::UsableChannelFilter::CELLULAR_COEXISTENCE) { + legacy_filter_mask |= + legacy_hal::WIFI_USABLE_CHANNEL_FILTER_CELLULAR_COEXISTENCE; + } + if (hidl_filter_mask & IWifiChip::UsableChannelFilter::CONCURRENCY) { + legacy_filter_mask |= + legacy_hal::WIFI_USABLE_CHANNEL_FILTER_CONCURRENCY; + } + return legacy_filter_mask; +} + +bool convertLegacyWifiUsableChannelToHidl( + const legacy_hal::wifi_usable_channel& legacy_usable_channel, + V1_5::WifiUsableChannel* hidl_usable_channel) { + if (!hidl_usable_channel) { + return false; + } + *hidl_usable_channel = {}; + hidl_usable_channel->channel = legacy_usable_channel.freq; + hidl_usable_channel->channelBandwidth = + convertLegacyWifiChannelWidthToHidl(legacy_usable_channel.width); + hidl_usable_channel->ifaceModeMask = convertLegacyWifiInterfaceModeToHidl( + legacy_usable_channel.iface_mode_mask); + + return true; +} + +bool convertLegacyWifiUsableChannelsToHidl( + const std::vector& legacy_usable_channels, + std::vector* hidl_usable_channels) { + if (!hidl_usable_channels) { + return false; + } + *hidl_usable_channels = {}; + for (const auto& legacy_usable_channel : legacy_usable_channels) { + V1_5::WifiUsableChannel hidl_usable_channel; + if (!convertLegacyWifiUsableChannelToHidl(legacy_usable_channel, + &hidl_usable_channel)) { + return false; + } + hidl_usable_channels->push_back(hidl_usable_channel); + } + return true; +} + bool convertLegacyWifiMacInfosToHidl( const std::vector& legacy_mac_infos, - std::vector* hidl_radio_mode_infos) { + std::vector* + hidl_radio_mode_infos) { if (!hidl_radio_mode_infos) { return false; } *hidl_radio_mode_infos = {}; for (const auto& legacy_mac_info : legacy_mac_infos) { - IWifiChipEventCallback::RadioModeInfo hidl_radio_mode_info; + V1_4::IWifiChipEventCallback::RadioModeInfo hidl_radio_mode_info; if (!convertLegacyWifiMacInfoToHidl(legacy_mac_info, &hidl_radio_mode_info)) { return false; @@ -813,27 +954,29 @@ bool convertLegacyVectorOfDebugRxPacketFateToHidl( bool convertLegacyLinkLayerRadioStatsToHidl( const legacy_hal::LinkLayerRadioStats& legacy_radio_stat, - V1_3::StaLinkLayerRadioStats* hidl_radio_stat) { + V1_5::StaLinkLayerRadioStats* hidl_radio_stat) { if (!hidl_radio_stat) { return false; } *hidl_radio_stat = {}; - hidl_radio_stat->V1_0.onTimeInMs = legacy_radio_stat.stats.on_time; - hidl_radio_stat->V1_0.txTimeInMs = legacy_radio_stat.stats.tx_time; - hidl_radio_stat->V1_0.rxTimeInMs = legacy_radio_stat.stats.rx_time; - hidl_radio_stat->V1_0.onTimeInMsForScan = + hidl_radio_stat->radioId = legacy_radio_stat.stats.radio; + hidl_radio_stat->V1_3.V1_0.onTimeInMs = legacy_radio_stat.stats.on_time; + hidl_radio_stat->V1_3.V1_0.txTimeInMs = legacy_radio_stat.stats.tx_time; + hidl_radio_stat->V1_3.V1_0.rxTimeInMs = legacy_radio_stat.stats.rx_time; + hidl_radio_stat->V1_3.V1_0.onTimeInMsForScan = legacy_radio_stat.stats.on_time_scan; - hidl_radio_stat->V1_0.txTimeInMsPerLevel = + hidl_radio_stat->V1_3.V1_0.txTimeInMsPerLevel = legacy_radio_stat.tx_time_per_levels; - hidl_radio_stat->onTimeInMsForNanScan = legacy_radio_stat.stats.on_time_nbd; - hidl_radio_stat->onTimeInMsForBgScan = + hidl_radio_stat->V1_3.onTimeInMsForNanScan = + legacy_radio_stat.stats.on_time_nbd; + hidl_radio_stat->V1_3.onTimeInMsForBgScan = legacy_radio_stat.stats.on_time_gscan; - hidl_radio_stat->onTimeInMsForRoamScan = + hidl_radio_stat->V1_3.onTimeInMsForRoamScan = legacy_radio_stat.stats.on_time_roam_scan; - hidl_radio_stat->onTimeInMsForPnoScan = + hidl_radio_stat->V1_3.onTimeInMsForPnoScan = legacy_radio_stat.stats.on_time_pno_scan; - hidl_radio_stat->onTimeInMsForHs20Scan = + hidl_radio_stat->V1_3.onTimeInMsForHs20Scan = legacy_radio_stat.stats.on_time_hs20; std::vector hidl_channel_stats; @@ -855,57 +998,102 @@ bool convertLegacyLinkLayerRadioStatsToHidl( hidl_channel_stats.push_back(hidl_channel_stat); } - hidl_radio_stat->channelStats = hidl_channel_stats; + hidl_radio_stat->V1_3.channelStats = hidl_channel_stats; return true; } bool convertLegacyLinkLayerStatsToHidl( const legacy_hal::LinkLayerStats& legacy_stats, - V1_3::StaLinkLayerStats* hidl_stats) { + StaLinkLayerStats* hidl_stats) { if (!hidl_stats) { return false; } *hidl_stats = {}; // iface legacy_stats conversion. - hidl_stats->iface.beaconRx = legacy_stats.iface.beacon_rx; - hidl_stats->iface.avgRssiMgmt = legacy_stats.iface.rssi_mgmt; - hidl_stats->iface.wmeBePktStats.rxMpdu = + hidl_stats->iface.V1_0.beaconRx = legacy_stats.iface.beacon_rx; + hidl_stats->iface.V1_0.avgRssiMgmt = legacy_stats.iface.rssi_mgmt; + hidl_stats->iface.V1_0.wmeBePktStats.rxMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu; - hidl_stats->iface.wmeBePktStats.txMpdu = + hidl_stats->iface.V1_0.wmeBePktStats.txMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu; - hidl_stats->iface.wmeBePktStats.lostMpdu = + hidl_stats->iface.V1_0.wmeBePktStats.lostMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost; - hidl_stats->iface.wmeBePktStats.retries = + hidl_stats->iface.V1_0.wmeBePktStats.retries = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries; - hidl_stats->iface.wmeBkPktStats.rxMpdu = + hidl_stats->iface.wmeBeContentionTimeStats.contentionTimeMinInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_min; + hidl_stats->iface.wmeBeContentionTimeStats.contentionTimeMaxInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_max; + hidl_stats->iface.wmeBeContentionTimeStats.contentionTimeAvgInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_avg; + hidl_stats->iface.wmeBeContentionTimeStats.contentionNumSamples = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_num_samples; + hidl_stats->iface.V1_0.wmeBkPktStats.rxMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu; - hidl_stats->iface.wmeBkPktStats.txMpdu = + hidl_stats->iface.V1_0.wmeBkPktStats.txMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu; - hidl_stats->iface.wmeBkPktStats.lostMpdu = + hidl_stats->iface.V1_0.wmeBkPktStats.lostMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost; - hidl_stats->iface.wmeBkPktStats.retries = + hidl_stats->iface.V1_0.wmeBkPktStats.retries = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries; - hidl_stats->iface.wmeViPktStats.rxMpdu = + hidl_stats->iface.wmeBkContentionTimeStats.contentionTimeMinInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_min; + hidl_stats->iface.wmeBkContentionTimeStats.contentionTimeMaxInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_max; + hidl_stats->iface.wmeBkContentionTimeStats.contentionTimeAvgInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_avg; + hidl_stats->iface.wmeBkContentionTimeStats.contentionNumSamples = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_num_samples; + hidl_stats->iface.V1_0.wmeViPktStats.rxMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu; - hidl_stats->iface.wmeViPktStats.txMpdu = + hidl_stats->iface.V1_0.wmeViPktStats.txMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu; - hidl_stats->iface.wmeViPktStats.lostMpdu = + hidl_stats->iface.V1_0.wmeViPktStats.lostMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost; - hidl_stats->iface.wmeViPktStats.retries = + hidl_stats->iface.V1_0.wmeViPktStats.retries = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries; - hidl_stats->iface.wmeVoPktStats.rxMpdu = + hidl_stats->iface.wmeViContentionTimeStats.contentionTimeMinInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_min; + hidl_stats->iface.wmeViContentionTimeStats.contentionTimeMaxInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_max; + hidl_stats->iface.wmeViContentionTimeStats.contentionTimeAvgInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_avg; + hidl_stats->iface.wmeViContentionTimeStats.contentionNumSamples = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_num_samples; + hidl_stats->iface.V1_0.wmeVoPktStats.rxMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu; - hidl_stats->iface.wmeVoPktStats.txMpdu = + hidl_stats->iface.V1_0.wmeVoPktStats.txMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu; - hidl_stats->iface.wmeVoPktStats.lostMpdu = + hidl_stats->iface.V1_0.wmeVoPktStats.lostMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost; - hidl_stats->iface.wmeVoPktStats.retries = + hidl_stats->iface.V1_0.wmeVoPktStats.retries = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries; + hidl_stats->iface.wmeVoContentionTimeStats.contentionTimeMinInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_min; + hidl_stats->iface.wmeVoContentionTimeStats.contentionTimeMaxInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_max; + hidl_stats->iface.wmeVoContentionTimeStats.contentionTimeAvgInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_avg; + hidl_stats->iface.wmeVoContentionTimeStats.contentionNumSamples = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_num_samples; + hidl_stats->iface.timeSliceDutyCycleInPercent = + legacy_stats.iface.info.time_slicing_duty_cycle_percent; + // peer info legacy_stats conversion. + std::vector hidl_peers_info_stats; + for (const auto& legacy_peer_info_stats : legacy_stats.peers) { + StaPeerInfo hidl_peer_info_stats; + if (!convertLegacyPeerInfoStatsToHidl(legacy_peer_info_stats, + &hidl_peer_info_stats)) { + return false; + } + hidl_peers_info_stats.push_back(hidl_peer_info_stats); + } + hidl_stats->iface.peers = hidl_peers_info_stats; // radio legacy_stats conversion. - std::vector hidl_radios_stats; + std::vector hidl_radios_stats; for (const auto& legacy_radio_stats : legacy_stats.radios) { - V1_3::StaLinkLayerRadioStats hidl_radio_stats; + V1_5::StaLinkLayerRadioStats hidl_radio_stats; if (!convertLegacyLinkLayerRadioStatsToHidl(legacy_radio_stats, &hidl_radio_stats)) { return false; @@ -919,6 +1107,35 @@ bool convertLegacyLinkLayerStatsToHidl( return true; } +bool convertLegacyPeerInfoStatsToHidl( + const legacy_hal::WifiPeerInfo& legacy_peer_info_stats, + StaPeerInfo* hidl_peer_info_stats) { + if (!hidl_peer_info_stats) { + return false; + } + *hidl_peer_info_stats = {}; + hidl_peer_info_stats->staCount = + legacy_peer_info_stats.peer_info.bssload.sta_count; + hidl_peer_info_stats->chanUtil = + legacy_peer_info_stats.peer_info.bssload.chan_util; + + std::vector hidlRateStats; + for (const auto& legacy_rate_stats : legacy_peer_info_stats.rate_stats) { + StaRateStat rateStat; + if (!convertLegacyWifiRateInfoToHidl(legacy_rate_stats.rate, + &rateStat.rateInfo)) { + return false; + } + rateStat.txMpdu = legacy_rate_stats.tx_mpdu; + rateStat.rxMpdu = legacy_rate_stats.rx_mpdu; + rateStat.mpduLost = legacy_rate_stats.mpdu_lost; + rateStat.retries = legacy_rate_stats.retries; + hidlRateStats.push_back(rateStat); + } + hidl_peer_info_stats->rateStats = hidlRateStats; + return true; +} + bool convertLegacyRoamingCapabilitiesToHidl( const legacy_hal::wifi_roaming_capabilities& legacy_caps, StaRoamingCapabilities* hidl_caps) { @@ -1079,7 +1296,7 @@ void convertToWifiNanStatus(legacy_hal::NanStatusType type, const char* str, } bool convertHidlNanEnableRequestToLegacy( - const NanEnableRequest& hidl_request, + const V1_4::NanEnableRequest& hidl_request, legacy_hal::NanEnableRequest* legacy_request) { if (!legacy_request) { LOG(ERROR) @@ -1275,8 +1492,8 @@ bool convertHidlNanEnableRequestToLegacy( } bool convertHidlNanEnableRequest_1_4ToLegacy( - const NanEnableRequest& hidl_request1, - const V1_2::NanConfigRequestSupplemental& hidl_request2, + const V1_4::NanEnableRequest& hidl_request1, + const NanConfigRequestSupplemental& hidl_request2, legacy_hal::NanEnableRequest* legacy_request) { if (!legacy_request) { LOG(ERROR) @@ -1291,14 +1508,60 @@ bool convertHidlNanEnableRequest_1_4ToLegacy( legacy_request->config_discovery_beacon_int = 1; legacy_request->discovery_beacon_interval = - hidl_request2.discoveryBeaconIntervalMs; + hidl_request2.V1_2.discoveryBeaconIntervalMs; legacy_request->config_nss = 1; - legacy_request->nss = hidl_request2.numberOfSpatialStreamsInDiscovery; + legacy_request->nss = hidl_request2.V1_2.numberOfSpatialStreamsInDiscovery; legacy_request->config_dw_early_termination = 1; legacy_request->enable_dw_termination = - hidl_request2.enableDiscoveryWindowEarlyTermination; + hidl_request2.V1_2.enableDiscoveryWindowEarlyTermination; legacy_request->config_enable_ranging = 1; - legacy_request->enable_ranging = hidl_request2.enableRanging; + legacy_request->enable_ranging = hidl_request2.V1_2.enableRanging; + + return true; +} + +bool convertHidlNanEnableRequest_1_5ToLegacy( + const V1_4::NanEnableRequest& hidl_request1, + const NanConfigRequestSupplemental& hidl_request2, + legacy_hal::NanEnableRequest* legacy_request) { + if (!legacy_request) { + LOG(ERROR) + << "convertHidlNanEnableRequest_1_5ToLegacy: null legacy_request"; + return false; + } + + *legacy_request = {}; + if (!convertHidlNanEnableRequest_1_4ToLegacy(hidl_request1, hidl_request2, + legacy_request)) { + return false; + } + + legacy_request->config_enable_instant_mode = 1; + legacy_request->enable_instant_mode = + hidl_request2.enableInstantCommunicationMode; + + return true; +} + +bool convertHidlNanConfigRequest_1_5ToLegacy( + const V1_4::NanConfigRequest& hidl_request1, + const NanConfigRequestSupplemental& hidl_request2, + legacy_hal::NanConfigRequest* legacy_request) { + if (!legacy_request) { + LOG(ERROR) + << "convertHidlNanConfigRequest_1_5ToLegacy: null legacy_request"; + return false; + } + + *legacy_request = {}; + if (!convertHidlNanConfigRequest_1_4ToLegacy(hidl_request1, hidl_request2, + legacy_request)) { + return false; + } + + legacy_request->config_enable_instant_mode = 1; + legacy_request->enable_instant_mode = + hidl_request2.enableInstantCommunicationMode; return true; } @@ -1674,7 +1937,7 @@ bool convertHidlNanTransmitFollowupRequestToLegacy( } bool convertHidlNanConfigRequestToLegacy( - const NanConfigRequest& hidl_request, + const V1_4::NanConfigRequest& hidl_request, legacy_hal::NanConfigRequest* legacy_request) { if (!legacy_request) { LOG(ERROR) @@ -1789,8 +2052,8 @@ bool convertHidlNanConfigRequestToLegacy( } bool convertHidlNanConfigRequest_1_4ToLegacy( - const NanConfigRequest& hidl_request1, - const V1_2::NanConfigRequestSupplemental& hidl_request2, + const V1_4::NanConfigRequest& hidl_request1, + const NanConfigRequestSupplemental& hidl_request2, legacy_hal::NanConfigRequest* legacy_request) { if (!legacy_request) { LOG(ERROR) << "convertHidlNanConfigRequest_1_4ToLegacy: legacy_request " @@ -1805,14 +2068,14 @@ bool convertHidlNanConfigRequest_1_4ToLegacy( legacy_request->config_discovery_beacon_int = 1; legacy_request->discovery_beacon_interval = - hidl_request2.discoveryBeaconIntervalMs; + hidl_request2.V1_2.discoveryBeaconIntervalMs; legacy_request->config_nss = 1; - legacy_request->nss = hidl_request2.numberOfSpatialStreamsInDiscovery; + legacy_request->nss = hidl_request2.V1_2.numberOfSpatialStreamsInDiscovery; legacy_request->config_dw_early_termination = 1; legacy_request->enable_dw_termination = - hidl_request2.enableDiscoveryWindowEarlyTermination; + hidl_request2.V1_2.enableDiscoveryWindowEarlyTermination; legacy_request->config_enable_ranging = 1; - legacy_request->enable_ranging = hidl_request2.enableRanging; + legacy_request->enable_ranging = hidl_request2.V1_2.enableRanging; return true; } @@ -2019,27 +2282,31 @@ bool convertLegacyNanCapabilitiesResponseToHidl( } *hidl_response = {}; - hidl_response->maxConcurrentClusters = + hidl_response->V1_0.maxConcurrentClusters = legacy_response.max_concurrent_nan_clusters; - hidl_response->maxPublishes = legacy_response.max_publishes; - hidl_response->maxSubscribes = legacy_response.max_subscribes; - hidl_response->maxServiceNameLen = legacy_response.max_service_name_len; - hidl_response->maxMatchFilterLen = legacy_response.max_match_filter_len; - hidl_response->maxTotalMatchFilterLen = + hidl_response->V1_0.maxPublishes = legacy_response.max_publishes; + hidl_response->V1_0.maxSubscribes = legacy_response.max_subscribes; + hidl_response->V1_0.maxServiceNameLen = + legacy_response.max_service_name_len; + hidl_response->V1_0.maxMatchFilterLen = + legacy_response.max_match_filter_len; + hidl_response->V1_0.maxTotalMatchFilterLen = legacy_response.max_total_match_filter_len; - hidl_response->maxServiceSpecificInfoLen = + hidl_response->V1_0.maxServiceSpecificInfoLen = legacy_response.max_service_specific_info_len; - hidl_response->maxExtendedServiceSpecificInfoLen = + hidl_response->V1_0.maxExtendedServiceSpecificInfoLen = legacy_response.max_sdea_service_specific_info_len; - hidl_response->maxNdiInterfaces = legacy_response.max_ndi_interfaces; - hidl_response->maxNdpSessions = legacy_response.max_ndp_sessions; - hidl_response->maxAppInfoLen = legacy_response.max_app_info_len; - hidl_response->maxQueuedTransmitFollowupMsgs = + hidl_response->V1_0.maxNdiInterfaces = legacy_response.max_ndi_interfaces; + hidl_response->V1_0.maxNdpSessions = legacy_response.max_ndp_sessions; + hidl_response->V1_0.maxAppInfoLen = legacy_response.max_app_info_len; + hidl_response->V1_0.maxQueuedTransmitFollowupMsgs = legacy_response.max_queued_transmit_followup_msgs; - hidl_response->maxSubscribeInterfaceAddresses = + hidl_response->V1_0.maxSubscribeInterfaceAddresses = legacy_response.max_subscribe_address; - hidl_response->supportedCipherSuites = + hidl_response->V1_0.supportedCipherSuites = legacy_response.cipher_suites_supported; + hidl_response->instantCommunicationModeSupportFlag = + legacy_response.is_instant_mode_supported; return true; } @@ -2292,36 +2559,37 @@ WifiChannelWidthInMhz convertLegacyWifiChannelWidthToHidl( return WifiChannelWidthInMhz::WIDTH_5; case legacy_hal::WIFI_CHAN_WIDTH_10: return WifiChannelWidthInMhz::WIDTH_10; - case legacy_hal::WIFI_CHAN_WIDTH_INVALID: + default: return WifiChannelWidthInMhz::WIDTH_INVALID; }; - CHECK(false) << "Unknown legacy type: " << type; } -legacy_hal::wifi_rtt_preamble convertHidlRttPreambleToLegacy(RttPreamble type) { +legacy_hal::wifi_rtt_preamble convertHidlRttPreambleToLegacy( + V1_4::RttPreamble type) { switch (type) { - case RttPreamble::LEGACY: + case V1_4::RttPreamble::LEGACY: return legacy_hal::WIFI_RTT_PREAMBLE_LEGACY; - case RttPreamble::HT: + case V1_4::RttPreamble::HT: return legacy_hal::WIFI_RTT_PREAMBLE_HT; - case RttPreamble::VHT: + case V1_4::RttPreamble::VHT: return legacy_hal::WIFI_RTT_PREAMBLE_VHT; - case RttPreamble::HE: + case V1_4::RttPreamble::HE: return legacy_hal::WIFI_RTT_PREAMBLE_HE; }; CHECK(false); } -RttPreamble convertLegacyRttPreambleToHidl(legacy_hal::wifi_rtt_preamble type) { +V1_4::RttPreamble convertLegacyRttPreambleToHidl( + legacy_hal::wifi_rtt_preamble type) { switch (type) { case legacy_hal::WIFI_RTT_PREAMBLE_LEGACY: - return RttPreamble::LEGACY; + return V1_4::RttPreamble::LEGACY; case legacy_hal::WIFI_RTT_PREAMBLE_HT: - return RttPreamble::HT; + return V1_4::RttPreamble::HT; case legacy_hal::WIFI_RTT_PREAMBLE_VHT: - return RttPreamble::VHT; + return V1_4::RttPreamble::VHT; case legacy_hal::WIFI_RTT_PREAMBLE_HE: - return RttPreamble::HE; + return V1_4::RttPreamble::HE; }; CHECK(false) << "Unknown legacy type: " << type; } @@ -2375,20 +2643,20 @@ legacy_hal::wifi_motion_pattern convertHidlRttMotionPatternToLegacy( CHECK(false); } -WifiRatePreamble convertLegacyWifiRatePreambleToHidl(uint8_t preamble) { +V1_4::WifiRatePreamble convertLegacyWifiRatePreambleToHidl(uint8_t preamble) { switch (preamble) { case 0: - return WifiRatePreamble::OFDM; + return V1_4::WifiRatePreamble::OFDM; case 1: - return WifiRatePreamble::CCK; + return V1_4::WifiRatePreamble::CCK; case 2: - return WifiRatePreamble::HT; + return V1_4::WifiRatePreamble::HT; case 3: - return WifiRatePreamble::VHT; + return V1_4::WifiRatePreamble::VHT; case 4: - return WifiRatePreamble::HE; + return V1_4::WifiRatePreamble::HE; default: - return WifiRatePreamble::RESERVED; + return V1_4::WifiRatePreamble::RESERVED; }; CHECK(false) << "Unknown legacy preamble: " << preamble; } @@ -2478,7 +2746,7 @@ bool convertLegacyWifiChannelInfoToHidl( return true; } -bool convertHidlRttConfigToLegacy(const RttConfig& hidl_config, +bool convertHidlRttConfigToLegacy(const V1_4::RttConfig& hidl_config, legacy_hal::wifi_rtt_config* legacy_config) { if (!legacy_config) { return false; @@ -2509,7 +2777,7 @@ bool convertHidlRttConfigToLegacy(const RttConfig& hidl_config, } bool convertHidlVectorOfRttConfigToLegacy( - const std::vector& hidl_configs, + const std::vector& hidl_configs, std::vector* legacy_configs) { if (!legacy_configs) { return false; @@ -2566,7 +2834,7 @@ bool convertHidlRttLcrInformationToLegacy( } bool convertHidlRttResponderToLegacy( - const RttResponder& hidl_responder, + const V1_4::RttResponder& hidl_responder, legacy_hal::wifi_rtt_responder* legacy_responder) { if (!legacy_responder) { return false; @@ -2583,7 +2851,7 @@ bool convertHidlRttResponderToLegacy( bool convertLegacyRttResponderToHidl( const legacy_hal::wifi_rtt_responder& legacy_responder, - RttResponder* hidl_responder) { + V1_4::RttResponder* hidl_responder) { if (!hidl_responder) { return false; } @@ -2599,7 +2867,7 @@ bool convertLegacyRttResponderToHidl( bool convertLegacyRttCapabilitiesToHidl( const legacy_hal::wifi_rtt_capabilities& legacy_capabilities, - RttCapabilities* hidl_capabilities) { + V1_4::RttCapabilities* hidl_capabilities) { if (!hidl_capabilities) { return false; } @@ -2618,7 +2886,7 @@ bool convertLegacyRttCapabilitiesToHidl( legacy_hal::WIFI_RTT_PREAMBLE_HE}) { if (legacy_capabilities.preamble_support & flag) { hidl_capabilities->preambleSupport |= - static_cast::type>( + static_cast::type>( convertLegacyRttPreambleToHidl(flag)); } } @@ -2638,7 +2906,7 @@ bool convertLegacyRttCapabilitiesToHidl( } bool convertLegacyWifiRateInfoToHidl(const legacy_hal::wifi_rate& legacy_rate, - WifiRateInfo* hidl_rate) { + V1_4::WifiRateInfo* hidl_rate) { if (!hidl_rate) { return false; } @@ -2654,7 +2922,8 @@ bool convertLegacyWifiRateInfoToHidl(const legacy_hal::wifi_rate& legacy_rate, } bool convertLegacyRttResultToHidl( - const legacy_hal::wifi_rtt_result& legacy_result, RttResult* hidl_result) { + const legacy_hal::wifi_rtt_result& legacy_result, + V1_4::RttResult* hidl_result) { if (!hidl_result) { return false; } @@ -2701,13 +2970,13 @@ bool convertLegacyRttResultToHidl( bool convertLegacyVectorOfRttResultToHidl( const std::vector& legacy_results, - std::vector* hidl_results) { + std::vector* hidl_results) { if (!hidl_results) { return false; } *hidl_results = {}; for (const auto legacy_result : legacy_results) { - RttResult hidl_result; + V1_4::RttResult hidl_result; if (!convertLegacyRttResultToHidl(*legacy_result, &hidl_result)) { return false; } @@ -2730,9 +2999,61 @@ legacy_hal::wifi_interface_type convertHidlIfaceTypeToLegacy( } CHECK(false); } + +legacy_hal::wifi_multi_sta_use_case convertHidlMultiStaUseCaseToLegacy( + IWifiChip::MultiStaUseCase use_case) { + switch (use_case) { + case IWifiChip::MultiStaUseCase::DUAL_STA_TRANSIENT_PREFER_PRIMARY: + return legacy_hal::WIFI_DUAL_STA_TRANSIENT_PREFER_PRIMARY; + case IWifiChip::MultiStaUseCase::DUAL_STA_NON_TRANSIENT_UNBIASED: + return legacy_hal::WIFI_DUAL_STA_NON_TRANSIENT_UNBIASED; + } + CHECK(false); +} + +bool convertHidlCoexUnsafeChannelToLegacy( + const IWifiChip::CoexUnsafeChannel& hidl_unsafe_channel, + legacy_hal::wifi_coex_unsafe_channel* legacy_unsafe_channel) { + if (!legacy_unsafe_channel) { + return false; + } + *legacy_unsafe_channel = {}; + switch (hidl_unsafe_channel.band) { + case WifiBand::BAND_24GHZ: + legacy_unsafe_channel->band = legacy_hal::WLAN_MAC_2_4_BAND; + break; + case WifiBand::BAND_5GHZ: + legacy_unsafe_channel->band = legacy_hal::WLAN_MAC_5_0_BAND; + break; + default: + return false; + }; + legacy_unsafe_channel->channel = hidl_unsafe_channel.channel; + legacy_unsafe_channel->power_cap_dbm = hidl_unsafe_channel.powerCapDbm; + return true; +} + +bool convertHidlVectorOfCoexUnsafeChannelToLegacy( + const std::vector& hidl_unsafe_channels, + std::vector* legacy_unsafe_channels) { + if (!legacy_unsafe_channels) { + return false; + } + *legacy_unsafe_channels = {}; + for (const auto& hidl_unsafe_channel : hidl_unsafe_channels) { + legacy_hal::wifi_coex_unsafe_channel legacy_unsafe_channel; + if (!hidl_struct_util::convertHidlCoexUnsafeChannelToLegacy( + hidl_unsafe_channel, &legacy_unsafe_channel)) { + return false; + } + legacy_unsafe_channels->push_back(legacy_unsafe_channel); + } + return true; +} + } // namespace hidl_struct_util } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/hidl_struct_util.h b/wifi/1.5/default/hidl_struct_util.h similarity index 76% rename from wifi/1.4/default/hidl_struct_util.h rename to wifi/1.5/default/hidl_struct_util.h index 929f877d96e9119dbf7ddd6b13b31e34a1733f9a..352f213664b77052615c3558ad7ff00c3e870259 100644 --- a/wifi/1.4/default/hidl_struct_util.h +++ b/wifi/1.5/default/hidl_struct_util.h @@ -22,10 +22,11 @@ #include #include #include -#include #include #include #include +#include +#include #include "wifi_legacy_hal.h" @@ -38,14 +39,14 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { namespace hidl_struct_util { using namespace android::hardware::wifi::V1_0; // Chip conversion methods. bool convertLegacyFeaturesToHidlChipCapabilities( - uint32_t legacy_feature_set, uint32_t legacy_logger_feature_set, + uint64_t legacy_feature_set, uint32_t legacy_logger_feature_set, uint32_t* hidl_caps); bool convertLegacyDebugRingBufferStatusToHidl( const legacy_hal::wifi_ring_buffer_status& legacy_status, @@ -64,9 +65,18 @@ legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy_1_2( V1_2::IWifiChip::TxPowerScenario hidl_scenario); bool convertLegacyWifiMacInfosToHidl( const std::vector& legacy_mac_infos, - std::vector* hidl_radio_mode_infos); + std::vector* + hidl_radio_mode_infos); legacy_hal::wifi_interface_type convertHidlIfaceTypeToLegacy( IfaceType hidl_interface_type); +legacy_hal::wifi_multi_sta_use_case convertHidlMultiStaUseCaseToLegacy( + IWifiChip::MultiStaUseCase use_case); +bool convertHidlCoexUnsafeChannelToLegacy( + const IWifiChip::CoexUnsafeChannel& hidl_unsafe_channel, + legacy_hal::wifi_coex_unsafe_channel* legacy_unsafe_channel); +bool convertHidlVectorOfCoexUnsafeChannelToLegacy( + const std::vector& hidl_unsafe_channels, + std::vector* legacy_unsafe_channels); // STA iface conversion methods. bool convertLegacyFeaturesToHidlStaCapabilities( @@ -94,7 +104,7 @@ bool convertLegacyVectorOfCachedGscanResultsToHidl( std::vector* hidl_scan_datas); bool convertLegacyLinkLayerStatsToHidl( const legacy_hal::LinkLayerStats& legacy_stats, - V1_3::StaLinkLayerStats* hidl_stats); + StaLinkLayerStats* hidl_stats); bool convertLegacyRoamingCapabilitiesToHidl( const legacy_hal::wifi_roaming_capabilities& legacy_caps, StaRoamingCapabilities* hidl_caps); @@ -114,18 +124,26 @@ bool convertLegacyVectorOfDebugRxPacketFateToHidl( void convertToWifiNanStatus(legacy_hal::NanStatusType type, const char* str, size_t max_len, WifiNanStatus* wifiNanStatus); bool convertHidlNanEnableRequestToLegacy( - const NanEnableRequest& hidl_request, + const V1_4::NanEnableRequest& hidl_request, legacy_hal::NanEnableRequest* legacy_request); bool convertHidlNanConfigRequestToLegacy( - const NanConfigRequest& hidl_request, + const V1_4::NanConfigRequest& hidl_request, legacy_hal::NanConfigRequest* legacy_request); bool convertHidlNanEnableRequest_1_4ToLegacy( - const NanEnableRequest& hidl_request1, - const V1_2::NanConfigRequestSupplemental& hidl_request2, + const V1_4::NanEnableRequest& hidl_request1, + const NanConfigRequestSupplemental& hidl_request2, legacy_hal::NanEnableRequest* legacy_request); bool convertHidlNanConfigRequest_1_4ToLegacy( - const NanConfigRequest& hidl_request1, - const V1_2::NanConfigRequestSupplemental& hidl_request2, + const V1_4::NanConfigRequest& hidl_request1, + const NanConfigRequestSupplemental& hidl_request2, + legacy_hal::NanConfigRequest* legacy_request); +bool convertHidlNanEnableRequest_1_5ToLegacy( + const V1_4::NanEnableRequest& hidl_request1, + const NanConfigRequestSupplemental& hidl_request2, + legacy_hal::NanEnableRequest* legacy_request); +bool convertHidlNanConfigRequest_1_5ToLegacy( + const V1_4::NanConfigRequest& hidl_request1, + const NanConfigRequestSupplemental& hidl_request2, legacy_hal::NanConfigRequest* legacy_request); bool convertHidlNanPublishRequestToLegacy( const NanPublishRequest& hidl_request, @@ -165,7 +183,7 @@ bool convertLegacyNanDataPathScheduleUpdateIndToHidl( // RTT controller conversion methods. bool convertHidlVectorOfRttConfigToLegacy( - const std::vector& hidl_configs, + const std::vector& hidl_configs, std::vector* legacy_configs); bool convertHidlRttLciInformationToLegacy( const RttLciInformation& hidl_info, @@ -174,23 +192,34 @@ bool convertHidlRttLcrInformationToLegacy( const RttLcrInformation& hidl_info, legacy_hal::wifi_lcr_information* legacy_info); bool convertHidlRttResponderToLegacy( - const RttResponder& hidl_responder, + const V1_4::RttResponder& hidl_responder, legacy_hal::wifi_rtt_responder* legacy_responder); bool convertHidlWifiChannelInfoToLegacy( const WifiChannelInfo& hidl_info, legacy_hal::wifi_channel_info* legacy_info); bool convertLegacyRttResponderToHidl( const legacy_hal::wifi_rtt_responder& legacy_responder, - RttResponder* hidl_responder); + V1_4::RttResponder* hidl_responder); bool convertLegacyRttCapabilitiesToHidl( const legacy_hal::wifi_rtt_capabilities& legacy_capabilities, - RttCapabilities* hidl_capabilities); + V1_4::RttCapabilities* hidl_capabilities); bool convertLegacyVectorOfRttResultToHidl( const std::vector& legacy_results, - std::vector* hidl_results); + std::vector* hidl_results); +uint32_t convertHidlWifiBandToLegacyMacBand(V1_5::WifiBand band); +uint32_t convertHidlWifiIfaceModeToLegacy(uint32_t hidl_iface_mask); +uint32_t convertHidlUsableChannelFilterToLegacy(uint32_t hidl_filter_mask); +bool convertLegacyWifiUsableChannelsToHidl( + const std::vector& legacy_usable_channels, + std::vector* hidl_usable_channels); +bool convertLegacyPeerInfoStatsToHidl( + const legacy_hal::WifiPeerInfo& legacy_peer_info_stats, + StaPeerInfo* hidl_peer_info_stats); +bool convertLegacyWifiRateInfoToHidl(const legacy_hal::wifi_rate& legacy_rate, + V1_4::WifiRateInfo* hidl_rate); } // namespace hidl_struct_util } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/hidl_sync_util.cpp b/wifi/1.5/default/hidl_sync_util.cpp similarity index 96% rename from wifi/1.4/default/hidl_sync_util.cpp rename to wifi/1.5/default/hidl_sync_util.cpp index 593a3bc5be9b06ffccc08106a355a12119b1bfad..93eefe9560589750474795fe4c096b67bc863197 100644 --- a/wifi/1.4/default/hidl_sync_util.cpp +++ b/wifi/1.5/default/hidl_sync_util.cpp @@ -23,7 +23,7 @@ std::recursive_mutex g_mutex; namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { namespace hidl_sync_util { @@ -33,7 +33,7 @@ std::unique_lock acquireGlobalLock() { } // namespace hidl_sync_util } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/hidl_sync_util.h b/wifi/1.5/default/hidl_sync_util.h similarity index 96% rename from wifi/1.4/default/hidl_sync_util.h rename to wifi/1.5/default/hidl_sync_util.h index 02444219e9ab9f58f034df0e8ad886fa84b76535..e706f4cd870db9f09564dd36a89f3103bc83b73a 100644 --- a/wifi/1.4/default/hidl_sync_util.h +++ b/wifi/1.5/default/hidl_sync_util.h @@ -24,13 +24,13 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { namespace hidl_sync_util { std::unique_lock acquireGlobalLock(); } // namespace hidl_sync_util } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/ringbuffer.cpp b/wifi/1.5/default/ringbuffer.cpp similarity index 93% rename from wifi/1.4/default/ringbuffer.cpp rename to wifi/1.5/default/ringbuffer.cpp index 0fe8ef45aaa880766af6c5dd5b01ee789c87ec34..f554111e6182c3aeba9469eeb32cefaefd503d4e 100644 --- a/wifi/1.4/default/ringbuffer.cpp +++ b/wifi/1.5/default/ringbuffer.cpp @@ -21,7 +21,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { Ringbuffer::Ringbuffer(size_t maxSize) : size_(0), maxSize_(maxSize) {} @@ -47,8 +47,13 @@ const std::list>& Ringbuffer::getData() const { return data_; } +void Ringbuffer::clear() { + data_.clear(); + size_ = 0; +} + } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/ringbuffer.h b/wifi/1.5/default/ringbuffer.h similarity index 96% rename from wifi/1.4/default/ringbuffer.h rename to wifi/1.5/default/ringbuffer.h index ddce648949aab136a508da556297090446e5b929..03fb37a6a2d4ee9d1e49bf21bc3d422a3085489f 100644 --- a/wifi/1.4/default/ringbuffer.h +++ b/wifi/1.5/default/ringbuffer.h @@ -23,7 +23,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { /** @@ -37,6 +37,7 @@ class Ringbuffer { // within |maxSize_|. void append(const std::vector& input); const std::list>& getData() const; + void clear(); private: std::list> data_; @@ -45,7 +46,7 @@ class Ringbuffer { }; } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/service.cpp b/wifi/1.5/default/service.cpp similarity index 76% rename from wifi/1.4/default/service.cpp rename to wifi/1.5/default/service.cpp index 3f7f6094fdf769cc15c3b8cd5290d1d9da9d4a74..3de49b29bb89805e209950edb2631eba1d8bd098 100644 --- a/wifi/1.4/default/service.cpp +++ b/wifi/1.5/default/service.cpp @@ -17,22 +17,25 @@ #include #include #include +#include #include #include #include "wifi.h" #include "wifi_feature_flags.h" #include "wifi_legacy_hal.h" +#include "wifi_legacy_hal_factory.h" #include "wifi_mode_controller.h" using android::hardware::configureRpcThreadpool; using android::hardware::joinRpcThreadpool; using android::hardware::LazyServiceRegistrar; -using android::hardware::wifi::V1_4::implementation::feature_flags:: +using android::hardware::wifi::V1_5::implementation::feature_flags:: WifiFeatureFlags; -using android::hardware::wifi::V1_4::implementation::iface_util::WifiIfaceUtil; -using android::hardware::wifi::V1_4::implementation::legacy_hal::WifiLegacyHal; -using android::hardware::wifi::V1_4::implementation::mode_controller:: +using android::hardware::wifi::V1_5::implementation::legacy_hal::WifiLegacyHal; +using android::hardware::wifi::V1_5::implementation::legacy_hal:: + WifiLegacyHalFactory; +using android::hardware::wifi::V1_5::implementation::mode_controller:: WifiModeController; #ifdef LAZY_SERVICE @@ -42,6 +45,7 @@ const bool kLazyService = false; #endif int main(int /*argc*/, char** argv) { + signal(SIGPIPE, SIG_IGN); android::base::InitLogging( argv, android::base::LogdLogger(android::base::SYSTEM)); LOG(INFO) << "Wifi Hal is booting up..."; @@ -50,12 +54,14 @@ int main(int /*argc*/, char** argv) { const auto iface_tool = std::make_shared(); + const auto legacy_hal_factory = + std::make_shared(iface_tool); + // Setup hwbinder service - android::sp service = - new android::hardware::wifi::V1_4::implementation::Wifi( - iface_tool, std::make_shared(iface_tool), + android::sp service = + new android::hardware::wifi::V1_5::implementation::Wifi( + iface_tool, legacy_hal_factory, std::make_shared(), - std::make_shared(iface_tool), std::make_shared()); if (kLazyService) { auto registrar = LazyServiceRegistrar::getInstance(); diff --git a/wifi/1.4/default/tests/hidl_struct_util_unit_tests.cpp b/wifi/1.5/default/tests/hidl_struct_util_unit_tests.cpp similarity index 50% rename from wifi/1.4/default/tests/hidl_struct_util_unit_tests.cpp rename to wifi/1.5/default/tests/hidl_struct_util_unit_tests.cpp index b71d549d9ce97f9c863195574854f64ef4e72f84..4b4ebd6138c0c0a65cdaeeb81882dbea7cb8bb33 100644 --- a/wifi/1.4/default/tests/hidl_struct_util_unit_tests.cpp +++ b/wifi/1.5/default/tests/hidl_struct_util_unit_tests.cpp @@ -34,7 +34,7 @@ constexpr char kIfaceName2[] = "wlan1"; namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { using namespace android::hardware::wifi::V1_0; using ::android::hardware::wifi::V1_0::WifiChannelWidthInMhz; @@ -55,14 +55,15 @@ TEST_F(HidlStructUtilTest, CanConvertLegacyWifiMacInfosToHidlWithOneMac) { legacy_mac_info1.iface_infos.push_back(legacy_iface_info2); legacy_mac_infos.push_back(legacy_mac_info1); - std::vector hidl_radio_mode_infos; + std::vector + hidl_radio_mode_infos; ASSERT_TRUE(hidl_struct_util::convertLegacyWifiMacInfosToHidl( legacy_mac_infos, &hidl_radio_mode_infos)); ASSERT_EQ(1u, hidl_radio_mode_infos.size()); auto hidl_radio_mode_info1 = hidl_radio_mode_infos[0]; EXPECT_EQ(legacy_mac_info1.wlan_mac_id, hidl_radio_mode_info1.radioId); - EXPECT_EQ(WifiBand::BAND_24GHZ_5GHZ, hidl_radio_mode_info1.bandInfo); + EXPECT_EQ(V1_4::WifiBand::BAND_24GHZ_5GHZ, hidl_radio_mode_info1.bandInfo); ASSERT_EQ(2u, hidl_radio_mode_info1.ifaceInfos.size()); auto hidl_iface_info1 = hidl_radio_mode_info1.ifaceInfos[0]; EXPECT_EQ(legacy_iface_info1.name, hidl_iface_info1.name); @@ -89,20 +90,22 @@ TEST_F(HidlStructUtilTest, CanConvertLegacyWifiMacInfosToHidlWithTwoMac) { legacy_mac_info2.iface_infos.push_back(legacy_iface_info2); legacy_mac_infos.push_back(legacy_mac_info2); - std::vector hidl_radio_mode_infos; + std::vector + hidl_radio_mode_infos; ASSERT_TRUE(hidl_struct_util::convertLegacyWifiMacInfosToHidl( legacy_mac_infos, &hidl_radio_mode_infos)); ASSERT_EQ(2u, hidl_radio_mode_infos.size()); // Find mac info 1. - const auto hidl_radio_mode_info1 = std::find_if( - hidl_radio_mode_infos.begin(), hidl_radio_mode_infos.end(), - [&legacy_mac_info1](const IWifiChipEventCallback::RadioModeInfo& x) { - return x.radioId == legacy_mac_info1.wlan_mac_id; - }); + const auto hidl_radio_mode_info1 = + std::find_if(hidl_radio_mode_infos.begin(), hidl_radio_mode_infos.end(), + [&legacy_mac_info1]( + const V1_4::IWifiChipEventCallback::RadioModeInfo& x) { + return x.radioId == legacy_mac_info1.wlan_mac_id; + }); ASSERT_NE(hidl_radio_mode_infos.end(), hidl_radio_mode_info1); - EXPECT_EQ(WifiBand::BAND_5GHZ, hidl_radio_mode_info1->bandInfo); + EXPECT_EQ(V1_4::WifiBand::BAND_5GHZ, hidl_radio_mode_info1->bandInfo); ASSERT_EQ(1u, hidl_radio_mode_info1->ifaceInfos.size()); auto hidl_iface_info1 = hidl_radio_mode_info1->ifaceInfos[0]; EXPECT_EQ(legacy_iface_info1.name, hidl_iface_info1.name); @@ -110,13 +113,14 @@ TEST_F(HidlStructUtilTest, CanConvertLegacyWifiMacInfosToHidlWithTwoMac) { hidl_iface_info1.channel); // Find mac info 2. - const auto hidl_radio_mode_info2 = std::find_if( - hidl_radio_mode_infos.begin(), hidl_radio_mode_infos.end(), - [&legacy_mac_info2](const IWifiChipEventCallback::RadioModeInfo& x) { - return x.radioId == legacy_mac_info2.wlan_mac_id; - }); + const auto hidl_radio_mode_info2 = + std::find_if(hidl_radio_mode_infos.begin(), hidl_radio_mode_infos.end(), + [&legacy_mac_info2]( + const V1_4::IWifiChipEventCallback::RadioModeInfo& x) { + return x.radioId == legacy_mac_info2.wlan_mac_id; + }); ASSERT_NE(hidl_radio_mode_infos.end(), hidl_radio_mode_info2); - EXPECT_EQ(WifiBand::BAND_24GHZ, hidl_radio_mode_info2->bandInfo); + EXPECT_EQ(V1_4::WifiBand::BAND_24GHZ, hidl_radio_mode_info2->bandInfo); ASSERT_EQ(1u, hidl_radio_mode_info2->ifaceInfos.size()); auto hidl_iface_info2 = hidl_radio_mode_info2->ifaceInfos[0]; EXPECT_EQ(legacy_iface_info2.name, hidl_iface_info2.name); @@ -128,29 +132,55 @@ TEST_F(HidlStructUtilTest, canConvertLegacyLinkLayerStatsToHidl) { legacy_hal::LinkLayerStats legacy_stats{}; legacy_stats.radios.push_back(legacy_hal::LinkLayerRadioStats{}); legacy_stats.radios.push_back(legacy_hal::LinkLayerRadioStats{}); + legacy_stats.peers.push_back(legacy_hal::WifiPeerInfo{}); + legacy_stats.peers.push_back(legacy_hal::WifiPeerInfo{}); legacy_stats.iface.beacon_rx = rand(); legacy_stats.iface.rssi_mgmt = rand(); legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu = rand(); legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu = rand(); legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost = rand(); legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_min = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_max = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_avg = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_num_samples = + rand(); legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu = rand(); legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu = rand(); legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost = rand(); legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_min = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_max = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_avg = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_num_samples = + rand(); legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu = rand(); legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu = rand(); legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost = rand(); legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_min = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_max = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_avg = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_num_samples = + rand(); legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu = rand(); legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu = rand(); legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost = rand(); legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_min = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_max = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_avg = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_num_samples = + rand(); + + legacy_stats.iface.info.time_slicing_duty_cycle_percent = rand(); + legacy_stats.iface.num_peers = 1; for (auto& radio : legacy_stats.radios) { + radio.stats.radio = rand(); radio.stats.on_time = rand(); radio.stats.tx_time = rand(); radio.stats.rx_time = rand(); @@ -178,91 +208,191 @@ TEST_F(HidlStructUtilTest, canConvertLegacyLinkLayerStatsToHidl) { radio.channel_stats.push_back(channel_stat2); } - V1_3::StaLinkLayerStats converted{}; + for (auto& peer : legacy_stats.peers) { + peer.peer_info.bssload.sta_count = rand(); + peer.peer_info.bssload.chan_util = rand(); + wifi_rate_stat rate_stat1 = { + .rate = {3, 1, 2, 5, 0, 0}, + .tx_mpdu = 0, + .rx_mpdu = 1, + .mpdu_lost = 2, + .retries = 3, + .retries_short = 4, + .retries_long = 5, + }; + wifi_rate_stat rate_stat2 = { + .rate = {2, 2, 1, 6, 0, 1}, + .tx_mpdu = 6, + .rx_mpdu = 7, + .mpdu_lost = 8, + .retries = 9, + .retries_short = 10, + .retries_long = 11, + }; + peer.rate_stats.push_back(rate_stat1); + peer.rate_stats.push_back(rate_stat2); + } + + V1_5::StaLinkLayerStats converted{}; hidl_struct_util::convertLegacyLinkLayerStatsToHidl(legacy_stats, &converted); - EXPECT_EQ(legacy_stats.iface.beacon_rx, converted.iface.beaconRx); - EXPECT_EQ(legacy_stats.iface.rssi_mgmt, converted.iface.avgRssiMgmt); + EXPECT_EQ(legacy_stats.iface.beacon_rx, converted.iface.V1_0.beaconRx); + EXPECT_EQ(legacy_stats.iface.rssi_mgmt, converted.iface.V1_0.avgRssiMgmt); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu, - converted.iface.wmeBePktStats.rxMpdu); + converted.iface.V1_0.wmeBePktStats.rxMpdu); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu, - converted.iface.wmeBePktStats.txMpdu); + converted.iface.V1_0.wmeBePktStats.txMpdu); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost, - converted.iface.wmeBePktStats.lostMpdu); + converted.iface.V1_0.wmeBePktStats.lostMpdu); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries, - converted.iface.wmeBePktStats.retries); + converted.iface.V1_0.wmeBePktStats.retries); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_min, + converted.iface.wmeBeContentionTimeStats.contentionTimeMinInUsec); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_max, + converted.iface.wmeBeContentionTimeStats.contentionTimeMaxInUsec); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_avg, + converted.iface.wmeBeContentionTimeStats.contentionTimeAvgInUsec); + EXPECT_EQ( + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_num_samples, + converted.iface.wmeBeContentionTimeStats.contentionNumSamples); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu, - converted.iface.wmeBkPktStats.rxMpdu); + converted.iface.V1_0.wmeBkPktStats.rxMpdu); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu, - converted.iface.wmeBkPktStats.txMpdu); + converted.iface.V1_0.wmeBkPktStats.txMpdu); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost, - converted.iface.wmeBkPktStats.lostMpdu); + converted.iface.V1_0.wmeBkPktStats.lostMpdu); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries, - converted.iface.wmeBkPktStats.retries); + converted.iface.V1_0.wmeBkPktStats.retries); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_min, + converted.iface.wmeBkContentionTimeStats.contentionTimeMinInUsec); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_max, + converted.iface.wmeBkContentionTimeStats.contentionTimeMaxInUsec); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_avg, + converted.iface.wmeBkContentionTimeStats.contentionTimeAvgInUsec); + EXPECT_EQ( + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_num_samples, + converted.iface.wmeBkContentionTimeStats.contentionNumSamples); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu, - converted.iface.wmeViPktStats.rxMpdu); + converted.iface.V1_0.wmeViPktStats.rxMpdu); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu, - converted.iface.wmeViPktStats.txMpdu); + converted.iface.V1_0.wmeViPktStats.txMpdu); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost, - converted.iface.wmeViPktStats.lostMpdu); + converted.iface.V1_0.wmeViPktStats.lostMpdu); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries, - converted.iface.wmeViPktStats.retries); + converted.iface.V1_0.wmeViPktStats.retries); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_min, + converted.iface.wmeViContentionTimeStats.contentionTimeMinInUsec); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_max, + converted.iface.wmeViContentionTimeStats.contentionTimeMaxInUsec); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_avg, + converted.iface.wmeViContentionTimeStats.contentionTimeAvgInUsec); + EXPECT_EQ( + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_num_samples, + converted.iface.wmeViContentionTimeStats.contentionNumSamples); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu, - converted.iface.wmeVoPktStats.rxMpdu); + converted.iface.V1_0.wmeVoPktStats.rxMpdu); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu, - converted.iface.wmeVoPktStats.txMpdu); + converted.iface.V1_0.wmeVoPktStats.txMpdu); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost, - converted.iface.wmeVoPktStats.lostMpdu); + converted.iface.V1_0.wmeVoPktStats.lostMpdu); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries, - converted.iface.wmeVoPktStats.retries); + converted.iface.V1_0.wmeVoPktStats.retries); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_min, + converted.iface.wmeVoContentionTimeStats.contentionTimeMinInUsec); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_max, + converted.iface.wmeVoContentionTimeStats.contentionTimeMaxInUsec); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_avg, + converted.iface.wmeVoContentionTimeStats.contentionTimeAvgInUsec); + EXPECT_EQ( + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_num_samples, + converted.iface.wmeVoContentionTimeStats.contentionNumSamples); + + EXPECT_EQ(legacy_stats.iface.info.time_slicing_duty_cycle_percent, + converted.iface.timeSliceDutyCycleInPercent); EXPECT_EQ(legacy_stats.radios.size(), converted.radios.size()); for (size_t i = 0; i < legacy_stats.radios.size(); i++) { + EXPECT_EQ(legacy_stats.radios[i].stats.radio, + converted.radios[i].radioId); EXPECT_EQ(legacy_stats.radios[i].stats.on_time, - converted.radios[i].V1_0.onTimeInMs); + converted.radios[i].V1_3.V1_0.onTimeInMs); EXPECT_EQ(legacy_stats.radios[i].stats.tx_time, - converted.radios[i].V1_0.txTimeInMs); + converted.radios[i].V1_3.V1_0.txTimeInMs); EXPECT_EQ(legacy_stats.radios[i].stats.rx_time, - converted.radios[i].V1_0.rxTimeInMs); + converted.radios[i].V1_3.V1_0.rxTimeInMs); EXPECT_EQ(legacy_stats.radios[i].stats.on_time_scan, - converted.radios[i].V1_0.onTimeInMsForScan); + converted.radios[i].V1_3.V1_0.onTimeInMsForScan); EXPECT_EQ(legacy_stats.radios[i].tx_time_per_levels.size(), - converted.radios[i].V1_0.txTimeInMsPerLevel.size()); + converted.radios[i].V1_3.V1_0.txTimeInMsPerLevel.size()); for (size_t j = 0; j < legacy_stats.radios[i].tx_time_per_levels.size(); j++) { EXPECT_EQ(legacy_stats.radios[i].tx_time_per_levels[j], - converted.radios[i].V1_0.txTimeInMsPerLevel[j]); + converted.radios[i].V1_3.V1_0.txTimeInMsPerLevel[j]); } EXPECT_EQ(legacy_stats.radios[i].stats.on_time_nbd, - converted.radios[i].onTimeInMsForNanScan); + converted.radios[i].V1_3.onTimeInMsForNanScan); EXPECT_EQ(legacy_stats.radios[i].stats.on_time_gscan, - converted.radios[i].onTimeInMsForBgScan); + converted.radios[i].V1_3.onTimeInMsForBgScan); EXPECT_EQ(legacy_stats.radios[i].stats.on_time_roam_scan, - converted.radios[i].onTimeInMsForRoamScan); + converted.radios[i].V1_3.onTimeInMsForRoamScan); EXPECT_EQ(legacy_stats.radios[i].stats.on_time_pno_scan, - converted.radios[i].onTimeInMsForPnoScan); + converted.radios[i].V1_3.onTimeInMsForPnoScan); EXPECT_EQ(legacy_stats.radios[i].stats.on_time_hs20, - converted.radios[i].onTimeInMsForHs20Scan); + converted.radios[i].V1_3.onTimeInMsForHs20Scan); EXPECT_EQ(legacy_stats.radios[i].channel_stats.size(), - converted.radios[i].channelStats.size()); + converted.radios[i].V1_3.channelStats.size()); for (size_t k = 0; k < legacy_stats.radios[i].channel_stats.size(); k++) { auto& legacy_channel_st = legacy_stats.radios[i].channel_stats[k]; EXPECT_EQ(WifiChannelWidthInMhz::WIDTH_20, - converted.radios[i].channelStats[k].channel.width); - EXPECT_EQ(WifiChannelInMhz(legacy_channel_st.channel.center_freq), - converted.radios[i].channelStats[k].channel.centerFreq); - EXPECT_EQ(WifiChannelInMhz(legacy_channel_st.channel.center_freq0), - converted.radios[i].channelStats[k].channel.centerFreq0); - EXPECT_EQ(WifiChannelInMhz(legacy_channel_st.channel.center_freq1), - converted.radios[i].channelStats[k].channel.centerFreq1); + converted.radios[i].V1_3.channelStats[k].channel.width); + EXPECT_EQ( + WifiChannelInMhz(legacy_channel_st.channel.center_freq), + converted.radios[i].V1_3.channelStats[k].channel.centerFreq); + EXPECT_EQ( + WifiChannelInMhz(legacy_channel_st.channel.center_freq0), + converted.radios[i].V1_3.channelStats[k].channel.centerFreq0); + EXPECT_EQ( + WifiChannelInMhz(legacy_channel_st.channel.center_freq1), + converted.radios[i].V1_3.channelStats[k].channel.centerFreq1); EXPECT_EQ(legacy_channel_st.cca_busy_time, - converted.radios[i].channelStats[k].ccaBusyTimeInMs); + converted.radios[i].V1_3.channelStats[k].ccaBusyTimeInMs); EXPECT_EQ(legacy_channel_st.on_time, - converted.radios[i].channelStats[k].onTimeInMs); + converted.radios[i].V1_3.channelStats[k].onTimeInMs); + } + } + + EXPECT_EQ(legacy_stats.peers.size(), converted.iface.peers.size()); + for (size_t i = 0; i < legacy_stats.peers.size(); i++) { + EXPECT_EQ(legacy_stats.peers[i].peer_info.bssload.sta_count, + converted.iface.peers[i].staCount); + EXPECT_EQ(legacy_stats.peers[i].peer_info.bssload.chan_util, + converted.iface.peers[i].chanUtil); + for (size_t j = 0; j < legacy_stats.peers[i].rate_stats.size(); j++) { + EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].rate.preamble, + (uint32_t)converted.iface.peers[i] + .rateStats[j] + .rateInfo.preamble); + EXPECT_EQ( + legacy_stats.peers[i].rate_stats[j].rate.nss, + (uint32_t)converted.iface.peers[i].rateStats[j].rateInfo.nss); + EXPECT_EQ( + legacy_stats.peers[i].rate_stats[j].rate.bw, + (uint32_t)converted.iface.peers[i].rateStats[j].rateInfo.bw); + EXPECT_EQ( + legacy_stats.peers[i].rate_stats[j].rate.rateMcsIdx, + converted.iface.peers[i].rateStats[j].rateInfo.rateMcsIdx); + EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].tx_mpdu, + converted.iface.peers[i].rateStats[j].txMpdu); + EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].rx_mpdu, + converted.iface.peers[i].rateStats[j].rxMpdu); + EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].mpdu_lost, + converted.iface.peers[i].rateStats[j].mpduLost); + EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].retries, + converted.iface.peers[i].rateStats[j].retries); } } } @@ -288,7 +418,7 @@ TEST_F(HidlStructUtilTest, CanConvertLegacyFeaturesToHidl) { hidle_caps); } } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/tests/main.cpp b/wifi/1.5/default/tests/main.cpp similarity index 100% rename from wifi/1.4/default/tests/main.cpp rename to wifi/1.5/default/tests/main.cpp diff --git a/wifi/1.4/default/tests/mock_interface_tool.cpp b/wifi/1.5/default/tests/mock_interface_tool.cpp similarity index 100% rename from wifi/1.4/default/tests/mock_interface_tool.cpp rename to wifi/1.5/default/tests/mock_interface_tool.cpp diff --git a/wifi/1.4/default/tests/mock_interface_tool.h b/wifi/1.5/default/tests/mock_interface_tool.h similarity index 100% rename from wifi/1.4/default/tests/mock_interface_tool.h rename to wifi/1.5/default/tests/mock_interface_tool.h diff --git a/wifi/1.4/default/tests/mock_wifi_feature_flags.cpp b/wifi/1.5/default/tests/mock_wifi_feature_flags.cpp similarity index 96% rename from wifi/1.4/default/tests/mock_wifi_feature_flags.cpp rename to wifi/1.5/default/tests/mock_wifi_feature_flags.cpp index b1fa432ca3bbb7d1f9fc5d2b461459bed9c3307e..2f66ba121bfbc2f949019abea26512d30bc0d778 100644 --- a/wifi/1.4/default/tests/mock_wifi_feature_flags.cpp +++ b/wifi/1.5/default/tests/mock_wifi_feature_flags.cpp @@ -21,7 +21,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { namespace feature_flags { @@ -29,7 +29,7 @@ MockWifiFeatureFlags::MockWifiFeatureFlags() {} } // namespace feature_flags } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/tests/mock_wifi_feature_flags.h b/wifi/1.5/default/tests/mock_wifi_feature_flags.h similarity index 89% rename from wifi/1.4/default/tests/mock_wifi_feature_flags.h rename to wifi/1.5/default/tests/mock_wifi_feature_flags.h index 72d23045b036b77a887d859f282b3c9f51bae92d..c3877edd6058d1a96fde50b8fee83aee2c48f2c1 100644 --- a/wifi/1.4/default/tests/mock_wifi_feature_flags.h +++ b/wifi/1.5/default/tests/mock_wifi_feature_flags.h @@ -25,7 +25,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { namespace feature_flags { @@ -33,13 +33,14 @@ class MockWifiFeatureFlags : public WifiFeatureFlags { public: MockWifiFeatureFlags(); - MOCK_METHOD0(getChipModes, std::vector()); + MOCK_METHOD1(getChipModes, + std::vector(bool is_primary)); MOCK_METHOD0(isApMacRandomizationDisabled, bool()); }; } // namespace feature_flags } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/tests/mock_wifi_iface_util.cpp b/wifi/1.5/default/tests/mock_wifi_iface_util.cpp similarity index 83% rename from wifi/1.4/default/tests/mock_wifi_iface_util.cpp rename to wifi/1.5/default/tests/mock_wifi_iface_util.cpp index 0968569c56657f759ada2b1d9ab9cf3a066c4d2d..b101c4ac34cb2b476d05cb8f4c67960c3f3b9eea 100644 --- a/wifi/1.4/default/tests/mock_wifi_iface_util.cpp +++ b/wifi/1.5/default/tests/mock_wifi_iface_util.cpp @@ -24,16 +24,17 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { namespace iface_util { MockWifiIfaceUtil::MockWifiIfaceUtil( - const std::weak_ptr iface_tool) - : WifiIfaceUtil(iface_tool) {} + const std::weak_ptr iface_tool, + const std::weak_ptr legacy_hal) + : WifiIfaceUtil(iface_tool, legacy_hal) {} } // namespace iface_util } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/tests/mock_wifi_iface_util.h b/wifi/1.5/default/tests/mock_wifi_iface_util.h similarity index 94% rename from wifi/1.4/default/tests/mock_wifi_iface_util.h rename to wifi/1.5/default/tests/mock_wifi_iface_util.h index 8d77a7d9d00d86b0520d310f362311fe8843dda1..6d5f59ce530feeaa1780d6943134935aabef0546 100644 --- a/wifi/1.4/default/tests/mock_wifi_iface_util.h +++ b/wifi/1.5/default/tests/mock_wifi_iface_util.h @@ -24,14 +24,15 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { namespace iface_util { class MockWifiIfaceUtil : public WifiIfaceUtil { public: MockWifiIfaceUtil( - const std::weak_ptr iface_tool); + const std::weak_ptr iface_tool, + const std::weak_ptr legacy_hal); MOCK_METHOD1(getFactoryMacAddress, std::array(const std::string&)); MOCK_METHOD2(setMacAddress, @@ -45,7 +46,7 @@ class MockWifiIfaceUtil : public WifiIfaceUtil { }; } // namespace iface_util } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/tests/mock_wifi_legacy_hal.cpp b/wifi/1.5/default/tests/mock_wifi_legacy_hal.cpp similarity index 84% rename from wifi/1.4/default/tests/mock_wifi_legacy_hal.cpp rename to wifi/1.5/default/tests/mock_wifi_legacy_hal.cpp index 8d65c59e259181acb63e5429f4707f93973367e9..d13c5568b3262bf1729eda5817bad3a548045161 100644 --- a/wifi/1.4/default/tests/mock_wifi_legacy_hal.cpp +++ b/wifi/1.5/default/tests/mock_wifi_legacy_hal.cpp @@ -24,16 +24,17 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { namespace legacy_hal { MockWifiLegacyHal::MockWifiLegacyHal( - const std::weak_ptr iface_tool) - : WifiLegacyHal(iface_tool) {} + const std::weak_ptr iface_tool, + const wifi_hal_fn& fn, bool is_primary) + : WifiLegacyHal(iface_tool, fn, is_primary) {} } // namespace legacy_hal } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/tests/mock_wifi_legacy_hal.h b/wifi/1.5/default/tests/mock_wifi_legacy_hal.h similarity index 95% rename from wifi/1.4/default/tests/mock_wifi_legacy_hal.h rename to wifi/1.5/default/tests/mock_wifi_legacy_hal.h index 3bb7b54760151f01d9e27763f108a75cdcfd91f2..826b35f8ddeb3986a7744c9bc7ac2f5014f856ec 100644 --- a/wifi/1.4/default/tests/mock_wifi_legacy_hal.h +++ b/wifi/1.5/default/tests/mock_wifi_legacy_hal.h @@ -24,14 +24,15 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { namespace legacy_hal { class MockWifiLegacyHal : public WifiLegacyHal { public: MockWifiLegacyHal( - const std::weak_ptr iface_tool); + const std::weak_ptr iface_tool, + const wifi_hal_fn& fn, bool is_primary); MOCK_METHOD0(initialize, wifi_error()); MOCK_METHOD0(start, wifi_error()); MOCK_METHOD2(stop, wifi_error(std::unique_lock*, @@ -61,10 +62,11 @@ class MockWifiLegacyHal : public WifiLegacyHal { wifi_error(const std::string& ifname, wifi_interface_type iftype)); MOCK_METHOD1(deleteVirtualInterface, wifi_error(const std::string& ifname)); + MOCK_METHOD0(waitForDriverReady, wifi_error()); }; } // namespace legacy_hal } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/tests/mock_wifi_mode_controller.cpp b/wifi/1.5/default/tests/mock_wifi_mode_controller.cpp similarity index 96% rename from wifi/1.4/default/tests/mock_wifi_mode_controller.cpp rename to wifi/1.5/default/tests/mock_wifi_mode_controller.cpp index ee0902982019444d3ba304a839c477e11c0a5634..e7ab22a01b8ca85aab2479ee4c1d2631376afd21 100644 --- a/wifi/1.4/default/tests/mock_wifi_mode_controller.cpp +++ b/wifi/1.5/default/tests/mock_wifi_mode_controller.cpp @@ -24,14 +24,14 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { namespace mode_controller { MockWifiModeController::MockWifiModeController() : WifiModeController() {} } // namespace mode_controller } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/tests/mock_wifi_mode_controller.h b/wifi/1.5/default/tests/mock_wifi_mode_controller.h similarity index 97% rename from wifi/1.4/default/tests/mock_wifi_mode_controller.h rename to wifi/1.5/default/tests/mock_wifi_mode_controller.h index 1e1ce696f007b2e1b1050508e1f1870341c3f5ea..b9151f18b462b93252d696977db1b871b965812a 100644 --- a/wifi/1.4/default/tests/mock_wifi_mode_controller.h +++ b/wifi/1.5/default/tests/mock_wifi_mode_controller.h @@ -24,7 +24,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { namespace mode_controller { @@ -38,7 +38,7 @@ class MockWifiModeController : public WifiModeController { }; } // namespace mode_controller } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/tests/ringbuffer_unit_tests.cpp b/wifi/1.5/default/tests/ringbuffer_unit_tests.cpp similarity index 98% rename from wifi/1.4/default/tests/ringbuffer_unit_tests.cpp rename to wifi/1.5/default/tests/ringbuffer_unit_tests.cpp index a65347f7ace590f0b9bdbb9e495830b750606242..6fd34ee29c83537ffa97846d03677981a734a362 100644 --- a/wifi/1.4/default/tests/ringbuffer_unit_tests.cpp +++ b/wifi/1.5/default/tests/ringbuffer_unit_tests.cpp @@ -24,7 +24,7 @@ using testing::Test; namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { class RingbufferTest : public Test { @@ -91,7 +91,7 @@ TEST_F(RingbufferTest, OversizedAppendDoesNotDropExistingData) { EXPECT_EQ(input, buffer_.getData().front()); } } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/tests/runtests.sh b/wifi/1.5/default/tests/runtests.sh similarity index 100% rename from wifi/1.4/default/tests/runtests.sh rename to wifi/1.5/default/tests/runtests.sh diff --git a/wifi/1.4/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.5/default/tests/wifi_chip_unit_tests.cpp similarity index 95% rename from wifi/1.4/default/tests/wifi_chip_unit_tests.cpp rename to wifi/1.5/default/tests/wifi_chip_unit_tests.cpp index 323d2ffa819eeafbcb16d8bbd2ba3c621a627253..0ad6f3e821bbb4c67df299e8fe2908d776a13363 100644 --- a/wifi/1.4/default/tests/wifi_chip_unit_tests.cpp +++ b/wifi/1.5/default/tests/wifi_chip_unit_tests.cpp @@ -41,7 +41,7 @@ constexpr ChipId kFakeChipId = 5; namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { class WifiChipTest : public Test { @@ -59,7 +59,7 @@ class WifiChipTest : public Test { {feature_flags::chip_mode_ids::kV1Ap, combinationsAp} }; // clang-format on - EXPECT_CALL(*feature_flags_, getChipModes()) + EXPECT_CALL(*feature_flags_, getChipModes(true)) .WillRepeatedly(testing::Return(modes)); } @@ -76,7 +76,7 @@ class WifiChipTest : public Test { {feature_flags::chip_mode_ids::kV1Ap, combinationsAp} }; // clang-format on - EXPECT_CALL(*feature_flags_, getChipModes()) + EXPECT_CALL(*feature_flags_, getChipModes(true)) .WillRepeatedly(testing::Return(modes)); } @@ -89,7 +89,7 @@ class WifiChipTest : public Test { {feature_flags::chip_mode_ids::kV1Sta, combinationsSta} }; // clang-format on - EXPECT_CALL(*feature_flags_, getChipModes()) + EXPECT_CALL(*feature_flags_, getChipModes(true)) .WillRepeatedly(testing::Return(modes)); } @@ -103,7 +103,7 @@ class WifiChipTest : public Test { {feature_flags::chip_mode_ids::kV3, combinations} }; // clang-format on - EXPECT_CALL(*feature_flags_, getChipModes()) + EXPECT_CALL(*feature_flags_, getChipModes(true)) .WillRepeatedly(testing::Return(modes)); } @@ -116,7 +116,7 @@ class WifiChipTest : public Test { {feature_flags::chip_mode_ids::kV3, combinations} }; // clang-format on - EXPECT_CALL(*feature_flags_, getChipModes()) + EXPECT_CALL(*feature_flags_, getChipModes(true)) .WillRepeatedly(testing::Return(modes)); } @@ -129,7 +129,7 @@ class WifiChipTest : public Test { {feature_flags::chip_mode_ids::kV3, combinations} }; // clang-format on - EXPECT_CALL(*feature_flags_, getChipModes()) + EXPECT_CALL(*feature_flags_, getChipModes(true)) .WillRepeatedly(testing::Return(modes)); } @@ -173,18 +173,18 @@ class WifiChipTest : public Test { std::string createIface(const IfaceType& type) { std::string iface_name; if (type == IfaceType::AP) { - chip_->createApIface([&iface_name]( - const WifiStatus& status, - const sp& iface) { - if (WifiStatusCode::SUCCESS == status.code) { - ASSERT_NE(iface.get(), nullptr); - iface->getName([&iface_name](const WifiStatus& status, - const hidl_string& name) { - ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); - iface_name = name.c_str(); - }); - } - }); + chip_->createApIface( + [&iface_name](const WifiStatus& status, + const sp& iface) { + if (WifiStatusCode::SUCCESS == status.code) { + ASSERT_NE(iface.get(), nullptr); + iface->getName([&iface_name](const WifiStatus& status, + const hidl_string& name) { + ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); + iface_name = name.c_str(); + }); + } + }); } else if (type == IfaceType::NAN) { chip_->createNanIface( [&iface_name]( @@ -263,23 +263,28 @@ class WifiChipTest : public Test { return success; } + static void subsystemRestartHandler(const std::string& /*error*/) {} + sp chip_; ChipId chip_id_ = kFakeChipId; + legacy_hal::wifi_hal_fn fake_func_table_; std::shared_ptr> iface_tool_{ new NiceMock}; std::shared_ptr> legacy_hal_{ - new NiceMock(iface_tool_)}; + new NiceMock(iface_tool_, + fake_func_table_, true)}; std::shared_ptr> mode_controller_{new NiceMock}; std::shared_ptr> iface_util_{ - new NiceMock(iface_tool_)}; + new NiceMock(iface_tool_, legacy_hal_)}; std::shared_ptr> feature_flags_{new NiceMock}; public: void SetUp() override { - chip_ = new WifiChip(chip_id_, legacy_hal_, mode_controller_, - iface_util_, feature_flags_); + chip_ = + new WifiChip(chip_id_, true, legacy_hal_, mode_controller_, + iface_util_, feature_flags_, subsystemRestartHandler); EXPECT_CALL(*mode_controller_, changeFirmwareMode(testing::_)) .WillRepeatedly(testing::Return(true)); @@ -894,7 +899,7 @@ TEST_F(WifiChip_MultiIfaceTest, CreateApStartsWithIdx1) { ASSERT_EQ(createIface(IfaceType::STA), "wlan3"); } } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/tests/wifi_iface_util_unit_tests.cpp b/wifi/1.5/default/tests/wifi_iface_util_unit_tests.cpp similarity index 89% rename from wifi/1.4/default/tests/wifi_iface_util_unit_tests.cpp rename to wifi/1.5/default/tests/wifi_iface_util_unit_tests.cpp index 03394bc209d6db9d8e7a66a212d49a4f50ab6812..8b67bb80c8f7889c0a27962dbbecf61c2088776e 100644 --- a/wifi/1.4/default/tests/wifi_iface_util_unit_tests.cpp +++ b/wifi/1.5/default/tests/wifi_iface_util_unit_tests.cpp @@ -22,6 +22,7 @@ #include "wifi_iface_util.h" #include "mock_interface_tool.h" +#include "mock_wifi_legacy_hal.h" using testing::NiceMock; using testing::Test; @@ -41,14 +42,18 @@ bool isValidUnicastLocallyAssignedMacAddress( namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { namespace iface_util { class WifiIfaceUtilTest : public Test { protected: std::shared_ptr> iface_tool_{ new NiceMock}; - WifiIfaceUtil* iface_util_ = new WifiIfaceUtil(iface_tool_); + legacy_hal::wifi_hal_fn fake_func_table_; + std::shared_ptr> legacy_hal_{ + new NiceMock(iface_tool_, + fake_func_table_, true)}; + WifiIfaceUtil* iface_util_ = new WifiIfaceUtil(iface_tool_, legacy_hal_); }; TEST_F(WifiIfaceUtilTest, GetOrCreateRandomMacAddress) { @@ -90,7 +95,7 @@ TEST_F(WifiIfaceUtilTest, IfaceEventHandlers_SetMacAddress) { } } // namespace iface_util } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/tests/wifi_nan_iface_unit_tests.cpp b/wifi/1.5/default/tests/wifi_nan_iface_unit_tests.cpp similarity index 92% rename from wifi/1.4/default/tests/wifi_nan_iface_unit_tests.cpp rename to wifi/1.5/default/tests/wifi_nan_iface_unit_tests.cpp index 70424db8152a480170c2d0d74c0183f64eeb665b..32da55ec2b456b1e82ca99ca26079edea3e900c6 100644 --- a/wifi/1.4/default/tests/wifi_nan_iface_unit_tests.cpp +++ b/wifi/1.5/default/tests/wifi_nan_iface_unit_tests.cpp @@ -38,10 +38,9 @@ constexpr char kIfaceName[] = "mockWlan0"; namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { -using android::hardware::wifi::V1_2::IWifiNanIfaceEventCallback; using android::hardware::wifi::V1_2::NanDataPathConfirmInd; bool CaptureIfaceEventHandlers( @@ -56,9 +55,10 @@ class MockNanIfaceEventCallback : public IWifiNanIfaceEventCallback { public: MockNanIfaceEventCallback() = default; - MOCK_METHOD3(notifyCapabilitiesResponse, - Return(uint16_t, const WifiNanStatus&, - const NanCapabilities&)); + MOCK_METHOD3( + notifyCapabilitiesResponse, + Return(uint16_t, const WifiNanStatus&, + const android::hardware::wifi::V1_0::NanCapabilities&)); MOCK_METHOD2(notifyEnableResponse, Return(uint16_t, const WifiNanStatus&)); MOCK_METHOD2(notifyConfigResponse, @@ -108,16 +108,21 @@ class MockNanIfaceEventCallback : public IWifiNanIfaceEventCallback { Return(const NanDataPathConfirmInd&)); MOCK_METHOD1(eventDataPathScheduleUpdate, Return(const NanDataPathScheduleUpdateInd&)); + MOCK_METHOD3(notifyCapabilitiesResponse_1_5, + Return(uint16_t, const WifiNanStatus&, + const NanCapabilities&)); }; class WifiNanIfaceTest : public Test { protected: + legacy_hal::wifi_hal_fn fake_func_table_; std::shared_ptr> iface_tool_{ new NiceMock}; std::shared_ptr> legacy_hal_{ - new NiceMock(iface_tool_)}; + new NiceMock(iface_tool_, + fake_func_table_, true)}; std::shared_ptr> iface_util_{ - new NiceMock(iface_tool_)}; + new NiceMock(iface_tool_, legacy_hal_)}; }; TEST_F(WifiNanIfaceTest, IfacEventHandlers_OnStateToggleOffOn) { @@ -151,7 +156,7 @@ TEST_F(WifiNanIfaceTest, IfacEventHandlers_OnStateToggleOffOn) { captured_iface_event_handlers.on_state_toggle_off_on(kIfaceName); } } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/wifi.cpp b/wifi/1.5/default/wifi.cpp similarity index 60% rename from wifi/1.4/default/wifi.cpp rename to wifi/1.5/default/wifi.cpp index 9c6b0f0f163403e374e2c7e357eff550dfde8655..b9f20a46155c747f1feb4038c6fe35c984e43359 100644 --- a/wifi/1.4/default/wifi.cpp +++ b/wifi/1.5/default/wifi.cpp @@ -21,28 +21,26 @@ #include "wifi_status_util.h" namespace { -// Chip ID to use for the only supported chip. -static constexpr android::hardware::wifi::V1_0::ChipId kChipId = 0; +// Starting Chip ID, will be assigned to primary chip +static constexpr android::hardware::wifi::V1_0::ChipId kPrimaryChipId = 0; } // namespace namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { using hidl_return_util::validateAndCall; using hidl_return_util::validateAndCallWithLock; Wifi::Wifi( const std::shared_ptr iface_tool, - const std::shared_ptr legacy_hal, + const std::shared_ptr legacy_hal_factory, const std::shared_ptr mode_controller, - const std::shared_ptr iface_util, const std::shared_ptr feature_flags) : iface_tool_(iface_tool), - legacy_hal_(legacy_hal), + legacy_hal_factory_(legacy_hal_factory), mode_controller_(mode_controller), - iface_util_(iface_util), feature_flags_(feature_flags), run_state_(RunState::STOPPED) {} @@ -52,13 +50,21 @@ bool Wifi::isValid() { } Return Wifi::registerEventCallback( - const sp& event_callback, + const sp& event_callback, registerEventCallback_cb hidl_status_cb) { return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::registerEventCallbackInternal, hidl_status_cb, event_callback); } +Return Wifi::registerEventCallback_1_5( + const sp& event_callback, + registerEventCallback_1_5_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, + &Wifi::registerEventCallbackInternal_1_5, + hidl_status_cb, event_callback); +} + Return Wifi::isStarted() { return run_state_ != RunState::STOPPED; } Return Wifi::start(start_cb hidl_status_cb) { @@ -84,14 +90,26 @@ Return Wifi::getChip(ChipId chip_id, getChip_cb hidl_status_cb) { Return Wifi::debug(const hidl_handle& handle, const hidl_vec&) { LOG(INFO) << "-----------Debug is called----------------"; - if (!chip_.get()) { + if (chips_.size() == 0) { return Void(); } - return chip_->debug(handle, {}); + + for (sp chip : chips_) { + if (!chip.get()) continue; + + chip->debug(handle, {}); + } + return Void(); } WifiStatus Wifi::registerEventCallbackInternal( - const sp& event_callback) { + const sp& event_callback __unused) { + // Deprecated support for this callback. + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus Wifi::registerEventCallbackInternal_1_5( + const sp& event_callback) { if (!event_cb_handler_.addCallback(event_callback)) { return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); } @@ -107,9 +125,27 @@ WifiStatus Wifi::startInternal() { } WifiStatus wifi_status = initializeModeControllerAndLegacyHal(); if (wifi_status.code == WifiStatusCode::SUCCESS) { + // Register the callback for subsystem restart + const auto& on_subsystem_restart_callback = + [this](const std::string& error) { + WifiStatus wifi_status = + createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, error); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onSubsystemRestart(wifi_status).isOk()) { + LOG(ERROR) << "Failed to invoke onFailure callback"; + } + } + }; + // Create the chip instance once the HAL is started. - chip_ = new WifiChip(kChipId, legacy_hal_, mode_controller_, - iface_util_, feature_flags_); + android::hardware::wifi::V1_0::ChipId chipId = kPrimaryChipId; + for (auto& hal : legacy_hals_) { + chips_.push_back(new WifiChip( + chipId, chipId == kPrimaryChipId, hal, mode_controller_, + std::make_shared(iface_tool_, hal), + feature_flags_, on_subsystem_restart_callback)); + chipId++; + } run_state_ = RunState::STARTED; for (const auto& callback : event_cb_handler_.getCallbacks()) { if (!callback->onStart().isOk()) { @@ -140,10 +176,13 @@ WifiStatus Wifi::stopInternal( } // Clear the chip object and its child objects since the HAL is now // stopped. - if (chip_.get()) { - chip_->invalidate(); - chip_.clear(); + for (auto& chip : chips_) { + if (chip.get()) { + chip->invalidate(); + chip.clear(); + } } + chips_.clear(); WifiStatus wifi_status = stopLegacyHalAndDeinitializeModeController(lock); if (wifi_status.code == WifiStatusCode::SUCCESS) { for (const auto& callback : event_cb_handler_.getCallbacks()) { @@ -167,20 +206,23 @@ WifiStatus Wifi::stopInternal( std::pair> Wifi::getChipIdsInternal() { std::vector chip_ids; - if (chip_.get()) { - chip_ids.emplace_back(kChipId); + + for (auto& chip : chips_) { + ChipId chip_id = getChipIdFromWifiChip(chip); + if (chip_id != UINT32_MAX) chip_ids.emplace_back(chip_id); } return {createWifiStatus(WifiStatusCode::SUCCESS), std::move(chip_ids)}; } -std::pair> Wifi::getChipInternal(ChipId chip_id) { - if (!chip_.get()) { - return {createWifiStatus(WifiStatusCode::ERROR_NOT_STARTED), nullptr}; - } - if (chip_id != kChipId) { - return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr}; +std::pair> Wifi::getChipInternal( + ChipId chip_id) { + for (auto& chip : chips_) { + ChipId cand_id = getChipIdFromWifiChip(chip); + if ((cand_id != UINT32_MAX) && (cand_id == chip_id)) + return {createWifiStatus(WifiStatusCode::SUCCESS), chip}; } - return {createWifiStatus(WifiStatusCode::SUCCESS), chip_}; + + return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr}; } WifiStatus Wifi::initializeModeControllerAndLegacyHal() { @@ -188,23 +230,46 @@ WifiStatus Wifi::initializeModeControllerAndLegacyHal() { LOG(ERROR) << "Failed to initialize firmware mode controller"; return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); } - legacy_hal::wifi_error legacy_status = legacy_hal_->initialize(); - if (legacy_status != legacy_hal::WIFI_SUCCESS) { - LOG(ERROR) << "Failed to initialize legacy HAL: " - << legacyErrorToString(legacy_status); - return createWifiStatusFromLegacyError(legacy_status); + + legacy_hals_ = legacy_hal_factory_->getHals(); + if (legacy_hals_.empty()) + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + int index = 0; // for failure log + for (auto& hal : legacy_hals_) { + legacy_hal::wifi_error legacy_status = hal->initialize(); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + // Currently WifiLegacyHal::initialize does not allocate extra mem, + // only initializes the function table. If this changes, need to + // implement WifiLegacyHal::deinitialize and deinitalize the + // HALs already initialized + LOG(ERROR) << "Failed to initialize legacy HAL index: " << index + << " error: " << legacyErrorToString(legacy_status); + return createWifiStatusFromLegacyError(legacy_status); + } + index++; } return createWifiStatus(WifiStatusCode::SUCCESS); } WifiStatus Wifi::stopLegacyHalAndDeinitializeModeController( /* NONNULL */ std::unique_lock* lock) { + legacy_hal::wifi_error legacy_status = legacy_hal::WIFI_SUCCESS; + int index = 0; + run_state_ = RunState::STOPPING; - legacy_hal::wifi_error legacy_status = - legacy_hal_->stop(lock, [&]() { run_state_ = RunState::STOPPED; }); + for (auto& hal : legacy_hals_) { + legacy_hal::wifi_error tmp = hal->stop(lock, [&]() {}); + if (tmp != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to stop legacy HAL index: " << index + << " error: " << legacyErrorToString(legacy_status); + legacy_status = tmp; + } + index++; + } + run_state_ = RunState::STOPPED; + if (legacy_status != legacy_hal::WIFI_SUCCESS) { - LOG(ERROR) << "Failed to stop legacy HAL: " - << legacyErrorToString(legacy_status); + LOG(ERROR) << "One or more legacy HALs failed to stop"; return createWifiStatusFromLegacyError(legacy_status); } if (!mode_controller_->deinitialize()) { @@ -213,8 +278,21 @@ WifiStatus Wifi::stopLegacyHalAndDeinitializeModeController( } return createWifiStatus(WifiStatusCode::SUCCESS); } + +ChipId Wifi::getChipIdFromWifiChip(sp& chip) { + ChipId chip_id = UINT32_MAX; + if (chip.get()) { + chip->getId([&](WifiStatus status, uint32_t id) { + if (status.code == WifiStatusCode::SUCCESS) { + chip_id = id; + } + }); + } + + return chip_id; +} } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/wifi.h b/wifi/1.5/default/wifi.h similarity index 75% rename from wifi/1.4/default/wifi.h rename to wifi/1.5/default/wifi.h index eac0aac9142721e912d50f614bc0df02a0480b4a..c94ef3f4cf7f713afe568026fd4973072da5b708 100644 --- a/wifi/1.4/default/wifi.h +++ b/wifi/1.5/default/wifi.h @@ -21,7 +21,7 @@ // headers. This wifi HAL uses an enum called NAN, which does not compile when // the macro is defined. Undefine NAN to work around it. #undef NAN -#include +#include #include #include @@ -31,32 +31,36 @@ #include "wifi_chip.h" #include "wifi_feature_flags.h" #include "wifi_legacy_hal.h" +#include "wifi_legacy_hal_factory.h" #include "wifi_mode_controller.h" namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { /** * Root HIDL interface object used to control the Wifi HAL. */ -class Wifi : public V1_4::IWifi { +class Wifi : public V1_5::IWifi { public: Wifi(const std::shared_ptr iface_tool, - const std::shared_ptr legacy_hal, + const std::shared_ptr + legacy_hal_factory, const std::shared_ptr mode_controller, - const std::shared_ptr iface_util, const std::shared_ptr feature_flags); bool isValid(); // HIDL methods exposed. Return registerEventCallback( - const sp& event_callback, + const sp& event_callback, registerEventCallback_cb hidl_status_cb) override; + Return registerEventCallback_1_5( + const sp& event_callback, + registerEventCallback_1_5_cb hidl_status_cb) override; Return isStarted() override; Return start(start_cb hidl_status_cb) override; Return stop(stop_cb hidl_status_cb) override; @@ -70,33 +74,36 @@ class Wifi : public V1_4::IWifi { // Corresponding worker functions for the HIDL methods. WifiStatus registerEventCallbackInternal( - const sp& event_callback); + const sp& event_callback __unused); + WifiStatus registerEventCallbackInternal_1_5( + const sp& event_callback); WifiStatus startInternal(); WifiStatus stopInternal(std::unique_lock* lock); std::pair> getChipIdsInternal(); - std::pair> getChipInternal(ChipId chip_id); + std::pair> getChipInternal(ChipId chip_id); WifiStatus initializeModeControllerAndLegacyHal(); WifiStatus stopLegacyHalAndDeinitializeModeController( std::unique_lock* lock); + ChipId getChipIdFromWifiChip(sp& chip); // Instance is created in this root level |IWifi| HIDL interface object // and shared with all the child HIDL interface objects. std::shared_ptr iface_tool_; - std::shared_ptr legacy_hal_; + std::shared_ptr legacy_hal_factory_; std::shared_ptr mode_controller_; - std::shared_ptr iface_util_; + std::vector> legacy_hals_; std::shared_ptr feature_flags_; RunState run_state_; - sp chip_; - hidl_callback_util::HidlCallbackHandler + std::vector> chips_; + hidl_callback_util::HidlCallbackHandler event_cb_handler_; DISALLOW_COPY_AND_ASSIGN(Wifi); }; } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/wifi_ap_iface.cpp b/wifi/1.5/default/wifi_ap_iface.cpp similarity index 51% rename from wifi/1.4/default/wifi_ap_iface.cpp rename to wifi/1.5/default/wifi_ap_iface.cpp index 8777a4cb9cae91488e416cfd0882d9168a61fc21..1ae7905f740c17fa9c597362dc50fb87fee82dba 100644 --- a/wifi/1.4/default/wifi_ap_iface.cpp +++ b/wifi/1.5/default/wifi_ap_iface.cpp @@ -24,15 +24,16 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { using hidl_return_util::validateAndCall; WifiApIface::WifiApIface( - const std::string& ifname, + const std::string& ifname, const std::vector& instances, const std::weak_ptr legacy_hal, const std::weak_ptr iface_util) : ifname_(ifname), + instances_(instances), legacy_hal_(legacy_hal), iface_util_(iface_util), is_valid_(true) {} @@ -46,6 +47,12 @@ bool WifiApIface::isValid() { return is_valid_; } std::string WifiApIface::getName() { return ifname_; } +void WifiApIface::removeInstance(std::string instance) { + instances_.erase( + std::remove(instances_.begin(), instances_.end(), instance), + instances_.end()); +} + Return WifiApIface::getName(getName_cb hidl_status_cb) { return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, &WifiApIface::getNameInternal, hidl_status_cb); @@ -81,6 +88,21 @@ Return WifiApIface::getFactoryMacAddress( getFactoryMacAddress_cb hidl_status_cb) { return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, &WifiApIface::getFactoryMacAddressInternal, + hidl_status_cb, + instances_.size() > 0 ? instances_[0] : ifname_); +} + +Return WifiApIface::resetToFactoryMacAddress( + resetToFactoryMacAddress_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiApIface::resetToFactoryMacAddressInternal, + hidl_status_cb); +} + +Return WifiApIface::getBridgedInstances( + getBridgedInstances_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiApIface::getBridgedInstancesInternal, hidl_status_cb); } @@ -94,8 +116,8 @@ std::pair WifiApIface::getTypeInternal() { WifiStatus WifiApIface::setCountryCodeInternal( const std::array& code) { - legacy_hal::wifi_error legacy_status = - legacy_hal_.lock()->setCountryCode(ifname_, code); + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->setCountryCode( + instances_.size() > 0 ? instances_[0] : ifname_, code); return createWifiStatusFromLegacyError(legacy_status); } @@ -107,31 +129,92 @@ WifiApIface::getValidFrequenciesForBandInternal(V1_0::WifiBand band) { std::vector valid_frequencies; std::tie(legacy_status, valid_frequencies) = legacy_hal_.lock()->getValidFrequenciesForBand( - ifname_, hidl_struct_util::convertHidlWifiBandToLegacy(band)); + instances_.size() > 0 ? instances_[0] : ifname_, + hidl_struct_util::convertHidlWifiBandToLegacy(band)); return {createWifiStatusFromLegacyError(legacy_status), valid_frequencies}; } WifiStatus WifiApIface::setMacAddressInternal( const std::array& mac) { - bool status = iface_util_.lock()->setMacAddress(ifname_, mac); - if (!status) { + // Support random MAC up to 2 interfaces + if (instances_.size() == 2) { + int rbyte = 1; + for (auto const& intf : instances_) { + std::array rmac = mac; + // reverse the bits to avoid collision + rmac[rbyte] = 0xff - rmac[rbyte]; + if (!iface_util_.lock()->setMacAddress(intf, rmac)) { + LOG(INFO) << "Failed to set random mac address on " << intf; + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + rbyte++; + } + } + // It also needs to set mac address for bridged interface, otherwise the mac + // address of bridged interface will be changed after one of instance + // down. + if (!iface_util_.lock()->setMacAddress(ifname_, mac)) { + LOG(ERROR) << "Fail to config MAC for interface " << ifname_; return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); } return createWifiStatus(WifiStatusCode::SUCCESS); } std::pair> -WifiApIface::getFactoryMacAddressInternal() { +WifiApIface::getFactoryMacAddressInternal(const std::string& ifaceName) { std::array mac = - iface_util_.lock()->getFactoryMacAddress(ifname_); + iface_util_.lock()->getFactoryMacAddress(ifaceName); if (mac[0] == 0 && mac[1] == 0 && mac[2] == 0 && mac[3] == 0 && mac[4] == 0 && mac[5] == 0) { return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), mac}; } return {createWifiStatus(WifiStatusCode::SUCCESS), mac}; } + +WifiStatus WifiApIface::resetToFactoryMacAddressInternal() { + std::pair> getMacResult; + if (instances_.size() == 2) { + for (auto const& intf : instances_) { + getMacResult = getFactoryMacAddressInternal(intf); + LOG(DEBUG) << "Reset MAC to factory MAC on " << intf; + if (getMacResult.first.code != WifiStatusCode::SUCCESS || + !iface_util_.lock()->setMacAddress(intf, getMacResult.second)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + } + // It needs to set mac address for bridged interface, otherwise the mac + // address of the bridged interface will be changed after one of the + // instance down. Thus we are generating a random MAC address for the + // bridged interface even if we got the request to reset the Factory + // MAC. Since the bridged interface is an internal interface for the + // operation of bpf and others networking operation. + if (!iface_util_.lock()->setMacAddress( + ifname_, iface_util_.lock()->createRandomMacAddress())) { + LOG(ERROR) << "Fail to config MAC for bridged interface " + << ifname_; + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + } else { + getMacResult = getFactoryMacAddressInternal(ifname_); + LOG(DEBUG) << "Reset MAC to factory MAC on " << ifname_; + if (getMacResult.first.code != WifiStatusCode::SUCCESS || + !iface_util_.lock()->setMacAddress(ifname_, getMacResult.second)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +std::pair> +WifiApIface::getBridgedInstancesInternal() { + std::vector instances; + for (const auto& instance_name : instances_) { + instances.push_back(instance_name); + } + return {createWifiStatus(WifiStatusCode::SUCCESS), instances}; +} } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/wifi_ap_iface.h b/wifi/1.5/default/wifi_ap_iface.h similarity index 78% rename from wifi/1.4/default/wifi_ap_iface.h rename to wifi/1.5/default/wifi_ap_iface.h index bf16d5eb851b4b58995c506173ca18fde314a742..8f8387deaef51702ce9b5a5d25a5188387e2948c 100644 --- a/wifi/1.4/default/wifi_ap_iface.h +++ b/wifi/1.5/default/wifi_ap_iface.h @@ -18,7 +18,7 @@ #define WIFI_AP_IFACE_H_ #include -#include +#include #include "wifi_iface_util.h" #include "wifi_legacy_hal.h" @@ -26,22 +26,24 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { using namespace android::hardware::wifi::V1_0; /** * HIDL interface object used to control a AP Iface instance. */ -class WifiApIface : public V1_4::IWifiApIface { +class WifiApIface : public V1_5::IWifiApIface { public: WifiApIface(const std::string& ifname, + const std::vector& instances, const std::weak_ptr legacy_hal, const std::weak_ptr iface_util); // Refer to |WifiChip::invalidate()|. void invalidate(); bool isValid(); std::string getName(); + void removeInstance(std::string instance); // HIDL methods exposed. Return getName(getName_cb hidl_status_cb) override; @@ -55,6 +57,11 @@ class WifiApIface : public V1_4::IWifiApIface { setMacAddress_cb hidl_status_cb) override; Return getFactoryMacAddress( getFactoryMacAddress_cb hidl_status_cb) override; + Return resetToFactoryMacAddress( + resetToFactoryMacAddress_cb hidl_status_cb) override; + + Return getBridgedInstances( + getBridgedInstances_cb hidl_status_cb) override; private: // Corresponding worker functions for the HIDL methods. @@ -64,10 +71,14 @@ class WifiApIface : public V1_4::IWifiApIface { std::pair> getValidFrequenciesForBandInternal(V1_0::WifiBand band); WifiStatus setMacAddressInternal(const std::array& mac); - std::pair> - getFactoryMacAddressInternal(); + std::pair> getFactoryMacAddressInternal( + const std::string& ifaceName); + WifiStatus resetToFactoryMacAddressInternal(); + std::pair> + getBridgedInstancesInternal(); std::string ifname_; + std::vector instances_; std::weak_ptr legacy_hal_; std::weak_ptr iface_util_; bool is_valid_; @@ -76,7 +87,7 @@ class WifiApIface : public V1_4::IWifiApIface { }; } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/wifi_chip.cpp b/wifi/1.5/default/wifi_chip.cpp similarity index 77% rename from wifi/1.4/default/wifi_chip.cpp rename to wifi/1.5/default/wifi_chip.cpp index 8cba46475718338e5a32413444febb0a7a9a2d8c..82d794ca163fdb29e6b6b103b18b7ead43986b85 100644 --- a/wifi/1.4/default/wifi_chip.cpp +++ b/wifi/1.5/default/wifi_chip.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -44,6 +45,7 @@ constexpr char kTombstoneFolderPath[] = "/data/vendor/tombstones/wifi/"; constexpr char kActiveWlanIfaceNameProperty[] = "wifi.active.interface"; constexpr char kNoActiveWlanIfaceNamePropertyValue[] = ""; constexpr unsigned kMaxWlanIfaces = 5; +constexpr char kApBridgeIfacePrefix[] = "ap_br_"; template void invalidateAndClear(std::vector>& ifaces, sp iface) { @@ -101,24 +103,36 @@ std::string getWlanIfaceName(unsigned idx) { return "wlan" + std::to_string(idx); } -// Returns the dedicated iface name if one is defined. -std::string getApIfaceName() { +// Returns the dedicated iface name if defined. +// Returns two ifaces in bridged mode. +std::vector getPredefinedApIfaceNames(bool is_bridged) { + std::vector ifnames; std::array buffer; + buffer.fill(0); if (property_get("ro.vendor.wifi.sap.interface", buffer.data(), nullptr) == 0) { - return {}; + return ifnames; + } + ifnames.push_back(buffer.data()); + if (is_bridged) { + buffer.fill(0); + if (property_get("ro.vendor.wifi.sap.concurrent.iface", buffer.data(), + nullptr) == 0) { + return ifnames; + } + ifnames.push_back(buffer.data()); } - return buffer.data(); + return ifnames; } -std::string getP2pIfaceName() { +std::string getPredefinedP2pIfaceName() { std::array buffer; property_get("wifi.direct.interface", buffer.data(), "p2p0"); return buffer.data(); } // Returns the dedicated iface name if one is defined. -std::string getNanIfaceName() { +std::string getPredefinedNanIfaceName() { std::array buffer; if (property_get("wifi.aware.interface", buffer.data(), nullptr) == 0) { return {}; @@ -281,9 +295,6 @@ size_t cpioArchiveFilesInDir(int out_fd, const char* input_dir) { continue; } std::string cur_file_name(dp->d_name); - // string.size() does not include the null terminator. The cpio FreeBSD - // file header expects the null character to be included in the length. - const size_t file_name_len = cur_file_name.size() + 1; struct stat st; const std::string cur_file_path = kTombstoneFolderPath + cur_file_name; if (stat(cur_file_path.c_str(), &st) == -1) { @@ -297,8 +308,15 @@ size_t cpioArchiveFilesInDir(int out_fd, const char* input_dir) { n_error++; continue; } + std::string file_name_with_last_modified_time = + cur_file_name + "-" + std::to_string(st.st_mtime); + // string.size() does not include the null terminator. The cpio FreeBSD + // file header expects the null character to be included in the length. + const size_t file_name_len = + file_name_with_last_modified_time.size() + 1; unique_fd file_auto_closer(fd_read); - if (!cpioWriteHeader(out_fd, st, cur_file_name.c_str(), + if (!cpioWriteHeader(out_fd, st, + file_name_with_last_modified_time.c_str(), file_name_len)) { return ++n_error; } @@ -326,24 +344,27 @@ std::vector makeCharVec(const std::string& str) { namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { using hidl_return_util::validateAndCall; using hidl_return_util::validateAndCallWithLock; WifiChip::WifiChip( - ChipId chip_id, const std::weak_ptr legacy_hal, + ChipId chip_id, bool is_primary, + const std::weak_ptr legacy_hal, const std::weak_ptr mode_controller, - const std::weak_ptr iface_util, - const std::weak_ptr feature_flags) + const std::shared_ptr iface_util, + const std::weak_ptr feature_flags, + const std::function& handler) : chip_id_(chip_id), legacy_hal_(legacy_hal), mode_controller_(mode_controller), iface_util_(iface_util), is_valid_(true), current_mode_id_(feature_flags::chip_mode_ids::kInvalid), - modes_(feature_flags.lock()->getChipModes()), - debug_ring_buffer_cb_registered_(false) { + modes_(feature_flags.lock()->getChipModes(is_primary)), + debug_ring_buffer_cb_registered_(false), + subsystemCallbackHandler_(handler) { setActiveWlanIfaceNameProperty(kNoActiveWlanIfaceNamePropertyValue); } @@ -360,7 +381,7 @@ void WifiChip::invalidate() { bool WifiChip::isValid() { return is_valid_; } -std::set> WifiChip::getEventCallbacks() { +std::set> WifiChip::getEventCallbacks() { return event_cb_handler_.getCallbacks(); } @@ -427,6 +448,13 @@ Return WifiChip::createApIface(createApIface_cb hidl_status_cb) { &WifiChip::createApIfaceInternal, hidl_status_cb); } +Return WifiChip::createBridgedApIface( + createBridgedApIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::createBridgedApIfaceInternal, + hidl_status_cb); +} + Return WifiChip::getApIfaceNames(getApIfaceNames_cb hidl_status_cb) { return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, &WifiChip::getApIfaceNamesInternal, hidl_status_cb); @@ -446,6 +474,15 @@ Return WifiChip::removeApIface(const hidl_string& ifname, ifname); } +Return WifiChip::removeIfaceInstanceFromBridgedApIface( + const hidl_string& ifname, const hidl_string& ifInstanceName, + removeIfaceInstanceFromBridgedApIface_cb hidl_status_cb) { + return validateAndCall( + this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::removeIfaceInstanceFromBridgedApIfaceInternal, + hidl_status_cb, ifname, ifInstanceName); +} + Return WifiChip::createNanIface(createNanIface_cb hidl_status_cb) { return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, &WifiChip::createNanIfaceInternal, hidl_status_cb); @@ -621,6 +658,13 @@ Return WifiChip::getCapabilities_1_3(getCapabilities_cb hidl_status_cb) { hidl_status_cb); } +Return WifiChip::getCapabilities_1_5( + getCapabilities_1_5_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getCapabilitiesInternal_1_5, + hidl_status_cb); +} + Return WifiChip::debug(const hidl_handle& handle, const hidl_vec&) { if (handle != nullptr && handle->numFds >= 1) { @@ -657,14 +701,61 @@ Return WifiChip::createRttController_1_4( } Return WifiChip::registerEventCallback_1_4( - const sp& event_callback, + const sp& event_callback, registerEventCallback_cb hidl_status_cb) { return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, &WifiChip::registerEventCallbackInternal_1_4, hidl_status_cb, event_callback); } +Return WifiChip::setMultiStaPrimaryConnection( + const hidl_string& ifname, setMultiStaPrimaryConnection_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::setMultiStaPrimaryConnectionInternal, + hidl_status_cb, ifname); +} + +Return WifiChip::setMultiStaUseCase( + MultiStaUseCase use_case, setMultiStaUseCase_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::setMultiStaUseCaseInternal, + hidl_status_cb, use_case); +} + +Return WifiChip::setCoexUnsafeChannels( + const hidl_vec& unsafeChannels, + hidl_bitfield restrictions, + setCoexUnsafeChannels_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::setCoexUnsafeChannelsInternal, + hidl_status_cb, unsafeChannels, restrictions); +} + +Return WifiChip::setCountryCode(const hidl_array& code, + setCountryCode_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiChip::setCountryCodeInternal, hidl_status_cb, + code); +} + +Return WifiChip::getUsableChannels( + WifiBand band, hidl_bitfield ifaceModeMask, + hidl_bitfield filterMask, + getUsableChannels_cb _hidl_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getUsableChannelsInternal, _hidl_cb, band, + ifaceModeMask, filterMask); +} + +Return WifiChip::triggerSubsystemRestart( + triggerSubsystemRestart_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::triggerSubsystemRestartInternal, + hidl_status_cb); +} + void WifiChip::invalidateAndRemoveAllIfaces() { + invalidateAndClearBridgedApAll(); invalidateAndClearAll(ap_ifaces_); invalidateAndClearAll(nan_ifaces_); invalidateAndClearAll(p2p_ifaces_); @@ -679,9 +770,10 @@ void WifiChip::invalidateAndRemoveAllIfaces() { void WifiChip::invalidateAndRemoveDependencies( const std::string& removed_iface_name) { - for (const auto& nan_iface : nan_ifaces_) { + for (auto it = nan_ifaces_.begin(); it != nan_ifaces_.end();) { + auto nan_iface = *it; if (nan_iface->getName() == removed_iface_name) { - invalidateAndClear(nan_ifaces_, nan_iface); + nan_iface->invalidate(); for (const auto& callback : event_cb_handler_.getCallbacks()) { if (!callback ->onIfaceRemoved(IfaceType::NAN, removed_iface_name) @@ -689,11 +781,19 @@ void WifiChip::invalidateAndRemoveDependencies( LOG(ERROR) << "Failed to invoke onIfaceRemoved callback"; } } + it = nan_ifaces_.erase(it); + } else { + ++it; } } - for (const auto& rtt : rtt_controllers_) { + + for (auto it = rtt_controllers_.begin(); it != rtt_controllers_.end();) { + auto rtt = *it; if (rtt->getIfaceName() == removed_iface_name) { - invalidateAndClear(rtt_controllers_, rtt); + rtt->invalidate(); + it = rtt_controllers_.erase(it); + } else { + ++it; } } } @@ -713,7 +813,7 @@ std::pair WifiChip::getCapabilitiesInternal() { return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), 0}; } -std::pair> +std::pair> WifiChip::getAvailableModesInternal() { return {createWifiStatus(WifiStatusCode::SUCCESS), modes_}; } @@ -746,6 +846,10 @@ WifiStatus WifiChip::configureChipInternal( current_mode_id_ = mode_id; LOG(INFO) << "Configured chip in mode " << mode_id; setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName()); + + legacy_hal_.lock()->registerSubsystemRestartCallbackHandler( + subsystemCallbackHandler_); + return status; } @@ -757,9 +861,9 @@ std::pair WifiChip::getModeInternal() { return {createWifiStatus(WifiStatusCode::SUCCESS), current_mode_id_}; } -std::pair +std::pair WifiChip::requestChipDebugInfoInternal() { - IWifiChip::ChipDebugInfo result; + V1_4::IWifiChip::ChipDebugInfo result; legacy_hal::wifi_error legacy_status; std::string driver_desc; const auto ifname = getFirstActiveWlanIfaceName(); @@ -820,21 +924,28 @@ WifiChip::requestFirmwareDebugDumpInternal() { return {createWifiStatus(WifiStatusCode::SUCCESS), firmware_dump}; } -std::pair> WifiChip::createApIfaceInternal() { - if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::AP)) { - return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; - } - std::string ifname = allocateApIfaceName(); - legacy_hal::wifi_error legacy_status = - legacy_hal_.lock()->createVirtualInterface( - ifname, - hidl_struct_util::convertHidlIfaceTypeToLegacy(IfaceType::AP)); +WifiStatus WifiChip::createVirtualApInterface(const std::string& apVirtIf) { + legacy_hal::wifi_error legacy_status; + legacy_status = legacy_hal_.lock()->createVirtualInterface( + apVirtIf, + hidl_struct_util::convertHidlIfaceTypeToLegacy(IfaceType::AP)); if (legacy_status != legacy_hal::WIFI_SUCCESS) { - LOG(ERROR) << "Failed to add interface: " << ifname << " " + LOG(ERROR) << "Failed to add interface: " << apVirtIf << " " << legacyErrorToString(legacy_status); - return {createWifiStatusFromLegacyError(legacy_status), {}}; + return createWifiStatusFromLegacyError(legacy_status); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +sp WifiChip::newWifiApIface(std::string& ifname) { + std::vector ap_instances; + for (auto const& it : br_ifaces_ap_instances_) { + if (it.first == ifname) { + ap_instances = it.second; + } } - sp iface = new WifiApIface(ifname, legacy_hal_, iface_util_); + sp iface = + new WifiApIface(ifname, ap_instances, legacy_hal_, iface_util_); ap_ifaces_.push_back(iface); for (const auto& callback : event_cb_handler_.getCallbacks()) { if (!callback->onIfaceAdded(IfaceType::AP, ifname).isOk()) { @@ -842,6 +953,61 @@ std::pair> WifiChip::createApIfaceInternal() { } } setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName()); + return iface; +} + +std::pair> +WifiChip::createApIfaceInternal() { + if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::AP)) { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } + std::string ifname = allocateApIfaceName(); + WifiStatus status = createVirtualApInterface(ifname); + if (status.code != WifiStatusCode::SUCCESS) { + return {status, {}}; + } + sp iface = newWifiApIface(ifname); + return {createWifiStatus(WifiStatusCode::SUCCESS), iface}; +} + +std::pair> +WifiChip::createBridgedApIfaceInternal() { + if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::AP)) { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } + std::vector ap_instances = allocateBridgedApInstanceNames(); + if (ap_instances.size() < 2) { + LOG(ERROR) << "Fail to allocate two instances"; + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } + std::string br_ifname = kApBridgeIfacePrefix + ap_instances[0]; + for (int i = 0; i < 2; i++) { + WifiStatus status = createVirtualApInterface(ap_instances[i]); + if (status.code != WifiStatusCode::SUCCESS) { + if (i != 0) { // The failure happened when creating second virtual + // iface. + legacy_hal_.lock()->deleteVirtualInterface( + ap_instances.front()); // Remove the first virtual iface. + } + return {status, {}}; + } + } + br_ifaces_ap_instances_[br_ifname] = ap_instances; + if (!iface_util_->createBridge(br_ifname)) { + LOG(ERROR) << "Failed createBridge - br_name=" << br_ifname.c_str(); + invalidateAndClearBridgedAp(br_ifname); + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } + for (auto const& instance : ap_instances) { + // Bind ap instance interface to AP bridge + if (!iface_util_->addIfaceToBridge(br_ifname, instance)) { + LOG(ERROR) << "Failed add if to Bridge - if_name=" + << instance.c_str(); + invalidateAndClearBridgedAp(br_ifname); + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } + } + sp iface = newWifiApIface(br_ifname); return {createWifiStatus(WifiStatusCode::SUCCESS), iface}; } @@ -853,7 +1019,7 @@ WifiChip::getApIfaceNamesInternal() { return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(ap_ifaces_)}; } -std::pair> WifiChip::getApIfaceInternal( +std::pair> WifiChip::getApIfaceInternal( const std::string& ifname) { const auto iface = findUsingName(ap_ifaces_, ifname); if (!iface.get()) { @@ -872,12 +1038,8 @@ WifiStatus WifiChip::removeApIfaceInternal(const std::string& ifname) { // nan/rtt objects over AP iface. But, there is no harm to do it // here and not make that assumption all over the place. invalidateAndRemoveDependencies(ifname); - legacy_hal::wifi_error legacy_status = - legacy_hal_.lock()->deleteVirtualInterface(ifname); - if (legacy_status != legacy_hal::WIFI_SUCCESS) { - LOG(ERROR) << "Failed to remove interface: " << ifname << " " - << legacyErrorToString(legacy_status); - } + // Clear the bridge interface and the iface instance. + invalidateAndClearBridgedAp(ifname); invalidateAndClear(ap_ifaces_, iface); for (const auto& callback : event_cb_handler_.getCallbacks()) { if (!callback->onIfaceRemoved(IfaceType::AP, ifname).isOk()) { @@ -888,13 +1050,57 @@ WifiStatus WifiChip::removeApIfaceInternal(const std::string& ifname) { return createWifiStatus(WifiStatusCode::SUCCESS); } -std::pair> WifiChip::createNanIfaceInternal() { +WifiStatus WifiChip::removeIfaceInstanceFromBridgedApIfaceInternal( + const std::string& ifname, const std::string& ifInstanceName) { + const auto iface = findUsingName(ap_ifaces_, ifname); + if (!iface.get() || ifInstanceName.empty()) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + // Requires to remove one of the instance in bridge mode + for (auto const& it : br_ifaces_ap_instances_) { + if (it.first == ifname) { + std::vector ap_instances = it.second; + for (auto const& iface : ap_instances) { + if (iface == ifInstanceName) { + if (!iface_util_->removeIfaceFromBridge(it.first, iface)) { + LOG(ERROR) + << "Failed to remove interface: " << ifInstanceName + << " from " << ifname; + return createWifiStatus( + WifiStatusCode::ERROR_NOT_AVAILABLE); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->deleteVirtualInterface(iface); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to del interface: " << iface + << " " << legacyErrorToString(legacy_status); + return createWifiStatusFromLegacyError(legacy_status); + } + ap_instances.erase( + std::remove(ap_instances.begin(), ap_instances.end(), + ifInstanceName), + ap_instances.end()); + br_ifaces_ap_instances_[ifname] = ap_instances; + break; + } + } + break; + } + } + iface->removeInstance(ifInstanceName); + setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName()); + + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +std::pair> +WifiChip::createNanIfaceInternal() { if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::NAN)) { return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; } bool is_dedicated_iface = true; - std::string ifname = getNanIfaceName(); - if (ifname.empty() || !iface_util_.lock()->ifNameToIndex(ifname)) { + std::string ifname = getPredefinedNanIfaceName(); + if (ifname.empty() || !iface_util_->ifNameToIndex(ifname)) { // Use the first shared STA iface (wlan0) if a dedicated aware iface is // not defined. ifname = getFirstActiveWlanIfaceName(); @@ -919,7 +1125,7 @@ WifiChip::getNanIfaceNamesInternal() { return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(nan_ifaces_)}; } -std::pair> WifiChip::getNanIfaceInternal( +std::pair> WifiChip::getNanIfaceInternal( const std::string& ifname) { const auto iface = findUsingName(nan_ifaces_, ifname); if (!iface.get()) { @@ -946,7 +1152,7 @@ std::pair> WifiChip::createP2pIfaceInternal() { if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::P2P)) { return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; } - std::string ifname = getP2pIfaceName(); + std::string ifname = getPredefinedP2pIfaceName(); sp iface = new WifiP2pIface(ifname, legacy_hal_); p2p_ifaces_.push_back(iface); for (const auto& callback : event_cb_handler_.getCallbacks()) { @@ -988,7 +1194,7 @@ WifiStatus WifiChip::removeP2pIfaceInternal(const std::string& ifname) { return createWifiStatus(WifiStatusCode::SUCCESS); } -std::pair> +std::pair> WifiChip::createStaIfaceInternal() { if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::STA)) { return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; @@ -1022,7 +1228,7 @@ WifiChip::getStaIfaceNamesInternal() { return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(sta_ifaces_)}; } -std::pair> WifiChip::getStaIfaceInternal( +std::pair> WifiChip::getStaIfaceInternal( const std::string& ifname) { const auto iface = findUsingName(sta_ifaces_, ifname); if (!iface.get()) { @@ -1216,8 +1422,13 @@ WifiStatus WifiChip::selectTxPowerScenarioInternal_1_2( } std::pair WifiChip::getCapabilitiesInternal_1_3() { + // Deprecated support for this callback. + return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), 0}; +} + +std::pair WifiChip::getCapabilitiesInternal_1_5() { legacy_hal::wifi_error legacy_status; - uint32_t legacy_feature_set; + uint64_t legacy_feature_set; uint32_t legacy_logger_feature_set; const auto ifname = getFirstActiveWlanIfaceName(); std::tie(legacy_status, legacy_feature_set) = @@ -1239,7 +1450,7 @@ std::pair WifiChip::getCapabilitiesInternal_1_3() { return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps}; } -std::pair> +std::pair> WifiChip::createRttControllerInternal_1_4(const sp& bound_iface) { if (sta_ifaces_.size() == 0 && !canCurrentModeSupportIfaceOfType(IfaceType::STA)) { @@ -1255,13 +1466,82 @@ WifiChip::createRttControllerInternal_1_4(const sp& bound_iface) { } WifiStatus WifiChip::registerEventCallbackInternal_1_4( - const sp& event_callback) { + const sp& event_callback) { if (!event_cb_handler_.addCallback(event_callback)) { return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); } return createWifiStatus(WifiStatusCode::SUCCESS); } +WifiStatus WifiChip::setMultiStaPrimaryConnectionInternal( + const std::string& ifname) { + auto legacy_status = + legacy_hal_.lock()->multiStaSetPrimaryConnection(ifname); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiChip::setMultiStaUseCaseInternal(MultiStaUseCase use_case) { + auto legacy_status = legacy_hal_.lock()->multiStaSetUseCase( + hidl_struct_util::convertHidlMultiStaUseCaseToLegacy(use_case)); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiChip::setCoexUnsafeChannelsInternal( + std::vector unsafe_channels, uint32_t restrictions) { + std::vector legacy_unsafe_channels; + if (!hidl_struct_util::convertHidlVectorOfCoexUnsafeChannelToLegacy( + unsafe_channels, &legacy_unsafe_channels)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + uint32_t legacy_restrictions = 0; + if (restrictions & CoexRestriction::WIFI_DIRECT) { + legacy_restrictions |= legacy_hal::wifi_coex_restriction::WIFI_DIRECT; + } + if (restrictions & CoexRestriction::SOFTAP) { + legacy_restrictions |= legacy_hal::wifi_coex_restriction::SOFTAP; + } + if (restrictions & CoexRestriction::WIFI_AWARE) { + legacy_restrictions |= legacy_hal::wifi_coex_restriction::WIFI_AWARE; + } + auto legacy_status = legacy_hal_.lock()->setCoexUnsafeChannels( + legacy_unsafe_channels, legacy_restrictions); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiChip::setCountryCodeInternal(const std::array& code) { + auto legacy_status = + legacy_hal_.lock()->setCountryCode(getFirstActiveWlanIfaceName(), code); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair> +WifiChip::getUsableChannelsInternal(WifiBand band, uint32_t ifaceModeMask, + uint32_t filterMask) { + legacy_hal::wifi_error legacy_status; + std::vector legacy_usable_channels; + std::tie(legacy_status, legacy_usable_channels) = + legacy_hal_.lock()->getUsableChannels( + hidl_struct_util::convertHidlWifiBandToLegacyMacBand(band), + hidl_struct_util::convertHidlWifiIfaceModeToLegacy(ifaceModeMask), + hidl_struct_util::convertHidlUsableChannelFilterToLegacy( + filterMask)); + + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + std::vector hidl_usable_channels; + if (!hidl_struct_util::convertLegacyWifiUsableChannelsToHidl( + legacy_usable_channels, &hidl_usable_channels)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_usable_channels}; +} + +WifiStatus WifiChip::triggerSubsystemRestartInternal() { + auto legacy_status = legacy_hal_.lock()->triggerSubsystemRestart(); + return createWifiStatusFromLegacyError(legacy_status); +} + WifiStatus WifiChip::handleChipConfiguration( /* NONNULL */ std::unique_lock* lock, ChipModeId mode_id) { @@ -1303,7 +1583,7 @@ WifiStatus WifiChip::handleChipConfiguration( LOG(ERROR) << "Failed to register radio mode change callback"; } // Extract and save the version information into property. - std::pair version_info; + std::pair version_info; version_info = WifiChip::requestChipDebugInfoInternal(); if (WifiStatusCode::SUCCESS == version_info.first.code) { property_set("vendor.wlan.firmware.version", @@ -1369,7 +1649,7 @@ WifiStatus WifiChip::registerRadioModeChangeCallback() { LOG(ERROR) << "Callback invoked on an invalid object"; return; } - std::vector + std::vector hidl_radio_mode_infos; if (!hidl_struct_util::convertLegacyWifiMacInfosToHidl( mac_infos, &hidl_radio_mode_infos)) { @@ -1390,7 +1670,7 @@ WifiStatus WifiChip::registerRadioModeChangeCallback() { return createWifiStatusFromLegacyError(legacy_status); } -std::vector +std::vector WifiChip::getCurrentModeIfaceCombinations() { if (!isValidModeId(current_mode_id_)) { LOG(ERROR) << "Chip not configured in a mode yet"; @@ -1421,7 +1701,7 @@ std::map WifiChip::getCurrentIfaceCombination() { // of ifaces of each type in the combination. // This method is a port of HalDeviceManager.expandIfaceCombos() from framework. std::vector> WifiChip::expandIfaceCombinations( - const IWifiChip::ChipIfaceCombination& combination) { + const V1_4::IWifiChip::ChipIfaceCombination& combination) { uint32_t num_expanded_combos = 1; for (const auto& limit : combination.limits) { for (uint32_t i = 0; i < limit.maxIfaces; i++) { @@ -1547,7 +1827,7 @@ bool WifiChip::canCurrentModeSupportIfaceCombo( // ChipIfaceCombination. // b) Check if the requested iface type can be added to the current mode. bool WifiChip::canCurrentModeSupportIfaceOfType(IfaceType requested_type) { - // Check if we can support atleast 1 iface of type. + // Check if we can support at least 1 iface of type. std::map req_iface_combo; req_iface_combo[requested_type] = 1; return canCurrentModeSupportIfaceCombo(req_iface_combo); @@ -1563,35 +1843,46 @@ bool WifiChip::isValidModeId(ChipModeId mode_id) { } bool WifiChip::isStaApConcurrencyAllowedInCurrentMode() { - // Check if we can support atleast 1 STA & 1 AP concurrently. + // Check if we can support at least 1 STA & 1 AP concurrently. std::map req_iface_combo; req_iface_combo[IfaceType::AP] = 1; req_iface_combo[IfaceType::STA] = 1; return canCurrentModeSupportIfaceCombo(req_iface_combo); } -bool WifiChip::isDualApAllowedInCurrentMode() { - // Check if we can support atleast 1 STA & 1 AP concurrently. +bool WifiChip::isDualStaConcurrencyAllowedInCurrentMode() { + // Check if we can support at least 2 STA concurrently. std::map req_iface_combo; - req_iface_combo[IfaceType::AP] = 2; + req_iface_combo[IfaceType::STA] = 2; return canCurrentModeSupportIfaceCombo(req_iface_combo); } std::string WifiChip::getFirstActiveWlanIfaceName() { if (sta_ifaces_.size() > 0) return sta_ifaces_[0]->getName(); - if (ap_ifaces_.size() > 0) return ap_ifaces_[0]->getName(); + if (ap_ifaces_.size() > 0) { + // If the first active wlan iface is bridged iface. + // Return first instance name. + for (auto const& it : br_ifaces_ap_instances_) { + if (it.first == ap_ifaces_[0]->getName()) { + return it.second[0]; + } + } + return ap_ifaces_[0]->getName(); + } // This could happen if the chip call is made before any STA/AP // iface is created. Default to wlan0 for such cases. LOG(WARNING) << "No active wlan interfaces in use! Using default"; - return getWlanIfaceName(0); + return getWlanIfaceNameWithType(IfaceType::STA, 0); } // Return the first wlan (wlan0, wlan1 etc.) starting from |start_idx| // not already in use. // Note: This doesn't check the actual presence of these interfaces. -std::string WifiChip::allocateApOrStaIfaceName(uint32_t start_idx) { +std::string WifiChip::allocateApOrStaIfaceName(IfaceType type, + uint32_t start_idx) { for (unsigned idx = start_idx; idx < kMaxWlanIfaces; idx++) { - const auto ifname = getWlanIfaceName(idx); + const auto ifname = getWlanIfaceNameWithType(type, idx); + if (findUsingNameFromBridgedApInstances(ifname)) continue; if (findUsingName(ap_ifaces_, ifname)) continue; if (findUsingName(sta_ifaces_, ifname)) continue; return ifname; @@ -1601,24 +1892,52 @@ std::string WifiChip::allocateApOrStaIfaceName(uint32_t start_idx) { return {}; } +uint32_t WifiChip::startIdxOfApIface() { + if (isDualStaConcurrencyAllowedInCurrentMode()) { + // When the HAL support dual STAs, AP should start with idx 2. + return 2; + } else if (isStaApConcurrencyAllowedInCurrentMode()) { + // When the HAL support STA + AP but it doesn't support dual STAs. + // AP should start with idx 1. + return 1; + } + // No concurrency support. + return 0; +} + // AP iface names start with idx 1 for modes supporting // concurrent STA and not dual AP, else start with idx 0. std::string WifiChip::allocateApIfaceName() { // Check if we have a dedicated iface for AP. - std::string ifname = getApIfaceName(); - if (!ifname.empty()) { - return ifname; + std::vector ifnames = getPredefinedApIfaceNames(false); + if (!ifnames.empty()) { + return ifnames[0]; } - return allocateApOrStaIfaceName((isStaApConcurrencyAllowedInCurrentMode() && - !isDualApAllowedInCurrentMode()) - ? 1 - : 0); + return allocateApOrStaIfaceName(IfaceType::AP, startIdxOfApIface()); +} + +std::vector WifiChip::allocateBridgedApInstanceNames() { + // Check if we have a dedicated iface for AP. + std::vector instances = getPredefinedApIfaceNames(true); + if (instances.size() == 2) { + return instances; + } else { + int num_ifaces_need_to_allocate = 2 - instances.size(); + for (int i = 0; i < num_ifaces_need_to_allocate; i++) { + std::string instance_name = allocateApOrStaIfaceName( + IfaceType::AP, startIdxOfApIface() + i); + if (!instance_name.empty()) { + instances.push_back(instance_name); + } + } + } + return instances; } // STA iface names start with idx 0. // Primary STA iface will always be 0. std::string WifiChip::allocateStaIfaceName() { - return allocateApOrStaIfaceName(0); + return allocateApOrStaIfaceName(IfaceType::STA, 0); } bool WifiChip::writeRingbufferFilesInternal() { @@ -1629,8 +1948,8 @@ bool WifiChip::writeRingbufferFilesInternal() { // write ringbuffers to file { std::unique_lock lk(lock_t); - for (const auto& item : ringbuffer_map_) { - const Ringbuffer& cur_buffer = item.second; + for (auto& item : ringbuffer_map_) { + Ringbuffer& cur_buffer = item.second; if (cur_buffer.getData().empty()) { continue; } @@ -1648,14 +1967,68 @@ bool WifiChip::writeRingbufferFilesInternal() { PLOG(ERROR) << "Error writing to file"; } } + cur_buffer.clear(); } // unique_lock unlocked here } return true; } +std::string WifiChip::getWlanIfaceNameWithType(IfaceType type, unsigned idx) { + std::string ifname; + + // let the legacy hal override the interface name + legacy_hal::wifi_error err = + legacy_hal_.lock()->getSupportedIfaceName((uint32_t)type, ifname); + if (err == legacy_hal::WIFI_SUCCESS) return ifname; + + return getWlanIfaceName(idx); +} + +void WifiChip::invalidateAndClearBridgedApAll() { + for (auto const& it : br_ifaces_ap_instances_) { + for (auto const& iface : it.second) { + iface_util_->removeIfaceFromBridge(it.first, iface); + legacy_hal_.lock()->deleteVirtualInterface(iface); + } + iface_util_->deleteBridge(it.first); + } + br_ifaces_ap_instances_.clear(); +} + +void WifiChip::invalidateAndClearBridgedAp(const std::string& br_name) { + if (br_name.empty()) return; + // delete managed interfaces + for (auto const& it : br_ifaces_ap_instances_) { + if (it.first == br_name) { + for (auto const& iface : it.second) { + iface_util_->removeIfaceFromBridge(br_name, iface); + legacy_hal_.lock()->deleteVirtualInterface(iface); + } + iface_util_->deleteBridge(br_name); + br_ifaces_ap_instances_.erase(br_name); + break; + } + } + return; +} + +bool WifiChip::findUsingNameFromBridgedApInstances(const std::string& name) { + for (auto const& it : br_ifaces_ap_instances_) { + if (it.first == name) { + return true; + } + for (auto const& iface : it.second) { + if (iface == name) { + return true; + } + } + } + return false; +} + } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/wifi_chip.h b/wifi/1.5/default/wifi_chip.h similarity index 73% rename from wifi/1.4/default/wifi_chip.h rename to wifi/1.5/default/wifi_chip.h index 98e18bba07f7239a9b13d5aacf1b2f756eb538a6..bd40ead35a87c3ad070e93aba9aa1bafd08c6864 100644 --- a/wifi/1.4/default/wifi_chip.h +++ b/wifi/1.5/default/wifi_chip.h @@ -22,8 +22,8 @@ #include #include -#include #include +#include #include "hidl_callback_util.h" #include "ringbuffer.h" @@ -39,7 +39,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { using namespace android::hardware::wifi::V1_0; @@ -48,15 +48,16 @@ using namespace android::hardware::wifi::V1_0; * Since there is only a single chip instance used today, there is no * identifying handle information stored here. */ -class WifiChip : public V1_4::IWifiChip { +class WifiChip : public V1_5::IWifiChip { public: - WifiChip( - ChipId chip_id, - const std::weak_ptr legacy_hal, - const std::weak_ptr - mode_controller, - const std::weak_ptr iface_util, - const std::weak_ptr feature_flags); + WifiChip(ChipId chip_id, bool is_primary, + const std::weak_ptr legacy_hal, + const std::weak_ptr + mode_controller, + const std::shared_ptr iface_util, + const std::weak_ptr feature_flags, + const std::function& + subsystemCallbackHandler); // HIDL does not provide a built-in mechanism to let the server invalidate // a HIDL interface object after creation. If any client process holds onto // a reference to the object in their context, any method calls on that @@ -72,7 +73,7 @@ class WifiChip : public V1_4::IWifiChip { // marked valid before processing them. void invalidate(); bool isValid(); - std::set> getEventCallbacks(); + std::set> getEventCallbacks(); // HIDL methods exposed. Return getId(getId_cb hidl_status_cb) override; @@ -93,11 +94,16 @@ class WifiChip : public V1_4::IWifiChip { Return requestFirmwareDebugDump( requestFirmwareDebugDump_cb hidl_status_cb) override; Return createApIface(createApIface_cb hidl_status_cb) override; + Return createBridgedApIface( + createBridgedApIface_cb hidl_status_cb) override; Return getApIfaceNames(getApIfaceNames_cb hidl_status_cb) override; Return getApIface(const hidl_string& ifname, getApIface_cb hidl_status_cb) override; Return removeApIface(const hidl_string& ifname, removeApIface_cb hidl_status_cb) override; + Return removeIfaceInstanceFromBridgedApIface( + const hidl_string& brIfaceName, const hidl_string& ifaceInstanceName, + removeIfaceInstanceFromBridgedApIface_cb hidl_status_cb) override; Return createNanIface(createNanIface_cb hidl_status_cb) override; Return getNanIfaceNames(getNanIfaceNames_cb hidl_status_cb) override; Return getNanIface(const hidl_string& ifname, @@ -152,14 +158,34 @@ class WifiChip : public V1_4::IWifiChip { selectTxPowerScenario_cb hidl_status_cb) override; Return getCapabilities_1_3( getCapabilities_cb hidl_status_cb) override; + Return getCapabilities_1_5( + getCapabilities_1_5_cb hidl_status_cb) override; Return debug(const hidl_handle& handle, const hidl_vec& options) override; Return createRttController_1_4( const sp& bound_iface, createRttController_1_4_cb hidl_status_cb) override; Return registerEventCallback_1_4( - const sp& event_callback, + const sp& event_callback, registerEventCallback_1_4_cb hidl_status_cb) override; + Return setMultiStaPrimaryConnection( + const hidl_string& ifname, + setMultiStaPrimaryConnection_cb hidl_status_cb) override; + Return setMultiStaUseCase( + MultiStaUseCase use_case, + setMultiStaUseCase_cb hidl_status_cb) override; + Return setCoexUnsafeChannels( + const hidl_vec& unsafe_channels, + hidl_bitfield restrictions, + setCoexUnsafeChannels_cb hidl_status_cb) override; + Return setCountryCode(const hidl_array& code, + setCountryCode_cb _hidl_cb) override; + Return getUsableChannels( + WifiBand band, hidl_bitfield ifaceModeMask, + hidl_bitfield filterMask, + getUsableChannels_cb _hidl_cb) override; + Return triggerSubsystemRestart( + triggerSubsystemRestart_cb hidl_status_cb) override; private: void invalidateAndRemoveAllIfaces(); @@ -183,14 +209,20 @@ class WifiChip : public V1_4::IWifiChip { requestDriverDebugDumpInternal(); std::pair> requestFirmwareDebugDumpInternal(); - std::pair> createApIfaceInternal(); + sp newWifiApIface(std::string& ifname); + WifiStatus createVirtualApInterface(const std::string& apVirtIf); + std::pair> createApIfaceInternal(); + std::pair> + createBridgedApIfaceInternal(); std::pair> getApIfaceNamesInternal(); - std::pair> getApIfaceInternal( + std::pair> getApIfaceInternal( const std::string& ifname); WifiStatus removeApIfaceInternal(const std::string& ifname); - std::pair> createNanIfaceInternal(); + WifiStatus removeIfaceInstanceFromBridgedApIfaceInternal( + const std::string& brIfaceName, const std::string& ifInstanceName); + std::pair> createNanIfaceInternal(); std::pair> getNanIfaceNamesInternal(); - std::pair> getNanIfaceInternal( + std::pair> getNanIfaceInternal( const std::string& ifname); WifiStatus removeNanIfaceInternal(const std::string& ifname); std::pair> createP2pIfaceInternal(); @@ -198,9 +230,9 @@ class WifiChip : public V1_4::IWifiChip { std::pair> getP2pIfaceInternal( const std::string& ifname); WifiStatus removeP2pIfaceInternal(const std::string& ifname); - std::pair> createStaIfaceInternal(); + std::pair> createStaIfaceInternal(); std::pair> getStaIfaceNamesInternal(); - std::pair> getStaIfaceInternal( + std::pair> getStaIfaceInternal( const std::string& ifname); WifiStatus removeStaIfaceInternal(const std::string& ifname); std::pair> @@ -225,21 +257,29 @@ class WifiChip : public V1_4::IWifiChip { const sp& event_callback); WifiStatus selectTxPowerScenarioInternal_1_2(TxPowerScenario scenario); std::pair getCapabilitiesInternal_1_3(); - std::pair> + std::pair getCapabilitiesInternal_1_5(); + std::pair> createRttControllerInternal_1_4(const sp& bound_iface); WifiStatus registerEventCallbackInternal_1_4( - const sp& event_callback); - + const sp& event_callback); + WifiStatus setMultiStaPrimaryConnectionInternal(const std::string& ifname); + WifiStatus setMultiStaUseCaseInternal(MultiStaUseCase use_case); + WifiStatus setCoexUnsafeChannelsInternal( + std::vector unsafe_channels, uint32_t restrictions); + WifiStatus setCountryCodeInternal(const std::array& code); + std::pair> + getUsableChannelsInternal(WifiBand band, uint32_t ifaceModeMask, + uint32_t filterMask); WifiStatus handleChipConfiguration( std::unique_lock* lock, ChipModeId mode_id); WifiStatus registerDebugRingBufferCallback(); WifiStatus registerRadioModeChangeCallback(); - std::vector + std::vector getCurrentModeIfaceCombinations(); std::map getCurrentIfaceCombination(); std::vector> expandIfaceCombinations( - const IWifiChip::ChipIfaceCombination& combination); + const V1_4::IWifiChip::ChipIfaceCombination& combination); bool canExpandedIfaceComboSupportIfaceOfTypeWithCurrentIfaces( const std::map& expanded_combo, IfaceType requested_type); @@ -253,17 +293,24 @@ class WifiChip : public V1_4::IWifiChip { bool canCurrentModeSupportIfaceOfType(IfaceType requested_type); bool isValidModeId(ChipModeId mode_id); bool isStaApConcurrencyAllowedInCurrentMode(); - bool isDualApAllowedInCurrentMode(); + bool isDualStaConcurrencyAllowedInCurrentMode(); + uint32_t startIdxOfApIface(); std::string getFirstActiveWlanIfaceName(); - std::string allocateApOrStaIfaceName(uint32_t start_idx); + std::string allocateApOrStaIfaceName(IfaceType type, uint32_t start_idx); std::string allocateApIfaceName(); + std::vector allocateBridgedApInstanceNames(); std::string allocateStaIfaceName(); bool writeRingbufferFilesInternal(); + std::string getWlanIfaceNameWithType(IfaceType type, unsigned idx); + void invalidateAndClearBridgedApAll(); + void invalidateAndClearBridgedAp(const std::string& br_name); + bool findUsingNameFromBridgedApInstances(const std::string& name); + WifiStatus triggerSubsystemRestartInternal(); ChipId chip_id_; std::weak_ptr legacy_hal_; std::weak_ptr mode_controller_; - std::weak_ptr iface_util_; + std::shared_ptr iface_util_; std::vector> ap_ifaces_; std::vector> nan_ifaces_; std::vector> p2p_ifaces_; @@ -274,19 +321,21 @@ class WifiChip : public V1_4::IWifiChip { // Members pertaining to chip configuration. uint32_t current_mode_id_; std::mutex lock_t; - std::vector modes_; + std::vector modes_; // The legacy ring buffer callback API has only a global callback // registration mechanism. Use this to check if we have already // registered a callback. bool debug_ring_buffer_cb_registered_; - hidl_callback_util::HidlCallbackHandler + hidl_callback_util::HidlCallbackHandler event_cb_handler_; + const std::function subsystemCallbackHandler_; + std::map> br_ifaces_ap_instances_; DISALLOW_COPY_AND_ASSIGN(WifiChip); }; } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/wifi_feature_flags.cpp b/wifi/1.5/default/wifi_feature_flags.cpp similarity index 64% rename from wifi/1.4/default/wifi_feature_flags.cpp rename to wifi/1.5/default/wifi_feature_flags.cpp index 195b460dfe05e88baef3f732483ea4d5919ae857..124ba32e9f6a1a26e9fc86eba76b92fcfd3437fb 100644 --- a/wifi/1.4/default/wifi_feature_flags.cpp +++ b/wifi/1.5/default/wifi_feature_flags.cpp @@ -14,12 +14,17 @@ * limitations under the License. */ +#include + +#include +#include + #include "wifi_feature_flags.h" namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { namespace feature_flags { @@ -131,7 +136,7 @@ struct ChipIfaceCombination #define AP IfaceType::AP #define P2P IfaceType::P2P #define NAN IfaceType::NAN -static const std::vector kChipModes{ +static const std::vector kChipModesPrimary{ {kMainModeId, ChipIfaceCombination::make_vec({WIFI_HAL_INTERFACE_COMBINATIONS})}, #ifdef WIFI_HAL_INTERFACE_COMBINATIONS_AP @@ -139,6 +144,57 @@ static const std::vector kChipModes{ ChipIfaceCombination::make_vec({WIFI_HAL_INTERFACE_COMBINATIONS_AP})}, #endif }; + +static const std::vector kChipModesSecondary{ +#ifdef WIFI_HAL_INTERFACE_COMBINATIONS_SECONDARY_CHIP + {chip_mode_ids::kV3, ChipIfaceCombination::make_vec( + {WIFI_HAL_INTERFACE_COMBINATIONS_SECONDARY_CHIP})}, +#endif +}; + +constexpr char kDebugPresetInterfaceCombinationIdxProperty[] = + "persist.vendor.debug.wifi.hal.preset_interface_combination_idx"; +// List of pre-defined interface combinations that can be enabled at runtime via +// setting the property: "kDebugPresetInterfaceCombinationIdxProperty" to the +// corresponding index value. +static const std::vector< + std::pair>> + kDebugChipModes{ + // Legacy combination - No STA/AP concurrencies. + // 0 - (1 AP) or (1 STA + 1 of (P2P or NAN)) + {"No STA/AP Concurrency", + {{kMainModeId, + ChipIfaceCombination::make_vec( + {{{{AP}, 1}}, {{{STA}, 1}, {{P2P, NAN}, 1}}})}}}, + + // STA + AP concurrency + // 1 - (1 STA + 1 AP) or (1 STA + 1 of (P2P or NAN)) + {"STA + AP Concurrency", + {{kMainModeId, + ChipIfaceCombination::make_vec( + {{{{STA}, 1}, {{AP}, 1}}, {{{STA}, 1}, {{P2P, NAN}, 1}}})}}}, + + // STA + STA concurrency + // 2 - (1 STA + 1 AP) or (2 STA + 1 of (P2P or NAN)) + {"Dual STA Concurrency", + {{kMainModeId, + ChipIfaceCombination::make_vec( + {{{{STA}, 1}, {{AP}, 1}}, {{{STA}, 2}, {{P2P, NAN}, 1}}})}}}, + + // AP + AP + STA concurrency + // 3 - (1 STA + 2 AP) or (1 STA + 1 of (P2P or NAN)) + {"Dual AP Concurrency", + {{kMainModeId, + ChipIfaceCombination::make_vec( + {{{{STA}, 1}, {{AP}, 2}}, {{{STA}, 1}, {{P2P, NAN}, 1}}})}}}, + + // STA + STA concurrency and AP + AP + STA concurrency + // 4 - (1 STA + 2 AP) or (2 STA + 1 of (P2P or NAN)) + {"Dual STA & Dual AP Concurrency", + {{kMainModeId, + ChipIfaceCombination::make_vec( + {{{{STA}, 1}, {{AP}, 2}}, {{{STA}, 2}, {{P2P, NAN}, 1}}})}}}}; + #undef STA #undef AP #undef P2P @@ -154,13 +210,36 @@ static const std::vector kChipModes{ WifiFeatureFlags::WifiFeatureFlags() {} -std::vector WifiFeatureFlags::getChipModes() { - return kChipModes; +std::vector WifiFeatureFlags::getChipModesForPrimary() { + std::array buffer; + auto res = property_get(kDebugPresetInterfaceCombinationIdxProperty, + buffer.data(), nullptr); + // Debug propety not set, use the device preset interface combination. + if (res <= 0) return kChipModesPrimary; + + // Debug propety set, use one of the debug preset interface combination. + unsigned long idx = std::stoul(buffer.data()); + if (idx >= kDebugChipModes.size()) { + LOG(ERROR) << "Invalid index set in property: " + << kDebugPresetInterfaceCombinationIdxProperty; + return kChipModesPrimary; + } + std::string name; + std::vector chip_modes; + std::tie(name, chip_modes) = kDebugChipModes[idx]; + LOG(INFO) << "Using debug chip mode: <" << name << "> set via property: " + << kDebugPresetInterfaceCombinationIdxProperty; + return chip_modes; +} + +std::vector WifiFeatureFlags::getChipModes( + bool is_primary) { + return (is_primary) ? getChipModesForPrimary() : kChipModesSecondary; } } // namespace feature_flags } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/wifi_feature_flags.h b/wifi/1.5/default/wifi_feature_flags.h similarity index 91% rename from wifi/1.4/default/wifi_feature_flags.h rename to wifi/1.5/default/wifi_feature_flags.h index 292dedfe19e427834d31a5adafa7abeaf9f9aa91..7d561fc94950ae2affa089197c9ccd960056090d 100644 --- a/wifi/1.4/default/wifi_feature_flags.h +++ b/wifi/1.5/default/wifi_feature_flags.h @@ -22,7 +22,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { namespace feature_flags { @@ -42,12 +42,16 @@ class WifiFeatureFlags { WifiFeatureFlags(); virtual ~WifiFeatureFlags() = default; - virtual std::vector getChipModes(); + virtual std::vector getChipModes( + bool is_primary); + + private: + std::vector getChipModesForPrimary(); }; } // namespace feature_flags } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/wifi_iface_util.cpp b/wifi/1.5/default/wifi_iface_util.cpp similarity index 67% rename from wifi/1.4/default/wifi_iface_util.cpp rename to wifi/1.5/default/wifi_iface_util.cpp index 49b76747d67fddb89aed04e2f5613c333797917a..7bf830b87528f9516bac1c431244658b90b2e8cd 100644 --- a/wifi/1.4/default/wifi_iface_util.cpp +++ b/wifi/1.5/default/wifi_iface_util.cpp @@ -36,13 +36,15 @@ constexpr uint8_t kMacAddressLocallyAssignedMask = 0x02; namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { namespace iface_util { WifiIfaceUtil::WifiIfaceUtil( - const std::weak_ptr iface_tool) + const std::weak_ptr iface_tool, + const std::weak_ptr legacy_hal) : iface_tool_(iface_tool), + legacy_hal_(legacy_hal), random_mac_address_(nullptr), event_handlers_map_() {} @@ -59,14 +61,20 @@ bool WifiIfaceUtil::setMacAddress(const std::string& iface_name, return false; } #endif - if (!iface_tool_.lock()->SetMacAddress(iface_name.c_str(), mac)) { - LOG(ERROR) << "SetMacAddress failed."; - return false; - } + bool success = iface_tool_.lock()->SetMacAddress(iface_name.c_str(), mac); #ifndef WIFI_AVOID_IFACE_RESET_MAC_CHANGE if (!iface_tool_.lock()->SetUpState(iface_name.c_str(), true)) { - LOG(ERROR) << "SetUpState(true) failed."; - return false; + LOG(ERROR) << "SetUpState(true) failed. Wait for driver ready."; + // Wait for driver ready and try to set iface UP again + if (legacy_hal_.lock()->waitForDriverReady() != + legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "SetUpState(true) wait for driver ready failed."; + return false; + } + if (!iface_tool_.lock()->SetUpState(iface_name.c_str(), true)) { + LOG(ERROR) << "SetUpState(true) failed after retry."; + return false; + } } #endif IfaceEventHandlers event_handlers = {}; @@ -77,8 +85,12 @@ bool WifiIfaceUtil::setMacAddress(const std::string& iface_name, if (event_handlers.on_state_toggle_off_on != nullptr) { event_handlers.on_state_toggle_off_on(iface_name); } - LOG(DEBUG) << "Successfully SetMacAddress."; - return true; + if (!success) { + LOG(ERROR) << "SetMacAddress failed on " << iface_name; + } else { + LOG(DEBUG) << "SetMacAddress succeeded on " << iface_name; + } + return success; } std::array WifiIfaceUtil::getOrCreateRandomMacAddress() { @@ -127,9 +139,39 @@ bool WifiIfaceUtil::setUpState(const std::string& iface_name, bool request_up) { unsigned WifiIfaceUtil::ifNameToIndex(const std::string& iface_name) { return if_nametoindex(iface_name.c_str()); } + +bool WifiIfaceUtil::createBridge(const std::string& br_name) { + if (!iface_tool_.lock()->createBridge(br_name)) { + return false; + } + + if (!iface_tool_.lock()->SetUpState(br_name.c_str(), true)) { + LOG(ERROR) << "bridge SetUpState(true) failed."; + } + return true; +} + +bool WifiIfaceUtil::deleteBridge(const std::string& br_name) { + if (!iface_tool_.lock()->SetUpState(br_name.c_str(), false)) { + LOG(INFO) << "SetUpState(false) failed for bridge=" << br_name.c_str(); + } + + return iface_tool_.lock()->deleteBridge(br_name); +} + +bool WifiIfaceUtil::addIfaceToBridge(const std::string& br_name, + const std::string& if_name) { + return iface_tool_.lock()->addIfaceToBridge(br_name, if_name); +} + +bool WifiIfaceUtil::removeIfaceFromBridge(const std::string& br_name, + const std::string& if_name) { + return iface_tool_.lock()->removeIfaceFromBridge(br_name, if_name); +} + } // namespace iface_util } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/wifi_iface_util.h b/wifi/1.5/default/wifi_iface_util.h similarity index 78% rename from wifi/1.4/default/wifi_iface_util.h rename to wifi/1.5/default/wifi_iface_util.h index 126b6ca59934f5b9ca569e6c10e2c5b0ae0fd3b5..544f575d4187a7a66fc50bb2efbd30cd4190aa19 100644 --- a/wifi/1.4/default/wifi_iface_util.h +++ b/wifi/1.5/default/wifi_iface_util.h @@ -21,10 +21,12 @@ #include +#include "wifi_legacy_hal.h" + namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { namespace iface_util { @@ -40,7 +42,8 @@ struct IfaceEventHandlers { */ class WifiIfaceUtil { public: - WifiIfaceUtil(const std::weak_ptr iface_tool); + WifiIfaceUtil(const std::weak_ptr iface_tool, + const std::weak_ptr legacy_hal); virtual ~WifiIfaceUtil() = default; virtual std::array getFactoryMacAddress( @@ -59,17 +62,28 @@ class WifiIfaceUtil { virtual bool setUpState(const std::string& iface_name, bool request_up); virtual unsigned ifNameToIndex(const std::string& iface_name); - private: - std::array createRandomMacAddress(); + virtual bool createBridge(const std::string& br_name); + + virtual bool deleteBridge(const std::string& br_name); + virtual bool addIfaceToBridge(const std::string& br_name, + const std::string& if_name); + + virtual bool removeIfaceFromBridge(const std::string& br_name, + const std::string& if_name); + // Get a random MAC address. + virtual std::array createRandomMacAddress(); + + private: std::weak_ptr iface_tool_; + std::weak_ptr legacy_hal_; std::unique_ptr> random_mac_address_; std::map event_handlers_map_; }; } // namespace iface_util } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/wifi_legacy_hal.cpp b/wifi/1.5/default/wifi_legacy_hal.cpp similarity index 85% rename from wifi/1.4/default/wifi_legacy_hal.cpp rename to wifi/1.5/default/wifi_legacy_hal.cpp index 9e6b5a3e143b63811d4ace9e0795c912ca3992ad..5074252d3de12289c044b00b6d49e5b406e7794c 100644 --- a/wifi/1.4/default/wifi_legacy_hal.cpp +++ b/wifi/1.5/default/wifi_legacy_hal.cpp @@ -36,7 +36,9 @@ 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 = 300; +static constexpr uint32_t kMaxWifiUsableChannels = 256; +// need a long timeout (1000ms) for chips that unload their driver. +static constexpr uint32_t kMaxStopCompleteWaitMs = 1000; static constexpr char kDriverPropName[] = "wlan.driver.status"; // Helper function to create a non-const char* for legacy Hal API's. @@ -51,9 +53,10 @@ std::vector makeCharVec(const std::string& str) { namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { 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. @@ -162,6 +165,15 @@ void onAsyncRadioModeChange(wifi_request_id id, uint32_t num_macs, } } +// Callback to be invoked to report subsystem restart +std::function on_subsystem_restart_internal_callback; +void onAsyncSubsystemRestart(const char* error) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_subsystem_restart_internal_callback) { + on_subsystem_restart_internal_callback(error); + } +} + // Callback to be invoked for rtt results results. std::function @@ -332,29 +344,60 @@ void onAsyncNanEventScheduleUpdate(NanDataPathScheduleUpdateInd* event) { on_nan_event_schedule_update_user_callback(*event); } } + +// Callbacks for the various TWT operations. +std::function + on_twt_event_setup_response_callback; +void onAsyncTwtEventSetupResponse(TwtSetupResponse* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_twt_event_setup_response_callback && event) { + on_twt_event_setup_response_callback(*event); + } +} + +std::function + on_twt_event_teardown_completion_callback; +void onAsyncTwtEventTeardownCompletion(TwtTeardownCompletion* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_twt_event_teardown_completion_callback && event) { + on_twt_event_teardown_completion_callback(*event); + } +} + +std::function + on_twt_event_info_frame_received_callback; +void onAsyncTwtEventInfoFrameReceived(TwtInfoFrameReceived* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_twt_event_info_frame_received_callback && event) { + on_twt_event_info_frame_received_callback(*event); + } +} + +std::function on_twt_event_device_notify_callback; +void onAsyncTwtEventDeviceNotify(TwtDeviceNotify* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_twt_event_device_notify_callback && event) { + on_twt_event_device_notify_callback(*event); + } +} + // End of the free-standing "C" style callbacks. WifiLegacyHal::WifiLegacyHal( - const std::weak_ptr iface_tool) - : global_handle_(nullptr), + const std::weak_ptr iface_tool, + const wifi_hal_fn& fn, bool is_primary) + : global_func_table_(fn), + global_handle_(nullptr), awaiting_event_loop_termination_(false), is_started_(false), - iface_tool_(iface_tool) {} + iface_tool_(iface_tool), + is_primary_(is_primary) {} wifi_error WifiLegacyHal::initialize() { LOG(DEBUG) << "Initialize legacy HAL"; - // TODO: Add back the HAL Tool if we need to. All we need from the HAL tool - // for now is this function call which we can directly call. - if (!initHalFuncTableWithStubs(&global_func_table_)) { - LOG(ERROR) - << "Failed to initialize legacy hal function table with stubs"; - return WIFI_ERROR_UNKNOWN; - } - wifi_error status = init_wifi_vendor_hal_func_table(&global_func_table_); - if (status != WIFI_SUCCESS) { - LOG(ERROR) << "Failed to initialize legacy hal function table"; - } - return status; + // this now does nothing, since HAL function table is provided + // to the constructor + return WIFI_SUCCESS; } wifi_error WifiLegacyHal::start() { @@ -371,13 +414,17 @@ wifi_error WifiLegacyHal::start() { LOG(ERROR) << "Failed or timed out awaiting driver ready"; return status; } - property_set(kDriverPropName, "ok"); - LOG(DEBUG) << "Starting legacy HAL"; - if (!iface_tool_.lock()->SetWifiUpState(true)) { - LOG(ERROR) << "Failed to set WiFi interface up"; - return WIFI_ERROR_UNKNOWN; + if (is_primary_) { + property_set(kDriverPropName, "ok"); + + if (!iface_tool_.lock()->SetWifiUpState(true)) { + LOG(ERROR) << "Failed to set WiFi interface up"; + return WIFI_ERROR_UNKNOWN; + } } + + LOG(DEBUG) << "Starting legacy HAL"; status = global_func_table_.wifi_initialize(&global_handle_); if (status != WIFI_SUCCESS || !global_handle_) { LOG(ERROR) << "Failed to retrieve global handle"; @@ -410,7 +457,7 @@ wifi_error WifiLegacyHal::stop( // Invalidate all the internal pointers now that the HAL is // stopped. invalidate(); - iface_tool_.lock()->SetWifiUpState(false); + if (is_primary_) iface_tool_.lock()->SetWifiUpState(false); on_stop_complete_user_callback(); is_started_ = false; }; @@ -429,6 +476,10 @@ wifi_error WifiLegacyHal::stop( bool WifiLegacyHal::isStarted() { return is_started_; } +wifi_error WifiLegacyHal::waitForDriverReady() { + return global_func_table_.wifi_wait_for_driver_ready(); +} + std::pair WifiLegacyHal::getDriverVersion( const std::string& iface_name) { std::array buffer; @@ -477,14 +528,23 @@ WifiLegacyHal::requestFirmwareMemoryDump(const std::string& iface_name) { return {status, std::move(firmware_dump)}; } -std::pair WifiLegacyHal::getSupportedFeatureSet( +std::pair WifiLegacyHal::getSupportedFeatureSet( const std::string& iface_name) { - feature_set set; + feature_set set = 0, chip_set = 0; + wifi_error status = WIFI_SUCCESS; + static_assert(sizeof(set) == sizeof(uint64_t), "Some feature_flags can not be represented in output"); - wifi_error status = global_func_table_.wifi_get_supported_feature_set( - getIfaceHandle(iface_name), &set); - return {status, static_cast(set)}; + wifi_interface_handle iface_handle = getIfaceHandle(iface_name); + + global_func_table_.wifi_get_chip_feature_set( + global_handle_, &chip_set); /* ignore error, chip_set will stay 0 */ + + if (iface_handle) { + status = global_func_table_.wifi_get_supported_feature_set(iface_handle, + &set); + } + return {status, static_cast(set | chip_set)}; } std::pair @@ -659,9 +719,29 @@ std::pair WifiLegacyHal::getLinkLayerStats( wifi_iface_stat* iface_stats_ptr, int num_radios, wifi_radio_stat* radio_stats_ptr) { wifi_radio_stat* l_radio_stats_ptr; + wifi_peer_info* l_peer_info_stats_ptr; if (iface_stats_ptr != nullptr) { link_stats_ptr->iface = *iface_stats_ptr; + l_peer_info_stats_ptr = iface_stats_ptr->peer_info; + for (uint32_t i = 0; i < iface_stats_ptr->num_peers; i++) { + WifiPeerInfo peer; + peer.peer_info = *l_peer_info_stats_ptr; + if (l_peer_info_stats_ptr->num_rate > 0) { + /* Copy the rate stats */ + peer.rate_stats.assign( + l_peer_info_stats_ptr->rate_stats, + l_peer_info_stats_ptr->rate_stats + + l_peer_info_stats_ptr->num_rate); + } + peer.peer_info.num_rate = 0; + link_stats_ptr->peers.push_back(peer); + l_peer_info_stats_ptr = + (wifi_peer_info*)((u8*)l_peer_info_stats_ptr + + sizeof(wifi_peer_info) + + (sizeof(wifi_rate_stat) * + l_peer_info_stats_ptr->num_rate)); + } link_stats_ptr->iface.num_peers = 0; } else { LOG(ERROR) << "Invalid iface stats in link layer stats"; @@ -836,10 +916,15 @@ wifi_error WifiLegacyHal::resetDscpToAccessCategoryMapping() { std::pair WifiLegacyHal::getLoggerSupportedFeatureSet( const std::string& iface_name) { - uint32_t supported_feature_flags; - wifi_error status = - global_func_table_.wifi_get_logger_supported_feature_set( - getIfaceHandle(iface_name), &supported_feature_flags); + uint32_t supported_feature_flags = 0; + wifi_error status = WIFI_SUCCESS; + + wifi_interface_handle iface_handle = getIfaceHandle(iface_name); + + if (iface_handle) { + status = global_func_table_.wifi_get_logger_supported_feature_set( + iface_handle, &supported_feature_flags); + } return {status, supported_feature_flags}; } @@ -1049,6 +1134,23 @@ wifi_error WifiLegacyHal::registerRadioModeChangeCallbackHandler( return status; } +wifi_error WifiLegacyHal::registerSubsystemRestartCallbackHandler( + const on_subsystem_restart_callback& on_restart_callback) { + if (on_subsystem_restart_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + on_subsystem_restart_internal_callback = + [on_restart_callback](const char* error) { + on_restart_callback(error); + }; + wifi_error status = global_func_table_.wifi_set_subsystem_restart_handler( + global_handle_, {onAsyncSubsystemRestart}); + if (status != WIFI_SUCCESS) { + on_subsystem_restart_internal_callback = nullptr; + } + return status; +} + wifi_error WifiLegacyHal::startRttRangeRequest( const std::string& iface_name, wifi_request_id id, const std::vector& rtt_configs, @@ -1459,6 +1561,125 @@ wifi_error WifiLegacyHal::handleVirtualInterfaceCreateOrDeleteStatus( return status; } +wifi_error WifiLegacyHal::getSupportedIfaceName(uint32_t iface_type, + std::string& ifname) { + std::array buffer; + + wifi_error res = global_func_table_.wifi_get_supported_iface_name( + global_handle_, (uint32_t)iface_type, buffer.data(), buffer.size()); + if (res == WIFI_SUCCESS) ifname = buffer.data(); + + return res; +} + +wifi_error WifiLegacyHal::multiStaSetPrimaryConnection( + const std::string& ifname) { + return global_func_table_.wifi_multi_sta_set_primary_connection( + global_handle_, getIfaceHandle(ifname)); +} + +wifi_error WifiLegacyHal::multiStaSetUseCase(wifi_multi_sta_use_case use_case) { + return global_func_table_.wifi_multi_sta_set_use_case(global_handle_, + use_case); +} + +wifi_error WifiLegacyHal::setCoexUnsafeChannels( + std::vector unsafe_channels, + uint32_t restrictions) { + return global_func_table_.wifi_set_coex_unsafe_channels( + global_handle_, unsafe_channels.size(), unsafe_channels.data(), + restrictions); +} + +wifi_error WifiLegacyHal::setVoipMode(const std::string& iface_name, + wifi_voip_mode mode) { + return global_func_table_.wifi_set_voip_mode(getIfaceHandle(iface_name), + mode); +} + +wifi_error WifiLegacyHal::twtRegisterHandler( + const std::string& iface_name, const TwtCallbackHandlers& user_callbacks) { + on_twt_event_setup_response_callback = user_callbacks.on_setup_response; + on_twt_event_teardown_completion_callback = + user_callbacks.on_teardown_completion; + on_twt_event_info_frame_received_callback = + user_callbacks.on_info_frame_received; + on_twt_event_device_notify_callback = user_callbacks.on_device_notify; + + return global_func_table_.wifi_twt_register_handler( + getIfaceHandle(iface_name), + {onAsyncTwtEventSetupResponse, onAsyncTwtEventTeardownCompletion, + onAsyncTwtEventInfoFrameReceived, onAsyncTwtEventDeviceNotify}); +} + +std::pair WifiLegacyHal::twtGetCapability( + const std::string& iface_name) { + TwtCapabilitySet capSet; + wifi_error status = global_func_table_.wifi_twt_get_capability( + getIfaceHandle(iface_name), &capSet); + return {status, capSet}; +} + +wifi_error WifiLegacyHal::twtSetupRequest(const std::string& iface_name, + const TwtSetupRequest& msg) { + TwtSetupRequest msgInternal(msg); + return global_func_table_.wifi_twt_setup_request(getIfaceHandle(iface_name), + &msgInternal); +} + +wifi_error WifiLegacyHal::twtTearDownRequest(const std::string& iface_name, + const TwtTeardownRequest& msg) { + TwtTeardownRequest msgInternal(msg); + return global_func_table_.wifi_twt_teardown_request( + getIfaceHandle(iface_name), &msgInternal); +} + +wifi_error WifiLegacyHal::twtInfoFrameRequest(const std::string& iface_name, + const TwtInfoFrameRequest& msg) { + TwtInfoFrameRequest msgInternal(msg); + return global_func_table_.wifi_twt_info_frame_request( + getIfaceHandle(iface_name), &msgInternal); +} + +std::pair WifiLegacyHal::twtGetStats( + const std::string& iface_name, uint8_t configId) { + TwtStats stats; + wifi_error status = global_func_table_.wifi_twt_get_stats( + getIfaceHandle(iface_name), configId, &stats); + return {status, stats}; +} + +wifi_error WifiLegacyHal::twtClearStats(const std::string& iface_name, + uint8_t configId) { + return global_func_table_.wifi_twt_clear_stats(getIfaceHandle(iface_name), + configId); +} + +wifi_error WifiLegacyHal::setDtimConfig(const std::string& iface_name, + uint32_t multiplier) { + return global_func_table_.wifi_set_dtim_config(getIfaceHandle(iface_name), + multiplier); +} + +std::pair> +WifiLegacyHal::getUsableChannels(uint32_t band_mask, uint32_t iface_mode_mask, + uint32_t filter_mask) { + std::vector channels; + channels.resize(kMaxWifiUsableChannels); + uint32_t size = 0; + wifi_error status = global_func_table_.wifi_get_usable_channels( + global_handle_, band_mask, iface_mode_mask, filter_mask, + channels.size(), &size, + reinterpret_cast(channels.data())); + CHECK(size >= 0 && size <= kMaxWifiUsableChannels); + channels.resize(size); + return {status, std::move(channels)}; +} + +wifi_error WifiLegacyHal::triggerSubsystemRestart() { + return global_func_table_.wifi_trigger_subsystem_restart(global_handle_); +} + void WifiLegacyHal::invalidate() { global_handle_ = nullptr; iface_name_to_handle_.clear(); @@ -1471,6 +1692,7 @@ void WifiLegacyHal::invalidate() { on_ring_buffer_data_internal_callback = nullptr; on_error_alert_internal_callback = nullptr; on_radio_mode_change_internal_callback = nullptr; + on_subsystem_restart_internal_callback = nullptr; on_rtt_results_internal_callback = nullptr; on_nan_notify_response_user_callback = nullptr; on_nan_event_publish_terminated_user_callback = nullptr; @@ -1489,11 +1711,15 @@ void WifiLegacyHal::invalidate() { on_nan_event_range_request_user_callback = nullptr; on_nan_event_range_report_user_callback = nullptr; on_nan_event_schedule_update_user_callback = nullptr; + on_twt_event_setup_response_callback = nullptr; + on_twt_event_teardown_completion_callback = nullptr; + on_twt_event_info_frame_received_callback = nullptr; + on_twt_event_device_notify_callback = nullptr; } } // namespace legacy_hal } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/wifi_legacy_hal.h b/wifi/1.5/default/wifi_legacy_hal.h similarity index 87% rename from wifi/1.4/default/wifi_legacy_hal.h rename to wifi/1.5/default/wifi_legacy_hal.h index 822f83aca3a5819240f9ad4ffaf625703a99ba4b..2bb7631efa9da7ff13df99938d1e54c0a3b8cd1a 100644 --- a/wifi/1.4/default/wifi_legacy_hal.h +++ b/wifi/1.5/default/wifi_legacy_hal.h @@ -29,16 +29,20 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { // This is in a separate namespace to prevent typename conflicts between // the legacy HAL types and the HIDL interface types. namespace legacy_hal { // Import all the types defined inside the legacy HAL header files into this // namespace. +using ::frame_info; +using ::frame_type; using ::FRAME_TYPE_80211_MGMT; using ::FRAME_TYPE_ETHERNET_II; using ::FRAME_TYPE_UNKNOWN; +using ::fw_roaming_state_t; +using ::mac_addr; using ::NAN_CHANNEL_24G_BAND; using ::NAN_CHANNEL_5G_BAND_HIGH; using ::NAN_CHANNEL_5G_BAND_LOW; @@ -80,8 +84,6 @@ using ::NAN_RESPONSE_SUBSCRIBE_CANCEL; using ::NAN_RESPONSE_TCA; using ::NAN_RESPONSE_TRANSMIT_FOLLOWUP; using ::NAN_SECURITY_KEY_INPUT_PASSPHRASE; -using ::NAN_SECURITY_KEY_INPUT_PASSPHRASE; -using ::NAN_SECURITY_KEY_INPUT_PMK; using ::NAN_SECURITY_KEY_INPUT_PMK; using ::NAN_SERVICE_ACCEPT_POLICY_ALL; using ::NAN_SERVICE_ACCEPT_POLICY_NONE; @@ -154,19 +156,20 @@ using ::RTT_PEER_NAN; using ::RTT_PEER_P2P_CLIENT; using ::RTT_PEER_P2P_GO; using ::RTT_PEER_STA; +using ::rtt_peer_type; using ::RTT_STATUS_ABORTED; -using ::RTT_STATUS_FAILURE; using ::RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL; using ::RTT_STATUS_FAIL_BUSY_TRY_LATER; using ::RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE; using ::RTT_STATUS_FAIL_INVALID_TS; -using ::RTT_STATUS_FAIL_NOT_SCHEDULED_YET; using ::RTT_STATUS_FAIL_NO_CAPABILITY; using ::RTT_STATUS_FAIL_NO_RSP; +using ::RTT_STATUS_FAIL_NOT_SCHEDULED_YET; using ::RTT_STATUS_FAIL_PROTOCOL; using ::RTT_STATUS_FAIL_REJECTED; using ::RTT_STATUS_FAIL_SCHEDULE; using ::RTT_STATUS_FAIL_TM_TIMEOUT; +using ::RTT_STATUS_FAILURE; using ::RTT_STATUS_INVALID_REQ; using ::RTT_STATUS_NAN_RANGING_CONCURRENCY_NOT_SUPPORTED; using ::RTT_STATUS_NAN_RANGING_PROTOCOL_FAILURE; @@ -185,6 +188,8 @@ using ::RX_PKT_FATE_FW_DROP_NOBUFS; using ::RX_PKT_FATE_FW_DROP_OTHER; using ::RX_PKT_FATE_FW_QUEUED; using ::RX_PKT_FATE_SUCCESS; +using ::ssid_t; +using ::transaction_id; using ::TX_PKT_FATE_ACKED; using ::TX_PKT_FATE_DRV_DROP_INVALID; using ::TX_PKT_FATE_DRV_DROP_NOBUFS; @@ -199,22 +204,31 @@ using ::WIFI_AC_BE; using ::WIFI_AC_BK; using ::WIFI_AC_VI; using ::WIFI_AC_VO; +using ::wifi_band; using ::WIFI_BAND_A; -using ::WIFI_BAND_ABG; -using ::WIFI_BAND_ABG_WITH_DFS; using ::WIFI_BAND_A_DFS; using ::WIFI_BAND_A_WITH_DFS; +using ::WIFI_BAND_ABG; +using ::WIFI_BAND_ABG_WITH_DFS; using ::WIFI_BAND_BG; using ::WIFI_BAND_UNSPECIFIED; +using ::wifi_cached_scan_results; using ::WIFI_CHAN_WIDTH_10; using ::WIFI_CHAN_WIDTH_160; using ::WIFI_CHAN_WIDTH_20; using ::WIFI_CHAN_WIDTH_40; using ::WIFI_CHAN_WIDTH_5; -using ::WIFI_CHAN_WIDTH_5; using ::WIFI_CHAN_WIDTH_80; using ::WIFI_CHAN_WIDTH_80P80; using ::WIFI_CHAN_WIDTH_INVALID; +using ::wifi_channel_info; +using ::wifi_channel_stat; +using ::wifi_channel_width; +using ::wifi_coex_restriction; +using ::wifi_coex_unsafe_channel; +using ::WIFI_DUAL_STA_NON_TRANSIENT_UNBIASED; +using ::WIFI_DUAL_STA_TRANSIENT_PREFER_PRIMARY; +using ::wifi_error; using ::WIFI_ERROR_BUSY; using ::WIFI_ERROR_INVALID_ARGS; using ::WIFI_ERROR_INVALID_REQUEST_ID; @@ -226,12 +240,29 @@ using ::WIFI_ERROR_TIMED_OUT; using ::WIFI_ERROR_TOO_MANY_REQUESTS; using ::WIFI_ERROR_UNINITIALIZED; using ::WIFI_ERROR_UNKNOWN; +using ::wifi_gscan_capabilities; +using ::wifi_hal_fn; +using ::wifi_information_element; +using ::WIFI_INTERFACE_IBSS; +using ::WIFI_INTERFACE_MESH; +using ::wifi_interface_mode; +using ::WIFI_INTERFACE_NAN; +using ::WIFI_INTERFACE_P2P_CLIENT; +using ::WIFI_INTERFACE_P2P_GO; +using ::WIFI_INTERFACE_SOFTAP; +using ::WIFI_INTERFACE_STA; +using ::WIFI_INTERFACE_TDLS; +using ::wifi_interface_type; using ::WIFI_INTERFACE_TYPE_AP; using ::WIFI_INTERFACE_TYPE_NAN; using ::WIFI_INTERFACE_TYPE_P2P; using ::WIFI_INTERFACE_TYPE_STA; +using ::WIFI_INTERFACE_UNKNOWN; +using ::wifi_latency_mode; using ::WIFI_LATENCY_MODE_LOW; using ::WIFI_LATENCY_MODE_NORMAL; +using ::wifi_lci_information; +using ::wifi_lcr_information; using ::WIFI_LOGGER_CONNECT_EVENT_SUPPORTED; using ::WIFI_LOGGER_DRIVER_DUMP_SUPPORTED; using ::WIFI_LOGGER_MEMORY_DUMP_SUPPORTED; @@ -240,57 +271,34 @@ using ::WIFI_LOGGER_POWER_EVENT_SUPPORTED; using ::WIFI_LOGGER_WAKE_LOCK_SUPPORTED; using ::WIFI_MOTION_EXPECTED; using ::WIFI_MOTION_NOT_EXPECTED; +using ::wifi_motion_pattern; using ::WIFI_MOTION_UNKNOWN; +using ::wifi_multi_sta_use_case; +using ::wifi_power_scenario; using ::WIFI_POWER_SCENARIO_ON_BODY_CELL_OFF; using ::WIFI_POWER_SCENARIO_ON_BODY_CELL_ON; using ::WIFI_POWER_SCENARIO_ON_HEAD_CELL_OFF; using ::WIFI_POWER_SCENARIO_ON_HEAD_CELL_ON; using ::WIFI_POWER_SCENARIO_VOICE_CALL; +using ::wifi_rate; +using ::wifi_request_id; +using ::wifi_ring_buffer_status; +using ::wifi_roaming_capabilities; +using ::wifi_roaming_config; +using ::wifi_rtt_bw; using ::WIFI_RTT_BW_10; using ::WIFI_RTT_BW_160; using ::WIFI_RTT_BW_20; using ::WIFI_RTT_BW_40; using ::WIFI_RTT_BW_5; using ::WIFI_RTT_BW_80; +using ::wifi_rtt_capabilities; +using ::wifi_rtt_config; +using ::wifi_rtt_preamble; using ::WIFI_RTT_PREAMBLE_HE; using ::WIFI_RTT_PREAMBLE_HT; using ::WIFI_RTT_PREAMBLE_LEGACY; using ::WIFI_RTT_PREAMBLE_VHT; -using ::WIFI_SCAN_FLAG_INTERRUPTED; -using ::WIFI_SUCCESS; -using ::WLAN_MAC_2_4_BAND; -using ::WLAN_MAC_5_0_BAND; -using ::WLAN_MAC_6_0_BAND; -using ::frame_info; -using ::frame_type; -using ::fw_roaming_state_t; -using ::mac_addr; -using ::rtt_peer_type; -using ::ssid_t; -using ::transaction_id; -using ::wifi_band; -using ::wifi_cached_scan_results; -using ::wifi_channel_info; -using ::wifi_channel_stat; -using ::wifi_channel_width; -using ::wifi_error; -using ::wifi_gscan_capabilities; -using ::wifi_information_element; -using ::wifi_interface_type; -using ::wifi_latency_mode; -using ::wifi_lci_information; -using ::wifi_lcr_information; -using ::wifi_motion_pattern; -using ::wifi_power_scenario; -using ::wifi_rate; -using ::wifi_request_id; -using ::wifi_ring_buffer_status; -using ::wifi_roaming_capabilities; -using ::wifi_roaming_config; -using ::wifi_rtt_bw; -using ::wifi_rtt_capabilities; -using ::wifi_rtt_config; -using ::wifi_rtt_preamble; using ::wifi_rtt_responder; using ::wifi_rtt_result; using ::wifi_rtt_status; @@ -299,9 +307,18 @@ using ::wifi_rx_packet_fate; using ::wifi_rx_report; using ::wifi_scan_bucket_spec; using ::wifi_scan_cmd_params; +using ::WIFI_SCAN_FLAG_INTERRUPTED; using ::wifi_scan_result; +using ::WIFI_SUCCESS; using ::wifi_tx_packet_fate; using ::wifi_tx_report; +using ::wifi_usable_channel; +using ::WIFI_USABLE_CHANNEL_FILTER_CELLULAR_COEXISTENCE; +using ::WIFI_USABLE_CHANNEL_FILTER_CONCURRENCY; +using ::WLAN_MAC_2_4_BAND; +using ::WLAN_MAC_5_0_BAND; +using ::WLAN_MAC_60_0_BAND; +using ::WLAN_MAC_6_0_BAND; // APF capabilities supported by the iface. struct PacketFilterCapabilities { @@ -323,9 +340,15 @@ struct LinkLayerRadioStats { std::vector channel_stats; }; +struct WifiPeerInfo { + wifi_peer_info peer_info; + std::vector rate_stats; +}; + struct LinkLayerStats { wifi_iface_stat iface; std::vector radios; + std::vector peers; }; #pragma GCC diagnostic pop @@ -401,6 +424,9 @@ using on_ring_buffer_data_callback = using on_error_alert_callback = std::function&)>; +// Callback for subsystem restart +using on_subsystem_restart_callback = std::function; + // Struct for the mac info from the legacy HAL. This is a cleaner version // of the |wifi_mac_info| & |wifi_iface_info|. typedef struct { @@ -420,6 +446,18 @@ typedef struct { using on_radio_mode_change_callback = std::function&)>; +// TWT response and event callbacks struct. +struct TwtCallbackHandlers { + // Callback for TWT setup response + std::function on_setup_response; + // Callback for TWT teardown completion + std::function on_teardown_completion; + // Callback for TWT info frame received event + std::function on_info_frame_received; + // Callback for TWT notification from the device + std::function on_device_notify; +}; + /** * Class that encapsulates all legacy HAL interactions. * This class manages the lifetime of the event loop thread used by legacy HAL. @@ -429,7 +467,8 @@ using on_radio_mode_change_callback = */ class WifiLegacyHal { public: - WifiLegacyHal(const std::weak_ptr iface_tool); + WifiLegacyHal(const std::weak_ptr iface_tool, + const wifi_hal_fn& fn, bool is_primary); virtual ~WifiLegacyHal() = default; // Initialize the legacy HAL function table. @@ -440,6 +479,7 @@ class WifiLegacyHal { // using a predefined timeout. virtual wifi_error stop(std::unique_lock* lock, const std::function& on_complete_callback); + virtual wifi_error waitForDriverReady(); // Checks if legacy HAL has successfully started bool isStarted(); // Wrappers for all the functions in the legacy HAL function table. @@ -451,7 +491,7 @@ class WifiLegacyHal { const std::string& iface_name); std::pair> requestFirmwareMemoryDump( const std::string& iface_name); - std::pair getSupportedFeatureSet( + std::pair getSupportedFeatureSet( const std::string& iface_name); // APF functions. std::pair getPacketFilterCapabilities( @@ -536,6 +576,8 @@ class WifiLegacyHal { const on_ring_buffer_data_callback& on_data_callback); wifi_error deregisterRingBufferCallbackHandler( const std::string& iface_name); + wifi_error registerSubsystemRestartCallbackHandler( + const on_subsystem_restart_callback& on_restart_callback); std::pair> getRingBuffersStatus(const std::string& iface_name); wifi_error startRingBufferLogging(const std::string& iface_name, @@ -633,6 +675,48 @@ class WifiLegacyHal { virtual wifi_error createVirtualInterface(const std::string& ifname, wifi_interface_type iftype); virtual wifi_error deleteVirtualInterface(const std::string& ifname); + wifi_error getSupportedIfaceName(uint32_t iface_type, std::string& ifname); + + // STA + STA functions + virtual wifi_error multiStaSetPrimaryConnection(const std::string& ifname); + virtual wifi_error multiStaSetUseCase(wifi_multi_sta_use_case use_case); + + // Coex functions. + virtual wifi_error setCoexUnsafeChannels( + std::vector unsafe_channels, + uint32_t restrictions); + + wifi_error setVoipMode(const std::string& iface_name, wifi_voip_mode mode); + + wifi_error twtRegisterHandler(const std::string& iface_name, + const TwtCallbackHandlers& handler); + + std::pair twtGetCapability( + const std::string& iface_name); + + wifi_error twtSetupRequest(const std::string& iface_name, + const TwtSetupRequest& msg); + + wifi_error twtTearDownRequest(const std::string& iface_name, + const TwtTeardownRequest& msg); + + wifi_error twtInfoFrameRequest(const std::string& iface_name, + const TwtInfoFrameRequest& msg); + + std::pair twtGetStats(const std::string& iface_name, + uint8_t configId); + + wifi_error twtClearStats(const std::string& iface_name, uint8_t configId); + + wifi_error setDtimConfig(const std::string& iface_name, + uint32_t multiplier); + + // Retrieve the list of usable channels in the requested bands + // for the requested modes + std::pair> getUsableChannels( + uint32_t band_mask, uint32_t iface_mode_mask, uint32_t filter_mask); + + wifi_error triggerSubsystemRestart(); private: // Retrieve interface handles for all the available interfaces. @@ -662,11 +746,16 @@ class WifiLegacyHal { // Flag to indicate if the legacy HAL has been started. bool is_started_; std::weak_ptr iface_tool_; + // flag to indicate if this HAL is for the primary chip. This is used + // in order to avoid some hard-coded behavior used with older HALs, + // such as bring wlan0 interface up/down on start/stop HAL. + // it may be removed once vendor HALs are updated. + bool is_primary_; }; } // namespace legacy_hal } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.5/default/wifi_legacy_hal_factory.cpp b/wifi/1.5/default/wifi_legacy_hal_factory.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fbaa284f56c0c52f10b54c2c5a8bb5670c56b04d --- /dev/null +++ b/wifi/1.5/default/wifi_legacy_hal_factory.cpp @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "wifi_legacy_hal_factory.h" +#include "wifi_legacy_hal_stubs.h" + +namespace { +static constexpr char kVendorHalsDescPath[] = "/vendor/etc/wifi/vendor_hals"; +static constexpr char kVendorHalsDescExt[] = ".xml"; +static constexpr uint32_t kVendorHalsDescVersion = 1; + +bool isDirectory(struct dirent* entryPtr) { + bool isDir = false; + if (entryPtr->d_type != DT_UNKNOWN && entryPtr->d_type != DT_LNK) { + isDir = (entryPtr->d_type == DT_DIR); + } else { + struct stat entryStat; + stat(entryPtr->d_name, &entryStat); + isDir = S_ISDIR(entryStat.st_mode); + } + return isDir; +} + +bool isFileExtension(const char* name, const char* ext) { + if (name == NULL) return false; + if (ext == NULL) return false; + + size_t extLen = strlen(ext); + size_t nameLen = strlen(name); + + if (extLen > nameLen) return false; + + if (strncmp(name + nameLen - extLen, ext, extLen) != 0) return false; + + return true; +} +}; // namespace + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_5 { +namespace implementation { +namespace legacy_hal { + +WifiLegacyHalFactory::WifiLegacyHalFactory( + const std::weak_ptr iface_tool) + : iface_tool_(iface_tool) {} + +std::vector> WifiLegacyHalFactory::getHals() { + if (legacy_hals_.empty()) { + if (!initVendorHalDescriptorFromLinked()) + initVendorHalsDescriptorList(); + for (auto& desc : descs_) { + std::shared_ptr hal = + std::make_shared(iface_tool_, desc.fn, + desc.primary); + legacy_hals_.push_back(hal); + } + } + + return legacy_hals_; +} + +bool WifiLegacyHalFactory::initVendorHalDescriptorFromLinked() { + wifi_hal_lib_desc desc; + + if (!initLinkedHalFunctionTable(&desc.fn)) return false; + + desc.primary = true; + desc.handle = NULL; + descs_.push_back(desc); + return true; +} + +bool WifiLegacyHalFactory::initLinkedHalFunctionTable(wifi_hal_fn* hal_fn) { + init_wifi_vendor_hal_func_table_t initfn; + + initfn = (init_wifi_vendor_hal_func_table_t)dlsym( + RTLD_DEFAULT, "init_wifi_vendor_hal_func_table"); + if (!initfn) { + LOG(INFO) << "no vendor HAL library linked, will try dynamic load"; + return false; + } + + if (!initHalFuncTableWithStubs(hal_fn)) { + LOG(ERROR) << "Can not initialize the basic function pointer table"; + return false; + } + + if (initfn(hal_fn) != WIFI_SUCCESS) { + LOG(ERROR) << "Can not initialize the vendor function pointer table"; + return false; + } + + return true; +} + +/* + * Overall structure of the HAL descriptor XML schema + * + * + * + * /vendor/lib64/libwifi-hal-qcom.so + * 1 + * + */ +void WifiLegacyHalFactory::initVendorHalsDescriptorList() { + xmlDocPtr xml; + xmlNodePtr node, cnode; + char* version; + std::string path; + xmlChar* value; + wifi_hal_lib_desc desc; + + LOG(INFO) << "processing vendor HALs descriptions in " + << kVendorHalsDescPath; + DIR* dirPtr = ::opendir(kVendorHalsDescPath); + if (dirPtr == NULL) { + LOG(ERROR) << "failed to open " << kVendorHalsDescPath; + return; + } + for (struct dirent* entryPtr = ::readdir(dirPtr); entryPtr != NULL; + entryPtr = ::readdir(dirPtr)) { + if (isDirectory(entryPtr)) continue; + + if (!isFileExtension(entryPtr->d_name, kVendorHalsDescExt)) + continue; // only process .xml files + + LOG(INFO) << "processing config file: " << entryPtr->d_name; + + std::string fullPath(kVendorHalsDescPath); + fullPath.append("/"); + fullPath.append(entryPtr->d_name); + xml = xmlReadFile(fullPath.c_str(), "UTF-8", XML_PARSE_RECOVER); + if (!xml) { + LOG(ERROR) << "failed to parse: " << entryPtr->d_name + << " skipping..."; + continue; + } + node = xmlDocGetRootElement(xml); + if (!node) { + LOG(ERROR) << "empty config file: " << entryPtr->d_name + << " skipping..."; + goto skip; + } + if (xmlStrcmp(node->name, BAD_CAST "WifiVendorHal")) { + LOG(ERROR) << "bad config, root element not WifiVendorHal: " + << entryPtr->d_name << " skipping..."; + goto skip; + } + version = (char*)xmlGetProp(node, BAD_CAST "version"); + if (!version || strtoul(version, NULL, 0) != kVendorHalsDescVersion) { + LOG(ERROR) << "conf file: " << entryPtr->d_name + << "must have version: " << kVendorHalsDescVersion + << ", skipping..."; + goto skip; + } + cnode = node->children; + path.clear(); + desc.primary = false; + while (cnode) { + if (!xmlStrcmp(cnode->name, BAD_CAST "path")) { + value = xmlNodeListGetString(xml, cnode->children, 1); + if (value) path = (char*)value; + xmlFree(value); + } else if (!xmlStrcmp(cnode->name, BAD_CAST "primary")) { + value = xmlNodeListGetString(xml, cnode->children, 1); + desc.primary = !xmlStrcmp(value, BAD_CAST "1"); + xmlFree(value); + } + cnode = cnode->next; + } + if (path.empty()) { + LOG(ERROR) << "hal library path not provided in: " + << entryPtr->d_name << ", skipping..."; + goto skip; + } + if (loadVendorHalLib(path, desc)) { + if (desc.primary) + descs_.insert(descs_.begin(), desc); + else + descs_.push_back(desc); + } + skip: + xmlFreeDoc(xml); + } + ::closedir(dirPtr); +} + +bool WifiLegacyHalFactory::loadVendorHalLib(const std::string& path, + wifi_hal_lib_desc& desc) { + void* h = dlopen(path.c_str(), RTLD_NOW | RTLD_LOCAL); + init_wifi_vendor_hal_func_table_t initfn; + wifi_error res; + + if (!h) { + LOG(ERROR) << "failed to open vendor hal library: " << path; + return false; + } + initfn = (init_wifi_vendor_hal_func_table_t)dlsym( + h, "init_wifi_vendor_hal_func_table"); + if (!initfn) { + LOG(ERROR) << "init_wifi_vendor_hal_func_table not found in: " << path; + goto out_err; + } + + if (!initHalFuncTableWithStubs(&desc.fn)) { + LOG(ERROR) << "Can not initialize the basic function pointer table"; + goto out_err; + } + res = initfn(&desc.fn); + if (res != WIFI_SUCCESS) { + LOG(ERROR) << "failed to initialize the vendor func table in: " << path + << " error: " << res; + goto out_err; + } + + res = desc.fn.wifi_early_initialize(); + // vendor HALs which do not implement early_initialize will return + // WIFI_ERROR_NOT_SUPPORTED, treat this as success. + if (res != WIFI_SUCCESS && res != WIFI_ERROR_NOT_SUPPORTED) { + LOG(ERROR) << "early initialization failed in: " << path + << " error: " << res; + goto out_err; + } + + desc.handle = h; + return true; +out_err: + dlclose(h); + return false; +} + +} // namespace legacy_hal +} // namespace implementation +} // namespace V1_5 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.5/default/wifi_legacy_hal_factory.h b/wifi/1.5/default/wifi_legacy_hal_factory.h new file mode 100644 index 0000000000000000000000000000000000000000..e3440faff29b4aa776f665b7c670185d94a2fb13 --- /dev/null +++ b/wifi/1.5/default/wifi_legacy_hal_factory.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WIFI_LEGACY_HAL_FACTORY_H_ +#define WIFI_LEGACY_HAL_FACTORY_H_ + +#include + +#include "wifi_legacy_hal.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_5 { +namespace implementation { +// This is in a separate namespace to prevent typename conflicts between +// the legacy HAL types and the HIDL interface types. +namespace legacy_hal { +/** + * Class that creates WifiLegacyHal objects for vendor HALs in the system. + */ +class WifiLegacyHalFactory { + public: + WifiLegacyHalFactory( + const std::weak_ptr iface_tool); + virtual ~WifiLegacyHalFactory() = default; + + std::vector> getHals(); + + private: + typedef struct { + wifi_hal_fn fn; + bool primary; + void* handle; + } wifi_hal_lib_desc; + + bool initVendorHalDescriptorFromLinked(); + void initVendorHalsDescriptorList(); + bool initLinkedHalFunctionTable(wifi_hal_fn* hal_fn); + bool loadVendorHalLib(const std::string& path, wifi_hal_lib_desc& desc); + + std::weak_ptr iface_tool_; + std::vector descs_; + std::vector> legacy_hals_; +}; + +} // namespace legacy_hal +} // namespace implementation +} // namespace V1_5 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_LEGACY_HAL_FACTORY_H_ diff --git a/wifi/1.4/default/wifi_legacy_hal_stubs.cpp b/wifi/1.5/default/wifi_legacy_hal_stubs.cpp similarity index 86% rename from wifi/1.4/default/wifi_legacy_hal_stubs.cpp rename to wifi/1.5/default/wifi_legacy_hal_stubs.cpp index 153a68520f3ac37d91f5fd010cb27f0b8df79b1c..dd860d69200b13be98d7b2f1dcddd5397604b6c2 100644 --- a/wifi/1.4/default/wifi_legacy_hal_stubs.cpp +++ b/wifi/1.5/default/wifi_legacy_hal_stubs.cpp @@ -20,7 +20,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { namespace legacy_hal { template @@ -143,11 +143,29 @@ bool initHalFuncTableWithStubs(wifi_hal_fn* hal_fn) { populateStubFor(&hal_fn->wifi_virtual_interface_delete); populateStubFor(&hal_fn->wifi_map_dscp_access_category); populateStubFor(&hal_fn->wifi_reset_dscp_mapping); + populateStubFor(&hal_fn->wifi_set_subsystem_restart_handler); + populateStubFor(&hal_fn->wifi_get_supported_iface_name); + populateStubFor(&hal_fn->wifi_early_initialize); + populateStubFor(&hal_fn->wifi_get_chip_feature_set); + populateStubFor(&hal_fn->wifi_multi_sta_set_primary_connection); + populateStubFor(&hal_fn->wifi_multi_sta_set_use_case); + populateStubFor(&hal_fn->wifi_set_coex_unsafe_channels); + populateStubFor(&hal_fn->wifi_set_voip_mode); + populateStubFor(&hal_fn->wifi_twt_register_handler); + populateStubFor(&hal_fn->wifi_twt_get_capability); + populateStubFor(&hal_fn->wifi_twt_setup_request); + populateStubFor(&hal_fn->wifi_twt_teardown_request); + populateStubFor(&hal_fn->wifi_twt_info_frame_request); + populateStubFor(&hal_fn->wifi_twt_get_stats); + populateStubFor(&hal_fn->wifi_twt_clear_stats); + populateStubFor(&hal_fn->wifi_set_dtim_config); + populateStubFor(&hal_fn->wifi_get_usable_channels); + populateStubFor(&hal_fn->wifi_trigger_subsystem_restart); return true; } } // namespace legacy_hal } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/wifi_legacy_hal_stubs.h b/wifi/1.5/default/wifi_legacy_hal_stubs.h similarity index 96% rename from wifi/1.4/default/wifi_legacy_hal_stubs.h rename to wifi/1.5/default/wifi_legacy_hal_stubs.h index c709680f4fbacb3a5f0ce736f33c77d2ad4b6d0e..480389b0cecc5d287ecb748e37c49923147d0b4e 100644 --- a/wifi/1.4/default/wifi_legacy_hal_stubs.h +++ b/wifi/1.5/default/wifi_legacy_hal_stubs.h @@ -22,14 +22,14 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { namespace legacy_hal { bool initHalFuncTableWithStubs(wifi_hal_fn* hal_fn); } // namespace legacy_hal } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/wifi_mode_controller.cpp b/wifi/1.5/default/wifi_mode_controller.cpp similarity index 98% rename from wifi/1.4/default/wifi_mode_controller.cpp rename to wifi/1.5/default/wifi_mode_controller.cpp index 252121a5b434eee4a41ca93f435ded9d7250041d..b1db8b37250cb052cdcbe8e83cfcb121c596afa1 100644 --- a/wifi/1.4/default/wifi_mode_controller.cpp +++ b/wifi/1.5/default/wifi_mode_controller.cpp @@ -48,7 +48,7 @@ int convertIfaceTypeToFirmwareMode(IfaceType type) { namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { namespace mode_controller { @@ -85,7 +85,7 @@ bool WifiModeController::deinitialize() { } } // namespace mode_controller } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/wifi_mode_controller.h b/wifi/1.5/default/wifi_mode_controller.h similarity index 98% rename from wifi/1.4/default/wifi_mode_controller.h rename to wifi/1.5/default/wifi_mode_controller.h index 45fa999b2abfb0f87258a4d869e9c4301f66dac3..2eeca78c8b97b116d91b0f0513032deb7a653794 100644 --- a/wifi/1.4/default/wifi_mode_controller.h +++ b/wifi/1.5/default/wifi_mode_controller.h @@ -24,7 +24,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { namespace mode_controller { using namespace android::hardware::wifi::V1_0; @@ -55,7 +55,7 @@ class WifiModeController { } // namespace mode_controller } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/wifi_nan_iface.cpp b/wifi/1.5/default/wifi_nan_iface.cpp similarity index 91% rename from wifi/1.4/default/wifi_nan_iface.cpp rename to wifi/1.5/default/wifi_nan_iface.cpp index 24ffb176e86d20d0b547e3997c84b7496cfd69ad..0cc6cd5fce1c1463437b9b393490f6cf6b15c509 100644 --- a/wifi/1.4/default/wifi_nan_iface.cpp +++ b/wifi/1.5/default/wifi_nan_iface.cpp @@ -24,7 +24,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { using hidl_return_util::validateAndCall; @@ -166,10 +166,10 @@ WifiNanIface::WifiNanIface( return; } for (const auto& callback : - shared_ptr_this->getEventCallbacks()) { + shared_ptr_this->getEventCallbacks_1_5()) { if (!callback - ->notifyCapabilitiesResponse(id, wifiNanStatus, - hidl_struct) + ->notifyCapabilitiesResponse_1_5(id, wifiNanStatus, + hidl_struct) .isOk()) { LOG(ERROR) << "Failed to invoke the callback"; } @@ -545,6 +545,7 @@ void WifiNanIface::invalidate() { legacy_hal_.reset(); event_cb_handler_.invalidate(); event_cb_handler_1_2_.invalidate(); + event_cb_handler_1_5_.invalidate(); is_valid_ = false; if (is_dedicated_iface_) { // If using a dedicated iface, set the iface down. @@ -566,6 +567,10 @@ WifiNanIface::getEventCallbacks_1_2() { return event_cb_handler_1_2_.getCallbacks(); } +std::set> WifiNanIface::getEventCallbacks_1_5() { + return event_cb_handler_1_5_.getCallbacks(); +} + Return WifiNanIface::getName(getName_cb hidl_status_cb) { return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, &WifiNanIface::getNameInternal, hidl_status_cb); @@ -721,7 +726,7 @@ Return WifiNanIface::configRequest_1_2( } Return WifiNanIface::enableRequest_1_4( - uint16_t cmd_id, const NanEnableRequest& msg1, + uint16_t cmd_id, const V1_4::NanEnableRequest& msg1, const V1_2::NanConfigRequestSupplemental& msg2, enableRequest_1_4_cb hidl_status_cb) { return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, @@ -730,7 +735,7 @@ Return WifiNanIface::enableRequest_1_4( } Return WifiNanIface::configRequest_1_4( - uint16_t cmd_id, const NanConfigRequest& msg1, + uint16_t cmd_id, const V1_4::NanConfigRequest& msg1, const V1_2::NanConfigRequestSupplemental& msg2, configRequest_1_4_cb hidl_status_cb) { return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, @@ -738,6 +743,39 @@ Return WifiNanIface::configRequest_1_4( hidl_status_cb, cmd_id, msg1, msg2); } +Return WifiNanIface::registerEventCallback_1_5( + const sp& callback, + registerEventCallback_1_5_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::registerEventCallback_1_5Internal, + hidl_status_cb, callback); +} + +Return WifiNanIface::enableRequest_1_5( + uint16_t cmd_id, const V1_4::NanEnableRequest& msg1, + const NanConfigRequestSupplemental& msg2, + enableRequest_1_5_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::enableRequest_1_5Internal, + hidl_status_cb, cmd_id, msg1, msg2); +} + +Return WifiNanIface::configRequest_1_5( + uint16_t cmd_id, const V1_4::NanConfigRequest& msg1, + const NanConfigRequestSupplemental& msg2, + configRequest_1_5_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::configRequest_1_5Internal, + hidl_status_cb, cmd_id, msg1, msg2); +} + +Return WifiNanIface::getCapabilitiesRequest_1_5( + uint16_t cmd_id, getCapabilitiesRequest_1_5_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::getCapabilitiesRequest_1_5Internal, + hidl_status_cb, cmd_id); +} + std::pair WifiNanIface::getNameInternal() { return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_}; } @@ -754,10 +792,8 @@ WifiStatus WifiNanIface::registerEventCallbackInternal( return createWifiStatus(WifiStatusCode::SUCCESS); } -WifiStatus WifiNanIface::getCapabilitiesRequestInternal(uint16_t cmd_id) { - legacy_hal::wifi_error legacy_status = - legacy_hal_.lock()->nanGetCapabilities(ifname_, cmd_id); - return createWifiStatusFromLegacyError(legacy_status); +WifiStatus WifiNanIface::getCapabilitiesRequestInternal(uint16_t /* cmd_id */) { + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); } WifiStatus WifiNanIface::enableRequestInternal( @@ -890,7 +926,7 @@ WifiStatus WifiNanIface::registerEventCallback_1_2Internal( WifiStatus WifiNanIface::enableRequest_1_2Internal( uint16_t /* cmd_id */, const V1_0::NanEnableRequest& /* msg1 */, - const V1_2::NanConfigRequestSupplemental& /*msg2 */) { + const V1_2::NanConfigRequestSupplemental& /* msg2 */) { return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); } @@ -901,10 +937,44 @@ WifiStatus WifiNanIface::configRequest_1_2Internal( } WifiStatus WifiNanIface::enableRequest_1_4Internal( - uint16_t cmd_id, const NanEnableRequest& msg1, - const V1_2::NanConfigRequestSupplemental& msg2) { + uint16_t /* cmd_id */, const V1_4::NanEnableRequest& /* msg1 */, + const V1_2::NanConfigRequestSupplemental& /* msg2 */) { + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiNanIface::configRequest_1_4Internal( + uint16_t /* cmd_id */, const V1_4::NanConfigRequest& /* msg1 */, + const V1_2::NanConfigRequestSupplemental& /* msg2 */) { + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiNanIface::registerEventCallback_1_5Internal( + const sp& callback) { + sp callback_1_0 = callback; + if (!event_cb_handler_.addCallback(callback_1_0)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + sp callback_1_2 = callback; + if (!event_cb_handler_1_2_.addCallback(callback_1_2)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + if (!event_cb_handler_1_5_.addCallback(callback)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +WifiStatus WifiNanIface::getCapabilitiesRequest_1_5Internal(uint16_t cmd_id) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanGetCapabilities(ifname_, cmd_id); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::enableRequest_1_5Internal( + uint16_t cmd_id, const V1_4::NanEnableRequest& msg1, + const NanConfigRequestSupplemental& msg2) { legacy_hal::NanEnableRequest legacy_msg; - if (!hidl_struct_util::convertHidlNanEnableRequest_1_4ToLegacy( + if (!hidl_struct_util::convertHidlNanEnableRequest_1_5ToLegacy( msg1, msg2, &legacy_msg)) { return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); } @@ -913,11 +983,11 @@ WifiStatus WifiNanIface::enableRequest_1_4Internal( return createWifiStatusFromLegacyError(legacy_status); } -WifiStatus WifiNanIface::configRequest_1_4Internal( - uint16_t cmd_id, const NanConfigRequest& msg1, - const V1_2::NanConfigRequestSupplemental& msg2) { +WifiStatus WifiNanIface::configRequest_1_5Internal( + uint16_t cmd_id, const V1_4::NanConfigRequest& msg1, + const NanConfigRequestSupplemental& msg2) { legacy_hal::NanConfigRequest legacy_msg; - if (!hidl_struct_util::convertHidlNanConfigRequest_1_4ToLegacy( + if (!hidl_struct_util::convertHidlNanConfigRequest_1_5ToLegacy( msg1, msg2, &legacy_msg)) { return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); } @@ -927,7 +997,7 @@ WifiStatus WifiNanIface::configRequest_1_4Internal( } } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/wifi_nan_iface.h b/wifi/1.5/default/wifi_nan_iface.h similarity index 80% rename from wifi/1.4/default/wifi_nan_iface.h rename to wifi/1.5/default/wifi_nan_iface.h index 06edbf260946d025a428345c15b8beffb7b04d23..fb9c047ff640d27e8bbd55869e454a2ca7a8f429 100644 --- a/wifi/1.4/default/wifi_nan_iface.h +++ b/wifi/1.5/default/wifi_nan_iface.h @@ -18,8 +18,8 @@ #define WIFI_NAN_IFACE_H_ #include -#include -#include +#include +#include #include "hidl_callback_util.h" #include "wifi_iface_util.h" @@ -28,7 +28,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { using namespace android::hardware::wifi::V1_0; using namespace android::hardware::wifi::V1_2; @@ -36,7 +36,7 @@ using namespace android::hardware::wifi::V1_2; /** * HIDL interface object used to control a NAN Iface instance. */ -class WifiNanIface : public V1_4::IWifiNanIface { +class WifiNanIface : public V1_5::IWifiNanIface { public: WifiNanIface(const std::string& ifname, bool is_dedicated_iface, const std::weak_ptr legacy_hal, @@ -105,13 +105,26 @@ class WifiNanIface : public V1_4::IWifiNanIface { const V1_2::NanConfigRequestSupplemental& msg2, configRequest_1_2_cb hidl_status_cb) override; Return enableRequest_1_4( - uint16_t cmd_id, const NanEnableRequest& msg1, + uint16_t cmd_id, const V1_4::NanEnableRequest& msg1, const V1_2::NanConfigRequestSupplemental& msg2, - enableRequest_1_2_cb hidl_status_cb) override; + enableRequest_1_4_cb hidl_status_cb) override; Return configRequest_1_4( - uint16_t cmd_id, const NanConfigRequest& msg1, + uint16_t cmd_id, const V1_4::NanConfigRequest& msg1, const V1_2::NanConfigRequestSupplemental& msg2, - configRequest_1_2_cb hidl_status_cb) override; + configRequest_1_4_cb hidl_status_cb) override; + Return registerEventCallback_1_5( + const sp& callback, + registerEventCallback_1_5_cb hidl_status_cb) override; + Return enableRequest_1_5( + uint16_t cmd_id, const V1_4::NanEnableRequest& msg1, + const NanConfigRequestSupplemental& msg2, + enableRequest_1_4_cb hidl_status_cb) override; + Return configRequest_1_5( + uint16_t cmd_id, const V1_4::NanConfigRequest& msg1, + const NanConfigRequestSupplemental& msg2, + configRequest_1_4_cb hidl_status_cb) override; + Return getCapabilitiesRequest_1_5( + uint16_t cmd_id, getCapabilitiesRequest_cb hidl_status_cb) override; private: // Corresponding worker functions for the HIDL methods. @@ -153,16 +166,27 @@ class WifiNanIface : public V1_4::IWifiNanIface { uint16_t cmd_id, const V1_0::NanConfigRequest& msg, const V1_2::NanConfigRequestSupplemental& msg2); WifiStatus enableRequest_1_4Internal( - uint16_t cmd_id, const NanEnableRequest& msg1, + uint16_t cmd_id, const V1_4::NanEnableRequest& msg1, const V1_2::NanConfigRequestSupplemental& msg2); WifiStatus configRequest_1_4Internal( - uint16_t cmd_id, const NanConfigRequest& msg, + uint16_t cmd_id, const V1_4::NanConfigRequest& msg, const V1_2::NanConfigRequestSupplemental& msg2); + WifiStatus registerEventCallback_1_5Internal( + const sp& callback); + WifiStatus enableRequest_1_5Internal( + uint16_t cmd_id, const V1_4::NanEnableRequest& msg1, + const NanConfigRequestSupplemental& msg2); + WifiStatus configRequest_1_5Internal( + uint16_t cmd_id, const V1_4::NanConfigRequest& msg, + const NanConfigRequestSupplemental& msg2); + WifiStatus getCapabilitiesRequest_1_5Internal(uint16_t cmd_id); // all 1_0 and descendant callbacks std::set> getEventCallbacks(); // all 1_2 and descendant callbacks std::set> getEventCallbacks_1_2(); + // all 1_5 and descendant callbacks + std::set> getEventCallbacks_1_5(); std::string ifname_; bool is_dedicated_iface_; @@ -173,12 +197,14 @@ class WifiNanIface : public V1_4::IWifiNanIface { event_cb_handler_; hidl_callback_util::HidlCallbackHandler event_cb_handler_1_2_; + hidl_callback_util::HidlCallbackHandler + event_cb_handler_1_5_; DISALLOW_COPY_AND_ASSIGN(WifiNanIface); }; } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/wifi_p2p_iface.cpp b/wifi/1.5/default/wifi_p2p_iface.cpp similarity index 98% rename from wifi/1.4/default/wifi_p2p_iface.cpp rename to wifi/1.5/default/wifi_p2p_iface.cpp index 9e7341f248cebc79e1852c18feb9754a8c46b091..b8893da153548062877f69400d77c67db3f64067 100644 --- a/wifi/1.4/default/wifi_p2p_iface.cpp +++ b/wifi/1.5/default/wifi_p2p_iface.cpp @@ -23,7 +23,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { using hidl_return_util::validateAndCall; @@ -60,7 +60,7 @@ std::pair WifiP2pIface::getTypeInternal() { } } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/wifi_p2p_iface.h b/wifi/1.5/default/wifi_p2p_iface.h similarity index 98% rename from wifi/1.4/default/wifi_p2p_iface.h rename to wifi/1.5/default/wifi_p2p_iface.h index a6fc59d04b52cb787cc4e8d2ce12025a2e178794..c1adc502789ee399dfa9242f7bc0a140d9575dd6 100644 --- a/wifi/1.4/default/wifi_p2p_iface.h +++ b/wifi/1.5/default/wifi_p2p_iface.h @@ -25,7 +25,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { using namespace android::hardware::wifi::V1_0; @@ -58,7 +58,7 @@ class WifiP2pIface : public V1_0::IWifiP2pIface { }; } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/wifi_rtt_controller.cpp b/wifi/1.5/default/wifi_rtt_controller.cpp similarity index 95% rename from wifi/1.4/default/wifi_rtt_controller.cpp rename to wifi/1.5/default/wifi_rtt_controller.cpp index 594a11660f7dc71b46e47747a04797e905445637..a0f9969033addc30668284d4d3b361db4249935c 100644 --- a/wifi/1.4/default/wifi_rtt_controller.cpp +++ b/wifi/1.5/default/wifi_rtt_controller.cpp @@ -24,7 +24,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { using hidl_return_util::validateAndCall; @@ -44,7 +44,7 @@ void WifiRttController::invalidate() { bool WifiRttController::isValid() { return is_valid_; } -std::vector> +std::vector> WifiRttController::getEventCallbacks() { return event_callbacks_; } @@ -131,7 +131,7 @@ Return WifiRttController::disableResponder( } Return WifiRttController::registerEventCallback_1_4( - const sp& callback, + const sp& callback, registerEventCallback_1_4_cb hidl_status_cb) { return validateAndCall( this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, @@ -140,7 +140,7 @@ Return WifiRttController::registerEventCallback_1_4( } Return WifiRttController::rangeRequest_1_4( - uint32_t cmd_id, const hidl_vec& rtt_configs, + uint32_t cmd_id, const hidl_vec& rtt_configs, rangeRequest_1_4_cb hidl_status_cb) { return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, @@ -164,7 +164,7 @@ Return WifiRttController::getResponderInfo_1_4( Return WifiRttController::enableResponder_1_4( uint32_t cmd_id, const WifiChannelInfo& channel_hint, - uint32_t max_duration_seconds, const RttResponder& info, + uint32_t max_duration_seconds, const V1_4::RttResponder& info, enableResponder_1_4_cb hidl_status_cb) { return validateAndCall( this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, @@ -252,14 +252,14 @@ WifiStatus WifiRttController::disableResponderInternal(uint32_t cmd_id) { } WifiStatus WifiRttController::registerEventCallbackInternal_1_4( - const sp& callback) { + const sp& callback) { // TODO(b/31632518): remove the callback when the client is destroyed event_callbacks_.emplace_back(callback); return createWifiStatus(WifiStatusCode::SUCCESS); } WifiStatus WifiRttController::rangeRequestInternal_1_4( - uint32_t cmd_id, const std::vector& rtt_configs) { + uint32_t cmd_id, const std::vector& rtt_configs) { std::vector legacy_configs; if (!hidl_struct_util::convertHidlVectorOfRttConfigToLegacy( rtt_configs, &legacy_configs)) { @@ -275,7 +275,7 @@ WifiStatus WifiRttController::rangeRequestInternal_1_4( LOG(ERROR) << "Callback invoked on an invalid object"; return; } - std::vector hidl_results; + std::vector hidl_results; if (!hidl_struct_util::convertLegacyVectorOfRttResultToHidl( results, &hidl_results)) { LOG(ERROR) << "Failed to convert rtt results to HIDL structs"; @@ -291,7 +291,7 @@ WifiStatus WifiRttController::rangeRequestInternal_1_4( return createWifiStatusFromLegacyError(legacy_status); } -std::pair +std::pair WifiRttController::getCapabilitiesInternal_1_4() { legacy_hal::wifi_error legacy_status; legacy_hal::wifi_rtt_capabilities legacy_caps; @@ -300,7 +300,7 @@ WifiRttController::getCapabilitiesInternal_1_4() { if (legacy_status != legacy_hal::WIFI_SUCCESS) { return {createWifiStatusFromLegacyError(legacy_status), {}}; } - RttCapabilities hidl_caps; + V1_4::RttCapabilities hidl_caps; if (!hidl_struct_util::convertLegacyRttCapabilitiesToHidl(legacy_caps, &hidl_caps)) { return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; @@ -308,7 +308,7 @@ WifiRttController::getCapabilitiesInternal_1_4() { return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps}; } -std::pair +std::pair WifiRttController::getResponderInfoInternal_1_4() { legacy_hal::wifi_error legacy_status; legacy_hal::wifi_rtt_responder legacy_responder; @@ -317,7 +317,7 @@ WifiRttController::getResponderInfoInternal_1_4() { if (legacy_status != legacy_hal::WIFI_SUCCESS) { return {createWifiStatusFromLegacyError(legacy_status), {}}; } - RttResponder hidl_responder; + V1_4::RttResponder hidl_responder; if (!hidl_struct_util::convertLegacyRttResponderToHidl(legacy_responder, &hidl_responder)) { return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; @@ -327,7 +327,7 @@ WifiRttController::getResponderInfoInternal_1_4() { WifiStatus WifiRttController::enableResponderInternal_1_4( uint32_t cmd_id, const WifiChannelInfo& channel_hint, - uint32_t max_duration_seconds, const RttResponder& info) { + uint32_t max_duration_seconds, const V1_4::RttResponder& info) { legacy_hal::wifi_channel_info legacy_channel_info; if (!hidl_struct_util::convertHidlWifiChannelInfoToLegacy( channel_hint, &legacy_channel_info)) { @@ -345,7 +345,7 @@ WifiStatus WifiRttController::enableResponderInternal_1_4( return createWifiStatusFromLegacyError(legacy_status); } } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/wifi_rtt_controller.h b/wifi/1.5/default/wifi_rtt_controller.h similarity index 87% rename from wifi/1.4/default/wifi_rtt_controller.h rename to wifi/1.5/default/wifi_rtt_controller.h index 1f125555d0e194398a85abd8f210081a6abb10da..9ac3e06fccf83ac5137fa67ff4495d887b8e9ca5 100644 --- a/wifi/1.4/default/wifi_rtt_controller.h +++ b/wifi/1.5/default/wifi_rtt_controller.h @@ -27,7 +27,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { /** @@ -41,7 +41,7 @@ class WifiRttController : public V1_4::IWifiRttController { // Refer to |WifiChip::invalidate()|. void invalidate(); bool isValid(); - std::vector> getEventCallbacks(); + std::vector> getEventCallbacks(); std::string getIfaceName(); // HIDL methods exposed. @@ -69,10 +69,10 @@ class WifiRttController : public V1_4::IWifiRttController { Return disableResponder(uint32_t cmd_id, disableResponder_cb hidl_status_cb) override; Return registerEventCallback_1_4( - const sp& callback, + const sp& callback, registerEventCallback_1_4_cb hidl_status_cb) override; Return rangeRequest_1_4(uint32_t cmd_id, - const hidl_vec& rtt_configs, + const hidl_vec& rtt_configs, rangeRequest_1_4_cb hidl_status_cb) override; Return getCapabilities_1_4( getCapabilities_1_4_cb hidl_status_cb) override; @@ -80,7 +80,7 @@ class WifiRttController : public V1_4::IWifiRttController { getResponderInfo_1_4_cb hidl_status_cb) override; Return enableResponder_1_4( uint32_t cmd_id, const WifiChannelInfo& channel_hint, - uint32_t max_duration_seconds, const RttResponder& info, + uint32_t max_duration_seconds, const V1_4::RttResponder& info, enableResponder_1_4_cb hidl_status_cb) override; private: @@ -102,27 +102,27 @@ class WifiRttController : public V1_4::IWifiRttController { const V1_0::RttResponder& info); WifiStatus disableResponderInternal(uint32_t cmd_id); WifiStatus registerEventCallbackInternal_1_4( - const sp& callback); + const sp& callback); WifiStatus rangeRequestInternal_1_4( - uint32_t cmd_id, const std::vector& rtt_configs); - std::pair getCapabilitiesInternal_1_4(); - std::pair getResponderInfoInternal_1_4(); + uint32_t cmd_id, const std::vector& rtt_configs); + std::pair getCapabilitiesInternal_1_4(); + std::pair getResponderInfoInternal_1_4(); WifiStatus enableResponderInternal_1_4(uint32_t cmd_id, const WifiChannelInfo& channel_hint, uint32_t max_duration_seconds, - const RttResponder& info); + const V1_4::RttResponder& info); std::string ifname_; sp bound_iface_; std::weak_ptr legacy_hal_; - std::vector> event_callbacks_; + std::vector> event_callbacks_; bool is_valid_; DISALLOW_COPY_AND_ASSIGN(WifiRttController); }; } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/wifi_sta_iface.cpp b/wifi/1.5/default/wifi_sta_iface.cpp similarity index 96% rename from wifi/1.4/default/wifi_sta_iface.cpp rename to wifi/1.5/default/wifi_sta_iface.cpp index bc6701d3ecb677951265beb47fbc903cd60ef9b3..92c9fe439276371bd8c1be000f7e7f643ccc5622 100644 --- a/wifi/1.4/default/wifi_sta_iface.cpp +++ b/wifi/1.5/default/wifi_sta_iface.cpp @@ -24,7 +24,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { using hidl_return_util::validateAndCall; @@ -163,6 +163,13 @@ Return WifiStaIface::getLinkLayerStats_1_3( hidl_status_cb); } +Return WifiStaIface::getLinkLayerStats_1_5( + getLinkLayerStats_1_5_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getLinkLayerStatsInternal_1_5, + hidl_status_cb); +} + Return WifiStaIface::startRssiMonitoring( uint32_t cmd_id, int32_t max_rssi, int32_t min_rssi, startRssiMonitoring_cb hidl_status_cb) { @@ -266,6 +273,13 @@ Return WifiStaIface::getFactoryMacAddress( hidl_status_cb); } +Return WifiStaIface::setScanMode(bool enable, + setScanMode_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::setScanModeInternal, hidl_status_cb, + enable); +} + std::pair WifiStaIface::getNameInternal() { return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_}; } @@ -470,6 +484,11 @@ WifiStaIface::getLinkLayerStatsInternal() { std::pair WifiStaIface::getLinkLayerStatsInternal_1_3() { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}}; +} + +std::pair +WifiStaIface::getLinkLayerStatsInternal_1_5() { legacy_hal::wifi_error legacy_status; legacy_hal::LinkLayerStats legacy_stats; std::tie(legacy_status, legacy_stats) = @@ -477,7 +496,7 @@ WifiStaIface::getLinkLayerStatsInternal_1_3() { if (legacy_status != legacy_hal::WIFI_SUCCESS) { return {createWifiStatusFromLegacyError(legacy_status), {}}; } - V1_3::StaLinkLayerStats hidl_stats; + V1_5::StaLinkLayerStats hidl_stats; if (!hidl_struct_util::convertLegacyLinkLayerStatsToHidl(legacy_stats, &hidl_stats)) { return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; @@ -643,8 +662,14 @@ WifiStaIface::getFactoryMacAddressInternal() { return {createWifiStatus(WifiStatusCode::SUCCESS), mac}; } +WifiStatus WifiStaIface::setScanModeInternal(bool enable) { + // OEM's need to implement this on their devices if needed. + LOG(WARNING) << "setScanModeInternal(" << enable << ") not supported"; + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/wifi_sta_iface.h b/wifi/1.5/default/wifi_sta_iface.h similarity index 94% rename from wifi/1.4/default/wifi_sta_iface.h rename to wifi/1.5/default/wifi_sta_iface.h index dee04f2a69ccf6772b58a2281bd63d85a4a8e96b..f9058b8af16984a825f22bbac3abf3eb5f0b07d5 100644 --- a/wifi/1.4/default/wifi_sta_iface.h +++ b/wifi/1.5/default/wifi_sta_iface.h @@ -19,7 +19,7 @@ #include #include -#include +#include #include "hidl_callback_util.h" #include "wifi_iface_util.h" @@ -28,14 +28,14 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { using namespace android::hardware::wifi::V1_0; /** * HIDL interface object used to control a STA Iface instance. */ -class WifiStaIface : public V1_3::IWifiStaIface { +class WifiStaIface : public V1_5::IWifiStaIface { public: WifiStaIface(const std::string& ifname, const std::weak_ptr legacy_hal, @@ -78,6 +78,8 @@ class WifiStaIface : public V1_3::IWifiStaIface { getLinkLayerStats_cb hidl_status_cb) override; Return getLinkLayerStats_1_3( getLinkLayerStats_1_3_cb hidl_status_cb) override; + Return getLinkLayerStats_1_5( + getLinkLayerStats_1_5_cb hidl_status_cb) override; Return startRssiMonitoring( uint32_t cmd_id, int32_t max_rssi, int32_t min_rssi, startRssiMonitoring_cb hidl_status_cb) override; @@ -112,6 +114,8 @@ class WifiStaIface : public V1_3::IWifiStaIface { setMacAddress_cb hidl_status_cb) override; Return getFactoryMacAddress( getFactoryMacAddress_cb hidl_status_cb) override; + Return setScanMode(bool enable, + setScanMode_cb hidl_status_cb) override; private: // Corresponding worker functions for the HIDL methods. @@ -138,6 +142,8 @@ class WifiStaIface : public V1_3::IWifiStaIface { std::pair getLinkLayerStatsInternal(); std::pair getLinkLayerStatsInternal_1_3(); + std::pair + getLinkLayerStatsInternal_1_5(); WifiStatus startRssiMonitoringInternal(uint32_t cmd_id, int32_t max_rssi, int32_t min_rssi); WifiStatus stopRssiMonitoringInternal(uint32_t cmd_id); @@ -160,6 +166,7 @@ class WifiStaIface : public V1_3::IWifiStaIface { WifiStatus setMacAddressInternal(const std::array& mac); std::pair> getFactoryMacAddressInternal(); + WifiStatus setScanModeInternal(bool enable); std::string ifname_; std::weak_ptr legacy_hal_; @@ -172,7 +179,7 @@ class WifiStaIface : public V1_3::IWifiStaIface { }; } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/wifi_status_util.cpp b/wifi/1.5/default/wifi_status_util.cpp similarity index 99% rename from wifi/1.4/default/wifi_status_util.cpp rename to wifi/1.5/default/wifi_status_util.cpp index 8ceb9265f17e5ab7b5479b6d0a5ff120a5ec00e7..eb8c8694db9cc08e55d4bca6e6914a309604d34f 100644 --- a/wifi/1.4/default/wifi_status_util.cpp +++ b/wifi/1.5/default/wifi_status_util.cpp @@ -19,7 +19,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { std::string legacyErrorToString(legacy_hal::wifi_error error) { @@ -106,7 +106,7 @@ WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error) { } } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.4/default/wifi_status_util.h b/wifi/1.5/default/wifi_status_util.h similarity index 97% rename from wifi/1.4/default/wifi_status_util.h rename to wifi/1.5/default/wifi_status_util.h index 3ff58f0c0a2a1566ae6b05d75899f4593fc9eae7..68f21689c5612e156b6da87f70468eeef9f5387c 100644 --- a/wifi/1.4/default/wifi_status_util.h +++ b/wifi/1.5/default/wifi_status_util.h @@ -24,7 +24,7 @@ namespace android { namespace hardware { namespace wifi { -namespace V1_4 { +namespace V1_5 { namespace implementation { using namespace android::hardware::wifi::V1_0; @@ -37,7 +37,7 @@ WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error, WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error); } // namespace implementation -} // namespace V1_4 +} // namespace V1_5 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.5/types.hal b/wifi/1.5/types.hal new file mode 100644 index 0000000000000000000000000000000000000000..3c197916eb113cd0d996b16fa50b1cb4c89d5a00 --- /dev/null +++ b/wifi/1.5/types.hal @@ -0,0 +1,285 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.wifi@1.5; + +import @1.0::StaLinkLayerIfaceStats; +import @1.0::StaLinkLayerIfacePacketStats; +import @1.0::TimeStampInMs; +import @1.4::WifiBand; +import @1.0::NanCipherSuiteType; +import @1.0::NanCapabilities; +import @1.2::NanConfigRequestSupplemental; +import @1.3::StaLinkLayerRadioStats; +import @1.0::WifiChannelInMhz; +import @1.0::WifiChannelWidthInMhz; +import @1.4::WifiRateInfo; + +/** + * Wifi bands defined in 80211 spec. + */ +enum WifiBand : @1.4::WifiBand { + /** + * 60 GHz. + */ + BAND_60GHZ = 16, + /** + * 2.4 GHz + 5 GHz no DFS + 6 GHz + 60 GHz. + */ + BAND_24GHZ_5GHZ_6GHZ_60GHZ = 27, + /** + * 2.4 GHz + 5 GHz with DFS + 6 GHz + 60 GHz. + */ + BAND_24GHZ_5GHZ_WITH_DFS_6GHZ_60GHZ = 31, +}; + +/** + * Interface operating modes. + */ +enum WifiIfaceMode : uint32_t { + /** + * Interface operation mode is client. + */ + IFACE_MODE_STA = 1 << 0, + /** + * Interface operation mode is Hotspot. + */ + IFACE_MODE_SOFTAP = 1 << 1, + /** + * Interface operation mode is Ad-Hoc network. + */ + IFACE_MODE_IBSS = 1 << 2, + /** + * Interface operation mode is Wifi Direct Client. + */ + IFACE_MODE_P2P_CLIENT = 1 << 3, + /** + * Interface operation mode is Wifi Direct Group Owner. + */ + IFACE_MODE_P2P_GO = 1 << 4, + /** + * Interface operation mode is Aware. + */ + IFACE_MODE_NAN = 1 << 5, + /** + * Interface operation mode is Mesh network. + */ + IFACE_MODE_MESH = 1 << 6, + /** + * Interface operation mode is Tunneled Direct Link Setup. + */ + IFACE_MODE_TDLS = 1 << 7, +}; + +/** + * Wifi usable channel information. + */ +struct WifiUsableChannel { + /** + * Wifi channel freqeuncy in MHz. + */ + WifiChannelInMhz channel; + + /** + * Wifi channel bandwidth in MHz. + */ + WifiChannelWidthInMhz channelBandwidth; + + /** + * Iface modes feasible on this channel. + */ + bitfield ifaceModeMask; +}; + +/** + * NAN configuration request parameters added in the 1.2 HAL. These are supplemental to previous + * versions. + */ +struct NanConfigRequestSupplemental { + /** + * Baseline information as defined in HAL 1.2. + */ + @1.2::NanConfigRequestSupplemental V1_2; + + /** + * Controls whether NAN instant communication mode is enabled. + */ + bool enableInstantCommunicationMode; +}; + +/** + * NDP Capabilities response. + */ +struct NanCapabilities { + /** + * Baseline information as defined in HAL 1.0. + */ + @1.0::NanCapabilities V1_0; + + /** + * Flag to indicate id instant communication mode is supported. + */ + bool instantCommunicationModeSupportFlag; +}; + +/** + * Contention time statistics for different traffic categories. + */ +struct StaLinkLayerIfaceContentionTimeStats { + /** + * Data packet min contention time (usec). It includes both the internal contention time + * among different access categories within the chipset and the contention time for the medium. + */ + uint32_t contentionTimeMinInUsec; + + /** + * Data packet max contention time (usec). It includes both the internal contention time + * among different access categories within the chipset and the contention time for the medium. + */ + uint32_t contentionTimeMaxInUsec; + /** + * Data packet average contention time (usec). It includes both the internal contention time + * among different access categories within the chipset and the contention time for the medium. + */ + uint32_t contentionTimeAvgInUsec; + + /** + * Number of data packets used for contention statistics. + */ + uint32_t contentionNumSamples; +}; + +/** + * Per rate statistics. The rate is characterized by the combination of preamble, number of spatial + * streams, transmission bandwidth, and modulation and coding scheme (MCS). + */ +struct StaRateStat{ + /** + * Wifi rate information: preamble, number of spatial streams, bandwidth, MCS, etc. + */ + WifiRateInfo rateInfo; + /** + * Number of successfully transmitted data packets (ACK received) + */ + uint32_t txMpdu; + /** + * Number of received data packets + */ + uint32_t rxMpdu; + /** + * Number of data packet losses (no ACK) + */ + uint32_t mpduLost; + /** + * Number of data packet retries + */ + uint32_t retries; +}; + +/** + * Per peer statistics. The types of peer include the Access Point (AP), the Tunneled Direct Link + * Setup (TDLS), the Group Owner (GO), the Neighbor Awareness Networking (NAN), etc. + */ +struct StaPeerInfo { + /** + * Station count: The total number of stations currently associated with the peer. + */ + uint16_t staCount; + /** + * Channel utilization: The percentage of time (normalized to 255, i.e., x% corresponds to + * (int) x * 255 / 100) that the medium is sensed as busy measured by either physical or + * virtual carrier sense (CS) mechanism. + */ + uint16_t chanUtil; + /** + * Per rate statistics + */ + vec rateStats; +}; + +/** + * Iface statistics for the current connection. + */ +struct StaLinkLayerIfaceStats { + /** + * Baseline information as defined in HAL 1.0. + */ + @1.0::StaLinkLayerIfaceStats V1_0; + + /** + * Duty cycle for the iface. + * if this iface is being served using time slicing on a radio with one or more ifaces + * (i.e MCC), then the duty cycle assigned to this iface in %. + * If not using time slicing (i.e SCC or DBS), set to 100. + */ + uint8_t timeSliceDutyCycleInPercent; + + /** + * WME Best Effort (BE) Access Category (AC) contention time statistics. + */ + StaLinkLayerIfaceContentionTimeStats wmeBeContentionTimeStats; + + /** + * WME Background (BK) Access Category (AC) contention time statistics. + */ + StaLinkLayerIfaceContentionTimeStats wmeBkContentionTimeStats; + + /** + * WME Video (VI) Access Category (AC) contention time statistics. + */ + StaLinkLayerIfaceContentionTimeStats wmeViContentionTimeStats; + + /** + * WME Voice (VO) Access Category (AC) contention time statistics. + */ + StaLinkLayerIfaceContentionTimeStats wmeVoContentionTimeStats; + + /** + * Per peer statistics. + */ + vec peers; +}; + +struct StaLinkLayerRadioStats { + /** + * Baseline information as defined in HAL 1.3. + */ + @1.3::StaLinkLayerRadioStats V1_3; + + /** + * Radio ID: An implementation specific value identifying the radio interface for which the + * stats are produced. Framework must not interpret this value. It must use this value for + * persistently identifying the statistics between calls, + * e.g. if the HAL provides them in different order. + */ + int32_t radioId; +}; + +/** + * Link layer stats retrieved via |getLinkLayerStats|. + */ +struct StaLinkLayerStats { + StaLinkLayerIfaceStats iface; + + vec radios; + + /** + * TimeStamp for each stats sample. + * This is the absolute milliseconds from boot when these stats were + * sampled. + */ + TimeStampInMs timeStampInMs; +}; diff --git a/wifi/1.5/vts/OWNERS b/wifi/1.5/vts/OWNERS new file mode 100644 index 0000000000000000000000000000000000000000..cf81c798925338533dcb4d1968ea7de942b367f3 --- /dev/null +++ b/wifi/1.5/vts/OWNERS @@ -0,0 +1,2 @@ +arabawy@google.com +etancohen@google.com diff --git a/wifi/1.5/vts/functional/Android.bp b/wifi/1.5/vts/functional/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..764d14da0a03a0355cfecd859c6ad57fce26e74c --- /dev/null +++ b/wifi/1.5/vts/functional/Android.bp @@ -0,0 +1,117 @@ +// +// Copyright (C) 2020 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_library_static { + name: "VtsHalWifiV1_5TargetTestUtil", + defaults: ["VtsHalTargetTestDefaults"], + srcs: [ + "wifi_hidl_test_utils_1_5.cpp", + ], + export_include_dirs: [ + ".", + ], + shared_libs: [ + "libnativehelper", + ], + static_libs: [ + "VtsHalWifiV1_0TargetTestUtil", + "android.hardware.wifi@1.0", + "android.hardware.wifi@1.3", + "android.hardware.wifi@1.5", + "libwifi-system-iface", + ], +} + +cc_test { + name: "VtsHalWifiV1_5TargetTest", + defaults: ["VtsHalTargetTestDefaults"], + srcs: [ + "wifi_chip_hidl_test.cpp", + "wifi_sta_iface_hidl_test.cpp", + ], + static_libs: [ + "VtsHalWifiV1_0TargetTestUtil", + "android.hardware.wifi@1.0", + "android.hardware.wifi@1.1", + "android.hardware.wifi@1.2", + "android.hardware.wifi@1.3", + "android.hardware.wifi@1.4", + "android.hardware.wifi@1.5", + "libwifi-system-iface", + ], + test_suites: [ + "general-tests", + "vts", + ], +} + +// These tests are split out so that they can be conditioned on presence of the +// "android.hardware.wifi.aware" feature. +cc_test { + name: "VtsHalWifiNanV1_5TargetTest", + defaults: ["VtsHalTargetTestDefaults"], + srcs: [ + "wifi_nan_iface_hidl_test.cpp", + ], + static_libs: [ + "VtsHalWifiV1_0TargetTestUtil", + "android.hardware.wifi@1.0", + "android.hardware.wifi@1.1", + "android.hardware.wifi@1.2", + "android.hardware.wifi@1.3", + "android.hardware.wifi@1.4", + "android.hardware.wifi@1.5", + "libwifi-system-iface", + ], + test_suites: [ + "general-tests", + "vts", + ], +} + +// SoftAP-specific tests, similar to VtsHalWifiApV1_0TargetTest. +cc_test { + name: "VtsHalWifiApV1_5TargetTest", + defaults: ["VtsHalTargetTestDefaults"], + srcs: [ + "wifi_chip_hidl_ap_test.cpp", + "wifi_ap_iface_hidl_test.cpp", + ], + static_libs: [ + "VtsHalWifiV1_0TargetTestUtil", + "VtsHalWifiV1_5TargetTestUtil", + "android.hardware.wifi@1.0", + "android.hardware.wifi@1.1", + "android.hardware.wifi@1.2", + "android.hardware.wifi@1.3", + "android.hardware.wifi@1.4", + "android.hardware.wifi@1.5", + "libwifi-system-iface", + ], + test_suites: [ + "general-tests", + "vts", + ], +} diff --git a/wifi/1.5/vts/functional/wifi_ap_iface_hidl_test.cpp b/wifi/1.5/vts/functional/wifi_ap_iface_hidl_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..424f9345f838f7db4a105f042cddf21587295a50 --- /dev/null +++ b/wifi/1.5/vts/functional/wifi_ap_iface_hidl_test.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#undef NAN // NAN is defined in bionic/libc/include/math.h:38 + +#include +#include +#include +#include +#include +#include +#include + +#include "wifi_hidl_call_util.h" +#include "wifi_hidl_test_utils.h" +#include "wifi_hidl_test_utils_1_5.h" + +using ::android::sp; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::wifi::V1_0::ChipModeId; +using ::android::hardware::wifi::V1_0::IfaceType; +using ::android::hardware::wifi::V1_0::IWifiIface; +using ::android::hardware::wifi::V1_0::WifiDebugRingBufferStatus; +using ::android::hardware::wifi::V1_0::WifiStatus; +using ::android::hardware::wifi::V1_0::WifiStatusCode; +using ::android::hardware::wifi::V1_4::IWifiChipEventCallback; +using ::android::hardware::wifi::V1_5::IWifiApIface; +using ::android::hardware::wifi::V1_5::IWifiChip; + +/** + * Fixture for IWifiChip tests that are conditioned on SoftAP support. + */ +class WifiApIfaceHidlTest : public ::testing::TestWithParam { + public: + virtual void SetUp() override { + isBridgedSupport_ = testing::checkSubstringInCommandOutput( + "/system/bin/cmd wifi get-softap-supported-features", + "wifi_softap_bridged_ap_supported"); + // Make sure to start with a clean state + stopWifi(GetInstanceName()); + } + + virtual void TearDown() override { stopWifi(GetInstanceName()); } + + protected: + bool isBridgedSupport_ = false; + std::string GetInstanceName() { return GetParam(); } +}; + +/** + * resetToFactoryMacAddress in bridged AP mode. + */ +TEST_P(WifiApIfaceHidlTest, resetToFactoryMacAddressInBridgedModeTest) { + if (!isBridgedSupport_) GTEST_SKIP() << "Missing Bridged AP support"; + sp wifi_ap_iface = + getBridgedWifiApIface_1_5(GetInstanceName()); + ASSERT_NE(nullptr, wifi_ap_iface.get()); + const auto& status = HIDL_INVOKE(wifi_ap_iface, resetToFactoryMacAddress); + EXPECT_EQ(WifiStatusCode::SUCCESS, status.code); +} + +/** + * resetToFactoryMacAddress in non-bridged mode + */ +TEST_P(WifiApIfaceHidlTest, resetToFactoryMacAddressTest) { + sp wifi_ap_iface = getWifiApIface_1_5(GetInstanceName()); + ASSERT_NE(nullptr, wifi_ap_iface.get()); + const auto& status = HIDL_INVOKE(wifi_ap_iface, resetToFactoryMacAddress); + EXPECT_EQ(WifiStatusCode::SUCCESS, status.code); +} + +/** + * getBridgedInstances in non-bridged mode + */ +TEST_P(WifiApIfaceHidlTest, getBridgedInstancesTest) { + sp wifi_ap_iface = getWifiApIface_1_5(GetInstanceName()); + ASSERT_NE(nullptr, wifi_ap_iface.get()); + const auto& status_and_instances = + HIDL_INVOKE(wifi_ap_iface, getBridgedInstances); + EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_instances.first.code); + const auto& instances = status_and_instances.second; + EXPECT_EQ(0, instances.size()); +} + +/** + * getBridgedInstances in bridged AP mode. + */ +TEST_P(WifiApIfaceHidlTest, getBridgedInstancesInBridgedModeTest) { + if (!isBridgedSupport_) GTEST_SKIP() << "Missing Bridged AP support"; + sp wifi_ap_iface = + getBridgedWifiApIface_1_5(GetInstanceName()); + ASSERT_NE(nullptr, wifi_ap_iface.get()); + const auto& status_and_instances = + HIDL_INVOKE(wifi_ap_iface, getBridgedInstances); + EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_instances.first.code); + const auto& instances = status_and_instances.second; + EXPECT_EQ(2, instances.size()); +} + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiApIfaceHidlTest); +INSTANTIATE_TEST_SUITE_P( + PerInstance, WifiApIfaceHidlTest, + testing::ValuesIn(android::hardware::getAllHalInstanceNames( + ::android::hardware::wifi::V1_5::IWifi::descriptor)), + android::hardware::PrintInstanceNameToString); diff --git a/wifi/1.5/vts/functional/wifi_chip_hidl_ap_test.cpp b/wifi/1.5/vts/functional/wifi_chip_hidl_ap_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d6a040852eea394d6d006bf2888d1c9832340f8b --- /dev/null +++ b/wifi/1.5/vts/functional/wifi_chip_hidl_ap_test.cpp @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#undef NAN // NAN is defined in bionic/libc/include/math.h:38 + +#include +#include +#include +#include +#include +#include +#include + +#include "wifi_hidl_call_util.h" +#include "wifi_hidl_test_utils.h" + +using ::android::sp; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::wifi::V1_0::ChipModeId; +using ::android::hardware::wifi::V1_0::IfaceType; +using ::android::hardware::wifi::V1_0::IWifiIface; +using ::android::hardware::wifi::V1_0::WifiDebugRingBufferStatus; +using ::android::hardware::wifi::V1_0::WifiStatus; +using ::android::hardware::wifi::V1_0::WifiStatusCode; +using ::android::hardware::wifi::V1_4::IWifiChipEventCallback; +using ::android::hardware::wifi::V1_5::IWifiApIface; +using ::android::hardware::wifi::V1_5::IWifiChip; + +/** + * Fixture for IWifiChip tests that are conditioned on SoftAP support. + */ +class WifiChipHidlTest : public ::testing::TestWithParam { + public: + virtual void SetUp() override { + isBridgedSupport_ = testing::checkSubstringInCommandOutput( + "/system/bin/cmd wifi get-softap-supported-features", + "wifi_softap_bridged_ap_supported"); + // Make sure to start with a clean state + stopWifi(GetInstanceName()); + + wifi_chip_ = IWifiChip::castFrom(getWifiChip(GetInstanceName())); + ASSERT_NE(nullptr, wifi_chip_.get()); + } + + virtual void TearDown() override { stopWifi(GetInstanceName()); } + + protected: + bool isBridgedSupport_ = false; + // Helper function to configure the Chip in one of the supported modes. + // Most of the non-mode-configuration-related methods require chip + // to be first configured. + ChipModeId configureChipForIfaceType(IfaceType type, bool expectSuccess) { + ChipModeId mode_id; + EXPECT_EQ(expectSuccess, + configureChipToSupportIfaceType(wifi_chip_, type, &mode_id)); + return mode_id; + } + + void createBridgedApIface(sp* ap_iface) { + configureChipForIfaceType(IfaceType::AP, true); + const auto& status_and_iface = + HIDL_INVOKE(wifi_chip_, createBridgedApIface); + *ap_iface = status_and_iface.second; + EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_iface.first.code); + } + + sp wifi_chip_; + + private: + std::string GetInstanceName() { return GetParam(); } +}; + +/** + * createBridgedApIface & removeIfaceInstanceFromBridgedApIface + */ +TEST_P(WifiChipHidlTest, + createBridgedApIfaceAndremoveIfaceInstanceFromBridgedApIfaceTest) { + if (!isBridgedSupport_) GTEST_SKIP() << "Missing Bridged AP support"; + sp wifi_ap_iface; + createBridgedApIface(&wifi_ap_iface); + ASSERT_NE(nullptr, wifi_ap_iface.get()); + const auto& status_and_name = HIDL_INVOKE(wifi_ap_iface, getName); + EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_name.first.code); + std::string br_name = status_and_name.second; + const auto& status_and_instances = + HIDL_INVOKE(wifi_ap_iface, getBridgedInstances); + EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_instances.first.code); + const auto& instances = status_and_instances.second; + EXPECT_EQ(2, instances.size()); + const auto& status_code = + HIDL_INVOKE(wifi_chip_, removeIfaceInstanceFromBridgedApIface, br_name, + instances[0]); + EXPECT_EQ(WifiStatusCode::SUCCESS, status_code.code); + const auto& status_and_instances_after_remove = + HIDL_INVOKE(wifi_ap_iface, getBridgedInstances); + EXPECT_EQ(WifiStatusCode::SUCCESS, + status_and_instances_after_remove.first.code); + const auto& instances_after_remove = + status_and_instances_after_remove.second; + EXPECT_EQ(1, instances_after_remove.size()); +} + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiChipHidlTest); +INSTANTIATE_TEST_SUITE_P( + PerInstance, WifiChipHidlTest, + testing::ValuesIn(android::hardware::getAllHalInstanceNames( + ::android::hardware::wifi::V1_5::IWifi::descriptor)), + android::hardware::PrintInstanceNameToString); diff --git a/wifi/1.5/vts/functional/wifi_chip_hidl_test.cpp b/wifi/1.5/vts/functional/wifi_chip_hidl_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..07f7f470feb1c63c79bedb8a98ff08a4b7b7fdd1 --- /dev/null +++ b/wifi/1.5/vts/functional/wifi_chip_hidl_test.cpp @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#undef NAN // NAN is defined in bionic/libc/include/math.h:38 + +#include +#include +#include +#include +#include +#include +#include + +#include "wifi_hidl_call_util.h" +#include "wifi_hidl_test_utils.h" + +using ::android::sp; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::wifi::V1_0::ChipModeId; +using ::android::hardware::wifi::V1_0::IfaceType; +using ::android::hardware::wifi::V1_0::IWifiIface; +using ::android::hardware::wifi::V1_0::IWifiStaIface; +using ::android::hardware::wifi::V1_0::WifiDebugRingBufferStatus; +using ::android::hardware::wifi::V1_0::WifiStatus; +using ::android::hardware::wifi::V1_0::WifiStatusCode; +using ::android::hardware::wifi::V1_4::IWifiChipEventCallback; +using ::android::hardware::wifi::V1_5::IWifiChip; +using ::android::hardware::wifi::V1_5::WifiBand; +using ::android::hardware::wifi::V1_5::WifiIfaceMode; + +/** + * Fixture to use for all Wifi chip HIDL interface tests. + */ +class WifiChipHidlTest : public ::testing::TestWithParam { + public: + virtual void SetUp() override { + // Make sure to start with a clean state + stopWifi(GetInstanceName()); + + wifi_chip_ = IWifiChip::castFrom(getWifiChip(GetInstanceName())); + ASSERT_NE(nullptr, wifi_chip_.get()); + } + + virtual void TearDown() override { stopWifi(GetInstanceName()); } + + protected: + // Helper function to configure the Chip in one of the supported modes. + // Most of the non-mode-configuration-related methods require chip + // to be first configured. + ChipModeId configureChipForIfaceType(IfaceType type, bool expectSuccess) { + ChipModeId mode_id; + EXPECT_EQ(expectSuccess, + configureChipToSupportIfaceType(wifi_chip_, type, &mode_id)); + return mode_id; + } + + WifiStatusCode createStaIface(sp* sta_iface) { + const auto& status_and_iface = HIDL_INVOKE(wifi_chip_, createStaIface); + *sta_iface = status_and_iface.second; + return status_and_iface.first.code; + } + + std::string getIfaceName(const sp& iface) { + const auto& status_and_name = HIDL_INVOKE(iface, getName); + EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_name.first.code); + return status_and_name.second; + } + + std::vector> create2StaIfacesIfPossible() { + configureChipForIfaceType(IfaceType::STA, true); + sp iface1, iface2; + EXPECT_EQ(WifiStatusCode::SUCCESS, createStaIface(&iface1)); + EXPECT_NE(nullptr, iface1.get()); + + // Try to create 2nd iface + auto status = createStaIface(&iface2); + if (status != WifiStatusCode::SUCCESS) { + return {iface1}; + } + EXPECT_NE(nullptr, iface2.get()); + return {iface1, iface2}; + } + + sp wifi_chip_; + + private: + std::string GetInstanceName() { return GetParam(); } +}; + +/* + * setMultiStaPrimaryConnection + * + * Only run if device supports 2 STA ifaces. + */ +TEST_P(WifiChipHidlTest, setMultiStaPrimaryConnection) { + auto ifaces = create2StaIfacesIfPossible(); + if (ifaces.size() < 2) { + GTEST_SKIP() << "Device does not support more than 1 STA concurrently"; + } + + const auto& status = HIDL_INVOKE(wifi_chip_, setMultiStaPrimaryConnection, + getIfaceName(ifaces.front())); + if (status.code != WifiStatusCode::SUCCESS) { + EXPECT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED, status.code); + } +} + +/* + * setMultiStaUseCase + * + * Only run if device supports 2 STA ifaces. + */ +TEST_P(WifiChipHidlTest, setMultiStaUseCase) { + auto ifaces = create2StaIfacesIfPossible(); + if (ifaces.size() < 2) { + GTEST_SKIP() << "Device does not support more than 1 STA concurrently"; + } + + const auto& status = HIDL_INVOKE( + wifi_chip_, setMultiStaUseCase, + IWifiChip::MultiStaUseCase::DUAL_STA_TRANSIENT_PREFER_PRIMARY); + if (status.code != WifiStatusCode::SUCCESS) { + EXPECT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED, status.code); + } +} + +/* + * setCoexUnsafeChannels + */ +TEST_P(WifiChipHidlTest, setCoexUnsafeChannels) { + configureChipForIfaceType(IfaceType::STA, true); + // Test with empty vector of CoexUnsafeChannels + std::vector vec; + const auto& statusEmpty = + HIDL_INVOKE(wifi_chip_, setCoexUnsafeChannels, vec, 0); + if (statusEmpty.code != WifiStatusCode::SUCCESS) { + EXPECT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED, statusEmpty.code); + } + + // Test with non-empty vector of CoexUnsafeChannels + IWifiChip::CoexUnsafeChannel unsafeChannel24Ghz; + unsafeChannel24Ghz.band = WifiBand::BAND_24GHZ; + unsafeChannel24Ghz.channel = 6; + vec.push_back(unsafeChannel24Ghz); + IWifiChip::CoexUnsafeChannel unsafeChannel5Ghz; + unsafeChannel5Ghz.band = WifiBand::BAND_5GHZ; + unsafeChannel5Ghz.channel = 36; + vec.push_back(unsafeChannel5Ghz); + uint32_t restrictions = IWifiChip::CoexRestriction::WIFI_AWARE | + IWifiChip::CoexRestriction::SOFTAP | + IWifiChip::CoexRestriction::WIFI_DIRECT; + const auto& statusNonEmpty = + HIDL_INVOKE(wifi_chip_, setCoexUnsafeChannels, vec, restrictions); + if (statusNonEmpty.code != WifiStatusCode::SUCCESS) { + EXPECT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED, statusNonEmpty.code); + } +} + +/* + * SetCountryCode: + * Ensures that a call to set the country code will return with a success + * status code. + */ +TEST_P(WifiChipHidlTest, setCountryCode) { + const android::hardware::hidl_array kCountryCode{ + std::array{{0x55, 0x53}}}; + + configureChipForIfaceType(IfaceType::STA, true); + EXPECT_EQ(WifiStatusCode::SUCCESS, + HIDL_INVOKE(wifi_chip_, setCountryCode, kCountryCode).code); +} + +/* getUsableChannels: + * Ensure that a call to getUsableChannels will return with a success + * status for valid inputs. + */ +TEST_P(WifiChipHidlTest, getUsableChannels) { + uint32_t ifaceModeMask = + WifiIfaceMode::IFACE_MODE_P2P_CLIENT | WifiIfaceMode::IFACE_MODE_P2P_GO; + uint32_t filterMask = IWifiChip::UsableChannelFilter::CELLULAR_COEXISTENCE | + IWifiChip::UsableChannelFilter::CONCURRENCY; + configureChipForIfaceType(IfaceType::STA, true); + WifiBand band = WifiBand::BAND_24GHZ_5GHZ_6GHZ; + const auto& statusNonEmpty = HIDL_INVOKE(wifi_chip_, getUsableChannels, + band, ifaceModeMask, filterMask); + if (statusNonEmpty.first.code != WifiStatusCode::SUCCESS) { + EXPECT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED, + statusNonEmpty.first.code); + } +} + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiChipHidlTest); +INSTANTIATE_TEST_SUITE_P( + PerInstance, WifiChipHidlTest, + testing::ValuesIn(android::hardware::getAllHalInstanceNames( + ::android::hardware::wifi::V1_5::IWifi::descriptor)), + android::hardware::PrintInstanceNameToString); diff --git a/wifi/1.5/vts/functional/wifi_hidl_test_utils_1_5.cpp b/wifi/1.5/vts/functional/wifi_hidl_test_utils_1_5.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f1da2eae98418d2f950c74f89cb42242da327154 --- /dev/null +++ b/wifi/1.5/vts/functional/wifi_hidl_test_utils_1_5.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#undef NAN // NAN is defined in bionic/libc/include/math.h:38 + +#include +#include +#include +#include +#include +#include + +#include "wifi_hidl_call_util.h" +#include "wifi_hidl_test_utils.h" + +using ::android::sp; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::wifi::V1_0::ChipModeId; +using ::android::hardware::wifi::V1_0::IfaceType; +using ::android::hardware::wifi::V1_5::IWifiApIface; +using ::android::hardware::wifi::V1_5::IWifiChip; + +sp getWifiChip_1_5(const std::string& instance_name) { + return IWifiChip::castFrom(getWifiChip(instance_name)); +} + +sp getWifiApIface_1_5(const std::string& instance_name) { + ChipModeId mode_id; + sp wifi_chip_ = getWifiChip_1_5(instance_name); + configureChipToSupportIfaceType(wifi_chip_, IfaceType::AP, &mode_id); + const auto& status_and_iface = HIDL_INVOKE(wifi_chip_, createApIface); + return IWifiApIface::castFrom(status_and_iface.second); +} + +sp getBridgedWifiApIface_1_5(const std::string& instance_name) { + ChipModeId mode_id; + sp wifi_chip_ = getWifiChip_1_5(instance_name); + configureChipToSupportIfaceType(wifi_chip_, IfaceType::AP, &mode_id); + const auto& status_and_iface = + HIDL_INVOKE(wifi_chip_, createBridgedApIface); + return IWifiApIface::castFrom(status_and_iface.second); +} diff --git a/wifi/1.5/vts/functional/wifi_hidl_test_utils_1_5.h b/wifi/1.5/vts/functional/wifi_hidl_test_utils_1_5.h new file mode 100644 index 0000000000000000000000000000000000000000..1b8b73763202aa0d341789856d5e5a6e40225435 --- /dev/null +++ b/wifi/1.5/vts/functional/wifi_hidl_test_utils_1_5.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include + +#include + +#include +// Helper functions to obtain references to the various HIDL interface objects. +// Note: We only have a single instance of each of these objects currently. +// These helper functions should be modified to return vectors if we support +// multiple instances. +android::sp getWifiChip_1_5( + const std::string& instance_name); +android::sp getWifiApIface_1_5( + const std::string& instance_name); +android::sp +getBridgedWifiApIface_1_5(const std::string& instance_name); diff --git a/wifi/1.5/vts/functional/wifi_nan_iface_hidl_test.cpp b/wifi/1.5/vts/functional/wifi_nan_iface_hidl_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..803d39df15104942e5e01f072858beb9480ddeaf --- /dev/null +++ b/wifi/1.5/vts/functional/wifi_nan_iface_hidl_test.cpp @@ -0,0 +1,628 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Nanache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "wifi_hidl_call_util.h" +#include "wifi_hidl_test_utils.h" + +using namespace ::android::hardware::wifi::V1_0; +using namespace ::android::hardware::wifi::V1_2; +using namespace ::android::hardware::wifi::V1_4; +using namespace ::android::hardware::wifi::V1_5; + +using ::android::sp; +using ::android::hardware::Return; +using ::android::hardware::Void; + +#define TIMEOUT_PERIOD 10 + +android::sp getWifiNanIface_1_5( + const std::string& instance_name) { + return android::hardware::wifi::V1_5::IWifiNanIface::castFrom( + getWifiNanIface(instance_name)); +} + +/** + * Fixture to use for all NAN Iface HIDL interface tests. + */ +class WifiNanIfaceHidlTest : public ::testing::TestWithParam { + public: + virtual void SetUp() override { + if (!::testing::deviceSupportsFeature("android.hardware.wifi.aware")) + GTEST_SKIP() << "Skipping this test since NAN is not supported."; + // Make sure to start with a clean state + stopWifi(GetInstanceName()); + + iwifiNanIface = getWifiNanIface_1_5(GetInstanceName()); + ASSERT_NE(nullptr, iwifiNanIface.get()); + ASSERT_EQ(WifiStatusCode::SUCCESS, + HIDL_INVOKE(iwifiNanIface, registerEventCallback_1_5, + new WifiNanIfaceEventCallback(*this)) + .code); + } + + virtual void TearDown() override { stopWifi(GetInstanceName()); } + + /* Used as a mechanism to inform the test about data/event callback */ + inline void notify() { + std::unique_lock lock(mtx_); + count_++; + cv_.notify_one(); + } + + enum CallbackType { + INVALID = -2, + ANY_CALLBACK = -1, + + NOTIFY_CAPABILITIES_RESPONSE = 0, + NOTIFY_ENABLE_RESPONSE, + NOTIFY_CONFIG_RESPONSE, + NOTIFY_DISABLE_RESPONSE, + NOTIFY_START_PUBLISH_RESPONSE, + NOTIFY_STOP_PUBLISH_RESPONSE, + NOTIFY_START_SUBSCRIBE_RESPONSE, + NOTIFY_STOP_SUBSCRIBE_RESPONSE, + NOTIFY_TRANSMIT_FOLLOWUP_RESPONSE, + NOTIFY_CREATE_DATA_INTERFACE_RESPONSE, + NOTIFY_DELETE_DATA_INTERFACE_RESPONSE, + NOTIFY_INITIATE_DATA_PATH_RESPONSE, + NOTIFY_RESPOND_TO_DATA_PATH_INDICATION_RESPONSE, + NOTIFY_TERMINATE_DATA_PATH_RESPONSE, + NOTIFY_CAPABILITIES_RESPONSE_1_5, + + EVENT_CLUSTER_EVENT, + EVENT_DISABLED, + EVENT_PUBLISH_TERMINATED, + EVENT_SUBSCRIBE_TERMINATED, + EVENT_MATCH, + EVENT_MATCH_EXPIRED, + EVENT_FOLLOWUP_RECEIVED, + EVENT_TRANSMIT_FOLLOWUP, + EVENT_DATA_PATH_REQUEST, + EVENT_DATA_PATH_CONFIRM, + EVENT_DATA_PATH_TERMINATED, + EVENT_DATA_PATH_CONFIRM_1_2, + EVENT_DATA_PATH_SCHEDULE_UPDATE + }; + + /* Test code calls this function to wait for data/event callback */ + /* Must set callbackType = INVALID before call this function */ + inline std::cv_status wait(CallbackType waitForCallbackType) { + std::unique_lock lock(mtx_); + + EXPECT_NE(INVALID, waitForCallbackType); // can't ASSERT in a + // non-void-returning method + + std::cv_status status = std::cv_status::no_timeout; + auto now = std::chrono::system_clock::now(); + while (count_ == 0) { + status = cv_.wait_until(lock, + now + std::chrono::seconds(TIMEOUT_PERIOD)); + if (status == std::cv_status::timeout) return status; + if (waitForCallbackType != ANY_CALLBACK && + callbackType != INVALID && + callbackType != waitForCallbackType) { + count_--; + } + } + count_--; + return status; + } + + class WifiNanIfaceEventCallback + : public ::android::hardware::wifi::V1_5::IWifiNanIfaceEventCallback { + WifiNanIfaceHidlTest& parent_; + + public: + WifiNanIfaceEventCallback(WifiNanIfaceHidlTest& parent) + : parent_(parent){}; + + virtual ~WifiNanIfaceEventCallback() = default; + + Return notifyCapabilitiesResponse( + uint16_t id, const WifiNanStatus& status, + const ::android::hardware::wifi::V1_0::NanCapabilities& + capabilities) override { + parent_.callbackType = NOTIFY_CAPABILITIES_RESPONSE; + + parent_.id = id; + parent_.status = status; + parent_.capabilities = capabilities; + + parent_.notify(); + return Void(); + } + + Return notifyCapabilitiesResponse_1_5( + uint16_t id, const WifiNanStatus& status, + const ::android::hardware::wifi::V1_5::NanCapabilities& + capabilities) override { + parent_.callbackType = NOTIFY_CAPABILITIES_RESPONSE_1_5; + + parent_.id = id; + parent_.status = status; + parent_.capabilities_1_5 = capabilities; + + parent_.notify(); + return Void(); + } + + Return notifyEnableResponse( + uint16_t id, const WifiNanStatus& status) override { + parent_.callbackType = NOTIFY_ENABLE_RESPONSE; + + parent_.id = id; + parent_.status = status; + + parent_.notify(); + return Void(); + } + + Return notifyConfigResponse( + uint16_t id, const WifiNanStatus& status) override { + parent_.callbackType = NOTIFY_CONFIG_RESPONSE; + + parent_.id = id; + parent_.status = status; + + parent_.notify(); + return Void(); + } + + Return notifyDisableResponse( + uint16_t id, const WifiNanStatus& status) override { + parent_.callbackType = NOTIFY_DISABLE_RESPONSE; + + parent_.id = id; + parent_.status = status; + + parent_.notify(); + return Void(); + } + + Return notifyStartPublishResponse(uint16_t id, + const WifiNanStatus& status, + uint8_t sessionId) override { + parent_.callbackType = NOTIFY_START_PUBLISH_RESPONSE; + + parent_.id = id; + parent_.status = status; + parent_.sessionId = sessionId; + + parent_.notify(); + return Void(); + } + + Return notifyStopPublishResponse( + uint16_t id, const WifiNanStatus& status) override { + parent_.callbackType = NOTIFY_STOP_PUBLISH_RESPONSE; + + parent_.id = id; + parent_.status = status; + + parent_.notify(); + return Void(); + } + + Return notifyStartSubscribeResponse(uint16_t id, + const WifiNanStatus& status, + uint8_t sessionId) override { + parent_.callbackType = NOTIFY_START_SUBSCRIBE_RESPONSE; + + parent_.id = id; + parent_.status = status; + parent_.sessionId = sessionId; + + parent_.notify(); + return Void(); + } + + Return notifyStopSubscribeResponse( + uint16_t id, const WifiNanStatus& status) override { + parent_.callbackType = NOTIFY_STOP_SUBSCRIBE_RESPONSE; + + parent_.id = id; + parent_.status = status; + + parent_.notify(); + return Void(); + } + + Return notifyTransmitFollowupResponse( + uint16_t id, const WifiNanStatus& status) override { + parent_.callbackType = NOTIFY_TRANSMIT_FOLLOWUP_RESPONSE; + + parent_.id = id; + parent_.status = status; + + parent_.notify(); + return Void(); + } + + Return notifyCreateDataInterfaceResponse( + uint16_t id, const WifiNanStatus& status) override { + parent_.callbackType = NOTIFY_CREATE_DATA_INTERFACE_RESPONSE; + + parent_.id = id; + parent_.status = status; + + parent_.notify(); + return Void(); + } + + Return notifyDeleteDataInterfaceResponse( + uint16_t id, const WifiNanStatus& status) override { + parent_.callbackType = NOTIFY_DELETE_DATA_INTERFACE_RESPONSE; + + parent_.id = id; + parent_.status = status; + + parent_.notify(); + return Void(); + } + + Return notifyInitiateDataPathResponse( + uint16_t id, const WifiNanStatus& status, + uint32_t ndpInstanceId) override { + parent_.callbackType = NOTIFY_INITIATE_DATA_PATH_RESPONSE; + + parent_.id = id; + parent_.status = status; + parent_.ndpInstanceId = ndpInstanceId; + + parent_.notify(); + return Void(); + } + + Return notifyRespondToDataPathIndicationResponse( + uint16_t id, const WifiNanStatus& status) override { + parent_.callbackType = + NOTIFY_RESPOND_TO_DATA_PATH_INDICATION_RESPONSE; + + parent_.id = id; + parent_.status = status; + + parent_.notify(); + return Void(); + } + + Return notifyTerminateDataPathResponse( + uint16_t id, const WifiNanStatus& status) override { + parent_.callbackType = NOTIFY_TERMINATE_DATA_PATH_RESPONSE; + + parent_.id = id; + parent_.status = status; + + parent_.notify(); + return Void(); + } + + Return eventClusterEvent( + const NanClusterEventInd& event) override { + parent_.callbackType = EVENT_CLUSTER_EVENT; + + parent_.nanClusterEventInd = event; + + parent_.notify(); + return Void(); + } + + Return eventDisabled(const WifiNanStatus& status) override { + parent_.callbackType = EVENT_DISABLED; + + parent_.status = status; + + parent_.notify(); + return Void(); + } + + Return eventPublishTerminated( + uint8_t sessionId, const WifiNanStatus& status) override { + parent_.callbackType = EVENT_PUBLISH_TERMINATED; + + parent_.sessionId = sessionId; + parent_.status = status; + + parent_.notify(); + return Void(); + } + + Return eventSubscribeTerminated( + uint8_t sessionId, const WifiNanStatus& status) override { + parent_.callbackType = EVENT_SUBSCRIBE_TERMINATED; + + parent_.sessionId = sessionId; + parent_.status = status; + + parent_.notify(); + return Void(); + } + + Return eventMatch(const NanMatchInd& event) override { + parent_.callbackType = EVENT_MATCH; + + parent_.nanMatchInd = event; + + parent_.notify(); + return Void(); + } + + Return eventMatchExpired(uint8_t discoverySessionId, + uint32_t peerId) override { + parent_.callbackType = EVENT_MATCH_EXPIRED; + + parent_.sessionId = discoverySessionId; + parent_.peerId = peerId; + + parent_.notify(); + return Void(); + } + + Return eventFollowupReceived( + const NanFollowupReceivedInd& event) override { + parent_.callbackType = EVENT_FOLLOWUP_RECEIVED; + + parent_.nanFollowupReceivedInd = event; + + parent_.notify(); + return Void(); + } + + Return eventTransmitFollowup( + uint16_t id, const WifiNanStatus& status) override { + parent_.callbackType = EVENT_TRANSMIT_FOLLOWUP; + + parent_.id = id; + parent_.status = status; + + parent_.notify(); + return Void(); + } + + Return eventDataPathRequest( + const NanDataPathRequestInd& event) override { + parent_.callbackType = EVENT_DATA_PATH_REQUEST; + + parent_.nanDataPathRequestInd = event; + + parent_.notify(); + return Void(); + } + + Return eventDataPathConfirm( + const ::android::hardware::wifi::V1_0::NanDataPathConfirmInd& event) + override { + parent_.callbackType = EVENT_DATA_PATH_CONFIRM; + + parent_.nanDataPathConfirmInd = event; + + parent_.notify(); + return Void(); + } + + Return eventDataPathTerminated(uint32_t ndpInstanceId) override { + parent_.callbackType = EVENT_DATA_PATH_TERMINATED; + + parent_.ndpInstanceId = ndpInstanceId; + + parent_.notify(); + return Void(); + } + + Return eventDataPathConfirm_1_2( + const ::android::hardware::wifi::V1_2::NanDataPathConfirmInd& event) + override { + parent_.callbackType = EVENT_DATA_PATH_CONFIRM_1_2; + + parent_.nanDataPathConfirmInd_1_2 = event; + + parent_.notify(); + return Void(); + } + + Return eventDataPathScheduleUpdate( + const NanDataPathScheduleUpdateInd& event) override { + parent_.callbackType = EVENT_DATA_PATH_SCHEDULE_UPDATE; + + parent_.nanDataPathScheduleUpdateInd = event; + + parent_.notify(); + return Void(); + } + }; + + private: + // synchronization objects + std::mutex mtx_; + std::condition_variable cv_; + int count_ = 0; + + protected: + android::sp<::android::hardware::wifi::V1_5::IWifiNanIface> iwifiNanIface; + + // Data from IWifiNanIfaceEventCallback callbacks: this is the collection of + // all arguments to all callbacks. They are set by the callback + // (notifications or events) and can be retrieved by tests. + CallbackType callbackType; + uint16_t id; + WifiNanStatus status; + uint8_t sessionId; + uint32_t ndpInstanceId; + NanClusterEventInd nanClusterEventInd; + NanMatchInd nanMatchInd; + uint32_t peerId; + NanFollowupReceivedInd nanFollowupReceivedInd; + NanDataPathRequestInd nanDataPathRequestInd; + ::android::hardware::wifi::V1_0::NanCapabilities capabilities; + ::android::hardware::wifi::V1_5::NanCapabilities capabilities_1_5; + ::android::hardware::wifi::V1_0::NanDataPathConfirmInd + nanDataPathConfirmInd; + ::android::hardware::wifi::V1_2::NanDataPathConfirmInd + nanDataPathConfirmInd_1_2; + NanDataPathScheduleUpdateInd nanDataPathScheduleUpdateInd; + + std::string GetInstanceName() { return GetParam(); } +}; + +/* + * Create: + * Ensures that an instance of the IWifiNanIface proxy object is + * successfully created. + */ +TEST_P(WifiNanIfaceHidlTest, Create) { + // The creation of a proxy object is tested as part of SetUp method. +} + +/* + * enableRequest_1_5InvalidArgs: validate that fails with invalid arguments + */ +TEST_P(WifiNanIfaceHidlTest, enableRequest_1_5InvalidArgs) { + uint16_t inputCmdId = 10; + callbackType = INVALID; + ::android::hardware::wifi::V1_4::NanEnableRequest nanEnableRequest = {}; + ::android::hardware::wifi::V1_5::NanConfigRequestSupplemental + nanConfigRequestSupp = {}; + const auto& halStatus = + HIDL_INVOKE(iwifiNanIface, enableRequest_1_5, inputCmdId, + nanEnableRequest, nanConfigRequestSupp); + if (halStatus.code != WifiStatusCode::ERROR_NOT_SUPPORTED) { + ASSERT_EQ(WifiStatusCode::SUCCESS, halStatus.code); + + // wait for a callback + ASSERT_EQ(std::cv_status::no_timeout, wait(NOTIFY_ENABLE_RESPONSE)); + ASSERT_EQ(NOTIFY_ENABLE_RESPONSE, callbackType); + ASSERT_EQ(id, inputCmdId); + ASSERT_EQ(status.status, NanStatusType::INVALID_ARGS); + } +} + +/* + * enableRequest_1_5ShimInvalidArgs: validate that fails with invalid arguments + * to the shim + */ +TEST_P(WifiNanIfaceHidlTest, enableRequest_1_5ShimInvalidArgs) { + uint16_t inputCmdId = 10; + ::android::hardware::wifi::V1_4::NanEnableRequest nanEnableRequest = {}; + nanEnableRequest.configParams.numberOfPublishServiceIdsInBeacon = + 128; // must be <= 127 + ::android::hardware::wifi::V1_5::NanConfigRequestSupplemental + nanConfigRequestSupp = {}; + const auto& halStatus = + HIDL_INVOKE(iwifiNanIface, enableRequest_1_5, inputCmdId, + nanEnableRequest, nanConfigRequestSupp); + if (halStatus.code != WifiStatusCode::ERROR_NOT_SUPPORTED) { + ASSERT_EQ(WifiStatusCode::ERROR_INVALID_ARGS, halStatus.code); + } +} + +/* + * configRequest_1_5InvalidArgs: validate that fails with invalid arguments + */ +TEST_P(WifiNanIfaceHidlTest, configRequest_1_5InvalidArgs) { + uint16_t inputCmdId = 10; + callbackType = INVALID; + ::android::hardware::wifi::V1_4::NanConfigRequest nanConfigRequest = {}; + ::android::hardware::wifi::V1_5::NanConfigRequestSupplemental + nanConfigRequestSupp = {}; + const auto& halStatus = + HIDL_INVOKE(iwifiNanIface, configRequest_1_5, inputCmdId, + nanConfigRequest, nanConfigRequestSupp); + + if (halStatus.code != WifiStatusCode::ERROR_NOT_SUPPORTED) { + ASSERT_EQ(WifiStatusCode::SUCCESS, halStatus.code); + + // wait for a callback + ASSERT_EQ(std::cv_status::no_timeout, wait(NOTIFY_CONFIG_RESPONSE)); + ASSERT_EQ(NOTIFY_CONFIG_RESPONSE, callbackType); + ASSERT_EQ(id, inputCmdId); + ASSERT_EQ(status.status, NanStatusType::INVALID_ARGS); + } +} + +/* + * configRequest_1_5ShimInvalidArgs: validate that fails with invalid arguments + * to the shim + */ +TEST_P(WifiNanIfaceHidlTest, configRequest_1_5ShimInvalidArgs) { + uint16_t inputCmdId = 10; + ::android::hardware::wifi::V1_4::NanConfigRequest nanConfigRequest = {}; + nanConfigRequest.numberOfPublishServiceIdsInBeacon = 128; // must be <= 127 + ::android::hardware::wifi::V1_5::NanConfigRequestSupplemental + nanConfigRequestSupp = {}; + const auto& halStatus = + HIDL_INVOKE(iwifiNanIface, configRequest_1_5, inputCmdId, + nanConfigRequest, nanConfigRequestSupp); + if (halStatus.code != WifiStatusCode::ERROR_NOT_SUPPORTED) { + ASSERT_EQ(WifiStatusCode::ERROR_INVALID_ARGS, halStatus.code); + } +} + +/* + * getCapabilitiesRequest: validate that returns capabilities. + */ +TEST_P(WifiNanIfaceHidlTest, getCapabilitiesRequest_1_5) { + uint16_t inputCmdId = 10; + callbackType = INVALID; + const auto& halStatus = + HIDL_INVOKE(iwifiNanIface, getCapabilitiesRequest_1_5, inputCmdId).code; + ASSERT_EQ(WifiStatusCode::SUCCESS, halStatus); + // wait for a callback + ASSERT_EQ(std::cv_status::no_timeout, + wait(NOTIFY_CAPABILITIES_RESPONSE_1_5)); + ASSERT_EQ(NOTIFY_CAPABILITIES_RESPONSE_1_5, callbackType); + ASSERT_EQ(id, inputCmdId); + + // check for reasonable capability values + EXPECT_GT(capabilities_1_5.V1_0.maxConcurrentClusters, (unsigned int)0); + EXPECT_GT(capabilities_1_5.V1_0.maxPublishes, (unsigned int)0); + EXPECT_GT(capabilities_1_5.V1_0.maxSubscribes, (unsigned int)0); + EXPECT_EQ(capabilities_1_5.V1_0.maxServiceNameLen, (unsigned int)255); + EXPECT_EQ(capabilities_1_5.V1_0.maxMatchFilterLen, (unsigned int)255); + EXPECT_GT(capabilities_1_5.V1_0.maxTotalMatchFilterLen, (unsigned int)255); + EXPECT_EQ(capabilities_1_5.V1_0.maxServiceSpecificInfoLen, + (unsigned int)255); + EXPECT_GE(capabilities_1_5.V1_0.maxExtendedServiceSpecificInfoLen, + (unsigned int)255); + EXPECT_GT(capabilities_1_5.V1_0.maxNdiInterfaces, (unsigned int)0); + EXPECT_GT(capabilities_1_5.V1_0.maxNdpSessions, (unsigned int)0); + EXPECT_GT(capabilities_1_5.V1_0.maxAppInfoLen, (unsigned int)0); + EXPECT_GT(capabilities_1_5.V1_0.maxQueuedTransmitFollowupMsgs, + (unsigned int)0); + EXPECT_GT(capabilities_1_5.V1_0.maxSubscribeInterfaceAddresses, + (unsigned int)0); + EXPECT_NE(capabilities_1_5.V1_0.supportedCipherSuites, (unsigned int)0); + EXPECT_TRUE(capabilities_1_5.instantCommunicationModeSupportFlag || + !capabilities_1_5.instantCommunicationModeSupportFlag); +} + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiNanIfaceHidlTest); +INSTANTIATE_TEST_SUITE_P( + PerInstance, WifiNanIfaceHidlTest, + testing::ValuesIn(android::hardware::getAllHalInstanceNames( + ::android::hardware::wifi::V1_5::IWifi::descriptor)), + android::hardware::PrintInstanceNameToString); diff --git a/wifi/1.5/vts/functional/wifi_sta_iface_hidl_test.cpp b/wifi/1.5/vts/functional/wifi_sta_iface_hidl_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..399307ecdc37522d9ce8d7e0f30a4bebcdf66f43 --- /dev/null +++ b/wifi/1.5/vts/functional/wifi_sta_iface_hidl_test.cpp @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Staache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include "wifi_hidl_call_util.h" +#include "wifi_hidl_test_utils.h" + +using ::android::sp; +using ::android::hardware::hidl_array; +using ::android::hardware::wifi::V1_0::WifiStatus; +using ::android::hardware::wifi::V1_0::WifiStatusCode; +using ::android::hardware::wifi::V1_5::IWifiChip; +using ::android::hardware::wifi::V1_5::IWifiStaIface; + +/** + * Fixture to use for all STA Iface HIDL interface tests. + */ +class WifiStaIfaceHidlTest : public ::testing::TestWithParam { + public: + virtual void SetUp() override { + // Make sure to start with a clean state + stopWifi(GetInstanceName()); + + wifi_sta_iface_ = + IWifiStaIface::castFrom(getWifiStaIface(GetInstanceName())); + ASSERT_NE(nullptr, wifi_sta_iface_.get()); + } + + virtual void TearDown() override { stopWifi(GetInstanceName()); } + + protected: + bool isCapabilitySupported(IWifiStaIface::StaIfaceCapabilityMask cap_mask) { + const auto& status_and_caps = + HIDL_INVOKE(wifi_sta_iface_, getCapabilities); + EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code); + return (status_and_caps.second & cap_mask) != 0; + } + + WifiStatusCode createStaIface(sp* sta_iface) { + sp wifi_chip = + IWifiChip::castFrom(getWifiChip(GetInstanceName())); + EXPECT_NE(nullptr, wifi_chip.get()); + const auto& status_and_iface = HIDL_INVOKE(wifi_chip, createStaIface); + *sta_iface = IWifiStaIface::castFrom(status_and_iface.second); + return status_and_iface.first.code; + } + + sp wifi_sta_iface_; + + private: + std::string GetInstanceName() { return GetParam(); } +}; + +/* + * GetLinkLayerStats_1_5 + * Ensures that calls to get link layer stats V1_5 will retrieve a non-empty + * StaLinkLayerStats after link layer stats collection is enabled. + */ +TEST_P(WifiStaIfaceHidlTest, GetLinkLayerStats_1_5) { + if (!isCapabilitySupported( + IWifiStaIface::StaIfaceCapabilityMask::LINK_LAYER_STATS)) { + // No-op if link layer stats is not supported. + return; + } + + // Enable link layer stats collection. + EXPECT_EQ(WifiStatusCode::SUCCESS, + HIDL_INVOKE(wifi_sta_iface_, enableLinkLayerStatsCollection, true) + .code); + // Retrieve link layer stats. + const auto& status_and_stats = + HIDL_INVOKE(wifi_sta_iface_, getLinkLayerStats_1_5); + EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_stats.first.code); + EXPECT_GT(status_and_stats.second.timeStampInMs, 0u); + // Try to create 2nd iface. If yes, it should fill in the duty cycle field. + sp iface; + auto status = createStaIface(&iface); + if (status == WifiStatusCode::SUCCESS) { + EXPECT_GT(status_and_stats.second.iface.timeSliceDutyCycleInPercent, + 0u); + } + // Disable link layer stats collection. + EXPECT_EQ( + WifiStatusCode::SUCCESS, + HIDL_INVOKE(wifi_sta_iface_, disableLinkLayerStatsCollection).code); +} +/** + * SetScanMode + */ +TEST_P(WifiStaIfaceHidlTest, SetScanMode) { + auto statusCode = + HIDL_INVOKE(wifi_sta_iface_, setScanMode, true).code; + EXPECT_TRUE(statusCode == WifiStatusCode::SUCCESS || + statusCode == WifiStatusCode::ERROR_NOT_SUPPORTED); + + statusCode = HIDL_INVOKE(wifi_sta_iface_, setScanMode, false).code; + EXPECT_TRUE(statusCode == WifiStatusCode::SUCCESS || + statusCode == WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiStaIfaceHidlTest); +INSTANTIATE_TEST_SUITE_P( + PerInstance, WifiStaIfaceHidlTest, + testing::ValuesIn(android::hardware::getAllHalInstanceNames( + ::android::hardware::wifi::V1_5::IWifi::descriptor)), + android::hardware::PrintInstanceNameToString); diff --git a/wifi/hostapd/1.0/vts/OWNERS b/wifi/hostapd/1.0/vts/OWNERS index 8bfb14882c8466954bd971a4603ab82e62077c61..cf81c798925338533dcb4d1968ea7de942b367f3 100644 --- a/wifi/hostapd/1.0/vts/OWNERS +++ b/wifi/hostapd/1.0/vts/OWNERS @@ -1,2 +1,2 @@ -rpius@google.com +arabawy@google.com etancohen@google.com diff --git a/wifi/hostapd/1.1/vts/OWNERS b/wifi/hostapd/1.1/vts/OWNERS index 8bfb14882c8466954bd971a4603ab82e62077c61..cf81c798925338533dcb4d1968ea7de942b367f3 100644 --- a/wifi/hostapd/1.1/vts/OWNERS +++ b/wifi/hostapd/1.1/vts/OWNERS @@ -1,2 +1,2 @@ -rpius@google.com +arabawy@google.com etancohen@google.com diff --git a/wifi/hostapd/1.1/vts/functional/Android.bp b/wifi/hostapd/1.1/vts/functional/Android.bp index 1695a381ea4b4f75d68287312088afea0d415661..999a6a7d3271adbd84e606629d32b30dcb3bc5a8 100644 --- a/wifi/hostapd/1.1/vts/functional/Android.bp +++ b/wifi/hostapd/1.1/vts/functional/Android.bp @@ -34,10 +34,15 @@ cc_test { "VtsHalWifiHostapdV1_0TargetTestUtil", "android.hardware.wifi.hostapd@1.0", "android.hardware.wifi.hostapd@1.1", + "android.hardware.wifi.hostapd@1.2", + "android.hardware.wifi.hostapd@1.3", "android.hardware.wifi@1.0", "libgmock", "libwifi-system", "libwifi-system-iface", ], - test_suites: ["general-tests", "vts"], + test_suites: [ + "general-tests", + "vts", + ], } diff --git a/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp b/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp index d823685dabd376fc3c927f9ce0943d2c7fb600cf..32bbe722f3395444771ee1fadd0cdb68a17e93f7 100644 --- a/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp +++ b/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp @@ -23,6 +23,7 @@ #include #include +#include #include "hostapd_hidl_call_util.h" #include "hostapd_hidl_test_utils.h" @@ -43,6 +44,7 @@ constexpr unsigned char kNwSsid[] = {'t', 'e', 's', 't', '1', constexpr char kNwPassphrase[] = "test12345"; constexpr int kIfaceChannel = 6; constexpr int kIfaceInvalidChannel = 567; + } // namespace class HostapdHidlTest @@ -173,10 +175,17 @@ class IfaceCallback : public IHostapdCallback { } }; +bool is_1_3(const sp& hostapd) { + sp<::android::hardware::wifi::hostapd::V1_3::IHostapd> hostapd_1_3 = + ::android::hardware::wifi::hostapd::V1_3::IHostapd::castFrom(hostapd); + return hostapd_1_3.get() != nullptr; +} + /* * RegisterCallback */ TEST_P(HostapdHidlTest, registerCallback) { + if (is_1_3(hostapd_)) GTEST_SKIP() << "Ignore since current HIDL over 1.3"; hostapd_->registerCallback( new IfaceCallback(), [](const HostapdStatus& status) { EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); diff --git a/wifi/hostapd/1.2/vts/OWNERS b/wifi/hostapd/1.2/vts/OWNERS index 8bfb14882c8466954bd971a4603ab82e62077c61..cf81c798925338533dcb4d1968ea7de942b367f3 100644 --- a/wifi/hostapd/1.2/vts/OWNERS +++ b/wifi/hostapd/1.2/vts/OWNERS @@ -1,2 +1,2 @@ -rpius@google.com +arabawy@google.com etancohen@google.com diff --git a/wifi/hostapd/1.2/vts/functional/Android.bp b/wifi/hostapd/1.2/vts/functional/Android.bp index f993e9e486f96d579bf00f756675e7ec9d71b302..9609da5d41686e036c3184f2b9b24e34762e1a46 100644 --- a/wifi/hostapd/1.2/vts/functional/Android.bp +++ b/wifi/hostapd/1.2/vts/functional/Android.bp @@ -34,11 +34,15 @@ cc_test { "VtsHalWifiHostapdV1_0TargetTestUtil", "android.hardware.wifi.hostapd@1.0", "android.hardware.wifi.hostapd@1.1", - "android.hardware.wifi.hostapd@1.2", + "android.hardware.wifi.hostapd@1.2", + "android.hardware.wifi.hostapd@1.3", "android.hardware.wifi@1.0", "libgmock", "libwifi-system", "libwifi-system-iface", ], - test_suites: ["general-tests", "vts"], + test_suites: [ + "general-tests", + "vts", + ], } diff --git a/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp b/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp index 99784a469ed5ea96a32ba4809f2252f8ae92eaf6..c40c5824061842108d4587ff8ea298dfe3b14309 100644 --- a/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp +++ b/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp @@ -25,6 +25,7 @@ #include #include +#include #include "hostapd_hidl_call_util.h" #include "hostapd_hidl_test_utils.h" @@ -216,12 +217,20 @@ class HostapdHidlTest std::string hostapd_instance_name_; }; +bool is_1_3(const sp& hostapd) { + sp<::android::hardware::wifi::hostapd::V1_3::IHostapd> hostapd_1_3 = + ::android::hardware::wifi::hostapd::V1_3::IHostapd::castFrom(hostapd); + return hostapd_1_3.get() != nullptr; +} + /** * Adds an access point with PSK network config & ACS enabled. * Access point creation should pass. */ TEST_P(HostapdHidlTest, AddPskAccessPointWithAcs) { if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support"; + if (is_1_3(hostapd_)) + GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3"; auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithAcs(), getPskNwParams()); EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); @@ -233,6 +242,8 @@ TEST_P(HostapdHidlTest, AddPskAccessPointWithAcs) { */ TEST_P(HostapdHidlTest, AddPskAccessPointWithAcsAndFreqRange) { if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support"; + if (is_1_3(hostapd_)) + GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3"; auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithAcsAndFreqRange(), getPskNwParams()); @@ -245,6 +256,8 @@ TEST_P(HostapdHidlTest, AddPskAccessPointWithAcsAndFreqRange) { */ TEST_P(HostapdHidlTest, AddPskAccessPointWithAcsAndInvalidFreqRange) { if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support"; + if (is_1_3(hostapd_)) + GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3"; auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithAcsAndInvalidFreqRange(), getPskNwParams()); @@ -257,6 +270,8 @@ TEST_P(HostapdHidlTest, AddPskAccessPointWithAcsAndInvalidFreqRange) { */ TEST_P(HostapdHidlTest, AddOpenAccessPointWithAcs) { if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support"; + if (is_1_3(hostapd_)) + GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3"; auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithAcs(), getOpenNwParams()); EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); @@ -267,6 +282,8 @@ TEST_P(HostapdHidlTest, AddOpenAccessPointWithAcs) { * Access point creation should pass. */ TEST_P(HostapdHidlTest, AddPskAccessPointWithoutAcs) { + if (is_1_3(hostapd_)) + GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3"; auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithoutAcs(), getPskNwParams()); EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); @@ -277,6 +294,8 @@ TEST_P(HostapdHidlTest, AddPskAccessPointWithoutAcs) { * Access point creation should pass. */ TEST_P(HostapdHidlTest, AddOpenAccessPointWithoutAcs) { + if (is_1_3(hostapd_)) + GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3"; auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithoutAcs(), getOpenNwParams()); EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); @@ -288,6 +307,8 @@ TEST_P(HostapdHidlTest, AddOpenAccessPointWithoutAcs) { */ TEST_P(HostapdHidlTest, AddSaeTransitionAccessPointWithoutAcs) { if (!isWpa3SaeSupport_) GTEST_SKIP() << "Missing SAE support"; + if (is_1_3(hostapd_)) + GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3"; auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithoutAcs(), getSaeTransitionNwParams()); @@ -300,6 +321,8 @@ TEST_P(HostapdHidlTest, AddSaeTransitionAccessPointWithoutAcs) { */ TEST_P(HostapdHidlTest, AddSAEAccessPointWithoutAcs) { if (!isWpa3SaeSupport_) GTEST_SKIP() << "Missing SAE support"; + if (is_1_3(hostapd_)) + GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3"; auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithoutAcs(), getSaeNwParams()); EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); @@ -311,6 +334,8 @@ TEST_P(HostapdHidlTest, AddSAEAccessPointWithoutAcs) { */ TEST_P(HostapdHidlTest, RemoveAccessPointWithAcs) { if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support"; + if (is_1_3(hostapd_)) + GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3"; auto status_1_2 = HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithAcs(), getPskNwParams()); EXPECT_EQ(HostapdStatusCode::SUCCESS, status_1_2.code); @@ -326,6 +351,8 @@ TEST_P(HostapdHidlTest, RemoveAccessPointWithAcs) { * Access point creation & removal should pass. */ TEST_P(HostapdHidlTest, RemoveAccessPointWithoutAcs) { + if (is_1_3(hostapd_)) + GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3"; auto status_1_2 = HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithoutAcs(), getPskNwParams()); EXPECT_EQ(HostapdStatusCode::SUCCESS, status_1_2.code); @@ -341,6 +368,8 @@ TEST_P(HostapdHidlTest, RemoveAccessPointWithoutAcs) { * Access point creation should fail. */ TEST_P(HostapdHidlTest, AddPskAccessPointWithInvalidChannel) { + if (is_1_3(hostapd_)) + GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3"; auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithInvalidChannel(), getPskNwParams()); @@ -352,6 +381,8 @@ TEST_P(HostapdHidlTest, AddPskAccessPointWithInvalidChannel) { * Access point creation should fail. */ TEST_P(HostapdHidlTest, AddInvalidPskAccessPointWithoutAcs) { + if (is_1_3(hostapd_)) + GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3"; auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithoutAcs(), getInvalidPskNwParams()); @@ -364,6 +395,8 @@ TEST_P(HostapdHidlTest, AddInvalidPskAccessPointWithoutAcs) { */ TEST_P(HostapdHidlTest, AddInvalidSaeTransitionAccessPointWithoutAcs) { if (!isWpa3SaeSupport_) GTEST_SKIP() << "Missing SAE support"; + if (is_1_3(hostapd_)) + GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3"; auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithoutAcs(), getInvalidSaeTransitionNwParams()); @@ -376,6 +409,8 @@ TEST_P(HostapdHidlTest, AddInvalidSaeTransitionAccessPointWithoutAcs) { */ TEST_P(HostapdHidlTest, AddInvalidSaeAccessPointWithoutAcs) { if (!isWpa3SaeSupport_) GTEST_SKIP() << "Missing SAE support"; + if (is_1_3(hostapd_)) + GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3"; auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithoutAcs(), getInvalidSaeNwParams()); @@ -398,6 +433,8 @@ TEST_P(HostapdHidlTest, DisconnectClientWhenIfaceNotAvailable) { * when hotspot interface available. */ TEST_P(HostapdHidlTest, DisconnectClientWhenIfacAvailable) { + if (is_1_3(hostapd_)) + GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3"; auto status_1_2 = HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithoutAcs(), getOpenNwParams()); diff --git a/wifi/hostapd/1.3/Android.bp b/wifi/hostapd/1.3/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..f75b5e25da218282dc4fa51a461b47d381e94286 --- /dev/null +++ b/wifi/hostapd/1.3/Android.bp @@ -0,0 +1,32 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +hidl_interface { + name: "android.hardware.wifi.hostapd@1.3", + root: "android.hardware", + srcs: [ + "types.hal", + "IHostapd.hal", + "IHostapdCallback.hal", + ], + interfaces: [ + "android.hardware.wifi.hostapd@1.0", + "android.hardware.wifi.hostapd@1.1", + "android.hardware.wifi.hostapd@1.2", + "android.hardware.wifi.supplicant@1.0", + "android.hidl.base@1.0", + ], + gen_java: true, + apex_available: [ + "//apex_available:platform", + "com.android.wifi", + ], +} diff --git a/wifi/hostapd/1.3/IHostapd.hal b/wifi/hostapd/1.3/IHostapd.hal new file mode 100644 index 0000000000000000000000000000000000000000..70de7c2ece5687a14180c657daa41c73bf639f57 --- /dev/null +++ b/wifi/hostapd/1.3/IHostapd.hal @@ -0,0 +1,165 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.wifi.hostapd@1.3; + +import @1.2::HostapdStatus; +import @1.2::IHostapd.BandMask; +import @1.2::IHostapd.HwModeParams; +import @1.2::IHostapd.IfaceParams; +import @1.2::IHostapd.NetworkParams; +import @1.2::IHostapd; +import IHostapdCallback; + +/** + * Top-level object for managing SoftAPs. + */ +interface IHostapd extends @1.2::IHostapd { + + enum BandMask : @1.2::IHostapd.BandMask { + /** + * 60 GHz band. + */ + BAND_60_GHZ = 1 << 3, + }; + + /** + * Parameters to control the HW mode for the interface. + */ + struct HwModeParams { + /** + * Baseline information as defined in HAL 1.2. + */ + @1.2::IHostapd.HwModeParams V1_2; + + /** + * Enable EDMG (802.11ay), this option is only allowed for the 60GHz band. + */ + bool enableEdmg; + }; + + /** + * Parameters to control the channel selection for the interface. + */ + struct ChannelParams { + /** + * Baseline information as defined in HAL 1.2. + * + * Includes bandMask and acsChannelFreqRangesMhz + */ + @1.2::IHostapd.ChannelParams V1_2; + + /** + * Whether to enable ACS (Automatic Channel Selection) or not. + * The channel can be selected automatically at run time by setting + * this flag, which must enable the ACS survey based algorithm. + * + * Note: It is used instead of V1_0::ChannelParams.enableAcs inside + * V1_3::IfaceParams.V1_2.V1_1.V1_0. + */ + bool enableAcs; + + /** + * Channel number (IEEE 802.11) to use for the interface. + * If ACS is enabled, this field is ignored. + * + * If |enableEdmg| is true, the channel must be set. Refer to + * P802.11ay_D4.0 29.3.4. + * + * Note: It is used instead of V1_0::ChannelParams.channel inside + * V1_3::IfaceParams.V1_2.V1_1.V1_0. + */ + uint32_t channel; + + /** + * Band to use for the SoftAp operations. + * Note: It is used instead of V1_2::ChannelParams.bandMask inside + * V1_3::IfaceParams.V1_2.channelParams + */ + bitfield bandMask; + }; + + /** + * Parameters to use for setting up the dual access point interfaces. + */ + struct IfaceParams { + /** + * Baseline information as defined in HAL 1.2. + */ + @1.2::IHostapd.IfaceParams V1_2; + + /** + * Additional Hw mode params for the interface + */ + HwModeParams hwModeParams; + + /** + * The list of the channel params for the dual interfaces. + */ + vec channelParamsList; + }; + + /** + * Parameters to use for setting up the access point network. + */ + struct NetworkParams { + /** + * Baseline information as defined in HAL 1.2. + */ + @1.2::IHostapd.NetworkParams V1_2; + + /** + * Enable the interworking service and set access network type to + * CHARGEABLE_PUBLIC_NETWORK when set to true. + */ + bool isMetered; + }; + + /** + * Adds a new access point for hostapd to control. + * + * This should trigger the setup of an access point with the specified + * interface and network params. + * + * @param ifaceParams AccessPoint Params for the access point. + * @param nwParams Network Params for the access point. + * @return status Status of the operation. + * Possible status codes: + * |HostapdStatusCode.SUCCESS|, + * |HostapdStatusCode.FAILURE_ARGS_INVALID|, + * |HostapdStatusCode.FAILURE_UNKNOWN|, + * |HostapdStatusCode.FAILURE_IFACE_EXISTS| + */ + addAccessPoint_1_3(IfaceParams ifaceParams, NetworkParams nwParams) + generates (HostapdStatus status); + + /** + * Register for callbacks from the hostapd service. + * + * These callbacks are invoked for global events that are not specific + * to any interface or network. Registration of multiple callback + * objects is supported. These objects must be deleted when the corresponding + * client process is dead. + * + * @param callback An instance of the |IHostapdCallback| HIDL interface + * object. + * @return status Status of the operation. + * Possible status codes: + * |HostapdStatusCode.SUCCESS|, + * |HostapdStatusCode.FAILURE_UNKNOWN| + */ + registerCallback_1_3(IHostapdCallback callback) generates (HostapdStatus status); +}; diff --git a/wifi/hostapd/1.3/IHostapdCallback.hal b/wifi/hostapd/1.3/IHostapdCallback.hal new file mode 100644 index 0000000000000000000000000000000000000000..32083669d214f48bffda0631d407b69affe409de --- /dev/null +++ b/wifi/hostapd/1.3/IHostapdCallback.hal @@ -0,0 +1,61 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.wifi.hostapd@1.3; + +import @1.1::IHostapdCallback; +import @1.2::MacAddress; +import Bandwidth; +import Generation; + +/** + * Top-level callback object for managing SoftAPs. + */ +interface IHostapdCallback extends @1.1::IHostapdCallback { + /** + * Invoked when information changes for one of the AP instances. + * + * @param ifaceName Name of the interface which was added via + * |IHostapd.addAccessPoint|. + * @param apIfaceInstance The identity of the AP instance. The interface + * will have two instances (e.q. 2.4 Ghz AP and 5 GHz AP) in dual AP mode. + * The apIfaceInstance can be used to identify which instance the callback + * is from. + * Note: The apIfaceInstance must be same as ifaceName in single AP mode. + * @param freqMhz The operational frequency of the AP in Mhz. + * @param bandwidth The operational bandwidth of the AP. + * @param generation The operational mode of the AP (e.g. 11ac, 11ax). + * @param apIfaceInstanceMacAddress MAC Address of the apIfaceInstance. + */ + oneway onApInstanceInfoChanged(string ifaceName, string apIfaceInstance, uint32_t freqMhz, + Bandwidth bandwidth, Generation generation, MacAddress apIfaceInstanceMacAddress); + + /** + * Invoked when a client connects/disconnects from the hotspot. + * + * @param ifaceName Name of the interface which was added via + * |IHostapd.addAccessPoint|. + * @param apIfaceInstance The identity of the AP instance. The interface + * will have two instances in dual AP mode. The apIfaceInstance can be used + * to identify which instance the callback is from. + * Note: The apIfaceInstance must be same as ifaceName in single AP mode. + * @param clientAddress MAC Address of hotspot client. + * @param isConnected true when client connected, false when client + * disconnected. + */ + oneway onConnectedClientsChanged(string ifaceName, string apIfaceInstance, + MacAddress clientAddress, bool isConnected); +}; diff --git a/wifi/hostapd/1.3/types.hal b/wifi/hostapd/1.3/types.hal new file mode 100644 index 0000000000000000000000000000000000000000..2230da86099a4dddecbce16b59630e4bd5acb0f9 --- /dev/null +++ b/wifi/hostapd/1.3/types.hal @@ -0,0 +1,55 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.wifi.hostapd@1.3; + +/** + * The wifi operational mode of the AP. + * It depends on hw mode and HT/VHT capabilities in hostapd. + * + * WIFI_STANDARD_LEGACY = (hw_mode is HOSTAPD_MODE_IEEE80211B) or + * (hw_mode is HOSTAPD_MODE_IEEE80211G and HT is 0). + * WIFI_STANDARD_11N = [hw_mode is HOSTAPD_MODE_IEEE80211G and (HT is 1 or HT40 is 1)] or + * [hw_mode is HOSTAPD_MODE_IEEE80211A and VHT is 0]. + * WIFI_STANDARD_11AC = hw_mode is HOSTAPD_MODE_IEEE80211A and VHT is 1. + * WIFI_STANDARD_11AX = hw_mode is HOSTAPD_MODE_IEEE80211A and HE supported. + * WIFI_STANDARD_11AD = hw_mode is HOSTAPD_MODE_IEEE80211AD. + */ +enum Generation : uint32_t { + WIFI_STANDARD_UNKNOWN = -1, + WIFI_STANDARD_LEGACY = 0, + WIFI_STANDARD_11N = 1, + WIFI_STANDARD_11AC = 2, + WIFI_STANDARD_11AX = 3, + WIFI_STANDARD_11AD = 4, +}; + +/** + * The channel bandwidth of the AP. + */ +enum Bandwidth : uint32_t { + WIFI_BANDWIDTH_INVALID = 0, + WIFI_BANDWIDTH_20_NOHT = 1, + WIFI_BANDWIDTH_20 = 2, + WIFI_BANDWIDTH_40 = 3, + WIFI_BANDWIDTH_80 = 4, + WIFI_BANDWIDTH_80P80 = 5, + WIFI_BANDWIDTH_160 = 6, + WIFI_BANDWIDTH_2160 = 7, + WIFI_BANDWIDTH_4320 = 8, + WIFI_BANDWIDTH_6480 = 9, + WIFI_BANDWIDTH_8640 = 10, +}; diff --git a/wifi/hostapd/1.3/vts/OWNERS b/wifi/hostapd/1.3/vts/OWNERS new file mode 100644 index 0000000000000000000000000000000000000000..cf81c798925338533dcb4d1968ea7de942b367f3 --- /dev/null +++ b/wifi/hostapd/1.3/vts/OWNERS @@ -0,0 +1,2 @@ +arabawy@google.com +etancohen@google.com diff --git a/wifi/hostapd/1.3/vts/functional/Android.bp b/wifi/hostapd/1.3/vts/functional/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..6eceadf7745fcc448c4ceff11f23bb1aa043fbd4 --- /dev/null +++ b/wifi/hostapd/1.3/vts/functional/Android.bp @@ -0,0 +1,54 @@ +// +// Copyright (C) 2020 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_test { + name: "VtsHalWifiHostapdV1_3TargetTest", + defaults: ["VtsHalTargetTestDefaults"], + srcs: [ + "hostapd_hidl_test.cpp", + ], + static_libs: [ + "VtsHalWifiV1_0TargetTestUtil", + "VtsHalWifiV1_5TargetTestUtil", + "VtsHalWifiHostapdV1_0TargetTestUtil", + "android.hardware.wifi.hostapd@1.0", + "android.hardware.wifi.hostapd@1.1", + "android.hardware.wifi.hostapd@1.2", + "android.hardware.wifi.hostapd@1.3", + "android.hardware.wifi@1.0", + "android.hardware.wifi@1.1", + "android.hardware.wifi@1.2", + "android.hardware.wifi@1.3", + "android.hardware.wifi@1.4", + "android.hardware.wifi@1.5", + "libgmock", + "libwifi-system", + "libwifi-system-iface", + ], + test_suites: [ + "general-tests", + "vts", + ], +} diff --git a/wifi/hostapd/1.3/vts/functional/hostapd_hidl_test.cpp b/wifi/hostapd/1.3/vts/functional/hostapd_hidl_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fe9a183d569cbd6fce9c8fb535bb27fca514c5d1 --- /dev/null +++ b/wifi/hostapd/1.3/vts/functional/hostapd_hidl_test.cpp @@ -0,0 +1,551 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include + +#include +#include +#include + +#include +#include + +#include "hostapd_hidl_call_util.h" +#include "hostapd_hidl_test_utils.h" +#include "wifi_hidl_test_utils_1_5.h" + +using ::android::sp; +using ::android::hardware::hidl_string; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::wifi::hostapd::V1_2::DebugLevel; +using ::android::hardware::wifi::hostapd::V1_2::HostapdStatusCode; +using ::android::hardware::wifi::hostapd::V1_2::Ieee80211ReasonCode; +using ::android::hardware::wifi::hostapd::V1_3::IHostapd; +using ::android::hardware::wifi::V1_0::IWifi; +using ::android::hardware::wifi::V1_0::WifiStatusCode; +using ::android::hardware::wifi::V1_5::IWifiApIface; + +namespace { +constexpr unsigned char kNwSsid[] = {'t', 'e', 's', 't', '1', + '2', '3', '4', '5'}; +constexpr char kNwPassphrase[] = "test12345"; +constexpr char kInvalidMaxPskNwPassphrase[] = + "0123456789012345678901234567890123456789012345678901234567890123456789"; +constexpr char kInvalidMinPskNwPassphrase[] = "test"; +constexpr int kIfaceChannel = 6; +constexpr int kIfaceInvalidChannel = 567; +constexpr uint8_t kTestZeroMacAddr[] = {[0 ... 5] = 0x0}; +constexpr Ieee80211ReasonCode kTestDisconnectReasonCode = + Ieee80211ReasonCode::WLAN_REASON_UNSPECIFIED; +} // namespace + +class HostapdHidlTest + : public ::testing::TestWithParam> { + public: + virtual void SetUp() override { + wifi_instance_name_ = std::get<0>(GetParam()); + hostapd_instance_name_ = std::get<1>(GetParam()); + stopSupplicantIfNeeded(wifi_instance_name_); + startHostapdAndWaitForHidlService(wifi_instance_name_, + hostapd_instance_name_); + hostapd_ = IHostapd::getService(hostapd_instance_name_); + ASSERT_NE(hostapd_.get(), nullptr); + HIDL_INVOKE(hostapd_, setDebugParams, DebugLevel::EXCESSIVE); + isAcsSupport_ = testing::checkSubstringInCommandOutput( + "/system/bin/cmd wifi get-softap-supported-features", + "wifi_softap_acs_supported"); + isWpa3SaeSupport_ = testing::checkSubstringInCommandOutput( + "/system/bin/cmd wifi get-softap-supported-features", + "wifi_softap_wpa3_sae_supported"); + isBridgedSupport_ = testing::checkSubstringInCommandOutput( + "/system/bin/cmd wifi get-softap-supported-features", + "wifi_softap_bridged_ap_supported"); + } + + virtual void TearDown() override { + HIDL_INVOKE_VOID_WITHOUT_ARGUMENTS(hostapd_, terminate); + // Wait 3 seconds to allow terminate processing before kill hostapd. + sleep(3); + stopHostapd(wifi_instance_name_); + } + + protected: + bool isWpa3SaeSupport_ = false; + bool isAcsSupport_ = false; + bool isBridgedSupport_ = false; + + std::string setupApIfaceAndGetName(bool isBridged) { + sp wifi_ap_iface; + if (isBridged) { + wifi_ap_iface = getBridgedWifiApIface_1_5(wifi_instance_name_); + } else { + wifi_ap_iface = getWifiApIface_1_5(wifi_instance_name_); + } + EXPECT_NE(nullptr, wifi_ap_iface.get()); + + const auto& status_and_name = HIDL_INVOKE(wifi_ap_iface, getName); + EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_name.first.code); + return status_and_name.second; + } + + IHostapd::IfaceParams getIfaceParamsWithoutAcs(std::string iface_name) { + ::android::hardware::wifi::hostapd::V1_0::IHostapd::IfaceParams + iface_params; + ::android::hardware::wifi::hostapd::V1_1::IHostapd::IfaceParams + iface_params_1_1; + ::android::hardware::wifi::hostapd::V1_2::IHostapd::IfaceParams + iface_params_1_2; + IHostapd::IfaceParams iface_params_1_3; + + std::vector< + ::android::hardware::wifi::hostapd::V1_3::IHostapd::ChannelParams> + vec_channelParams; + + ::android::hardware::wifi::hostapd::V1_3::IHostapd::ChannelParams + channelParams_1_3; + + iface_params.ifaceName = iface_name; + iface_params.hwModeParams.enable80211N = true; + iface_params.hwModeParams.enable80211AC = false; + iface_params.channelParams.enableAcs = false; + iface_params.channelParams.acsShouldExcludeDfs = false; + iface_params.channelParams.channel = kIfaceChannel; + iface_params_1_1.V1_0 = iface_params; + iface_params_1_2.V1_1 = iface_params_1_1; + // Newly added attributes in V1_2 + iface_params_1_2.hwModeParams.enable80211AX = false; + iface_params_1_2.hwModeParams.enable6GhzBand = false; + iface_params_1_2.channelParams.bandMask = 0; + iface_params_1_2.channelParams.bandMask |= + IHostapd::BandMask::BAND_2_GHZ; + + // Newly added attributes in V1_3 + channelParams_1_3.channel = iface_params.channelParams.channel; + channelParams_1_3.enableAcs = iface_params.channelParams.enableAcs; + channelParams_1_3.bandMask = iface_params_1_2.channelParams.bandMask; + channelParams_1_3.V1_2 = iface_params_1_2.channelParams; + + vec_channelParams.push_back(channelParams_1_3); + iface_params_1_3.V1_2 = iface_params_1_2; + iface_params_1_3.channelParamsList = vec_channelParams; + return iface_params_1_3; + } + + IHostapd::IfaceParams getIfaceParamsWithBridgedModeACS( + std::string iface_name) { + // First get the settings for WithoutAcs and then make changes + IHostapd::IfaceParams iface_params_1_3 = + getIfaceParamsWithoutAcs(iface_name); + iface_params_1_3.V1_2.V1_1.V1_0.channelParams.enableAcs = true; + iface_params_1_3.V1_2.V1_1.V1_0.channelParams.acsShouldExcludeDfs = + true; + + std::vector< + ::android::hardware::wifi::hostapd::V1_3::IHostapd::ChannelParams> + vec_channelParams; + + vec_channelParams.push_back(iface_params_1_3.channelParamsList[0]); + + ::android::hardware::wifi::hostapd::V1_3::IHostapd::ChannelParams + second_channelParams_1_3; + second_channelParams_1_3.channel = 0; + second_channelParams_1_3.enableAcs = true; + second_channelParams_1_3.bandMask = 0; + second_channelParams_1_3.bandMask |= IHostapd::BandMask::BAND_5_GHZ; + second_channelParams_1_3.V1_2 = iface_params_1_3.V1_2.channelParams; + second_channelParams_1_3.V1_2.bandMask = 0; + second_channelParams_1_3.V1_2.bandMask |= + IHostapd::BandMask::BAND_5_GHZ; + vec_channelParams.push_back(second_channelParams_1_3); + + iface_params_1_3.channelParamsList = vec_channelParams; + return iface_params_1_3; + } + + IHostapd::IfaceParams getIfaceParamsWithAcs(std::string iface_name) { + // First get the settings for WithoutAcs and then make changes + IHostapd::IfaceParams iface_params_1_3 = + getIfaceParamsWithoutAcs(iface_name); + iface_params_1_3.V1_2.V1_1.V1_0.channelParams.enableAcs = true; + iface_params_1_3.V1_2.V1_1.V1_0.channelParams.acsShouldExcludeDfs = + true; + iface_params_1_3.V1_2.V1_1.V1_0.channelParams.channel = 0; + iface_params_1_3.V1_2.channelParams.bandMask |= + IHostapd::BandMask::BAND_5_GHZ; + iface_params_1_3.channelParamsList[0].channel = + iface_params_1_3.V1_2.V1_1.V1_0.channelParams.channel; + iface_params_1_3.channelParamsList[0].enableAcs = + iface_params_1_3.V1_2.V1_1.V1_0.channelParams.enableAcs; + iface_params_1_3.channelParamsList[0].V1_2 = + iface_params_1_3.V1_2.channelParams; + iface_params_1_3.channelParamsList[0].bandMask = + iface_params_1_3.V1_2.channelParams.bandMask; + return iface_params_1_3; + } + + IHostapd::IfaceParams getIfaceParamsWithAcsAndFreqRange( + std::string iface_name) { + IHostapd::IfaceParams iface_params_1_3 = + getIfaceParamsWithAcs(iface_name); + ::android::hardware::wifi::hostapd::V1_2::IHostapd::AcsFrequencyRange + acsFrequencyRange; + acsFrequencyRange.start = 2412; + acsFrequencyRange.end = 2462; + std::vector<::android::hardware::wifi::hostapd::V1_2::IHostapd:: + AcsFrequencyRange> + vec_acsFrequencyRange; + vec_acsFrequencyRange.push_back(acsFrequencyRange); + iface_params_1_3.V1_2.channelParams.acsChannelFreqRangesMhz = + vec_acsFrequencyRange; + iface_params_1_3.channelParamsList[0].V1_2 = + iface_params_1_3.V1_2.channelParams; + return iface_params_1_3; + } + + IHostapd::IfaceParams getIfaceParamsWithAcsAndInvalidFreqRange( + std::string iface_name) { + IHostapd::IfaceParams iface_params_1_3 = + getIfaceParamsWithAcsAndFreqRange(iface_name); + iface_params_1_3.V1_2.channelParams.acsChannelFreqRangesMhz[0].start = + 222; + iface_params_1_3.V1_2.channelParams.acsChannelFreqRangesMhz[0].end = + 999; + iface_params_1_3.channelParamsList[0].V1_2 = + iface_params_1_3.V1_2.channelParams; + return iface_params_1_3; + } + + IHostapd::NetworkParams getOpenNwParams() { + IHostapd::NetworkParams nw_params_1_3; + ::android::hardware::wifi::hostapd::V1_2::IHostapd::NetworkParams + nw_params_1_2; + ::android::hardware::wifi::hostapd::V1_0::IHostapd::NetworkParams + nw_params_1_0; + nw_params_1_0.ssid = + std::vector(kNwSsid, kNwSsid + sizeof(kNwSsid)); + nw_params_1_0.isHidden = false; + nw_params_1_2.V1_0 = nw_params_1_0; + nw_params_1_2.encryptionType = IHostapd::EncryptionType::NONE; + nw_params_1_3.V1_2 = nw_params_1_2; + nw_params_1_3.isMetered = true; + return nw_params_1_3; + } + + IHostapd::NetworkParams getPskNwParamsWithNonMetered() { + IHostapd::NetworkParams nw_params_1_3 = getOpenNwParams(); + nw_params_1_3.V1_2.encryptionType = IHostapd::EncryptionType::WPA2; + nw_params_1_3.V1_2.passphrase = kNwPassphrase; + nw_params_1_3.isMetered = false; + return nw_params_1_3; + } + + IHostapd::NetworkParams getPskNwParams() { + IHostapd::NetworkParams nw_params_1_3 = getOpenNwParams(); + nw_params_1_3.V1_2.encryptionType = IHostapd::EncryptionType::WPA2; + nw_params_1_3.V1_2.passphrase = kNwPassphrase; + return nw_params_1_3; + } + + IHostapd::NetworkParams getInvalidPskNwParams() { + IHostapd::NetworkParams nw_params_1_3 = getOpenNwParams(); + nw_params_1_3.V1_2.encryptionType = IHostapd::EncryptionType::WPA2; + nw_params_1_3.V1_2.passphrase = kInvalidMaxPskNwPassphrase; + + return nw_params_1_3; + } + + IHostapd::NetworkParams getSaeTransitionNwParams() { + IHostapd::NetworkParams nw_params_1_3 = getOpenNwParams(); + nw_params_1_3.V1_2.encryptionType = + IHostapd::EncryptionType::WPA3_SAE_TRANSITION; + nw_params_1_3.V1_2.passphrase = kNwPassphrase; + return nw_params_1_3; + } + + IHostapd::NetworkParams getInvalidSaeTransitionNwParams() { + IHostapd::NetworkParams nw_params_1_3 = getOpenNwParams(); + nw_params_1_3.V1_2.encryptionType = IHostapd::EncryptionType::WPA2; + nw_params_1_3.V1_2.passphrase = kInvalidMinPskNwPassphrase; + return nw_params_1_3; + } + + IHostapd::NetworkParams getSaeNwParams() { + IHostapd::NetworkParams nw_params_1_3 = getOpenNwParams(); + nw_params_1_3.V1_2.encryptionType = IHostapd::EncryptionType::WPA3_SAE; + nw_params_1_3.V1_2.passphrase = kNwPassphrase; + return nw_params_1_3; + } + + IHostapd::NetworkParams getInvalidSaeNwParams() { + IHostapd::NetworkParams nw_params_1_3 = getOpenNwParams(); + nw_params_1_3.V1_2.encryptionType = IHostapd::EncryptionType::WPA3_SAE; + nw_params_1_3.V1_2.passphrase = ""; + return nw_params_1_3; + } + + IHostapd::IfaceParams getIfaceParamsWithInvalidChannel( + std::string iface_name) { + IHostapd::IfaceParams iface_params_1_3 = + getIfaceParamsWithoutAcs(iface_name); + iface_params_1_3.V1_2.V1_1.V1_0.channelParams.channel = + kIfaceInvalidChannel; + iface_params_1_3.channelParamsList[0].channel = + iface_params_1_3.V1_2.V1_1.V1_0.channelParams.channel; + return iface_params_1_3; + } + + // IHostapd object used for all tests in this fixture. + sp hostapd_; + std::string wifi_instance_name_; + std::string hostapd_instance_name_; +}; + +/** + * Adds an access point with PSK network config & ACS enabled. + * Access point creation should pass. + */ +TEST_P(HostapdHidlTest, AddPskAccessPointWithAcs) { + if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support"; + std::string ifname = setupApIfaceAndGetName(false); + auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_3, + getIfaceParamsWithAcs(ifname), getPskNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with PSK network config, ACS enabled & frequency Range. + * Access point creation should pass. + */ +TEST_P(HostapdHidlTest, AddPskAccessPointWithAcsAndFreqRange) { + if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support"; + std::string ifname = setupApIfaceAndGetName(false); + auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_3, + getIfaceParamsWithAcsAndFreqRange(ifname), + getPskNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with invalid channel range. + * Access point creation should fail. + */ +TEST_P(HostapdHidlTest, AddPskAccessPointWithAcsAndInvalidFreqRange) { + if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support"; + std::string ifname = setupApIfaceAndGetName(false); + auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_3, + getIfaceParamsWithAcsAndInvalidFreqRange(ifname), + getPskNwParams()); + EXPECT_NE(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with Open network config & ACS enabled. + * Access point creation should pass. + */ +TEST_P(HostapdHidlTest, AddOpenAccessPointWithAcs) { + if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support"; + std::string ifname = setupApIfaceAndGetName(false); + auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_3, + getIfaceParamsWithAcs(ifname), getOpenNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with PSK network config & ACS disabled. + * Access point creation should pass. + */ +TEST_P(HostapdHidlTest, AddPskAccessPointWithoutAcs) { + std::string ifname = setupApIfaceAndGetName(false); + auto status = + HIDL_INVOKE(hostapd_, addAccessPoint_1_3, + getIfaceParamsWithoutAcs(ifname), getPskNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with PSK network config, ACS disabled & Non metered. + * Access point creation should pass. + */ +TEST_P(HostapdHidlTest, AddPskAccessPointWithoutAcsAndNonMetered) { + std::string ifname = setupApIfaceAndGetName(false); + auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_3, + getIfaceParamsWithoutAcs(ifname), + getPskNwParamsWithNonMetered()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with Open network config & ACS disabled. + * Access point creation should pass. + */ +TEST_P(HostapdHidlTest, AddOpenAccessPointWithoutAcs) { + std::string ifname = setupApIfaceAndGetName(false); + auto status = + HIDL_INVOKE(hostapd_, addAccessPoint_1_3, + getIfaceParamsWithoutAcs(ifname), getOpenNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with SAE Transition network config & ACS disabled. + * Access point creation should pass. + */ +TEST_P(HostapdHidlTest, AddSaeTransitionAccessPointWithoutAcs) { + if (!isWpa3SaeSupport_) GTEST_SKIP() << "Missing SAE support"; + std::string ifname = setupApIfaceAndGetName(false); + auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_3, + getIfaceParamsWithoutAcs(ifname), + getSaeTransitionNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with SAE network config & ACS disabled. + * Access point creation should pass. + */ +TEST_P(HostapdHidlTest, AddSAEAccessPointWithoutAcs) { + if (!isWpa3SaeSupport_) GTEST_SKIP() << "Missing SAE support"; + std::string ifname = setupApIfaceAndGetName(false); + auto status = + HIDL_INVOKE(hostapd_, addAccessPoint_1_3, + getIfaceParamsWithoutAcs(ifname), getSaeNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds & then removes an access point with PSK network config & ACS enabled. + * Access point creation & removal should pass. + */ +TEST_P(HostapdHidlTest, RemoveAccessPointWithAcs) { + if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support"; + std::string ifname = setupApIfaceAndGetName(false); + auto status_1_2 = + HIDL_INVOKE(hostapd_, addAccessPoint_1_3, getIfaceParamsWithAcs(ifname), + getPskNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status_1_2.code); + auto status = HIDL_INVOKE(hostapd_, removeAccessPoint, ifname); + EXPECT_EQ( + android::hardware::wifi::hostapd::V1_0::HostapdStatusCode::SUCCESS, + status.code); +} + +/** + * Adds & then removes an access point with PSK network config & ACS disabled. + * Access point creation & removal should pass. + */ +TEST_P(HostapdHidlTest, RemoveAccessPointWithoutAcs) { + std::string ifname = setupApIfaceAndGetName(false); + auto status_1_2 = + HIDL_INVOKE(hostapd_, addAccessPoint_1_3, + getIfaceParamsWithoutAcs(ifname), getPskNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status_1_2.code); + auto status = HIDL_INVOKE(hostapd_, removeAccessPoint, ifname); + EXPECT_EQ( + android::hardware::wifi::hostapd::V1_0::HostapdStatusCode::SUCCESS, + status.code); +} + +/** + * Adds an access point with invalid channel. + * Access point creation should fail. + */ +TEST_P(HostapdHidlTest, AddPskAccessPointWithInvalidChannel) { + std::string ifname = setupApIfaceAndGetName(false); + auto status = + HIDL_INVOKE(hostapd_, addAccessPoint_1_3, + getIfaceParamsWithInvalidChannel(ifname), getPskNwParams()); + EXPECT_NE(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with invalid PSK network config. + * Access point creation should fail. + */ +TEST_P(HostapdHidlTest, AddInvalidPskAccessPointWithoutAcs) { + std::string ifname = setupApIfaceAndGetName(false); + auto status = + HIDL_INVOKE(hostapd_, addAccessPoint_1_3, + getIfaceParamsWithoutAcs(ifname), getInvalidPskNwParams()); + EXPECT_NE(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with invalid SAE transition network config. + * Access point creation should fail. + */ +TEST_P(HostapdHidlTest, AddInvalidSaeTransitionAccessPointWithoutAcs) { + if (!isWpa3SaeSupport_) GTEST_SKIP() << "Missing SAE support"; + std::string ifname = setupApIfaceAndGetName(false); + auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_3, + getIfaceParamsWithoutAcs(ifname), + getInvalidSaeTransitionNwParams()); + EXPECT_NE(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with invalid SAE network config. + * Access point creation should fail. + */ +TEST_P(HostapdHidlTest, AddInvalidSaeAccessPointWithoutAcs) { + if (!isWpa3SaeSupport_) GTEST_SKIP() << "Missing SAE support"; + std::string ifname = setupApIfaceAndGetName(false); + auto status = + HIDL_INVOKE(hostapd_, addAccessPoint_1_3, + getIfaceParamsWithoutAcs(ifname), getInvalidSaeNwParams()); + EXPECT_NE(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * forceClientDisconnect should return FAILURE_CLIENT_UNKNOWN + * when hotspot interface available. + */ +TEST_P(HostapdHidlTest, DisconnectClientWhenIfacAvailable) { + std::string ifname = setupApIfaceAndGetName(false); + auto status_1_2 = + HIDL_INVOKE(hostapd_, addAccessPoint_1_3, + getIfaceParamsWithoutAcs(ifname), getOpenNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status_1_2.code); + + status_1_2 = HIDL_INVOKE(hostapd_, forceClientDisconnect, ifname, + kTestZeroMacAddr, kTestDisconnectReasonCode); + EXPECT_EQ(HostapdStatusCode::FAILURE_CLIENT_UNKNOWN, status_1_2.code); +} + +/** + * AddAccessPointWithDualBandConfig should pass + */ +TEST_P(HostapdHidlTest, AddAccessPointWithDualBandConfig) { + if (!isBridgedSupport_) GTEST_SKIP() << "Missing Bridged AP support"; + std::string ifname = setupApIfaceAndGetName(true); + auto status_1_2 = HIDL_INVOKE(hostapd_, addAccessPoint_1_3, + getIfaceParamsWithBridgedModeACS(ifname), + getOpenNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status_1_2.code); +} + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HostapdHidlTest); +INSTANTIATE_TEST_CASE_P( + PerInstance, HostapdHidlTest, + testing::Combine( + testing::ValuesIn( + android::hardware::getAllHalInstanceNames(IWifi::descriptor)), + testing::ValuesIn(android::hardware::getAllHalInstanceNames( + android::hardware::wifi::hostapd::V1_3::IHostapd::descriptor))), + android::hardware::PrintInstanceTupleNameToString<>); diff --git a/wifi/supplicant/1.0/vts/functional/Android.bp b/wifi/supplicant/1.0/vts/functional/Android.bp index cbfa2833be2ff97fb7c4411f602ba04563b465cb..121117c2440e2351ec7a0fd4d9b1e09ced024858 100644 --- a/wifi/supplicant/1.0/vts/functional/Android.bp +++ b/wifi/supplicant/1.0/vts/functional/Android.bp @@ -56,6 +56,7 @@ cc_test { "android.hardware.wifi.supplicant@1.1", "android.hardware.wifi.supplicant@1.2", "android.hardware.wifi.supplicant@1.3", + "android.hardware.wifi.supplicant@1.4", "android.hardware.wifi@1.0", "libgmock", "libwifi-system", diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp index 5e7a371d67a90ab088c2d65526665c811992ba3f..be6aad95834b49d5e940f8c8537e312319524fcb 100644 --- a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp +++ b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp @@ -283,3 +283,17 @@ bool turnOnExcessiveLogging(const sp& supplicant) { }); return !operation_failed; } + +bool waitForFrameworkReady() { + int waitCount = 10; + do { + // Check whether package service is ready or not. + if (!testing::checkSubstringInCommandOutput( + "/system/bin/service check package", ": not found")) { + return true; + } + LOG(INFO) << "Framework is not ready"; + sleep(1); + } while (waitCount-- > 0); + return false; +} diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.h b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.h index 1ccf0919aa26d0d48b5c2068869fea39135aacdf..33945ccb19ddd521bf5c9188feb2db1162aa1b1b 100644 --- a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.h +++ b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.h @@ -17,6 +17,8 @@ #ifndef SUPPLICANT_HIDL_TEST_UTILS_H #define SUPPLICANT_HIDL_TEST_UTILS_H +#include +#include #include #include #include @@ -62,4 +64,51 @@ bool turnOnExcessiveLogging( bool turnOnExcessiveLogging(); +bool waitForFrameworkReady(); + +class SupplicantHidlTestBase + : public ::testing::TestWithParam> { + public: + virtual void SetUp() override { + // should always be v1.0 wifi + wifi_v1_0_instance_name_ = std::get<0>(GetParam()); + supplicant_instance_name_ = std::get<1>(GetParam()); + std::system("/system/bin/start"); + ASSERT_TRUE(waitForFrameworkReady()); + + isP2pOn_ = + testing::deviceSupportsFeature("android.hardware.wifi.direct"); + // Stop Framework + std::system("/system/bin/stop"); + stopSupplicant(wifi_v1_0_instance_name_); + startSupplicantAndWaitForHidlService(wifi_v1_0_instance_name_, + supplicant_instance_name_); + LOG(INFO) << "SupplicantHidlTestBase isP2pOn_: " << isP2pOn_; + } + + virtual void TearDown() override { + stopSupplicant(wifi_v1_0_instance_name_); + // Start Framework + std::system("/system/bin/start"); + } + + protected: + bool isP2pOn_ = false; + std::string wifi_v1_0_instance_name_; + std::string supplicant_instance_name_; +}; + +class SupplicantHidlTestBaseV1_0 : public SupplicantHidlTestBase { + public: + virtual void SetUp() override { + SupplicantHidlTestBase::SetUp(); + supplicant_ = getSupplicant(supplicant_instance_name_, isP2pOn_); + ASSERT_NE(supplicant_.get(), nullptr); + EXPECT_TRUE(turnOnExcessiveLogging(supplicant_)); + } + + protected: + android::sp + supplicant_; +}; #endif /* SUPPLICANT_HIDL_TEST_UTILS_H */ diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp index 616869b26bfe65ace62446c590187073718f1165..325f355f4ad711948198b9b8cdefc5e3cb9f22da 100644 --- a/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp +++ b/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp @@ -71,21 +71,13 @@ constexpr uint32_t kTestExtListenInterval = 400; constexpr SupplicantNetworkId kTestNetworkId = 5; } // namespace -class SupplicantP2pIfaceHidlTest - : public ::testing::TestWithParam> { +class SupplicantP2pIfaceHidlTest : public SupplicantHidlTestBaseV1_0 { public: virtual void SetUp() override { - wifi_instance_name_ = std::get<0>(GetParam()); - supplicant_instance_name_ = std::get<1>(GetParam()); - isP2pOn_ = - testing::deviceSupportsFeature("android.hardware.wifi.direct"); - // Stop Framework - std::system("/system/bin/stop"); - stopSupplicant(wifi_instance_name_); - startSupplicantAndWaitForHidlService(wifi_instance_name_, - supplicant_instance_name_); - supplicant_ = getSupplicant(supplicant_instance_name_, isP2pOn_); - EXPECT_TRUE(turnOnExcessiveLogging(supplicant_)); + SupplicantHidlTestBaseV1_0::SetUp(); + if (!isP2pOn_) { + GTEST_SKIP() << "Wi-Fi Direct is not supported, skip this test."; + } p2p_iface_ = getSupplicantP2pIface(supplicant_); ASSERT_NE(p2p_iface_.get(), nullptr); @@ -93,22 +85,11 @@ class SupplicantP2pIfaceHidlTest memcpy(peer_mac_addr_.data(), kTestPeerMacAddr, peer_mac_addr_.size()); } - virtual void TearDown() override { - stopSupplicant(wifi_instance_name_); - // Start Framework - std::system("/system/bin/start"); - } - protected: - bool isP2pOn_ = false; - sp supplicant_; - // ISupplicantP2pIface object used for all tests in this fixture. sp p2p_iface_; // MAC address to use for various tests. std::array mac_addr_; std::array peer_mac_addr_; - std::string wifi_instance_name_; - std::string supplicant_instance_name_; }; class IfaceCallback : public ISupplicantP2pIfaceCallback { @@ -201,8 +182,8 @@ class IfaceCallback : public ISupplicantP2pIfaceCallback { * successfully created. */ TEST_P(SupplicantP2pIfaceHidlTest, Create) { - stopSupplicant(wifi_instance_name_); - startSupplicantAndWaitForHidlService(wifi_instance_name_, + stopSupplicant(wifi_v1_0_instance_name_); + startSupplicantAndWaitForHidlService(wifi_v1_0_instance_name_, supplicant_instance_name_); sp p2p_iface = getSupplicantP2pIface( getSupplicant(supplicant_instance_name_, isP2pOn_)); @@ -301,8 +282,17 @@ TEST_P(SupplicantP2pIfaceHidlTest, Connect) { mac_addr_, ISupplicantP2pIface::WpsProvisionMethod::PBC, kTestConnectPin, false, false, kTestConnectGoIntent, [](const SupplicantStatus& status, const hidl_string& /* pin */) { - // This is not going to work with fake values. - EXPECT_EQ(SupplicantStatusCode::FAILURE_UNKNOWN, status.code); + /* + * Before R, auto-join is not enabled and it is not going to work + * with fake values. After enabling auto-join, it will succeed + * always. + */ + LOG(INFO) << "ISupplicantP2pIface::connect() ret: " + << toString(status); + if (SupplicantStatusCode::FAILURE_UNKNOWN != status.code && + SupplicantStatusCode::SUCCESS != status.code) { + FAIL(); + } }); } @@ -314,12 +304,26 @@ TEST_P(SupplicantP2pIfaceHidlTest, CancelConnect) { mac_addr_, ISupplicantP2pIface::WpsProvisionMethod::PBC, kTestConnectPin, false, false, kTestConnectGoIntent, [](const SupplicantStatus& status, const hidl_string& /* pin */) { - // This is not going to work with fake values. - EXPECT_EQ(SupplicantStatusCode::FAILURE_UNKNOWN, status.code); + /* + * Before R, auto-join is not enabled and it is not going to work + * with fake values. After enabling auto-join, it will succeed + * always. + */ + LOG(INFO) << "ISupplicantP2pIface::connect() ret: " + << toString(status); + if (SupplicantStatusCode::FAILURE_UNKNOWN != status.code && + SupplicantStatusCode::SUCCESS != status.code) { + FAIL(); + } }); p2p_iface_->cancelConnect([](const SupplicantStatus& status) { - EXPECT_EQ(SupplicantStatusCode::FAILURE_UNKNOWN, status.code); + LOG(INFO) << "ISupplicantP2pIface::cancelConnect() ret: " + << toString(status); + if (SupplicantStatusCode::FAILURE_UNKNOWN != status.code && + SupplicantStatusCode::SUCCESS != status.code) { + FAIL(); + } }); } @@ -655,4 +659,4 @@ INSTANTIATE_TEST_CASE_P( android::hardware::getAllHalInstanceNames(IWifi::descriptor)), testing::ValuesIn(android::hardware::getAllHalInstanceNames( ISupplicant::descriptor))), - android::hardware::PrintInstanceTupleNameToString<>); \ No newline at end of file + android::hardware::PrintInstanceTupleNameToString<>); diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_sta_iface_hidl_test.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_sta_iface_hidl_test.cpp index bdca32c51560d74ff15b1d2a7df8ac79982bc826..bd0e8cfe50feb6e5fc8754b7515d9c2d01586eb6 100644 --- a/wifi/supplicant/1.0/vts/functional/supplicant_sta_iface_hidl_test.cpp +++ b/wifi/supplicant/1.0/vts/functional/supplicant_sta_iface_hidl_test.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include "supplicant_hidl_call_util.h" #include "supplicant_hidl_test_utils.h" @@ -67,42 +68,27 @@ constexpr uint8_t kTestWpsDeviceType[] = {[0 ... 7] = 0x01}; constexpr uint16_t kTestWpsConfigMethods = 0xffff; } // namespace -class SupplicantStaIfaceHidlTest - : public ::testing::TestWithParam> { +class SupplicantStaIfaceHidlTest : public SupplicantHidlTestBaseV1_0 { public: virtual void SetUp() override { - wifi_instance_name_ = std::get<0>(GetParam()); - supplicant_instance_name_ = std::get<1>(GetParam()); - isP2pOn_ = - testing::deviceSupportsFeature("android.hardware.wifi.direct"); - // Stop Framework - std::system("/system/bin/stop"); - stopSupplicant(wifi_instance_name_); - startSupplicantAndWaitForHidlService(wifi_instance_name_, - supplicant_instance_name_); - supplicant_ = getSupplicant(supplicant_instance_name_, isP2pOn_); - EXPECT_TRUE(turnOnExcessiveLogging(supplicant_)); + SupplicantHidlTestBaseV1_0::SetUp(); sta_iface_ = getSupplicantStaIface(supplicant_); ASSERT_NE(sta_iface_.get(), nullptr); - memcpy(mac_addr_.data(), kTestMacAddr, mac_addr_.size()); - } + v1_4 = ::android::hardware::wifi::supplicant::V1_4:: + ISupplicantStaIface::castFrom(sta_iface_); - virtual void TearDown() override { - stopSupplicant(wifi_instance_name_); - // Start Framework - std::system("/system/bin/start"); + memcpy(mac_addr_.data(), kTestMacAddr, mac_addr_.size()); } protected: bool isP2pOn_ = false; - sp supplicant_; + sp<::android::hardware::wifi::supplicant::V1_4::ISupplicantStaIface> v1_4 = + nullptr; // ISupplicantStaIface object used for all tests in this fixture. sp sta_iface_; // MAC address to use for various tests. std::array mac_addr_; - std::string wifi_instance_name_; - std::string supplicant_instance_name_; }; class IfaceCallback : public ISupplicantStaIfaceCallback { @@ -184,8 +170,8 @@ class IfaceCallback : public ISupplicantStaIfaceCallback { * successfully created. */ TEST_P(SupplicantStaIfaceHidlTest, Create) { - stopSupplicant(wifi_instance_name_); - startSupplicantAndWaitForHidlService(wifi_instance_name_, + stopSupplicant(wifi_v1_0_instance_name_); + startSupplicantAndWaitForHidlService(wifi_v1_0_instance_name_, supplicant_instance_name_); EXPECT_NE(nullptr, getSupplicantStaIface( getSupplicant(supplicant_instance_name_, isP2pOn_)) @@ -196,10 +182,14 @@ TEST_P(SupplicantStaIfaceHidlTest, Create) { * RegisterCallback */ TEST_P(SupplicantStaIfaceHidlTest, RegisterCallback) { - sta_iface_->registerCallback( - new IfaceCallback(), [](const SupplicantStatus& status) { - EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code); - }); + // This API is deprecated from v1.4 HAL. + SupplicantStatusCode expectedCode = + (nullptr != v1_4) ? SupplicantStatusCode::FAILURE_UNKNOWN + : SupplicantStatusCode::SUCCESS; + sta_iface_->registerCallback(new IfaceCallback(), + [&](const SupplicantStatus& status) { + EXPECT_EQ(expectedCode, status.code); + }); } /* @@ -571,4 +561,4 @@ INSTANTIATE_TEST_CASE_P( android::hardware::getAllHalInstanceNames(IWifi::descriptor)), testing::ValuesIn(android::hardware::getAllHalInstanceNames( ISupplicant::descriptor))), - android::hardware::PrintInstanceTupleNameToString<>); \ No newline at end of file + android::hardware::PrintInstanceTupleNameToString<>); diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_sta_network_hidl_test.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_sta_network_hidl_test.cpp index 7e93c5f4e934179b1ceb206474674f1fc95a3061..5aaba22afc6aafe032d9b4d03d8a5d04ec2fe542 100644 --- a/wifi/supplicant/1.0/vts/functional/supplicant_sta_network_hidl_test.cpp +++ b/wifi/supplicant/1.0/vts/functional/supplicant_sta_network_hidl_test.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -79,21 +80,10 @@ constexpr uint32_t kTestPairwiseCipher = ISupplicantStaNetwork::PairwiseCipherMask::TKIP); } // namespace -class SupplicantStaNetworkHidlTest - : public ::testing::TestWithParam> { +class SupplicantStaNetworkHidlTest : public SupplicantHidlTestBaseV1_0 { public: virtual void SetUp() override { - wifi_instance_name_ = std::get<0>(GetParam()); - supplicant_instance_name_ = std::get<1>(GetParam()); - isP2pOn_ = - testing::deviceSupportsFeature("android.hardware.wifi.direct"); - // Stop Framework - std::system("/system/bin/stop"); - stopSupplicant(wifi_instance_name_); - startSupplicantAndWaitForHidlService(wifi_instance_name_, - supplicant_instance_name_); - supplicant_ = getSupplicant(supplicant_instance_name_, isP2pOn_); - EXPECT_TRUE(turnOnExcessiveLogging(supplicant_)); + SupplicantHidlTestBaseV1_0::SetUp(); sta_network_ = createSupplicantStaNetwork(supplicant_); ASSERT_NE(sta_network_.get(), nullptr); /* variable used to check if the underlying HAL version is 1.3 or @@ -101,16 +91,12 @@ class SupplicantStaNetworkHidlTest */ v1_3 = ::android::hardware::wifi::supplicant::V1_3:: ISupplicantStaNetwork::castFrom(sta_network_); + v1_4 = ::android::hardware::wifi::supplicant::V1_4:: + ISupplicantStaNetwork::castFrom(sta_network_); ssid_.assign(kTestSsidStr, kTestSsidStr + strlen(kTestSsidStr)); } - virtual void TearDown() override { - stopSupplicant(wifi_instance_name_); - // Start Framework - std::system("/system/bin/start"); - } - protected: void removeNetwork() { sp sta_iface = getSupplicantStaIface(supplicant_); @@ -128,14 +114,12 @@ class SupplicantStaNetworkHidlTest sp<::android::hardware::wifi::supplicant::V1_3::ISupplicantStaNetwork> v1_3 = nullptr; - bool isP2pOn_ = false; - sp supplicant_; + sp<::android::hardware::wifi::supplicant::V1_4::ISupplicantStaNetwork> + v1_4 = nullptr; // ISupplicantStaNetwork object used for all tests in this fixture. sp sta_network_; // SSID to use for various tests. std::vector ssid_; - std::string wifi_instance_name_; - std::string supplicant_instance_name_; }; class NetworkCallback : public ISupplicantStaNetworkCallback { @@ -158,8 +142,8 @@ class NetworkCallback : public ISupplicantStaNetworkCallback { * successfully created. */ TEST_P(SupplicantStaNetworkHidlTest, Create) { - stopSupplicant(wifi_instance_name_); - startSupplicantAndWaitForHidlService(wifi_instance_name_, + stopSupplicant(wifi_v1_0_instance_name_); + startSupplicantAndWaitForHidlService(wifi_v1_0_instance_name_, supplicant_instance_name_); sp supplicant = getSupplicant(supplicant_instance_name_, isP2pOn_); @@ -172,8 +156,12 @@ TEST_P(SupplicantStaNetworkHidlTest, Create) { */ TEST_P(SupplicantStaNetworkHidlTest, RegisterCallback) { sta_network_->registerCallback( - new NetworkCallback(), [](const SupplicantStatus& status) { - EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code); + new NetworkCallback(), [&](const SupplicantStatus& status) { + if (nullptr != v1_4) { + EXPECT_EQ(SupplicantStatusCode::FAILURE_UNKNOWN, status.code); + } else { + EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code); + } }); } diff --git a/wifi/supplicant/1.1/vts/functional/Android.bp b/wifi/supplicant/1.1/vts/functional/Android.bp index 61c9a139a9bb80e01e40f9a2e3c5d8a56ec0ad52..68cda33d3e4f39d75763755ee3aef990532d9687 100644 --- a/wifi/supplicant/1.1/vts/functional/Android.bp +++ b/wifi/supplicant/1.1/vts/functional/Android.bp @@ -56,6 +56,9 @@ cc_test { "VtsHalWifiSupplicantV1_1TargetTestUtil", "android.hardware.wifi.supplicant@1.0", "android.hardware.wifi.supplicant@1.1", + "android.hardware.wifi.supplicant@1.2", + "android.hardware.wifi.supplicant@1.3", + "android.hardware.wifi.supplicant@1.4", "android.hardware.wifi@1.0", "android.hardware.wifi@1.1", "libgmock", diff --git a/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test.cpp b/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test.cpp index 6ad4290795fb28ffb8d8537b1cfbf7f39adc914b..a8e72b854c7e5bc77db64ce8259728940ddb28bd 100644 --- a/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test.cpp +++ b/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test.cpp @@ -36,9 +36,9 @@ using ::android::hardware::wifi::supplicant::V1_1::ISupplicant; using ::android::hardware::wifi::V1_0::IWifi; using ::android::sp; -class SupplicantHidlTest : public SupplicantHidlTestBase { +class SupplicantHidlTest : public SupplicantHidlTestBaseV1_1 { public: - virtual void SetUp() override { SupplicantHidlTestBase::SetUp(); } + virtual void SetUp() override { SupplicantHidlTestBaseV1_1::SetUp(); } protected: std::string getWlan0IfaceName() { diff --git a/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.h b/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.h index 21047947701e833730312a32df08c0407437f6f7..b6feb41abe93d91de36dc57c9b0d534caa7c971e 100644 --- a/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.h +++ b/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.h @@ -36,34 +36,15 @@ createSupplicantStaNetwork_1_1( const android::sp& supplicant); -class SupplicantHidlTestBase - : public ::testing::TestWithParam> { +class SupplicantHidlTestBaseV1_1 : public SupplicantHidlTestBase { public: virtual void SetUp() override { - wifi_v1_0_instance_name_ = std::get<0>(GetParam()); - supplicant_v1_1_instance_name_ = std::get<1>(GetParam()); - isP2pOn_ = - testing::deviceSupportsFeature("android.hardware.wifi.direct"); - // Stop Framework - std::system("/system/bin/stop"); - stopSupplicant(wifi_v1_0_instance_name_); - startSupplicantAndWaitForHidlService(wifi_v1_0_instance_name_, - supplicant_v1_1_instance_name_); - supplicant_ = - getSupplicant_1_1(supplicant_v1_1_instance_name_, isP2pOn_); + SupplicantHidlTestBase::SetUp(); + supplicant_ = getSupplicant_1_1(supplicant_instance_name_, isP2pOn_); ASSERT_NE(supplicant_.get(), nullptr); } - virtual void TearDown() override { - stopSupplicant(wifi_v1_0_instance_name_); - // Start Framework - std::system("/system/bin/start"); - } - protected: android::sp supplicant_; - bool isP2pOn_ = false; - std::string wifi_v1_0_instance_name_; - std::string supplicant_v1_1_instance_name_; }; diff --git a/wifi/supplicant/1.1/vts/functional/supplicant_sta_iface_hidl_test.cpp b/wifi/supplicant/1.1/vts/functional/supplicant_sta_iface_hidl_test.cpp index 2fade4493de08961846df2a67468678b364e6d5e..7e6e3e47b9ccc3eb661afb74962caf5654ebe222 100644 --- a/wifi/supplicant/1.1/vts/functional/supplicant_sta_iface_hidl_test.cpp +++ b/wifi/supplicant/1.1/vts/functional/supplicant_sta_iface_hidl_test.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -39,18 +40,22 @@ using ::android::hardware::wifi::supplicant::V1_1::ISupplicant; using ::android::hardware::wifi::supplicant::V1_1::ISupplicantStaIface; using ::android::hardware::wifi::supplicant::V1_1::ISupplicantStaIfaceCallback; -class SupplicantStaIfaceHidlTest : public SupplicantHidlTestBase { +class SupplicantStaIfaceHidlTest : public SupplicantHidlTestBaseV1_1 { public: virtual void SetUp() override { - SupplicantHidlTestBase::SetUp(); - EXPECT_TRUE(turnOnExcessiveLogging(supplicant_)); + SupplicantHidlTestBaseV1_1::SetUp(); sta_iface_ = getSupplicantStaIface_1_1(supplicant_); ASSERT_NE(sta_iface_.get(), nullptr); + + v1_4 = ::android::hardware::wifi::supplicant::V1_4:: + ISupplicantStaIface::castFrom(sta_iface_); } protected: // ISupplicantStaIface object used for all tests in this fixture. sp sta_iface_; + sp<::android::hardware::wifi::supplicant::V1_4::ISupplicantStaIface> v1_4 = + nullptr; }; class IfaceCallback : public ISupplicantStaIfaceCallback { @@ -134,10 +139,14 @@ class IfaceCallback : public ISupplicantStaIfaceCallback { * RegisterCallback_1_1 */ TEST_P(SupplicantStaIfaceHidlTest, RegisterCallback_1_1) { - sta_iface_->registerCallback_1_1( - new IfaceCallback(), [](const SupplicantStatus& status) { - EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code); - }); + // This API is deprecated from v1.4 HAL. + SupplicantStatusCode expectedCode = + (nullptr != v1_4) ? SupplicantStatusCode::FAILURE_UNKNOWN + : SupplicantStatusCode::SUCCESS; + sta_iface_->registerCallback_1_1(new IfaceCallback(), + [&](const SupplicantStatus& status) { + EXPECT_EQ(expectedCode, status.code); + }); } GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SupplicantStaIfaceHidlTest); @@ -149,4 +158,4 @@ INSTANTIATE_TEST_CASE_P( testing::ValuesIn(android::hardware::getAllHalInstanceNames( android::hardware::wifi::supplicant::V1_1::ISupplicant:: descriptor))), - android::hardware::PrintInstanceTupleNameToString<>); \ No newline at end of file + android::hardware::PrintInstanceTupleNameToString<>); diff --git a/wifi/supplicant/1.1/vts/functional/supplicant_sta_network_hidl_test.cpp b/wifi/supplicant/1.1/vts/functional/supplicant_sta_network_hidl_test.cpp index bd8a2ab2f708c96bf522c47e60b788c56771f533..37641a4a04485e30497b9eff638399baa8b7ecc9 100644 --- a/wifi/supplicant/1.1/vts/functional/supplicant_sta_network_hidl_test.cpp +++ b/wifi/supplicant/1.1/vts/functional/supplicant_sta_network_hidl_test.cpp @@ -37,11 +37,10 @@ constexpr uint8_t kTestIdentity[] = {0x45, 0x67, 0x98, 0x67, 0x56}; constexpr uint8_t kTestEncryptedIdentity[] = {0x35, 0x37, 0x58, 0x57, 0x26}; } // namespace -class SupplicantStaNetworkHidlTest : public SupplicantHidlTestBase { +class SupplicantStaNetworkHidlTest : public SupplicantHidlTestBaseV1_1 { public: virtual void SetUp() override { - SupplicantHidlTestBase::SetUp(); - EXPECT_TRUE(turnOnExcessiveLogging(supplicant_)); + SupplicantHidlTestBaseV1_1::SetUp(); sta_network_ = createSupplicantStaNetwork_1_1(supplicant_); ASSERT_NE(sta_network_.get(), nullptr); } @@ -59,9 +58,9 @@ class SupplicantStaNetworkHidlTest : public SupplicantHidlTestBase { TEST_P(SupplicantStaNetworkHidlTest, Create) { stopSupplicant(wifi_v1_0_instance_name_); startSupplicantAndWaitForHidlService(wifi_v1_0_instance_name_, - supplicant_v1_1_instance_name_); + supplicant_instance_name_); sp supplicant = - getSupplicant_1_1(supplicant_v1_1_instance_name_, isP2pOn_); + getSupplicant_1_1(supplicant_instance_name_, isP2pOn_); EXPECT_NE(nullptr, createSupplicantStaNetwork_1_1(supplicant).get()); } @@ -102,4 +101,4 @@ INSTANTIATE_TEST_CASE_P( testing::ValuesIn(android::hardware::getAllHalInstanceNames( android::hardware::wifi::supplicant::V1_1::ISupplicant:: descriptor))), - android::hardware::PrintInstanceTupleNameToString<>); \ No newline at end of file + android::hardware::PrintInstanceTupleNameToString<>); diff --git a/wifi/supplicant/1.2/vts/OWNERS b/wifi/supplicant/1.2/vts/OWNERS index 8bfb14882c8466954bd971a4603ab82e62077c61..cf81c798925338533dcb4d1968ea7de942b367f3 100644 --- a/wifi/supplicant/1.2/vts/OWNERS +++ b/wifi/supplicant/1.2/vts/OWNERS @@ -1,2 +1,2 @@ -rpius@google.com +arabawy@google.com etancohen@google.com diff --git a/wifi/supplicant/1.2/vts/functional/Android.bp b/wifi/supplicant/1.2/vts/functional/Android.bp index 44ae962ee4f6b29b6817f0a01fbd7aea25f4a089..ec3ca2210a614c44fc5e10e5ec02084166f4178b 100644 --- a/wifi/supplicant/1.2/vts/functional/Android.bp +++ b/wifi/supplicant/1.2/vts/functional/Android.bp @@ -60,6 +60,7 @@ cc_test { "android.hardware.wifi.supplicant@1.1", "android.hardware.wifi.supplicant@1.2", "android.hardware.wifi.supplicant@1.3", + "android.hardware.wifi.supplicant@1.4", "android.hardware.wifi@1.0", "android.hardware.wifi@1.1", "libgmock", diff --git a/wifi/supplicant/1.2/vts/functional/supplicant_hidl_test_utils_1_2.h b/wifi/supplicant/1.2/vts/functional/supplicant_hidl_test_utils_1_2.h index 2a432d075c15ee0b3fd558cda80655e71defac8f..b9c5adef7486a6541981c54817e574373f471d14 100644 --- a/wifi/supplicant/1.2/vts/functional/supplicant_hidl_test_utils_1_2.h +++ b/wifi/supplicant/1.2/vts/functional/supplicant_hidl_test_utils_1_2.h @@ -42,35 +42,16 @@ getSupplicantP2pIface_1_2( const android::sp& supplicant); -class SupplicantHidlTestBase - : public ::testing::TestWithParam> { +class SupplicantHidlTestBaseV1_2 : public SupplicantHidlTestBase { public: virtual void SetUp() override { - wifi_v1_0_instance_name_ = std::get<0>(GetParam()); - supplicant_v1_2_instance_name_ = std::get<1>(GetParam()); - isP2pOn_ = - testing::deviceSupportsFeature("android.hardware.wifi.direct"); - // Stop Framework - std::system("/system/bin/stop"); - stopSupplicant(wifi_v1_0_instance_name_); - startSupplicantAndWaitForHidlService(wifi_v1_0_instance_name_, - supplicant_v1_2_instance_name_); - supplicant_ = - getSupplicant_1_2(supplicant_v1_2_instance_name_, isP2pOn_); + SupplicantHidlTestBase::SetUp(); + supplicant_ = getSupplicant_1_2(supplicant_instance_name_, isP2pOn_); ASSERT_NE(supplicant_.get(), nullptr); EXPECT_TRUE(turnOnExcessiveLogging(supplicant_)); } - virtual void TearDown() override { - stopSupplicant(wifi_v1_0_instance_name_); - // Start Framework - std::system("/system/bin/start"); - } - protected: android::sp supplicant_; - bool isP2pOn_ = false; - std::string wifi_v1_0_instance_name_; - std::string supplicant_v1_2_instance_name_; }; diff --git a/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp b/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp index 75512d703523e80e3df936e961073a43384d68d4..7884cc6a25148fd35da12496edc1bb6001192f22 100644 --- a/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp +++ b/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp @@ -38,11 +38,10 @@ constexpr char kTestPassphrase[] = "P2pWorld1234"; constexpr uint8_t kTestZeroMacAddr[] = {[0 ... 5] = 0x0}; } // namespace -class SupplicantP2pIfaceHidlTest : public SupplicantHidlTestBase { +class SupplicantP2pIfaceHidlTest : public SupplicantHidlTestBaseV1_2 { public: virtual void SetUp() override { - SupplicantHidlTestBase::SetUp(); - EXPECT_TRUE(turnOnExcessiveLogging(supplicant_)); + SupplicantHidlTestBaseV1_2::SetUp(); if (!isP2pOn_) { GTEST_SKIP() << "Wi-Fi Direct is not supported, skip this test."; } diff --git a/wifi/supplicant/1.2/vts/functional/supplicant_sta_iface_hidl_test.cpp b/wifi/supplicant/1.2/vts/functional/supplicant_sta_iface_hidl_test.cpp index 184543b58de11a4fe639ea3d0c48e94ac0308cca..7f81206debd1a8c25d798ea0a6283437e642d17c 100644 --- a/wifi/supplicant/1.2/vts/functional/supplicant_sta_iface_hidl_test.cpp +++ b/wifi/supplicant/1.2/vts/functional/supplicant_sta_iface_hidl_test.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -53,14 +54,18 @@ using ::android::hardware::wifi::supplicant::V1_2::ISupplicantStaNetwork; #define TIMEOUT_PERIOD 60 class IfaceDppCallback; -class SupplicantStaIfaceHidlTest : public SupplicantHidlTestBase { +class SupplicantStaIfaceHidlTest : public SupplicantHidlTestBaseV1_2 { public: virtual void SetUp() override { - SupplicantHidlTestBase::SetUp(); - EXPECT_TRUE(turnOnExcessiveLogging(supplicant_)); + SupplicantHidlTestBaseV1_2::SetUp(); sta_iface_ = getSupplicantStaIface_1_2(supplicant_); ASSERT_NE(sta_iface_.get(), nullptr); count_ = 0; + + v1_3 = ::android::hardware::wifi::supplicant::V1_3:: + ISupplicantStaIface::castFrom(sta_iface_); + v1_4 = ::android::hardware::wifi::supplicant::V1_4:: + ISupplicantStaIface::castFrom(sta_iface_); } enum DppCallbackType { @@ -103,6 +108,8 @@ class SupplicantStaIfaceHidlTest : public SupplicantHidlTestBase { protected: // ISupplicantStaIface object used for all tests in this fixture. sp sta_iface_; + sp<::android::hardware::wifi::supplicant::V1_3::ISupplicantStaIface> v1_3; + sp<::android::hardware::wifi::supplicant::V1_4::ISupplicantStaIface> v1_4; bool isDppSupported() { uint32_t keyMgmtMask = 0; @@ -263,10 +270,14 @@ class IfaceDppCallback : public IfaceCallback { * RegisterCallback_1_2 */ TEST_P(SupplicantStaIfaceHidlTest, RegisterCallback_1_2) { - sta_iface_->registerCallback_1_2( - new IfaceCallback(), [](const SupplicantStatus& status) { - EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code); - }); + // This API is deprecated from v1.4 HAL. + SupplicantStatusCode expectedCode = + (nullptr != v1_4) ? SupplicantStatusCode::FAILURE_UNKNOWN + : SupplicantStatusCode::SUCCESS; + sta_iface_->registerCallback_1_2(new IfaceCallback(), + [&](const SupplicantStatus& status) { + EXPECT_EQ(expectedCode, status.code); + }); } /* @@ -340,9 +351,6 @@ TEST_P(SupplicantStaIfaceHidlTest, StartDppEnrolleeInitiator) { * it is waiting for will never be called. Note that this test is also * implemented in the 1.3 VTS test. */ - sp<::android::hardware::wifi::supplicant::V1_3::ISupplicantStaIface> v1_3 = - ::android::hardware::wifi::supplicant::V1_3::ISupplicantStaIface:: - castFrom(sta_iface_); if (v1_3 != nullptr) { GTEST_SKIP() << "Test not supported with this HAL version"; } @@ -405,10 +413,6 @@ TEST_P(SupplicantStaIfaceHidlTest, StartDppConfiguratorInitiator) { * it is waiting for will never be called. Note that this test is also * implemented in the 1.3 VTS test. */ - sp<::android::hardware::wifi::supplicant::V1_3::ISupplicantStaIface> v1_3 = - ::android::hardware::wifi::supplicant::V1_3::ISupplicantStaIface:: - castFrom(sta_iface_); - if (v1_3 != nullptr) { GTEST_SKIP() << "Test not supported with this HAL version"; return; diff --git a/wifi/supplicant/1.2/vts/functional/supplicant_sta_network_hidl_test.cpp b/wifi/supplicant/1.2/vts/functional/supplicant_sta_network_hidl_test.cpp index 5a2f8089490c5d86fafebf6a786e85dd3d9b5dc6..ee5de69a7860af17348960ce083f25224e50da20 100644 --- a/wifi/supplicant/1.2/vts/functional/supplicant_sta_network_hidl_test.cpp +++ b/wifi/supplicant/1.2/vts/functional/supplicant_sta_network_hidl_test.cpp @@ -37,10 +37,10 @@ using ::android::hardware::wifi::supplicant::V1_2::ISupplicantStaNetwork; // constexpr uint8_t kTestEncryptedIdentity[] = {0x35, 0x37, 0x58, 0x57, 0x26}; //} // namespace -class SupplicantStaNetworkHidlTest : public SupplicantHidlTestBase { +class SupplicantStaNetworkHidlTest : public SupplicantHidlTestBaseV1_2 { public: virtual void SetUp() override { - SupplicantHidlTestBase::SetUp(); + SupplicantHidlTestBaseV1_2::SetUp(); sta_network_ = createSupplicantStaNetwork_1_2(supplicant_); ASSERT_NE(sta_network_.get(), nullptr); } diff --git a/wifi/supplicant/1.3/vts/OWNERS b/wifi/supplicant/1.3/vts/OWNERS index 8bfb14882c8466954bd971a4603ab82e62077c61..cf81c798925338533dcb4d1968ea7de942b367f3 100644 --- a/wifi/supplicant/1.3/vts/OWNERS +++ b/wifi/supplicant/1.3/vts/OWNERS @@ -1,2 +1,2 @@ -rpius@google.com +arabawy@google.com etancohen@google.com diff --git a/wifi/supplicant/1.3/vts/functional/Android.bp b/wifi/supplicant/1.3/vts/functional/Android.bp index 1f26c3d54ddd987ec5526d912a7d940467fd3a7c..ec25de2a43a4d25160a4dd409c5a8c011de33c5a 100644 --- a/wifi/supplicant/1.3/vts/functional/Android.bp +++ b/wifi/supplicant/1.3/vts/functional/Android.bp @@ -63,6 +63,7 @@ cc_test { "android.hardware.wifi.supplicant@1.1", "android.hardware.wifi.supplicant@1.2", "android.hardware.wifi.supplicant@1.3", + "android.hardware.wifi.supplicant@1.4", "android.hardware.wifi@1.0", "android.hardware.wifi@1.1", "libgmock", diff --git a/wifi/supplicant/1.3/vts/functional/supplicant_hidl_test_utils_1_3.h b/wifi/supplicant/1.3/vts/functional/supplicant_hidl_test_utils_1_3.h index 69fc5985935af7913382113053c0454df0a49fe7..b28c5a486dc5a76a6f409ac1295a78003c1204b4 100644 --- a/wifi/supplicant/1.3/vts/functional/supplicant_hidl_test_utils_1_3.h +++ b/wifi/supplicant/1.3/vts/functional/supplicant_hidl_test_utils_1_3.h @@ -34,4 +34,17 @@ getSupplicant_1_3(const std::string& supplicant_instance_name, bool isP2pOn); bool isFilsSupported( android::sp sta_iface); + +class SupplicantHidlTestBaseV1_3 : public SupplicantHidlTestBase { + public: + virtual void SetUp() override { + SupplicantHidlTestBase::SetUp(); + supplicant_ = getSupplicant_1_3(supplicant_instance_name_, isP2pOn_); + ASSERT_NE(supplicant_.get(), nullptr); + } + + protected: + android::sp + supplicant_; +}; #endif /* SUPPLICANT_HIDL_TEST_UTILS_1_3_H */ diff --git a/wifi/supplicant/1.3/vts/functional/supplicant_sta_iface_hidl_test.cpp b/wifi/supplicant/1.3/vts/functional/supplicant_sta_iface_hidl_test.cpp index 504ccc4e77cb4e890b3b7b1b8e61f76fd4bd6f64..9ffe0ece0903b4553c9a8e5eaf5ba6d8239cf728 100644 --- a/wifi/supplicant/1.3/vts/functional/supplicant_sta_iface_hidl_test.cpp +++ b/wifi/supplicant/1.3/vts/functional/supplicant_sta_iface_hidl_test.cpp @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include #include @@ -55,31 +57,16 @@ using ::android::hardware::wifi::supplicant::V1_3::WpaDriverCapabilitiesMask; #define TIMEOUT_PERIOD 60 class IfaceDppCallback; -class SupplicantStaIfaceHidlTest - : public ::testing::TestWithParam> { +class SupplicantStaIfaceHidlTest : public SupplicantHidlTestBaseV1_3 { public: virtual void SetUp() override { - wifi_v1_0_instance_name_ = std::get<0>(GetParam()); - supplicant_v1_3_instance_name_ = std::get<1>(GetParam()); - isP2pOn_ = - testing::deviceSupportsFeature("android.hardware.wifi.direct"); - // Stop Framework - std::system("/system/bin/stop"); - - stopSupplicant(wifi_v1_0_instance_name_); - startSupplicantAndWaitForHidlService(wifi_v1_0_instance_name_, - supplicant_v1_3_instance_name_); - supplicant_ = - getSupplicant_1_3(supplicant_v1_3_instance_name_, isP2pOn_); - EXPECT_TRUE(turnOnExcessiveLogging(supplicant_)); + SupplicantHidlTestBaseV1_3::SetUp(); sta_iface_ = getSupplicantStaIface_1_3(supplicant_); ASSERT_NE(sta_iface_.get(), nullptr); - } - virtual void TearDown() override { - stopSupplicant(wifi_v1_0_instance_name_); - // Start Framework - std::system("/system/bin/start"); + /* Variable used to check the underlying HAL version. */ + sta_iface_v1_4_ = ::android::hardware::wifi::supplicant::V1_4:: + ISupplicantStaIface::castFrom(sta_iface_); } int64_t pmkCacheExpirationTimeInSec; @@ -127,10 +114,8 @@ class SupplicantStaIfaceHidlTest protected: // ISupplicantStaIface object used for all tests in this fixture. sp sta_iface_; - sp supplicant_; - bool isP2pOn_ = false; - std::string wifi_v1_0_instance_name_; - std::string supplicant_v1_3_instance_name_; + sp<::android::hardware::wifi::supplicant::V1_4::ISupplicantStaIface> + sta_iface_v1_4_ = nullptr; bool isDppSupported() { uint32_t keyMgmtMask = 0; @@ -340,10 +325,13 @@ class IfaceBssTmHandlingDoneCallback : public IfaceCallback { * RegisterCallback_1_3 */ TEST_P(SupplicantStaIfaceHidlTest, RegisterCallback_1_3) { - sta_iface_->registerCallback_1_3( - new IfaceCallback(), [](const SupplicantStatus& status) { - EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code); - }); + SupplicantStatusCode expectedCode = + (nullptr != sta_iface_v1_4_) ? SupplicantStatusCode::FAILURE_UNKNOWN + : SupplicantStatusCode::SUCCESS; + sta_iface_->registerCallback_1_3(new IfaceCallback(), + [&](const SupplicantStatus& status) { + EXPECT_EQ(expectedCode, status.code); + }); } /* @@ -353,7 +341,11 @@ TEST_P(SupplicantStaIfaceHidlTest, GetConnectionCapabilities) { sta_iface_->getConnectionCapabilities( [&](const SupplicantStatus& status, ConnectionCapabilities /* capabilities */) { - EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code); + // Since getConnectionCapabilities() is overridden by an + // upgraded API in newer HAL versions, allow for FAILURE_UNKNOWN + if (status.code != SupplicantStatusCode::FAILURE_UNKNOWN) { + EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code); + } }); } @@ -361,9 +353,12 @@ TEST_P(SupplicantStaIfaceHidlTest, GetConnectionCapabilities) { * GetWpaDriverCapabilities */ TEST_P(SupplicantStaIfaceHidlTest, GetWpaDriverCapabilities) { + SupplicantStatusCode expectedCode = + (nullptr != sta_iface_v1_4_) ? SupplicantStatusCode::FAILURE_UNKNOWN + : SupplicantStatusCode::SUCCESS; sta_iface_->getWpaDriverCapabilities( [&](const SupplicantStatus& status, uint32_t) { - EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code); + EXPECT_EQ(expectedCode, status.code); }); } @@ -374,12 +369,26 @@ TEST_P(SupplicantStaIfaceHidlTest, SetMboCellularDataStatus) { uint32_t driverCapMask = 0; // Get MBO support from the device. - sta_iface_->getWpaDriverCapabilities( - [&](const SupplicantStatus& status, uint32_t driverCapMaskInternal) { - EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code); + if (nullptr != sta_iface_v1_4_) { + sta_iface_v1_4_->getWpaDriverCapabilities_1_4( + [&](const ::android::hardware::wifi::supplicant::V1_4:: + SupplicantStatus& status, + uint32_t driverCapMaskInternal) { + EXPECT_EQ(::android::hardware::wifi::supplicant::V1_4:: + SupplicantStatusCode::SUCCESS, + status.code); + + driverCapMask = driverCapMaskInternal; + }); + } else { + sta_iface_->getWpaDriverCapabilities( + [&](const SupplicantStatus& status, + uint32_t driverCapMaskInternal) { + EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code); - driverCapMask = driverCapMaskInternal; - }); + driverCapMask = driverCapMaskInternal; + }); + } SupplicantStatusCode expectedStatusCode = (driverCapMask & WpaDriverCapabilitiesMask::MBO) @@ -422,6 +431,11 @@ TEST_P(SupplicantStaIfaceHidlTest, StartDppEnrolleeInitiator) { return; } + if (sta_iface_v1_4_ != nullptr) { + GTEST_SKIP() << "Test not supported with this HAL version"; + return; + } + hidl_string uri = "DPP:C:81/1,117/" "40;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj" @@ -474,6 +488,11 @@ TEST_P(SupplicantStaIfaceHidlTest, StartDppConfiguratorInitiator) { return; } + if (sta_iface_v1_4_ != nullptr) { + GTEST_SKIP() << "Test not supported with this HAL version"; + return; + } + hidl_string uri = "DPP:C:81/1,117/" "40;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj" diff --git a/wifi/supplicant/1.3/vts/functional/supplicant_sta_network_hidl_test.cpp b/wifi/supplicant/1.3/vts/functional/supplicant_sta_network_hidl_test.cpp index 11c55a6a205a963051e9009918bc77376ef546d9..12d8d0db0a47458ce5868d99026233bc323ba8e3 100644 --- a/wifi/supplicant/1.3/vts/functional/supplicant_sta_network_hidl_test.cpp +++ b/wifi/supplicant/1.3/vts/functional/supplicant_sta_network_hidl_test.cpp @@ -43,43 +43,20 @@ constexpr OcspType kTestOcspType = OcspType::REQUEST_CERT_STATUS; constexpr OcspType kTestInvalidOcspType = (OcspType)-1; } // namespace -class SupplicantStaNetworkHidlTest - : public ::testing::TestWithParam> { +class SupplicantStaNetworkHidlTest : public SupplicantHidlTestBaseV1_3 { public: virtual void SetUp() override { - wifi_v1_0_instance_name_ = std::get<0>(GetParam()); - supplicant_v1_3_instance_name_ = std::get<1>(GetParam()); - isP2pOn_ = - testing::deviceSupportsFeature("android.hardware.wifi.direct"); - // Stop Framework - std::system("/system/bin/stop"); - - stopSupplicant(wifi_v1_0_instance_name_); - startSupplicantAndWaitForHidlService(wifi_v1_0_instance_name_, - supplicant_v1_3_instance_name_); - supplicant_ = - getSupplicant_1_3(supplicant_v1_3_instance_name_, isP2pOn_); - EXPECT_TRUE(turnOnExcessiveLogging(supplicant_)); + SupplicantHidlTestBaseV1_3::SetUp(); sta_iface_ = getSupplicantStaIface_1_3(supplicant_); ASSERT_NE(nullptr, sta_iface_.get()); sta_network_ = createSupplicantStaNetwork_1_3(supplicant_); ASSERT_NE(sta_network_.get(), nullptr); } - virtual void TearDown() override { - stopSupplicant(wifi_v1_0_instance_name_); - // Start Framework - std::system("/system/bin/start"); - } - protected: sp sta_iface_; // ISupplicantStaNetwork object used for all tests in this fixture. sp sta_network_; - sp supplicant_; - bool isP2pOn_ = false; - std::string wifi_v1_0_instance_name_; - std::string supplicant_v1_3_instance_name_; bool isWapiSupported() { uint32_t keyMgmtMask = 0; diff --git a/wifi/supplicant/1.4/Android.bp b/wifi/supplicant/1.4/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..c988fdbb9e26f115c27c5d33b32235f278a83bb2 --- /dev/null +++ b/wifi/supplicant/1.4/Android.bp @@ -0,0 +1,38 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +hidl_interface { + name: "android.hardware.wifi.supplicant@1.4", + root: "android.hardware", + srcs: [ + "types.hal", + "ISupplicant.hal", + "ISupplicantP2pIface.hal", + "ISupplicantP2pIfaceCallback.hal", + "ISupplicantStaIface.hal", + "ISupplicantStaNetwork.hal", + "ISupplicantStaNetworkCallback.hal", + "ISupplicantStaIfaceCallback.hal", + ], + interfaces: [ + "android.hardware.wifi.supplicant@1.0", + "android.hardware.wifi.supplicant@1.1", + "android.hardware.wifi.supplicant@1.2", + "android.hardware.wifi.supplicant@1.3", + "android.hardware.wifi@1.0", + "android.hidl.base@1.0", + ], + gen_java: true, + apex_available: [ + "//apex_available:platform", + "com.android.wifi", + ], +} diff --git a/wifi/supplicant/1.4/ISupplicant.hal b/wifi/supplicant/1.4/ISupplicant.hal new file mode 100644 index 0000000000000000000000000000000000000000..9cb88ba43ba62d4f260035f1b3adf31c1ffba17e --- /dev/null +++ b/wifi/supplicant/1.4/ISupplicant.hal @@ -0,0 +1,29 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.wifi.supplicant@1.4; + +import @1.3::ISupplicant; + +/** + * Interface exposed by the supplicant HIDL service registered + * with the hardware service manager. + * This is the root level object for any the supplicant interactions. + * To use 1.4 features you must cast specific interfaces returned from the + * 1.1 HAL. For example V1_1::ISupplicant::addIface() adds V1_0::ISupplicantIface, + * which can be cast to V1_4::ISupplicantStaIface. + */ +interface ISupplicant extends @1.3::ISupplicant {}; diff --git a/wifi/supplicant/1.4/ISupplicantP2pIface.hal b/wifi/supplicant/1.4/ISupplicantP2pIface.hal new file mode 100644 index 0000000000000000000000000000000000000000..28846dec64af9a2fac4f7fdf0df211b8060f57e6 --- /dev/null +++ b/wifi/supplicant/1.4/ISupplicantP2pIface.hal @@ -0,0 +1,84 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.wifi.supplicant@1.4; + +import @1.2::ISupplicantP2pIface; +import ISupplicantP2pIfaceCallback; + +/** + * Interface exposed by the supplicant for each P2P mode network + * interface (e.g p2p0) it controls. + * To use 1.4 features you must cast specific interfaces returned from the + * 1.4 HAL. For example V1_4::ISupplicant::addIface() adds V1_4::ISupplicantIface, + * which can be cast to V1_4::ISupplicantP2pIface. + */ +interface ISupplicantP2pIface extends @1.2::ISupplicantP2pIface { + /** + * Set whether to enable EDMG(802.11ay). Only allowed if hw mode is |HOSTAPD_MODE_IEEE80211AD| + * + * @param enable true to set, false otherwise. + * @return status Status of the operation. + * Possible status codes: + * |SupplicantStatusCode.SUCCESS|, + * |SupplicantStatusCode.FAILURE_UNKNOWN|, + * |SupplicantStatusCode.FAILURE_NETWORK_INVALID| + */ + setEdmg(bool enable) generates (SupplicantStatus status); + + /** + * Get whether EDMG(802.11ay) is enabled for this network. + * + * @return status Status of the operation. + * Possible status codes: + * |SupplicantStatusCode.SUCCESS|, + * |SupplicantStatusCode.FAILURE_NETWORK_INVALID| + * @return enabled true if set, false otherwise. + */ + getEdmg() generates (SupplicantStatus status, bool enabled); + + /** + * Register for callbacks from this interface. + * + * These callbacks are invoked for events that are specific to this interface. + * Registration of multiple callback objects is supported. These objects must + * be automatically deleted when the corresponding client process is dead or + * if this interface is removed. + * + * @param callback An instance of the |ISupplicantP2pIfaceCallback| HIDL + * interface object. + * @return status Status of the operation. + * Possible status codes: + * |SupplicantStatusCode.SUCCESS|, + * |SupplicantStatusCode.FAILURE_UNKNOWN|, + * |SupplicantStatusCode.FAILURE_IFACE_INVALID| + */ + registerCallback_1_4(ISupplicantP2pIfaceCallback callback) + generates (SupplicantStatus status); + + /* + * Set Wifi Display R2 device info. + * + * @param info WFD R2 device info as described in section 5.1.12 of WFD technical + * specification v2.1. + * @return status Status of the operation. + * Possible status codes: + * |SupplicantStatusCode.SUCCESS|, + * |SupplicantStatusCode.FAILURE_UNKNOWN|, + * |SupplicantStatusCode.FAILURE_IFACE_INVALID| + */ + setWfdR2DeviceInfo(uint8_t[4] info) generates (SupplicantStatus status); +}; diff --git a/wifi/supplicant/1.4/ISupplicantP2pIfaceCallback.hal b/wifi/supplicant/1.4/ISupplicantP2pIfaceCallback.hal new file mode 100644 index 0000000000000000000000000000000000000000..a0912746fb269e0628fb3db529279de5df493b6b --- /dev/null +++ b/wifi/supplicant/1.4/ISupplicantP2pIfaceCallback.hal @@ -0,0 +1,61 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.wifi.supplicant@1.4; + +import @1.0::ISupplicantP2pIfaceCallback; +import @1.0::MacAddress; +import @1.0::WpsConfigMethods; +import @1.0::P2pGroupCapabilityMask; + +/** + * Callback Interface exposed by the supplicant service + * for each P2P mode interface (ISupplicantP2pIface). + * + * Clients need to host an instance of this HIDL interface object and + * pass a reference of the object to the supplicant via the + * corresponding |ISupplicantP2pIface.registerCallback| method. + */ +interface ISupplicantP2pIfaceCallback extends @1.0::ISupplicantP2pIfaceCallback { + /** + * Used to indicate that a P2P Wi-Fi Display R2 device has been found. Refer to + * Wi-Fi Display Technical Specification Version 2.0. + * + * @param srcAddress MAC address of the device found. This must either + * be the P2P device address for a peer which is not in a group, + * or the P2P interface address for a peer which is a Group Owner. + * @param p2pDeviceAddress P2P device address. + * @param primaryDeviceType Type of device. Refer to section B.1 of Wifi P2P + * Technical specification v1.2. + * @param deviceName Name of the device. + * @param configMethods Mask of WPS configuration methods supported by the + * device. + * @param deviceCapabilities Refer to section 4.1.4 of Wifi P2P Technical + * specification v1.2. + * @param groupCapabilites Refer to section 4.1.4 of Wifi P2P Technical + * specification v1.2. + * @param wfdDeviceInfo WFD device info as described in section 5.1.2 of WFD + * technical specification v1.0.0. + * @param wfdR2DeviceInfo WFD R2 device info as described in section 5.1.12 of WFD + * technical specification v2.1. + */ + oneway onR2DeviceFound( + MacAddress srcAddress, MacAddress p2pDeviceAddress, + uint8_t[8] primaryDeviceType, string deviceName, + bitfield configMethods, uint8_t deviceCapabilities, + bitfield groupCapabilities, uint8_t[6] wfdDeviceInfo, + uint8_t[2] wfdR2DeviceInfo); +}; diff --git a/wifi/supplicant/1.4/ISupplicantStaIface.hal b/wifi/supplicant/1.4/ISupplicantStaIface.hal new file mode 100644 index 0000000000000000000000000000000000000000..7441ba5f2c0d997afba929a6e6c4e5765b89e6fa --- /dev/null +++ b/wifi/supplicant/1.4/ISupplicantStaIface.hal @@ -0,0 +1,137 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.wifi.supplicant@1.4; + +import @1.0::SupplicantStatus; +import @1.0::ISupplicantStaIface; +import @1.0::MacAddress; +import ISupplicantStaIfaceCallback; +import @1.3::ISupplicantStaIface; + +/** + * Interface exposed by the supplicant for each station mode network + * interface (e.g wlan0) it controls. + */ +interface ISupplicantStaIface extends @1.3::ISupplicantStaIface { + /** + * Get Connection capabilities + * + * @return status Status of the operation, and connection capabilities. + * Possible status codes: + * |SupplicantStatusCode.SUCCESS|, + * |SupplicantStatusCode.FAILURE_UNKNOWN|, + */ + getConnectionCapabilities_1_4() + generates (SupplicantStatus status, ConnectionCapabilities capabilities); + + /** + * Register for callbacks from this interface. + * + * These callbacks are invoked for events that are specific to this interface. + * Registration of multiple callback objects is supported. These objects must + * be automatically deleted when the corresponding client process is dead or + * if this interface is removed. + * + * @param callback An instance of the |ISupplicantStaIfaceCallback| HIDL + * interface object. + * @return status Status of the operation. + * Possible status codes: + * |SupplicantStatusCode.SUCCESS|, + * |SupplicantStatusCode.FAILURE_UNKNOWN|, + * |SupplicantStatusCode.FAILURE_IFACE_INVALID| + */ + registerCallback_1_4(ISupplicantStaIfaceCallback callback) + generates (SupplicantStatus status); + + /** + * Initiate Venue URL ANQP (for IEEE 802.11u Interworking/Hotspot 2.0) query with the + * specified access point. This specific query can be used only post connection, once security + * is established and PMF is enabled, to avoid spoofing preassociation ANQP responses. + * The ANQP data fetched must be returned in the + * |ISupplicantStaIfaceCallback.onAnqpQueryDone| callback. + * + * @param macAddress MAC address of the access point. + * @return status Status of the operation. + * Possible status codes: + * |SupplicantStatusCode.SUCCESS|, + * |SupplicantStatusCode.FAILURE_UNKNOWN|, + * |SupplicantStatusCode.FAILURE_IFACE_INVALID| + */ + initiateVenueUrlAnqpQuery(MacAddress macAddress) generates (SupplicantStatus status); + + /** + * Get wpa driver capabilities. + * + * @return status Status of the operation, and a bitmap of wpa driver features. + * Possible status codes: + * |SupplicantStatusCode.SUCCESS|, + * |SupplicantStatusCode.FAILURE_UNKNOWN|, + */ + getWpaDriverCapabilities_1_4() generates (SupplicantStatus status, + bitfield driverCapabilitiesMask); + + /** + * Generates DPP bootstrap information: Bootstrap ID, DPP URI and listen + * channel for responder mode. + * + * @param MacAddress MAC address of the interface for the DPP operation. + * @param deviceInfo Device specific information. + * As per DPP Specification V1.0 section 5.2, + * allowed Range of ASCII characters in deviceInfo - %x20-7E + * semicolon is not allowed. + * @param DppCurve Elliptic curve cryptography type used to generate DPP + * public/private key pair. + * @return status of operation and bootstrap info. + * Possible status codes: + * |SupplicantStatusCode.SUCCESS|, + * |SupplicantStatusCode.FAILURE_IFACE_INVALID|, + * |SupplicantStatusCode.FAILURE_UNKNOWN| + * |SupplicantStatusCode.FAILURE_UNSUPPORTED| + */ + generateDppBootstrapInfoForResponder(MacAddress macAddress, string deviceInfo, DppCurve curve) + generates (SupplicantStatus status, DppResponderBootstrapInfo bootstrapInfo); + + /** + * Start DPP in Enrollee-Responder mode. + * Framework must first call |generateDppBootstrapInfoForResponder| to generate + * the bootstrapping information: Bootstrap ID, DPP URI and the listen channel. + * Then call this API with derived listen channel to start listening for + * authentication request from Peer initiator. + * + * @param listenChannel DPP listen channel. + * @return status Status of the operation. + * Possible status codes: + * |SupplicantStatusCode.SUCCESS|, + * |SupplicantStatusCode.FAILURE_UNKNOWN|, + * |SupplicantStatusCode.FAILURE_IFACE_INVALID| + * |SupplicantStatusCode.FAILURE_UNSUPPORTED| + */ + startDppEnrolleeResponder(uint32_t listenChannel) generates (SupplicantStatus status); + + /** + * Stop DPP Responder operation - Remove the bootstrap code and stop listening. + * + * @param ownBootstrapId Local device's URI ID obtained through + * |generateDppBootstrapInfoForResponder| call. + * @return status Status of the operation. + * Possible status codes: + * |SupplicantStatusCode.SUCCESS|, + * |SupplicantStatusCode.FAILURE_IFACE_INVALID| + * |SupplicantStatusCode.FAILURE_UNSUPPORTED| + */ + stopDppResponder(uint32_t ownBootstrapId) generates (SupplicantStatus status); +}; diff --git a/wifi/supplicant/1.4/ISupplicantStaIfaceCallback.hal b/wifi/supplicant/1.4/ISupplicantStaIfaceCallback.hal new file mode 100644 index 0000000000000000000000000000000000000000..3b0a4d4ca09c4b911c7563cc75127a596643d664 --- /dev/null +++ b/wifi/supplicant/1.4/ISupplicantStaIfaceCallback.hal @@ -0,0 +1,180 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.wifi.supplicant@1.4; + +import @1.0::ISupplicantStaIfaceCallback.AnqpData; +import @1.0::ISupplicantStaIfaceCallback.Hs20AnqpData; +import @1.3::ISupplicantStaIfaceCallback; +import @1.0::ISupplicantStaIfaceCallback.State; +import @1.0::ISupplicantStaIfaceCallback.StatusCode; +import @1.0::Bssid; +import @1.0::Ssid; + +/** + * Callback Interface exposed by the supplicant service + * for each station mode interface (ISupplicantStaIface). + * + * Clients need to host an instance of this HIDL interface object and + * pass a reference of the object to the supplicant via the + * corresponding |ISupplicantStaIface.registerCallback_1_4| method. + */ +interface ISupplicantStaIfaceCallback extends @1.3::ISupplicantStaIfaceCallback { + /** + * MBO spec v1.2, 4.2.4 Table 14: MBO Association disallowed reason code attribute + * values. + */ + enum MboAssocDisallowedReasonCode : uint8_t { + RESERVED = 0, + UNSPECIFIED = 1, + MAX_NUM_STA_ASSOCIATED = 2, + AIR_INTERFACE_OVERLOADED = 3, + AUTH_SERVER_OVERLOADED = 4, + INSUFFICIENT_RSSI = 5, + }; + + /** + * ANQP data for IEEE Std 802.11-2016. + * The format of the data within these elements follows the IEEE + * Std 802.11-2016 standard, section 9.4.5. + */ + struct AnqpData { + /** + * Baseline information as defined in HAL 1.0. + */ + @1.0::ISupplicantStaIfaceCallback.AnqpData V1_0; + + /* + * Container for v1.0 of this struct + */ + vec venueUrl; + }; + + /** + * OceRssiBasedAssocRejectAttr is extracted from (Re-)Association response + * frame from an OCE AP to indicate that the AP has rejected the + * (Re-)Association request on the basis of insufficient RSSI. + * Refer OCE spec v1.0 section 4.2.2 Table 7. + */ + struct OceRssiBasedAssocRejectAttr { + /* + * Delta RSSI - The difference in dB between the minimum RSSI at which + * the AP would accept a (Re-)Association request from the STA before + * Retry Delay expires and the AP's measurement of the RSSI at which the + * (Re-)Association request was received. + */ + uint32_t deltaRssi; + + /* + * Retry Delay - The time period in seconds for which the AP will not + * accept any subsequent (Re-)Association requests from the STA, unless + * the received RSSI has improved by Delta RSSI. + */ + uint32_t retryDelayS; + }; + + /** + * Association Rejection related information. + */ + struct AssociationRejectionData { + /** + * SSID of the AP that rejected the association. + */ + Ssid ssid; + + /** + * BSSID of the AP that rejected the association. + */ + Bssid bssid; + + /* + * 802.11 code to indicate the reject reason. + * Refer to section 8.4.1.9 of IEEE 802.11 spec. + */ + StatusCode statusCode; + + /* + * Flag to indicate that failure is due to timeout rather than + * explicit rejection response from the AP. + */ + bool timedOut; + + /** + * Flag to indicate that MboAssocDisallowedReasonCode is present + * in the (Re-)Association response frame. + */ + bool isMboAssocDisallowedReasonCodePresent; + + /** + * mboAssocDisallowedReason is extracted from MBO association disallowed attribute + * in (Re-)Association response frame to indicate that the AP is not accepting new + * associations. + * Refer MBO spec v1.2 section 4.2.4 Table 13 for the details of reason code. + * The value is undefined if isMboAssocDisallowedReasonCodePresent is false. + */ + MboAssocDisallowedReasonCode mboAssocDisallowedReason; + + /** + * Flag to indicate that OceRssiBasedAssocRejectAttr is present + * in the (Re-)Association response frame. + */ + bool isOceRssiBasedAssocRejectAttrPresent; + + /* + * OCE RSSI-based (Re-)Association rejection attribute. + * The contents are undefined if isOceRssiBasedAssocRejectAttrPresent is false. + */ + OceRssiBasedAssocRejectAttr oceRssiBasedAssocRejectData; + }; + + /** + * Used to indicate a Hotspot 2.0 terms and conditions acceptance is requested from the user + * before allowing the device to get internet access. + * + * @param bssid BSSID of the access point. + * @param url URL of the T&C server. + */ + oneway onHs20TermsAndConditionsAcceptanceRequestedNotification(Bssid bssid, string url); + + /** + * Used to indicate the result of ANQP (either for IEEE 802.11u Interworking + * or Hotspot 2.0) query. + * + * @param bssid BSSID of the access point. + * @param data ANQP data fetched from the access point. + * All the fields in this struct must be empty if the query failed. + * @param hs20Data ANQP data fetched from the Hotspot 2.0 access point. + * All the fields in this struct must be empty if the query failed. + */ + oneway onAnqpQueryDone_1_4(Bssid bssid, AnqpData data, Hs20AnqpData hs20Data); + + /** + * Used to indicate an association rejection received from the AP + * to which the connection is being attempted. + * + * @param assocRejectData Association Rejection related information. + */ + oneway onAssociationRejected_1_4(AssociationRejectionData assocRejectData); + + /** + * Used to indicate that the supplicant failed to find a network in scan result + * which matches with the network capabilities requested by upper layer + * for connection. + * + * @param ssid network name supplicant tried to connect. + */ + oneway onNetworkNotFound(Ssid ssid); +}; diff --git a/wifi/supplicant/1.4/ISupplicantStaNetwork.hal b/wifi/supplicant/1.4/ISupplicantStaNetwork.hal new file mode 100644 index 0000000000000000000000000000000000000000..4dfe8e69ae757ef303e687f7aa4a62beed854cca --- /dev/null +++ b/wifi/supplicant/1.4/ISupplicantStaNetwork.hal @@ -0,0 +1,203 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.wifi.supplicant@1.4; + +import @1.3::ISupplicantStaNetwork; +import ISupplicantStaNetworkCallback; + +/** + * Interface exposed by the supplicant for each station mode network + * configuration it controls. + */ +interface ISupplicantStaNetwork extends @1.3::ISupplicantStaNetwork { + /** + * Possible mask of values for KeyMgmt param. + */ + enum KeyMgmtMask : @1.3::ISupplicantStaNetwork.KeyMgmtMask { + /** + * SAE PK mode + */ + SAE_PK, + }; + + /** + * Possible mask of values for PairwiseCipher param. + */ + enum PairwiseCipherMask : @1.3::ISupplicantStaNetwork.PairwiseCipherMask { + /** + * GCMP-128 Pairwise Cipher + */ + GCMP_128 = 1 << 6, + }; + + /** + * Possible mask of values for GroupCipher param. + */ + enum GroupCipherMask : @1.3::ISupplicantStaNetwork.GroupCipherMask { + /** + * GCMP-128 Group Cipher + */ + GCMP_128 = 1 << 6, + }; + + /** + * SAE Hash-to-Element mode. + */ + enum SaeH2eMode : uint8_t { + /** + * Hash-to-Element is disabled, only Hunting & Pecking is allowed. + */ + DISABLED, + /** + * Both Hash-to-Element and Hunting & Pecking are allowed. + */ + H2E_OPTIONAL, + /** + * Only Hash-to-Element is allowed. + */ + H2E_MANDATORY, + }; + + /** + * Set group cipher mask for the network. + * + * @param groupCipherMask value to set. + * Combination of |ProtoMask| values. + * @return status Status of the operation. + * Possible status codes: + * |SupplicantStatusCode.SUCCESS|, + * |SupplicantStatusCode.FAILURE_ARGS_INVALID|, + * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|, + * |SupplicantStatusCode.FAILURE_UNKNOWN| + */ + setGroupCipher_1_4(bitfield groupCipherMask) + generates (SupplicantStatus status); + + /** + * Get the group cipher mask set for the network. + * + * @return status Status of the operation. + * Possible status codes: + * |SupplicantStatusCode.SUCCESS|, + * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|, + * |SupplicantStatusCode.FAILURE_UNKNOWN| + * @return groupCipherMask Combination of |GroupCipherMask| values. + */ + getGroupCipher_1_4() + generates (SupplicantStatus status, bitfield groupCipherMask); + + /** + * Set pairwise cipher mask for the network. + * + * @param pairwiseCipherMask value to set. + * Combination of |ProtoMask| values. + * @return status Status of the operation. + * Possible status codes: + * |SupplicantStatusCode.SUCCESS|, + * |SupplicantStatusCode.FAILURE_ARGS_INVALID|, + * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|, + * |SupplicantStatusCode.FAILURE_UNKNOWN| + */ + setPairwiseCipher_1_4(bitfield pairwiseCipherMask) + generates (SupplicantStatus status); + + /** + * Get the pairwise cipher mask set for the network. + * + * @return status Status of the operation. + * Possible status codes: + * |SupplicantStatusCode.SUCCESS|, + * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|, + * |SupplicantStatusCode.FAILURE_UNKNOWN| + * @return pairwiseCipherMask Combination of |PairwiseCipherMask| values. + */ + getPairwiseCipher_1_4() + generates (SupplicantStatus status, bitfield pairwiseCipherMask); + + /** + * Set whether to enable enhanced directional multi-gigabit (802.11ay EDMG). + * Only allowed if hw mode is |HOSTAPD_MODE_IEEE80211AD| + * + * @param enable true to set, false otherwise. + * @return status Status of the operation. + * Possible status codes: + * |SupplicantStatusCode.SUCCESS|, + * |SupplicantStatusCode.FAILURE_UNKNOWN|, + * |SupplicantStatusCode.FAILURE_NETWORK_INVALID| + */ + setEdmg(bool enable) generates (SupplicantStatus status); + + /** + * Get whether enhanced directional multi-gigabit (802.11ay EDMG) is enabled for this network. + * + * @return status Status of the operation. + * Possible status codes: + * |SupplicantStatusCode.SUCCESS|, + * |SupplicantStatusCode.FAILURE_NETWORK_INVALID| + * @return enabled true if set, false otherwise. + */ + getEdmg() generates (SupplicantStatus status, bool enabled); + + /** + * Register for callbacks from this network. + * + * These callbacks are invoked for events that are specific to this network. + * Registration of multiple callback objects is supported. These objects must + * be automatically deleted when the corresponding client process is dead or + * if this network is removed. + * + * @param callback An instance of the |ISupplicantStaNetworkCallback| HIDL + * interface object. + * @return status Status of the operation. + * Possible status codes: + * |SupplicantStatusCode.SUCCESS|, + * |SupplicantStatusCode.FAILURE_UNKNOWN|, + * |SupplicantStatusCode.FAILURE_NETWORK_INVALID| + */ + registerCallback_1_4(ISupplicantStaNetworkCallback callback) + generates (SupplicantStatus status); + + /** + * Set SAE H2E (Hash-to-Element) mode. + * + * @param mode SAE H2E supporting mode. + * @return status Status of the operation. + * Possible status codes: + * |SupplicantStatusCode.SUCCESS|, + * |SupplicantStatusCode.FAILURE_UNKNOWN|, + * |SupplicantStatusCode.FAILURE_NETWORK_INVALID| + */ + setSaeH2eMode(SaeH2eMode mode) generates (SupplicantStatus status); + + /** + * Set whether to enable SAE PK (Public Key) only mode to enable public AP validation. + * When enabled, only SAE PK network is allowed; otherwise PK is optional. + * If this API is not called before connecting to an SAE + * network, SAE PK mode depends on SAE PK config in wpa_supplicant configuration. + * If SAE PK config of wpa_supplicant configuration is not set, + * the default mode is optional (support for both PK and standard mode). + * + * @param enable true to set, false otherwise. + * @return status Status of the operation. + * Possible status codes: + * |SupplicantStatusCode.SUCCESS|, + * |SupplicantStatusCode.FAILURE_UNKNOWN|, + * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|, + * |SupplicantStatusCode.FAILURE_UNSUPPORTED| + */ + enableSaePkOnlyMode(bool enable) generates (SupplicantStatus status); +}; diff --git a/wifi/supplicant/1.4/ISupplicantStaNetworkCallback.hal b/wifi/supplicant/1.4/ISupplicantStaNetworkCallback.hal new file mode 100644 index 0000000000000000000000000000000000000000..38cdcf9612b531c316b67d7001c1234d841f1f96 --- /dev/null +++ b/wifi/supplicant/1.4/ISupplicantStaNetworkCallback.hal @@ -0,0 +1,46 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.wifi.supplicant@1.4; + +import @1.0::ISupplicantStaNetworkCallback; + +/** + * Callback Interface exposed by the supplicant service + * for each network (ISupplicantStaNetwork). + * + * Clients need to host an instance of this HIDL interface object and + * pass a reference of the object to the supplicant via the + * corresponding |ISupplicantStaNetwork.registerCallback_1_4| method. + */ +interface ISupplicantStaNetworkCallback extends @1.0::ISupplicantStaNetworkCallback { + /** + * WPA3™ Specification Addendum for WPA3 R3 - Table 3. + * Transition Disable Indication filled in the third + * 4-way handshake message. + */ + enum TransitionDisableIndication : uint32_t { + USE_WPA3_PERSONAL = 1 << 0, + USE_SAE_PK = 1 << 1, + USE_WPA3_ENTERPRISE = 1 << 2, + USE_ENHANCED_OPEN = 1 << 3, + }; + + /** + * Used to notify WPA3 transition disable. + */ + oneway onTransitionDisable(bitfield ind); +}; diff --git a/wifi/supplicant/1.4/types.hal b/wifi/supplicant/1.4/types.hal new file mode 100644 index 0000000000000000000000000000000000000000..b72eb425b0b0e637f9196eeca99c7e9327d75331 --- /dev/null +++ b/wifi/supplicant/1.4/types.hal @@ -0,0 +1,135 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.wifi.supplicant@1.4; + +import @1.0::SupplicantStatusCode; +import @1.3::ConnectionCapabilities; +import @1.3::DppFailureCode; +import @1.3::WpaDriverCapabilitiesMask; + +/** + * Detailed network mode for legacy network + */ +enum LegacyMode : uint32_t { + UNKNOWN = 0, + /** + * For 802.11a + */ + A_MODE = 1, + /** + * For 802.11b + */ + B_MODE = 2, + /** + * For 802.11g + */ + G_MODE = 3, +}; + +/** + * DppFailureCode: Error codes for DPP (Easy Connect) + */ +enum DppFailureCode : @1.3::DppFailureCode { + /** + * Failure to generate a DPP URI. + */ + URI_GENERATION, +}; + +/** + * DppCurve: Elliptic curve cryptography type used to generate DPP + * public/private key pair. + */ +enum DppCurve : uint32_t { + PRIME256V1, + SECP384R1, + SECP521R1, + BRAINPOOLP256R1, + BRAINPOOLP384R1, + BRAINPOOLP512R1, +}; + +/** + * Connection Capabilities supported by current network and device + */ +struct ConnectionCapabilities { + /** + * Baseline information as defined in HAL 1.3. + */ + @1.3::ConnectionCapabilities V1_3; + + /** + * detailed network mode for legacy network + */ + LegacyMode legacyMode; +}; + +/** + * Enum values indicating the status of any supplicant operation. + */ +enum SupplicantStatusCode : @1.0::SupplicantStatusCode { + FAILURE_UNSUPPORTED, +}; + +/** + * Generic structure to return the status of any supplicant operation. + */ +struct SupplicantStatus { + SupplicantStatusCode code; + + /** + * A vendor specific error message to provide more information beyond the + * status code. + * This will be used for debbuging purposes only. + */ + string debugMessage; +}; + +/** + * WPA Driver capability. + */ +enum WpaDriverCapabilitiesMask : @1.3::WpaDriverCapabilitiesMask { + /** + * WPA3 SAE Public-Key. + */ + SAE_PK = 1 << 2, + /** + * Wi-Fi Display R2 + */ + WFD_R2 = 1 << 3, +}; + +/** + * DPP bootstrap info generated for responder mode operation + */ +struct DppResponderBootstrapInfo { + /** + * Generated bootstrap identifier + */ + uint32_t bootstrapId; + + /** + * The Wi-Fi channel that the DPP responder is listening on. + */ + uint32_t listenChannel; + + /** + * Bootstrapping URI per DPP specification, "section 5.2 Bootstrapping + * information", may contain listen channel, MAC address, public key, or other information. + */ + string uri; +}; diff --git a/wifi/supplicant/1.4/vts/OWNERS b/wifi/supplicant/1.4/vts/OWNERS new file mode 100644 index 0000000000000000000000000000000000000000..cf81c798925338533dcb4d1968ea7de942b367f3 --- /dev/null +++ b/wifi/supplicant/1.4/vts/OWNERS @@ -0,0 +1,2 @@ +arabawy@google.com +etancohen@google.com diff --git a/wifi/supplicant/1.4/vts/functional/Android.bp b/wifi/supplicant/1.4/vts/functional/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..8cbe04f686c13a76c566940de3fb81a73d3d5d4e --- /dev/null +++ b/wifi/supplicant/1.4/vts/functional/Android.bp @@ -0,0 +1,112 @@ +// +// Copyright (C) 2020 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_library_static { + name: "VtsHalWifiSupplicantV1_4TargetTestUtil", + defaults: ["VtsHalTargetTestDefaults"], + srcs: ["supplicant_hidl_test_utils_1_4.cpp"], + export_include_dirs: [ + ".", + ], + static_libs: [ + "VtsHalWifiV1_0TargetTestUtil", + "VtsHalWifiSupplicantV1_0TargetTestUtil", + "VtsHalWifiSupplicantV1_1TargetTestUtil", + "VtsHalWifiSupplicantV1_2TargetTestUtil", + "VtsHalWifiSupplicantV1_3TargetTestUtil", + "android.hardware.wifi.supplicant@1.0", + "android.hardware.wifi.supplicant@1.1", + "android.hardware.wifi.supplicant@1.2", + "android.hardware.wifi.supplicant@1.3", + "android.hardware.wifi.supplicant@1.4", + "android.hardware.wifi@1.0", + "libgmock", + "libwifi-system", + "libwifi-system-iface", + ], +} + +cc_test { + name: "VtsHalWifiSupplicantV1_4TargetTest", + defaults: ["VtsHalTargetTestDefaults"], + srcs: [ + "supplicant_sta_iface_hidl_test.cpp", + "supplicant_sta_network_hidl_test.cpp", + ], + static_libs: [ + "VtsHalWifiV1_0TargetTestUtil", + "VtsHalWifiSupplicantV1_0TargetTestUtil", + "VtsHalWifiSupplicantV1_1TargetTestUtil", + "VtsHalWifiSupplicantV1_2TargetTestUtil", + "VtsHalWifiSupplicantV1_3TargetTestUtil", + "VtsHalWifiSupplicantV1_4TargetTestUtil", + "android.hardware.wifi.supplicant@1.0", + "android.hardware.wifi.supplicant@1.1", + "android.hardware.wifi.supplicant@1.2", + "android.hardware.wifi.supplicant@1.3", + "android.hardware.wifi.supplicant@1.4", + "android.hardware.wifi@1.0", + "android.hardware.wifi@1.1", + "libgmock", + "libwifi-system", + "libwifi-system-iface", + ], + test_suites: [ + "general-tests", + "vts", + ], + disable_framework: true, +} + +cc_test { + name: "VtsHalWifiSupplicantP2pV1_4TargetTest", + defaults: ["VtsHalTargetTestDefaults"], + srcs: [ + "supplicant_p2p_iface_hidl_test.cpp", + ], + static_libs: [ + "VtsHalWifiV1_0TargetTestUtil", + "VtsHalWifiSupplicantV1_0TargetTestUtil", + "VtsHalWifiSupplicantV1_1TargetTestUtil", + "VtsHalWifiSupplicantV1_2TargetTestUtil", + "VtsHalWifiSupplicantV1_3TargetTestUtil", + "VtsHalWifiSupplicantV1_4TargetTestUtil", + "android.hardware.wifi.supplicant@1.0", + "android.hardware.wifi.supplicant@1.1", + "android.hardware.wifi.supplicant@1.2", + "android.hardware.wifi.supplicant@1.3", + "android.hardware.wifi.supplicant@1.4", + "android.hardware.wifi@1.0", + "android.hardware.wifi@1.1", + "libgmock", + "libwifi-system", + "libwifi-system-iface", + ], + test_suites: [ + "general-tests", + "vts", + ], + disable_framework: true, +} diff --git a/wifi/supplicant/1.4/vts/functional/supplicant_hidl_test_utils_1_4.cpp b/wifi/supplicant/1.4/vts/functional/supplicant_hidl_test_utils_1_4.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7e7a465e3f4187e904e2b5495b075b987f8c1e1e --- /dev/null +++ b/wifi/supplicant/1.4/vts/functional/supplicant_hidl_test_utils_1_4.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "supplicant_hidl_test_utils.h" +#include "supplicant_hidl_test_utils_1_4.h" + +using ::android::sp; +using ::android::hardware::wifi::supplicant::V1_4::ISupplicant; +using ::android::hardware::wifi::supplicant::V1_4::ISupplicantP2pIface; +using ::android::hardware::wifi::supplicant::V1_4::ISupplicantStaIface; + +sp getSupplicantStaIface_1_4( + const android::sp& + supplicant) { + return ISupplicantStaIface::castFrom(getSupplicantStaIface(supplicant)); +} + +sp getSupplicantP2pIface_1_4( + const android::sp& + supplicant) { + return ISupplicantP2pIface::castFrom(getSupplicantP2pIface(supplicant)); +} + +sp getSupplicant_1_4(const std::string& supplicant_instance_name, + bool isP2pOn) { + return ISupplicant::castFrom( + getSupplicant(supplicant_instance_name, isP2pOn)); +} diff --git a/wifi/supplicant/1.4/vts/functional/supplicant_hidl_test_utils_1_4.h b/wifi/supplicant/1.4/vts/functional/supplicant_hidl_test_utils_1_4.h new file mode 100644 index 0000000000000000000000000000000000000000..b3b699033b73aee13b34eddc8d7e9382e41b17b2 --- /dev/null +++ b/wifi/supplicant/1.4/vts/functional/supplicant_hidl_test_utils_1_4.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SUPPLICANT_HIDL_TEST_UTILS_1_4_H +#define SUPPLICANT_HIDL_TEST_UTILS_1_4_H + +#include +#include +#include + +android::sp +getSupplicantStaIface_1_4( + const android::sp& + supplicant); +android::sp +getSupplicantP2pIface_1_4( + const android::sp& + supplicant); +android::sp +getSupplicant_1_4(const std::string& supplicant_instance_name, bool isP2pOn); + +class SupplicantHidlTestBaseV1_4 : public SupplicantHidlTestBase { + public: + virtual void SetUp() override { + SupplicantHidlTestBase::SetUp(); + supplicant_ = getSupplicant_1_4(supplicant_instance_name_, isP2pOn_); + ASSERT_NE(supplicant_.get(), nullptr); + EXPECT_TRUE(turnOnExcessiveLogging(supplicant_)); + } + + protected: + android::sp + supplicant_; +}; +#endif /* SUPPLICANT_HIDL_TEST_UTILS_1_4_H */ diff --git a/wifi/supplicant/1.4/vts/functional/supplicant_p2p_iface_hidl_test.cpp b/wifi/supplicant/1.4/vts/functional/supplicant_p2p_iface_hidl_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4427c390c47aa806ab5160b8fb05ee0ee4c210d8 --- /dev/null +++ b/wifi/supplicant/1.4/vts/functional/supplicant_p2p_iface_hidl_test.cpp @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "supplicant_hidl_test_utils.h" +#include "supplicant_hidl_test_utils_1_4.h" + +using ::android::sp; +using ::android::hardware::hidl_array; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatus; +using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode; +using ::android::hardware::wifi::supplicant::V1_4::ISupplicantP2pIface; +using ::android::hardware::wifi::supplicant::V1_4::ISupplicantP2pIfaceCallback; + +using SupplicantStatusV1_4 = + ::android::hardware::wifi::supplicant::V1_4::SupplicantStatus; +using SupplicantStatusCodeV1_4 = + ::android::hardware::wifi::supplicant::V1_4::SupplicantStatusCode; + +constexpr uint8_t kTestWfdR2DeviceInfo[] = {[0 ... 3] = 0x01}; + +class SupplicantP2pIfaceHidlTest : public SupplicantHidlTestBaseV1_4 { + public: + virtual void SetUp() override { + SupplicantHidlTestBaseV1_4::SetUp(); + p2p_iface_ = getSupplicantP2pIface_1_4(supplicant_); + ASSERT_NE(p2p_iface_.get(), nullptr); + } + + protected: + // ISupplicantP2pIface object used for all tests in this fixture. + sp p2p_iface_; +}; + +class IfaceCallback : public ISupplicantP2pIfaceCallback { + Return onNetworkAdded(uint32_t /* id */) override { return Void(); } + Return onNetworkRemoved(uint32_t /* id */) override { return Void(); } + Return onDeviceFound( + const hidl_array& /* srcAddress */, + const hidl_array& /* p2pDeviceAddress */, + const hidl_array& /* primaryDeviceType */, + const hidl_string& /* deviceName */, uint16_t /* configMethods */, + uint8_t /* deviceCapabilities */, uint32_t /* groupCapabilities */, + const hidl_array& /* wfdDeviceInfo */) override { + return Void(); + } + Return onDeviceLost( + const hidl_array& /* p2pDeviceAddress */) override { + return Void(); + } + Return onFindStopped() override { return Void(); } + Return onGoNegotiationRequest( + const hidl_array& /* srcAddress */, + ISupplicantP2pIfaceCallback::WpsDevPasswordId /* passwordId */) + override { + return Void(); + } + Return onGoNegotiationCompleted( + ISupplicantP2pIfaceCallback::P2pStatusCode /* status */) override { + return Void(); + } + Return onGroupFormationSuccess() override { return Void(); } + Return onGroupFormationFailure( + const hidl_string& /* failureReason */) override { + return Void(); + } + Return onGroupStarted( + const hidl_string& /* groupIfname */, bool /* isGo */, + const hidl_vec& /* ssid */, uint32_t /* frequency */, + const hidl_array& /* psk */, + const hidl_string& /* passphrase */, + const hidl_array& /* goDeviceAddress */, + bool /* isPersistent */) override { + return Void(); + } + Return onGroupRemoved(const hidl_string& /* groupIfname */, + bool /* isGo */) override { + return Void(); + } + Return onInvitationReceived( + const hidl_array& /* srcAddress */, + const hidl_array& /* goDeviceAddress */, + const hidl_array& /* bssid */, + uint32_t /* persistentNetworkId */, + uint32_t /* operatingFrequency */) override { + return Void(); + } + Return onInvitationResult( + const hidl_array& /* bssid */, + ISupplicantP2pIfaceCallback::P2pStatusCode /* status */) override { + return Void(); + } + Return onProvisionDiscoveryCompleted( + const hidl_array& /* p2pDeviceAddress */, + bool /* isRequest */, + ISupplicantP2pIfaceCallback::P2pProvDiscStatusCode /* status */, + uint16_t /* configMethods */, + const hidl_string& /* generatedPin */) override { + return Void(); + } + Return onServiceDiscoveryResponse( + const hidl_array& /* srcAddress */, + uint16_t /* updateIndicator */, + const hidl_vec& /* tlvs */) override { + return Void(); + } + Return onStaAuthorized( + const hidl_array& /* srcAddress */, + const hidl_array& /* p2pDeviceAddress */) override { + return Void(); + } + Return onStaDeauthorized( + const hidl_array& /* srcAddress */, + const hidl_array& /* p2pDeviceAddress */) override { + return Void(); + } + Return onR2DeviceFound( + const hidl_array& /* srcAddress */, + const hidl_array& /* p2pDeviceAddress */, + const hidl_array& /* primaryDeviceType */, + const hidl_string& /* deviceName */, uint16_t /* configMethods */, + uint8_t /* deviceCapabilities */, uint32_t /* groupCapabilities */, + const hidl_array& /* wfdDeviceInfo */, + const hidl_array& /* wfdR2DeviceInfo */) override { + return Void(); + } +}; + +/* + * SetGetEdmg + */ +TEST_P(SupplicantP2pIfaceHidlTest, SetGetEdmg) { + p2p_iface_->setEdmg(true, [&](const SupplicantStatusV1_4& status) { + EXPECT_EQ(SupplicantStatusCodeV1_4::SUCCESS, status.code); + }); + p2p_iface_->getEdmg([&](const SupplicantStatusV1_4& status, bool enable) { + EXPECT_EQ(SupplicantStatusCodeV1_4::SUCCESS, status.code); + EXPECT_EQ(true, enable); + }); + p2p_iface_->setEdmg(false, [&](const SupplicantStatusV1_4& status) { + EXPECT_EQ(SupplicantStatusCodeV1_4::SUCCESS, status.code); + }); + p2p_iface_->getEdmg([&](const SupplicantStatusV1_4& status, bool enable) { + EXPECT_EQ(SupplicantStatusCodeV1_4::SUCCESS, status.code); + EXPECT_EQ(false, enable); + }); +} + +/* + * RegisterCallback_1_4 + */ +TEST_P(SupplicantP2pIfaceHidlTest, RegisterCallback_1_4) { + p2p_iface_->registerCallback_1_4( + new IfaceCallback(), [](const SupplicantStatusV1_4& status) { + EXPECT_EQ(SupplicantStatusCodeV1_4::SUCCESS, status.code); + }); +} + +/* + * SetWfdR2DeviceInfo + */ +TEST_P(SupplicantP2pIfaceHidlTest, SetWfdR2DeviceInfo) { + p2p_iface_->setWfdR2DeviceInfo( + kTestWfdR2DeviceInfo, [&](const SupplicantStatusV1_4& status) { + EXPECT_EQ(SupplicantStatusCodeV1_4::SUCCESS, status.code); + }); +} + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SupplicantP2pIfaceHidlTest); +INSTANTIATE_TEST_CASE_P( + PerInstance, SupplicantP2pIfaceHidlTest, + testing::Combine( + testing::ValuesIn(android::hardware::getAllHalInstanceNames( + android::hardware::wifi::V1_0::IWifi::descriptor)), + testing::ValuesIn(android::hardware::getAllHalInstanceNames( + android::hardware::wifi::supplicant::V1_4::ISupplicant:: + descriptor))), + android::hardware::PrintInstanceTupleNameToString<>); diff --git a/wifi/supplicant/1.4/vts/functional/supplicant_sta_iface_hidl_test.cpp b/wifi/supplicant/1.4/vts/functional/supplicant_sta_iface_hidl_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..86d6737fa98470cbeb4be1a1129a53aa8a0e1a97 --- /dev/null +++ b/wifi/supplicant/1.4/vts/functional/supplicant_sta_iface_hidl_test.cpp @@ -0,0 +1,340 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "supplicant_hidl_test_utils.h" +#include "supplicant_hidl_test_utils_1_4.h" + +using ::android::sp; +using ::android::hardware::hidl_array; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatus; +using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode; +using ::android::hardware::wifi::supplicant::V1_2::DppAkm; +using ::android::hardware::wifi::supplicant::V1_2::DppFailureCode; +using ::android::hardware::wifi::supplicant::V1_2::DppNetRole; +using ::android::hardware::wifi::supplicant::V1_2::DppProgressCode; +using ::android::hardware::wifi::supplicant::V1_3::DppSuccessCode; +using ::android::hardware::wifi::supplicant::V1_3::ISupplicantStaNetwork; +using ::android::hardware::wifi::supplicant::V1_4::ConnectionCapabilities; +using ::android::hardware::wifi::supplicant::V1_4::DppCurve; +using ::android::hardware::wifi::supplicant::V1_4::DppResponderBootstrapInfo; +using ::android::hardware::wifi::supplicant::V1_4::ISupplicant; +using ::android::hardware::wifi::supplicant::V1_4::ISupplicantStaIface; +using ::android::hardware::wifi::supplicant::V1_4::ISupplicantStaIfaceCallback; + +namespace { +constexpr uint8_t kTestMacAddr[] = {0x56, 0x67, 0x67, 0xf4, 0x56, 0x92}; +} // namespace + +using SupplicantStatusV1_4 = + ::android::hardware::wifi::supplicant::V1_4::SupplicantStatus; +using SupplicantStatusCodeV1_4 = + ::android::hardware::wifi::supplicant::V1_4::SupplicantStatusCode; + +class SupplicantStaIfaceHidlTest : public SupplicantHidlTestBaseV1_4 { + public: + virtual void SetUp() override { + SupplicantHidlTestBaseV1_4::SetUp(); + sta_iface_ = getSupplicantStaIface_1_4(supplicant_); + ASSERT_NE(sta_iface_.get(), nullptr); + + memcpy(mac_addr_.data(), kTestMacAddr, mac_addr_.size()); + } + + protected: + // ISupplicantStaIface object used for all tests in this fixture. + sp sta_iface_; + // MAC address to use for various tests. + std::array mac_addr_; + + bool isDppSupported() { + uint32_t keyMgmtMask = 0; + + // We need to first get the key management capabilities from the device. + // If DPP is not supported, we just pass the test. + sta_iface_->getKeyMgmtCapabilities_1_3( + [&](const SupplicantStatus& status, uint32_t keyMgmtMaskInternal) { + EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code); + keyMgmtMask = keyMgmtMaskInternal; + }); + + if (!(keyMgmtMask & ISupplicantStaNetwork::KeyMgmtMask::DPP)) { + // DPP not supported + return false; + } + return true; + } +}; + +class IfaceCallback : public ISupplicantStaIfaceCallback { + Return onNetworkAdded(uint32_t /* id */) override { return Void(); } + Return onNetworkRemoved(uint32_t /* id */) override { return Void(); } + Return onStateChanged( + ISupplicantStaIfaceCallback::State /* newState */, + const hidl_array& /*bssid */, uint32_t /* id */, + const hidl_vec& /* ssid */) override { + return Void(); + } + Return onAnqpQueryDone( + const hidl_array& /* bssid */, + const ::android::hardware::wifi::supplicant::V1_0:: + ISupplicantStaIfaceCallback::AnqpData& /* data */, + const ISupplicantStaIfaceCallback::Hs20AnqpData& /* hs20Data */) + override { + return Void(); + } + virtual Return onHs20IconQueryDone( + const hidl_array& /* bssid */, + const hidl_string& /* fileName */, + const hidl_vec& /* data */) override { + return Void(); + } + virtual Return onHs20SubscriptionRemediation( + const hidl_array& /* bssid */, + ISupplicantStaIfaceCallback::OsuMethod /* osuMethod */, + const hidl_string& /* url*/) override { + return Void(); + } + Return onHs20TermsAndConditionsAcceptanceRequestedNotification( + const hidl_array& /* bssid */, + const hidl_string& /* url */) override { + return Void(); + } + Return onHs20DeauthImminentNotice( + const hidl_array& /* bssid */, uint32_t /* reasonCode */, + uint32_t /* reAuthDelayInSec */, + const hidl_string& /* url */) override { + return Void(); + } + Return onDisconnected(const hidl_array& /* bssid */, + bool /* locallyGenerated */, + ISupplicantStaIfaceCallback::ReasonCode + /* reasonCode */) override { + return Void(); + } + Return onAssociationRejected( + const hidl_array& /* bssid */, + ISupplicantStaIfaceCallback::StatusCode /* statusCode */, + bool /*timedOut */) override { + return Void(); + } + Return onAuthenticationTimeout( + const hidl_array& /* bssid */) override { + return Void(); + } + Return onBssidChanged( + ISupplicantStaIfaceCallback::BssidChangeReason /* reason */, + const hidl_array& /* bssid */) override { + return Void(); + } + Return onEapFailure() override { return Void(); } + Return onEapFailure_1_1( + ISupplicantStaIfaceCallback::EapErrorCode /* eapErrorCode */) override { + return Void(); + } + Return onEapFailure_1_3(uint32_t /* eapErrorCode */) override { + return Void(); + } + Return onWpsEventSuccess() override { return Void(); } + Return onWpsEventFail( + const hidl_array& /* bssid */, + ISupplicantStaIfaceCallback::WpsConfigError /* configError */, + ISupplicantStaIfaceCallback::WpsErrorIndication /* errorInd */) + override { + return Void(); + } + Return onWpsEventPbcOverlap() override { return Void(); } + Return onExtRadioWorkStart(uint32_t /* id */) override { + return Void(); + } + Return onExtRadioWorkTimeout(uint32_t /* id*/) override { + return Void(); + } + Return onDppSuccessConfigReceived( + const hidl_vec& /* ssid */, const hidl_string& /* password */, + const hidl_array& /* psk */, + DppAkm /* securityAkm */) override { + return Void(); + } + Return onDppSuccessConfigSent() override { return Void(); } + Return onDppProgress(DppProgressCode /* code */) override { + return Void(); + } + Return onDppFailure(DppFailureCode /* code */) override { + return Void(); + } + Return onDppSuccess(DppSuccessCode /* code */) override { + return Void(); + } + Return onDppProgress_1_3( + ::android::hardware::wifi::supplicant::V1_3::DppProgressCode /* code */) + override { + return Void(); + } + Return onDppFailure_1_3( + ::android::hardware::wifi::supplicant::V1_3::DppFailureCode /* code */, + const hidl_string& /* ssid */, const hidl_string& /* channelList */, + const hidl_vec& /* bandList */) override { + return Void(); + } + Return onPmkCacheAdded( + int64_t /* expirationTimeInSec */, + const hidl_vec& /* serializedEntry */) override { + return Void(); + } + Return onBssTmHandlingDone( + const ISupplicantStaIfaceCallback::BssTmData& /* data */) override { + return Void(); + } + Return onStateChanged_1_3( + ISupplicantStaIfaceCallback::State /* newState */, + const hidl_array& /*bssid */, uint32_t /* id */, + const hidl_vec& /* ssid */, bool /* filsHlpSent */) override { + return Void(); + } + Return onAnqpQueryDone_1_4( + const hidl_array& /* bssid */, + const ::android::hardware::wifi::supplicant::V1_4:: + ISupplicantStaIfaceCallback::AnqpData& /* data */, + const ISupplicantStaIfaceCallback::Hs20AnqpData& /* hs20Data */) + override { + return Void(); + } + Return onAssociationRejected_1_4( + const ISupplicantStaIfaceCallback::AssociationRejectionData& /* data */) + override { + return Void(); + } + Return onNetworkNotFound( + const hidl_vec& /* ssid */) override { + return Void(); + } +}; + +/* + * getConnectionCapabilities_1_4 + */ +TEST_P(SupplicantStaIfaceHidlTest, GetConnectionCapabilities) { + sta_iface_->getConnectionCapabilities_1_4( + [&](const SupplicantStatusV1_4& status, + ConnectionCapabilities /* capabilities */) { + EXPECT_EQ(SupplicantStatusCodeV1_4::SUCCESS, status.code); + }); +} + +/* + * RegisterCallback_1_4 + */ +TEST_P(SupplicantStaIfaceHidlTest, RegisterCallback_1_4) { + sta_iface_->registerCallback_1_4( + new IfaceCallback(), [](const SupplicantStatusV1_4& status) { + EXPECT_EQ(SupplicantStatusCodeV1_4::SUCCESS, status.code); + }); +} + +/* + * InitiateVenueUrlAnqpQuery. + */ +TEST_P(SupplicantStaIfaceHidlTest, InitiateVenueUrlAnqpQuery) { + sta_iface_->initiateVenueUrlAnqpQuery( + mac_addr_, [](const SupplicantStatusV1_4& status) { + // These requests will fail unless the BSSID mentioned is actually + // present in scan results. + EXPECT_EQ(SupplicantStatusCodeV1_4::FAILURE_UNKNOWN, status.code); + }); +} + +/* + * GetWpaDriverCapabilities + */ +TEST_P(SupplicantStaIfaceHidlTest, GetWpaDriverCapabilities) { + sta_iface_->getWpaDriverCapabilities_1_4( + [&](const SupplicantStatusV1_4& status, uint32_t) { + EXPECT_EQ(SupplicantStatusCodeV1_4::SUCCESS, status.code); + }); +} + +/* + * StartDppEnrolleeResponder + */ +TEST_P(SupplicantStaIfaceHidlTest, StartDppEnrolleeResponder) { + // We need to first get the key management capabilities from the device. + // If DPP is not supported, we just pass the test. + if (!isDppSupported()) { + // DPP not supported + return; + } + + hidl_string deviceInfo = "DPP_Responder_Mode_VTS_Test"; + uint32_t bootstrap_id = 0; + uint32_t listen_channel = 0; + uint8_t mac_address[6] = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + + // Generate DPP bootstrap information + sta_iface_->generateDppBootstrapInfoForResponder( + mac_address, deviceInfo, DppCurve::PRIME256V1, + [&](const SupplicantStatusV1_4& status, + DppResponderBootstrapInfo bootstrapInfo) { + EXPECT_EQ(SupplicantStatusCodeV1_4::SUCCESS, status.code); + EXPECT_NE(-1, bootstrapInfo.bootstrapId); + EXPECT_NE(0, bootstrapInfo.bootstrapId); + bootstrap_id = bootstrapInfo.bootstrapId; + listen_channel = bootstrapInfo.listenChannel; + EXPECT_NE(0, bootstrapInfo.listenChannel); + }); + + // Start DPP as Enrollee-Responder. + sta_iface_->startDppEnrolleeResponder( + listen_channel, [&](const SupplicantStatusV1_4& status) { + EXPECT_EQ(SupplicantStatusCodeV1_4::SUCCESS, status.code); + }); + + // Stop DPP Enrollee-Responder mode, ie remove the URI and stop listen. + sta_iface_->stopDppResponder( + bootstrap_id, [&](const SupplicantStatusV1_4& status) { + EXPECT_EQ(SupplicantStatusCodeV1_4::SUCCESS, status.code); + }); +} + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SupplicantStaIfaceHidlTest); +INSTANTIATE_TEST_CASE_P( + PerInstance, SupplicantStaIfaceHidlTest, + testing::Combine( + testing::ValuesIn(android::hardware::getAllHalInstanceNames( + android::hardware::wifi::V1_0::IWifi::descriptor)), + testing::ValuesIn(android::hardware::getAllHalInstanceNames( + android::hardware::wifi::supplicant::V1_4::ISupplicant:: + descriptor))), + android::hardware::PrintInstanceTupleNameToString<>); diff --git a/wifi/supplicant/1.4/vts/functional/supplicant_sta_network_hidl_test.cpp b/wifi/supplicant/1.4/vts/functional/supplicant_sta_network_hidl_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..49d471bbc45aa6741db51ec68f889c46f6fa9e57 --- /dev/null +++ b/wifi/supplicant/1.4/vts/functional/supplicant_sta_network_hidl_test.cpp @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "supplicant_hidl_test_utils.h" +#include "supplicant_hidl_test_utils_1_4.h" + +using ::android::sp; +using ::android::hardware::hidl_array; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::wifi::supplicant::V1_0::IfaceType; +using ::android::hardware::wifi::supplicant::V1_0::ISupplicant; +using ::android::hardware::wifi::supplicant::V1_0::ISupplicantStaIface; +using ::android::hardware::wifi::supplicant::V1_0::ISupplicantStaNetwork; +using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatus; +using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode; +using ::android::hardware::wifi::supplicant::V1_4:: + ISupplicantStaNetworkCallback; +using ::android::hardware::wifi::V1_0::IWifi; +using ISupplicantStaNetworkV1_4 = + ::android::hardware::wifi::supplicant::V1_4::ISupplicantStaNetwork; +using SupplicantStatusV1_4 = + ::android::hardware::wifi::supplicant::V1_4::SupplicantStatus; +using SupplicantStatusCodeV1_4 = + ::android::hardware::wifi::supplicant::V1_4::SupplicantStatusCode; +using WpaDriverCapabilitiesMaskV1_4 = + ::android::hardware::wifi::supplicant::V1_4::WpaDriverCapabilitiesMask; + +class SupplicantStaNetworkHidlTest : public SupplicantHidlTestBaseV1_4 { + public: + virtual void SetUp() override { + SupplicantHidlTestBaseV1_4::SetUp(); + sta_iface_ = getSupplicantStaIface_1_4(supplicant_); + ASSERT_NE(nullptr, sta_iface_.get()); + sta_network_ = createSupplicantStaNetwork(supplicant_); + ASSERT_NE(sta_network_.get(), nullptr); + /* variable used to check if the underlying HAL version is 1.4 or + * higher. This is to skip tests which are using deprecated methods. + */ + v1_4 = ::android::hardware::wifi::supplicant::V1_4:: + ISupplicantStaNetwork::castFrom(sta_network_); + } + + protected: + sp<::android::hardware::wifi::supplicant::V1_4::ISupplicantStaIface> + sta_iface_; + sp<::android::hardware::wifi::supplicant::V1_4::ISupplicantStaNetwork> + v1_4 = nullptr; + // ISupplicantStaNetwork object used for all tests in this fixture. + sp sta_network_; + bool isSaePkSupported() { + uint32_t caps; + sta_iface_->getWpaDriverCapabilities_1_4( + [&](const SupplicantStatusV1_4& status, uint32_t capsInternal) { + EXPECT_EQ(SupplicantStatusCodeV1_4::SUCCESS, status.code); + caps = capsInternal; + }); + return !!(caps & WpaDriverCapabilitiesMaskV1_4::SAE_PK); + } +}; + +class NetworkCallback : public ISupplicantStaNetworkCallback { + Return onNetworkEapSimGsmAuthRequest( + const ISupplicantStaNetworkCallback::NetworkRequestEapSimGsmAuthParams& + /* params */) override { + return Void(); + } + Return onNetworkEapSimUmtsAuthRequest( + const ISupplicantStaNetworkCallback::NetworkRequestEapSimUmtsAuthParams& + /* params */) override { + return Void(); + } + Return onNetworkEapIdentityRequest() override { return Void(); } + Return onTransitionDisable(uint32_t /* params */) override { + return Void(); + } +}; + +/* + * RegisterCallback + */ +TEST_P(SupplicantStaNetworkHidlTest, RegisterCallback_1_4) { + v1_4->registerCallback_1_4( + new NetworkCallback(), [](const SupplicantStatusV1_4& status) { + EXPECT_EQ(SupplicantStatusCodeV1_4::SUCCESS, status.code); + }); +} + +/* + * set SAE H2E (Hash-to-Element) mode + */ +TEST_P(SupplicantStaNetworkHidlTest, SetSaeH2eMode) { + v1_4->setSaeH2eMode(ISupplicantStaNetworkV1_4::SaeH2eMode::DISABLED, + [&](const SupplicantStatusV1_4& status) { + EXPECT_EQ(SupplicantStatusCodeV1_4::SUCCESS, + status.code); + }); + v1_4->setSaeH2eMode(ISupplicantStaNetworkV1_4::SaeH2eMode::H2E_MANDATORY, + [&](const SupplicantStatusV1_4& status) { + EXPECT_EQ(SupplicantStatusCodeV1_4::SUCCESS, + status.code); + }); + v1_4->setSaeH2eMode(ISupplicantStaNetworkV1_4::SaeH2eMode::H2E_OPTIONAL, + [&](const SupplicantStatusV1_4& status) { + EXPECT_EQ(SupplicantStatusCodeV1_4::SUCCESS, + status.code); + }); +} + +/* + * enable SAE PK only mode + */ +TEST_P(SupplicantStaNetworkHidlTest, EnableSaePkOnlyMode) { + LOG(INFO) << "SAE-PK Supported: " << isSaePkSupported(); + SupplicantStatusCodeV1_4 expectedCode = + isSaePkSupported() ? SupplicantStatusCodeV1_4::SUCCESS + : SupplicantStatusCodeV1_4::FAILURE_UNSUPPORTED; + v1_4->enableSaePkOnlyMode(true, [&](const SupplicantStatusV1_4& status) { + EXPECT_EQ(expectedCode, status.code); + }); + v1_4->enableSaePkOnlyMode(false, [&](const SupplicantStatusV1_4& status) { + EXPECT_EQ(expectedCode, status.code); + }); +} + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SupplicantStaNetworkHidlTest); +INSTANTIATE_TEST_CASE_P( + PerInstance, SupplicantStaNetworkHidlTest, + testing::Combine( + testing::ValuesIn( + android::hardware::getAllHalInstanceNames(IWifi::descriptor)), + testing::ValuesIn(android::hardware::getAllHalInstanceNames( + android::hardware::wifi::supplicant::V1_4::ISupplicant:: + descriptor))), + android::hardware::PrintInstanceTupleNameToString<>);