Be more defensive around invalid tzids

Add checks during boot in case the persist.sys.timezone property is set
to a bad ID.

This can happen in the rare case of a mainline rollback: i.e. if a device has
been set to a new ID and then the update is rolled back. Using GMT as a
fallback probably works without this change (it does in java.util.TimeZone),
but relies on all code, including native code that uses
persist.sys.timezone directly, knowing to interpret a bad ID as "GMT".
This commit makes that choice more explicit and defensive.

This change also removes the possibility of IOException, which is never
thrown, from some ZoneInfoDb methods.

Bug: 155738410
Test: boot with a valid id, verify persist.sys.timezone is unchanged
Test: boot with an invalid id set,  verify persist.sys.timezone is "GMT"
Merged-In: I6dc0f4f81848efbbaec6a11a62014471a0ef01fd
Change-Id: I6dc0f4f81848efbbaec6a11a62014471a0ef01fd
Exempt-From-Owner-Approval: Approved / landed internally
This commit is contained in:
Neil Fuller
2020-05-11 19:05:52 +01:00
parent ad00b4c7f1
commit 26fe60a188
3 changed files with 19 additions and 22 deletions

View File

@@ -37,7 +37,6 @@ import android.util.proto.ProtoOutputStream;
import libcore.timezone.ZoneInfoDb;
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -998,12 +997,7 @@ public class AlarmManager {
// Reject this timezone if it isn't an Olson zone we recognize.
if (mTargetSdkVersion >= Build.VERSION_CODES.M) {
boolean hasTimeZone = false;
try {
hasTimeZone = ZoneInfoDb.getInstance().hasTimeZone(timeZone);
} catch (IOException ignored) {
}
boolean hasTimeZone = ZoneInfoDb.getInstance().hasTimeZone(timeZone);
if (!hasTimeZone) {
throw new IllegalArgumentException("Timezone: " + timeZone + " is not an Olson ID");
}

View File

@@ -21,7 +21,6 @@ import android.util.TimeFormatException;
import libcore.timezone.ZoneInfoDb;
import libcore.util.ZoneInfo;
import java.io.IOException;
import java.util.Locale;
import java.util.TimeZone;
@@ -1106,19 +1105,14 @@ public class Time {
}
private static ZoneInfo lookupZoneInfo(String timezoneId) {
try {
ZoneInfo zoneInfo = ZoneInfoDb.getInstance().makeTimeZone(timezoneId);
if (zoneInfo == null) {
zoneInfo = ZoneInfoDb.getInstance().makeTimeZone("GMT");
}
if (zoneInfo == null) {
throw new AssertionError("GMT not found: \"" + timezoneId + "\"");
}
return zoneInfo;
} catch (IOException e) {
// This should not ever be thrown.
throw new AssertionError("Error loading timezone: \"" + timezoneId + "\"", e);
ZoneInfo zoneInfo = ZoneInfoDb.getInstance().makeTimeZone(timezoneId);
if (zoneInfo == null) {
zoneInfo = ZoneInfoDb.getInstance().makeTimeZone("GMT");
}
if (zoneInfo == null) {
throw new AssertionError("GMT not found: \"" + timezoneId + "\"");
}
return zoneInfo;
}
public void switchTimeZone(String timezone) {

View File

@@ -165,6 +165,8 @@ import com.android.server.wm.ActivityTaskManagerService;
import com.android.server.wm.WindowManagerGlobalLock;
import com.android.server.wm.WindowManagerService;
import libcore.timezone.ZoneInfoDb;
import dalvik.system.VMRuntime;
import java.io.File;
@@ -395,8 +397,9 @@ public final class SystemServer {
// Default the timezone property to GMT if not set.
//
String timezoneProperty = SystemProperties.get("persist.sys.timezone");
if (timezoneProperty == null || timezoneProperty.isEmpty()) {
Slog.w(TAG, "Timezone not set; setting to GMT.");
if (!isValidTimeZoneId(timezoneProperty)) {
Slog.w(TAG, "persist.sys.timezone is not valid (" + timezoneProperty
+ "); setting to GMT.");
SystemProperties.set("persist.sys.timezone", "GMT");
}
@@ -564,6 +567,12 @@ public final class SystemServer {
throw new RuntimeException("Main thread loop unexpectedly exited");
}
private static boolean isValidTimeZoneId(String timezoneProperty) {
return timezoneProperty != null
&& !timezoneProperty.isEmpty()
&& ZoneInfoDb.getInstance().hasTimeZone(timezoneProperty);
}
private boolean isFirstBootOrUpgrade() {
return mPackageManagerService.isFirstBoot() || mPackageManagerService.isDeviceUpgrading();
}