Loading automotive/vehicle/2.0/default/Android.bp +14 −1 Original line number Diff line number Diff line Loading @@ -75,7 +75,10 @@ cc_library_static { ], local_include_dirs: ["common/include/vhal_v2_0"], export_include_dirs: ["impl"], whole_static_libs: ["android.hardware.automotive.vehicle@2.0-manager-lib"], whole_static_libs: [ "android.hardware.automotive.vehicle@2.0-emulated-user-hal-lib", "android.hardware.automotive.vehicle@2.0-manager-lib", ], shared_libs: [ "libbase", "libjsoncpp", Loading @@ -87,6 +90,16 @@ cc_library_static { ], } // Library used to emulate User HAL behavior through lshal debug requests. cc_library_static { name: "android.hardware.automotive.vehicle@2.0-emulated-user-hal-lib", vendor: true, defaults: ["vhal_v2_0_defaults"], srcs: [ "impl/vhal_v2_0/EmulatedUserHal.cpp", ], } cc_test { name: "android.hardware.automotive.vehicle@2.0-manager-unit-tests", vendor: true, Loading automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h +0 −2 Original line number Diff line number Diff line Loading @@ -79,8 +79,6 @@ 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; constexpr int INITIAL_USER_INFO = (int)VehicleProperty::INITIAL_USER_INFO; constexpr int SWITCH_USER = (int)VehicleProperty::SWITCH_USER; /** * This property is used for test purpose to generate fake events. Here is the test package that Loading automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp 0 → 100644 +186 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT 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 "EmulatedUserHal" #include <cutils/log.h> #include <utils/SystemClock.h> #include "EmulatedUserHal.h" namespace android { namespace hardware { namespace automotive { namespace vehicle { namespace V2_0 { namespace impl { constexpr int INITIAL_USER_INFO = static_cast<int>(VehicleProperty::INITIAL_USER_INFO); constexpr int SWITCH_USER = static_cast<int>(VehicleProperty::SWITCH_USER); bool EmulatedUserHal::isSupported(int32_t prop) { switch (prop) { case INITIAL_USER_INFO: case SWITCH_USER: return true; default: return false; } } android::base::Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetProperty( const VehiclePropValue& value) { ALOGV("onSetProperty(): %s", toString(value).c_str()); switch (value.prop) { case INITIAL_USER_INFO: return onSetInitialUserInfoResponse(value); case SWITCH_USER: return onSetSwitchUserResponse(value); default: return android::base::Error(static_cast<int>(StatusCode::INVALID_ARG)) << "Unsupported property: " << toString(value); } } android::base::Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetInitialUserInfoResponse(const VehiclePropValue& value) { if (value.value.int32Values.size() == 0) { ALOGE("set(INITIAL_USER_INFO): no int32values, ignoring it: %s", toString(value).c_str()); return android::base::Error(static_cast<int>(StatusCode::INVALID_ARG)) << "no int32values on " << toString(value); } if (value.areaId != 0) { ALOGD("set(INITIAL_USER_INFO) called from lshal; storing it: %s", toString(value).c_str()); mInitialUserResponseFromCmd.reset(new VehiclePropValue(value)); return {}; } ALOGD("set(INITIAL_USER_INFO) called from Android: %s", toString(value).c_str()); int32_t requestId = value.value.int32Values[0]; if (mInitialUserResponseFromCmd != nullptr) { ALOGI("replying INITIAL_USER_INFO with lshal value: %s", toString(*mInitialUserResponseFromCmd).c_str()); return sendUserHalResponse(std::move(mInitialUserResponseFromCmd), requestId); } // Returns default response auto updatedValue = std::unique_ptr<VehiclePropValue>(new VehiclePropValue); updatedValue->prop = INITIAL_USER_INFO; updatedValue->timestamp = elapsedRealtimeNano(); updatedValue->value.int32Values.resize(2); updatedValue->value.int32Values[0] = requestId; updatedValue->value.int32Values[1] = (int32_t)InitialUserInfoResponseAction::DEFAULT; ALOGI("no lshal response; replying with InitialUserInfoResponseAction::DEFAULT: %s", toString(*updatedValue).c_str()); return updatedValue; } android::base::Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetSwitchUserResponse( const VehiclePropValue& value) { if (value.value.int32Values.size() == 0) { ALOGE("set(SWITCH_USER): no int32values, ignoring it: %s", toString(value).c_str()); return android::base::Error(static_cast<int>(StatusCode::INVALID_ARG)) << "no int32values on " << toString(value); } if (value.areaId != 0) { ALOGD("set(SWITCH_USER) called from lshal; storing it: %s", toString(value).c_str()); mSwitchUserResponseFromCmd.reset(new VehiclePropValue(value)); return {}; } ALOGD("set(SWITCH_USER) called from Android: %s", toString(value).c_str()); int32_t requestId = value.value.int32Values[0]; if (mSwitchUserResponseFromCmd != nullptr) { ALOGI("replying SWITCH_USER with lshal value: %s", toString(*mSwitchUserResponseFromCmd).c_str()); return sendUserHalResponse(std::move(mSwitchUserResponseFromCmd), requestId); } // Returns default response auto updatedValue = std::unique_ptr<VehiclePropValue>(new VehiclePropValue); updatedValue->prop = SWITCH_USER; updatedValue->timestamp = elapsedRealtimeNano(); updatedValue->value.int32Values.resize(3); updatedValue->value.int32Values[0] = requestId; updatedValue->value.int32Values[1] = (int32_t)SwitchUserMessageType::VEHICLE_RESPONSE; updatedValue->value.int32Values[2] = (int32_t)SwitchUserStatus::SUCCESS; ALOGI("no lshal response; replying with VEHICLE_RESPONSE / SUCCESS: %s", toString(*updatedValue).c_str()); return updatedValue; } android::base::Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::sendUserHalResponse( std::unique_ptr<VehiclePropValue> response, int32_t requestId) { switch (response->areaId) { case 1: ALOGD("returning response with right request id"); response->value.int32Values[0] = requestId; break; case 2: ALOGD("returning response with wrong request id"); response->value.int32Values[0] = -requestId; break; case 3: ALOGD("not generating a property change event because of lshal prop: %s", toString(*response).c_str()); return android::base::Error(static_cast<int>(StatusCode::NOT_AVAILABLE)) << "not generating a property change event because of lshal prop: " << toString(*response); default: ALOGE("invalid action on lshal response: %s", toString(*response).c_str()); return android::base::Error(static_cast<int>(StatusCode::INTERNAL_ERROR)) << "invalid action on lshal response: " << toString(*response); } ALOGD("updating property to: %s", toString(*response).c_str()); return response; } void EmulatedUserHal::showDumpHelp(int fd) { dprintf(fd, "%s: dumps state used for user management\n", kUserHalDumpOption); } void EmulatedUserHal::dump(int fd, std::string indent) { if (mInitialUserResponseFromCmd != nullptr) { dprintf(fd, "%sInitialUserInfo response: %s\n", indent.c_str(), toString(*mInitialUserResponseFromCmd).c_str()); } else { dprintf(fd, "%sNo InitialUserInfo response\n", indent.c_str()); } if (mSwitchUserResponseFromCmd != nullptr) { dprintf(fd, "%sSwitchUser response: %s\n", indent.c_str(), toString(*mSwitchUserResponseFromCmd).c_str()); } else { dprintf(fd, "%sNo SwitchUser response\n", indent.c_str()); } } } // namespace impl } // namespace V2_0 } // namespace vehicle } // namespace automotive } // namespace hardware } // namespace android automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.h 0 → 100644 +115 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef android_hardware_automotive_vehicle_V2_0_impl_EmulatedUserHal_H_ #define android_hardware_automotive_vehicle_V2_0_impl_EmulatedUserHal_H_ #include <android-base/result.h> #include <android/hardware/automotive/vehicle/2.0/types.h> namespace android { namespace hardware { namespace automotive { namespace vehicle { namespace V2_0 { namespace impl { constexpr char kUserHalDumpOption[] = "--user-hal"; /** * Class used to emulate User HAL behavior through lshal debug requests. */ class EmulatedUserHal { public: EmulatedUserHal() {} ~EmulatedUserHal() = default; /** * Checks if the emulator can handle the property. */ bool isSupported(int32_t prop); /** * Lets the emulator handle the property. * * @return updated property and StatusCode */ android::base::Result<std::unique_ptr<VehiclePropValue>> onSetProperty( const VehiclePropValue& value); /** * Shows the User HAL emulation help. */ void showDumpHelp(int fd); /** * Dump its contents. */ void dump(int fd, std::string indent); private: /** * INITIAL_USER_INFO is called by Android when it starts, and it's expecting a property change * indicating what the initial user should be. * * During normal circumstances, the emulator will reply right away, passing a response if * InitialUserInfoResponseAction::DEFAULT (so Android could use its own logic to decide which * user to boot). * * But during development / testing, the behavior can be changed using lshal dump, which must * use the areaId to indicate what should happen next. * * So, the behavior of set(INITIAL_USER_INFO) is: * * - if it has an areaId, store the property into mInitialUserResponseFromCmd (as it was called * by lshal). * - else if mInitialUserResponseFromCmd is not set, return a response with the same request id * and InitialUserInfoResponseAction::DEFAULT * - else the behavior is defined by the areaId on mInitialUserResponseFromCmd: * - if it's 1, reply with mInitialUserResponseFromCmd and the right request id * - if it's 2, reply with mInitialUserResponseFromCmd but a wrong request id (so Android can * test this error scenario) * - if it's 3, then don't send a property change (so Android can emulate a timeout) * */ android::base::Result<std::unique_ptr<VehiclePropValue>> onSetInitialUserInfoResponse( const VehiclePropValue& value); /** * Used to emulate SWITCH_USER - see onSetInitialUserInfoResponse() for usage. */ android::base::Result<std::unique_ptr<VehiclePropValue>> onSetSwitchUserResponse( const VehiclePropValue& value); android::base::Result<std::unique_ptr<VehiclePropValue>> sendUserHalResponse( std::unique_ptr<VehiclePropValue> response, int32_t requestId); std::unique_ptr<VehiclePropValue> mInitialUserResponseFromCmd; std::unique_ptr<VehiclePropValue> mSwitchUserResponseFromCmd; }; } // namespace impl } // namespace V2_0 } // namespace vehicle } // namespace automotive } // namespace hardware } // namespace android #endif // android_hardware_automotive_vehicle_V2_0_impl_EmulatedUserHal_H_ automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp +4 −22 Original line number Diff line number Diff line Loading @@ -38,9 +38,6 @@ namespace impl { class EmulatedPassthroughConnector : public PassthroughConnector { public: bool onDump(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override; private: void dumpUserHal(int fd, std::string indent); }; bool EmulatedPassthroughConnector::onDump(const hidl_handle& handle, Loading @@ -50,12 +47,12 @@ bool EmulatedPassthroughConnector::onDump(const hidl_handle& handle, if (options.size() > 0) { if (options[0] == "--help") { dprintf(fd, "Emulator-specific usage:\n"); dprintf(fd, "--user-hal: dumps state used for user management \n"); mEmulatedUserHal.showDumpHelp(fd); dprintf(fd, "\n"); // Include caller's help options return true; } else if (options[0] == "--user-hal") { dumpUserHal(fd, ""); } else if (options[0] == kUserHalDumpOption) { mEmulatedUserHal.dump(fd, ""); return false; } else { Loading @@ -65,27 +62,12 @@ bool EmulatedPassthroughConnector::onDump(const hidl_handle& handle, } dprintf(fd, "Emulator-specific state:\n"); dumpUserHal(fd, " "); mEmulatedUserHal.dump(fd, " "); dprintf(fd, "\n"); return true; } void EmulatedPassthroughConnector::dumpUserHal(int fd, std::string indent) { if (mInitialUserResponseFromCmd != nullptr) { dprintf(fd, "%sInitialUserInfo response: %s\n", indent.c_str(), toString(*mInitialUserResponseFromCmd).c_str()); } else { dprintf(fd, "%sNo InitialUserInfo response\n", indent.c_str()); } if (mSwitchUserResponseFromCmd != nullptr) { dprintf(fd, "%sSwitchUser response: %s\n", indent.c_str(), toString(*mSwitchUserResponseFromCmd).c_str()); } else { dprintf(fd, "%sNo SwitchUser response\n", indent.c_str()); } } PassthroughConnectorPtr makeEmulatedPassthroughConnector() { return std::make_unique<EmulatedPassthroughConnector>(); } Loading Loading
automotive/vehicle/2.0/default/Android.bp +14 −1 Original line number Diff line number Diff line Loading @@ -75,7 +75,10 @@ cc_library_static { ], local_include_dirs: ["common/include/vhal_v2_0"], export_include_dirs: ["impl"], whole_static_libs: ["android.hardware.automotive.vehicle@2.0-manager-lib"], whole_static_libs: [ "android.hardware.automotive.vehicle@2.0-emulated-user-hal-lib", "android.hardware.automotive.vehicle@2.0-manager-lib", ], shared_libs: [ "libbase", "libjsoncpp", Loading @@ -87,6 +90,16 @@ cc_library_static { ], } // Library used to emulate User HAL behavior through lshal debug requests. cc_library_static { name: "android.hardware.automotive.vehicle@2.0-emulated-user-hal-lib", vendor: true, defaults: ["vhal_v2_0_defaults"], srcs: [ "impl/vhal_v2_0/EmulatedUserHal.cpp", ], } cc_test { name: "android.hardware.automotive.vehicle@2.0-manager-unit-tests", vendor: true, Loading
automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h +0 −2 Original line number Diff line number Diff line Loading @@ -79,8 +79,6 @@ 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; constexpr int INITIAL_USER_INFO = (int)VehicleProperty::INITIAL_USER_INFO; constexpr int SWITCH_USER = (int)VehicleProperty::SWITCH_USER; /** * This property is used for test purpose to generate fake events. Here is the test package that Loading
automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp 0 → 100644 +186 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT 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 "EmulatedUserHal" #include <cutils/log.h> #include <utils/SystemClock.h> #include "EmulatedUserHal.h" namespace android { namespace hardware { namespace automotive { namespace vehicle { namespace V2_0 { namespace impl { constexpr int INITIAL_USER_INFO = static_cast<int>(VehicleProperty::INITIAL_USER_INFO); constexpr int SWITCH_USER = static_cast<int>(VehicleProperty::SWITCH_USER); bool EmulatedUserHal::isSupported(int32_t prop) { switch (prop) { case INITIAL_USER_INFO: case SWITCH_USER: return true; default: return false; } } android::base::Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetProperty( const VehiclePropValue& value) { ALOGV("onSetProperty(): %s", toString(value).c_str()); switch (value.prop) { case INITIAL_USER_INFO: return onSetInitialUserInfoResponse(value); case SWITCH_USER: return onSetSwitchUserResponse(value); default: return android::base::Error(static_cast<int>(StatusCode::INVALID_ARG)) << "Unsupported property: " << toString(value); } } android::base::Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetInitialUserInfoResponse(const VehiclePropValue& value) { if (value.value.int32Values.size() == 0) { ALOGE("set(INITIAL_USER_INFO): no int32values, ignoring it: %s", toString(value).c_str()); return android::base::Error(static_cast<int>(StatusCode::INVALID_ARG)) << "no int32values on " << toString(value); } if (value.areaId != 0) { ALOGD("set(INITIAL_USER_INFO) called from lshal; storing it: %s", toString(value).c_str()); mInitialUserResponseFromCmd.reset(new VehiclePropValue(value)); return {}; } ALOGD("set(INITIAL_USER_INFO) called from Android: %s", toString(value).c_str()); int32_t requestId = value.value.int32Values[0]; if (mInitialUserResponseFromCmd != nullptr) { ALOGI("replying INITIAL_USER_INFO with lshal value: %s", toString(*mInitialUserResponseFromCmd).c_str()); return sendUserHalResponse(std::move(mInitialUserResponseFromCmd), requestId); } // Returns default response auto updatedValue = std::unique_ptr<VehiclePropValue>(new VehiclePropValue); updatedValue->prop = INITIAL_USER_INFO; updatedValue->timestamp = elapsedRealtimeNano(); updatedValue->value.int32Values.resize(2); updatedValue->value.int32Values[0] = requestId; updatedValue->value.int32Values[1] = (int32_t)InitialUserInfoResponseAction::DEFAULT; ALOGI("no lshal response; replying with InitialUserInfoResponseAction::DEFAULT: %s", toString(*updatedValue).c_str()); return updatedValue; } android::base::Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetSwitchUserResponse( const VehiclePropValue& value) { if (value.value.int32Values.size() == 0) { ALOGE("set(SWITCH_USER): no int32values, ignoring it: %s", toString(value).c_str()); return android::base::Error(static_cast<int>(StatusCode::INVALID_ARG)) << "no int32values on " << toString(value); } if (value.areaId != 0) { ALOGD("set(SWITCH_USER) called from lshal; storing it: %s", toString(value).c_str()); mSwitchUserResponseFromCmd.reset(new VehiclePropValue(value)); return {}; } ALOGD("set(SWITCH_USER) called from Android: %s", toString(value).c_str()); int32_t requestId = value.value.int32Values[0]; if (mSwitchUserResponseFromCmd != nullptr) { ALOGI("replying SWITCH_USER with lshal value: %s", toString(*mSwitchUserResponseFromCmd).c_str()); return sendUserHalResponse(std::move(mSwitchUserResponseFromCmd), requestId); } // Returns default response auto updatedValue = std::unique_ptr<VehiclePropValue>(new VehiclePropValue); updatedValue->prop = SWITCH_USER; updatedValue->timestamp = elapsedRealtimeNano(); updatedValue->value.int32Values.resize(3); updatedValue->value.int32Values[0] = requestId; updatedValue->value.int32Values[1] = (int32_t)SwitchUserMessageType::VEHICLE_RESPONSE; updatedValue->value.int32Values[2] = (int32_t)SwitchUserStatus::SUCCESS; ALOGI("no lshal response; replying with VEHICLE_RESPONSE / SUCCESS: %s", toString(*updatedValue).c_str()); return updatedValue; } android::base::Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::sendUserHalResponse( std::unique_ptr<VehiclePropValue> response, int32_t requestId) { switch (response->areaId) { case 1: ALOGD("returning response with right request id"); response->value.int32Values[0] = requestId; break; case 2: ALOGD("returning response with wrong request id"); response->value.int32Values[0] = -requestId; break; case 3: ALOGD("not generating a property change event because of lshal prop: %s", toString(*response).c_str()); return android::base::Error(static_cast<int>(StatusCode::NOT_AVAILABLE)) << "not generating a property change event because of lshal prop: " << toString(*response); default: ALOGE("invalid action on lshal response: %s", toString(*response).c_str()); return android::base::Error(static_cast<int>(StatusCode::INTERNAL_ERROR)) << "invalid action on lshal response: " << toString(*response); } ALOGD("updating property to: %s", toString(*response).c_str()); return response; } void EmulatedUserHal::showDumpHelp(int fd) { dprintf(fd, "%s: dumps state used for user management\n", kUserHalDumpOption); } void EmulatedUserHal::dump(int fd, std::string indent) { if (mInitialUserResponseFromCmd != nullptr) { dprintf(fd, "%sInitialUserInfo response: %s\n", indent.c_str(), toString(*mInitialUserResponseFromCmd).c_str()); } else { dprintf(fd, "%sNo InitialUserInfo response\n", indent.c_str()); } if (mSwitchUserResponseFromCmd != nullptr) { dprintf(fd, "%sSwitchUser response: %s\n", indent.c_str(), toString(*mSwitchUserResponseFromCmd).c_str()); } else { dprintf(fd, "%sNo SwitchUser response\n", indent.c_str()); } } } // namespace impl } // namespace V2_0 } // namespace vehicle } // namespace automotive } // namespace hardware } // namespace android
automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.h 0 → 100644 +115 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef android_hardware_automotive_vehicle_V2_0_impl_EmulatedUserHal_H_ #define android_hardware_automotive_vehicle_V2_0_impl_EmulatedUserHal_H_ #include <android-base/result.h> #include <android/hardware/automotive/vehicle/2.0/types.h> namespace android { namespace hardware { namespace automotive { namespace vehicle { namespace V2_0 { namespace impl { constexpr char kUserHalDumpOption[] = "--user-hal"; /** * Class used to emulate User HAL behavior through lshal debug requests. */ class EmulatedUserHal { public: EmulatedUserHal() {} ~EmulatedUserHal() = default; /** * Checks if the emulator can handle the property. */ bool isSupported(int32_t prop); /** * Lets the emulator handle the property. * * @return updated property and StatusCode */ android::base::Result<std::unique_ptr<VehiclePropValue>> onSetProperty( const VehiclePropValue& value); /** * Shows the User HAL emulation help. */ void showDumpHelp(int fd); /** * Dump its contents. */ void dump(int fd, std::string indent); private: /** * INITIAL_USER_INFO is called by Android when it starts, and it's expecting a property change * indicating what the initial user should be. * * During normal circumstances, the emulator will reply right away, passing a response if * InitialUserInfoResponseAction::DEFAULT (so Android could use its own logic to decide which * user to boot). * * But during development / testing, the behavior can be changed using lshal dump, which must * use the areaId to indicate what should happen next. * * So, the behavior of set(INITIAL_USER_INFO) is: * * - if it has an areaId, store the property into mInitialUserResponseFromCmd (as it was called * by lshal). * - else if mInitialUserResponseFromCmd is not set, return a response with the same request id * and InitialUserInfoResponseAction::DEFAULT * - else the behavior is defined by the areaId on mInitialUserResponseFromCmd: * - if it's 1, reply with mInitialUserResponseFromCmd and the right request id * - if it's 2, reply with mInitialUserResponseFromCmd but a wrong request id (so Android can * test this error scenario) * - if it's 3, then don't send a property change (so Android can emulate a timeout) * */ android::base::Result<std::unique_ptr<VehiclePropValue>> onSetInitialUserInfoResponse( const VehiclePropValue& value); /** * Used to emulate SWITCH_USER - see onSetInitialUserInfoResponse() for usage. */ android::base::Result<std::unique_ptr<VehiclePropValue>> onSetSwitchUserResponse( const VehiclePropValue& value); android::base::Result<std::unique_ptr<VehiclePropValue>> sendUserHalResponse( std::unique_ptr<VehiclePropValue> response, int32_t requestId); std::unique_ptr<VehiclePropValue> mInitialUserResponseFromCmd; std::unique_ptr<VehiclePropValue> mSwitchUserResponseFromCmd; }; } // namespace impl } // namespace V2_0 } // namespace vehicle } // namespace automotive } // namespace hardware } // namespace android #endif // android_hardware_automotive_vehicle_V2_0_impl_EmulatedUserHal_H_
automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp +4 −22 Original line number Diff line number Diff line Loading @@ -38,9 +38,6 @@ namespace impl { class EmulatedPassthroughConnector : public PassthroughConnector { public: bool onDump(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override; private: void dumpUserHal(int fd, std::string indent); }; bool EmulatedPassthroughConnector::onDump(const hidl_handle& handle, Loading @@ -50,12 +47,12 @@ bool EmulatedPassthroughConnector::onDump(const hidl_handle& handle, if (options.size() > 0) { if (options[0] == "--help") { dprintf(fd, "Emulator-specific usage:\n"); dprintf(fd, "--user-hal: dumps state used for user management \n"); mEmulatedUserHal.showDumpHelp(fd); dprintf(fd, "\n"); // Include caller's help options return true; } else if (options[0] == "--user-hal") { dumpUserHal(fd, ""); } else if (options[0] == kUserHalDumpOption) { mEmulatedUserHal.dump(fd, ""); return false; } else { Loading @@ -65,27 +62,12 @@ bool EmulatedPassthroughConnector::onDump(const hidl_handle& handle, } dprintf(fd, "Emulator-specific state:\n"); dumpUserHal(fd, " "); mEmulatedUserHal.dump(fd, " "); dprintf(fd, "\n"); return true; } void EmulatedPassthroughConnector::dumpUserHal(int fd, std::string indent) { if (mInitialUserResponseFromCmd != nullptr) { dprintf(fd, "%sInitialUserInfo response: %s\n", indent.c_str(), toString(*mInitialUserResponseFromCmd).c_str()); } else { dprintf(fd, "%sNo InitialUserInfo response\n", indent.c_str()); } if (mSwitchUserResponseFromCmd != nullptr) { dprintf(fd, "%sSwitchUser response: %s\n", indent.c_str(), toString(*mSwitchUserResponseFromCmd).c_str()); } else { dprintf(fd, "%sNo SwitchUser response\n", indent.c_str()); } } PassthroughConnectorPtr makeEmulatedPassthroughConnector() { return std::make_unique<EmulatedPassthroughConnector>(); } Loading