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

Commit 47aacc8c authored by Jooyung Han's avatar Jooyung Han Committed by Automerger Merge Worker
Browse files

Merge "Fix VintfObject to use vintf" into main am: f2c3583a

parents 71539cd6 f2c3583a
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));