1/* 2 * Copyright (C) 2017 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 "chre_host/host_protocol_host.h" 18 19#include <inttypes.h> 20#include <string.h> 21 22#include "chre_host/log.h" 23 24using flatbuffers::FlatBufferBuilder; 25using flatbuffers::Offset; 26 27// Aliased for consistency with the way these symbols are referenced in 28// CHRE-side code 29namespace fbs = ::chre::fbs; 30 31namespace android { 32namespace chre { 33 34namespace { 35 36/** 37 * Checks that a string encapsulated as a byte vector is null-terminated, and 38 * if it is, returns a pointer to the vector's data. Otherwise returns null. 39 * 40 * @param vec Target vector, can be null 41 * 42 * @return Pointer to the vector's data, or null 43 */ 44const char *getStringFromByteVector(const flatbuffers::Vector<int8_t> *vec) { 45 constexpr int8_t kNullChar = 0; 46 const char *str = nullptr; 47 48 // Check that the vector is present, non-empty, and null-terminated 49 if (vec != nullptr && vec->size() > 0 50 && (*vec)[vec->size() - 1] == kNullChar) { 51 str = reinterpret_cast<const char *>(vec->data()); 52 } 53 54 return str; 55} 56 57} // anonymous namespace 58 59bool HostProtocolHost::decodeMessageFromChre( 60 const void *message, size_t messageLen, IChreMessageHandlers& handlers) { 61 bool success = verifyMessage(message, messageLen); 62 if (success) { 63 const fbs::MessageContainer *container = fbs::GetMessageContainer(message); 64 65 switch (container->message_type()) { 66 case fbs::ChreMessage::NanoappMessage: { 67 const auto *nanoappMsg = static_cast<const fbs::NanoappMessage *>( 68 container->message()); 69 // Required field; verifier ensures that this is not null (though it 70 // may be empty) 71 const flatbuffers::Vector<uint8_t> *msgData = nanoappMsg->message(); 72 handlers.handleNanoappMessage( 73 nanoappMsg->app_id(), nanoappMsg->message_type(), 74 nanoappMsg->host_endpoint(), msgData->data(), msgData->size()); 75 break; 76 } 77 78 case fbs::ChreMessage::HubInfoResponse: { 79 const auto *resp = static_cast<const fbs::HubInfoResponse *>( 80 container->message()); 81 82 const char *name = getStringFromByteVector(resp->name()); 83 const char *vendor = getStringFromByteVector(resp->vendor()); 84 const char *toolchain = getStringFromByteVector(resp->toolchain()); 85 86 handlers.handleHubInfoResponse( 87 name, vendor, toolchain, resp->platform_version(), 88 resp->toolchain_version(), resp->peak_mips(), resp->stopped_power(), 89 resp->sleep_power(), resp->peak_power(), resp->max_msg_len(), 90 resp->platform_id(), resp->chre_platform_version()); 91 break; 92 } 93 94 case fbs::ChreMessage::NanoappListResponse: { 95 const auto *resp = static_cast<const fbs::NanoappListResponse *>( 96 container->message()); 97 fbs::NanoappListResponseT response; 98 resp->UnPackTo(&response); 99 handlers.handleNanoappListResponse(response); 100 break; 101 } 102 103 case fbs::ChreMessage::LoadNanoappResponse: { 104 const auto *resp = static_cast<const fbs::LoadNanoappResponse *>( 105 container->message()); 106 fbs::LoadNanoappResponseT response; 107 resp->UnPackTo(&response); 108 handlers.handleLoadNanoappResponse(response); 109 break; 110 } 111 112 default: 113 LOGW("Got invalid/unexpected message type %" PRIu8, 114 static_cast<uint8_t>(container->message_type())); 115 success = false; 116 } 117 } 118 119 return success; 120} 121 122void HostProtocolHost::encodeHubInfoRequest(FlatBufferBuilder& builder) { 123 auto request = fbs::CreateHubInfoRequest(builder); 124 finalize(builder, fbs::ChreMessage::HubInfoRequest, request.Union()); 125} 126 127void HostProtocolHost::encodeLoadNanoappRequest( 128 FlatBufferBuilder& builder, uint32_t transactionId, uint64_t appId, 129 uint32_t appVersion, uint32_t targetApiVersion, 130 const std::vector<uint8_t>& nanoappBinary) { 131 auto appBinary = builder.CreateVector(nanoappBinary); 132 auto request = fbs::CreateLoadNanoappRequest( 133 builder, transactionId, appId, appVersion, targetApiVersion, appBinary); 134 finalize(builder, fbs::ChreMessage::LoadNanoappRequest, request.Union()); 135} 136 137void HostProtocolHost::encodeNanoappListRequest(FlatBufferBuilder& builder) { 138 auto request = fbs::CreateNanoappListRequest(builder); 139 finalize(builder, fbs::ChreMessage::NanoappListRequest, request.Union()); 140} 141 142bool HostProtocolHost::extractHostClientId(const void *message, 143 size_t messageLen, 144 uint16_t *hostClientId) { 145 bool success = verifyMessage(message, messageLen); 146 147 if (success && hostClientId != nullptr) { 148 const fbs::MessageContainer *container = fbs::GetMessageContainer(message); 149 // host_addr guaranteed to be non-null via verifyMessage (it's a required 150 // field) 151 *hostClientId = container->host_addr()->client_id(); 152 success = true; 153 } 154 155 return success; 156} 157 158bool HostProtocolHost::mutateHostClientId(void *message, size_t messageLen, 159 uint16_t hostClientId) { 160 bool success = verifyMessage(message, messageLen); 161 162 if (!success) { 163 LOGE("Message verification failed - can't mutate host ID"); 164 } else { 165 fbs::MessageContainer *container = fbs::GetMutableMessageContainer(message); 166 // host_addr guaranteed to be non-null via verifyMessage (it's a required 167 // field) 168 container->mutable_host_addr()->mutate_client_id(hostClientId); 169 success = true; 170 } 171 172 return success; 173} 174 175} // namespace chre 176} // namespace android 177