Home | History | Annotate | Download | only in jni
      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 <nativehelper/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 
     31 static jclass gString;
     32 static jclass gHashMapClazz;
     33 static jmethodID gHashMapInit;
     34 static jmethodID gHashMapPut;
     35 
     36 namespace android {
     37 
     38 using vintf::HalManifest;
     39 using vintf::SchemaType;
     40 using vintf::VintfObject;
     41 using vintf::XmlConverter;
     42 using vintf::Vndk;
     43 using vintf::gHalManifestConverter;
     44 using vintf::gCompatibilityMatrixConverter;
     45 using vintf::to_string;
     46 
     47 template<typename V>
     48 static 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 
     58 template<typename T>
     59 static 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 
     69 static 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 
     80 static 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 
     96 static 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     std::string error;
    106     int32_t status = VintfObject::CheckCompatibility(cPackageInfo, &error);
    107     if (status)
    108         LOG(WARNING) << "VintfObject.verify() returns " << status << ": " << error;
    109     return status;
    110 }
    111 
    112 static jobjectArray android_os_VintfObject_getHalNamesAndVersions(JNIEnv* env, jclass) {
    113     std::set<std::string> halNames;
    114     tryAddHalNamesAndVersions(VintfObject::GetDeviceHalManifest(),
    115             "device manifest", &halNames);
    116     tryAddHalNamesAndVersions(VintfObject::GetFrameworkHalManifest(),
    117             "framework manifest", &halNames);
    118     return toJavaStringArray(env, halNames);
    119 }
    120 
    121 static jstring android_os_VintfObject_getSepolicyVersion(JNIEnv* env, jclass) {
    122     const HalManifest *manifest = VintfObject::GetDeviceHalManifest();
    123     if (manifest == nullptr || manifest->type() != SchemaType::DEVICE) {
    124         LOG(WARNING) << __FUNCTION__ << "Cannot get device manifest";
    125         return nullptr;
    126     }
    127     std::string cString = to_string(manifest->sepolicyVersion());
    128     return env->NewStringUTF(cString.c_str());
    129 }
    130 
    131 static jobject android_os_VintfObject_getVndkSnapshots(JNIEnv* env, jclass) {
    132     const HalManifest *manifest = VintfObject::GetFrameworkHalManifest();
    133     if (manifest == nullptr || manifest->type() != SchemaType::FRAMEWORK) {
    134         LOG(WARNING) << __FUNCTION__ << "Cannot get framework manifest";
    135         return nullptr;
    136     }
    137     jobject jMap = env->NewObject(gHashMapClazz, gHashMapInit);
    138     for (const Vndk &vndk : manifest->vndks()) {
    139         std::string key = to_string(vndk.versionRange());
    140         env->CallObjectMethod(jMap, gHashMapPut,
    141                 env->NewStringUTF(key.c_str()), toJavaStringArray(env, vndk.libraries()));
    142     }
    143     return jMap;
    144 }
    145 
    146 // ----------------------------------------------------------------------------
    147 
    148 static const JNINativeMethod gVintfObjectMethods[] = {
    149     {"report", "()[Ljava/lang/String;", (void*)android_os_VintfObject_report},
    150     {"verify", "([Ljava/lang/String;)I", (void*)android_os_VintfObject_verify},
    151     {"getHalNamesAndVersions", "()[Ljava/lang/String;", (void*)android_os_VintfObject_getHalNamesAndVersions},
    152     {"getSepolicyVersion", "()Ljava/lang/String;", (void*)android_os_VintfObject_getSepolicyVersion},
    153     {"getVndkSnapshots", "()Ljava/util/Map;", (void*)android_os_VintfObject_getVndkSnapshots},
    154 };
    155 
    156 const char* const kVintfObjectPathName = "android/os/VintfObject";
    157 
    158 int register_android_os_VintfObject(JNIEnv* env)
    159 {
    160 
    161     gString = MakeGlobalRefOrDie(env, FindClassOrDie(env, "java/lang/String"));
    162     gHashMapClazz = MakeGlobalRefOrDie(env, FindClassOrDie(env, "java/util/HashMap"));
    163     gHashMapInit = GetMethodIDOrDie(env, gHashMapClazz, "<init>", "()V");
    164     gHashMapPut = GetMethodIDOrDie(env, gHashMapClazz,
    165             "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
    166 
    167     return RegisterMethodsOrDie(env, kVintfObjectPathName, gVintfObjectMethods,
    168             NELEM(gVintfObjectMethods));
    169 }
    170 
    171 };
    172