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