普通文本  |  177行  |  5.98 KB

/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "chre_host/host_protocol_host.h"

#include <inttypes.h>
#include <string.h>

#include "chre_host/log.h"

using flatbuffers::FlatBufferBuilder;
using flatbuffers::Offset;

// Aliased for consistency with the way these symbols are referenced in
// CHRE-side code
namespace fbs = ::chre::fbs;

namespace android {
namespace chre {

namespace {

/**
 * Checks that a string encapsulated as a byte vector is null-terminated, and
 * if it is, returns a pointer to the vector's data. Otherwise returns null.
 *
 * @param vec Target vector, can be null
 *
 * @return Pointer to the vector's data, or null
 */
const char *getStringFromByteVector(const flatbuffers::Vector<int8_t> *vec) {
  constexpr int8_t kNullChar = 0;
  const char *str = nullptr;

  // Check that the vector is present, non-empty, and null-terminated
  if (vec != nullptr && vec->size() > 0
      && (*vec)[vec->size() - 1] == kNullChar) {
    str = reinterpret_cast<const char *>(vec->data());
  }

  return str;
}

}  // anonymous namespace

bool HostProtocolHost::decodeMessageFromChre(
    const void *message, size_t messageLen, IChreMessageHandlers& handlers) {
  bool success = verifyMessage(message, messageLen);
  if (success) {
    const fbs::MessageContainer *container = fbs::GetMessageContainer(message);

    switch (container->message_type()) {
      case fbs::ChreMessage::NanoappMessage: {
        const auto *nanoappMsg = static_cast<const fbs::NanoappMessage *>(
            container->message());
        // Required field; verifier ensures that this is not null (though it
        // may be empty)
        const flatbuffers::Vector<uint8_t> *msgData = nanoappMsg->message();
        handlers.handleNanoappMessage(
            nanoappMsg->app_id(), nanoappMsg->message_type(),
            nanoappMsg->host_endpoint(), msgData->data(), msgData->size());
        break;
      }

      case fbs::ChreMessage::HubInfoResponse: {
        const auto *resp = static_cast<const fbs::HubInfoResponse *>(
            container->message());

        const char *name = getStringFromByteVector(resp->name());
        const char *vendor = getStringFromByteVector(resp->vendor());
        const char *toolchain = getStringFromByteVector(resp->toolchain());

        handlers.handleHubInfoResponse(
            name, vendor, toolchain, resp->platform_version(),
            resp->toolchain_version(), resp->peak_mips(), resp->stopped_power(),
            resp->sleep_power(), resp->peak_power(), resp->max_msg_len(),
            resp->platform_id(), resp->chre_platform_version());
        break;
      }

      case fbs::ChreMessage::NanoappListResponse: {
        const auto *resp = static_cast<const fbs::NanoappListResponse *>(
            container->message());
        fbs::NanoappListResponseT response;
        resp->UnPackTo(&response);
        handlers.handleNanoappListResponse(response);
        break;
      }

      case fbs::ChreMessage::LoadNanoappResponse: {
        const auto *resp = static_cast<const fbs::LoadNanoappResponse *>(
            container->message());
        fbs::LoadNanoappResponseT response;
        resp->UnPackTo(&response);
        handlers.handleLoadNanoappResponse(response);
        break;
      }

      default:
        LOGW("Got invalid/unexpected message type %" PRIu8,
             static_cast<uint8_t>(container->message_type()));
        success = false;
    }
  }

  return success;
}

void HostProtocolHost::encodeHubInfoRequest(FlatBufferBuilder& builder) {
  auto request = fbs::CreateHubInfoRequest(builder);
  finalize(builder, fbs::ChreMessage::HubInfoRequest, request.Union());
}

void HostProtocolHost::encodeLoadNanoappRequest(
    FlatBufferBuilder& builder, uint32_t transactionId, uint64_t appId,
    uint32_t appVersion, uint32_t targetApiVersion,
    const std::vector<uint8_t>& nanoappBinary) {
  auto appBinary = builder.CreateVector(nanoappBinary);
  auto request = fbs::CreateLoadNanoappRequest(
      builder, transactionId, appId, appVersion, targetApiVersion, appBinary);
  finalize(builder, fbs::ChreMessage::LoadNanoappRequest, request.Union());
}

void HostProtocolHost::encodeNanoappListRequest(FlatBufferBuilder& builder) {
  auto request = fbs::CreateNanoappListRequest(builder);
  finalize(builder, fbs::ChreMessage::NanoappListRequest, request.Union());
}

bool HostProtocolHost::extractHostClientId(const void *message,
                                           size_t messageLen,
                                           uint16_t *hostClientId) {
  bool success = verifyMessage(message, messageLen);

  if (success && hostClientId != nullptr) {
    const fbs::MessageContainer *container = fbs::GetMessageContainer(message);
    // host_addr guaranteed to be non-null via verifyMessage (it's a required
    // field)
    *hostClientId = container->host_addr()->client_id();
    success = true;
  }

  return success;
}

bool HostProtocolHost::mutateHostClientId(void *message, size_t messageLen,
                                          uint16_t hostClientId) {
  bool success = verifyMessage(message, messageLen);

  if (!success) {
    LOGE("Message verification failed - can't mutate host ID");
  } else {
    fbs::MessageContainer *container = fbs::GetMutableMessageContainer(message);
    // host_addr guaranteed to be non-null via verifyMessage (it's a required
    // field)
    container->mutable_host_addr()->mutate_client_id(hostClientId);
    success = true;
  }

  return success;
}

}  // namespace chre
}  // namespace android