Home | History | Annotate | Download | only in common
      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 
     24 using flatbuffers::FlatBufferBuilder;
     25 using flatbuffers::Offset;
     26 
     27 // Aliased for consistency with the way these symbols are referenced in
     28 // CHRE-side code
     29 namespace fbs = ::chre::fbs;
     30 
     31 namespace android {
     32 namespace chre {
     33 
     34 const char *getStringFromByteVector(const std::vector<int8_t>& vec) {
     35   constexpr int8_t kNullChar = static_cast<int8_t>('\0');
     36   const char *str = nullptr;
     37 
     38   // Check that the vector is present, non-empty, and null-terminated
     39   if (vec.size() > 0 && vec[vec.size() - 1] == kNullChar) {
     40     str = reinterpret_cast<const char *>(vec.data());
     41   }
     42 
     43   return str;
     44 }
     45 
     46 bool HostProtocolHost::decodeMessageFromChre(
     47     const void *message, size_t messageLen, IChreMessageHandlers& handlers) {
     48   bool success = verifyMessage(message, messageLen);
     49   if (success) {
     50     std::unique_ptr<fbs::MessageContainerT> container =
     51         fbs::UnPackMessageContainer(message);
     52     fbs::ChreMessageUnion& msg = container->message;
     53 
     54     switch (container->message.type) {
     55       case fbs::ChreMessage::NanoappMessage:
     56         handlers.handleNanoappMessage(*msg.AsNanoappMessage());
     57         break;
     58 
     59       case fbs::ChreMessage::HubInfoResponse:
     60         handlers.handleHubInfoResponse(*msg.AsHubInfoResponse());
     61         break;
     62 
     63       case fbs::ChreMessage::NanoappListResponse:
     64         handlers.handleNanoappListResponse(*msg.AsNanoappListResponse());
     65         break;
     66 
     67       case fbs::ChreMessage::LoadNanoappResponse:
     68         handlers.handleLoadNanoappResponse(*msg.AsLoadNanoappResponse());
     69         break;
     70 
     71       case fbs::ChreMessage::UnloadNanoappResponse:
     72         handlers.handleUnloadNanoappResponse(*msg.AsUnloadNanoappResponse());
     73         break;
     74 
     75       case fbs::ChreMessage::DebugDumpData:
     76         handlers.handleDebugDumpData(*msg.AsDebugDumpData());
     77         break;
     78 
     79       case fbs::ChreMessage::DebugDumpResponse:
     80         handlers.handleDebugDumpResponse(*msg.AsDebugDumpResponse());
     81         break;
     82 
     83       default:
     84         LOGW("Got invalid/unexpected message type %" PRIu8,
     85              static_cast<uint8_t>(msg.type));
     86         success = false;
     87     }
     88   }
     89 
     90   return success;
     91 }
     92 
     93 void HostProtocolHost::encodeHubInfoRequest(FlatBufferBuilder& builder) {
     94   auto request = fbs::CreateHubInfoRequest(builder);
     95   finalize(builder, fbs::ChreMessage::HubInfoRequest, request.Union());
     96 }
     97 
     98 void HostProtocolHost::encodeFragmentedLoadNanoappRequest(
     99     flatbuffers::FlatBufferBuilder& builder,
    100     const FragmentedLoadRequest& request) {
    101   encodeLoadNanoappRequest(
    102       builder, request.transactionId, request.appId, request.appVersion,
    103       request.targetApiVersion, request.binary, request.fragmentId,
    104       request.appTotalSizeBytes);
    105 }
    106 
    107 void HostProtocolHost::encodeNanoappListRequest(FlatBufferBuilder& builder) {
    108   auto request = fbs::CreateNanoappListRequest(builder);
    109   finalize(builder, fbs::ChreMessage::NanoappListRequest, request.Union());
    110 }
    111 
    112 void HostProtocolHost::encodeUnloadNanoappRequest(
    113     FlatBufferBuilder& builder, uint32_t transactionId, uint64_t appId,
    114     bool allowSystemNanoappUnload) {
    115   auto request = fbs::CreateUnloadNanoappRequest(
    116       builder, transactionId, appId, allowSystemNanoappUnload);
    117   finalize(builder, fbs::ChreMessage::UnloadNanoappRequest, request.Union());
    118 }
    119 
    120 void HostProtocolHost::encodeTimeSyncMessage(FlatBufferBuilder& builder,
    121                                              int64_t offset) {
    122   auto request = fbs::CreateTimeSyncMessage(builder, offset);
    123   finalize(builder, fbs::ChreMessage::TimeSyncMessage, request.Union());
    124 }
    125 
    126 void HostProtocolHost::encodeDebugDumpRequest(FlatBufferBuilder& builder) {
    127   auto request = fbs::CreateDebugDumpRequest(builder);
    128   finalize(builder, fbs::ChreMessage::DebugDumpRequest, request.Union());
    129 }
    130 
    131 bool HostProtocolHost::extractHostClientIdAndType(
    132     const void *message, size_t messageLen, uint16_t *hostClientId,
    133     ::chre::fbs::ChreMessage *messageType) {
    134   bool success = false;
    135   if (hostClientId != nullptr && messageType != nullptr) {
    136     success = verifyMessage(message, messageLen);
    137 
    138     if (success) {
    139       const fbs::MessageContainer *container = fbs::GetMessageContainer(message);
    140       // host_addr guaranteed to be non-null via verifyMessage (it's a required
    141       // field)
    142       *hostClientId = container->host_addr()->client_id();
    143       *messageType = container->message_type();
    144     }
    145   }
    146 
    147   return success;
    148 }
    149 
    150 bool HostProtocolHost::mutateHostClientId(void *message, size_t messageLen,
    151                                           uint16_t hostClientId) {
    152   bool success = verifyMessage(message, messageLen);
    153 
    154   if (!success) {
    155     LOGE("Message verification failed - can't mutate host ID");
    156   } else {
    157     fbs::MessageContainer *container = fbs::GetMutableMessageContainer(message);
    158     // host_addr guaranteed to be non-null via verifyMessage (it's a required
    159     // field)
    160     container->mutable_host_addr()->mutate_client_id(hostClientId);
    161     success = true;
    162   }
    163 
    164   return success;
    165 }
    166 
    167 void HostProtocolHost::encodeLoadNanoappRequest(
    168     FlatBufferBuilder& builder, uint32_t transactionId, uint64_t appId,
    169     uint32_t appVersion, uint32_t targetApiVersion,
    170     const std::vector<uint8_t>& nanoappBinary, uint32_t fragmentId,
    171     size_t appTotalSizeBytes) {
    172   auto appBinary = builder.CreateVector(nanoappBinary);
    173   auto request = fbs::CreateLoadNanoappRequest(
    174       builder, transactionId, appId, appVersion, targetApiVersion, appBinary,
    175       fragmentId, appTotalSizeBytes);
    176   finalize(builder, fbs::ChreMessage::LoadNanoappRequest, request.Union());
    177 }
    178 
    179 }  // namespace chre
    180 }  // namespace android
    181