blob: a2bb469021823ed4b4df6136abd66ecb156a9e45 [file] [log] [blame]
Chong Zhangea788f72018-10-12 14:44:24 -07001/*
2 * Copyright 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "MediaCodecUpdateService"
18//#define LOG_NDEBUG 0
19
20#include <android/dlext.h>
21#include <android-base/logging.h>
22#include <android-base/strings.h>
23#include <dirent.h>
24#include <dlfcn.h>
25#include <media/CodecServiceRegistrant.h>
26#include <utils/Log.h>
27#include <ziparchive/zip_archive.h>
28#include <cutils/properties.h>
29
30#include "MediaCodecUpdateService.h"
31
32// Copied from GraphicsEnv.cpp
33// TODO(b/37049319) Get this from a header once one exists
34extern "C" {
35 android_namespace_t* android_create_namespace(const char* name,
36 const char* ld_library_path,
37 const char* default_library_path,
38 uint64_t type,
39 const char* permitted_when_isolated_path,
40 android_namespace_t* parent);
41 bool android_link_namespaces(android_namespace_t* from,
42 android_namespace_t* to,
43 const char* shared_libs_sonames);
44 enum {
45 ANDROID_NAMESPACE_TYPE_ISOLATED = 1,
46 };
47}
48
49namespace android {
50namespace media {
51
52binder::Status MediaCodecUpdateService::loadPlugins(const ::std::string& apkPath) {
53 ALOGV("loadPlugins %s", apkPath.c_str());
54
55 ZipArchiveHandle zipHandle;
56 void *registrantLib = NULL;
57 int32_t ret = OpenArchive(apkPath.c_str(), &zipHandle);
58
59 if (ret == 0) {
60 char abilist32[PROPERTY_VALUE_MAX];
61 property_get("ro.product.cpu.abilist32", abilist32, "armeabi-v7a");
62
63 auto abis = base::Split(abilist32, ",");
64 if (abis.empty()) {
65 ALOGW("abilist is empty, trying armeabi-v7a ...");
66 abis.push_back("armeabi-v7a");
67 }
68
69 // TODO: Only try the first entry in abilist32 for now.
70 // We probably should try the next if it fails.
71 String8 libPathInApk = String8("lib/") + String8(abis[0].c_str());
72 String8 defaultLibPath = String8(apkPath.c_str()) + "!/" + libPathInApk;
73 String8 libPath = defaultLibPath + "/libmedia_codecserviceregistrant.so";
74
75 ZipEntry entry;
76 ZipString name(libPathInApk + "/libmedia_codecserviceregistrant.so");
77 ret = FindEntry(zipHandle, name, &entry);
78
79 if (ret == 0) {
80 android_namespace_t *codecNs = android_create_namespace("codecs",
81 nullptr, // ld_library_path
82 defaultLibPath.c_str(),
83 ANDROID_NAMESPACE_TYPE_ISOLATED,
84 nullptr, // permitted_when_isolated_path
85 nullptr); // parent
86
87 if (codecNs != nullptr) {
88 String8 linked_libraries(LINKED_LIBRARIES);
89 if (android_link_namespaces(
90 codecNs, nullptr, linked_libraries.c_str())) {
91 const android_dlextinfo dlextinfo = {
92 .flags = ANDROID_DLEXT_USE_NAMESPACE,
93 .library_namespace = codecNs,
94 };
95
96 registrantLib = android_dlopen_ext(
97 libPath.string(),
98 RTLD_NOW | RTLD_LOCAL, &dlextinfo);
99
100 if (registrantLib == NULL) {
101 ALOGE("Failed to load lib from archive: %s", dlerror());
102 }
103 } else {
104 ALOGE("Failed to link namespace");
105 }
106 } else {
107 ALOGE("Failed to create codec namespace");
108 }
109 } else {
110 ALOGE("Failed to find entry (ret=%d)", ret);
111 }
112
113 CloseArchive(zipHandle);
114 } else {
115 ALOGE("Failed to open archive (ret=%d)", ret);
116 }
117
118 if (registrantLib) {
119 RegisterCodecServicesFunc registerCodecServices =
120 reinterpret_cast<RegisterCodecServicesFunc>(
121 dlsym(registrantLib, "RegisterCodecServices"));
122 if (registerCodecServices) {
123 registerCodecServices();
124 } else {
125 LOG(WARNING) << "Cannot register codec services "
126 "-- corrupted library.";
127 }
128 } else {
129 LOG(ERROR) << "Cannot find codec service registrant.";
130 }
131
132 return binder::Status::ok();
133}
134
135} // namespace media
136} // namespace android