1 //
2 // Copyright 2018 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 __VTS_RESOURCE_VTSRESOURCEMANAGER_H
18 #define __VTS_RESOURCE_VTSRESOURCEMANAGER_H
19 
20 #include <android-base/logging.h>
21 #include <android/hardware/audio/4.0/IStreamIn.h>
22 #include <android/hardware/audio/4.0/IStreamOut.h>
23 #include <android/hardware/audio/effect/2.0/types.h>
24 #include <android/hardware/audio/effect/4.0/types.h>
25 #include <google/protobuf/repeated_field.h>
26 #include <google/protobuf/text_format.h>
27 
28 #include "fmq_driver/VtsFmqDriver.h"
29 #include "hidl_handle_driver/VtsHidlHandleDriver.h"
30 #include "hidl_memory_driver/VtsHidlMemoryDriver.h"
31 #include "test/vts/proto/ComponentSpecificationMessage.pb.h"
32 #include "test/vts/proto/VtsResourceControllerMessage.pb.h"
33 
34 using namespace std;
35 
36 namespace android {
37 namespace vts {
38 
39 typedef ::android::hardware::audio::V4_0::IStreamIn::ReadParameters
40     ReadParameters;
41 typedef ::android::hardware::audio::V4_0::IStreamIn::ReadStatus ReadStatus;
42 typedef ::android::hardware::audio::V4_0::IStreamOut::WriteCommand WriteCommand;
43 typedef ::android::hardware::audio::V4_0::IStreamOut::WriteStatus WriteStatus;
44 typedef ::android::hardware::audio::effect::V4_0::Result ResultV4_0;
45 typedef ::android::hardware::audio::effect::V2_0::Result ResultV2_0;
46 
47 // A class that manages all resources allocated on the target side.
48 // Resources include fast message queue, hidl_memory, hidl_handle.
49 //
50 // Example (Process FMQ Command):
51 //   // Initialize a manager.
52 //   VtsResourceManager manager;
53 //
54 //   // Generate some FMQ request (e.g. creating a queue.).
55 //   FmqRequestMessage fmq_request;
56 //   fmq_request.set_operation(FMQ_CREATE);
57 //   fmq_request.set_data_type("uint16_t");
58 //   fmq_request.set_sync(true);
59 //   fmq_request.set_queue_size(2048);
60 //   fmq_request.set_blocking(false);
61 //
62 //   // receive response.
63 //   FmqRequestResponse fmq_response;
64 //   // This will ask FMQ driver to process request and send response.
65 //   ProcessFmqCommand(fmq_request, &fmq_response);
66 class VtsResourceManager {
67  public:
68   // Constructor to set up the resource manager.
69   VtsResourceManager();
70 
71   // Destructor to clean up the resource manager.
72   ~VtsResourceManager();
73 
74   // Processes command for operations on hidl_handle.
75   //
76   // @param hidl_handle_request  contains arguments for the operation.
77   // @param hidl_handle_response to be filled by the function.
78   void ProcessHidlHandleCommand(
79       const HidlHandleRequestMessage& hidl_handle_request,
80       HidlHandleResponseMessage* hidl_handle_response);
81 
82   // Registers the handle object in hidl_handle_driver_ given the hidl_handle
83   // address provided in hidl_handle_msg.
84   //
85   // @param hidl_handle_msg stores hidl_handle address, used to find actual
86   //                        handle object.
87   //
88   // @return handle_id assigned to the new handle object.
89   int RegisterHidlHandle(const VariableSpecificationMessage& hidl_handle_msg);
90 
91   // Gets hidl_handle address in hidl_handle_driver_.
92   // If caller wants to use a handle object in the driver, it specifies
93   // handle_id in HandleDataValueMessage. This method calls hidl_handle_driver_
94   // to locate the handle object with handle_id, and stores the address
95   // in result pointer.
96   //
97   // @param hidl_handle_msg contains handle_id of the handle object.
98   // @param result          stores hidl_handle address.
99   //
100   // @return true if the handle object with handle_id is found, and stores
101   //              address in result,
102   //         false otherwise.
103   bool GetHidlHandleAddress(const VariableSpecificationMessage& hidl_handle_msg,
104                             size_t* result);
105 
106   // Processes command for operations on hidl_memory.
107   //
108   // @param hidl_memory_request  contains arguments for the operation.
109   // @param hidl_memory_response to be filled by the function.
110   void ProcessHidlMemoryCommand(
111       const HidlMemoryRequestMessage& hidl_memory_request,
112       HidlMemoryResponseMessage* hidl_memory_response);
113 
114   // Registers the memory object in hidl_memory_driver_ given the hidl_memory
115   // pointer address provided in hidl_memory_msg.
116   //
117   // @param hidl_memory_msg stores hidl_memory pointer, used to find actual
118   //                        memory pointer.
119   //
120   // @return mem_id assigned to the new memory object.
121   int RegisterHidlMemory(const VariableSpecificationMessage& hidl_memory_msg);
122 
123   // Gets hidl_memory pointer address in hidl_memory_driver_.
124   // If caller wants to use a memory object in the driver, it specifies mem_id
125   // in MemoryDataValueMessage. This method calls hidl_memory_driver to locate
126   // the memory object with mem_id, and stores the address in result pointer.
127   //
128   // @param hidl_memory_msg contains memory object mem_id.
129   // @param result          stores hidl_memory pointer.
130   //
131   // @return true if the memory object with mem_id is found, and stores pointer
132   //              address in result,
133   //         false otherwise.
134   bool GetHidlMemoryAddress(const VariableSpecificationMessage& hidl_memory_msg,
135                             size_t* result);
136 
137   // Processes command for operations on Fast Message Queue.
138   // The arguments are specified in fmq_request, and this function stores result
139   // in fmq_response.
140   //
141   // @param fmq_request  contains arguments for the operation.
142   // @param fmq_response to be filled by the function.
143   void ProcessFmqCommand(const FmqRequestMessage& fmq_request,
144                          FmqResponseMessage* fmq_response);
145 
146   // Registers a fmq in fmq_driver_ given the information provided in
147   // queue_msg.
148   // This message stores queue data_type, sync option, and existing
149   // descriptor address. This method recasts the address into a pointer
150   // and passes it to fmq_driver_.
151   //
152   // @param queue_msg stores queue information, data_type, sync option,
153   //                  and queue descriptor address.
154   //
155   // @return queue_id assigned to the new queue object.
156   int RegisterFmq(const VariableSpecificationMessage& queue_msg);
157 
158   // Gets queue descriptor address specified in VariableSpecificationMessage.
159   // The message contains type of data in the queue, queue flavor,
160   // and queue id. The method calls fmq_driver to locate the address of the
161   // descriptor using these information, then stores the address in
162   // result pointer.
163   //
164   // @param queue_msg contains queue information.
165   // @param result    to store queue descriptor pointer address.
166   //
167   // @return true if queue is found and type matches, and stores the descriptor
168   //              address in result.
169   //         false otherwise.
170   bool GetQueueDescAddress(const VariableSpecificationMessage& queue_msg,
171                            size_t* result);
172 
173  private:
174   // Function template used in our map that maps type name to function
175   // with template.
176   typedef void (VtsResourceManager::*ProcessFmqCommandFn)(
177       const FmqRequestMessage&, FmqResponseMessage*);
178 
179   // This method infers the queue flavor from the sync field in fmq_request
180   // proto message, and calls ProcessFmqCommandInternal() with template T
181   // and queue flavor.
182   // Notice we create another method called
183   // ProcessFmqCommandWithPredefinedType() with the same interface.
184   // This prevents compiler error during conversion between protobuf message
185   // and C++.
186   //
187   // @param fmq_request  contains arguments for FMQ operation.
188   // @param fmq_response FMQ response to be filled by this function.
189   template <typename T>
190   void ProcessFmqCommandWithType(const FmqRequestMessage& fmq_request,
191                                  FmqResponseMessage* fmq_response);
192 
193   // A helper method to call methods on fmq_driver.
194   // This method already has the template type and flavor of FMQ.
195   //
196   // @param fmq_request  contains arguments for FMQ operation.
197   // @param fmq_response FMQ response to be filled by this function.
198   template <typename T, hardware::MQFlavor flavor>
199   void ProcessFmqCommandInternal(const FmqRequestMessage& fmq_request,
200                                  FmqResponseMessage* fmq_response);
201 
202   // Converts write_data field in fmq_request to a C++ buffer.
203   // For user-defined type, dynamically load the HAL shared library
204   // to parse protobuf message to C++ type.
205   //
206   // @param fmq_request    contains the write_data, represented as a repeated
207   //                       proto field.
208   // @param write_data     converted data that will be written into FMQ.
209   // @param write_data_size number of items in write_data.
210   //
211   // @return true if parsing is successful, false otherwise.
212   //         This function can fail if loading shared library or locating
213   //         function symbols fails in user-defined type.
214   template <typename T>
215   bool FmqProto2Cpp(const FmqRequestMessage& fmq_request, T* write_data,
216                     size_t write_data_size);
217 
218   // Converts a C++ buffer into read_data field in fmq_response.
219   // For user-defined type, dynamically load the HAL shared library
220   // to parse C++ type to protobuf message.
221   //
222   // @param fmq_response   to be filled by the function. The function fills the
223   //                       read_data field, which is represented as a repeated
224   //                       proto field.
225   // @param data_type      type of data in FMQ, this information will be
226   //                       written into protobuf message.
227   // @param read_data      contains data read from FMQ read operation.
228   // @param read_data_size number of items in read_data.
229   //
230   // @return true if parsing is successful, false otherwise.
231   //         This function can fail if loading shared library or locating
232   //         function symbols fails in user-defined type.
233   template <typename T>
234   bool FmqCpp2Proto(FmqResponseMessage* fmq_response, const string& data_type,
235                     T* read_data, size_t read_data_size);
236 
237   // Loads the corresponding HAL driver shared library from the type name.
238   // This function parses the shared library path from a type name, and
239   // loads the shared library object from the path.
240   //
241   // Example:
242   // For type ::android::hardware::audio::V4_0::IStreamIn::ReadParameters,
243   // the path that is parsed from the type name is
244   // /data/local/tmp/android.hardware.audio@4.0-vts.driver.so.
245   // Then the function loads the shared library object from this path.
246   //
247   // TODO: Consider determining the path and bitness by passing a field
248   // in the protobuf message.
249   //
250   // @param data_type type name.
251   //
252   // @return shared library object.
253   void* LoadSharedLibFromTypeName(const string& data_type);
254 
255   // Load the translation function between C++ and protobuf.
256   // This method parses the function name that can translate C++ to protobuf
257   // or translate protobuf to C++ from data_type.
258   // Then it loads the function symbol from shared_lib_obj, which is an opened
259   // HAL shared library.
260   //
261   // Example: type name is
262   // ::android::hardware::audio::V4_0::IStreamIn::ReadParameters,
263   // and we have the shared library pointer shared_lib_obj.
264   // To translate from protobuf to C++, we need to call
265   // GetTranslationFuncPtr(shared_lib_obj, data_type, true);
266   // To translate from C++ to protobuf, we need to call
267   // GetTranslationFuncPtr(shared_lib_obj, data_type, false);
268   //
269   // @param shared_lib_obj  opened HAL shared library object.
270   // @param data_type       type name.
271   // @param is_proto_to_cpp whether the function is to convert proto to C++.
272   //
273   // @return name of the translation function.
274   void* GetTranslationFuncPtr(void* shared_lib_obj, const string& data_type,
275                               bool is_proto_to_cpp);
276 
277   // Manages Fast Message Queue (FMQ) driver.
278   VtsFmqDriver fmq_driver_;
279   // Manages hidl_memory driver.
280   VtsHidlMemoryDriver hidl_memory_driver_;
281   // Manages hidl_handle driver.
282   VtsHidlHandleDriver hidl_handle_driver_;
283   // A map that maps each FMQ user-defined type into a process
284   // function with template.
285   const unordered_map<string, ProcessFmqCommandFn> func_map_ = {
286       {"int8_t", &VtsResourceManager::ProcessFmqCommandWithType<int8_t>},
287       {"uint8_t", &VtsResourceManager::ProcessFmqCommandWithType<uint8_t>},
288       {"int16_t", &VtsResourceManager::ProcessFmqCommandWithType<int16_t>},
289       {"uint16_t", &VtsResourceManager::ProcessFmqCommandWithType<uint16_t>},
290       {"int32_t", &VtsResourceManager::ProcessFmqCommandWithType<int32_t>},
291       {"uint32_t", &VtsResourceManager::ProcessFmqCommandWithType<uint32_t>},
292       {"int64_t", &VtsResourceManager::ProcessFmqCommandWithType<int64_t>},
293       {"uint64_t", &VtsResourceManager::ProcessFmqCommandWithType<uint64_t>},
294       {"float_t", &VtsResourceManager::ProcessFmqCommandWithType<float>},
295       {"double_t", &VtsResourceManager::ProcessFmqCommandWithType<double>},
296       {"bool_t", &VtsResourceManager::ProcessFmqCommandWithType<bool>},
297       {"::android::hardware::audio::V4_0::IStreamIn::ReadParameters",
298        &VtsResourceManager::ProcessFmqCommandWithType<ReadParameters>},
299       {"::android::hardware::audio::V4_0::IStreamIn::ReadStatus",
300        &VtsResourceManager::ProcessFmqCommandWithType<ReadStatus>},
301       {"::android::hardware::audio::V4_0::IStreamOut::WriteCommand",
302        &VtsResourceManager::ProcessFmqCommandWithType<WriteCommand>},
303       {"::android::hardware::audio::effect::V4_0::Result",
304        &VtsResourceManager::ProcessFmqCommandWithType<ResultV4_0>},
305       {"::android::hardware::audio::effect::V2_0::Result",
306        &VtsResourceManager::ProcessFmqCommandWithType<ResultV2_0>}};
307 };
308 
309 }  // namespace vts
310 }  // namespace android
311 #endif  //__VTS_RESOURCE_VTSRESOURCEMANAGER_H
312