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 #ifndef CPP_TELEMETRY_CARTELEMETRYD_SRC_TELEMETRYSERVER_H_
18 #define CPP_TELEMETRY_CARTELEMETRYD_SRC_TELEMETRYSERVER_H_
19 
20 #include "LooperWrapper.h"
21 #include "RingBuffer.h"
22 
23 #include <aidl/android/automotive/telemetry/internal/ICarDataListener.h>
24 #include <aidl/android/frameworks/automotive/telemetry/CallbackConfig.h>
25 #include <aidl/android/frameworks/automotive/telemetry/CarData.h>
26 #include <aidl/android/frameworks/automotive/telemetry/ICarTelemetryCallback.h>
27 #include <android-base/chrono_utils.h>
28 #include <android-base/result.h>
29 #include <android-base/thread_annotations.h>
30 #include <gtest/gtest_prod.h>
31 #include <utils/Looper.h>
32 
33 #include <cstdint>
34 #include <memory>
35 #include <unordered_map>
36 #include <unordered_set>
37 
38 namespace android {
39 namespace automotive {
40 namespace telemetry {
41 
42 using ::aidl::android::frameworks::automotive::telemetry::CallbackConfig;
43 using ::aidl::android::frameworks::automotive::telemetry::ICarTelemetryCallback;
44 
45 struct TelemetryCallback {
46     CallbackConfig config;
47     std::shared_ptr<ICarTelemetryCallback> callback;
48 
TelemetryCallbackTelemetryCallback49     TelemetryCallback() {}
TelemetryCallbackTelemetryCallback50     explicit TelemetryCallback(const std::shared_ptr<ICarTelemetryCallback>& cb) : callback(cb) {}
TelemetryCallbackTelemetryCallback51     explicit TelemetryCallback(const CallbackConfig& cfg,
52                                const std::shared_ptr<ICarTelemetryCallback>& cb) :
53           config(cfg), callback(cb) {}
54     // Copy constructor & copy assignment
55     TelemetryCallback(const TelemetryCallback& other) = default;
56     TelemetryCallback& operator=(const TelemetryCallback& other) = default;
57     // Move constructor & move assignment
58     TelemetryCallback(TelemetryCallback&& other) = default;
59     TelemetryCallback& operator=(TelemetryCallback&& other) = default;
60 
61     // Equal function
62     bool operator==(const TelemetryCallback& other) const {
63         return reinterpret_cast<uintptr_t>(callback->asBinder().get()) ==
64                 reinterpret_cast<uintptr_t>(other.callback->asBinder().get());
65     }
66 
67     struct HashFunction {
operatorTelemetryCallback::HashFunction68         size_t operator()(const TelemetryCallback& tc) const {
69             return std::hash<uintptr_t>()(
70                     reinterpret_cast<uintptr_t>(tc.callback->asBinder().get()));
71         }
72     };
73 };
74 
75 // This class contains the main logic of cartelemetryd native service.
76 //
77 //   [writer clients] -> ICarTelemetry  -----------.
78 //   [reader client] --> ICarTelemetryInternal -----`-> TelemetryServer
79 //
80 // TelemetryServer starts pushing CarData to ICarDataListener when there is a data available and
81 // the listener is set and alive. It uses `mLooper` for periodically pushing the data.
82 //
83 // This class is thread-safe.
84 class TelemetryServer {
85 public:
86     explicit TelemetryServer(LooperWrapper* looper,
87                              const std::chrono::nanoseconds& pushCarDataDelayNs, int maxBufferSize);
88 
89     /**
90      * Dumps the current state for dumpsys.
91      *
92      * <p>Expected to be called from a binder thread pool.
93      */
94     void dump(int fd);
95 
96     /**
97      * Writes incoming CarData to the RingBuffer.
98      *
99      * <p>Expected to be called from a binder thread pool.
100      */
101     void writeCarData(
102             const std::vector<aidl::android::frameworks::automotive::telemetry::CarData>& dataList,
103             uid_t publisherUid);
104 
105     /**
106      * Adds a ICarTelemtryCallback and associate it with the CallbackConfig.
107      *
108      * <p>Expected to be called from a binder thread pool.
109 
110      * @return An empty okay result on success, or an error result if the callback already
111      * exists.
112      */
113     android::base::Result<void> addCallback(const CallbackConfig& config,
114                                             const std::shared_ptr<ICarTelemetryCallback>& callback);
115 
116     /**
117      * Removes a ICarTelemetryCallback.
118      *
119      * <p>Expected to be called from a binder thread pool.
120      *
121      * @return An empty okay result on success, or an error result if the callback is not found.
122      */
123     android::base::Result<void> removeCallback(
124             const std::shared_ptr<ICarTelemetryCallback>& callback);
125 
126     /**
127      * Sets the listener and overrides the previous listener if it exists.
128      *
129      * <p>Expected to be called from a binder thread pool.
130      */
131     void setListener(
132             const std::shared_ptr<aidl::android::automotive::telemetry::internal::ICarDataListener>&
133                     listener);
134 
135     /**
136      * Clears the ICarDataListener.
137      *
138      * <p>Expected to be called from a binder thread pool.
139      */
140     void clearListener();
141 
142     /**
143      * Adds active CarData IDs, called by CarTelemetrydPublisher when the IDs
144      * has active subscribers.
145      *
146      * <p>Expected to be called from a binder thread pool.
147      */
148     void addCarDataIds(const std::vector<int32_t>& ids);
149 
150     /**
151      * Removes CarData IDs, called by CarTelemetrydPublisher when the IDs
152      * no longer has subscribers.
153      *
154      * <p>Expected to be called from a binder thread pool.
155      */
156     void removeCarDataIds(const std::vector<int32_t>& ids);
157 
158     /**
159      * Expected to be called from a binder thread pool.
160      */
161     std::shared_ptr<aidl::android::automotive::telemetry::internal::ICarDataListener> getListener();
162 
163 private:
164     class MessageHandlerImpl : public MessageHandler {
165     public:
166         explicit MessageHandlerImpl(TelemetryServer* server);
167 
168         void handleMessage(const Message& message) override;
169 
170     private:
171         TelemetryServer* mTelemetryServer;  // not owned
172     };
173 
174 private:
175     // Find the common elements in mCarDataIds and the argument ids
176     std::vector<int32_t> findCarDataIdsIntersection(const std::vector<int32_t>& ids);
177     // Periodically called by mLooper if there is a "push car data" messages.
178     void pushCarDataToListeners();
179 
180     LooperWrapper* mLooper;  // not owned
181     const std::chrono::nanoseconds mPushCarDataDelayNs;
182 
183     // A single mutex for all the sensitive operations. Threads must not lock it for long time,
184     // as clients will be writing CarData to the ring buffer under this mutex.
185     std::mutex mMutex;
186 
187     // Buffers vendor written CarData.
188     RingBuffer mRingBuffer GUARDED_BY(mMutex);
189 
190     // Notifies listener when CarData is written.
191     std::shared_ptr<aidl::android::automotive::telemetry::internal::ICarDataListener>
192             mCarDataListener GUARDED_BY(mMutex);
193 
194     // Stores a set of CarData IDs that have subscribers in CarTelemetryService.
195     // Used for filtering data.
196     std::unordered_set<int32_t> mCarDataIds GUARDED_BY(mMutex);
197 
198     // A hashset of TelemetryCallbacks to keep track of which callbacks have been added.
199     std::unordered_set<TelemetryCallback, TelemetryCallback::HashFunction> mCallbacks
200             GUARDED_BY(mMutex);
201 
202     // Maps CarData ID to a set of callbacks that are associated with this ID.
203     // Used for invoking the callback when this ID has been added or removed.
204     std::unordered_map<int32_t,
205                        std::unordered_set<TelemetryCallback, TelemetryCallback::HashFunction>>
206             mIdToCallbacksMap GUARDED_BY(mMutex);
207 
208     // Handler for mLooper.
209     android::sp<MessageHandlerImpl> mMessageHandler;
210 
211     // Friends are simplest way of testing if `pushCarDataToListeners()` can handle edge cases.
212     friend class TelemetryServerTest;
213     FRIEND_TEST(TelemetryServerTest, NoListenerButMultiplePushes);
214     FRIEND_TEST(TelemetryServerTest, NoDataButMultiplePushes);
215     // The following test accesses member variables such as `mCarDataIds` and `mCallbacks`
216     // to check its contents.
217     FRIEND_TEST(TelemetryServerTest, RemoveCarDataIdsReturnsOk);
218     FRIEND_TEST(TelemetryServerTest, RemoveCallbackReturnsOk);
219 };
220 
221 }  // namespace telemetry
222 }  // namespace automotive
223 }  // namespace android
224 
225 #endif  // CPP_TELEMETRY_CARTELEMETRYD_SRC_TELEMETRYSERVER_H_
226