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/CarData.h>
25 #include <android-base/chrono_utils.h>
26 #include <android-base/result.h>
27 #include <android-base/thread_annotations.h>
28 #include <gtest/gtest_prod.h>
29 #include <utils/Looper.h>
30 
31 #include <memory>
32 
33 namespace android {
34 namespace automotive {
35 namespace telemetry {
36 
37 // This class contains the main logic of cartelemetryd native service.
38 //
39 //   [writer clients] -> ICarTelemetry  -----------.
40 //   [reader client] --> ICarTelemetryInternal -----`-> TelemetryServer
41 //
42 // TelemetryServer starts pushing CarData to ICarDataListener when there is a data available and
43 // the listener is set and alive. It uses `mLooper` for periodically pushing the data.
44 //
45 // This class is thread-safe.
46 class TelemetryServer {
47 public:
48     explicit TelemetryServer(LooperWrapper* looper,
49                              const std::chrono::nanoseconds& pushCarDataDelayNs, int maxBufferSize);
50 
51     // Dumps the current state for dumpsys.
52     // Expected to be called from a binder thread pool.
53     void dump(int fd);
54 
55     // Writes incoming CarData to the RingBuffer.
56     // Expected to be called from a binder thread pool.
57     void writeCarData(
58             const std::vector<aidl::android::frameworks::automotive::telemetry::CarData>& dataList,
59             uid_t publisherUid);
60 
61     // Sets the listener. If the listener already set, it returns an error.
62     // Expected to be called from a binder thread pool.
63     android::base::Result<void> setListener(
64             const std::shared_ptr<aidl::android::automotive::telemetry::internal::ICarDataListener>&
65                     listener);
66 
67     // Clears the listener and returns it.
68     // Expected to be called from a binder thread pool.
69     void clearListener();
70 
71     // Expected to be called from a binder thread pool.
72     std::shared_ptr<aidl::android::automotive::telemetry::internal::ICarDataListener> getListener();
73 
74 private:
75     class MessageHandlerImpl : public MessageHandler {
76     public:
77         explicit MessageHandlerImpl(TelemetryServer* server);
78 
79         void handleMessage(const Message& message) override;
80 
81     private:
82         TelemetryServer* mTelemetryServer;  // not owned
83     };
84 
85 private:
86     // Periodically called by mLooper if there is a "push car data" messages.
87     void pushCarDataToListeners();
88 
89     LooperWrapper* mLooper;  // not owned
90     const std::chrono::nanoseconds mPushCarDataDelayNs;
91 
92     // A single mutex for all the sensitive operations. Threads must not lock it for long time,
93     // as clients will be writing CarData to the ring buffer under this mutex.
94     std::mutex mMutex;
95     RingBuffer mRingBuffer GUARDED_BY(mMutex);
96     std::shared_ptr<aidl::android::automotive::telemetry::internal::ICarDataListener>
97             mCarDataListener GUARDED_BY(mMutex);
98     android::sp<MessageHandlerImpl> mMessageHandler;  // Handler for mLooper.
99 
100     // Friends are simplest way of testing if `pushCarDataToListeners()` can handle edge cases.
101     friend class TelemetryServerTest;
102     FRIEND_TEST(TelemetryServerTest, NoListenerButMultiplePushes);
103     FRIEND_TEST(TelemetryServerTest, NoDataButMultiplePushes);
104 };
105 
106 }  // namespace telemetry
107 }  // namespace automotive
108 }  // namespace android
109 
110 #endif  // CPP_TELEMETRY_CARTELEMETRYD_SRC_TELEMETRYSERVER_H_
111