1 /*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "EmulatedVehicleHardware"
18
19 #include "EmulatedVehicleHardware.h"
20 #include "VehicleEmulator.h"
21
22 #include <VehicleHalTypes.h>
23 #include <VehicleUtils.h>
24 #include <android-base/properties.h>
25 #include <android/binder_manager.h>
26 #include <utils/Log.h>
27
28 namespace android {
29 namespace hardware {
30 namespace automotive {
31 namespace vehicle {
32 namespace fake {
33
34 using ::aidl::android::hardware::automotive::vehicle::StatusCode;
35 using ::aidl::android::hardware::automotive::vehicle::SetValueRequest;
36 using ::aidl::android::hardware::automotive::vehicle::SetValueResult;
37 using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
38 using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
39 using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
40
41 using ::android::base::Result;
42 using ::android::hardware::automotive::vehicle::V2_0::impl::MessageSender;
43
EmulatedVehicleHardware()44 EmulatedVehicleHardware::EmulatedVehicleHardware() {
45 mInQemu = isInQemu();
46 ALOGD("mInQemu=%s", mInQemu ? "true" : "false");
47
48 mVehicleBusCallback = ::ndk::SharedRefBase::make<VehicleBusCallback>(this);
49 mEmulator = std::make_unique<VehicleEmulator>(this);
50 startVehicleBuses();
51 }
52
EmulatedVehicleHardware(bool inQemu,std::unique_ptr<MessageSender> socketComm,std::unique_ptr<MessageSender> pipeComm)53 EmulatedVehicleHardware::EmulatedVehicleHardware(
54 bool inQemu,
55 std::unique_ptr<MessageSender> socketComm,
56 std::unique_ptr<MessageSender> pipeComm) {
57 mInQemu = inQemu;
58 mEmulator = std::make_unique<VehicleEmulator>(std::move(socketComm), std::move(pipeComm), this);
59 }
60
getEmulator()61 VehicleEmulator* EmulatedVehicleHardware::getEmulator() {
62 return mEmulator.get();
63 }
64
~EmulatedVehicleHardware()65 EmulatedVehicleHardware::~EmulatedVehicleHardware() {
66 mEmulator.reset();
67 stopVehicleBuses();
68 }
69
setValues(std::shared_ptr<const SetValuesCallback> callback,const std::vector<SetValueRequest> & requests)70 StatusCode EmulatedVehicleHardware::setValues(
71 std::shared_ptr<const SetValuesCallback> callback,
72 const std::vector<SetValueRequest>& requests) {
73 std::vector<SetValueResult> results;
74
75 for (const auto& request: requests) {
76 const VehiclePropValue& value = request.value;
77 int propId = value.prop;
78
79 ALOGD("Set value for property ID: %d", propId);
80
81 if (mInQemu && propId == toInt(VehicleProperty::DISPLAY_BRIGHTNESS)) {
82 ALOGD("Return OKAY for DISPLAY_BRIGHTNESS in QEMU");
83
84 // Emulator does not support remote brightness control, b/139959479
85 // do not send it down so that it does not bring unnecessary property change event
86 // return other error code, such NOT_AVAILABLE, causes Emulator to be freezing
87 // TODO: return StatusCode::NOT_AVAILABLE once the above issue is fixed
88 results.push_back({
89 .requestId = request.requestId,
90 .status = StatusCode::OK,
91 });
92 continue;
93 }
94
95 SetValueResult setValueResult;
96 setValueResult.requestId = request.requestId;
97
98 if (auto result = setValue(value); !result.ok()) {
99 ALOGE("failed to set value, error: %s, code: %d", getErrorMsg(result).c_str(),
100 getIntErrorCode(result));
101 setValueResult.status = getErrorCode(result);
102 } else {
103 setValueResult.status = StatusCode::OK;
104 // Inform the emulator about a new value change.
105 mEmulator->doSetValueFromClient(value);
106 }
107
108 results.push_back(std::move(setValueResult));
109 }
110 // In real Vehicle HAL, the values would be sent to vehicle bus. But here, we just assume
111 // it is done and notify the client.
112 (*callback)(std::move(results));
113
114 return StatusCode::OK;
115 }
116
startVehicleBuses()117 void EmulatedVehicleHardware::startVehicleBuses() {
118 std::vector<std::string> names;
119 AServiceManager_forEachDeclaredInstance(IVehicleBus::descriptor, static_cast<void*>(&names),
120 [](const char* instance, void* context) {
121 auto fullName = std::string(IVehicleBus::descriptor) + "/" + instance;
122 static_cast<std::vector<std::string>*>(context)->push_back(fullName);
123 });
124
125 for (const auto& fullName : names) {
126 ::ndk::SpAIBinder binder(AServiceManager_waitForService(fullName.c_str()));
127 if (binder.get() == nullptr) {
128 ALOGE("%s binder returned null", fullName.c_str());
129 continue;
130 }
131 std::shared_ptr<IVehicleBus> vehicleBus = IVehicleBus::fromBinder(binder);
132 if (vehicleBus == nullptr) {
133 ALOGE("Couldn't open %s", fullName.c_str());
134 continue;
135 }
136
137 vehicleBus->setOnNewPropValuesCallback(mVehicleBusCallback);
138 mVehicleBuses.push_back(vehicleBus);
139 }
140 }
141
onNewPropValues(const std::vector<AidlVehiclePropValue> & aidlPropValues)142 ::ndk::ScopedAStatus EmulatedVehicleHardware::VehicleBusCallback::onNewPropValues(
143 const std::vector<AidlVehiclePropValue>& aidlPropValues) {
144 for (const auto& aidlPropValue : aidlPropValues) {
145 if (auto result = mVehicleHardware->setValue(aidlPropValue); !result.ok()) {
146 ALOGE("Failed to set value, error: %s", getErrorMsg(result).c_str());
147 continue;
148 }
149 }
150 return ::ndk::ScopedAStatus::ok();
151 }
152
stopVehicleBuses()153 void EmulatedVehicleHardware::stopVehicleBuses() {
154 for (const auto& vehicleBus : mVehicleBuses) {
155 vehicleBus->unsetOnNewPropValuesCallback(mVehicleBusCallback);
156 }
157 }
158
getAllProperties() const159 std::vector<VehiclePropValuePool::RecyclableType> EmulatedVehicleHardware::getAllProperties()
160 const {
161 return mServerSidePropStore->readAllValues();
162 }
163
getPropConfig(int32_t propId) const164 EmulatedVehicleHardware::ConfigResultType EmulatedVehicleHardware::getPropConfig(int32_t propId)
165 const {
166 return mServerSidePropStore->getConfig(propId);
167 }
168
isInQemu()169 bool EmulatedVehicleHardware::isInQemu() {
170 return android::base::GetBoolProperty("ro.boot.qemu", false);
171 }
172
173 } // namespace fake
174 } // namespace vehicle
175 } // namespace automotive
176 } // namespace hardware
177 } // namespace android
178
179