13d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie/*
23d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie * Copyright (C) 2017 The Android Open Source Project
33d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie *
43d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie * Licensed under the Apache License, Version 2.0 (the "License");
53d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie * you may not use this file except in compliance with the License.
63d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie * You may obtain a copy of the License at
73d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie *
83d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie *      http://www.apache.org/licenses/LICENSE-2.0
93d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie *
103d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie * Unless required by applicable law or agreed to in writing, software
113d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie * distributed under the License is distributed on an "AS IS" BASIS,
123d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie * See the License for the specific language governing permissions and
143d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie * limitations under the License.
153d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie */
163d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
173d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie#define LOG_TAG "ContextHubHal"
1847a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie#define LOG_NDEBUG 0
193d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
203d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie#include "generic_context_hub.h"
213d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
223d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie#include <chrono>
23a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie#include <cinttypes>
24a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie#include <vector>
253d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
2658276308709e5568ba2976e93b37211a52589166Brian Duddie#include <unistd.h>
273d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie#include <utils/Log.h>
283d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
293d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddienamespace android {
303d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddienamespace hardware {
313d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddienamespace contexthub {
323d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddienamespace V1_0 {
333d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddienamespace implementation {
343d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
353d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddieusing ::android::hardware::Return;
36a413add0b3504b1e8576235cea52b6738829feccBrian Duddieusing ::android::hardware::contexthub::V1_0::AsyncEventType;
373d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddieusing ::android::hardware::contexthub::V1_0::Result;
3847a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddieusing ::android::hardware::contexthub::V1_0::TransactionResult;
393d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddieusing ::android::chre::HostProtocolHost;
403d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddieusing ::flatbuffers::FlatBufferBuilder;
413d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
4207da7d6425058577d477074f99bafd4b8e81bb83Brian Duddie// Aliased for consistency with the way these symbols are referenced in
4307da7d6425058577d477074f99bafd4b8e81bb83Brian Duddie// CHRE-side code
4407da7d6425058577d477074f99bafd4b8e81bb83Brian Duddienamespace fbs = ::chre::fbs;
4507da7d6425058577d477074f99bafd4b8e81bb83Brian Duddie
463d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddienamespace {
473d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
483d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddieconstexpr uint32_t kDefaultHubId = 0;
493d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
503d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddieconstexpr uint8_t extractChreApiMajorVersion(uint32_t chreVersion) {
513d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  return static_cast<uint8_t>(chreVersion >> 24);
523d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie}
533d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
543d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddieconstexpr uint8_t extractChreApiMinorVersion(uint32_t chreVersion) {
553d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  return static_cast<uint8_t>(chreVersion >> 16);
563d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie}
573d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
583d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddieconstexpr uint16_t extractChrePatchVersion(uint32_t chreVersion) {
593d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  return static_cast<uint16_t>(chreVersion);
603d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie}
613d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
6258276308709e5568ba2976e93b37211a52589166Brian Duddie/**
6358276308709e5568ba2976e93b37211a52589166Brian Duddie * @return file descriptor contained in the hidl_handle, or -1 if there is none
6458276308709e5568ba2976e93b37211a52589166Brian Duddie */
6558276308709e5568ba2976e93b37211a52589166Brian Duddieint hidlHandleToFileDescriptor(const hidl_handle& hh) {
6658276308709e5568ba2976e93b37211a52589166Brian Duddie  const native_handle_t *handle = hh.getNativeHandle();
6758276308709e5568ba2976e93b37211a52589166Brian Duddie  return (handle->numFds >= 1) ? handle->data[0] : -1;
6858276308709e5568ba2976e93b37211a52589166Brian Duddie}
6958276308709e5568ba2976e93b37211a52589166Brian Duddie
703d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie}  // anonymous namespace
713d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
72d38c43ca921506be8c6e310ffff5408e03cea848Arthur IshiguroGenericContextHub::DeathRecipient::DeathRecipient(
73d38c43ca921506be8c6e310ffff5408e03cea848Arthur Ishiguro    sp<GenericContextHub> contexthub) : mGenericContextHub(contexthub){}
74d38c43ca921506be8c6e310ffff5408e03cea848Arthur Ishiguro
75d38c43ca921506be8c6e310ffff5408e03cea848Arthur Ishigurovoid GenericContextHub::DeathRecipient::serviceDied(
76d38c43ca921506be8c6e310ffff5408e03cea848Arthur Ishiguro    uint64_t cookie, const wp<::android::hidl::base::V1_0::IBase>& /* who */) {
77d38c43ca921506be8c6e310ffff5408e03cea848Arthur Ishiguro  uint32_t hubId = static_cast<uint32_t>(cookie);
78d38c43ca921506be8c6e310ffff5408e03cea848Arthur Ishiguro  mGenericContextHub->handleServiceDeath(hubId);
79d38c43ca921506be8c6e310ffff5408e03cea848Arthur Ishiguro}
80d38c43ca921506be8c6e310ffff5408e03cea848Arthur Ishiguro
813d891e3fa75ff638c03d5083a47161c044cbfad8Brian DuddieGenericContextHub::GenericContextHub() {
823d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  constexpr char kChreSocketName[] = "chre";
833d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
843d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  mSocketCallbacks = new SocketCallbacks(*this);
853d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  if (!mClient.connectInBackground(kChreSocketName, mSocketCallbacks)) {
863d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    ALOGE("Couldn't start socket client");
873d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  }
88d38c43ca921506be8c6e310ffff5408e03cea848Arthur Ishiguro
89d38c43ca921506be8c6e310ffff5408e03cea848Arthur Ishiguro  mDeathRecipient = new DeathRecipient(this);
903d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie}
913d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
9258276308709e5568ba2976e93b37211a52589166Brian DuddieReturn<void> GenericContextHub::debug(
9358276308709e5568ba2976e93b37211a52589166Brian Duddie    const hidl_handle& hh_fd, const hidl_vec<hidl_string>& /*options*/) {
9458276308709e5568ba2976e93b37211a52589166Brian Duddie  // Timeout inside CHRE is typically 5 seconds, grant 500ms extra here to let
9558276308709e5568ba2976e93b37211a52589166Brian Duddie  // the data reach us
9658276308709e5568ba2976e93b37211a52589166Brian Duddie  constexpr auto kDebugDumpTimeout = std::chrono::milliseconds(5500);
9758276308709e5568ba2976e93b37211a52589166Brian Duddie
9858276308709e5568ba2976e93b37211a52589166Brian Duddie  mDebugFd = hidlHandleToFileDescriptor(hh_fd);
9958276308709e5568ba2976e93b37211a52589166Brian Duddie  if (mDebugFd < 0) {
10058276308709e5568ba2976e93b37211a52589166Brian Duddie    ALOGW("Can't dump debug info to invalid fd");
10158276308709e5568ba2976e93b37211a52589166Brian Duddie  } else {
10258276308709e5568ba2976e93b37211a52589166Brian Duddie    writeToDebugFile("-- Dumping CHRE/ASH debug info --\n");
10358276308709e5568ba2976e93b37211a52589166Brian Duddie
10458276308709e5568ba2976e93b37211a52589166Brian Duddie    ALOGV("Sending debug dump request");
10558276308709e5568ba2976e93b37211a52589166Brian Duddie    FlatBufferBuilder builder;
10658276308709e5568ba2976e93b37211a52589166Brian Duddie    HostProtocolHost::encodeDebugDumpRequest(builder);
10758276308709e5568ba2976e93b37211a52589166Brian Duddie    std::unique_lock<std::mutex> lock(mDebugDumpMutex);
10858276308709e5568ba2976e93b37211a52589166Brian Duddie    mDebugDumpPending = true;
10958276308709e5568ba2976e93b37211a52589166Brian Duddie    if (!mClient.sendMessage(builder.GetBufferPointer(), builder.GetSize())) {
11058276308709e5568ba2976e93b37211a52589166Brian Duddie      ALOGW("Couldn't send debug dump request");
11158276308709e5568ba2976e93b37211a52589166Brian Duddie    } else {
11258276308709e5568ba2976e93b37211a52589166Brian Duddie      mDebugDumpCond.wait_for(lock, kDebugDumpTimeout,
11358276308709e5568ba2976e93b37211a52589166Brian Duddie                              [this]() { return !mDebugDumpPending; });
11458276308709e5568ba2976e93b37211a52589166Brian Duddie      if (mDebugDumpPending) {
11558276308709e5568ba2976e93b37211a52589166Brian Duddie        ALOGI("Timed out waiting on debug dump data");
11658276308709e5568ba2976e93b37211a52589166Brian Duddie        mDebugDumpPending = false;
11758276308709e5568ba2976e93b37211a52589166Brian Duddie      }
11858276308709e5568ba2976e93b37211a52589166Brian Duddie    }
11958276308709e5568ba2976e93b37211a52589166Brian Duddie    writeToDebugFile("\n-- End of CHRE/ASH debug info --\n");
12058276308709e5568ba2976e93b37211a52589166Brian Duddie
12158276308709e5568ba2976e93b37211a52589166Brian Duddie    mDebugFd = kInvalidFd;
12258276308709e5568ba2976e93b37211a52589166Brian Duddie    ALOGV("Debug dump complete");
12358276308709e5568ba2976e93b37211a52589166Brian Duddie  }
12458276308709e5568ba2976e93b37211a52589166Brian Duddie
12558276308709e5568ba2976e93b37211a52589166Brian Duddie  return Void();
12658276308709e5568ba2976e93b37211a52589166Brian Duddie}
12758276308709e5568ba2976e93b37211a52589166Brian Duddie
1283d891e3fa75ff638c03d5083a47161c044cbfad8Brian DuddieReturn<void> GenericContextHub::getHubs(getHubs_cb _hidl_cb) {
1293d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  constexpr auto kHubInfoQueryTimeout = std::chrono::seconds(5);
1303d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  std::vector<ContextHub> hubs;
1313d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  ALOGV("%s", __func__);
1323d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
1333d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  // If we're not connected yet, give it some time
13488b885ff8b460d3b17053aae954a13720237a9b7Wei Wang  // TODO refactor from polling into conditional wait
13588b885ff8b460d3b17053aae954a13720237a9b7Wei Wang  int maxSleepIterations = 250;
1363d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  while (!mHubInfoValid && !mClient.isConnected() && --maxSleepIterations > 0) {
13788b885ff8b460d3b17053aae954a13720237a9b7Wei Wang    std::this_thread::sleep_for(std::chrono::milliseconds(20));
1383d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  }
1393d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
1403d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  if (!mClient.isConnected()) {
1413d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    ALOGE("Couldn't connect to hub daemon");
1423d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  } else if (!mHubInfoValid) {
1433d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    // We haven't cached the hub details yet, so send a request and block
1443d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    // waiting on a response
1453d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    std::unique_lock<std::mutex> lock(mHubInfoMutex);
1463d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    FlatBufferBuilder builder;
1473d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    HostProtocolHost::encodeHubInfoRequest(builder);
1483d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
1493d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    ALOGD("Sending hub info request");
1503d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    if (!mClient.sendMessage(builder.GetBufferPointer(), builder.GetSize())) {
1513d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie      ALOGE("Couldn't send hub info request");
1523d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    } else {
1533d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie      mHubInfoCond.wait_for(lock, kHubInfoQueryTimeout,
1543d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie                            [this]() { return mHubInfoValid; });
1553d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    }
1563d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  }
1573d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
1583d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  if (mHubInfoValid) {
1593d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    hubs.push_back(mHubInfo);
1603d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  } else {
1613d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    ALOGE("Unable to get hub info from CHRE");
1623d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  }
1633d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
1643d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  _hidl_cb(hubs);
1653d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  return Void();
1663d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie}
1673d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
1683d891e3fa75ff638c03d5083a47161c044cbfad8Brian DuddieReturn<Result> GenericContextHub::registerCallback(
1693d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    uint32_t hubId, const sp<IContexthubCallback>& cb) {
1703d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  Result result;
1713d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  ALOGV("%s", __func__);
1723d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
1733d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  // TODO: currently we only support 1 hub behind this HAL implementation
1743d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  if (hubId == kDefaultHubId) {
1756c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie    std::lock_guard<std::mutex> lock(mCallbacksLock);
176d38c43ca921506be8c6e310ffff5408e03cea848Arthur Ishiguro
177d38c43ca921506be8c6e310ffff5408e03cea848Arthur Ishiguro    if (cb != nullptr) {
178d38c43ca921506be8c6e310ffff5408e03cea848Arthur Ishiguro      if (mCallbacks != nullptr) {
179d38c43ca921506be8c6e310ffff5408e03cea848Arthur Ishiguro        ALOGD("Modifying callback for hubId %" PRIu32, hubId);
180d38c43ca921506be8c6e310ffff5408e03cea848Arthur Ishiguro        mCallbacks->unlinkToDeath(mDeathRecipient);
181d38c43ca921506be8c6e310ffff5408e03cea848Arthur Ishiguro      }
182d38c43ca921506be8c6e310ffff5408e03cea848Arthur Ishiguro      Return<bool> linkReturn = cb->linkToDeath(mDeathRecipient, hubId);
183d38c43ca921506be8c6e310ffff5408e03cea848Arthur Ishiguro      if (!linkReturn.withDefault(false)) {
184d38c43ca921506be8c6e310ffff5408e03cea848Arthur Ishiguro        ALOGW("Could not link death recipient to hubId %" PRIu32, hubId);
185d38c43ca921506be8c6e310ffff5408e03cea848Arthur Ishiguro      }
186d38c43ca921506be8c6e310ffff5408e03cea848Arthur Ishiguro    }
187d38c43ca921506be8c6e310ffff5408e03cea848Arthur Ishiguro
1886c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie    mCallbacks = cb;
1893d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    result = Result::OK;
1903d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  } else {
1913d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    result = Result::BAD_PARAMS;
1923d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  }
1933d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
1943d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  return result;
1953d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie}
1963d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
1973d891e3fa75ff638c03d5083a47161c044cbfad8Brian DuddieReturn<Result> GenericContextHub::sendMessageToHub(uint32_t hubId,
1983d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie                                                   const ContextHubMsg& msg) {
1993d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  Result result;
2003d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  ALOGV("%s", __func__);
2013d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
2023d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  if (hubId != kDefaultHubId) {
2033d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    result = Result::BAD_PARAMS;
2043d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  } else {
2053d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    FlatBufferBuilder builder(1024);
2063d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    HostProtocolHost::encodeNanoappMessage(
2073d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie        builder, msg.appName, msg.msgType, msg.hostEndPoint, msg.msg.data(),
2083d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie        msg.msg.size());
2093d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
2103d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    if (!mClient.sendMessage(builder.GetBufferPointer(), builder.GetSize())) {
2113d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie      result = Result::UNKNOWN_FAILURE;
2123d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    } else {
2133d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie      result = Result::OK;
2143d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    }
2153d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  }
2163d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
2173d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  return result;
2183d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie}
2193d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
2203d891e3fa75ff638c03d5083a47161c044cbfad8Brian DuddieReturn<Result> GenericContextHub::loadNanoApp(
2213d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    uint32_t hubId, const NanoAppBinary& appBinary, uint32_t transactionId) {
22247a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie  Result result;
2233d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  ALOGV("%s", __func__);
22447a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie
22547a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie  if (hubId != kDefaultHubId) {
22647a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie    result = Result::BAD_PARAMS;
22747a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie  } else {
22847a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie    FlatBufferBuilder builder(128 + appBinary.customBinary.size());
22947a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie    uint32_t targetApiVersion = (appBinary.targetChreApiMajorVersion << 24) |
23047a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie                                (appBinary.targetChreApiMinorVersion << 16);
23147a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie    HostProtocolHost::encodeLoadNanoappRequest(
23247a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie        builder, transactionId, appBinary.appId, appBinary.appVersion,
23347a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie        targetApiVersion, appBinary.customBinary);
23447a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie    if (!mClient.sendMessage(builder.GetBufferPointer(), builder.GetSize())) {
23547a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie      result = Result::UNKNOWN_FAILURE;
23647a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie    } else {
23747a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie      result = Result::OK;
23847a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie    }
23947a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie  }
24047a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie
24147a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie  ALOGD("Attempted to send load nanoapp request for app of size %zu with ID "
24247a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie        "0x%016" PRIx64 " as transaction ID %" PRIu32 ": result %" PRIu32,
24347a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie        appBinary.customBinary.size(), appBinary.appId, transactionId, result);
24447a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie
24547a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie  return result;
2463d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie}
2473d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
2483d891e3fa75ff638c03d5083a47161c044cbfad8Brian DuddieReturn<Result> GenericContextHub::unloadNanoApp(
2493d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    uint32_t hubId, uint64_t appId, uint32_t transactionId) {
25099f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie  Result result;
2513d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  ALOGV("%s", __func__);
25299f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie
25399f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie  if (hubId != kDefaultHubId) {
25499f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie    result = Result::BAD_PARAMS;
25599f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie  } else {
25699f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie    FlatBufferBuilder builder(64);
25799f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie    HostProtocolHost::encodeUnloadNanoappRequest(
25899f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie        builder, transactionId, appId, false /* allowSystemNanoappUnload */);
25999f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie    if (!mClient.sendMessage(builder.GetBufferPointer(), builder.GetSize())) {
26099f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie      result = Result::UNKNOWN_FAILURE;
26199f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie    } else {
26299f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie      result = Result::OK;
26399f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie    }
26499f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie  }
26599f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie
26699f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie  ALOGD("Attempted to send unload nanoapp request for app ID 0x%016" PRIx64
26799f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie        " as transaction ID %" PRIu32 ": result %" PRIu32, appId, transactionId,
26899f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie        result);
26999f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie
27099f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie  return result;
2713d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie}
2723d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
2733d891e3fa75ff638c03d5083a47161c044cbfad8Brian DuddieReturn<Result> GenericContextHub::enableNanoApp(
27499f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie    uint32_t /* hubId */, uint64_t appId, uint32_t /* transactionId */) {
2753d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  // TODO
27699f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie  ALOGW("Attempted to enable app ID 0x%016" PRIx64 ", but not supported",
27799f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie        appId);
2786c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie  return Result::TRANSACTION_FAILED;
2793d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie}
2803d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
2813d891e3fa75ff638c03d5083a47161c044cbfad8Brian DuddieReturn<Result> GenericContextHub::disableNanoApp(
28299f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie    uint32_t /* hubId */, uint64_t appId, uint32_t /* transactionId */) {
2833d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  // TODO
28499f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie  ALOGW("Attempted to disable app ID 0x%016" PRIx64 ", but not supported",
28599f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie        appId);
2866c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie  return Result::TRANSACTION_FAILED;
2873d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie}
2883d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
2893d891e3fa75ff638c03d5083a47161c044cbfad8Brian DuddieReturn<Result> GenericContextHub::queryApps(uint32_t hubId) {
29047a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie  Result result;
2913d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  ALOGV("%s", __func__);
29247a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie
29347a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie  if (hubId != kDefaultHubId) {
29447a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie    result = Result::BAD_PARAMS;
29547a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie  } else {
29647a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie    FlatBufferBuilder builder(64);
29747a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie    HostProtocolHost::encodeNanoappListRequest(builder);
29847a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie    if (!mClient.sendMessage(builder.GetBufferPointer(), builder.GetSize())) {
29947a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie      result = Result::UNKNOWN_FAILURE;
30047a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie    } else {
30147a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie      result = Result::OK;
30247a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie    }
30347a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie  }
30447a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie
3056c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie  return result;
3063d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie}
3073d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
3083d891e3fa75ff638c03d5083a47161c044cbfad8Brian DuddieGenericContextHub::SocketCallbacks::SocketCallbacks(GenericContextHub& parent)
3093d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    : mParent(parent) {}
3103d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
3113d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddievoid GenericContextHub::SocketCallbacks::onMessageReceived(const void *data,
3123d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie                                                           size_t length) {
3133d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  if (!HostProtocolHost::decodeMessageFromChre(data, length, *this)) {
3143d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    ALOGE("Failed to decode message");
3153d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  }
3163d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie}
3173d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
318a413add0b3504b1e8576235cea52b6738829feccBrian Duddievoid GenericContextHub::SocketCallbacks::onConnected() {
319a413add0b3504b1e8576235cea52b6738829feccBrian Duddie  if (mHaveConnected) {
320a413add0b3504b1e8576235cea52b6738829feccBrian Duddie    ALOGI("Reconnected to CHRE daemon");
3216c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie    invokeClientCallback([&]() {
322a413add0b3504b1e8576235cea52b6738829feccBrian Duddie      mParent.mCallbacks->handleHubEvent(AsyncEventType::RESTARTED);
3236c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie    });
324a413add0b3504b1e8576235cea52b6738829feccBrian Duddie  }
325a413add0b3504b1e8576235cea52b6738829feccBrian Duddie  mHaveConnected = true;
326a413add0b3504b1e8576235cea52b6738829feccBrian Duddie}
327a413add0b3504b1e8576235cea52b6738829feccBrian Duddie
328a413add0b3504b1e8576235cea52b6738829feccBrian Duddievoid GenericContextHub::SocketCallbacks::onDisconnected() {
329a413add0b3504b1e8576235cea52b6738829feccBrian Duddie  ALOGW("Lost connection to CHRE daemon");
330a413add0b3504b1e8576235cea52b6738829feccBrian Duddie}
331a413add0b3504b1e8576235cea52b6738829feccBrian Duddie
3323d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddievoid GenericContextHub::SocketCallbacks::handleNanoappMessage(
3333d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    uint64_t appId, uint32_t messageType, uint16_t hostEndpoint,
3343d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    const void *messageData, size_t messageDataLen) {
3356c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie  ContextHubMsg msg;
3366c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie  msg.appName = appId;
3376c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie  msg.hostEndPoint = hostEndpoint;
3386c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie  msg.msgType = messageType;
3396c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie
3406c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie  // Dropping const from messageData when we wrap it in hidl_vec here. This is
3416c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie  // safe because we won't modify it here, and the ContextHubMsg we pass to
3426c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie  // the callback is const.
3436c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie  msg.msg.setToExternal(
3446c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie      const_cast<uint8_t *>(static_cast<const uint8_t *>(messageData)),
3456c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie      messageDataLen, false /* shouldOwn */);
3466c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie  invokeClientCallback([&]() {
3473d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    mParent.mCallbacks->handleClientMsg(msg);
3486c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie  });
3493d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie}
3503d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
3513d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddievoid GenericContextHub::SocketCallbacks::handleHubInfoResponse(
3523d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    const char *name, const char *vendor,
3533d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    const char *toolchain, uint32_t legacyPlatformVersion,
3543d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    uint32_t legacyToolchainVersion, float peakMips, float stoppedPower,
3553d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    float sleepPower, float peakPower, uint32_t maxMessageLen,
3563d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    uint64_t platformId, uint32_t version) {
3573d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  ALOGD("Got hub info response");
3583d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
3593d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  std::lock_guard<std::mutex> lock(mParent.mHubInfoMutex);
3603d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  if (mParent.mHubInfoValid) {
3613d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    ALOGI("Ignoring duplicate/unsolicited hub info response");
3623d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  } else {
3633d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    mParent.mHubInfo.name = name;
3643d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    mParent.mHubInfo.vendor = vendor;
3653d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    mParent.mHubInfo.toolchain = toolchain;
3663d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    mParent.mHubInfo.platformVersion = legacyPlatformVersion;
3673d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    mParent.mHubInfo.toolchainVersion = legacyToolchainVersion;
3683d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    mParent.mHubInfo.hubId = kDefaultHubId;
3693d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
3703d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    mParent.mHubInfo.peakMips = peakMips;
3713d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    mParent.mHubInfo.stoppedPowerDrawMw = stoppedPower;
3723d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    mParent.mHubInfo.sleepPowerDrawMw = sleepPower;
3733d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    mParent.mHubInfo.peakPowerDrawMw = peakPower;
3743d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
3753d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    mParent.mHubInfo.maxSupportedMsgLen = maxMessageLen;
3763d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    mParent.mHubInfo.chrePlatformId = platformId;
3773d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
3783d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    mParent.mHubInfo.chreApiMajorVersion = extractChreApiMajorVersion(version);
3793d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    mParent.mHubInfo.chreApiMinorVersion = extractChreApiMinorVersion(version);
3803d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    mParent.mHubInfo.chrePatchVersion = extractChrePatchVersion(version);
3813d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
3823d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    mParent.mHubInfoValid = true;
3833d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie    mParent.mHubInfoCond.notify_all();
3843d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  }
3853d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie}
3863d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
387a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddievoid GenericContextHub::SocketCallbacks::handleNanoappListResponse(
38807da7d6425058577d477074f99bafd4b8e81bb83Brian Duddie    const fbs::NanoappListResponseT& response) {
389a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie  std::vector<HubAppInfo> appInfoList;
390a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie
39107da7d6425058577d477074f99bafd4b8e81bb83Brian Duddie  ALOGV("Got nanoapp list response with %zu apps", response.nanoapps.size());
39207da7d6425058577d477074f99bafd4b8e81bb83Brian Duddie  for (const std::unique_ptr<fbs::NanoappListEntryT>& nanoapp
39307da7d6425058577d477074f99bafd4b8e81bb83Brian Duddie         : response.nanoapps) {
39407da7d6425058577d477074f99bafd4b8e81bb83Brian Duddie    // TODO: determine if this is really required, and if so, have
39507da7d6425058577d477074f99bafd4b8e81bb83Brian Duddie    // HostProtocolHost strip out null entries as part of decode
39607da7d6425058577d477074f99bafd4b8e81bb83Brian Duddie    if (nanoapp == nullptr) {
39707da7d6425058577d477074f99bafd4b8e81bb83Brian Duddie      continue;
39807da7d6425058577d477074f99bafd4b8e81bb83Brian Duddie    }
39907da7d6425058577d477074f99bafd4b8e81bb83Brian Duddie
400a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie    ALOGV("App 0x%016" PRIx64 " ver 0x%" PRIx32 " enabled %d system %d",
40107da7d6425058577d477074f99bafd4b8e81bb83Brian Duddie          nanoapp->app_id, nanoapp->version, nanoapp->enabled,
40207da7d6425058577d477074f99bafd4b8e81bb83Brian Duddie          nanoapp->is_system);
40307da7d6425058577d477074f99bafd4b8e81bb83Brian Duddie    if (!nanoapp->is_system) {
404a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie      HubAppInfo appInfo;
405a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie
40607da7d6425058577d477074f99bafd4b8e81bb83Brian Duddie      appInfo.appId = nanoapp->app_id;
40707da7d6425058577d477074f99bafd4b8e81bb83Brian Duddie      appInfo.version = nanoapp->version;
40807da7d6425058577d477074f99bafd4b8e81bb83Brian Duddie      appInfo.enabled = nanoapp->enabled;
409a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie
410a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie      appInfoList.push_back(appInfo);
411a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie    }
412a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie  }
413a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie
4146c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie  invokeClientCallback([&]() {
4156c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie    mParent.mCallbacks->handleAppsInfo(appInfoList);
4166c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie  });
417a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie}
418a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie
41947a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddievoid GenericContextHub::SocketCallbacks::handleLoadNanoappResponse(
42047a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie    const ::chre::fbs::LoadNanoappResponseT& response) {
42147a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie  ALOGV("Got load nanoapp response for transaction %" PRIu32 " with result %d",
42247a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie        response.transaction_id, response.success);
42347a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie
4246c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie  invokeClientCallback([&]() {
4256c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie    TransactionResult result = (response.success) ?
4266c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie        TransactionResult::SUCCESS : TransactionResult::FAILURE;
4276c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie    mParent.mCallbacks->handleTxnResult(response.transaction_id, result);
4286c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie  });
42947a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie}
43047a99dc3cacacb0418548609c0e2d3b2b70d821eBrian Duddie
43199f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddievoid GenericContextHub::SocketCallbacks::handleUnloadNanoappResponse(
43299f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie    const ::chre::fbs::UnloadNanoappResponseT& response) {
43399f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie  ALOGV("Got unload nanoapp response for transaction %" PRIu32 " with result "
43499f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie        "%d", response.transaction_id, response.success);
43599f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie
43699f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie  invokeClientCallback([&]() {
43799f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie    TransactionResult result = (response.success) ?
43899f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie        TransactionResult::SUCCESS : TransactionResult::FAILURE;
43999f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie    mParent.mCallbacks->handleTxnResult(response.transaction_id, result);
44099f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie  });
44199f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie}
44299f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie
44358276308709e5568ba2976e93b37211a52589166Brian Duddievoid GenericContextHub::SocketCallbacks::handleDebugDumpData(
44458276308709e5568ba2976e93b37211a52589166Brian Duddie    const ::chre::fbs::DebugDumpDataT& data) {
44558276308709e5568ba2976e93b37211a52589166Brian Duddie  ALOGV("Got debug dump data, size %zu", data.debug_str.size());
44658276308709e5568ba2976e93b37211a52589166Brian Duddie  if (mParent.mDebugFd == kInvalidFd) {
44758276308709e5568ba2976e93b37211a52589166Brian Duddie    ALOGW("Got unexpected debug dump data message");
44858276308709e5568ba2976e93b37211a52589166Brian Duddie  } else {
44958276308709e5568ba2976e93b37211a52589166Brian Duddie    mParent.writeToDebugFile(
45058276308709e5568ba2976e93b37211a52589166Brian Duddie        reinterpret_cast<const char *>(data.debug_str.data()),
45158276308709e5568ba2976e93b37211a52589166Brian Duddie        data.debug_str.size());
45258276308709e5568ba2976e93b37211a52589166Brian Duddie  }
45358276308709e5568ba2976e93b37211a52589166Brian Duddie}
45458276308709e5568ba2976e93b37211a52589166Brian Duddie
45558276308709e5568ba2976e93b37211a52589166Brian Duddievoid GenericContextHub::SocketCallbacks::handleDebugDumpResponse(
45658276308709e5568ba2976e93b37211a52589166Brian Duddie    const ::chre::fbs::DebugDumpResponseT& response) {
45758276308709e5568ba2976e93b37211a52589166Brian Duddie  ALOGV("Got debug dump response, success %d, data count %" PRIu32,
45858276308709e5568ba2976e93b37211a52589166Brian Duddie        response.success, response.data_count);
45958276308709e5568ba2976e93b37211a52589166Brian Duddie  std::lock_guard<std::mutex> lock(mParent.mDebugDumpMutex);
46058276308709e5568ba2976e93b37211a52589166Brian Duddie  if (!mParent.mDebugDumpPending) {
46158276308709e5568ba2976e93b37211a52589166Brian Duddie    ALOGI("Ignoring duplicate/unsolicited debug dump response");
46258276308709e5568ba2976e93b37211a52589166Brian Duddie  } else {
46358276308709e5568ba2976e93b37211a52589166Brian Duddie    mParent.mDebugDumpPending = false;
46458276308709e5568ba2976e93b37211a52589166Brian Duddie    mParent.mDebugDumpCond.notify_all();
46558276308709e5568ba2976e93b37211a52589166Brian Duddie  }
46658276308709e5568ba2976e93b37211a52589166Brian Duddie}
46758276308709e5568ba2976e93b37211a52589166Brian Duddie
4686c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddievoid GenericContextHub::SocketCallbacks::invokeClientCallback(
4696c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie    std::function<void()> callback) {
4706c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie  std::lock_guard<std::mutex> lock(mParent.mCallbacksLock);
4716c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie  if (mParent.mCallbacks != nullptr) {
4726c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie    callback();
4736c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie  }
4746c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie}
4756c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie
47658276308709e5568ba2976e93b37211a52589166Brian Duddievoid GenericContextHub::writeToDebugFile(const char *str) {
47758276308709e5568ba2976e93b37211a52589166Brian Duddie  writeToDebugFile(str, strlen(str));
47858276308709e5568ba2976e93b37211a52589166Brian Duddie}
47958276308709e5568ba2976e93b37211a52589166Brian Duddie
48058276308709e5568ba2976e93b37211a52589166Brian Duddievoid GenericContextHub::writeToDebugFile(const char *str, size_t len) {
48158276308709e5568ba2976e93b37211a52589166Brian Duddie  ssize_t written = write(mDebugFd, str, len);
48258276308709e5568ba2976e93b37211a52589166Brian Duddie  if (written != (ssize_t) len) {
48358276308709e5568ba2976e93b37211a52589166Brian Duddie    ALOGW("Couldn't write to debug header: returned %zd, expected %zu "
48458276308709e5568ba2976e93b37211a52589166Brian Duddie          "(errno %d)", written, len, errno);
48558276308709e5568ba2976e93b37211a52589166Brian Duddie  }
48658276308709e5568ba2976e93b37211a52589166Brian Duddie}
48758276308709e5568ba2976e93b37211a52589166Brian Duddie
488d38c43ca921506be8c6e310ffff5408e03cea848Arthur Ishigurovoid GenericContextHub::handleServiceDeath(uint32_t hubId) {
489d38c43ca921506be8c6e310ffff5408e03cea848Arthur Ishiguro  std::lock_guard<std::mutex> lock(mCallbacksLock);
490d38c43ca921506be8c6e310ffff5408e03cea848Arthur Ishiguro  ALOGI("Context hub service died for hubId %" PRIu32, hubId);
491d38c43ca921506be8c6e310ffff5408e03cea848Arthur Ishiguro  mCallbacks.clear();
492d38c43ca921506be8c6e310ffff5408e03cea848Arthur Ishiguro}
4936c90e539c79a443c18adbf9f77238b3828ac2bf4Brian Duddie
4943d891e3fa75ff638c03d5083a47161c044cbfad8Brian DuddieIContexthub* HIDL_FETCH_IContexthub(const char* /* name */) {
4953d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie  return new GenericContextHub();
4963d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie}
4973d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie
4983d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie}  // namespace implementation
4993d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie}  // namespace V1_0
5003d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie}  // namespace contexthub
5013d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie}  // namespace hardware
5023d891e3fa75ff638c03d5083a47161c044cbfad8Brian Duddie}  // namespace android
503