Skip to content

Commit

Permalink
Cherry pick PR #1664: Correct Linux implementation of SbTimezoneGetNa…
Browse files Browse the repository at this point in the history
…me (#1886)

Refer to the original PR: youtube/cobalt#1664

b/302569322

Change-Id: Icce69ed2db148020c44ab9d95af8d83283e3c138

Co-authored-by: johnxwork <[email protected]>
Co-authored-by: y4vor <[email protected]>
  • Loading branch information
3 people committed Nov 2, 2023
1 parent f8fea8f commit 96dc8d3
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 27 deletions.
2 changes: 1 addition & 1 deletion starboard/linux/shared/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ static_library("starboard_platform_sources") {
"//starboard/shared/linux/thread_get_id.cc",
"//starboard/shared/linux/thread_get_name.cc",
"//starboard/shared/linux/thread_set_name.cc",
"//starboard/shared/linux/time_zone_get_name.cc",
"//starboard/shared/nouser/user_get_current.cc",
"//starboard/shared/nouser/user_get_property.cc",
"//starboard/shared/nouser/user_get_signed_in.cc",
Expand Down Expand Up @@ -219,7 +220,6 @@ static_library("starboard_platform_sources") {
"//starboard/shared/posix/time_get_now.cc",
"//starboard/shared/posix/time_is_time_thread_now_supported.cc",
"//starboard/shared/posix/time_zone_get_current.cc",
"//starboard/shared/posix/time_zone_get_name.cc",
"//starboard/shared/pthread/condition_variable_broadcast.cc",
"//starboard/shared/pthread/condition_variable_create.cc",
"//starboard/shared/pthread/condition_variable_destroy.cc",
Expand Down
30 changes: 30 additions & 0 deletions starboard/nplb/time_zone_get_name_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,19 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#include <string.h>

#include "starboard/common/log.h"
#include "starboard/extension/time_zone.h"
#include "starboard/nplb/time_constants.h"
#include "starboard/system.h"
#include "starboard/time_zone.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using testing::AnyOf;
using testing::MatchesRegex;

namespace starboard {
namespace nplb {
namespace {
Expand All @@ -41,6 +50,27 @@ TEST(SbTimeZoneGetNameTest, IsKindOfSane) {
// ":Pacific/Kiritimati" is the western-most timezone at UTC+14.
}

TEST(SbTimeZoneGetNameTest, IsIANAFormat) {
const char* name = SbTimeZoneGetName();
SB_LOG(INFO) << "time zone name: " << name;
char cpy[100];
snprintf(cpy, sizeof(cpy), "%s", name);
char* continent = strtok(cpy, "/");
// The time zone ID starts with a Continent or Ocean name.
EXPECT_THAT(
continent,
testing::AnyOf(std::string("Asia"), std::string("America"),
std::string("Africa"), std::string("Europe"),
std::string("Australia"), std::string("Pacific"),
std::string("Atlantic"), std::string("Antarctica"),
// time zone can be "Etc/UTC" if unset(such as on
// CI builders), shouldn't happen in production.
// TODO(b/304351956): Remove Etc after fixing builders.
std::string("Indian"), std::string("Etc")));
char* city = strtok(NULL, "/");
EXPECT_TRUE(strlen(city) != 0);
}

} // namespace
} // namespace nplb
} // namespace starboard
2 changes: 1 addition & 1 deletion starboard/raspi/shared/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ static_library("starboard_platform_sources") {
"//starboard/shared/linux/thread_get_id.cc",
"//starboard/shared/linux/thread_get_name.cc",
"//starboard/shared/linux/thread_set_name.cc",
"//starboard/shared/linux/time_zone_get_name.cc",
"//starboard/shared/nouser/user_get_current.cc",
"//starboard/shared/nouser/user_get_property.cc",
"//starboard/shared/nouser/user_get_signed_in.cc",
Expand Down Expand Up @@ -189,7 +190,6 @@ static_library("starboard_platform_sources") {
"//starboard/shared/posix/time_get_now.cc",
"//starboard/shared/posix/time_is_time_thread_now_supported.cc",
"//starboard/shared/posix/time_zone_get_current.cc",
"//starboard/shared/posix/time_zone_get_name.cc",
"//starboard/shared/pthread/condition_variable_broadcast.cc",
"//starboard/shared/pthread/condition_variable_create.cc",
"//starboard/shared/pthread/condition_variable_destroy.cc",
Expand Down
75 changes: 75 additions & 0 deletions starboard/shared/linux/time_zone_get_name.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright 2015 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <string.h>
#include <time.h>
#include <unistd.h>

#include "starboard/common/log.h"
#include "starboard/time_zone.h"

#define TZDEFAULT "/etc/localtime"
#define TZZONEINFOTAIL "/zoneinfo/"
#define isNonDigit(ch) (ch < '0' || '9' < ch)

static char gTimeZoneBuffer[PATH_MAX];
static char* gTimeZoneBufferPtr = NULL;

static bool isValidOlsonID(const char* id) {
int32_t idx = 0;

/* Determine if this is something like Iceland (Olson ID)
or AST4ADT (non-Olson ID) */
while (id[idx] && isNonDigit(id[idx]) && id[idx] != ',') {
idx++;
}

/* If we went through the whole string, then it might be okay.
The timezone is sometimes set to "CST-7CDT", "CST6CDT5,J129,J131/19:30",
"GRNLNDST3GRNLNDDT" or similar, so we cannot use it.
The rest of the time it could be an Olson ID. George */
return static_cast<bool>(id[idx] == 0 || strcmp(id, "PST8PDT") == 0 ||
strcmp(id, "MST7MDT") == 0 ||
strcmp(id, "CST6CDT") == 0 ||
strcmp(id, "EST5EDT") == 0);
}

// Similar to how ICU::putil.cpp gets IANA(Olsen) timezone ID.
const char* SbTimeZoneGetName() {
/*
This is a trick to look at the name of the link to get the Olson ID
because the tzfile contents is underspecified.
This isn't guaranteed to work because it may not be a symlink.
But this is production-tested solution for most versions of Linux.
*/

if (gTimeZoneBufferPtr == NULL) {
int32_t ret = (int32_t)readlink(TZDEFAULT, gTimeZoneBuffer,
sizeof(gTimeZoneBuffer) - 1);
if (0 < ret) {
int32_t tzZoneInfoTailLen = strlen(TZZONEINFOTAIL);
gTimeZoneBuffer[ret] = 0;
char* tzZoneInfoTailPtr = strstr(gTimeZoneBuffer, TZZONEINFOTAIL);

if (tzZoneInfoTailPtr != NULL &&
isValidOlsonID(tzZoneInfoTailPtr + tzZoneInfoTailLen)) {
return (gTimeZoneBufferPtr = tzZoneInfoTailPtr + tzZoneInfoTailLen);
}
}
SB_NOTREACHED();
return "";
} else {
return gTimeZoneBufferPtr;
}
}
24 changes: 0 additions & 24 deletions starboard/shared/posix/time_zone_get_name.cc

This file was deleted.

2 changes: 1 addition & 1 deletion starboard/time_zone.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ extern "C" {
// The number of minutes west of the Greenwich Prime Meridian, NOT including
// Daylight Savings Time adjustments.
//
// For example: PST/PDT is 480 minutes (28800 seconds, 8 hours).
// For example: America/Los_Angeles is 480 minutes (28800 seconds, 8 hours).
typedef int SbTimeZone;

// Gets the system's current SbTimeZone in minutes.
Expand Down
4 changes: 4 additions & 0 deletions starboard/win/win32/test_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@

# Enable once verified on the platform.
'SbMediaCanPlayMimeAndKeySystem.MinimumSupport',

# Windows uses a special time zone format that ICU accepts, so we don't enforce IANA.
# TODO(b/304335954): Re-enable the test after fixing Windows implementation.
'SbTimeZoneGetNameTest.IsIANAFormat',
],
'player_filter_tests': [
# These tests fail on our VMs for win-win32 builds due to missing
Expand Down

0 comments on commit 96dc8d3

Please sign in to comment.