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 "send_message.h"
18
19 #include <pb_encode.h>
20
21 #include "chre/util/nanoapp/callbacks.h"
22 #include "chre/util/nanoapp/log.h"
23 #include "chre/util/system/napp_permissions.h"
24 #include "chre_api/chre.h"
25
26 #ifndef LOG_TAG
27 #define LOG_TAG "[TestShared]"
28 #endif
29
30 namespace chre::test_shared {
31 namespace {
32
encodeErrorMessage(pb_ostream_t * stream,const pb_field_t *,void * const * arg)33 bool encodeErrorMessage(pb_ostream_t *stream, const pb_field_t * /*field*/,
34 void *const *arg) {
35 const char *str = static_cast<const char *>(const_cast<const void *>(*arg));
36 size_t len = strlen(str);
37 return pb_encode_tag_for_field(
38 stream, &chre_test_common_TestResult_fields
39 [chre_test_common_TestResult_errorMessage_tag - 1]) &&
40 pb_encode_string(stream, reinterpret_cast<const pb_byte_t *>(str),
41 len);
42 }
43
44 } // namespace
45
makeTestResultProtoMessage(bool success,const char * errMessage)46 chre_test_common_TestResult makeTestResultProtoMessage(bool success,
47 const char *errMessage) {
48 chre_test_common_TestResult testResult =
49 chre_test_common_TestResult_init_default;
50 testResult.has_code = true;
51 testResult.code = success ? chre_test_common_TestResult_Code_PASSED
52 : chre_test_common_TestResult_Code_FAILED;
53 if (!success && errMessage != nullptr) {
54 testResult.errorMessage = {.funcs = {.encode = encodeErrorMessage},
55 .arg = const_cast<char *>(errMessage)};
56 LOGE("%s", errMessage);
57 }
58 return testResult;
59 }
60
sendTestResultWithMsgToHost(uint16_t hostEndpointId,uint32_t messageType,bool success,const char * errMessage,bool abortOnFailure)61 void sendTestResultWithMsgToHost(uint16_t hostEndpointId, uint32_t messageType,
62 bool success, const char *errMessage,
63 bool abortOnFailure) {
64 // Unspecified endpoint is not allowed in chreSendMessageToHostEndpoint.
65 if (hostEndpointId == CHRE_HOST_ENDPOINT_UNSPECIFIED) {
66 hostEndpointId = CHRE_HOST_ENDPOINT_BROADCAST;
67 LOGE("Unspecified endpoint ID is not allowed");
68 success = false;
69 }
70
71 chre_test_common_TestResult result =
72 makeTestResultProtoMessage(success, errMessage);
73
74 sendMessageToHost(hostEndpointId, &result, chre_test_common_TestResult_fields,
75 messageType);
76
77 if (!success && abortOnFailure) {
78 chreAbort(0);
79 }
80 }
81
sendTestResultToHost(uint16_t hostEndpointId,uint32_t messageType,bool success,bool abortOnFailure)82 void sendTestResultToHost(uint16_t hostEndpointId, uint32_t messageType,
83 bool success, bool abortOnFailure) {
84 sendTestResultWithMsgToHost(hostEndpointId, messageType, success,
85 nullptr /* errMessage */, abortOnFailure);
86 }
87
sendEmptyMessageToHost(uint16_t hostEndpointId,uint32_t messageType)88 void sendEmptyMessageToHost(uint16_t hostEndpointId, uint32_t messageType) {
89 // Unspecified endpoint is not allowed in chreSendMessageToHostEndpoint.
90 if (hostEndpointId == CHRE_HOST_ENDPOINT_UNSPECIFIED) {
91 hostEndpointId = CHRE_HOST_ENDPOINT_BROADCAST;
92 LOGE("Unspecified endpoint ID is not allowed");
93 // TODO: Send failure message to host
94 return;
95 }
96
97 chreSendMessageToHostEndpoint(nullptr /* message */, 0 /* messageSize */,
98 messageType, hostEndpointId,
99 nullptr /* freeCallback */);
100 }
101
sendMessageToHost(uint16_t hostEndpointId,const void * message,const pb_field_t * fields,uint32_t messageType)102 void sendMessageToHost(uint16_t hostEndpointId, const void *message,
103 const pb_field_t *fields, uint32_t messageType) {
104 sendMessageToHostWithPermissions(hostEndpointId, message, fields, messageType,
105 chre::NanoappPermissions::CHRE_PERMS_NONE);
106 }
107
sendMessageToHostWithPermissions(uint16_t hostEndpointId,const void * message,const pb_field_t * fields,uint32_t messageType,chre::NanoappPermissions perms)108 void sendMessageToHostWithPermissions(uint16_t hostEndpointId,
109 const void *message,
110 const pb_field_t *fields,
111 uint32_t messageType,
112 chre::NanoappPermissions perms) {
113 size_t size;
114 if (!pb_get_encoded_size(&size, fields, message)) {
115 LOGE("Failed to get message size");
116 } else {
117 pb_byte_t *bytes = static_cast<pb_byte_t *>(chreHeapAlloc(size));
118 if (size > 0 && bytes == nullptr) {
119 LOG_OOM();
120 } else {
121 pb_ostream_t stream = pb_ostream_from_buffer(bytes, size);
122 if (!pb_encode(&stream, fields, message)) {
123 LOGE("Failed to encode message error %s", PB_GET_ERROR(&stream));
124 chreHeapFree(bytes);
125 } else if (!chreSendMessageWithPermissions(
126 bytes, size, messageType, hostEndpointId,
127 static_cast<uint32_t>(perms), heapFreeMessageCallback)) {
128 LOGE("Failed to send message to host");
129 }
130 }
131 }
132 }
133
134 } // namespace chre::test_shared
135