1*84e33947SAndroid Build Coastguard Worker /*
2*84e33947SAndroid Build Coastguard Worker * Copyright (C) 2017 The Android Open Source Project
3*84e33947SAndroid Build Coastguard Worker *
4*84e33947SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*84e33947SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*84e33947SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*84e33947SAndroid Build Coastguard Worker *
8*84e33947SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*84e33947SAndroid Build Coastguard Worker *
10*84e33947SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*84e33947SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*84e33947SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*84e33947SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*84e33947SAndroid Build Coastguard Worker * limitations under the License.
15*84e33947SAndroid Build Coastguard Worker */
16*84e33947SAndroid Build Coastguard Worker
17*84e33947SAndroid Build Coastguard Worker // Disable verbose logging
18*84e33947SAndroid Build Coastguard Worker // TODO: use property_get_bool to make verbose logging runtime configurable
19*84e33947SAndroid Build Coastguard Worker // #define LOG_NDEBUG 0
20*84e33947SAndroid Build Coastguard Worker
21*84e33947SAndroid Build Coastguard Worker #include "fastrpc_daemon.h"
22*84e33947SAndroid Build Coastguard Worker
23*84e33947SAndroid Build Coastguard Worker #include "generated/chre_slpi.h"
24*84e33947SAndroid Build Coastguard Worker
25*84e33947SAndroid Build Coastguard Worker // TODO: The following conditional compilation needs to be removed, and done
26*84e33947SAndroid Build Coastguard Worker // for all platforms after verifying that it works on older devices where
27*84e33947SAndroid Build Coastguard Worker // we're currently not defining this macro
28*84e33947SAndroid Build Coastguard Worker #ifdef CHRE_DAEMON_LOAD_INTO_SENSORSPD
29*84e33947SAndroid Build Coastguard Worker #include "remote.h"
30*84e33947SAndroid Build Coastguard Worker
31*84e33947SAndroid Build Coastguard Worker #define ITRANSPORT_PREFIX "'\":;./\\"
32*84e33947SAndroid Build Coastguard Worker #endif // CHRE_DAEMON_LOAD_INTO_SENSORSPD
33*84e33947SAndroid Build Coastguard Worker
34*84e33947SAndroid Build Coastguard Worker // Aliased for consistency with the way these symbols are referenced in
35*84e33947SAndroid Build Coastguard Worker // CHRE-side code
36*84e33947SAndroid Build Coastguard Worker namespace fbs = ::chre::fbs;
37*84e33947SAndroid Build Coastguard Worker
38*84e33947SAndroid Build Coastguard Worker namespace android {
39*84e33947SAndroid Build Coastguard Worker namespace chre {
40*84e33947SAndroid Build Coastguard Worker
41*84e33947SAndroid Build Coastguard Worker namespace {
42*84e33947SAndroid Build Coastguard Worker
43*84e33947SAndroid Build Coastguard Worker #ifdef CHRE_DAEMON_LPMA_ENABLED
44*84e33947SAndroid Build Coastguard Worker constexpr bool kLpmaAllowed = true;
45*84e33947SAndroid Build Coastguard Worker #else
46*84e33947SAndroid Build Coastguard Worker constexpr bool kLpmaAllowed = false;
47*84e33947SAndroid Build Coastguard Worker #endif // CHRE_DAEMON_LPMA_ENABLED
48*84e33947SAndroid Build Coastguard Worker
49*84e33947SAndroid Build Coastguard Worker } // namespace
50*84e33947SAndroid Build Coastguard Worker
FastRpcChreDaemon()51*84e33947SAndroid Build Coastguard Worker FastRpcChreDaemon::FastRpcChreDaemon() : mLpmaHandler(kLpmaAllowed) {}
52*84e33947SAndroid Build Coastguard Worker
init()53*84e33947SAndroid Build Coastguard Worker bool FastRpcChreDaemon::init() {
54*84e33947SAndroid Build Coastguard Worker constexpr size_t kMaxTimeSyncRetries = 5;
55*84e33947SAndroid Build Coastguard Worker constexpr useconds_t kTimeSyncRetryDelayUs = 50000; // 50 ms
56*84e33947SAndroid Build Coastguard Worker
57*84e33947SAndroid Build Coastguard Worker int rc = -1;
58*84e33947SAndroid Build Coastguard Worker
59*84e33947SAndroid Build Coastguard Worker #ifdef CHRE_DAEMON_LOAD_INTO_SENSORSPD
60*84e33947SAndroid Build Coastguard Worker remote_handle remote_handle_fd = 0xFFFFFFFF;
61*84e33947SAndroid Build Coastguard Worker if (remote_handle_open(ITRANSPORT_PREFIX "createstaticpd:sensorspd",
62*84e33947SAndroid Build Coastguard Worker &remote_handle_fd)) {
63*84e33947SAndroid Build Coastguard Worker LOGE("Failed to open remote handle for sensorspd");
64*84e33947SAndroid Build Coastguard Worker } else {
65*84e33947SAndroid Build Coastguard Worker LOGD("Successfully opened remote handle for sensorspd");
66*84e33947SAndroid Build Coastguard Worker }
67*84e33947SAndroid Build Coastguard Worker #endif // CHRE_DAEMON_LOAD_INTO_SENSORSPD
68*84e33947SAndroid Build Coastguard Worker
69*84e33947SAndroid Build Coastguard Worker mLpmaHandler.init();
70*84e33947SAndroid Build Coastguard Worker
71*84e33947SAndroid Build Coastguard Worker if (!sendTimeSyncWithRetry(kMaxTimeSyncRetries, kTimeSyncRetryDelayUs,
72*84e33947SAndroid Build Coastguard Worker true /* logOnError */)) {
73*84e33947SAndroid Build Coastguard Worker LOGE("Failed to send initial time sync message");
74*84e33947SAndroid Build Coastguard Worker } else if ((rc = chre_slpi_initialize_reverse_monitor()) !=
75*84e33947SAndroid Build Coastguard Worker CHRE_FASTRPC_SUCCESS) {
76*84e33947SAndroid Build Coastguard Worker LOGE("Failed to initialize reverse monitor: (err) %d", rc);
77*84e33947SAndroid Build Coastguard Worker } else if ((rc = chre_slpi_start_thread()) != CHRE_FASTRPC_SUCCESS) {
78*84e33947SAndroid Build Coastguard Worker LOGE("Failed to start CHRE: (err) %d", rc);
79*84e33947SAndroid Build Coastguard Worker } else {
80*84e33947SAndroid Build Coastguard Worker mMonitorThread = std::thread(&FastRpcChreDaemon::monitorThreadEntry, this);
81*84e33947SAndroid Build Coastguard Worker mMsgToHostThread =
82*84e33947SAndroid Build Coastguard Worker std::thread(&FastRpcChreDaemon::msgToHostThreadEntry, this);
83*84e33947SAndroid Build Coastguard Worker loadPreloadedNanoapps();
84*84e33947SAndroid Build Coastguard Worker LOGI("CHRE started");
85*84e33947SAndroid Build Coastguard Worker }
86*84e33947SAndroid Build Coastguard Worker
87*84e33947SAndroid Build Coastguard Worker return (rc == CHRE_FASTRPC_SUCCESS);
88*84e33947SAndroid Build Coastguard Worker }
89*84e33947SAndroid Build Coastguard Worker
deinit()90*84e33947SAndroid Build Coastguard Worker void FastRpcChreDaemon::deinit() {
91*84e33947SAndroid Build Coastguard Worker int rc;
92*84e33947SAndroid Build Coastguard Worker
93*84e33947SAndroid Build Coastguard Worker setShutdownRequested(true);
94*84e33947SAndroid Build Coastguard Worker
95*84e33947SAndroid Build Coastguard Worker if ((rc = chre_slpi_stop_thread()) != CHRE_FASTRPC_SUCCESS) {
96*84e33947SAndroid Build Coastguard Worker LOGE("Failed to stop CHRE: (err) %d", rc);
97*84e33947SAndroid Build Coastguard Worker }
98*84e33947SAndroid Build Coastguard Worker
99*84e33947SAndroid Build Coastguard Worker if (mMonitorThread.has_value()) {
100*84e33947SAndroid Build Coastguard Worker mMonitorThread->join();
101*84e33947SAndroid Build Coastguard Worker }
102*84e33947SAndroid Build Coastguard Worker if (mMsgToHostThread.has_value()) {
103*84e33947SAndroid Build Coastguard Worker mMsgToHostThread->join();
104*84e33947SAndroid Build Coastguard Worker }
105*84e33947SAndroid Build Coastguard Worker }
106*84e33947SAndroid Build Coastguard Worker
run()107*84e33947SAndroid Build Coastguard Worker void FastRpcChreDaemon::run() {
108*84e33947SAndroid Build Coastguard Worker constexpr char kChreSocketName[] = "chre";
109*84e33947SAndroid Build Coastguard Worker auto serverCb = [&](uint16_t clientId, void *data, size_t len) {
110*84e33947SAndroid Build Coastguard Worker if (mCrashDetected) {
111*84e33947SAndroid Build Coastguard Worker LOGW("Dropping data, CHRE restart in process...");
112*84e33947SAndroid Build Coastguard Worker } else {
113*84e33947SAndroid Build Coastguard Worker sendMessageToChre(clientId, data, len);
114*84e33947SAndroid Build Coastguard Worker }
115*84e33947SAndroid Build Coastguard Worker };
116*84e33947SAndroid Build Coastguard Worker
117*84e33947SAndroid Build Coastguard Worker // TODO: take 2nd argument as command-line parameter
118*84e33947SAndroid Build Coastguard Worker mServer.run(kChreSocketName, true /* allowSocketCreation */, serverCb);
119*84e33947SAndroid Build Coastguard Worker }
120*84e33947SAndroid Build Coastguard Worker
doSendMessage(void * data,size_t length)121*84e33947SAndroid Build Coastguard Worker bool FastRpcChreDaemon::doSendMessage(void *data, size_t length) {
122*84e33947SAndroid Build Coastguard Worker // This limitation is due to FastRPC, but there's no case
123*84e33947SAndroid Build Coastguard Worker // where we should come close to this limit
124*84e33947SAndroid Build Coastguard Worker constexpr size_t kMaxPayloadSize = 1024 * 1024; // 1 MiB
125*84e33947SAndroid Build Coastguard Worker static_assert(kMaxPayloadSize <= INT32_MAX,
126*84e33947SAndroid Build Coastguard Worker "DSP uses 32-bit signed integers to represent message size");
127*84e33947SAndroid Build Coastguard Worker
128*84e33947SAndroid Build Coastguard Worker bool success = false;
129*84e33947SAndroid Build Coastguard Worker if (length > kMaxPayloadSize) {
130*84e33947SAndroid Build Coastguard Worker LOGE("Message too large (got %zu, max %zu bytes)", length, kMaxPayloadSize);
131*84e33947SAndroid Build Coastguard Worker } else {
132*84e33947SAndroid Build Coastguard Worker int ret = chre_slpi_deliver_message_from_host(
133*84e33947SAndroid Build Coastguard Worker static_cast<const unsigned char *>(data), static_cast<int>(length));
134*84e33947SAndroid Build Coastguard Worker if (ret != CHRE_FASTRPC_SUCCESS) {
135*84e33947SAndroid Build Coastguard Worker LOGE("Failed to deliver message from host to CHRE: %d", ret);
136*84e33947SAndroid Build Coastguard Worker } else {
137*84e33947SAndroid Build Coastguard Worker success = true;
138*84e33947SAndroid Build Coastguard Worker }
139*84e33947SAndroid Build Coastguard Worker }
140*84e33947SAndroid Build Coastguard Worker
141*84e33947SAndroid Build Coastguard Worker return success;
142*84e33947SAndroid Build Coastguard Worker }
143*84e33947SAndroid Build Coastguard Worker
monitorThreadEntry()144*84e33947SAndroid Build Coastguard Worker void FastRpcChreDaemon::monitorThreadEntry() {
145*84e33947SAndroid Build Coastguard Worker LOGD("Monitor thread started");
146*84e33947SAndroid Build Coastguard Worker
147*84e33947SAndroid Build Coastguard Worker int ret = chre_slpi_wait_on_thread_exit();
148*84e33947SAndroid Build Coastguard Worker if (!wasShutdownRequested()) {
149*84e33947SAndroid Build Coastguard Worker LOGE("Monitor detected unexpected CHRE thread exit (%d)", ret);
150*84e33947SAndroid Build Coastguard Worker onRemoteCrashDetected();
151*84e33947SAndroid Build Coastguard Worker }
152*84e33947SAndroid Build Coastguard Worker LOGD("Monitor thread exited");
153*84e33947SAndroid Build Coastguard Worker }
154*84e33947SAndroid Build Coastguard Worker
msgToHostThreadEntry()155*84e33947SAndroid Build Coastguard Worker void FastRpcChreDaemon::msgToHostThreadEntry() {
156*84e33947SAndroid Build Coastguard Worker unsigned char messageBuffer[4096];
157*84e33947SAndroid Build Coastguard Worker unsigned int messageLen;
158*84e33947SAndroid Build Coastguard Worker int result = 0;
159*84e33947SAndroid Build Coastguard Worker
160*84e33947SAndroid Build Coastguard Worker LOGD("MsgToHost thread started");
161*84e33947SAndroid Build Coastguard Worker
162*84e33947SAndroid Build Coastguard Worker while (true) {
163*84e33947SAndroid Build Coastguard Worker messageLen = 0;
164*84e33947SAndroid Build Coastguard Worker LOGV("Calling into chre_slpi_get_message_to_host");
165*84e33947SAndroid Build Coastguard Worker result = chre_slpi_get_message_to_host(messageBuffer, sizeof(messageBuffer),
166*84e33947SAndroid Build Coastguard Worker &messageLen);
167*84e33947SAndroid Build Coastguard Worker LOGV("Got message from CHRE with size %u (result %d)", messageLen, result);
168*84e33947SAndroid Build Coastguard Worker
169*84e33947SAndroid Build Coastguard Worker if (result == CHRE_FASTRPC_ERROR_SHUTTING_DOWN) {
170*84e33947SAndroid Build Coastguard Worker LOGD("CHRE shutting down, exiting CHRE->Host message thread");
171*84e33947SAndroid Build Coastguard Worker break;
172*84e33947SAndroid Build Coastguard Worker } else if (result == CHRE_FASTRPC_SUCCESS && messageLen > 0) {
173*84e33947SAndroid Build Coastguard Worker onMessageReceived(messageBuffer, messageLen);
174*84e33947SAndroid Build Coastguard Worker } else if (!wasShutdownRequested()) {
175*84e33947SAndroid Build Coastguard Worker LOGE("get_message_to_host returned unexpected error (%d)", result);
176*84e33947SAndroid Build Coastguard Worker onRemoteCrashDetected();
177*84e33947SAndroid Build Coastguard Worker } else {
178*84e33947SAndroid Build Coastguard Worker // Received an unknown result but a shutdown was requested. Break from
179*84e33947SAndroid Build Coastguard Worker // the loop to allow the daemon to cleanup.
180*84e33947SAndroid Build Coastguard Worker break;
181*84e33947SAndroid Build Coastguard Worker }
182*84e33947SAndroid Build Coastguard Worker }
183*84e33947SAndroid Build Coastguard Worker LOGD("Message to host thread exited");
184*84e33947SAndroid Build Coastguard Worker }
185*84e33947SAndroid Build Coastguard Worker
getTimeOffset(bool * success)186*84e33947SAndroid Build Coastguard Worker int64_t FastRpcChreDaemon::getTimeOffset(bool *success) {
187*84e33947SAndroid Build Coastguard Worker int64_t timeOffset = 0;
188*84e33947SAndroid Build Coastguard Worker
189*84e33947SAndroid Build Coastguard Worker #if defined(__aarch64__)
190*84e33947SAndroid Build Coastguard Worker // Reads the system time counter (CNTVCT) and its frequency (CNTFRQ)
191*84e33947SAndroid Build Coastguard Worker // CNTVCT is used in the sensors HAL for time synchronization.
192*84e33947SAndroid Build Coastguard Worker // More information can be found in the ARM reference manual
193*84e33947SAndroid Build Coastguard Worker // (http://infocenter.arm.com/help/index.jsp?topic=
194*84e33947SAndroid Build Coastguard Worker // /com.arm.doc.100048_0002_05_en/jfa1406793266982.html)
195*84e33947SAndroid Build Coastguard Worker // Use uint64_t to store since the MRS instruction uses 64 bit (X) registers
196*84e33947SAndroid Build Coastguard Worker // (http://infocenter.arm.com/help/topic/
197*84e33947SAndroid Build Coastguard Worker // com.arm.doc.den0024a/ch06s05s02.html)
198*84e33947SAndroid Build Coastguard Worker uint64_t qTimerCount = 0, qTimerFreq = 0;
199*84e33947SAndroid Build Coastguard Worker uint64_t hostTimeNano = elapsedRealtimeNano();
200*84e33947SAndroid Build Coastguard Worker asm volatile("mrs %0, cntvct_el0" : "=r"(qTimerCount));
201*84e33947SAndroid Build Coastguard Worker asm volatile("mrs %0, cntfrq_el0" : "=r"(qTimerFreq));
202*84e33947SAndroid Build Coastguard Worker
203*84e33947SAndroid Build Coastguard Worker constexpr uint64_t kOneSecondInNanoseconds = 1000000000;
204*84e33947SAndroid Build Coastguard Worker if (qTimerFreq != 0) {
205*84e33947SAndroid Build Coastguard Worker // Get the seconds part first, then convert the remainder to prevent
206*84e33947SAndroid Build Coastguard Worker // overflow
207*84e33947SAndroid Build Coastguard Worker uint64_t qTimerNanos = (qTimerCount / qTimerFreq);
208*84e33947SAndroid Build Coastguard Worker if (qTimerNanos > UINT64_MAX / kOneSecondInNanoseconds) {
209*84e33947SAndroid Build Coastguard Worker LOGE(
210*84e33947SAndroid Build Coastguard Worker "CNTVCT_EL0 conversion to nanoseconds overflowed during time sync. "
211*84e33947SAndroid Build Coastguard Worker "Aborting time sync.");
212*84e33947SAndroid Build Coastguard Worker *success = false;
213*84e33947SAndroid Build Coastguard Worker } else {
214*84e33947SAndroid Build Coastguard Worker qTimerNanos *= kOneSecondInNanoseconds;
215*84e33947SAndroid Build Coastguard Worker
216*84e33947SAndroid Build Coastguard Worker // Round the remainder portion to the nearest nanosecond
217*84e33947SAndroid Build Coastguard Worker uint64_t remainder = (qTimerCount % qTimerFreq);
218*84e33947SAndroid Build Coastguard Worker qTimerNanos +=
219*84e33947SAndroid Build Coastguard Worker (remainder * kOneSecondInNanoseconds + qTimerFreq / 2) / qTimerFreq;
220*84e33947SAndroid Build Coastguard Worker
221*84e33947SAndroid Build Coastguard Worker timeOffset = hostTimeNano - qTimerNanos;
222*84e33947SAndroid Build Coastguard Worker *success = true;
223*84e33947SAndroid Build Coastguard Worker }
224*84e33947SAndroid Build Coastguard Worker } else {
225*84e33947SAndroid Build Coastguard Worker LOGE("CNTFRQ_EL0 had 0 value. Aborting time sync.");
226*84e33947SAndroid Build Coastguard Worker *success = false;
227*84e33947SAndroid Build Coastguard Worker }
228*84e33947SAndroid Build Coastguard Worker #else
229*84e33947SAndroid Build Coastguard Worker #error "Unsupported CPU architecture type"
230*84e33947SAndroid Build Coastguard Worker #endif
231*84e33947SAndroid Build Coastguard Worker
232*84e33947SAndroid Build Coastguard Worker return timeOffset;
233*84e33947SAndroid Build Coastguard Worker }
234*84e33947SAndroid Build Coastguard Worker
onRemoteCrashDetected()235*84e33947SAndroid Build Coastguard Worker void FastRpcChreDaemon::onRemoteCrashDetected() {
236*84e33947SAndroid Build Coastguard Worker // After a DSP crash, we delay a short period of time before exiting. This is
237*84e33947SAndroid Build Coastguard Worker // primarily to avoid any potential race conditions arising from trying to
238*84e33947SAndroid Build Coastguard Worker // initialize CHRE very early in the DSP boot flow. Normally the firmware is
239*84e33947SAndroid Build Coastguard Worker // reloaded within a second or so, but we use a longer time here to have some
240*84e33947SAndroid Build Coastguard Worker // padding to handle cases where the system is slower than usual, etc.
241*84e33947SAndroid Build Coastguard Worker constexpr auto kDelayAfterCrash = std::chrono::seconds(3);
242*84e33947SAndroid Build Coastguard Worker
243*84e33947SAndroid Build Coastguard Worker // It's technically fine if multiple threads race here, but to avoid duplicate
244*84e33947SAndroid Build Coastguard Worker // logs, give the first one to reach this point a shorter delay than others
245*84e33947SAndroid Build Coastguard Worker bool firstDetection = !mCrashDetected.exchange(true);
246*84e33947SAndroid Build Coastguard Worker auto delay = (firstDetection) ? kDelayAfterCrash : kDelayAfterCrash * 2;
247*84e33947SAndroid Build Coastguard Worker std::this_thread::sleep_for(delay);
248*84e33947SAndroid Build Coastguard Worker LOGE("Exiting daemon");
249*84e33947SAndroid Build Coastguard Worker std::exit(EXIT_FAILURE);
250*84e33947SAndroid Build Coastguard Worker }
251*84e33947SAndroid Build Coastguard Worker
252*84e33947SAndroid Build Coastguard Worker } // namespace chre
253*84e33947SAndroid Build Coastguard Worker } // namespace android
254