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 ANDROID_HARDWARE_CONTEXTHUB_AIDL_CONTEXTHUB_H
18 #define ANDROID_HARDWARE_CONTEXTHUB_AIDL_CONTEXTHUB_H
19 
20 #include <aidl/android/hardware/contexthub/BnContextHub.h>
21 #include <log/log.h>
22 #include <atomic>
23 #include <future>
24 #include <map>
25 #include <mutex>
26 #include <optional>
27 #include <unordered_set>
28 
29 #include "chre_host/napp_header.h"
30 #include "debug_dump_helper.h"
31 #include "event_logger.h"
32 #include "hal_chre_socket_connection.h"
33 
34 namespace aidl::android::hardware::contexthub {
35 
36 using ::android::chre::NanoAppBinaryHeader;
37 
38 /**
39  * Contains information about a preloaded nanoapp. Used when getting
40  * preloaded nanoapp information from the config.
41  */
42 struct chrePreloadedNanoappInfo {
chrePreloadedNanoappInfochrePreloadedNanoappInfo43   chrePreloadedNanoappInfo(int64_t _id, const std::string &_name,
44                            const NanoAppBinaryHeader &_header)
45       : id(_id), name(_name), header(_header) {}
46 
47   int64_t id;
48   std::string name;
49   NanoAppBinaryHeader header;
50 };
51 
52 class ContextHub : public BnContextHub,
53                    public ::android::hardware::contexthub::DebugDumpHelper,
54                    public ::android::hardware::contexthub::common::
55                        implementation::IChreSocketCallback {
56  public:
ContextHub()57   ContextHub()
58       : mDeathRecipient(
59             AIBinder_DeathRecipient_new(ContextHub::onServiceDied)) {}
60   ::ndk::ScopedAStatus getContextHubs(
61       std::vector<ContextHubInfo> *out_contextHubInfos) override;
62   ::ndk::ScopedAStatus loadNanoapp(int32_t contextHubId,
63                                    const NanoappBinary &appBinary,
64                                    int32_t transactionId) override;
65   ::ndk::ScopedAStatus unloadNanoapp(int32_t contextHubId, int64_t appId,
66                                      int32_t transactionId) override;
67   ::ndk::ScopedAStatus disableNanoapp(int32_t contextHubId, int64_t appId,
68                                       int32_t transactionId) override;
69   ::ndk::ScopedAStatus enableNanoapp(int32_t contextHubId, int64_t appId,
70                                      int32_t transactionId) override;
71   ::ndk::ScopedAStatus onSettingChanged(Setting setting, bool enabled) override;
72   ::ndk::ScopedAStatus queryNanoapps(int32_t contextHubId) override;
73   ::ndk::ScopedAStatus getPreloadedNanoappIds(
74       int32_t contextHubId,
75       std::vector<int64_t> *out_preloadedNanoappIds) override;
76   ::ndk::ScopedAStatus registerCallback(
77       int32_t contextHubId,
78       const std::shared_ptr<IContextHubCallback> &cb) override;
79   ::ndk::ScopedAStatus sendMessageToHub(
80       int32_t contextHubId, const ContextHubMessage &message) override;
81   ::ndk::ScopedAStatus setTestMode(bool enable) override;
82   ::ndk::ScopedAStatus sendMessageDeliveryStatusToHub(
83       int32_t contextHubId,
84       const MessageDeliveryStatus &messageDeliveryStatus) override;
85   ::ndk::ScopedAStatus onHostEndpointConnected(
86       const HostEndpointInfo &in_info) override;
87   ::ndk::ScopedAStatus onHostEndpointDisconnected(
88       char16_t in_hostEndpointId) override;
89   ::ndk::ScopedAStatus onNanSessionStateChanged(
90       const NanSessionStateUpdate &in_update) override;
91 
92   void onNanoappMessage(const ::chre::fbs::NanoappMessageT &message) override;
93 
94   void onNanoappListResponse(
95       const ::chre::fbs::NanoappListResponseT &response) override;
96 
97   void onTransactionResult(uint32_t transactionId, bool success) override;
98 
99   void onContextHubRestarted() override;
100 
101   void onDebugDumpData(const ::chre::fbs::DebugDumpDataT &data) override;
102 
103   void onDebugDumpComplete(
104       const ::chre::fbs::DebugDumpResponseT &response) override;
105 
106   void handleServiceDeath();
107   static void onServiceDied(void *cookie);
108 
109   binder_status_t dump(int fd, const char **args, uint32_t numArgs) override;
110 
requestDebugDump()111   bool requestDebugDump() override {
112     return mConnection.requestDebugDump();
113   }
114 
115   void debugDumpFinish() override;
116 
117   void writeToDebugFile(const char *str) override;
118 
119  private:
120   /**
121    * Enables test mode on the context hub. This unloads all nanoapps and puts
122    * CHRE in a state that is consistent for testing.
123    *
124    * @return                            the status.
125    */
126   ::ndk::ScopedAStatus enableTestMode();
127 
128   /**
129    * Disables test mode. Reverses the affects of enableTestMode() by loading all
130    * preloaded nanoapps. This puts CHRE back in a normal state.
131    *
132    * @return                            the status.
133    */
134   ::ndk::ScopedAStatus disableTestMode();
135 
136   /**
137    * Queries the list of loaded nanoapps in a synchronous manner.
138    * The list is stored in the mQueryNanoappsInternalList variable.
139    *
140    * @param contextHubId                the ID of the context hub.
141    * @param nanoappIdList               (out) optional out parameter that
142    *                                    contains the nanoapp IDs.
143    *
144    * @return true                       the operation was successful.
145    * @return false                      the operation was not successful.
146    */
147   bool queryNanoappsInternal(int32_t contextHubId,
148                              std::vector<int64_t> *nanoappIdList);
149 
150   /**
151    * Loads a nanoapp.
152    *
153    * @param appBinary                   the nanoapp binary to load.
154    * @param transactionId               the transaction ID.
155    *
156    * @return true                       the operation was successful.
157    * @return false                      the operation was not successful.
158    */
159   bool loadNanoappInternal(const NanoappBinary &appBinary,
160                            int32_t transactionId);
161 
162   /**
163    * Loads the nanoapps in a synchronous manner.
164    *
165    * @param contextHubId                the ID of the context hub.
166    * @param nanoappBinaryList           the list of NanoappBinary's to load.
167    * @return true                       the operation was successful.
168    * @return false                      the operation was not successful.
169    */
170   bool loadNanoappsInternal(
171       int32_t contextHubId,
172       const std::vector<NanoappBinary> &nanoappBinaryList);
173 
174   /**
175    * Unloads a nanoapp.
176    *
177    * @param appId                       the nanoapp ID to unload.
178    * @param transactionId               the transaction ID.
179    *
180    * @return true                       the operation was successful.
181    * @return false                      the operation was not successful.
182    */
183   bool unloadNanoappInternal(int64_t appId, int32_t transactionId);
184 
185   /**
186    * Unloads the nanoapps in a synchronous manner.
187    *
188    * @param contextHubId                the ID of the context hub.
189    * @param nanoappIdsToUnload          the list of nanoapp IDs to unload.
190    * @return true                       the operation was successful.
191    * @return false                      the operation was not successful.
192    */
193   bool unloadNanoappsInternal(int32_t contextHubId,
194                               const std::vector<int64_t> &nanoappIdList);
195 
196   /**
197    * Get the preloaded nanoapp IDs from the config file and headers. All IDs,
198    * names and headers are in the same order (one nanoapp has the same index in
199    * each).
200    *
201    * @param out_preloadedNanoapps       out parameter, the nanoapp information.
202    * @param out_directory               out parameter, optional, the directory
203    * that contains the nanoapps.
204    * @return true                       the operation was successful.
205    * @return false                      the operation was not successful.
206    */
207   bool getPreloadedNanoappIdsFromConfigFile(
208       std::vector<chrePreloadedNanoappInfo> &out_preloadedNanoapps,
209       std::string *out_directory) const;
210 
211   /**
212    * Selects the nanoapps to load -> all preloaded and non-system nanoapps.
213    *
214    * @param preloadedNanoapps           the preloaded nanoapps.
215    * @param preloadedNanoappDirectory   the preloaded nanoapp directory.
216    * @return                            the nanoapps to load.
217    */
218   std::vector<NanoappBinary> selectPreloadedNanoappsToLoad(
219       std::vector<chrePreloadedNanoappInfo> &preloadedNanoapps,
220       const std::string &preloadedNanoappDirectory);
221 
isSettingEnabled(Setting setting)222   bool isSettingEnabled(Setting setting) {
223     return mSettingEnabled.count(setting) > 0 && mSettingEnabled[setting];
224   }
225 
toFbsSettingState(bool enabled)226   chre::fbs::SettingState toFbsSettingState(bool enabled) const {
227     return enabled ? chre::fbs::SettingState::ENABLED
228                    : chre::fbs::SettingState::DISABLED;
229   }
230 
231   ::android::hardware::contexthub::common::implementation::
232       HalChreSocketConnection mConnection{this};
233 
234   // A mutex to protect concurrent modifications to the callback pointer and
235   // access (invocations).
236   std::mutex mCallbackMutex;
237   std::shared_ptr<IContextHubCallback> mCallback;
238 
239   ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
240 
241   std::map<Setting, bool> mSettingEnabled;
242   std::optional<bool> mIsWifiAvailable;
243   std::optional<bool> mIsBleAvailable;
244 
245   std::mutex mConnectedHostEndpointsMutex;
246   std::unordered_set<char16_t> mConnectedHostEndpoints;
247 
248   // Logs events to be reported in debug dumps.
249   EventLogger mEventLogger;
250 
251   // A mutex to synchronize access to the list of preloaded nanoapp IDs.
252   std::mutex mPreloadedNanoappIdsMutex;
253   std::optional<std::vector<int64_t>> mPreloadedNanoappIds;
254 
255   // A mutex and condition variable to synchronize queryNanoappsInternal.
256   std::mutex mQueryNanoappsInternalMutex;
257   std::condition_variable mQueryNanoappsInternalCondVar;
258   std::optional<std::vector<NanoappInfo>> mQueryNanoappsInternalList;
259 
260   // State for synchronous loads and unloads. Primarily used for test mode.
261   std::mutex mSynchronousLoadUnloadMutex;
262   std::condition_variable mSynchronousLoadUnloadCondVar;
263   std::optional<bool> mSynchronousLoadUnloadSuccess;
264   std::optional<int32_t> mSynchronousLoadUnloadTransactionId;
265 
266   // A boolean and mutex to synchronize test mode state changes and
267   // load/unloads.
268   std::mutex mTestModeMutex;
269   bool mIsTestModeEnabled = false;
270 
271   // List of system nanoapp Ids.
272   std::vector<int64_t> mSystemNanoappIds;
273 };
274 
275 }  // namespace aidl::android::hardware::contexthub
276 
277 #endif  // ANDROID_HARDWARE_CONTEXTHUB_AIDL_CONTEXTHUB_H
278