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

Commit 70ad501a authored by Remi NGUYEN VAN's avatar Remi NGUYEN VAN
Browse files

Refine getNativeFileDescriptor

Factor out the isAtLeastR method, allow the "T" codename in addition to
"S", and add some comments.

Also remove usage of __ANDROID_API_S__ as it is not yet available in all
branches.

Bug: 166414751
Test: built, installed, wifi and tethering working
Change-Id: I473e6b224b670c18a85fa33d6ec3b4cc2873ce94
parent 7f03c094
Loading
Loading
Loading
Loading
+28 −17
Original line number Diff line number Diff line
@@ -58,9 +58,35 @@ static bool checkLenAndCopy(JNIEnv* env, const jbyteArray& addr, int len, void*
    return true;
}

static bool isAtLeastS() {
    static bool atLeastS = false;
    static bool doProbe = true;

    if (!doProbe) {
        return atLeastS;
    }

    atLeastS = (android_get_device_api_level() > __ANDROID_API_R__);
    if (!atLeastS) {
        // Check if this is a device with Android S dogfood build.
        static constexpr const char* kCodenameProperty = "ro.build.version.codename";
        char codename[PROP_VALUE_MAX] = { 0 };
        // SDK may be 30 (R) with codename T if S SDK was finalized but not yet merged in the
        // branch, and T development started.
        atLeastS = (__system_property_get(kCodenameProperty, codename) > 0 &&
                    (strncmp(codename, "S", 2) == 0 || strncmp(codename, "T", 2) == 0));
    }
    doProbe = false;

    return atLeastS;
}

static int getNativeFileDescriptorWithoutNdk(JNIEnv* env, jobject javaFd) {
    // Prior to Android S, we need to find the descriptor field in the FileDescriptor class. The
    // symbol name has been stable in libcore, but is a private implementation detail.
    // Older libnativehelper_compat_c++ versions had a jniGetFdFromFileDescriptor method, but this
    // was removed in S to replace it with the NDK API in libnativehelper.
    // The code is copied here instead. This code can be removed once R is not supported anymore.
    static jfieldID descriptorFieldID = nullptr;
    if (descriptorFieldID == nullptr) {
        jclass fileDescriptorClass = env->FindClass("java/io/FileDescriptor");
@@ -94,23 +120,8 @@ static int getNativeFileDescriptorWithNdk(JNIEnv* env, jobject javaFd) {
}

static int getNativeFileDescriptor(JNIEnv* env, jobject javaFd) {
    static bool preferNdkFileDescriptorApi = false;
    static bool probeNdkFileDescriptorApi = true;

    if (probeNdkFileDescriptorApi) {
    // Check if we should use the NDK File Descriptor API introduced in S.
        preferNdkFileDescriptorApi = (android_get_device_api_level() >= __ANDROID_API_S__);
        if (!preferNdkFileDescriptorApi) {
            // Check if this is a device with Android S dogfood build.
            static constexpr const char* kCodenameProperty = "ro.build.version.codename";
            char codename[PROP_VALUE_MAX] = { 0 };
            preferNdkFileDescriptorApi = (__system_property_get(kCodenameProperty, codename) > 0 &&
                                          strncmp(codename, "S", 2) == 0);
        }
        probeNdkFileDescriptorApi = false;
    }

    if (preferNdkFileDescriptorApi) {
    if (isAtLeastS()) {
        return getNativeFileDescriptorWithNdk(env, javaFd);
    } else {
        return getNativeFileDescriptorWithoutNdk(env, javaFd);