1 /*
2 * Copyright (c) 2021, 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 "CarTelemetryInternalImpl.h"
18
19 #include <aidl/android/automotive/telemetry/internal/BnCarDataListener.h>
20 #include <aidl/android/automotive/telemetry/internal/CarDataInternal.h>
21 #include <aidl/android/automotive/telemetry/internal/ICarDataListener.h>
22 #include <android-base/logging.h>
23 #include <android-base/stringprintf.h>
24 #include <android-base/strings.h>
25
26 namespace android {
27 namespace automotive {
28 namespace telemetry {
29
30 using ::aidl::android::automotive::telemetry::internal::BnCarDataListener;
31 using ::aidl::android::automotive::telemetry::internal::CarDataInternal;
32 using ::aidl::android::automotive::telemetry::internal::ICarDataListener;
33 using ::android::base::StringPrintf;
34
CarTelemetryInternalImpl(TelemetryServer * server)35 CarTelemetryInternalImpl::CarTelemetryInternalImpl(TelemetryServer* server) :
36 mTelemetryServer(server),
37 mBinderDeathRecipient(
38 ::AIBinder_DeathRecipient_new(CarTelemetryInternalImpl::listenerBinderDied)) {}
39
setListener(const std::shared_ptr<ICarDataListener> & listener)40 ndk::ScopedAStatus CarTelemetryInternalImpl::setListener(
41 const std::shared_ptr<ICarDataListener>& listener) {
42 LOG(VERBOSE) << "Received a setListener call";
43 mTelemetryServer->setListener(listener);
44
45 // If passed a local binder, AIBinder_linkToDeath will do nothing and return
46 // STATUS_INVALID_OPERATION. We ignore this case because we only use local binders in tests
47 // where this is not an error.
48 if (!listener->isRemote()) {
49 return ndk::ScopedAStatus::ok();
50 }
51
52 auto status = ndk::ScopedAStatus::fromStatus(
53 ::AIBinder_linkToDeath(listener->asBinder().get(), mBinderDeathRecipient.get(), this));
54 if (!status.isOk()) {
55 LOG(WARNING) << __func__ << ": Failed to linkToDeath: " << status.getMessage();
56 mTelemetryServer->clearListener();
57 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(::EX_ILLEGAL_STATE,
58 status.getMessage());
59 }
60 return ndk::ScopedAStatus::ok();
61 }
62
clearListener()63 ndk::ScopedAStatus CarTelemetryInternalImpl::clearListener() {
64 auto listener = mTelemetryServer->getListener();
65 mTelemetryServer->clearListener();
66 if (listener == nullptr) {
67 return ndk::ScopedAStatus::ok();
68 }
69 auto status = ndk::ScopedAStatus::fromStatus(
70 ::AIBinder_unlinkToDeath(listener->asBinder().get(), mBinderDeathRecipient.get(),
71 this));
72 if (!status.isOk()) {
73 LOG(WARNING) << __func__
74 << ": unlinkToDeath failed, continuing anyway: " << status.getMessage();
75 }
76 return ndk::ScopedAStatus::ok();
77 }
78
addCarDataIds(const std::vector<int32_t> & ids)79 ndk::ScopedAStatus CarTelemetryInternalImpl::addCarDataIds(const std::vector<int32_t>& ids) {
80 mTelemetryServer->addCarDataIds(ids);
81 return ndk::ScopedAStatus::ok();
82 }
83
removeCarDataIds(const std::vector<int32_t> & ids)84 ndk::ScopedAStatus CarTelemetryInternalImpl::removeCarDataIds(const std::vector<int32_t>& ids) {
85 mTelemetryServer->removeCarDataIds(ids);
86 return ndk::ScopedAStatus::ok();
87 }
88
dump(int fd,const char ** args,uint32_t numArgs)89 binder_status_t CarTelemetryInternalImpl::dump(int fd, const char** args, uint32_t numArgs) {
90 dprintf(fd, "ICarTelemetryInternal:\n");
91 mTelemetryServer->dump(fd);
92 return ::STATUS_OK;
93 }
94
95 // Removes the listener if its binder dies.
listenerBinderDiedImpl()96 void CarTelemetryInternalImpl::listenerBinderDiedImpl() {
97 LOG(WARNING) << "A ICarDataListener died, clearing the listener.";
98 mTelemetryServer->clearListener();
99 }
100
101 // static
listenerBinderDied(void * cookie)102 void CarTelemetryInternalImpl::listenerBinderDied(void* cookie) {
103 // We expect the pointer to be alive as there is only a single instance of
104 // CarTelemetryInternalImpl and if it dies, the whole process should die too.
105 auto thiz = static_cast<CarTelemetryInternalImpl*>(cookie);
106 thiz->listenerBinderDiedImpl();
107 }
108
109 } // namespace telemetry
110 } // namespace automotive
111 } // namespace android
112