xref: /aosp_15_r20/system/chre/host/common/daemon_base.cc (revision 84e339476a462649f82315436d70fd732297a399)
1*84e33947SAndroid Build Coastguard Worker /*
2*84e33947SAndroid Build Coastguard Worker  * Copyright (C) 2020 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 #include <signal.h>
18*84e33947SAndroid Build Coastguard Worker #include <cstdlib>
19*84e33947SAndroid Build Coastguard Worker #include <fstream>
20*84e33947SAndroid Build Coastguard Worker 
21*84e33947SAndroid Build Coastguard Worker #include "chre_host/config_util.h"
22*84e33947SAndroid Build Coastguard Worker #include "chre_host/daemon_base.h"
23*84e33947SAndroid Build Coastguard Worker #include "chre_host/file_stream.h"
24*84e33947SAndroid Build Coastguard Worker #include "chre_host/log.h"
25*84e33947SAndroid Build Coastguard Worker #include "chre_host/napp_header.h"
26*84e33947SAndroid Build Coastguard Worker 
27*84e33947SAndroid Build Coastguard Worker #ifdef CHRE_DAEMON_METRIC_ENABLED
28*84e33947SAndroid Build Coastguard Worker #include <android_chre_flags.h>
29*84e33947SAndroid Build Coastguard Worker #include <chre_atoms_log.h>
30*84e33947SAndroid Build Coastguard Worker #include <system/chre/core/chre_metrics.pb.h>
31*84e33947SAndroid Build Coastguard Worker #endif  // CHRE_DAEMON_METRIC_ENABLED
32*84e33947SAndroid Build Coastguard Worker 
33*84e33947SAndroid Build Coastguard Worker // Aliased for consistency with the way these symbols are referenced in
34*84e33947SAndroid Build Coastguard Worker // CHRE-side code
35*84e33947SAndroid Build Coastguard Worker namespace fbs = ::chre::fbs;
36*84e33947SAndroid Build Coastguard Worker 
37*84e33947SAndroid Build Coastguard Worker namespace android {
38*84e33947SAndroid Build Coastguard Worker namespace chre {
39*84e33947SAndroid Build Coastguard Worker 
40*84e33947SAndroid Build Coastguard Worker #ifdef CHRE_DAEMON_METRIC_ENABLED
41*84e33947SAndroid Build Coastguard Worker using ::aidl::android::frameworks::stats::IStats;
42*84e33947SAndroid Build Coastguard Worker using ::aidl::android::frameworks::stats::VendorAtom;
43*84e33947SAndroid Build Coastguard Worker using ::aidl::android::frameworks::stats::VendorAtomValue;
44*84e33947SAndroid Build Coastguard Worker 
45*84e33947SAndroid Build Coastguard Worker using ::android::chre::Atoms::CHRE_EVENT_QUEUE_SNAPSHOT_REPORTED;
46*84e33947SAndroid Build Coastguard Worker using ::android::chre::Atoms::CHRE_PAL_OPEN_FAILED;
47*84e33947SAndroid Build Coastguard Worker using ::android::chre::Atoms::ChrePalOpenFailed;
48*84e33947SAndroid Build Coastguard Worker #endif  // CHRE_DAEMON_METRIC_ENABLED
49*84e33947SAndroid Build Coastguard Worker 
50*84e33947SAndroid Build Coastguard Worker namespace {
51*84e33947SAndroid Build Coastguard Worker 
signalHandler(void * ctx)52*84e33947SAndroid Build Coastguard Worker void signalHandler(void *ctx) {
53*84e33947SAndroid Build Coastguard Worker   auto *daemon = static_cast<ChreDaemonBase *>(ctx);
54*84e33947SAndroid Build Coastguard Worker   int rc = -1;
55*84e33947SAndroid Build Coastguard Worker   sigset_t signalMask;
56*84e33947SAndroid Build Coastguard Worker   sigfillset(&signalMask);
57*84e33947SAndroid Build Coastguard Worker   sigdelset(&signalMask, SIGINT);
58*84e33947SAndroid Build Coastguard Worker   sigdelset(&signalMask, SIGTERM);
59*84e33947SAndroid Build Coastguard Worker   if (sigprocmask(SIG_SETMASK, &signalMask, NULL) != 0) {
60*84e33947SAndroid Build Coastguard Worker     LOG_ERROR("Couldn't mask all signals except INT/TERM", errno);
61*84e33947SAndroid Build Coastguard Worker   }
62*84e33947SAndroid Build Coastguard Worker 
63*84e33947SAndroid Build Coastguard Worker   while (true) {
64*84e33947SAndroid Build Coastguard Worker     int signum = 0;
65*84e33947SAndroid Build Coastguard Worker     if ((rc = sigwait(&signalMask, &signum)) != 0) {
66*84e33947SAndroid Build Coastguard Worker       LOGE("Sigwait failed: %d", rc);
67*84e33947SAndroid Build Coastguard Worker     }
68*84e33947SAndroid Build Coastguard Worker     LOGI("Received signal %d", signum);
69*84e33947SAndroid Build Coastguard Worker     if (signum == SIGINT || signum == SIGTERM) {
70*84e33947SAndroid Build Coastguard Worker       daemon->onShutdown();
71*84e33947SAndroid Build Coastguard Worker       break;
72*84e33947SAndroid Build Coastguard Worker     }
73*84e33947SAndroid Build Coastguard Worker   }
74*84e33947SAndroid Build Coastguard Worker }
75*84e33947SAndroid Build Coastguard Worker 
76*84e33947SAndroid Build Coastguard Worker }  // anonymous namespace
77*84e33947SAndroid Build Coastguard Worker 
ChreDaemonBase()78*84e33947SAndroid Build Coastguard Worker ChreDaemonBase::ChreDaemonBase() : mChreShutdownRequested(false) {
79*84e33947SAndroid Build Coastguard Worker   mLogger.init();
80*84e33947SAndroid Build Coastguard Worker   // TODO(b/297388964): Replace thread with handler installed via std::signal()
81*84e33947SAndroid Build Coastguard Worker   mSignalHandlerThread = std::thread(signalHandler, this);
82*84e33947SAndroid Build Coastguard Worker }
83*84e33947SAndroid Build Coastguard Worker 
loadPreloadedNanoapps()84*84e33947SAndroid Build Coastguard Worker void ChreDaemonBase::loadPreloadedNanoapps() {
85*84e33947SAndroid Build Coastguard Worker   const std::string kPreloadedNanoappsConfigPath =
86*84e33947SAndroid Build Coastguard Worker       "/vendor/etc/chre/preloaded_nanoapps.json";
87*84e33947SAndroid Build Coastguard Worker   std::string directory;
88*84e33947SAndroid Build Coastguard Worker   std::vector<std::string> nanoapps;
89*84e33947SAndroid Build Coastguard Worker   bool success = getPreloadedNanoappsFromConfigFile(
90*84e33947SAndroid Build Coastguard Worker       kPreloadedNanoappsConfigPath, directory, nanoapps);
91*84e33947SAndroid Build Coastguard Worker   if (!success) {
92*84e33947SAndroid Build Coastguard Worker     LOGE("Failed to parse preloaded nanoapps config file");
93*84e33947SAndroid Build Coastguard Worker     return;
94*84e33947SAndroid Build Coastguard Worker   }
95*84e33947SAndroid Build Coastguard Worker 
96*84e33947SAndroid Build Coastguard Worker   for (uint32_t i = 0; i < nanoapps.size(); ++i) {
97*84e33947SAndroid Build Coastguard Worker     loadPreloadedNanoapp(directory, nanoapps[i], i);
98*84e33947SAndroid Build Coastguard Worker   }
99*84e33947SAndroid Build Coastguard Worker }
100*84e33947SAndroid Build Coastguard Worker 
loadPreloadedNanoapp(const std::string & directory,const std::string & name,uint32_t transactionId)101*84e33947SAndroid Build Coastguard Worker void ChreDaemonBase::loadPreloadedNanoapp(const std::string &directory,
102*84e33947SAndroid Build Coastguard Worker                                           const std::string &name,
103*84e33947SAndroid Build Coastguard Worker                                           uint32_t transactionId) {
104*84e33947SAndroid Build Coastguard Worker   std::vector<uint8_t> headerBuffer;
105*84e33947SAndroid Build Coastguard Worker 
106*84e33947SAndroid Build Coastguard Worker   std::string headerFile = directory + "/" + name + ".napp_header";
107*84e33947SAndroid Build Coastguard Worker 
108*84e33947SAndroid Build Coastguard Worker   // Only create the nanoapp filename as the CHRE framework will load from
109*84e33947SAndroid Build Coastguard Worker   // within the directory its own binary resides in.
110*84e33947SAndroid Build Coastguard Worker   std::string nanoappFilename = name + ".so";
111*84e33947SAndroid Build Coastguard Worker 
112*84e33947SAndroid Build Coastguard Worker   if (!readFileContents(headerFile.c_str(), headerBuffer) ||
113*84e33947SAndroid Build Coastguard Worker       !loadNanoapp(headerBuffer, nanoappFilename, transactionId)) {
114*84e33947SAndroid Build Coastguard Worker     LOGE("Failed to load nanoapp: '%s'", name.c_str());
115*84e33947SAndroid Build Coastguard Worker   }
116*84e33947SAndroid Build Coastguard Worker }
117*84e33947SAndroid Build Coastguard Worker 
loadNanoapp(const std::vector<uint8_t> & header,const std::string & nanoappName,uint32_t transactionId)118*84e33947SAndroid Build Coastguard Worker bool ChreDaemonBase::loadNanoapp(const std::vector<uint8_t> &header,
119*84e33947SAndroid Build Coastguard Worker                                  const std::string &nanoappName,
120*84e33947SAndroid Build Coastguard Worker                                  uint32_t transactionId) {
121*84e33947SAndroid Build Coastguard Worker   bool success = false;
122*84e33947SAndroid Build Coastguard Worker   if (header.size() != sizeof(NanoAppBinaryHeader)) {
123*84e33947SAndroid Build Coastguard Worker     LOGE("Header size mismatch");
124*84e33947SAndroid Build Coastguard Worker   } else {
125*84e33947SAndroid Build Coastguard Worker     // The header blob contains the struct above.
126*84e33947SAndroid Build Coastguard Worker     const auto *appHeader =
127*84e33947SAndroid Build Coastguard Worker         reinterpret_cast<const NanoAppBinaryHeader *>(header.data());
128*84e33947SAndroid Build Coastguard Worker 
129*84e33947SAndroid Build Coastguard Worker     // Build the target API version from major and minor.
130*84e33947SAndroid Build Coastguard Worker     uint32_t targetApiVersion = (appHeader->targetChreApiMajorVersion << 24) |
131*84e33947SAndroid Build Coastguard Worker                                 (appHeader->targetChreApiMinorVersion << 16);
132*84e33947SAndroid Build Coastguard Worker 
133*84e33947SAndroid Build Coastguard Worker     success = sendNanoappLoad(appHeader->appId, appHeader->appVersion,
134*84e33947SAndroid Build Coastguard Worker                               targetApiVersion, nanoappName, transactionId);
135*84e33947SAndroid Build Coastguard Worker   }
136*84e33947SAndroid Build Coastguard Worker 
137*84e33947SAndroid Build Coastguard Worker   return success;
138*84e33947SAndroid Build Coastguard Worker }
139*84e33947SAndroid Build Coastguard Worker 
sendTimeSyncWithRetry(size_t numRetries,useconds_t retryDelayUs,bool logOnError)140*84e33947SAndroid Build Coastguard Worker bool ChreDaemonBase::sendTimeSyncWithRetry(size_t numRetries,
141*84e33947SAndroid Build Coastguard Worker                                            useconds_t retryDelayUs,
142*84e33947SAndroid Build Coastguard Worker                                            bool logOnError) {
143*84e33947SAndroid Build Coastguard Worker   bool success = false;
144*84e33947SAndroid Build Coastguard Worker   while (!success && (numRetries-- != 0)) {
145*84e33947SAndroid Build Coastguard Worker     success = sendTimeSync(logOnError);
146*84e33947SAndroid Build Coastguard Worker     if (!success) {
147*84e33947SAndroid Build Coastguard Worker       usleep(retryDelayUs);
148*84e33947SAndroid Build Coastguard Worker     }
149*84e33947SAndroid Build Coastguard Worker   }
150*84e33947SAndroid Build Coastguard Worker   return success;
151*84e33947SAndroid Build Coastguard Worker }
152*84e33947SAndroid Build Coastguard Worker 
handleNanConfigurationRequest(const::chre::fbs::NanConfigurationRequestT *)153*84e33947SAndroid Build Coastguard Worker void ChreDaemonBase::handleNanConfigurationRequest(
154*84e33947SAndroid Build Coastguard Worker     const ::chre::fbs::NanConfigurationRequestT * /*request*/) {
155*84e33947SAndroid Build Coastguard Worker   LOGE("NAN is unsupported on this platform");
156*84e33947SAndroid Build Coastguard Worker }
157*84e33947SAndroid Build Coastguard Worker 
158*84e33947SAndroid Build Coastguard Worker #ifdef CHRE_DAEMON_METRIC_ENABLED
handleMetricLog(const::chre::fbs::MetricLogT * metricMsg)159*84e33947SAndroid Build Coastguard Worker void ChreDaemonBase::handleMetricLog(const ::chre::fbs::MetricLogT *metricMsg) {
160*84e33947SAndroid Build Coastguard Worker   const std::vector<int8_t> &encodedMetric = metricMsg->encoded_metric;
161*84e33947SAndroid Build Coastguard Worker 
162*84e33947SAndroid Build Coastguard Worker   switch (metricMsg->id) {
163*84e33947SAndroid Build Coastguard Worker     case CHRE_PAL_OPEN_FAILED: {
164*84e33947SAndroid Build Coastguard Worker       metrics::ChrePalOpenFailed metric;
165*84e33947SAndroid Build Coastguard Worker       if (!metric.ParseFromArray(encodedMetric.data(), encodedMetric.size())) {
166*84e33947SAndroid Build Coastguard Worker         LOGE("Failed to parse metric data");
167*84e33947SAndroid Build Coastguard Worker       } else {
168*84e33947SAndroid Build Coastguard Worker         ChrePalOpenFailed::ChrePalType pal =
169*84e33947SAndroid Build Coastguard Worker             static_cast<ChrePalOpenFailed::ChrePalType>(metric.pal());
170*84e33947SAndroid Build Coastguard Worker         ChrePalOpenFailed::Type type =
171*84e33947SAndroid Build Coastguard Worker             static_cast<ChrePalOpenFailed::Type>(metric.type());
172*84e33947SAndroid Build Coastguard Worker         if (!mMetricsReporter.logPalOpenFailed(pal, type)) {
173*84e33947SAndroid Build Coastguard Worker           LOGE("Could not log the PAL open failed metric");
174*84e33947SAndroid Build Coastguard Worker         }
175*84e33947SAndroid Build Coastguard Worker       }
176*84e33947SAndroid Build Coastguard Worker       break;
177*84e33947SAndroid Build Coastguard Worker     }
178*84e33947SAndroid Build Coastguard Worker     case CHRE_EVENT_QUEUE_SNAPSHOT_REPORTED: {
179*84e33947SAndroid Build Coastguard Worker       metrics::ChreEventQueueSnapshotReported metric;
180*84e33947SAndroid Build Coastguard Worker       if (!metric.ParseFromArray(encodedMetric.data(), encodedMetric.size())) {
181*84e33947SAndroid Build Coastguard Worker         LOGE("Failed to parse metric data");
182*84e33947SAndroid Build Coastguard Worker       } else if (!mMetricsReporter.logEventQueueSnapshotReported(
183*84e33947SAndroid Build Coastguard Worker               metric.snapshot_chre_get_time_ms(),
184*84e33947SAndroid Build Coastguard Worker               metric.max_event_queue_size(), metric.mean_event_queue_size(),
185*84e33947SAndroid Build Coastguard Worker               metric.num_dropped_events())) {
186*84e33947SAndroid Build Coastguard Worker         LOGE("Could not log the event queue snapshot metric");
187*84e33947SAndroid Build Coastguard Worker       }
188*84e33947SAndroid Build Coastguard Worker       break;
189*84e33947SAndroid Build Coastguard Worker     }
190*84e33947SAndroid Build Coastguard Worker     default: {
191*84e33947SAndroid Build Coastguard Worker #ifdef CHRE_LOG_ATOM_EXTENSION_ENABLED
192*84e33947SAndroid Build Coastguard Worker       handleVendorMetricLog(metricMsg);
193*84e33947SAndroid Build Coastguard Worker #else
194*84e33947SAndroid Build Coastguard Worker       LOGW("Unknown metric ID %" PRIu32, metricMsg->id);
195*84e33947SAndroid Build Coastguard Worker #endif  // CHRE_LOG_ATOM_EXTENSION_ENABLED
196*84e33947SAndroid Build Coastguard Worker     }
197*84e33947SAndroid Build Coastguard Worker   }
198*84e33947SAndroid Build Coastguard Worker }
199*84e33947SAndroid Build Coastguard Worker 
reportMetric(const VendorAtom & atom)200*84e33947SAndroid Build Coastguard Worker void ChreDaemonBase::reportMetric(const VendorAtom &atom) {
201*84e33947SAndroid Build Coastguard Worker   const std::string statsServiceName =
202*84e33947SAndroid Build Coastguard Worker       std::string(IStats::descriptor).append("/default");
203*84e33947SAndroid Build Coastguard Worker   if (!AServiceManager_isDeclared(statsServiceName.c_str())) {
204*84e33947SAndroid Build Coastguard Worker     LOGE("Stats service is not declared.");
205*84e33947SAndroid Build Coastguard Worker     return;
206*84e33947SAndroid Build Coastguard Worker   }
207*84e33947SAndroid Build Coastguard Worker 
208*84e33947SAndroid Build Coastguard Worker   std::shared_ptr<IStats> stats_client = IStats::fromBinder(ndk::SpAIBinder(
209*84e33947SAndroid Build Coastguard Worker       AServiceManager_waitForService(statsServiceName.c_str())));
210*84e33947SAndroid Build Coastguard Worker   if (stats_client == nullptr) {
211*84e33947SAndroid Build Coastguard Worker     LOGE("Failed to get IStats service");
212*84e33947SAndroid Build Coastguard Worker     return;
213*84e33947SAndroid Build Coastguard Worker   }
214*84e33947SAndroid Build Coastguard Worker 
215*84e33947SAndroid Build Coastguard Worker   const ndk::ScopedAStatus ret = stats_client->reportVendorAtom(atom);
216*84e33947SAndroid Build Coastguard Worker   if (!ret.isOk()) {
217*84e33947SAndroid Build Coastguard Worker     LOGE("Failed to report vendor atom");
218*84e33947SAndroid Build Coastguard Worker   }
219*84e33947SAndroid Build Coastguard Worker }
220*84e33947SAndroid Build Coastguard Worker #endif  // CHRE_DAEMON_METRIC_ENABLED
221*84e33947SAndroid Build Coastguard Worker 
222*84e33947SAndroid Build Coastguard Worker }  // namespace chre
223*84e33947SAndroid Build Coastguard Worker }  // namespace android
224