153b98346214effa969c45e95ae417c08fe492779Andrew Rossignol/*
253b98346214effa969c45e95ae417c08fe492779Andrew Rossignol * Copyright (C) 2017 The Android Open Source Project
353b98346214effa969c45e95ae417c08fe492779Andrew Rossignol *
453b98346214effa969c45e95ae417c08fe492779Andrew Rossignol * Licensed under the Apache License, Version 2.0 (the "License");
553b98346214effa969c45e95ae417c08fe492779Andrew Rossignol * you may not use this file except in compliance with the License.
653b98346214effa969c45e95ae417c08fe492779Andrew Rossignol * You may obtain a copy of the License at
753b98346214effa969c45e95ae417c08fe492779Andrew Rossignol *
853b98346214effa969c45e95ae417c08fe492779Andrew Rossignol *      http://www.apache.org/licenses/LICENSE-2.0
953b98346214effa969c45e95ae417c08fe492779Andrew Rossignol *
1053b98346214effa969c45e95ae417c08fe492779Andrew Rossignol * Unless required by applicable law or agreed to in writing, software
1153b98346214effa969c45e95ae417c08fe492779Andrew Rossignol * distributed under the License is distributed on an "AS IS" BASIS,
1253b98346214effa969c45e95ae417c08fe492779Andrew Rossignol * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1353b98346214effa969c45e95ae417c08fe492779Andrew Rossignol * See the License for the specific language governing permissions and
1453b98346214effa969c45e95ae417c08fe492779Andrew Rossignol * limitations under the License.
1553b98346214effa969c45e95ae417c08fe492779Andrew Rossignol */
1653b98346214effa969c45e95ae417c08fe492779Andrew Rossignol
1753b98346214effa969c45e95ae417c08fe492779Andrew Rossignol#include "chre/platform/android/host_link.h"
1853b98346214effa969c45e95ae417c08fe492779Andrew Rossignol
1953b98346214effa969c45e95ae417c08fe492779Andrew Rossignol#include "chre/core/event_loop_manager.h"
2053b98346214effa969c45e95ae417c08fe492779Andrew Rossignol#include "chre/platform/shared/host_protocol_common.h"
2153b98346214effa969c45e95ae417c08fe492779Andrew Rossignol#include "chre/util/macros.h"
2253b98346214effa969c45e95ae417c08fe492779Andrew Rossignol#include "chre_api/chre/version.h"
2353b98346214effa969c45e95ae417c08fe492779Andrew Rossignol#include "chre_host/host_messages_generated.h"
2453b98346214effa969c45e95ae417c08fe492779Andrew Rossignol
2553b98346214effa969c45e95ae417c08fe492779Andrew Rossignolnamespace chre {
2653b98346214effa969c45e95ae417c08fe492779Andrew Rossignol
273f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol//! Used to pass the client ID through the user data pointer in deferCallback
283f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignolunion HostClientIdCallbackData {
293f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol  uint16_t hostClientId;
303f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol  void *ptr;
313f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol};
323f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol
333f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignolstatic_assert(sizeof(uint16_t) <= sizeof(void*),
343f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol              "Pointer must at least fit a u16 for passing the host client ID");
353f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol
3653b98346214effa969c45e95ae417c08fe492779Andrew Rossignol/**
3753b98346214effa969c45e95ae417c08fe492779Andrew Rossignol * Assigns a vector the contents of a C-style, null-terminated string.
3853b98346214effa969c45e95ae417c08fe492779Andrew Rossignol *
3953b98346214effa969c45e95ae417c08fe492779Andrew Rossignol * @param vector The vector to assign with the contents of a string.
4053b98346214effa969c45e95ae417c08fe492779Andrew Rossignol * @param str The string to assign.
4153b98346214effa969c45e95ae417c08fe492779Andrew Rossignol */
4253b98346214effa969c45e95ae417c08fe492779Andrew Rossignolvoid setVectorToString(std::vector<int8_t> *vector, const char *str) {
4353b98346214effa969c45e95ae417c08fe492779Andrew Rossignol  *vector = std::vector<int8_t>(str, str + strlen(str));
4453b98346214effa969c45e95ae417c08fe492779Andrew Rossignol}
4553b98346214effa969c45e95ae417c08fe492779Andrew Rossignol
4653b98346214effa969c45e95ae417c08fe492779Andrew Rossignol/**
473f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol * Sends a message to the host given a hostClientId.
483f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol *
493f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol * @param message The message to send to the host.
503f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol * @param hostClientId The host who made the original request for which this is
513f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol *        a reply.
523f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol */
533f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignoltemplate<typename T>
543f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignolvoid sendFlatbufferToHost(T& message, uint16_t hostClientId) {
553f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol  static_assert(
563f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol      fbs::ChreMessageTraits<typename T::TableType>::enum_value
573f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol          != fbs::ChreMessage::NONE,
583f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol      "Only works for message types supported by ChreMessageUnion");
593f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol
603f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol  fbs::MessageContainerT container;
613f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol  container.message.Set(std::move(message));
623f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol  container.host_addr.reset(new fbs::HostAddress(hostClientId));
633f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol
643f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol  flatbuffers::FlatBufferBuilder builder;
653f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol  auto containerOffset = CreateMessageContainer(builder, &container, nullptr);
663f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol  builder.Finish(containerOffset);
673f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol
683f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol  SocketServerSingleton::get()->sendToClientById(
693f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol      builder.GetBufferPointer(), builder.GetSize(), hostClientId);
703f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol}
713f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol
723f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol/**
7353b98346214effa969c45e95ae417c08fe492779Andrew Rossignol * Handles a message directed to a nanoapp from the system.
7453b98346214effa969c45e95ae417c08fe492779Andrew Rossignol *
7553b98346214effa969c45e95ae417c08fe492779Andrew Rossignol * @param message The message to deliver to a nanoapp.
7653b98346214effa969c45e95ae417c08fe492779Andrew Rossignol */
7753b98346214effa969c45e95ae417c08fe492779Andrew Rossignolvoid handleNanoappMessage(const fbs::NanoappMessageT& message) {
7853b98346214effa969c45e95ae417c08fe492779Andrew Rossignol  LOGD("handleNanoappMessage");
79b10afb27a73ed62371ea56c9cf96f02aa45354a6Andrew Rossignol  HostCommsManager& manager =
80b10afb27a73ed62371ea56c9cf96f02aa45354a6Andrew Rossignol      EventLoopManagerSingleton::get()->getHostCommsManager();
81b10afb27a73ed62371ea56c9cf96f02aa45354a6Andrew Rossignol  manager.sendMessageToNanoappFromHost(
82b10afb27a73ed62371ea56c9cf96f02aa45354a6Andrew Rossignol      message.app_id, message.message_type, message.host_endpoint,
83b10afb27a73ed62371ea56c9cf96f02aa45354a6Andrew Rossignol      message.message.data(), message.message.size());
8453b98346214effa969c45e95ae417c08fe492779Andrew Rossignol}
8553b98346214effa969c45e95ae417c08fe492779Andrew Rossignol
8653b98346214effa969c45e95ae417c08fe492779Andrew Rossignol/**
8753b98346214effa969c45e95ae417c08fe492779Andrew Rossignol * Handles a request for information about this context hub instance.
8853b98346214effa969c45e95ae417c08fe492779Andrew Rossignol *
8953b98346214effa969c45e95ae417c08fe492779Andrew Rossignol * @param hostClientId The client ID on the host making the request.
9053b98346214effa969c45e95ae417c08fe492779Andrew Rossignol */
9153b98346214effa969c45e95ae417c08fe492779Andrew Rossignolvoid handleHubInfoRequest(uint16_t hostClientId) {
9253b98346214effa969c45e95ae417c08fe492779Andrew Rossignol  LOGD("handleHubInfoRequest");
9353b98346214effa969c45e95ae417c08fe492779Andrew Rossignol  fbs::HubInfoResponseT response;
9453b98346214effa969c45e95ae417c08fe492779Andrew Rossignol  setVectorToString(&response.name, "CHRE on Android");
9553b98346214effa969c45e95ae417c08fe492779Andrew Rossignol  setVectorToString(&response.vendor, "Google");
9653b98346214effa969c45e95ae417c08fe492779Andrew Rossignol  setVectorToString(&response.toolchain, "Android NDK API 26 (clang "
9753b98346214effa969c45e95ae417c08fe492779Andrew Rossignol    STRINGIFY(__clang_major__) "."
9853b98346214effa969c45e95ae417c08fe492779Andrew Rossignol    STRINGIFY(__clang_minor__) "."
9953b98346214effa969c45e95ae417c08fe492779Andrew Rossignol    STRINGIFY(__clang_patchlevel__) ")");
10053b98346214effa969c45e95ae417c08fe492779Andrew Rossignol  response.platform_version = 0;
10153b98346214effa969c45e95ae417c08fe492779Andrew Rossignol  response.toolchain_version = ((__clang_major__ & 0xFF) << 24) |
10253b98346214effa969c45e95ae417c08fe492779Andrew Rossignol    ((__clang_minor__ & 0xFF) << 16) |
10353b98346214effa969c45e95ae417c08fe492779Andrew Rossignol    (__clang_patchlevel__ & 0xFFFF);
10453b98346214effa969c45e95ae417c08fe492779Andrew Rossignol  response.peak_mips = 1000;
10553b98346214effa969c45e95ae417c08fe492779Andrew Rossignol  response.stopped_power = 1000;
10653b98346214effa969c45e95ae417c08fe492779Andrew Rossignol  response.sleep_power = 1000;
10753b98346214effa969c45e95ae417c08fe492779Andrew Rossignol  response.peak_power = 10000;
10853b98346214effa969c45e95ae417c08fe492779Andrew Rossignol  response.max_msg_len = CHRE_MESSAGE_TO_HOST_MAX_SIZE;
10953b98346214effa969c45e95ae417c08fe492779Andrew Rossignol  response.platform_id = chreGetPlatformId();
11053b98346214effa969c45e95ae417c08fe492779Andrew Rossignol  response.chre_platform_version = chreGetVersion();
11153b98346214effa969c45e95ae417c08fe492779Andrew Rossignol
1123f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol  sendFlatbufferToHost(response, hostClientId);
1133f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol}
11453b98346214effa969c45e95ae417c08fe492779Andrew Rossignol
1153f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignolvoid constructNanoappListCallback(uint16_t /*eventType*/, void *cookie) {
1163f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol  HostClientIdCallbackData clientIdCbData;
1173f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol  clientIdCbData.ptr = cookie;
11853b98346214effa969c45e95ae417c08fe492779Andrew Rossignol
1193f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol  auto nanoappAddCallback = [](const Nanoapp *nanoapp, void *data) {
1203f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol    auto response = static_cast<fbs::NanoappListResponseT *>(data);
1213f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol    auto nanoappListEntry =
1223f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol        std::unique_ptr<fbs::NanoappListEntryT>(new fbs::NanoappListEntryT());
1233f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol    nanoappListEntry->app_id = nanoapp->getAppId();
1243f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol    nanoappListEntry->version = nanoapp->getAppVersion();
1253f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol    nanoappListEntry->enabled = true;
1263f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol    nanoappListEntry->is_system = nanoapp->isSystemNanoapp();
1273f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol    response->nanoapps.push_back(std::move(nanoappListEntry));
1283f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol  };
1293f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol
1303f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol  fbs::NanoappListResponseT response;
1313f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol  EventLoop& eventLoop = EventLoopManagerSingleton::get()->getEventLoop();
1323f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol  eventLoop.forEachNanoapp(nanoappAddCallback, &response);
1333f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol
1343f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol  sendFlatbufferToHost(response, clientIdCbData.hostClientId);
13553b98346214effa969c45e95ae417c08fe492779Andrew Rossignol}
13653b98346214effa969c45e95ae417c08fe492779Andrew Rossignol
13753b98346214effa969c45e95ae417c08fe492779Andrew Rossignol/**
13853b98346214effa969c45e95ae417c08fe492779Andrew Rossignol * Handles a request from the host for a list of nanoapps.
13953b98346214effa969c45e95ae417c08fe492779Andrew Rossignol *
14053b98346214effa969c45e95ae417c08fe492779Andrew Rossignol * @param hostClientId The client ID on the host making the request.
14153b98346214effa969c45e95ae417c08fe492779Andrew Rossignol */
14253b98346214effa969c45e95ae417c08fe492779Andrew Rossignolvoid handleNanoappListRequest(uint16_t hostClientId) {
14353b98346214effa969c45e95ae417c08fe492779Andrew Rossignol  LOGD("handleNanoappListRequest");
1443f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol  HostClientIdCallbackData cbData = {};
1453f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol  cbData.hostClientId = hostClientId;
1463f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol  EventLoopManagerSingleton::get()->deferCallback(
1473f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol      SystemCallbackType::NanoappListResponse, cbData.ptr,
1483f346add1e161ee5e1b1f8580a7c024095e867b2Andrew Rossignol      constructNanoappListCallback);
14953b98346214effa969c45e95ae417c08fe492779Andrew Rossignol}
15053b98346214effa969c45e95ae417c08fe492779Andrew Rossignol
15153b98346214effa969c45e95ae417c08fe492779Andrew Rossignol/**
15253b98346214effa969c45e95ae417c08fe492779Andrew Rossignol * Handles a request to load a nanoapp.
15353b98346214effa969c45e95ae417c08fe492779Andrew Rossignol *
15453b98346214effa969c45e95ae417c08fe492779Andrew Rossignol * @param hostClientId The client ID on the host making the request.
15553b98346214effa969c45e95ae417c08fe492779Andrew Rossignol * @param loadRequest The details of the nanoapp load request.
15653b98346214effa969c45e95ae417c08fe492779Andrew Rossignol */
15753b98346214effa969c45e95ae417c08fe492779Andrew Rossignolvoid handleLoadNanoappRequest(
15853b98346214effa969c45e95ae417c08fe492779Andrew Rossignol    uint16_t hostClientId, const fbs::LoadNanoappRequestT& loadRequest) {
15953b98346214effa969c45e95ae417c08fe492779Andrew Rossignol  LOGD("handleLoadNanoappRequest");
16053b98346214effa969c45e95ae417c08fe492779Andrew Rossignol}
16153b98346214effa969c45e95ae417c08fe492779Andrew Rossignol
16253b98346214effa969c45e95ae417c08fe492779Andrew Rossignol/**
16353b98346214effa969c45e95ae417c08fe492779Andrew Rossignol * Handles a request to unload a nanoapp.
16453b98346214effa969c45e95ae417c08fe492779Andrew Rossignol *
16553b98346214effa969c45e95ae417c08fe492779Andrew Rossignol * @param hostClientId The client ID on the host making the request.
16653b98346214effa969c45e95ae417c08fe492779Andrew Rossignol * @param unloadRequest The details of the nanoapp unload request.
16753b98346214effa969c45e95ae417c08fe492779Andrew Rossignol */
16853b98346214effa969c45e95ae417c08fe492779Andrew Rossignolvoid handleUnloadNanoappRequest(
16953b98346214effa969c45e95ae417c08fe492779Andrew Rossignol    uint16_t hostClientId, const fbs::UnloadNanoappRequestT& unloadRequest) {
17053b98346214effa969c45e95ae417c08fe492779Andrew Rossignol  LOGD("handleUnloadNanoappRequest");
17153b98346214effa969c45e95ae417c08fe492779Andrew Rossignol}
17253b98346214effa969c45e95ae417c08fe492779Andrew Rossignol
17353b98346214effa969c45e95ae417c08fe492779Andrew Rossignol/**
17453b98346214effa969c45e95ae417c08fe492779Andrew Rossignol * Handles a request for a debug dump.
17553b98346214effa969c45e95ae417c08fe492779Andrew Rossignol *
17653b98346214effa969c45e95ae417c08fe492779Andrew Rossignol * @param hostClientId The client OD on the host making the request.
17753b98346214effa969c45e95ae417c08fe492779Andrew Rossignol */
17853b98346214effa969c45e95ae417c08fe492779Andrew Rossignolvoid handleDebugDumpRequest(uint16_t hostClientId) {
17953b98346214effa969c45e95ae417c08fe492779Andrew Rossignol  LOGD("handleDebugDumpRequest");
18053b98346214effa969c45e95ae417c08fe492779Andrew Rossignol}
18153b98346214effa969c45e95ae417c08fe492779Andrew Rossignol
18253b98346214effa969c45e95ae417c08fe492779Andrew Rossignolbool handleMessageFromHost(void *message, size_t length) {
18353b98346214effa969c45e95ae417c08fe492779Andrew Rossignol  bool success = HostProtocolCommon::verifyMessage(message, length);
18453b98346214effa969c45e95ae417c08fe492779Andrew Rossignol  if (success) {
18553b98346214effa969c45e95ae417c08fe492779Andrew Rossignol    fbs::MessageContainerT container;
18653b98346214effa969c45e95ae417c08fe492779Andrew Rossignol    fbs::GetMessageContainer(message)->UnPackTo(&container);
18753b98346214effa969c45e95ae417c08fe492779Andrew Rossignol    uint16_t hostClientId = container.host_addr->client_id();
18853b98346214effa969c45e95ae417c08fe492779Andrew Rossignol    switch (container.message.type) {
18953b98346214effa969c45e95ae417c08fe492779Andrew Rossignol      case fbs::ChreMessage::NanoappMessage:
19053b98346214effa969c45e95ae417c08fe492779Andrew Rossignol        handleNanoappMessage(*container.message.AsNanoappMessage());
19153b98346214effa969c45e95ae417c08fe492779Andrew Rossignol        break;
19253b98346214effa969c45e95ae417c08fe492779Andrew Rossignol
19353b98346214effa969c45e95ae417c08fe492779Andrew Rossignol      case fbs::ChreMessage::HubInfoRequest:
19453b98346214effa969c45e95ae417c08fe492779Andrew Rossignol        handleHubInfoRequest(hostClientId);
19553b98346214effa969c45e95ae417c08fe492779Andrew Rossignol        break;
19653b98346214effa969c45e95ae417c08fe492779Andrew Rossignol
19753b98346214effa969c45e95ae417c08fe492779Andrew Rossignol      case fbs::ChreMessage::NanoappListRequest:
19853b98346214effa969c45e95ae417c08fe492779Andrew Rossignol        handleNanoappListRequest(hostClientId);
19953b98346214effa969c45e95ae417c08fe492779Andrew Rossignol        break;
20053b98346214effa969c45e95ae417c08fe492779Andrew Rossignol
20153b98346214effa969c45e95ae417c08fe492779Andrew Rossignol      case fbs::ChreMessage::LoadNanoappRequest:
20253b98346214effa969c45e95ae417c08fe492779Andrew Rossignol        handleLoadNanoappRequest(hostClientId,
20353b98346214effa969c45e95ae417c08fe492779Andrew Rossignol                                 *container.message.AsLoadNanoappRequest());
20453b98346214effa969c45e95ae417c08fe492779Andrew Rossignol        break;
20553b98346214effa969c45e95ae417c08fe492779Andrew Rossignol
20653b98346214effa969c45e95ae417c08fe492779Andrew Rossignol      case fbs::ChreMessage::UnloadNanoappRequest:
20753b98346214effa969c45e95ae417c08fe492779Andrew Rossignol        handleUnloadNanoappRequest(hostClientId,
20853b98346214effa969c45e95ae417c08fe492779Andrew Rossignol                                   *container.message.AsUnloadNanoappRequest());
20953b98346214effa969c45e95ae417c08fe492779Andrew Rossignol        break;
21053b98346214effa969c45e95ae417c08fe492779Andrew Rossignol
21153b98346214effa969c45e95ae417c08fe492779Andrew Rossignol      case fbs::ChreMessage::DebugDumpRequest:
21253b98346214effa969c45e95ae417c08fe492779Andrew Rossignol        handleDebugDumpRequest(hostClientId);
21353b98346214effa969c45e95ae417c08fe492779Andrew Rossignol        break;
21453b98346214effa969c45e95ae417c08fe492779Andrew Rossignol
21553b98346214effa969c45e95ae417c08fe492779Andrew Rossignol      default:
21653b98346214effa969c45e95ae417c08fe492779Andrew Rossignol        LOGW("Got invalid/unexpected message type %" PRIu8,
21753b98346214effa969c45e95ae417c08fe492779Andrew Rossignol             static_cast<uint8_t>(container.message.type));
21853b98346214effa969c45e95ae417c08fe492779Andrew Rossignol        success = false;
21953b98346214effa969c45e95ae417c08fe492779Andrew Rossignol    }
22053b98346214effa969c45e95ae417c08fe492779Andrew Rossignol  }
22153b98346214effa969c45e95ae417c08fe492779Andrew Rossignol
22253b98346214effa969c45e95ae417c08fe492779Andrew Rossignol  return success;
22353b98346214effa969c45e95ae417c08fe492779Andrew Rossignol}
22453b98346214effa969c45e95ae417c08fe492779Andrew Rossignol
22553b98346214effa969c45e95ae417c08fe492779Andrew Rossignol}  // namespace chre
226