Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f2c3583a authored by Jooyung Han's avatar Jooyung Han Committed by Gerrit Code Review
Browse files

Merge "Fix VintfObject to use vintf" into main

parents 2597bf42 e22f560d
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -17,8 +17,11 @@
package android.os;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.app.ActivityThread;

import java.io.IOException;
import java.util.Map;

/**
@@ -113,5 +116,20 @@ public class VintfObject {
    @TestApi
    public static native Long getTargetFrameworkCompatibilityMatrixVersion();

    /**
     * Executes a shell command using shell user identity, and return the standard output in string.
     *
     * @hide
     */
    private static @Nullable String runShellCommand(@NonNull String command) throws IOException {
        var activityThread = ActivityThread.currentActivityThread();
        var instrumentation = activityThread.getInstrumentation();
        var automation = instrumentation.getUiAutomation();
        var pfd = automation.executeShellCommand(command);
        try (var is = new ParcelFileDescriptor.AutoCloseInputStream(pfd)) {
            return new String(is.readAllBytes());
        }
    }

    private VintfObject() {}
}
+69 −21
Original line number Diff line number Diff line
@@ -32,6 +32,8 @@ static jmethodID gHashMapInit;
static jmethodID gHashMapPut;
static jclass gLongClazz;
static jmethodID gLongValueOf;
static jclass gVintfObjectClazz;
static jmethodID gRunCommand;

namespace android {

@@ -47,6 +49,56 @@ using vintf::VintfObject;
using vintf::Vndk;
using vintf::CheckFlags::ENABLE_ALL_CHECKS;

// Instead of VintfObject::GetXxx(), we construct
// HalManifest/CompatibilityMatrix objects by calling `vintf` through
// UiAutomation.executeShellCommand() so that the commands are executed
// using shell identity. Otherwise, we would need to allow "apps" to access
// files like apex-info-list.xml which we don't want to open to apps.
// This is okay because VintfObject is @TestApi and only used in CTS tests.

static std::string runCmd(JNIEnv* env, const char* cmd) {
    jstring jstr = (jstring)env->CallStaticObjectMethod(gVintfObjectClazz, gRunCommand,
                                                        env->NewStringUTF(cmd));
    std::string output;
    if (jstr) {
        auto cstr = env->GetStringUTFChars(jstr, nullptr);
        output = std::string(cstr);
        env->ReleaseStringUTFChars(jstr, cstr);
    } else {
        LOG(WARNING) << "Failed to run " << cmd;
        env->ExceptionDescribe();
        env->ExceptionClear();
    }
    return output;
}

template <typename T>
static std::shared_ptr<const T> fromXml(const std::string& content) {
    std::shared_ptr<T> object = std::make_unique<T>();
    std::string error;
    if (fromXml(object.get(), content, &error)) {
        return object;
    }
    LOG(WARNING) << "Unabled to parse: " << error;
    return nullptr;
}

static std::shared_ptr<const HalManifest> getDeviceHalManifest(JNIEnv* env) {
    return fromXml<HalManifest>(runCmd(env, "vintf dm"));
}

static std::shared_ptr<const HalManifest> getFrameworkHalManifest(JNIEnv* env) {
    return fromXml<HalManifest>(runCmd(env, "vintf fm"));
}

static std::shared_ptr<const CompatibilityMatrix> getDeviceCompatibilityMatrix(JNIEnv* env) {
    return fromXml<CompatibilityMatrix>(runCmd(env, "vintf dcm"));
}

static std::shared_ptr<const CompatibilityMatrix> getFrameworkCompatibilityMatrix(JNIEnv* env) {
    return fromXml<CompatibilityMatrix>(runCmd(env, "vintf fcm"));
}

template<typename V>
static inline jobjectArray toJavaStringArray(JNIEnv* env, const V& v) {
    size_t i;
@@ -83,12 +135,10 @@ static jobjectArray android_os_VintfObject_report(JNIEnv* env, jclass)
{
    std::vector<std::string> cStrings;

    tryAddSchema(VintfObject::GetDeviceHalManifest(), "device manifest", &cStrings);
    tryAddSchema(VintfObject::GetFrameworkHalManifest(), "framework manifest", &cStrings);
    tryAddSchema(VintfObject::GetDeviceCompatibilityMatrix(), "device compatibility matrix",
                 &cStrings);
    tryAddSchema(VintfObject::GetFrameworkCompatibilityMatrix(), "framework compatibility matrix",
                 &cStrings);
    tryAddSchema(getDeviceHalManifest(env), "device manifest", &cStrings);
    tryAddSchema(getFrameworkHalManifest(env), "framework manifest", &cStrings);
    tryAddSchema(getDeviceCompatibilityMatrix(env), "device compatibility matrix", &cStrings);
    tryAddSchema(getFrameworkCompatibilityMatrix(env), "framework compatibility matrix", &cStrings);

    return toJavaStringArray(env, cStrings);
}
@@ -108,15 +158,13 @@ static jint android_os_VintfObject_verifyBuildAtBoot(JNIEnv*, jclass) {

static jobjectArray android_os_VintfObject_getHalNamesAndVersions(JNIEnv* env, jclass) {
    std::set<std::string> halNames;
    tryAddHalNamesAndVersions(VintfObject::GetDeviceHalManifest(),
            "device manifest", &halNames);
    tryAddHalNamesAndVersions(VintfObject::GetFrameworkHalManifest(),
            "framework manifest", &halNames);
    tryAddHalNamesAndVersions(getDeviceHalManifest(env), "device manifest", &halNames);
    tryAddHalNamesAndVersions(getFrameworkHalManifest(env), "framework manifest", &halNames);
    return toJavaStringArray(env, halNames);
}

static jstring android_os_VintfObject_getSepolicyVersion(JNIEnv* env, jclass) {
    std::shared_ptr<const HalManifest> manifest = VintfObject::GetDeviceHalManifest();
    std::shared_ptr<const HalManifest> manifest = getDeviceHalManifest(env);
    if (manifest == nullptr || manifest->type() != SchemaType::DEVICE) {
        LOG(WARNING) << __FUNCTION__ << "Cannot get device manifest";
        return nullptr;
@@ -126,8 +174,7 @@ static jstring android_os_VintfObject_getSepolicyVersion(JNIEnv* env, jclass) {
}

static jstring android_os_VintfObject_getPlatformSepolicyVersion(JNIEnv* env, jclass) {
    std::shared_ptr<const CompatibilityMatrix> matrix =
            VintfObject::GetFrameworkCompatibilityMatrix();
    std::shared_ptr<const CompatibilityMatrix> matrix = getFrameworkCompatibilityMatrix(env);
    if (matrix == nullptr || matrix->type() != SchemaType::FRAMEWORK) {
        jniThrowRuntimeException(env, "Cannot get framework compatibility matrix");
        return nullptr;
@@ -148,7 +195,7 @@ static jstring android_os_VintfObject_getPlatformSepolicyVersion(JNIEnv* env, jc
}

static jobject android_os_VintfObject_getVndkSnapshots(JNIEnv* env, jclass) {
    std::shared_ptr<const HalManifest> manifest = VintfObject::GetFrameworkHalManifest();
    std::shared_ptr<const HalManifest> manifest = getFrameworkHalManifest(env);
    if (manifest == nullptr || manifest->type() != SchemaType::FRAMEWORK) {
        LOG(WARNING) << __FUNCTION__ << "Cannot get framework manifest";
        return nullptr;
@@ -163,7 +210,7 @@ static jobject android_os_VintfObject_getVndkSnapshots(JNIEnv* env, jclass) {
}

static jobject android_os_VintfObject_getTargetFrameworkCompatibilityMatrixVersion(JNIEnv* env, jclass) {
    std::shared_ptr<const HalManifest> manifest = VintfObject::GetDeviceHalManifest();
    std::shared_ptr<const HalManifest> manifest = getDeviceHalManifest(env);
    if (manifest == nullptr || manifest->level() == Level::UNSPECIFIED) {
        return nullptr;
    }
@@ -188,16 +235,17 @@ static const JNINativeMethod gVintfObjectMethods[] = {

const char* const kVintfObjectPathName = "android/os/VintfObject";

int register_android_os_VintfObject(JNIEnv* env)
{

int register_android_os_VintfObject(JNIEnv* env) {
    gString = MakeGlobalRefOrDie(env, FindClassOrDie(env, "java/lang/String"));
    gHashMapClazz = MakeGlobalRefOrDie(env, FindClassOrDie(env, "java/util/HashMap"));
    gHashMapInit = GetMethodIDOrDie(env, gHashMapClazz, "<init>", "()V");
    gHashMapPut = GetMethodIDOrDie(env, gHashMapClazz,
            "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
    gHashMapPut = GetMethodIDOrDie(env, gHashMapClazz, "put",
                                   "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
    gLongClazz = MakeGlobalRefOrDie(env, FindClassOrDie(env, "java/lang/Long"));
    gLongValueOf = GetStaticMethodIDOrDie(env, gLongClazz, "valueOf", "(J)Ljava/lang/Long;");
    gVintfObjectClazz = MakeGlobalRefOrDie(env, FindClassOrDie(env, kVintfObjectPathName));
    gRunCommand = GetStaticMethodIDOrDie(env, gVintfObjectClazz, "runShellCommand",
                                         "(Ljava/lang/String;)Ljava/lang/String;");

    return RegisterMethodsOrDie(env, kVintfObjectPathName, gVintfObjectMethods,
                                NELEM(gVintfObjectMethods));