1e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie/*
2e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * Copyright (C) 2016 The Android Open Source Project
3e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie *
4e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * Licensed under the Apache License, Version 2.0 (the "License");
5e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * you may not use this file except in compliance with the License.
6e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * You may obtain a copy of the License at
7e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie *
8e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie *      http://www.apache.org/licenses/LICENSE-2.0
9e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie *
10e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * Unless required by applicable law or agreed to in writing, software
11e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * distributed under the License is distributed on an "AS IS" BASIS,
12e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * See the License for the specific language governing permissions and
14e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * limitations under the License.
15e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie */
16e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie
17e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie#include "chre/platform/platform_nanoapp.h"
18e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie
19fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol#include <cinttypes>
20fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol#include <dlfcn.h>
21fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol
22fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol#include "chre_api/chre/version.h"
23fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol#include "chre/platform/assert.h"
24fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol#include "chre/platform/log.h"
25fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol#include "chre/platform/shared/nanoapp_dso_util.h"
26fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol
27e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddienamespace chre {
28e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie
29fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew RossignolPlatformNanoapp::~PlatformNanoapp() {
30fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol  closeNanoapp();
31fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol}
329d5b500a223ef73560f0dce38f50b809bde5dd0dBrian Duddie
33e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddiebool PlatformNanoapp::start() {
34fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol  return openNanoapp() && mAppInfo->entryPoints.start();
35e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie}
36e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie
37e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddievoid PlatformNanoapp::handleEvent(uint32_t senderInstanceId,
38e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie                                  uint16_t eventType,
39e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie                                  const void *eventData) {
40fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol  mAppInfo->entryPoints.handleEvent(senderInstanceId, eventType, eventData);
41e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie}
42e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie
432b9d71a9f6a9e8cc0e787957d022154231f29962Brian Duddievoid PlatformNanoapp::end() {
44fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol  mAppInfo->entryPoints.end();
45fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol  closeNanoapp();
46e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie}
47e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie
489d5b500a223ef73560f0dce38f50b809bde5dd0dBrian Duddieuint64_t PlatformNanoapp::getAppId() const {
491a436aa2739b13c4f5625fa1fca75c7a964068adAndrew Rossignol  return (mAppInfo == nullptr) ? 0 : mAppInfo->appId;
509d5b500a223ef73560f0dce38f50b809bde5dd0dBrian Duddie}
519d5b500a223ef73560f0dce38f50b809bde5dd0dBrian Duddie
529d5b500a223ef73560f0dce38f50b809bde5dd0dBrian Duddieuint32_t PlatformNanoapp::getAppVersion() const {
53fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol  return mAppInfo->appVersion;
549d5b500a223ef73560f0dce38f50b809bde5dd0dBrian Duddie}
559d5b500a223ef73560f0dce38f50b809bde5dd0dBrian Duddie
569d5b500a223ef73560f0dce38f50b809bde5dd0dBrian Duddieuint32_t PlatformNanoapp::getTargetApiVersion() const {
579d5b500a223ef73560f0dce38f50b809bde5dd0dBrian Duddie  return CHRE_API_VERSION;
589d5b500a223ef73560f0dce38f50b809bde5dd0dBrian Duddie}
599d5b500a223ef73560f0dce38f50b809bde5dd0dBrian Duddie
609d5b500a223ef73560f0dce38f50b809bde5dd0dBrian Duddiebool PlatformNanoapp::isSystemNanoapp() const {
611a436aa2739b13c4f5625fa1fca75c7a964068adAndrew Rossignol  return (mAppInfo != nullptr && mAppInfo->isSystemNanoapp);
629d5b500a223ef73560f0dce38f50b809bde5dd0dBrian Duddie}
639d5b500a223ef73560f0dce38f50b809bde5dd0dBrian Duddie
64d0530f420d8bdaee755ec2834af407424de195e0Arthur Ishigurobool PlatformNanoapp::logStateToBuffer(char *buffer, size_t *bufferPos,
65d0530f420d8bdaee755ec2834af407424de195e0Arthur Ishiguro                                       size_t bufferSize) const {
66d0530f420d8bdaee755ec2834af407424de195e0Arthur Ishiguro  return true;
67d0530f420d8bdaee755ec2834af407424de195e0Arthur Ishiguro}
68d0530f420d8bdaee755ec2834af407424de195e0Arthur Ishiguro
69fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignolvoid PlatformNanoappBase::loadFromFile(const std::string& filename) {
70fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol  CHRE_ASSERT(!isLoaded());
71fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol  mFilename = filename;
72fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol}
73fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol
74fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignolvoid PlatformNanoappBase::loadStatic(const struct chreNslNanoappInfo *appInfo) {
75fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol  CHRE_ASSERT(!isLoaded());
76fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol  mIsStatic = true;
77fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol  mAppInfo = appInfo;
78fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol}
79fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol
80fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignolbool PlatformNanoappBase::isLoaded() const {
81fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol  return (mIsStatic || mDsoHandle != nullptr);
82fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol}
83fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol
84fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignolbool PlatformNanoappBase::openNanoapp() {
85fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol  bool success = false;
86fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol
87fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol  if (mIsStatic) {
88fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol    success = true;
89fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol  } else if (!mFilename.empty()) {
90fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol    success = openNanoappFromFile();
91fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol  } else {
92fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol    CHRE_ASSERT(false);
93fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol  }
94fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol
95fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol  return success;
96fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol}
97fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol
98fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignolbool PlatformNanoappBase::openNanoappFromFile() {
99fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol  CHRE_ASSERT(!mFilename.empty());
100fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol  CHRE_ASSERT_LOG(mDsoHandle == nullptr, "Re-opening nanoapp");
101fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol  bool success = false;
102fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol
103fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol  mDsoHandle = dlopen(mFilename.c_str(), RTLD_NOW | RTLD_GLOBAL);
104fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol  if (mDsoHandle == nullptr) {
105fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol    LOGE("Failed to load nanoapp from file %s: %s",
106fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol         mFilename.c_str(), dlerror());
107fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol  } else {
108fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol    mAppInfo = static_cast<const struct chreNslNanoappInfo *>(
109fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol        dlsym(mDsoHandle, CHRE_NSL_DSO_NANOAPP_INFO_SYMBOL_NAME));
110fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol    if (mAppInfo == nullptr) {
111fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol      LOGE("Failed to find app info symbol in %s: %s",
112fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol           mFilename.c_str(), dlerror());
113fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol    } else {
114fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol      success = validateAppInfo(0 /* skip ID validation */, 0, mAppInfo,
115fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol                                true /* ignoreAppVersion */);
116fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol      if (!success) {
117fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol        mAppInfo = nullptr;
118fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol      } else {
119fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol        LOGI("Successfully loaded nanoapp %s (0x%016" PRIx64 ") version 0x%"
120fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol             PRIx32 " uimg %d system %d from file %s", mAppInfo->name,
121fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol             mAppInfo->appId, mAppInfo->appVersion, mAppInfo->isTcmNanoapp,
122fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol             mAppInfo->isSystemNanoapp, mFilename.c_str());
123fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol      }
124fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol    }
125fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol  }
126fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol
127fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol  return success;
128fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol}
129fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol
130fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignolvoid PlatformNanoappBase::closeNanoapp() {
131fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol  if (mDsoHandle != nullptr) {
132fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol    if (dlclose(mDsoHandle) != 0) {
133fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol      LOGE("dlclose failed: %s", dlerror());
134fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol    }
135fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol    mDsoHandle = nullptr;
136fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol  }
137fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol}
138fc4d354a2ad34172f508a9017b49747b9193eaf8Andrew Rossignol
139e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie}  // namespace chre
140