17464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne/* 27464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne * Copyright (C) 2017 The Android Open Source Project 37464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne * 47464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne * Licensed under the Apache License, Version 2.0 (the "License"); 57464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne * you may not use this file except in compliance with the License. 67464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne * You may obtain a copy of the License at 77464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne * 87464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne * http://www.apache.org/licenses/LICENSE-2.0 97464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne * 107464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne * Unless required by applicable law or agreed to in writing, software 117464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne * distributed under the License is distributed on an "AS IS" BASIS, 127464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne * See the License for the specific language governing permissions and 147464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne * limitations under the License. 157464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne */ 167464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne 177464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne#include "BootAction.h" 187464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne 197464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne#define LOG_TAG "BootAction" 207464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne 217464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne#include <android-base/strings.h> 227464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne#include <cpu-features.h> 237464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne#include <dlfcn.h> 247464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne#include <pio/peripheral_manager_client.h> 257464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne#include <utils/Log.h> 267464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne 277464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyneusing android::base::Split; 287464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyneusing android::base::Join; 297464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyneusing android::base::StartsWith; 307464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyneusing android::base::EndsWith; 317464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne 327464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coynenamespace android { 337464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne 347464ac9bd7fe89061e47617e4b6004b88c91d636Ed CoyneBootAction::~BootAction() { 357464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne if (mLibHandle != nullptr) { 367464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne dlclose(mLibHandle); 377464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne } 387464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne} 397464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne 407464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coynebool BootAction::init(const std::string& libraryPath, const std::string& config) { 417464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne APeripheralManagerClient* client = nullptr; 427464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne ALOGD("Connecting to peripheralmanager"); 437464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne // Wait for peripheral manager to come up. 447464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne while (client == nullptr) { 457464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne client = APeripheralManagerClient_new(); 467464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne if (client == nullptr) { 477464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne ALOGV("peripheralmanager is not up, sleeping before we check again."); 487464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne usleep(250000); 497464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne } 507464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne } 517464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne ALOGD("Peripheralmanager is up."); 527464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne APeripheralManagerClient_delete(client); 537464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne 547464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne std::string path_to_lib = libraryPath; 557464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne if (!parseConfig(config, &path_to_lib)) { 567464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne return false; 577464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne } 587464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne 597464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne ALOGI("Loading boot action %s", path_to_lib.c_str()); 607464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne mLibHandle = dlopen(path_to_lib.c_str(), RTLD_NOW); 617464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne if (mLibHandle == nullptr) { 627464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne ALOGE("Unable to load library at %s :: %s", 637464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne path_to_lib.c_str(), dlerror()); 647464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne return false; 657464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne } 667464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne 677464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne void* loaded = nullptr; 687464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne if (!loadSymbol("boot_action_init", &loaded) || loaded == nullptr) { 697464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne return false; 707464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne } 717464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne mLibInit = reinterpret_cast<libInit>(loaded); 727464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne 737464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne loaded = nullptr; 747464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne if (!loadSymbol("boot_action_shutdown", &loaded) || loaded == nullptr) { 757464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne return false; 767464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne } 777464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne mLibShutdown = reinterpret_cast<libShutdown>(loaded); 787464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne 797464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne // StartPart is considered optional, if it isn't exported by the library 807464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne // we will still call init and shutdown. 817464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne loaded = nullptr; 827464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne if (!loadSymbol("boot_action_start_part", &loaded) || loaded == nullptr) { 837464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne ALOGI("No boot_action_start_part found, action will not be told when " 847464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne "Animation parts change."); 857464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne } else { 867464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne mLibStartPart = reinterpret_cast<libStartPart>(loaded); 877464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne } 887464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne 897464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne ALOGD("Entering boot_action_init"); 907464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne bool result = mLibInit(); 917464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne ALOGD("Returned from boot_action_init"); 927464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne return result; 937464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne} 947464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne 957464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coynevoid BootAction::startPart(int partNumber, int playNumber) { 967464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne if (mLibStartPart == nullptr) return; 977464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne 987464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne ALOGD("Entering boot_action_start_part"); 997464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne mLibStartPart(partNumber, playNumber); 1007464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne ALOGD("Returned from boot_action_start_part"); 1017464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne} 1027464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne 1037464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coynevoid BootAction::shutdown() { 1047464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne ALOGD("Entering boot_action_shutdown"); 1057464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne mLibShutdown(); 1067464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne ALOGD("Returned from boot_action_shutdown"); 1077464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne} 1087464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne 1097464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coynebool BootAction::loadSymbol(const char* symbol, void** loaded) { 1107464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne *loaded = dlsym(mLibHandle, symbol); 1117464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne if (loaded == nullptr) { 1127464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne ALOGE("Unable to load symbol : %s :: %s", symbol, dlerror()); 1137464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne return false; 1147464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne } 1157464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne return true; 1167464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne} 1177464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne 1187464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne 1197464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coynebool BootAction::parseConfig(const std::string& config, std::string* path) { 1207464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne auto lines = Split(config, "\n"); 1217464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne 1227464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne if (lines.size() < 1) { 1237464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne ALOGE("Config format invalid, expected one line, found %d", 1247464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne lines.size()); 1257464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne return false; 1267464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne } 1277464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne 1287464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne size_t lineNumber = 0; 1297464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne auto& line1 = lines.at(lineNumber); 1307464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne while (StartsWith(line1, "#")) { 1317464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne if (lines.size() < ++lineNumber) { 1327464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne ALOGE("Config file contains no non-comment lines."); 1337464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne return false; 1347464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne } 1357464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne line1 = lines.at(lineNumber); 1367464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne } 1377464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne 1387464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne const std::string libraryNameToken("LIBRARY_NAME="); 1397464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne if (!StartsWith(line1, libraryNameToken.c_str())) { 1407464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne ALOGE("Invalid config format, expected second line to start with %s " 1417464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne "Instead found: %s", libraryNameToken.c_str(), line1.c_str()); 1427464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne return false; 1437464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne } 1447464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne 1457464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne std::string libraryName = line1.substr(libraryNameToken.length()); 1467464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne 1477464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne *path += "/"; 1487464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne *path += architectureDirectory(); 1497464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne *path += "/"; 1507464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne *path += libraryName; 1517464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne 1527464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne return true; 1537464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne} 1547464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne 1557464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyneconst char* BootAction::architectureDirectory() { 1567464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne switch(android_getCpuFamily()) { 1577464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne case ANDROID_CPU_FAMILY_ARM: 1587464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne return "arm"; 1597464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne case ANDROID_CPU_FAMILY_X86: 1607464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne return "x86"; 1617464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne case ANDROID_CPU_FAMILY_MIPS: 1627464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne return "mips"; 1637464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne case ANDROID_CPU_FAMILY_ARM64: 1647464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne return "arm64"; 1657464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne case ANDROID_CPU_FAMILY_X86_64: 1667464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne return "x86_64"; 1677464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne case ANDROID_CPU_FAMILY_MIPS64: 1687464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne return "mips64"; 1697464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne default: 1707464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne ALOGE("Unsupported cpu family: %d", android_getCpuFamily()); 1717464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne return ""; 1727464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne } 1737464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne} 1747464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne 1757464ac9bd7fe89061e47617e4b6004b88c91d636Ed Coyne} // namespace android 176