blob: 5f78004c9f93629e49f29db258e77ae46ab7f02f [file] [log] [blame]
Ashutosh Joshi1bec86a2016-11-15 13:48:58 -08001/*
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 "Contexthub.h"
18
19#include <inttypes.h>
20
Mark Salyzyn3ff52602017-01-10 10:16:48 -080021#include <log/log.h>
22
Ashutosh Joshi1bec86a2016-11-15 13:48:58 -080023#include <android/hardware/contexthub/1.0/IContexthub.h>
24#include <hardware/context_hub.h>
25
26#undef LOG_TAG
27#define LOG_TAG "ContextHubHalAdapter"
28
29namespace android {
30namespace hardware {
31namespace contexthub {
32namespace V1_0 {
33namespace implementation {
34
35static constexpr uint64_t ALL_APPS = UINT64_C(0xFFFFFFFFFFFFFFFF);
36
37Contexthub::Contexthub()
38 : mInitCheck(NO_INIT),
39 mContextHubModule(nullptr),
40 mIsTransactionPending(false) {
41 const hw_module_t *module;
42
43 mInitCheck = hw_get_module(CONTEXT_HUB_MODULE_ID, &module);
44
45 if (mInitCheck != OK) {
46 ALOGE("Could not load %s module: %s", CONTEXT_HUB_MODULE_ID, strerror(-mInitCheck));
47 } else if (module == nullptr) {
48 ALOGE("hal returned succes but a null module!");
49 // Assign an error, this should not really happen...
50 mInitCheck = UNKNOWN_ERROR;
51 } else {
52 ALOGI("Loaded Context Hub module");
53 mContextHubModule = reinterpret_cast<const context_hub_module_t *>(module);
54 }
55}
56
57bool Contexthub::setOsAppAsDestination(hub_message_t *msg, int hubId) {
58 if (!isValidHubId(hubId)) {
59 ALOGW("%s: Hub information is null for hubHandle %d",
60 __FUNCTION__,
61 hubId);
62 return false;
63 } else {
64 msg->app_name = mCachedHubInfo[hubId].osAppName;
65 return true;
66 }
67}
68
69Return<void> Contexthub::getHubs(getHubs_cb _hidl_cb) {
70 std::vector<ContextHub> hubs;
71 if (isInitialized()) {
72 const context_hub_t *hubArray = nullptr;
73 size_t numHubs;
74
75 // Explicitly discarding const. HAL method discards it.
76 numHubs = mContextHubModule->get_hubs(const_cast<context_hub_module_t *>(mContextHubModule),
77 &hubArray);
78 ALOGI("Context Hub Hal Adapter reports %zu hubs", numHubs);
79
80 mCachedHubInfo.clear();
81
82 for (size_t i = 0; i < numHubs; i++) {
83 CachedHubInformation info;
84 ContextHub c;
85
86 c.hubId = hubArray[i].hub_id;
87 c.name = hubArray[i].name;
88 c.vendor = hubArray[i].vendor;
89 c.toolchain = hubArray[i].toolchain;
90 c.toolchainVersion = hubArray[i].toolchain_version;
91 c.platformVersion = hubArray[i].platform_version;
92 c.maxSupportedMsgLen = hubArray[i].max_supported_msg_len;
93 c.peakMips = hubArray[i].peak_mips;
94 c.peakPowerDrawMw = hubArray[i].peak_power_draw_mw;
95 c.stoppedPowerDrawMw = hubArray[i].stopped_power_draw_mw;
96 c.sleepPowerDrawMw = hubArray[i].sleep_power_draw_mw;
97
98 info.callBack = nullptr;
99 info.osAppName = hubArray[i].os_app_name;
100 mCachedHubInfo[hubArray[i].hub_id] = info;
101
102 hubs.push_back(c);
103 }
104 } else {
105 ALOGW("Context Hub Hal Adapter not initialized");
106 }
107
108 _hidl_cb(hubs);
109 return Void();
110}
111
112bool Contexthub::isValidHubId(uint32_t hubId) {
113 if (!mCachedHubInfo.count(hubId)) {
114 ALOGW("Hub information not found for hubId %" PRIu32, hubId);
115 return false;
116 } else {
117 return true;
118 }
119}
120
121sp<IContexthubCallback> Contexthub::getCallBackForHubId(uint32_t hubId) {
122 if (!isValidHubId(hubId)) {
123 return nullptr;
124 } else {
125 return mCachedHubInfo[hubId].callBack;
126 }
127}
128
129Return<Result> Contexthub::sendMessageToHub(uint32_t hubId,
130 const ContextHubMsg &msg) {
131 if (!isInitialized()) {
132 return Result::NOT_INIT;
133 }
134
135 if (!isValidHubId(hubId) || msg.msg.size() > UINT32_MAX) {
136 return Result::BAD_PARAMS;
137 }
138
139 hub_message_t txMsg = {
140 .app_name.id = msg.appName,
141 .message_type = msg.msgType,
142 .message_len = static_cast<uint32_t>(msg.msg.size()), // Note the check above
143 .message = static_cast<const uint8_t *>(msg.msg.data()),
144 };
145
146 ALOGI("Sending msg of type %" PRIu32 ", size %" PRIu32 " to app 0x%" PRIx64,
147 txMsg.message_type,
148 txMsg.message_len,
149 txMsg.app_name.id);
150
151 if(mContextHubModule->send_message(hubId, &txMsg) != 0) {
152 return Result::TRANSACTION_FAILED;
153 }
154
155 return Result::OK;
156}
157
158Return<Result> Contexthub::reboot(uint32_t hubId) {
159 if (!isInitialized()) {
160 return Result::NOT_INIT;
161 }
162
163 hub_message_t msg;
164
165 if (setOsAppAsDestination(&msg, hubId) == false) {
166 return Result::BAD_PARAMS;
167 }
168
169 msg.message_type = CONTEXT_HUB_OS_REBOOT;
170 msg.message_len = 0;
171 msg.message = nullptr;
172
173 if(mContextHubModule->send_message(hubId, &msg) != 0) {
174 return Result::TRANSACTION_FAILED;
175 } else {
176 return Result::OK;
177 }
178}
179
180Return<Result> Contexthub::registerCallback(uint32_t hubId,
181 const sp<IContexthubCallback> &cb) {
182 Return<Result> retVal = Result::BAD_PARAMS;
183
184 if (!isInitialized()) {
185 // Not initilalized
186 ALOGW("Context hub not initialized successfully");
187 retVal = Result::NOT_INIT;
188 } else if (!isValidHubId(hubId)) {
189 // Initialized, but hubId is not valid
190 retVal = Result::BAD_PARAMS;
191 } else if (mContextHubModule->subscribe_messages(hubId,
192 contextHubCb,
193 this) == 0) {
194 // Initialized && valid hub && subscription successful
195 retVal = Result::OK;
196 mCachedHubInfo[hubId].callBack = cb;
197 } else {
198 // Initalized && valid hubId - but subscription unsuccessful
199 // This is likely an internal error in the HAL implementation, but we
200 // cannot add more information.
201 ALOGW("Could not subscribe to the hub for callback");
202 retVal = Result::UNKNOWN_FAILURE;
203 }
204
205 return retVal;
206}
207
208static bool isValidOsStatus(const uint8_t *msg,
209 size_t msgLen,
210 status_response_t *rsp) {
211 // Workaround a bug in some HALs
212 if (msgLen == 1) {
213 rsp->result = msg[0];
214 return true;
215 }
216
217 if (msg == nullptr || msgLen != sizeof(*rsp)) {
218 ALOGI("Received invalid response (is null : %d, size %zu)",
219 msg == nullptr ? 1 : 0,
220 msgLen);
221 return false;
222 }
223
224 memcpy(rsp, msg, sizeof(*rsp));
225
226 // No sanity checks on return values
227 return true;
228}
229
230int Contexthub::handleOsMessage(sp<IContexthubCallback> cb,
231 uint32_t msgType,
232 const uint8_t *msg,
233 int msgLen) {
234 int retVal = -1;
235
236
237 switch(msgType) {
238 case CONTEXT_HUB_APPS_ENABLE:
239 case CONTEXT_HUB_APPS_DISABLE:
240 case CONTEXT_HUB_LOAD_APP:
241 case CONTEXT_HUB_UNLOAD_APP:
242 {
243 struct status_response_t rsp;
244 TransactionResult result;
245 if (isValidOsStatus(msg, msgLen, &rsp) && rsp.result == 0) {
246 retVal = 0;
247 result = TransactionResult::SUCCESS;
248 } else {
249 result = TransactionResult::FAILURE;
250 }
251
252 if (cb != nullptr) {
253 cb->handleTxnResult(mTransactionId, result);
254 }
255 retVal = 0;
256 mIsTransactionPending = false;
257 break;
258 }
259
260 case CONTEXT_HUB_QUERY_APPS:
261 {
262 std::vector<HubAppInfo> apps;
263 int numApps = msgLen / sizeof(hub_app_info);
264 const hub_app_info *unalignedInfoAddr = reinterpret_cast<const hub_app_info *>(msg);
265
266 for (int i = 0; i < numApps; i++) {
267 hub_app_info query_info;
268 memcpy(&query_info, &unalignedInfoAddr[i], sizeof(query_info));
269 HubAppInfo app;
270 app.appId = query_info.app_name.id;
271 app.version = query_info.version;
272 // TODO :: Add memory ranges
273
274 apps.push_back(app);
275 }
276
277 if (cb != nullptr) {
278 cb->handleAppsInfo(apps);
279 }
280 retVal = 0;
281 break;
282 }
283
284 case CONTEXT_HUB_QUERY_MEMORY:
285 {
286 // Deferring this use
287 retVal = 0;
288 break;
289 }
290
291 case CONTEXT_HUB_OS_REBOOT:
292 {
293 mIsTransactionPending = false;
294 if (cb != nullptr) {
295 cb->handleHubEvent(AsyncEventType::RESTARTED);
296 }
297 retVal = 0;
298 break;
299 }
300
301 default:
302 {
303 retVal = -1;
304 break;
305 }
306 }
307
308 return retVal;
309}
310
311int Contexthub::contextHubCb(uint32_t hubId,
312 const struct hub_message_t *rxMsg,
313 void *cookie) {
314 Contexthub *obj = static_cast<Contexthub *>(cookie);
315
316 if (rxMsg == nullptr) {
317 ALOGW("Ignoring NULL message");
318 return -1;
319 }
320
321 if (!obj->isValidHubId(hubId)) {
322 ALOGW("Invalid hub Id %" PRIu32, hubId);
323 return -1;
324 }
325
326 sp<IContexthubCallback> cb = obj->getCallBackForHubId(hubId);
327
328 if (cb == nullptr) {
329 // This should not ever happen
330 ALOGW("No callback registered, returning");
331 return -1;
332 }
333
334 if (rxMsg->message_type < CONTEXT_HUB_TYPE_PRIVATE_MSG_BASE) {
335 obj->handleOsMessage(cb,
336 rxMsg->message_type,
337 static_cast<const uint8_t *>(rxMsg->message),
338 rxMsg->message_len);
339 } else {
340 ContextHubMsg msg;
341
342 msg.appName = rxMsg->app_name.id;
343 msg.msgType = rxMsg->message_type;
344 msg.msg = std::vector<uint8_t>(static_cast<const uint8_t *>(rxMsg->message),
345 static_cast<const uint8_t *>(rxMsg->message) +
346 rxMsg->message_len);
347
348 cb->handleClientMsg(msg);
349 }
350
351 return 0;
352}
353
354Return<Result> Contexthub::unloadNanoApp(uint32_t hubId,
355 uint64_t appId,
356 uint32_t transactionId) {
357 if (!isInitialized()) {
358 return Result::NOT_INIT;
359 }
360
361 if (mIsTransactionPending) {
362 return Result::TRANSACTION_PENDING;
363 }
364
365 hub_message_t msg;
366
367 if (setOsAppAsDestination(&msg, hubId) == false) {
368 return Result::BAD_PARAMS;
369 }
370
371 struct apps_disable_request_t req;
372
373 msg.message_type = CONTEXT_HUB_UNLOAD_APP;
374 msg.message_len = sizeof(req);
375 msg.message = &req;
376 req.app_name.id = appId;
377
378 if(mContextHubModule->send_message(hubId, &msg) != 0) {
379 return Result::TRANSACTION_FAILED;
380 } else {
381 mTransactionId = transactionId;
382 mIsTransactionPending = true;
383 return Result::OK;
384 }
385}
386
387Return<Result> Contexthub::loadNanoApp(uint32_t hubId,
388 const ::android::hardware::hidl_vec<uint8_t>& appBinary,
389 uint32_t transactionId) {
390 if (!isInitialized()) {
391 return Result::NOT_INIT;
392 }
393
394 if (mIsTransactionPending) {
395 return Result::TRANSACTION_PENDING;
396 }
397
398 hub_message_t hubMsg;
399
400 if (setOsAppAsDestination(&hubMsg, hubId) == false) {
401 return Result::BAD_PARAMS;
402 }
403
404 hubMsg.message_type = CONTEXT_HUB_LOAD_APP;
405 hubMsg.message_len = appBinary.size();
406 hubMsg.message = appBinary.data();
407
408 if(mContextHubModule->send_message(hubId, &hubMsg) != 0) {
409 return Result::TRANSACTION_FAILED;
410 } else {
411 mTransactionId = transactionId;
412 mIsTransactionPending = true;
413 return Result::OK;
414 }
415}
416
417Return<Result> Contexthub::enableNanoApp(uint32_t hubId,
418 uint64_t appId,
419 uint32_t transactionId) {
420 if (!isInitialized()) {
421 return Result::NOT_INIT;
422 }
423
424 if (mIsTransactionPending) {
425 return Result::TRANSACTION_PENDING;
426 }
427
428 hub_message_t msg;
429
430 if (setOsAppAsDestination(&msg, hubId) == false) {
431 return Result::BAD_PARAMS;
432 }
433
434 struct apps_enable_request_t req;
435
436 msg.message_type = CONTEXT_HUB_APPS_ENABLE;
437 msg.message_len = sizeof(req);
438 req.app_name.id = appId;
439 msg.message = &req;
440
441 if(mContextHubModule->send_message(hubId, &msg) != 0) {
442 return Result::TRANSACTION_FAILED;
443 } else {
444 mTransactionId = transactionId;
445 mIsTransactionPending = true;
446 return Result::OK;
447 }
448}
449
450Return<Result> Contexthub::disableNanoApp(uint32_t hubId,
451 uint64_t appId,
452 uint32_t transactionId) {
453 if (!isInitialized()) {
454 return Result::NOT_INIT;
455 }
456
457 if (mIsTransactionPending) {
458 return Result::TRANSACTION_PENDING;
459 }
460
461 hub_message_t msg;
462
463 if (setOsAppAsDestination(&msg, hubId) == false) {
464 return Result::BAD_PARAMS;
465 }
466
467 struct apps_disable_request_t req;
468
469 msg.message_type = CONTEXT_HUB_APPS_DISABLE;
470 msg.message_len = sizeof(req);
471 req.app_name.id = appId;
472 msg.message = &req;
473
474 if(mContextHubModule->send_message(hubId, &msg) != 0) {
475 return Result::TRANSACTION_FAILED;
476 } else {
477 mTransactionId = transactionId;
478 mIsTransactionPending = true;
479 return Result::OK;
480 }
481}
482
483Return<Result> Contexthub::queryApps(uint32_t hubId) {
484 if (!isInitialized()) {
485 return Result::NOT_INIT;
486 }
487
488 hub_message_t msg;
489
490 if (setOsAppAsDestination(&msg, hubId) == false) {
491 ALOGW("Could not find hubId %" PRIu32, hubId);
492 return Result::BAD_PARAMS;
493 }
494
495 query_apps_request_t payload;
496 payload.app_name.id = ALL_APPS; // TODO : Pass this in as a parameter
497 msg.message = &payload;
498 msg.message_len = sizeof(payload);
499 msg.message_type = CONTEXT_HUB_QUERY_APPS;
500
501 if(mContextHubModule->send_message(hubId, &msg) != 0) {
502 ALOGW("Query Apps sendMessage failed");
503 return Result::TRANSACTION_FAILED;
504 }
505
506 return Result::OK;
507}
508
509bool Contexthub::isInitialized() {
510 return (mInitCheck == OK && mContextHubModule != nullptr);
511}
512
513IContexthub *HIDL_FETCH_IContexthub(const char * halName) {
514 ALOGI("%s Called for %s", __FUNCTION__, halName);
515 Contexthub *contexthub = new Contexthub;
516
517 if (!contexthub->isInitialized()) {
518 delete contexthub;
519 contexthub = nullptr;
520 }
521
522 return contexthub;
523}
524
525} // namespace implementation
526} // namespace V1_0
527} // namespace contexthub
528} // namespace hardware
529} // namespace android