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

Commit 29fba44b authored by Neil Fuller's avatar Neil Fuller
Browse files

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"
Change-Id: I6dc0f4f81848efbbaec6a11a62014471a0ef01fd
parent aa80c270
Loading
Loading
Loading
Loading
+1 −7
Original line number Diff line number Diff line
@@ -36,7 +36,6 @@ import android.util.proto.ProtoOutputStream;

import libcore.timezone.ZoneInfoDb;

import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
@@ -996,12 +995,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");
            }
+7 −13
Original line number Diff line number Diff line
@@ -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;

@@ -1117,7 +1116,6 @@ public class Time {
        }

        private static ZoneInfo lookupZoneInfo(String timezoneId) {
            try {
            ZoneInfo zoneInfo = ZoneInfoDb.getInstance().makeTimeZone(timezoneId);
            if (zoneInfo == null) {
                zoneInfo = ZoneInfoDb.getInstance().makeTimeZone("GMT");
@@ -1126,10 +1124,6 @@ public class Time {
                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);
            }
        }

        public void switchTimeZone(String timezone) {
+11 −2
Original line number Diff line number Diff line
@@ -184,6 +184,8 @@ import dalvik.system.VMRuntime;

import com.google.android.startop.iorap.IorapForwardingService;

import libcore.timezone.ZoneInfoDb;

import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
@@ -448,8 +450,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");
            }

@@ -627,6 +630,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();
    }