• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 <cstdlib>
18 #include <fstream>
19 
20 #include "chre_host/fbs_daemon_base.h"
21 #include "chre_host/log.h"
22 #include "chre_host/napp_header.h"
23 
24 #include <json/json.h>
25 
26 #ifdef CHRE_DAEMON_METRIC_ENABLED
27 #include <aidl/android/frameworks/stats/IStats.h>
28 #include <android/binder_manager.h>
29 #include <chre_atoms_log.h>
30 
31 using ::aidl::android::frameworks::stats::IStats;
32 using ::aidl::android::frameworks::stats::VendorAtom;
33 using ::aidl::android::frameworks::stats::VendorAtomValue;
34 #endif  // CHRE_DAEMON_METRIC_ENABLED
35 
36 // Aliased for consistency with the way these symbols are referenced in
37 // CHRE-side code
38 namespace fbs = ::chre::fbs;
39 
40 namespace android {
41 namespace chre {
42 
sendNanoappLoad(uint64_t appId,uint32_t appVersion,uint32_t appTargetApiVersion,const std::string & appBinaryName,uint32_t transactionId)43 bool FbsDaemonBase::sendNanoappLoad(uint64_t appId, uint32_t appVersion,
44                                     uint32_t appTargetApiVersion,
45                                     const std::string &appBinaryName,
46                                     uint32_t transactionId) {
47   flatbuffers::FlatBufferBuilder builder;
48   HostProtocolHost::encodeLoadNanoappRequestForFile(
49       builder, transactionId, appId, appVersion, appTargetApiVersion,
50       appBinaryName.c_str());
51 
52   bool success = sendMessageToChre(
53       kHostClientIdDaemon, builder.GetBufferPointer(), builder.GetSize());
54 
55   if (!success) {
56     LOGE("Failed to send nanoapp filename.");
57   } else {
58     Transaction transaction = {
59         .transactionId = transactionId,
60         .nanoappId = appId,
61     };
62     mPreloadedNanoappPendingTransactions.push(transaction);
63   }
64 
65   return success;
66 }
67 
sendTimeSync(bool logOnError)68 bool FbsDaemonBase::sendTimeSync(bool logOnError) {
69   bool success = false;
70   int64_t timeOffset = getTimeOffset(&success);
71 
72   if (success) {
73     flatbuffers::FlatBufferBuilder builder(64);
74     HostProtocolHost::encodeTimeSyncMessage(builder, timeOffset);
75     success = sendMessageToChre(kHostClientIdDaemon, builder.GetBufferPointer(),
76                                 builder.GetSize());
77 
78     if (!success && logOnError) {
79       LOGE("Failed to deliver time sync message from host to CHRE");
80     }
81   }
82 
83   return success;
84 }
85 
sendMessageToChre(uint16_t clientId,void * data,size_t length)86 bool FbsDaemonBase::sendMessageToChre(uint16_t clientId, void *data,
87                                       size_t length) {
88   bool success = false;
89   if (!HostProtocolHost::mutateHostClientId(data, length, clientId)) {
90     LOGE("Couldn't set host client ID in message container!");
91   } else {
92     LOGV("Delivering message from host (size %zu)", length);
93     getLogger().dump(static_cast<const uint8_t *>(data), length);
94     success = doSendMessage(data, length);
95   }
96 
97   return success;
98 }
99 
onMessageReceived(const unsigned char * messageBuffer,size_t messageLen)100 void FbsDaemonBase::onMessageReceived(const unsigned char *messageBuffer,
101                                       size_t messageLen) {
102   getLogger().dump(messageBuffer, messageLen);
103 
104   uint16_t hostClientId;
105   fbs::ChreMessage messageType;
106   if (!HostProtocolHost::extractHostClientIdAndType(
107           messageBuffer, messageLen, &hostClientId, &messageType)) {
108     LOGW("Failed to extract host client ID from message - sending broadcast");
109     hostClientId = ::chre::kHostClientIdUnspecified;
110   }
111 
112   if (messageType == fbs::ChreMessage::LogMessage) {
113     std::unique_ptr<fbs::MessageContainerT> container =
114         fbs::UnPackMessageContainer(messageBuffer);
115     const auto *logMessage = container->message.AsLogMessage();
116     const std::vector<int8_t> &logData = logMessage->buffer;
117 
118     getLogger().log(reinterpret_cast<const uint8_t *>(logData.data()),
119                     logData.size());
120   } else if (messageType == fbs::ChreMessage::LogMessageV2) {
121     std::unique_ptr<fbs::MessageContainerT> container =
122         fbs::UnPackMessageContainer(messageBuffer);
123     const auto *logMessage = container->message.AsLogMessageV2();
124     const std::vector<int8_t> &logDataBuffer = logMessage->buffer;
125     const auto *logData =
126         reinterpret_cast<const uint8_t *>(logDataBuffer.data());
127     uint32_t numLogsDropped = logMessage->num_logs_dropped;
128 
129     getLogger().logV2(logData, logDataBuffer.size(), numLogsDropped);
130   } else if (messageType == fbs::ChreMessage::TimeSyncRequest) {
131     sendTimeSync(true /* logOnError */);
132   } else if (messageType == fbs::ChreMessage::LowPowerMicAccessRequest) {
133     configureLpma(true /* enabled */);
134   } else if (messageType == fbs::ChreMessage::LowPowerMicAccessRelease) {
135     configureLpma(false /* enabled */);
136   } else if (messageType == fbs::ChreMessage::MetricLog) {
137 #ifdef CHRE_DAEMON_METRIC_ENABLED
138     std::unique_ptr<fbs::MessageContainerT> container =
139         fbs::UnPackMessageContainer(messageBuffer);
140     const auto *metricMsg = container->message.AsMetricLog();
141     handleMetricLog(metricMsg);
142 #endif  // CHRE_DAEMON_METRIC_ENABLED
143   } else if (messageType == fbs::ChreMessage::NanConfigurationRequest) {
144     std::unique_ptr<fbs::MessageContainerT> container =
145         fbs::UnPackMessageContainer(messageBuffer);
146     handleNanConfigurationRequest(
147         container->message.AsNanConfigurationRequest());
148   } else if (hostClientId == kHostClientIdDaemon) {
149     handleDaemonMessage(messageBuffer);
150   } else if (hostClientId == ::chre::kHostClientIdUnspecified) {
151     mServer.sendToAllClients(messageBuffer, static_cast<size_t>(messageLen));
152   } else {
153     mServer.sendToClientById(messageBuffer, static_cast<size_t>(messageLen),
154                              hostClientId);
155   }
156 }
157 
handleDaemonMessage(const uint8_t * message)158 void FbsDaemonBase::handleDaemonMessage(const uint8_t *message) {
159   std::unique_ptr<fbs::MessageContainerT> container =
160       fbs::UnPackMessageContainer(message);
161   if (container->message.type != fbs::ChreMessage::LoadNanoappResponse) {
162     LOGE("Invalid message from CHRE directed to daemon");
163   } else {
164     const auto *response = container->message.AsLoadNanoappResponse();
165     if (mPreloadedNanoappPendingTransactions.empty()) {
166       LOGE("Received nanoapp load response with no pending load");
167     } else if (mPreloadedNanoappPendingTransactions.front().transactionId !=
168                response->transaction_id) {
169       LOGE("Received nanoapp load response with ID %" PRIu32
170            " expected transaction id %" PRIu32,
171            response->transaction_id,
172            mPreloadedNanoappPendingTransactions.front().transactionId);
173     } else {
174       if (!response->success) {
175         LOGE("Received unsuccessful nanoapp load response with ID %" PRIu32,
176              mPreloadedNanoappPendingTransactions.front().transactionId);
177 
178 #ifdef CHRE_DAEMON_METRIC_ENABLED
179         std::vector<VendorAtomValue> values(3);
180         values[0].set<VendorAtomValue::longValue>(
181             mPreloadedNanoappPendingTransactions.front().nanoappId);
182         values[1].set<VendorAtomValue::intValue>(
183             Atoms::ChreHalNanoappLoadFailed::TYPE_PRELOADED);
184         values[2].set<VendorAtomValue::intValue>(
185             Atoms::ChreHalNanoappLoadFailed::REASON_ERROR_GENERIC);
186         const VendorAtom atom{
187             .atomId = Atoms::CHRE_HAL_NANOAPP_LOAD_FAILED,
188             .values{std::move(values)},
189         };
190         reportMetric(atom);
191 #endif  // CHRE_DAEMON_METRIC_ENABLED
192       }
193       mPreloadedNanoappPendingTransactions.pop();
194     }
195   }
196 }
197 
198 }  // namespace chre
199 }  // namespace android
200