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     Init();
46 }
47 
EmulatedVehicleHardware(std::string_view default_config_dir,std::string_view override_config_dir,bool force_override)48 EmulatedVehicleHardware::EmulatedVehicleHardware(
49     std::string_view default_config_dir, std::string_view override_config_dir,
50     bool force_override)
51     : FakeVehicleHardware(std::string(default_config_dir),
52                           std::string(override_config_dir), force_override) {
53   Init();
54 }
55 
EmulatedVehicleHardware(bool inQemu,std::unique_ptr<MessageSender> socketComm,std::unique_ptr<MessageSender> pipeComm)56 EmulatedVehicleHardware::EmulatedVehicleHardware(
57         bool inQemu,
58         std::unique_ptr<MessageSender> socketComm,
59         std::unique_ptr<MessageSender> pipeComm) {
60     mInQemu = inQemu;
61     mEmulator = std::make_unique<VehicleEmulator>(std::move(socketComm), std::move(pipeComm), this);
62 }
63 
getEmulator()64 VehicleEmulator* EmulatedVehicleHardware::getEmulator() {
65     return mEmulator.get();
66 }
67 
~EmulatedVehicleHardware()68 EmulatedVehicleHardware::~EmulatedVehicleHardware() {
69     mEmulator.reset();
70     stopVehicleBuses();
71 }
72 
Init()73 void EmulatedVehicleHardware::Init() {
74     mInQemu = isInQemu();
75     ALOGD("mInQemu=%s", mInQemu ? "true" : "false");
76 
77     mVehicleBusCallback = ::ndk::SharedRefBase::make<VehicleBusCallback>(this);
78     mEmulator = std::make_unique<VehicleEmulator>(this);
79     startVehicleBuses();
80 }
81 
setValues(std::shared_ptr<const SetValuesCallback> callback,const std::vector<SetValueRequest> & requests)82 StatusCode EmulatedVehicleHardware::setValues(
83             std::shared_ptr<const SetValuesCallback> callback,
84             const std::vector<SetValueRequest>& requests) {
85     std::vector<SetValueResult> results;
86 
87     for (const auto& request: requests) {
88         const VehiclePropValue& value = request.value;
89         int propId = value.prop;
90 
91         ALOGD("Set value for property ID: %d", propId);
92 
93         if (mInQemu && propId == toInt(VehicleProperty::DISPLAY_BRIGHTNESS)) {
94             ALOGD("Return OKAY for DISPLAY_BRIGHTNESS in QEMU");
95 
96             // Emulator does not support remote brightness control, b/139959479
97             // do not send it down so that it does not bring unnecessary property change event
98             // return other error code, such NOT_AVAILABLE, causes Emulator to be freezing
99             // TODO: return StatusCode::NOT_AVAILABLE once the above issue is fixed
100             results.push_back({
101                 .requestId = request.requestId,
102                 .status = StatusCode::OK,
103             });
104             continue;
105         }
106 
107         SetValueResult setValueResult;
108         setValueResult.requestId = request.requestId;
109 
110         if (auto result = setValue(value); !result.ok()) {
111             ALOGE("failed to set value, error: %s, code: %d", getErrorMsg(result).c_str(),
112                     getIntErrorCode(result));
113             setValueResult.status = getErrorCode(result);
114         } else {
115             setValueResult.status = StatusCode::OK;
116             // Inform the emulator about a new value change.
117             mEmulator->doSetValueFromClient(value);
118         }
119 
120         results.push_back(std::move(setValueResult));
121     }
122     // In real Vehicle HAL, the values would be sent to vehicle bus. But here, we just assume
123     // it is done and notify the client.
124     (*callback)(std::move(results));
125 
126     return StatusCode::OK;
127 }
128 
startVehicleBuses()129 void EmulatedVehicleHardware::startVehicleBuses() {
130     std::vector<std::string> names;
131     AServiceManager_forEachDeclaredInstance(IVehicleBus::descriptor, static_cast<void*>(&names),
132         [](const char* instance, void* context) {
133             auto fullName = std::string(IVehicleBus::descriptor) + "/" + instance;
134             static_cast<std::vector<std::string>*>(context)->push_back(fullName);
135         });
136 
137     for (const auto& fullName : names) {
138         ::ndk::SpAIBinder binder(AServiceManager_waitForService(fullName.c_str()));
139         if (binder.get() == nullptr) {
140             ALOGE("%s binder returned null", fullName.c_str());
141             continue;
142         }
143         std::shared_ptr<IVehicleBus> vehicleBus = IVehicleBus::fromBinder(binder);
144         if (vehicleBus == nullptr) {
145             ALOGE("Couldn't open %s", fullName.c_str());
146             continue;
147         }
148 
149         vehicleBus->setOnNewPropValuesCallback(mVehicleBusCallback);
150         mVehicleBuses.push_back(vehicleBus);
151     }
152 }
153 
onNewPropValues(const std::vector<AidlVehiclePropValue> & aidlPropValues)154 ::ndk::ScopedAStatus EmulatedVehicleHardware::VehicleBusCallback::onNewPropValues(
155         const std::vector<AidlVehiclePropValue>& aidlPropValues) {
156     for (const auto& aidlPropValue : aidlPropValues) {
157         if (auto result = mVehicleHardware->setValue(aidlPropValue); !result.ok()) {
158             ALOGE("Failed to set value, error: %s", getErrorMsg(result).c_str());
159             continue;
160         }
161     }
162     return ::ndk::ScopedAStatus::ok();
163 }
164 
stopVehicleBuses()165 void EmulatedVehicleHardware::stopVehicleBuses() {
166     for (const auto& vehicleBus : mVehicleBuses) {
167         vehicleBus->unsetOnNewPropValuesCallback(mVehicleBusCallback);
168     }
169 }
170 
getAllProperties() const171 std::vector<VehiclePropValuePool::RecyclableType> EmulatedVehicleHardware::getAllProperties()
172         const {
173     return mServerSidePropStore->readAllValues();
174 }
175 
getPropConfig(int32_t propId) const176 EmulatedVehicleHardware::ConfigResultType EmulatedVehicleHardware::getPropConfig(int32_t propId)
177         const {
178     return mServerSidePropStore->getPropConfig(propId);
179 }
180 
isInQemu()181 bool EmulatedVehicleHardware::isInQemu() {
182     return android::base::GetBoolProperty("ro.boot.qemu", false);
183 }
184 
185 }  // namespace fake
186 }  // namespace vehicle
187 }  // namespace automotive
188 }  // namespace hardware
189 }  // namespace android
190 
191