• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 <dlfcn.h>
18 #include <cstdint>
19 
20 extern "C" {
21 
22 #include "qsh_na_api.h"
23 
24 }  // extern "C"
25 
26 #include "chre/core/event_loop_manager.h"
27 #include "chre/core/nanoapp.h"
28 #include "chre/platform/assert.h"
29 #include "chre/platform/log.h"
30 #include "chre/platform/memory.h"
31 #include "chre/platform/slpi/qsh/qsh_proto_shim.h"
32 #include "chre/sensor.h"
33 #include "chre/util/macros.h"
34 #include "chre/util/system/event_callbacks.h"
35 
36 namespace chre {
37 namespace {
38 
39 //! Function pointer to store QSH's version of chreSensorFlushAsync
40 decltype(chreSensorFlushAsync) *gFlushFuncPtr = nullptr;
41 
42 /*
43  * Used by QSH to obtain the currently running nanoapp instance ID when nanoapps
44  * invoke CHRE APIs implemented by its shim.
45  */
getCurrentNanoappInstanceId(uint32_t * nanoappInstId)46 bool getCurrentNanoappInstanceId(uint32_t *nanoappInstId) {
47   CHRE_ASSERT(nanoappInstId != nullptr);
48   if (nanoappInstId == nullptr) {
49     return false;
50   }
51 
52   bool success = false;
53   Nanoapp *currentNanoapp =
54       EventLoopManagerSingleton::get()->getEventLoop().getCurrentNanoapp();
55   if (currentNanoapp == nullptr) {
56     LOGE("No nanoapp currently executing");
57   } else {
58     *nanoappInstId = currentNanoapp->getInstanceId();
59     success = true;
60   }
61   return success;
62 }
63 
64 /*
65  * Used by QSH to post events to the CHRE event loop. The caller continues to
66  * own the event pointer after returning so a copy must be made of the data.
67  */
postEventFromQsh(uint16_t eventType,void * event,uint32_t eventLen,uint32_t nanoappInstId)68 bool postEventFromQsh(uint16_t eventType, void *event, uint32_t eventLen,
69                       uint32_t nanoappInstId) {
70   // Default success to true if the event is empty since an empty event can
71   // still be sent to CHRE.
72   bool success = false;
73   void *eventCopy = nullptr;
74   if (eventLen == 0) {
75     CHRE_ASSERT(event == nullptr);
76     if (event != nullptr) {
77       LOGE("Event len 0 with non-null event data");
78     } else {
79       success = true;
80     }
81   } else {
82     CHRE_ASSERT(event != nullptr);
83     if (event != nullptr) {
84       eventCopy = memoryAlloc(eventLen);
85       if (eventCopy == nullptr) {
86         LOG_OOM();
87       } else {
88         memcpy(eventCopy, event, eventLen);
89         success = true;
90       }
91     }
92   }
93 
94   if (success) {
95     EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
96         eventType, eventCopy, freeEventDataCallback,
97         static_cast<uint16_t>(nanoappInstId));
98   }
99   return success;
100 }
101 
102 const qsh_na_api_callbacks gQshCallbacks = {
103     getCurrentNanoappInstanceId, /* get_current_nanoapp_inst_id */
104     postEventFromQsh,            /* post_event */
105 };
106 
107 }  // anonymous namespace
108 
openQsh()109 void openQsh() {
110   if (!qsh_na_open(&gQshCallbacks)) {
111     LOGE("QSH failed to open");
112   } else {
113     LOGI("QSH opened");
114     gFlushFuncPtr = reinterpret_cast<decltype(gFlushFuncPtr)>(
115         dlsym(RTLD_NEXT, STRINGIFY(chreSensorFlushAsync)));
116     if (gFlushFuncPtr == nullptr) {
117       LOGE("Flush function not found!");
118     }
119   }
120 }
121 
closeQsh()122 void closeQsh() {
123   qsh_na_close();
124 }
125 
126 }  // namespace chre
127 
128 // Define the delete operator so that SLPI doesn't have to expose this symbol
129 // since CHRE will never call it directly
operator delete(void * ptr)130 void operator delete(void *ptr) noexcept {
131   free(ptr);
132 }
133 
134 // Export the chreSensorFlushAsync symbol from CHRE and then used the previously
135 // looked up symbol to WAR loader issue where nanoapps can't see QSH symbols.
chreSensorFlushAsync(uint32_t sensorHandle,const void * cookie)136 DLL_EXPORT extern "C" bool chreSensorFlushAsync(uint32_t sensorHandle,
137                                                 const void *cookie) {
138   return (chre::gFlushFuncPtr != nullptr)
139              ? chre::gFlushFuncPtr(sensorHandle, cookie)
140              : false;
141 }