1/* 2 * Copyright (C) 2017 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 "VintfObject" 18//#define LOG_NDEBUG 0 19#include <android-base/logging.h> 20 21#include <vector> 22#include <string> 23 24#include <JNIHelp.h> 25#include <vintf/VintfObject.h> 26#include <vintf/parse_string.h> 27#include <vintf/parse_xml.h> 28 29#include "core_jni_helpers.h" 30 31static jclass gString; 32static jclass gHashMapClazz; 33static jmethodID gHashMapInit; 34static jmethodID gHashMapPut; 35 36namespace android { 37 38using vintf::HalManifest; 39using vintf::SchemaType; 40using vintf::VintfObject; 41using vintf::XmlConverter; 42using vintf::Vndk; 43using vintf::gHalManifestConverter; 44using vintf::gCompatibilityMatrixConverter; 45using vintf::to_string; 46 47template<typename V> 48static inline jobjectArray toJavaStringArray(JNIEnv* env, const V& v) { 49 size_t i; 50 typename V::const_iterator it; 51 jobjectArray ret = env->NewObjectArray(v.size(), gString, NULL /* init element */); 52 for (i = 0, it = v.begin(); it != v.end(); ++i, ++it) { 53 env->SetObjectArrayElement(ret, i, env->NewStringUTF(it->c_str())); 54 } 55 return ret; 56} 57 58template<typename T> 59static void tryAddSchema(const T* object, const XmlConverter<T>& converter, 60 const std::string& description, 61 std::vector<std::string>* cStrings) { 62 if (object == nullptr) { 63 LOG(WARNING) << __FUNCTION__ << "Cannot get " << description; 64 } else { 65 cStrings->push_back(converter(*object)); 66 } 67} 68 69static void tryAddHalNamesAndVersions(const HalManifest *manifest, 70 const std::string& description, 71 std::set<std::string> *output) { 72 if (manifest == nullptr) { 73 LOG(WARNING) << __FUNCTION__ << "Cannot get " << description; 74 } else { 75 auto names = manifest->getHalNamesAndVersions(); 76 output->insert(names.begin(), names.end()); 77 } 78} 79 80static jobjectArray android_os_VintfObject_report(JNIEnv* env, jclass) 81{ 82 std::vector<std::string> cStrings; 83 84 tryAddSchema(VintfObject::GetDeviceHalManifest(), gHalManifestConverter, 85 "device manifest", &cStrings); 86 tryAddSchema(VintfObject::GetFrameworkHalManifest(), gHalManifestConverter, 87 "framework manifest", &cStrings); 88 tryAddSchema(VintfObject::GetDeviceCompatibilityMatrix(), gCompatibilityMatrixConverter, 89 "device compatibility matrix", &cStrings); 90 tryAddSchema(VintfObject::GetFrameworkCompatibilityMatrix(), gCompatibilityMatrixConverter, 91 "framework compatibility matrix", &cStrings); 92 93 return toJavaStringArray(env, cStrings); 94} 95 96static jint android_os_VintfObject_verify(JNIEnv* env, jclass, jobjectArray packageInfo) { 97 size_t count = env->GetArrayLength(packageInfo); 98 std::vector<std::string> cPackageInfo{count}; 99 for (size_t i = 0; i < count; ++i) { 100 jstring element = (jstring)env->GetObjectArrayElement(packageInfo, i); 101 const char *cString = env->GetStringUTFChars(element, NULL /* isCopy */); 102 cPackageInfo[i] = cString; 103 env->ReleaseStringUTFChars(element, cString); 104 } 105 int32_t status = VintfObject::CheckCompatibility(cPackageInfo); 106 return status; 107} 108 109static jobjectArray android_os_VintfObject_getHalNamesAndVersions(JNIEnv* env, jclass) { 110 std::set<std::string> halNames; 111 tryAddHalNamesAndVersions(VintfObject::GetDeviceHalManifest(), 112 "device manifest", &halNames); 113 tryAddHalNamesAndVersions(VintfObject::GetFrameworkHalManifest(), 114 "framework manifest", &halNames); 115 return toJavaStringArray(env, halNames); 116} 117 118static jstring android_os_VintfObject_getSepolicyVersion(JNIEnv* env, jclass) { 119 const HalManifest *manifest = VintfObject::GetDeviceHalManifest(); 120 if (manifest == nullptr || manifest->type() != SchemaType::DEVICE) { 121 LOG(WARNING) << __FUNCTION__ << "Cannot get device manifest"; 122 return nullptr; 123 } 124 std::string cString = to_string(manifest->sepolicyVersion()); 125 return env->NewStringUTF(cString.c_str()); 126} 127 128static jobject android_os_VintfObject_getVndkSnapshots(JNIEnv* env, jclass) { 129 const HalManifest *manifest = VintfObject::GetFrameworkHalManifest(); 130 if (manifest == nullptr || manifest->type() != SchemaType::FRAMEWORK) { 131 LOG(WARNING) << __FUNCTION__ << "Cannot get framework manifest"; 132 return nullptr; 133 } 134 jobject jMap = env->NewObject(gHashMapClazz, gHashMapInit); 135 for (const Vndk &vndk : manifest->vndks()) { 136 std::string key = to_string(vndk.versionRange()); 137 env->CallObjectMethod(jMap, gHashMapPut, 138 env->NewStringUTF(key.c_str()), toJavaStringArray(env, vndk.libraries())); 139 } 140 return jMap; 141} 142 143// ---------------------------------------------------------------------------- 144 145static const JNINativeMethod gVintfObjectMethods[] = { 146 {"report", "()[Ljava/lang/String;", (void*)android_os_VintfObject_report}, 147 {"verify", "([Ljava/lang/String;)I", (void*)android_os_VintfObject_verify}, 148 {"getHalNamesAndVersions", "()[Ljava/lang/String;", (void*)android_os_VintfObject_getHalNamesAndVersions}, 149 {"getSepolicyVersion", "()Ljava/lang/String;", (void*)android_os_VintfObject_getSepolicyVersion}, 150 {"getVndkSnapshots", "()Ljava/util/Map;", (void*)android_os_VintfObject_getVndkSnapshots}, 151}; 152 153const char* const kVintfObjectPathName = "android/os/VintfObject"; 154 155int register_android_os_VintfObject(JNIEnv* env) 156{ 157 158 gString = MakeGlobalRefOrDie(env, FindClassOrDie(env, "java/lang/String")); 159 gHashMapClazz = MakeGlobalRefOrDie(env, FindClassOrDie(env, "java/util/HashMap")); 160 gHashMapInit = GetMethodIDOrDie(env, gHashMapClazz, "<init>", "()V"); 161 gHashMapPut = GetMethodIDOrDie(env, gHashMapClazz, 162 "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); 163 164 return RegisterMethodsOrDie(env, kVintfObjectPathName, gVintfObjectMethods, 165 NELEM(gVintfObjectMethods)); 166} 167 168}; 169