1 /*
2  * Copyright (C) 2019 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 #include "CanClient.h"
18 
19 #include <android-base/logging.h>
20 #include <android/hardware/automotive/can/1.0/ICanMessageListener.h>
21 #include <android/hidl/manager/1.1/IServiceManager.h>
22 #include <hidl-utils/hidl-utils.h>
23 
24 namespace android {
25 namespace hardware {
26 namespace automotive {
27 namespace can {
28 namespace V1_0 {
29 namespace utils {
30 
31 using hidl::manager::V1_1::IServiceManager;
32 using hidl::manager::V1_0::IServiceNotification;
33 
CanClient(const std::string & busName)34 CanClient::CanClient(const std::string& busName) : mBusName(busName) {}
35 
start()36 ::ndk::ScopedAStatus CanClient::start() {
37     VehicleBus::start();
38     LOG(VERBOSE) << "Waiting for ICanBus/" << mBusName;
39     ICanBus::registerForNotifications(mBusName, static_cast<IServiceNotification*>(this));
40     return ::ndk::ScopedAStatus::ok();
41 }
42 
~CanClient()43 CanClient::~CanClient() {
44     auto manager = IServiceManager::getService();
45     CHECK(manager != nullptr) << "Can't fetch IServiceManager";
46     manager->unregisterForNotifications("", "", static_cast<IServiceNotification*>(this));
47 
48     close();
49 }
50 
onReady(const sp<ICanBus> &)51 void CanClient::onReady(const sp<ICanBus>&) {}
52 
onRegistration(const hidl_string &,const hidl_string & name,bool)53 Return<void> CanClient::onRegistration(const hidl_string&, const hidl_string& name, bool) {
54     LOG(VERBOSE) << "ICanBus/" << name << " is registered";
55     auto bus = ICanBus::tryGetService(name);
56     if (bus == nullptr) {
57         LOG(WARNING) << "Can't fetch ICanBus/" << name;
58         return {};
59     }
60 
61     std::lock_guard<std::mutex> lck(mCanBusGuard);
62     if (mCanBus) {
63         LOG(DEBUG) << "Bus " << mBusName << " service is already registered";
64         return {};
65     }
66     mCanBus = bus;
67 
68     // TODO(b/146214370): configure CAN message filtering (see first argument to listen())
69     Result halResult;
70     sp<ICloseHandle> listenerCloseHandle;
71     // TODO(b/146214370): check why the cast requires transfer SEPolicy permission
72     auto res = bus->listen({}, static_cast<ICanMessageListener*>(this),
73             hidl_utils::fill(&halResult, &listenerCloseHandle));
74     mListenerCloseHandle = CloseHandleWrapper(listenerCloseHandle);
75     if (!res.isOk() || halResult != Result::OK) {
76         LOG(WARNING) << "Listen call failed";
77         close();
78         return {};
79     }
80 
81     auto errRes = bus->listenForErrors(static_cast<ICanErrorListener*>(this));
82     if (!errRes.isOk()) {
83         LOG(WARNING) << "listenForErrors call failed";
84         close();
85         return {};
86     }
87     mErrorCloseHandle = CloseHandleWrapper(errRes);
88 
89     if (!bus->linkToDeath(static_cast<hidl_death_recipient*>(this), 0).withDefault(false)) {
90         LOG(WARNING) << "linkToDeath failed";
91         close();
92         return {};
93     }
94 
95     LOG(INFO) << "Bus " << mBusName << " successfully configured";
96     onReady(mCanBus);
97     return {};
98 }
99 
serviceDied(uint64_t,const wp<hidl::base::V1_0::IBase> &)100 void CanClient::serviceDied(uint64_t, const wp<hidl::base::V1_0::IBase>&) {
101     onError(ErrorEvent::INTERFACE_DOWN, true);
102 }
103 
onError(ErrorEvent error,bool isFatal)104 Return<void> CanClient::onError(ErrorEvent error, bool isFatal) {
105     if (!isFatal) {
106         LOG(VERBOSE) << "Got non-fatal error from CAN bus HAL: " << toString(error);
107         return {};
108     }
109 
110     LOG(DEBUG) << "Got fatal error from CAN bus HAL: " << toString(error);
111 
112     if (!close()) {
113         LOG(WARNING) << "Service is dead already";
114         return {};
115     }
116     LOG(INFO) << "Bus " << mBusName << " became unavailable, waiting for it to come back...";
117 
118     return {};
119 }
120 
close()121 bool CanClient::close() {
122     std::lock_guard<std::mutex> lck(mCanBusGuard);
123     mListenerCloseHandle.close();
124     mErrorCloseHandle.close();
125     if (mCanBus == nullptr) return false;
126     if (!mCanBus->unlinkToDeath(static_cast<hidl_death_recipient*>(this)).isOk()) {
127         LOG(WARNING) << "unlinkToDeath failed";
128     }
129     mCanBus = nullptr;
130     return true;
131 }
132 
133 }  // namespace utils
134 }  // namespace V1_0
135 }  // namespace can
136 }  // namespace automotive
137 }  // namespace hardware
138 }  // namespace android
139