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