Search code examples
androidcjava-native-interface

Why is there an API limit on native libraries?


While looking for a native key/value storage library to use into an Android application, I tried to use hsearch, but when trying to deploy on my "old" phone (API 23), I got an error: "undefined reference to 'hcreate'".

Looking into search.h with Android Studio, I found out that these functions can only be used with API levels higher than or equal to 28 (declarations are protected by #if __ANDROID_API__ >= 28) in search.h.

Android API 28 was released in August, 2018, and I believe that hsearch is older than that, so the question is: why is there such a high API limit on hsearch functions?


Solution

  • Probably only the responsible developers at Google can answer the "why" definitively.

    that'll be me :-)

    historically, as you said, bionic was basically "just enough libc to build dalvik". during the dalvik to ART transition i worked on ART and spent enough time fixing libc issues that -- when the need to add 64-bit support arose -- i ended up owning libc instead.

    you can see Android bionic status both what's happened since the earliest days i was involved with bionic to now, and "what's left". specifically there's actually quite a small list of "stuff we definitely won't add" now, and we try to ensure that's always explained there at the top of that page.

    if you look at that page, you'll notice that L -- which is when i basically started working full-time on libc -- was where most of the missing stuff appeared. so in the specific case of <search.h> the question remains "why were these added in API 28 rather than API 21?". the answer to that, as i recall is basically a combination of (a) i don't think we'd ever seen any code using these functions at that point and (b) they look like they ought to be deprecated. the non-_r forms are not suitable for use from library code, for example, because they operate on a single global table.

    at some point someone came along with third-party code that used it, and i held my nose and added it. part of me still wonders whether we should have only added the _r variants, but since C is just one big foot-gun anyway, i felt like the positive value of "it just works" outweighed the negative value of "almost no code should use this, and there's no good way for us to help you catch your mistake".

    just because glibc has feature X doesn't automatically mean that it will make its way over to bionic

    we do try to keep track of what glibc adds, to see if there's anything useful going in, but in terms of portability iOS is more relevant to most Android developers. (the conflict between the glibc qsort_r and the iOS qsort_r is why Android still doesn't have either, for example!)

    As for why they didn't backport the feature to older API levels when they did add it to bionic, I don't know.

    none of these cases were security issues, so they'd be ineligible for going into the minor updates.

    in some cases, we do actually have inline versions of functions in the headers for targeting old API levels. for example: termios_inlines.h


    getting back to this specific case, the hcreate/hsearch/hdestroy functions are small and simple, so if you want them, you can always include them in your code directly. here's the current ones used in Android (from FreeBSD): source. but remember that you also have libc++ available, so std::map and friends are trivially available and usually a better choice. (this was one reason why the demand didn't arise for so long.)