Skip to content

Commit

Permalink
Allow for __system_property_get() being hidden in Android 'L' and bey…
Browse files Browse the repository at this point in the history
…ond.
  • Loading branch information
devbww committed Dec 18, 2017
1 parent 36a8fff commit 017e685
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 10 deletions.
16 changes: 8 additions & 8 deletions src/time_zone_info.cc
Original file line number Diff line number Diff line change
Expand Up @@ -649,22 +649,22 @@ std::unique_ptr<ZoneInfoSource> FileZoneInfoSource::Open(
return std::unique_ptr<ZoneInfoSource>(new FileZoneInfoSource(fp, length));
}

#if defined(__BIONIC__)
class BionicZoneInfoSource : public FileZoneInfoSource {
#if defined(__ANDROID__)
class AndroidZoneInfoSource : public FileZoneInfoSource {
public:
static std::unique_ptr<ZoneInfoSource> Open(const std::string& name);

private:
explicit BionicZoneInfoSource(FILE* fp, std::size_t len)
explicit AndroidZoneInfoSource(FILE* fp, std::size_t len)
: FileZoneInfoSource(fp, len) {}
};

std::unique_ptr<ZoneInfoSource> BionicZoneInfoSource::Open(
std::unique_ptr<ZoneInfoSource> AndroidZoneInfoSource::Open(
const std::string& name) {
// Use of the "file:" prefix is intended for testing purposes only.
if (name.compare(0, 5, "file:") == 0) return Open(name.substr(5));

// See Bionic libc/tzcode/bionic.cpp for additional information.
// See Android's libc/tzcode/bionic.cpp for additional information.
for (const char* tzdata : {"/data/misc/zoneinfo/current/tzdata",
"/system/usr/share/zoneinfo/tzdata"}) {
std::unique_ptr<FILE, int (*)(FILE*)> fp(FOpen(tzdata, "rb"), fclose);
Expand Down Expand Up @@ -692,7 +692,7 @@ std::unique_ptr<ZoneInfoSource> BionicZoneInfoSource::Open(
ebuf[40] = '\0'; // ensure zone name is NUL terminated
if (strcmp(name.c_str(), ebuf) == 0) {
if (fseek(fp.get(), static_cast<long>(start), SEEK_SET) != 0) break;
return std::unique_ptr<ZoneInfoSource>(new BionicZoneInfoSource(
return std::unique_ptr<ZoneInfoSource>(new AndroidZoneInfoSource(
fp.release(), static_cast<std::size_t>(length)));
}
}
Expand All @@ -717,8 +717,8 @@ bool TimeZoneInfo::Load(const std::string& name) {
auto zip = cctz_extension::zone_info_source_factory(
name, [](const std::string& name) -> std::unique_ptr<ZoneInfoSource> {
if (auto zip = FileZoneInfoSource::Open(name)) return zip;
#if defined(__BIONIC__)
if (auto zip = BionicZoneInfoSource::Open(name)) return zip;
#if defined(__ANDROID__)
if (auto zip = AndroidZoneInfoSource::Open(name)) return zip;
#endif
return nullptr;
});
Expand Down
36 changes: 34 additions & 2 deletions src/time_zone_lookup.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@

#include "cctz/time_zone.h"

#if defined(__BIONIC__)
#if defined(__ANDROID__)
#include <sys/system_properties.h>
#if __ANDROID_API__ >= 21
#include <dlfcn.h>
#endif
#endif
#include <cstdlib>
#include <cstring>
Expand All @@ -26,6 +29,35 @@

namespace cctz {

#if defined(__ANDROID__) && __ANDROID_API__ >= 21
namespace {
// Android 'L' removes __system_property_get() from the NDK, however
// it is still a hidden symbol in libc so we use dlsym() to access it.
// See Chromium's base/sys_info_android.cc for a similar example.

using property_get_func = int (*)(const char*, char*);

property_get_func LoadSystemPropertyGet() {
int flag = RTLD_LAZY | RTLD_GLOBAL;
#if defined(RTLD_NOLOAD)
flag |= RTLD_NOLOAD; // libc.so should already be resident
#endif
if (void* handle = dlopen("libc.so", flag)) {
void* sym = dlsym(handle, "__system_property_get");
dlclose(handle);
return reinterpret_cast<property_get_func>(sym);
}
return nullptr;
}

int __system_property_get(const char* name, char* value) {
static property_get_func system_property_get = LoadSystemPropertyGet();
return system_property_get ? system_property_get(name, value) : -1;
}

} // namespace
#endif

std::string time_zone::name() const {
return time_zone::Impl::get(*this).name();
}
Expand Down Expand Up @@ -67,7 +99,7 @@ time_zone local_time_zone() {
#else
tz_env = std::getenv("TZ");
#endif
#if defined(__BIONIC__)
#if defined(__ANDROID__)
char sysprop[PROP_VALUE_MAX];
if (tz_env == nullptr)
if (__system_property_get("persist.sys.timezone", sysprop) > 0)
Expand Down

0 comments on commit 017e685

Please sign in to comment.