[automerger skipped] Empty merge of sc-v2-dev-plus-aosp-without-vendor@8084891 am: 4c46e5ee17 -s ours am: e22c7011cb -s ours

am skip reason: Merged-In I9a30b08c8240a156f6861a9b32ec06345c8a2936 with SHA-1 61b83166ac is already in history

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/modules/GeoTZ/+/16843986

Change-Id: I44d308413391908147fffe2487ec9fcd392f65e2
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
new file mode 100644
index 0000000..2ff4036
--- /dev/null
+++ b/PREUPLOAD.cfg
@@ -0,0 +1,9 @@
+[Builtin Hooks]
+bpfmt = true
+commit_msg_bug_field = true
+pylint = true
+xmllint = true
+
+[Hook Scripts]
+checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --sha ${PREUPLOAD_COMMIT}
+
diff --git a/common/host/main/java/com/android/timezone/location/common/LicenseSupport.java b/common/host/main/java/com/android/timezone/location/common/LicenseSupport.java
index 4795d41..f046391 100644
--- a/common/host/main/java/com/android/timezone/location/common/LicenseSupport.java
+++ b/common/host/main/java/com/android/timezone/location/common/LicenseSupport.java
@@ -32,16 +32,16 @@
      * The standard header to be put in files generated from OpenStreetMap data obtained from
      * https://opendatacommons.org/licenses/odbl/ on 2020-08-04.
      */
-    private final static String TEXT_PROTO_ODBL_LICENSE_HEADER = ""
+    private static final String TEXT_PROTO_ODBL_LICENSE_HEADER = ""
             + "# This time zone geo data is made available under the Open Database License:\n"
             + "# http://opendatacommons.org/licenses/odbl/1.0/.\n"
             + "# Any rights in individual contents of the database are licensed under the Database"
             + " Contents License:\n"
             + "# http://opendatacommons.org/licenses/dbcl/1.0/\n"
             + "\n";
-    private final static String ODBL_LICENSE_SNIPPET = "Open Database License (ODbL) v1.0";
+    private static final String ODBL_LICENSE_SNIPPET = "Open Database License (ODbL) v1.0";
 
-    public final static String LICENSE_FILE_NAME = "LICENSE";
+    public static final String LICENSE_FILE_NAME = "LICENSE";
 
     /** Individual licenses. */
     public enum License {
diff --git a/common/src/main/java/com/android/timezone/location/common/PiiLoggables.java b/common/src/main/java/com/android/timezone/location/common/PiiLoggables.java
index 24699a3..a658dba 100644
--- a/common/src/main/java/com/android/timezone/location/common/PiiLoggables.java
+++ b/common/src/main/java/com/android/timezone/location/common/PiiLoggables.java
@@ -54,6 +54,8 @@
      *
      * <p>See {@link #fromPiiValue(Object)} for a method that returns objects that implement a
      * minimal contract.
+     *
+     * @param <V> the type of the value held
      */
     public interface PiiLoggableValue<V> extends PiiLoggable {
         /** Returns the held value. */
@@ -122,7 +124,7 @@
 
             private final String mString;
 
-            public PiiLoggableString(String string) {
+            PiiLoggableString(String string) {
                 mString = string;
             }
 
@@ -168,7 +170,7 @@
             @NonNull private final String mTemplate;
             @NonNull private final PiiLoggable[] mLoggables;
 
-            public TemplatedPiiLoggable(String template, PiiLoggable... loggables) {
+            TemplatedPiiLoggable(String template, PiiLoggable... loggables) {
                 mTemplate = Objects.requireNonNull(template);
                 mLoggables = Objects.requireNonNull(loggables);
             }
@@ -192,8 +194,8 @@
                     return false;
                 }
                 TemplatedPiiLoggable that = (TemplatedPiiLoggable) o;
-                return mTemplate.equals(that.mTemplate) &&
-                        Arrays.equals(mLoggables, that.mLoggables);
+                return mTemplate.equals(that.mTemplate)
+                        && Arrays.equals(mLoggables, that.mLoggables);
             }
 
             @Override
diff --git a/common/src/test/java/com/android/timezone/location/common/PiiLoggablesTest.java b/common/src/test/java/com/android/timezone/location/common/PiiLoggablesTest.java
index 59e7a82..2c00800 100644
--- a/common/src/test/java/com/android/timezone/location/common/PiiLoggablesTest.java
+++ b/common/src/test/java/com/android/timezone/location/common/PiiLoggablesTest.java
@@ -25,8 +25,6 @@
 
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.timezone.location.common.PiiLoggable;
-import com.android.timezone.location.common.PiiLoggables;
 import com.android.timezone.location.common.PiiLoggables.PiiLoggableValue;
 
 import org.junit.Test;
@@ -124,7 +122,7 @@
         private final String mNoPii;
         private final String mPii;
 
-        public TestPiiLoggable(String noPii, String pii) {
+        TestPiiLoggable(String noPii, String pii) {
             mNoPii = noPii;
             mPii = pii;
         }
@@ -148,8 +146,8 @@
                 return false;
             }
             TestPiiLoggable that = (TestPiiLoggable) o;
-            return mNoPii.equals(that.mNoPii) &&
-                    mPii.equals(that.mPii);
+            return mNoPii.equals(that.mNoPii)
+                    && mPii.equals(that.mPii);
         }
 
         @Override
diff --git a/data_pipeline/src/debug/java/com/android/timezone/location/data_pipeline/tools/PrintTzS2CellUnionStats.java b/data_pipeline/src/debug/java/com/android/timezone/location/data_pipeline/tools/PrintTzS2CellUnionStats.java
index 946f60f..eec49a9 100644
--- a/data_pipeline/src/debug/java/com/android/timezone/location/data_pipeline/tools/PrintTzS2CellUnionStats.java
+++ b/data_pipeline/src/debug/java/com/android/timezone/location/data_pipeline/tools/PrintTzS2CellUnionStats.java
@@ -19,6 +19,7 @@
 import com.android.timezone.location.data_pipeline.steps.Types;
 import com.android.timezone.location.data_pipeline.steps.Types.ProtoStorageFormat;
 import com.android.timezone.location.data_pipeline.steps.Types.TzS2CellUnion;
+
 import com.google.common.geometry.S2CellId;
 
 import java.io.File;
diff --git a/data_pipeline/src/main/java/com/android/timezone/location/data_pipeline/steps/CanonicalizeTzS2Polygons.java b/data_pipeline/src/main/java/com/android/timezone/location/data_pipeline/steps/CanonicalizeTzS2Polygons.java
index 0c86d98..fbbaf73 100644
--- a/data_pipeline/src/main/java/com/android/timezone/location/data_pipeline/steps/CanonicalizeTzS2Polygons.java
+++ b/data_pipeline/src/main/java/com/android/timezone/location/data_pipeline/steps/CanonicalizeTzS2Polygons.java
@@ -92,30 +92,29 @@
                 description = "The input directory containing TzS2Polygons files",
                 required = true,
                 converter = FileConverter.class)
-        File inputDir;
+        public File inputDir;
 
         @Parameter(names = "--tz-ids",
                 description = "The input TzIds prototz file",
                 required = true,
                 converter = FileConverter.class)
-        File tzIdsFile;
+        public File tzIdsFile;
 
         @Parameter(names = "--replacement-threshold",
                 description = "The ISO 8601 format date/time to use when generating time zone"
                         + " ID replacements",
                 required = true)
-        String replacementThreshold;
+        public String replacementThreshold;
 
         @Parameter(names = "--output",
                 description = "The output dir to write TzS2Polygons files to",
                 required = true,
                 converter = FileConverter.class)
-        File outputDir;
+        public File outputDir;
 
         Instant replacementThreshold() {
             return Instant.parse(replacementThreshold);
         }
-
     }
 
     /**
diff --git a/data_pipeline/src/main/java/com/android/timezone/location/data_pipeline/steps/CreateTzS2ProtoDataFile.java b/data_pipeline/src/main/java/com/android/timezone/location/data_pipeline/steps/CreateTzS2ProtoDataFile.java
index 583f0ee..c849b58 100644
--- a/data_pipeline/src/main/java/com/android/timezone/location/data_pipeline/steps/CreateTzS2ProtoDataFile.java
+++ b/data_pipeline/src/main/java/com/android/timezone/location/data_pipeline/steps/CreateTzS2ProtoDataFile.java
@@ -63,14 +63,13 @@
                 description = "The input TzS2Ranges file to parse",
                 required = true,
                 converter = FileConverter.class)
-        File inputFile;
+        public File inputFile;
 
         @Parameter(names = "--output-file",
                 description = "The output file to produce",
                 required = true,
                 converter = FileConverter.class)
-        File outputFile;
-
+        public File outputFile;
     }
 
     /**
@@ -139,4 +138,4 @@
         }
         return builder.build();
     }
-}
\ No newline at end of file
+}
diff --git a/data_pipeline/src/main/java/com/android/timezone/location/data_pipeline/steps/GeoJsonTzToTzS2Polygons.java b/data_pipeline/src/main/java/com/android/timezone/location/data_pipeline/steps/GeoJsonTzToTzS2Polygons.java
index fccd36d..f43829c 100644
--- a/data_pipeline/src/main/java/com/android/timezone/location/data_pipeline/steps/GeoJsonTzToTzS2Polygons.java
+++ b/data_pipeline/src/main/java/com/android/timezone/location/data_pipeline/steps/GeoJsonTzToTzS2Polygons.java
@@ -33,6 +33,7 @@
 import com.google.common.geometry.S2Loop;
 import com.google.common.geometry.S2Point;
 import com.google.common.geometry.S2Polygon;
+
 import org.geojson.Feature;
 import org.geojson.FeatureCollection;
 import org.geojson.Geometry;
@@ -94,22 +95,22 @@
                 description = "The input geojson file to parse",
                 required = true,
                 converter = FileConverter.class)
-        File geoJsonFile;
+        public File geoJsonFile;
 
         @Parameter(names = "--num-threads",
                 description = "The number of threads to use",
                 required = true)
-        int numThreads;
+        public int numThreads;
 
         @Parameter(names = "--output",
                 description = "The output directory",
                 required = true,
                 converter = FileConverter.class)
-        File outputDir;
+        public File outputDir;
 
         @Parameter(names = "--tz-ids",
                 description = "Comma separated list of time zones to build S2Polygons for")
-        String tzIds;
+        public String tzIds;
 
         Set<String> tzIds() {
             return tzIds == null
diff --git a/data_pipeline/src/main/java/com/android/timezone/location/data_pipeline/steps/MergeTzS2Ranges.java b/data_pipeline/src/main/java/com/android/timezone/location/data_pipeline/steps/MergeTzS2Ranges.java
index f0d3a15..593a5f8 100644
--- a/data_pipeline/src/main/java/com/android/timezone/location/data_pipeline/steps/MergeTzS2Ranges.java
+++ b/data_pipeline/src/main/java/com/android/timezone/location/data_pipeline/steps/MergeTzS2Ranges.java
@@ -76,25 +76,24 @@
                 description = "The input directory containing the TzS2Ranges files",
                 required = true,
                 converter = FileConverter.class)
-        File inputDir;
+        public File inputDir;
 
         @Parameter(names = "--num-threads",
                 description = "The number of threads to use",
                 required = true)
-        int numThreads;
+        public int numThreads;
 
         @Parameter(names = "--working-dir",
                 description = "A working dir(for storage of intermediate files)",
                 required = true,
                 converter = FileConverter.class)
-        File workingDir;
+        public File workingDir;
 
         @Parameter(names = "--output-file",
                 description = "The output file to store the combined TzS2Ranges file",
                 required = true,
                 converter = FileConverter.class)
-        File outputFile;
-
+        public File outputFile;
     }
 
     /**
diff --git a/data_pipeline/src/main/java/com/android/timezone/location/data_pipeline/steps/Types.java b/data_pipeline/src/main/java/com/android/timezone/location/data_pipeline/steps/Types.java
index 167f581..72546e1 100644
--- a/data_pipeline/src/main/java/com/android/timezone/location/data_pipeline/steps/Types.java
+++ b/data_pipeline/src/main/java/com/android/timezone/location/data_pipeline/steps/Types.java
@@ -20,6 +20,7 @@
 
 import com.android.timezone.location.common.LicenseSupport.License;
 import com.android.timezone.location.data_pipeline.steps.proto.S2Protos;
+
 import com.google.common.geometry.S2CellId;
 import com.google.common.geometry.S2CellUnion;
 import com.google.common.geometry.S2Loop;
@@ -129,13 +130,13 @@
     }
 
     /** A basic pair class. */
-    public static class Pair<A, B> {
+    static class Pair<A, B> {
 
         public final A a;
 
         public final B b;
 
-        public Pair(A a, B b) {
+        Pair(A a, B b) {
             this.a = a;
             this.b = b;
         }
@@ -344,8 +345,8 @@
         @Override
         public String toString() {
             return "TzS2CellUnion{"
-                    + "tzId='" + tzId + '\'' +
-                    ", s2CellUnion=" + s2CellUnion
+                    + "tzId='" + tzId + '\''
+                    + ", s2CellUnion=" + s2CellUnion
                     + '}';
         }
 
diff --git a/data_pipeline/src/main/java/com/android/timezone/location/data_pipeline/steps/TzS2CellUnionsToTzS2Ranges.java b/data_pipeline/src/main/java/com/android/timezone/location/data_pipeline/steps/TzS2CellUnionsToTzS2Ranges.java
index 7763b22..ddf659e 100644
--- a/data_pipeline/src/main/java/com/android/timezone/location/data_pipeline/steps/TzS2CellUnionsToTzS2Ranges.java
+++ b/data_pipeline/src/main/java/com/android/timezone/location/data_pipeline/steps/TzS2CellUnionsToTzS2Ranges.java
@@ -80,25 +80,24 @@
                 description = "The input directory containing the TzS2CellUnion files",
                 required = true,
                 converter = FileConverter.class)
-        File inputDir;
+        public File inputDir;
 
         @Parameter(names = "--num-threads",
                 description = "The number of threads to use",
                 required = true)
-        int numThreads;
+        public int numThreads;
 
         @Parameter(names = "--output",
                 description = "The output directory to store the TzS2Ranges files",
                 required = true,
                 converter = FileConverter.class)
-        File outputDir;
+        public File outputDir;
 
         @Parameter(names = "--s2-level",
                 description = "The S2 level of the ranges to produce. The TzS2CellUnion must not "
                         + "contain S2 Cell IDs with a higher level than this",
                 required = true)
-        int s2Level;
-
+        public int s2Level;
     }
 
     /**
diff --git a/data_pipeline/src/main/java/com/android/timezone/location/data_pipeline/steps/TzS2PolygonsToTzS2CellUnions.java b/data_pipeline/src/main/java/com/android/timezone/location/data_pipeline/steps/TzS2PolygonsToTzS2CellUnions.java
index 7feb63e..53d222a 100644
--- a/data_pipeline/src/main/java/com/android/timezone/location/data_pipeline/steps/TzS2PolygonsToTzS2CellUnions.java
+++ b/data_pipeline/src/main/java/com/android/timezone/location/data_pipeline/steps/TzS2PolygonsToTzS2CellUnions.java
@@ -82,24 +82,23 @@
                 description = "The input directory containing the TzS2Polygons files",
                 required = true,
                 converter = FileConverter.class)
-        File inputDir;
+        public File inputDir;
 
         @Parameter(names = "--num-threads",
                 description = "The number of threads to use",
                 required = true)
-        int numThreads;
+        public int numThreads;
 
         @Parameter(names = "--output",
                 description = "The output directory to store the TzS2CellUnion files",
                 required = true,
                 converter = FileConverter.class)
-        File outputDir;
+        public File outputDir;
 
         @Parameter(names = "--max-s2-level",
                 description = "The maximum S2 level of the cells to include in the S2 cell unions",
                 required = true)
-        int maxS2Level;
-
+        public int maxS2Level;
     }
 
     /**
diff --git a/data_pipeline/src/test/java/com/android/timezone/location/data_pipeline/steps/TestSupport.java b/data_pipeline/src/test/java/com/android/timezone/location/data_pipeline/steps/TestSupport.java
index 54e75c5..69bedf0 100644
--- a/data_pipeline/src/test/java/com/android/timezone/location/data_pipeline/steps/TestSupport.java
+++ b/data_pipeline/src/test/java/com/android/timezone/location/data_pipeline/steps/TestSupport.java
@@ -17,6 +17,7 @@
 package com.android.timezone.location.data_pipeline.steps;
 
 import static com.android.timezone.location.common.LicenseSupport.LICENSE_FILE_NAME;
+
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.fail;
 
diff --git a/data_pipeline/src/test/java/com/android/timezone/location/data_pipeline/steps/canonicalizetzs2polygons/CanonicalizeTzS2PolygonsTest.java b/data_pipeline/src/test/java/com/android/timezone/location/data_pipeline/steps/canonicalizetzs2polygons/CanonicalizeTzS2PolygonsTest.java
index 45f9e29..80f47ba 100644
--- a/data_pipeline/src/test/java/com/android/timezone/location/data_pipeline/steps/canonicalizetzs2polygons/CanonicalizeTzS2PolygonsTest.java
+++ b/data_pipeline/src/test/java/com/android/timezone/location/data_pipeline/steps/canonicalizetzs2polygons/CanonicalizeTzS2PolygonsTest.java
@@ -19,9 +19,11 @@
 import static com.android.timezone.location.data_pipeline.steps.TestSupport.copyTestResource;
 import static com.android.timezone.location.data_pipeline.steps.TestSupport.copyTestResourceWithoutLicense;
 import static com.android.timezone.location.data_pipeline.steps.Types.DEFAULT_PROTO_STORAGE_FORMAT;
-import static java.time.ZoneOffset.UTC;
+
 import static org.junit.Assert.assertEquals;
 
+import static java.time.ZoneOffset.UTC;
+
 import com.android.timezone.location.data_pipeline.steps.CanonicalizeTzS2Polygons;
 import com.android.timezone.location.data_pipeline.steps.TestSupport;
 import com.android.timezone.location.data_pipeline.steps.Types.TzS2Polygons;
diff --git a/data_pipeline/src/test/java/com/android/timezone/location/data_pipeline/steps/createtzs2protodatafile/CreateTzS2ProtoDataFileTest.java b/data_pipeline/src/test/java/com/android/timezone/location/data_pipeline/steps/createtzs2protodatafile/CreateTzS2ProtoDataFileTest.java
index bb0583e..5e479bc 100644
--- a/data_pipeline/src/test/java/com/android/timezone/location/data_pipeline/steps/createtzs2protodatafile/CreateTzS2ProtoDataFileTest.java
+++ b/data_pipeline/src/test/java/com/android/timezone/location/data_pipeline/steps/createtzs2protodatafile/CreateTzS2ProtoDataFileTest.java
@@ -17,6 +17,7 @@
 package com.android.timezone.location.data_pipeline.steps.createtzs2protodatafile;
 
 import static com.android.timezone.location.data_pipeline.steps.TestSupport.copyTestResource;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
diff --git a/data_pipeline/src/test/java/com/android/timezone/location/data_pipeline/steps/geojsontz_to_tzs2polygons/GeoJsonTzToTzS2PolygonsTest.java b/data_pipeline/src/test/java/com/android/timezone/location/data_pipeline/steps/geojsontz_to_tzs2polygons/GeoJsonTzToTzS2PolygonsTest.java
index e5ed813..ffe135e 100644
--- a/data_pipeline/src/test/java/com/android/timezone/location/data_pipeline/steps/geojsontz_to_tzs2polygons/GeoJsonTzToTzS2PolygonsTest.java
+++ b/data_pipeline/src/test/java/com/android/timezone/location/data_pipeline/steps/geojsontz_to_tzs2polygons/GeoJsonTzToTzS2PolygonsTest.java
@@ -17,6 +17,7 @@
 package com.android.timezone.location.data_pipeline.steps.geojsontz_to_tzs2polygons;
 
 import static com.android.timezone.location.data_pipeline.steps.TestSupport.copyTestResource;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
diff --git a/data_pipeline/src/test/java/com/android/timezone/location/data_pipeline/steps/mergetzs2ranges/MergeTzS2RangesTest.java b/data_pipeline/src/test/java/com/android/timezone/location/data_pipeline/steps/mergetzs2ranges/MergeTzS2RangesTest.java
index c664dd6..68a8d84 100644
--- a/data_pipeline/src/test/java/com/android/timezone/location/data_pipeline/steps/mergetzs2ranges/MergeTzS2RangesTest.java
+++ b/data_pipeline/src/test/java/com/android/timezone/location/data_pipeline/steps/mergetzs2ranges/MergeTzS2RangesTest.java
@@ -17,6 +17,7 @@
 package com.android.timezone.location.data_pipeline.steps.mergetzs2ranges;
 
 import static com.android.timezone.location.data_pipeline.steps.TestSupport.copyTestResource;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
diff --git a/data_pipeline/src/test/java/com/android/timezone/location/data_pipeline/steps/tzs2cellunions_to_tzs2ranges/TzS2CellUnionsToTzS2RangesTest.java b/data_pipeline/src/test/java/com/android/timezone/location/data_pipeline/steps/tzs2cellunions_to_tzs2ranges/TzS2CellUnionsToTzS2RangesTest.java
index 43b2add..d18580e 100644
--- a/data_pipeline/src/test/java/com/android/timezone/location/data_pipeline/steps/tzs2cellunions_to_tzs2ranges/TzS2CellUnionsToTzS2RangesTest.java
+++ b/data_pipeline/src/test/java/com/android/timezone/location/data_pipeline/steps/tzs2cellunions_to_tzs2ranges/TzS2CellUnionsToTzS2RangesTest.java
@@ -17,6 +17,7 @@
 package com.android.timezone.location.data_pipeline.steps.tzs2cellunions_to_tzs2ranges;
 
 import static com.android.timezone.location.data_pipeline.steps.TestSupport.copyTestResource;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
diff --git a/data_pipeline/src/test/java/com/android/timezone/location/data_pipeline/steps/tzs2polygons_tzs2cellunions/TzS2PolygonsToTzS2CellUnionsTest.java b/data_pipeline/src/test/java/com/android/timezone/location/data_pipeline/steps/tzs2polygons_tzs2cellunions/TzS2PolygonsToTzS2CellUnionsTest.java
index 401ef66..0b13a30 100644
--- a/data_pipeline/src/test/java/com/android/timezone/location/data_pipeline/steps/tzs2polygons_tzs2cellunions/TzS2PolygonsToTzS2CellUnionsTest.java
+++ b/data_pipeline/src/test/java/com/android/timezone/location/data_pipeline/steps/tzs2polygons_tzs2cellunions/TzS2PolygonsToTzS2CellUnionsTest.java
@@ -17,6 +17,7 @@
 package com.android.timezone.location.data_pipeline.steps.tzs2polygons_tzs2cellunions;
 
 import static com.android.timezone.location.data_pipeline.steps.TestSupport.copyTestResource;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
diff --git a/geotz_lookup/src/main/java/com/android/timezone/location/lookup/S2RangeFileBasedGeoTimeZonesFinder.java b/geotz_lookup/src/main/java/com/android/timezone/location/lookup/S2RangeFileBasedGeoTimeZonesFinder.java
index 681af52..c2d54b0 100644
--- a/geotz_lookup/src/main/java/com/android/timezone/location/lookup/S2RangeFileBasedGeoTimeZonesFinder.java
+++ b/geotz_lookup/src/main/java/com/android/timezone/location/lookup/S2RangeFileBasedGeoTimeZonesFinder.java
@@ -18,6 +18,7 @@
 import androidx.annotation.NonNull;
 
 import com.android.timezone.location.storage.tzs2range.read.TzS2RangeFileReader;
+
 import com.google.common.geometry.S2CellId;
 import com.google.common.geometry.S2LatLng;
 
diff --git a/locationtzprovider/src/main/java/com/android/timezone/location/provider/EnvironmentImpl.java b/locationtzprovider/src/main/java/com/android/timezone/location/provider/EnvironmentImpl.java
index efdca8b..e1b1fd4 100644
--- a/locationtzprovider/src/main/java/com/android/timezone/location/provider/EnvironmentImpl.java
+++ b/locationtzprovider/src/main/java/com/android/timezone/location/provider/EnvironmentImpl.java
@@ -483,7 +483,7 @@
     private static class HandlerExecutor implements Executor {
         private final Handler mHandler;
 
-        public HandlerExecutor(@NonNull Handler handler) {
+        HandlerExecutor(@NonNull Handler handler) {
             mHandler = Objects.requireNonNull(handler);
         }
 
@@ -495,7 +495,7 @@
         }
     }
 
-    private static abstract class BaseCancellable implements Cancellable {
+    private abstract static class BaseCancellable implements Cancellable {
         final String mIdentifier;
         boolean mCancelled = false;
 
diff --git a/locationtzprovider/src/main/java/com/android/timezone/location/provider/OfflineLocationTimeZoneProviderService.java b/locationtzprovider/src/main/java/com/android/timezone/location/provider/OfflineLocationTimeZoneProviderService.java
index d7fea5a..c8b7e22 100644
--- a/locationtzprovider/src/main/java/com/android/timezone/location/provider/OfflineLocationTimeZoneProviderService.java
+++ b/locationtzprovider/src/main/java/com/android/timezone/location/provider/OfflineLocationTimeZoneProviderService.java
@@ -59,6 +59,11 @@
     }
 
     @Override
+    public void onDestroy() {
+        mDelegate.onDestroy();
+    }
+
+    @Override
     public void onStartUpdates(long initializationTimeoutMillis) {
         mDelegate.onStartUpdates(Duration.ofMillis(initializationTimeoutMillis));
     }
@@ -93,4 +98,4 @@
     protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
         mDelegate.dump(writer);
     }
-}
\ No newline at end of file
+}
diff --git a/locationtzprovider/src/main/java/com/android/timezone/location/provider/core/Environment.java b/locationtzprovider/src/main/java/com/android/timezone/location/provider/core/Environment.java
index fe24651..d28eba8 100644
--- a/locationtzprovider/src/main/java/com/android/timezone/location/provider/core/Environment.java
+++ b/locationtzprovider/src/main/java/com/android/timezone/location/provider/core/Environment.java
@@ -28,9 +28,9 @@
 
 import com.android.timezone.location.common.PiiLoggable;
 import com.android.timezone.location.common.PiiLoggables;
+import com.android.timezone.location.common.PiiLoggables.PiiLoggableValue;
 import com.android.timezone.location.lookup.GeoTimeZonesFinder;
 import com.android.timezone.location.provider.core.OfflineLocationTimeZoneDelegate.ListenModeEnum;
-import com.android.timezone.location.common.PiiLoggables.PiiLoggableValue;
 
 import java.io.IOException;
 import java.time.Duration;
diff --git a/locationtzprovider/src/main/java/com/android/timezone/location/provider/core/Mode.java b/locationtzprovider/src/main/java/com/android/timezone/location/provider/core/Mode.java
index 6d0eda4..0233442 100644
--- a/locationtzprovider/src/main/java/com/android/timezone/location/provider/core/Mode.java
+++ b/locationtzprovider/src/main/java/com/android/timezone/location/provider/core/Mode.java
@@ -56,10 +56,10 @@
  *       - when the system server sends a "stopped" request it stops listening for the current
  *         location.
  *
- * {All states}
+ * {States except MODE_DESTROYED}
  *   -> {@link #MODE_FAILED} (terminal state)
  *       - when there is a fatal error.
- * {Most states}
+ * {All states}
  *   -> {@link #MODE_DESTROYED} (terminal state)
  *       - when the provider's service is destroyed, perhaps as part of the current user changing
  * </pre>
diff --git a/locationtzprovider/src/main/java/com/android/timezone/location/provider/core/OfflineLocationTimeZoneDelegate.java b/locationtzprovider/src/main/java/com/android/timezone/location/provider/core/OfflineLocationTimeZoneDelegate.java
index 7d8a053..f97e9c8 100644
--- a/locationtzprovider/src/main/java/com/android/timezone/location/provider/core/OfflineLocationTimeZoneDelegate.java
+++ b/locationtzprovider/src/main/java/com/android/timezone/location/provider/core/OfflineLocationTimeZoneDelegate.java
@@ -59,7 +59,10 @@
  * <p>Implementation details:
  *
  * <p>The instance interacts with multiple threads, but state changes occur in a single-threaded
- * manner through the use of a lock object, {@link #mLock}.
+ * manner through the use of a lock object, {@link #mLock}. Because multiple threads are involved,
+ * service lifecycle calls like {@link #onDestroy()} may be invoked by different threads than binder
+ * calls like {@link #onStopUpdates()}, leading to unintuitive ordering. See
+ * {@link android.service.timezone.TimeZoneProviderService} for details.
  *
  * <p>There are two listening modes:
  * <ul>
@@ -158,6 +161,7 @@
     @Nullable
     private Cancellable mInitializationTimeoutCancellable;
 
+    /** Creates a new instance that uses the supplied {@link Environment}. */
     @NonNull
     public static OfflineLocationTimeZoneDelegate create(@NonNull Environment environment) {
         return new OfflineLocationTimeZoneDelegate(environment);
@@ -173,23 +177,7 @@
         }
     }
 
-    public void onBind() {
-        PiiLoggable entryCause = PiiLoggables.fromString("onBind() called");
-        logDebug(entryCause);
-
-        synchronized (mLock) {
-            Mode currentMode = mCurrentMode.get();
-            if (currentMode.mModeEnum != MODE_STOPPED) {
-                handleUnexpectedStateTransition(
-                        "onBind() called when in unexpected mode=" + currentMode);
-                return;
-            }
-
-            Mode newMode = new Mode(MODE_STOPPED, entryCause);
-            mCurrentMode.set(newMode);
-        }
-    }
-
+    /** Called during {@link android.service.timezone.TimeZoneProviderService#onDestroy}. */
     public void onDestroy() {
         PiiLoggable entryCause = PiiLoggables.fromString("onDestroy() called");
         logDebug(entryCause);
@@ -201,11 +189,13 @@
             if (currentMode.mModeEnum == MODE_STARTED) {
                 sendTimeZoneUncertainResultIfNeeded();
             }
+            // The current mode can be set to MODE_DESTROYED in all cases, even from MODE_FAILED.
             Mode newMode = new Mode(MODE_DESTROYED, entryCause);
             mCurrentMode.set(newMode);
         }
     }
 
+    /** Called during {@link android.service.timezone.TimeZoneProviderService#onStartUpdates}. */
     public void onStartUpdates(@NonNull Duration initializationTimeout) {
         Objects.requireNonNull(initializationTimeout);
 
@@ -215,54 +205,35 @@
 
         synchronized (mLock) {
             Mode currentMode = mCurrentMode.get();
-            switch (currentMode.mModeEnum) {
-                case MODE_STOPPED: {
-                    enterStartedMode(initializationTimeout, debugInfo);
-                    break;
-                }
-                case MODE_STARTED: {
-                    // No-op - the provider is already started.
-                    logWarn("Unexpected onStarted() received when in currentMode=" + currentMode);
-                    break;
-                }
-                case MODE_FAILED:
-                case MODE_DESTROYED:
-                default: {
-                    handleUnexpectedStateTransition(
-                            "Unexpected onStarted() received when in currentMode=" + currentMode);
-                    break;
-                }
+            if (currentMode.mModeEnum == MODE_STOPPED) {
+                enterStartedMode(initializationTimeout, debugInfo);
+            } else {
+                logWarn("Unexpected onStarted() received when in currentMode=" + currentMode);
             }
         }
     }
 
+    /** Called during {@link android.service.timezone.TimeZoneProviderService#onStopUpdates}. */
     public void onStopUpdates() {
         PiiLoggable debugInfo = PiiLoggables.fromString("onStopUpdates()");
         logDebug(debugInfo);
 
         synchronized (mLock) {
             Mode currentMode = mCurrentMode.get();
-            switch (currentMode.mModeEnum) {
-                case MODE_STOPPED: {
-                    // No-op - the provider is already stopped.
-                    logWarn("Unexpected onStopUpdates() when currentMode=" + currentMode);
-                    break;
-                }
-                case MODE_STARTED: {
-                    enterStoppedMode(debugInfo);
-                    break;
-                }
-                case MODE_FAILED:
-                case MODE_DESTROYED:
-                default: {
-                    handleUnexpectedStateTransition(
-                            "Unexpected onStopUpdates() when currentMode=" + currentMode);
-                    break;
-                }
+            if (currentMode.mModeEnum == MODE_STARTED) {
+                enterStoppedMode(debugInfo);
+            } else if (currentMode.mModeEnum == MODE_DESTROYED) {
+                // This can happen because onDestroy() and onStopUpdates() are handled by different
+                // threads: it is still logged, but at a lower priority than other unexpected
+                // transitions.
+                logDebug("Unexpected onStopUpdates() when currentMode=" + currentMode);
+            } else {
+                logWarn("Unexpected onStopUpdates() when currentMode=" + currentMode);
             }
         }
     }
 
+    /** Called during {@link android.service.timezone.TimeZoneProviderService#dump}. */
     public void dump(@NonNull PrintWriter pw) {
         synchronized (mLock) {
             // Output useful "current time" information to help with debugging.
@@ -288,6 +259,7 @@
         }
     }
 
+    /** Returns the current mode. Only intended for use in tests. */
     public int getCurrentModeEnumForTests() {
         synchronized (mLock) {
             return mCurrentMode.get().mModeEnum;
@@ -306,7 +278,7 @@
                 String unexpectedStateDebugInfo = "Unexpected call to onActiveListeningResult(),"
                         + " activeListeningResult=" + activeListeningResult
                         + ", currentMode=" + currentMode;
-                handleUnexpectedLocationCallback(unexpectedStateDebugInfo);
+                reportUnexpectedLocationCallback(unexpectedStateDebugInfo);
                 return;
             }
 
@@ -348,7 +320,7 @@
                 String unexpectedStateDebugInfo = "Unexpected call to onPassiveListeningResult(),"
                         + " passiveListeningResult=" + passiveListeningResult
                         + ", currentMode=" + currentMode;
-                handleUnexpectedLocationCallback(unexpectedStateDebugInfo);
+                reportUnexpectedLocationCallback(unexpectedStateDebugInfo);
                 return;
             }
             logDebug("onPassiveListeningResult()"
@@ -373,7 +345,7 @@
         Mode currentMode = mCurrentMode.get();
         PiiLoggable debugInfo = PiiLoggables.fromTemplate(
                 "handleLocationKnown(), locationResult=%s"
-                +", currentMode.mListenMode=" + prettyPrintListenModeEnum(currentMode.mListenMode),
+                + ", currentMode.mListenMode=" + prettyPrintListenModeEnum(currentMode.mListenMode),
                 locationResult);
         logDebug(debugInfo);
 
@@ -425,7 +397,7 @@
             Mode currentMode = mCurrentMode.get();
             if (currentMode.mModeEnum != MODE_STARTED
                     || currentMode.mListenMode != LOCATION_LISTEN_MODE_PASSIVE) {
-                handleUnexpectedLocationCallback("Unexpected call to onPassiveListeningEnded()"
+                reportUnexpectedLocationCallback("Unexpected call to onPassiveListeningEnded()"
                         + ", currentMode=" + currentMode);
                 return;
             }
@@ -515,8 +487,8 @@
         }
 
         // If the last result was uncertain, there is no need to send another.
-        if (lastResult == null ||
-                lastResult.getType() != TimeZoneProviderResult.RESULT_TYPE_UNCERTAIN) {
+        if (lastResult == null
+                || lastResult.getType() != TimeZoneProviderResult.RESULT_TYPE_UNCERTAIN) {
             TimeZoneProviderResult result = TimeZoneProviderResult.createUncertain();
             reportTimeZoneProviderResultInternal(result, null /* locationToken */);
         } else {
@@ -557,14 +529,7 @@
     }
 
     @GuardedBy("mLock")
-    private void handleUnexpectedStateTransition(@NonNull String debugInfo) {
-        // To help track down unexpected behavior, this fails hard.
-        logWarn(debugInfo);
-        throw new IllegalStateException(debugInfo);
-    }
-
-    @GuardedBy("mLock")
-    private void handleUnexpectedLocationCallback(@NonNull String debugInfo) {
+    private void reportUnexpectedLocationCallback(@NonNull String debugInfo) {
         // Unexpected location callbacks can occur when location listening is cancelled, but a
         // location is already available (e.g. the callback is already invoked but blocked or
         // sitting in a handler queue). This is logged but generally ignored.
@@ -594,10 +559,13 @@
 
         cancelTimeoutsAndLocationCallbacks();
 
-        sendPermanentFailureResult(failure);
+        // Avoid a transition from MODE_DESTROYED -> MODE_FAILED.
+        if (mCurrentMode.get().mModeEnum != MODE_DESTROYED) {
+            sendPermanentFailureResult(failure);
 
-        Mode newMode = new Mode(MODE_FAILED, entryCause);
-        mCurrentMode.set(newMode);
+            Mode newMode = new Mode(MODE_FAILED, entryCause);
+            mCurrentMode.set(newMode);
+        }
     }
 
     @GuardedBy("mLock")
@@ -651,4 +619,4 @@
             mEnvironment.releaseWakeLock();
         }
     }
-}
\ No newline at end of file
+}
diff --git a/locationtzprovider/src/main/java/com/android/timezone/location/provider/core/ReferenceWithHistory.java b/locationtzprovider/src/main/java/com/android/timezone/location/provider/core/ReferenceWithHistory.java
index 1676eaa..6459aab 100644
--- a/locationtzprovider/src/main/java/com/android/timezone/location/provider/core/ReferenceWithHistory.java
+++ b/locationtzprovider/src/main/java/com/android/timezone/location/provider/core/ReferenceWithHistory.java
@@ -73,7 +73,7 @@
     /**
      * Creates an instance that records, at most, the specified number of values.
      */
-    public ReferenceWithHistory(@IntRange(from = 1) int maxHistorySize) {
+    ReferenceWithHistory(@IntRange(from = 1) int maxHistorySize) {
         this(maxHistorySize, String::valueOf);
     }
 
@@ -83,7 +83,7 @@
      * <p>The {@link #dump(PrintWriter)} method will use {@code dumpValueFunction} to format the
      * values held.
      */
-    public ReferenceWithHistory(@IntRange(from = 1) int maxHistorySize,
+    ReferenceWithHistory(@IntRange(from = 1) int maxHistorySize,
             Function<? super V, String> dumpValueFunction) {
         if (maxHistorySize < 1) {
             throw new IllegalArgumentException("maxHistorySize < 1: " + maxHistorySize);
diff --git a/locationtzprovider/src/main/java/com/android/timezone/location/provider/core/TimeZoneProviderResult.java b/locationtzprovider/src/main/java/com/android/timezone/location/provider/core/TimeZoneProviderResult.java
index 96fe068..55a5099 100644
--- a/locationtzprovider/src/main/java/com/android/timezone/location/provider/core/TimeZoneProviderResult.java
+++ b/locationtzprovider/src/main/java/com/android/timezone/location/provider/core/TimeZoneProviderResult.java
@@ -16,13 +16,13 @@
 
 package com.android.timezone.location.provider.core;
 
+import android.service.timezone.TimeZoneProviderService;
+import android.service.timezone.TimeZoneProviderSuggestion;
+
 import androidx.annotation.IntDef;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
-import android.service.timezone.TimeZoneProviderService;
-import android.service.timezone.TimeZoneProviderSuggestion;
-
 import java.util.Objects;
 
 /**
diff --git a/locationtzprovider/src/test/java/com/android/timezone/location/provider/core/OfflineLocationTimeZoneDelegateTest.java b/locationtzprovider/src/test/java/com/android/timezone/location/provider/core/OfflineLocationTimeZoneDelegateTest.java
index 25aff0b..e1947ef 100644
--- a/locationtzprovider/src/test/java/com/android/timezone/location/provider/core/OfflineLocationTimeZoneDelegateTest.java
+++ b/locationtzprovider/src/test/java/com/android/timezone/location/provider/core/OfflineLocationTimeZoneDelegateTest.java
@@ -18,6 +18,7 @@
 import static com.android.timezone.location.provider.core.OfflineLocationTimeZoneDelegate.LOCATION_LISTEN_MODE_ACTIVE;
 import static com.android.timezone.location.provider.core.OfflineLocationTimeZoneDelegate.LOCATION_LISTEN_MODE_PASSIVE;
 import static com.android.timezone.location.provider.core.TimeZoneProviderResult.RESULT_TYPE_SUGGESTION;
+import static com.android.timezone.location.provider.core.TimeZoneProviderResult.RESULT_TYPE_UNCERTAIN;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -91,16 +92,13 @@
         assertEquals(Mode.MODE_STOPPED, mDelegate.getCurrentModeEnumForTests());
         mTestEnvironment.assertIsNotListening();
         mTestEnvironment.assertNoActiveTimeouts();
+        mTestEnvironment.assertNoResultReported();
 
-        mDelegate.onBind();
-        assertEquals(Mode.MODE_STOPPED, mDelegate.getCurrentModeEnumForTests());
-        mTestEnvironment.assertIsNotListening();
-        mTestEnvironment.assertNoActiveTimeouts();
+        final Duration initializationTimeout = Duration.ofSeconds(20);
+        mDelegate.onStartUpdates(initializationTimeout);
 
         // The provider should have started an initialization timeout and followed the first
         // instruction from the accountant.
-        final Duration initializationTimeout = Duration.ofSeconds(20);
-        mDelegate.onStartUpdates(initializationTimeout);
         FakeEnvironment.TestTimeoutState<?> initializationTimeoutState =
                 mTestEnvironment.getActiveTimeoutState(0);
         initializationTimeoutState.assertDelay(initializationTimeout);
@@ -147,16 +145,13 @@
         assertEquals(Mode.MODE_STOPPED, mDelegate.getCurrentModeEnumForTests());
         mTestEnvironment.assertIsNotListening();
         mTestEnvironment.assertNoActiveTimeouts();
+        mTestEnvironment.assertNoResultReported();
 
-        mDelegate.onBind();
-        assertEquals(Mode.MODE_STOPPED, mDelegate.getCurrentModeEnumForTests());
-        mTestEnvironment.assertIsNotListening();
-        mTestEnvironment.assertNoActiveTimeouts();
+        final Duration initializationTimeout = Duration.ofSeconds(20);
+        mDelegate.onStartUpdates(initializationTimeout);
 
         // The provider should have started an initialization timeout and followed the first
         // instruction from the accountant.
-        final Duration initializationTimeout = Duration.ofSeconds(20);
-        mDelegate.onStartUpdates(initializationTimeout);
         FakeEnvironment.TestTimeoutState<?> initializationTimeoutState =
                 mTestEnvironment.getActiveTimeoutState(0);
         initializationTimeoutState.assertDelay(initializationTimeout);
@@ -179,6 +174,102 @@
                 passiveInstruction.listenMode, passiveInstruction.duration);
     }
 
+    @Test
+    public void onDestroy_neverStarted() throws Exception {
+        assertEquals(Mode.MODE_STOPPED, mDelegate.getCurrentModeEnumForTests());
+        mTestEnvironment.assertIsNotListening();
+        mTestEnvironment.assertNoActiveTimeouts();
+        mTestEnvironment.assertNoResultReported();
+
+        mDelegate.onDestroy();
+
+        assertEquals(Mode.MODE_DESTROYED, mDelegate.getCurrentModeEnumForTests());
+        mTestEnvironment.assertIsNotListening();
+        mTestEnvironment.assertNoActiveTimeouts();
+        mTestEnvironment.assertNoResultReported();
+    }
+
+    @Test
+    public void onDestroy_afterStarted() throws Exception {
+        // Prime the accountant with instructions.
+        ListeningInstruction activeInstruction = new ListeningInstruction(
+                LOCATION_LISTEN_MODE_ACTIVE, Duration.ofSeconds(15));
+        ListeningInstruction passiveInstruction = new ListeningInstruction(
+                LOCATION_LISTEN_MODE_PASSIVE, Duration.ofSeconds(25));
+        mTestLocationListeningAccountant.addInstruction(activeInstruction)
+                .addInstruction(passiveInstruction);
+
+        // Start of the test
+
+        assertEquals(Mode.MODE_STOPPED, mDelegate.getCurrentModeEnumForTests());
+        mTestEnvironment.assertIsNotListening();
+        mTestEnvironment.assertNoActiveTimeouts();
+        mTestEnvironment.assertNoResultReported();
+
+        final Duration initializationTimeout = Duration.ofSeconds(20);
+        mDelegate.onStartUpdates(initializationTimeout);
+
+        // The provider should have started an initialization timeout and followed the first
+        // instruction from the accountant.
+        FakeEnvironment.TestTimeoutState<?> initializationTimeoutState =
+                mTestEnvironment.getActiveTimeoutState(0);
+        initializationTimeoutState.assertDelay(initializationTimeout);
+        assertEquals(Mode.MODE_STARTED, mDelegate.getCurrentModeEnumForTests());
+        mTestEnvironment.assertIsLocationListening(
+                activeInstruction.listenMode, activeInstruction.duration);
+
+        // Destroyed without first being stopped.
+        mDelegate.onDestroy();
+
+        assertEquals(Mode.MODE_DESTROYED, mDelegate.getCurrentModeEnumForTests());
+        mTestEnvironment.assertIsNotListening();
+        mTestEnvironment.assertNoActiveTimeouts();
+        mTestEnvironment.assertUncertainResultReported();
+    }
+
+    @Test
+    public void onDestroy_afterStartedAndStopped() throws Exception {
+        // Prime the accountant with instructions.
+        ListeningInstruction activeInstruction = new ListeningInstruction(
+                LOCATION_LISTEN_MODE_ACTIVE, Duration.ofSeconds(15));
+        ListeningInstruction passiveInstruction = new ListeningInstruction(
+                LOCATION_LISTEN_MODE_PASSIVE, Duration.ofSeconds(25));
+        mTestLocationListeningAccountant.addInstruction(activeInstruction)
+                .addInstruction(passiveInstruction);
+
+        // Start of the test
+        assertEquals(Mode.MODE_STOPPED, mDelegate.getCurrentModeEnumForTests());
+        mTestEnvironment.assertIsNotListening();
+        mTestEnvironment.assertNoActiveTimeouts();
+        mTestEnvironment.assertNoResultReported();
+
+        final Duration initializationTimeout = Duration.ofSeconds(20);
+        mDelegate.onStartUpdates(initializationTimeout);
+
+        // The provider should have started an initialization timeout and followed the first
+        // instruction from the accountant.
+        FakeEnvironment.TestTimeoutState<?> initializationTimeoutState =
+                mTestEnvironment.getActiveTimeoutState(0);
+        initializationTimeoutState.assertDelay(initializationTimeout);
+        assertEquals(Mode.MODE_STARTED, mDelegate.getCurrentModeEnumForTests());
+        mTestEnvironment.assertIsLocationListening(
+                activeInstruction.listenMode, activeInstruction.duration);
+
+        mDelegate.onStopUpdates();
+        assertEquals(Mode.MODE_STOPPED, mDelegate.getCurrentModeEnumForTests());
+        mTestEnvironment.assertIsNotListening();
+        mTestEnvironment.assertNoActiveTimeouts();
+        mTestEnvironment.assertNoResultReported();
+
+        // Destroyed without first being stopped.
+        mDelegate.onDestroy();
+
+        assertEquals(Mode.MODE_DESTROYED, mDelegate.getCurrentModeEnumForTests());
+        mTestEnvironment.assertIsNotListening();
+        mTestEnvironment.assertNoActiveTimeouts();
+        mTestEnvironment.assertNoResultReported();
+    }
+
     private static class FakeEnvironment implements Environment {
 
         private final FakeGeoTimeZonesFinder mFakeGeoTimeZonesFinder = new FakeGeoTimeZonesFinder();
@@ -331,6 +422,12 @@
             return this;
         }
 
+        FakeEnvironment assertUncertainResultReported() {
+            assertNotNull(mLastResultReported);
+            assertEquals(RESULT_TYPE_UNCERTAIN, mLastResultReported.getType());
+            return this;
+        }
+
         FakeEnvironment simulateTimePassing(Duration duration) {
             mElapsedRealtimeMillis += duration.toMillis();
             return this;
@@ -483,8 +580,8 @@
                     return false;
                 }
                 FakeLocationToken that = (FakeLocationToken) o;
-                return Double.compare(that.mLngDegrees, mLngDegrees) == 0 &&
-                        Double.compare(that.mLatDegrees, mLatDegrees) == 0;
+                return Double.compare(that.mLngDegrees, mLngDegrees) == 0
+                        && Double.compare(that.mLatDegrees, mLatDegrees) == 0;
             }
 
             @Override
diff --git a/s2storage/src/readonly/java/com/android/timezone/location/storage/block/read/BlockInfo.java b/s2storage/src/readonly/java/com/android/timezone/location/storage/block/read/BlockInfo.java
index d43d46b..6c01994 100644
--- a/s2storage/src/readonly/java/com/android/timezone/location/storage/block/read/BlockInfo.java
+++ b/s2storage/src/readonly/java/com/android/timezone/location/storage/block/read/BlockInfo.java
@@ -132,4 +132,4 @@
             blockInfoVisitor.end();
         }
     }
-}
\ No newline at end of file
+}
diff --git a/s2storage/src/readonly/java/com/android/timezone/location/storage/io/read/TypedInputStream.java b/s2storage/src/readonly/java/com/android/timezone/location/storage/io/read/TypedInputStream.java
index 63c98e5..a4195e8 100644
--- a/s2storage/src/readonly/java/com/android/timezone/location/storage/io/read/TypedInputStream.java
+++ b/s2storage/src/readonly/java/com/android/timezone/location/storage/io/read/TypedInputStream.java
@@ -31,26 +31,26 @@
  */
 public final class TypedInputStream implements Closeable {
 
-    private final DataInputStream dis;
+    private final DataInputStream mDataInputStream;
 
     /** Wraps an InputStream. */
     public TypedInputStream(InputStream is) {
-        dis = new DataInputStream(new BufferedInputStream(is, 8192));
+        mDataInputStream = new DataInputStream(new BufferedInputStream(is, 8192));
     }
 
     /** Skip forward the specified number of bytes. */
     public int skipBytes(int n) throws IOException {
-        return dis.skipBytes(n);
+        return mDataInputStream.skipBytes(n);
     }
 
     /** Reads the next byte as an unsigned value. */
     public int readUnsignedByte() throws IOException {
-        return dis.readByte() & 0xFF;
+        return mDataInputStream.readByte() & 0xFF;
     }
 
     /** Reads the next byte as a signed value. */
     public byte readSignedByte() throws IOException {
-        return dis.readByte();
+        return mDataInputStream.readByte();
     }
 
     /**
@@ -61,7 +61,7 @@
         int arraySize = readUnsignedByte();
         byte[] bytes = new byte[arraySize];
         for (int i = 0; i < bytes.length; i++) {
-            bytes[i] = (byte) dis.readUnsignedByte();
+            bytes[i] = (byte) mDataInputStream.readUnsignedByte();
         }
         return bytes;
     }
@@ -73,7 +73,7 @@
         int arraySize = readUnsignedByte();
         char[] chars = new char[arraySize];
         for (int i = 0; i < chars.length; i++) {
-            chars[i] = dis.readChar();
+            chars[i] = mDataInputStream.readChar();
         }
         return chars;
     }
@@ -82,25 +82,25 @@
      * Reads a char in network byte order.
      */
     public char readChar() throws IOException {
-        return dis.readChar();
+        return mDataInputStream.readChar();
     }
 
     /**
      * Reads a signed int in network byte order.
      */
     public int readInt() throws IOException {
-        return dis.readInt();
+        return mDataInputStream.readInt();
     }
 
     /**
      * Reads a signed long in network byte order.
      */
     public long readLong() throws IOException {
-        return dis.readLong();
+        return mDataInputStream.readLong();
     }
 
     @Override
     public void close() throws IOException {
-        dis.close();
+        mDataInputStream.close();
     }
 }
diff --git a/s2storage/src/readonly/java/com/android/timezone/location/storage/s2/SortedS2Ranges.java b/s2storage/src/readonly/java/com/android/timezone/location/storage/s2/SortedS2Ranges.java
index 03f14c5..4fecc25 100644
--- a/s2storage/src/readonly/java/com/android/timezone/location/storage/s2/SortedS2Ranges.java
+++ b/s2storage/src/readonly/java/com/android/timezone/location/storage/s2/SortedS2Ranges.java
@@ -43,11 +43,23 @@
         mRanges = Collections.unmodifiableList(new ArrayList<>(ranges));
     }
 
+    /**
+     * Creates a {@link SortedS2Ranges} from a pre-sorted set of ranges with the same S2 level.
+     *
+     * @thorws IllegalArgumentException if the ranges are at different levels, ranges are not
+     *     sorted, or ranges overlap
+     */
     public static <T extends S2LevelRange> SortedS2Ranges<T> createFromSorted(
             int s2Level, T... ranges) {
         return createFromSorted(s2Level, Arrays.asList(ranges));
     }
 
+    /**
+     * Creates a {@link SortedS2Ranges} from a pre-sorted set of ranges with the same S2 level.
+     *
+     * @thorws IllegalArgumentException if the ranges are at different levels, ranges are not
+     *     sorted, or ranges overlap
+     */
     public static <T extends S2LevelRange> SortedS2Ranges<T> createFromSorted(
             int s2Level, List<T> ranges) {
         // Validate - look for overlapping ranges or ranges of the wrong level.
diff --git a/s2storage/src/readonly/java/com/android/timezone/location/storage/table/reader/Table.java b/s2storage/src/readonly/java/com/android/timezone/location/storage/table/reader/Table.java
index 6adf74d..6aa5fa1 100644
--- a/s2storage/src/readonly/java/com/android/timezone/location/storage/table/reader/Table.java
+++ b/s2storage/src/readonly/java/com/android/timezone/location/storage/table/reader/Table.java
@@ -45,7 +45,11 @@
     /** Returns the number of entries in the table. */
     int getEntryCount();
 
-    /** An entry in a {@link Table}. */
+    /**
+     * An entry in a {@link Table}.
+     *
+     * @param <T> the type of the entry
+     */
     interface TableEntry<T extends TableEntry<T>> {
 
         /** Returns the entry's index in the table. */
diff --git a/s2storage/src/readonly/java/com/android/timezone/location/storage/tzs2range/BankedTzIdSets.java b/s2storage/src/readonly/java/com/android/timezone/location/storage/tzs2range/BankedTzIdSets.java
index d92fccd..6046e36 100644
--- a/s2storage/src/readonly/java/com/android/timezone/location/storage/tzs2range/BankedTzIdSets.java
+++ b/s2storage/src/readonly/java/com/android/timezone/location/storage/tzs2range/BankedTzIdSets.java
@@ -172,6 +172,9 @@
             return mId;
         }
 
+        /**
+         * Returns the {@link TzIdSet} with the specified index.
+         */
         public TzIdSet getTzIdSet(int index) {
             return mTzIdSets.get(index);
         }
diff --git a/s2storage/src/readonly/java/com/android/timezone/location/storage/tzs2range/read/PopulatedSuffixTableBlock.java b/s2storage/src/readonly/java/com/android/timezone/location/storage/tzs2range/read/PopulatedSuffixTableBlock.java
index 2b719da..d701d83 100644
--- a/s2storage/src/readonly/java/com/android/timezone/location/storage/tzs2range/read/PopulatedSuffixTableBlock.java
+++ b/s2storage/src/readonly/java/com/android/timezone/location/storage/tzs2range/read/PopulatedSuffixTableBlock.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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.
+ */
+
 package com.android.timezone.location.storage.tzs2range.read;
 
 import static com.android.timezone.location.storage.s2.S2Support.MAX_FACE_ID;
@@ -108,7 +124,7 @@
 
         private final int mSuffixSearchValue;
 
-        public S2CellMatcher(TzS2RangeFileFormat fileFormat, int suffixSearchValue) {
+        S2CellMatcher(TzS2RangeFileFormat fileFormat, int suffixSearchValue) {
             mFileFormat = Objects.requireNonNull(fileFormat);
             mSuffixSearchValue = suffixSearchValue;
         }
@@ -138,7 +154,7 @@
 
         private final IntValueTable.TableEntry mSuffixTableEntry;
 
-        private SuffixTableRange suffixTableRange;
+        private SuffixTableRange mSuffixTableRange;
 
         Entry(IntValueTable.TableEntry suffixTableEntry) {
             mSuffixTableEntry = Objects.requireNonNull(suffixTableEntry);
@@ -159,7 +175,7 @@
         public SuffixTableRange getSuffixTableRange() {
             // Creating SuffixTableRange is relatively expensive so it is created lazily and
             // memoized.
-            if (suffixTableRange == null) {
+            if (mSuffixTableRange == null) {
                 // Create the range to return.
                 int startCellIdSuffix = mSuffixTableEntry.getKey();
                 checkStateInRange("startCellIdSuffixBits", startCellIdSuffix,
@@ -193,9 +209,9 @@
                 long endCellId = mFileFormat.createCellId(endCellPrefixValue, endCellIdSuffix);
 
                 int tzIdSetId = mFileFormat.extractTzIdSetIdFromTableEntryValue(value);
-                suffixTableRange = new SuffixTableRange(startCellId, endCellId, tzIdSetId);
+                mSuffixTableRange = new SuffixTableRange(startCellId, endCellId, tzIdSetId);
             }
-            return suffixTableRange;
+            return mSuffixTableRange;
         }
 
         @Override
diff --git a/s2storage/src/readonly/java/com/android/timezone/location/storage/tzs2range/read/SuffixTableBlock.java b/s2storage/src/readonly/java/com/android/timezone/location/storage/tzs2range/read/SuffixTableBlock.java
index af8e2c5..0a1bc30 100644
--- a/s2storage/src/readonly/java/com/android/timezone/location/storage/tzs2range/read/SuffixTableBlock.java
+++ b/s2storage/src/readonly/java/com/android/timezone/location/storage/tzs2range/read/SuffixTableBlock.java
@@ -190,7 +190,7 @@
      * An entry from the {@link SuffixTableBlock}. Use {@link #getSuffixTableRange()} to get the
      * full, interpreted entry data.
      */
-    public static abstract class Entry {
+    public abstract static class Entry {
 
         /** Returns the position of this entry in the table. */
         public abstract int getIndex();
diff --git a/s2storage/src/readonly/java/com/android/timezone/location/storage/tzs2range/read/UnpopulatedSuffixTableBlock.java b/s2storage/src/readonly/java/com/android/timezone/location/storage/tzs2range/read/UnpopulatedSuffixTableBlock.java
index 64b3e8e..ce3b168 100644
--- a/s2storage/src/readonly/java/com/android/timezone/location/storage/tzs2range/read/UnpopulatedSuffixTableBlock.java
+++ b/s2storage/src/readonly/java/com/android/timezone/location/storage/tzs2range/read/UnpopulatedSuffixTableBlock.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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.
+ */
+
 package com.android.timezone.location.storage.tzs2range.read;
 
 /**
diff --git a/s2storage/src/readonly/java/com/android/timezone/location/storage/util/BitwiseUtils.java b/s2storage/src/readonly/java/com/android/timezone/location/storage/util/BitwiseUtils.java
index 26a4162..549cde9 100644
--- a/s2storage/src/readonly/java/com/android/timezone/location/storage/util/BitwiseUtils.java
+++ b/s2storage/src/readonly/java/com/android/timezone/location/storage/util/BitwiseUtils.java
@@ -16,6 +16,7 @@
 
 package com.android.timezone.location.storage.util;
 
+/** Utility functions for bit twiddling. */
 public final class BitwiseUtils {
 
     // [0]  = ...00001
diff --git a/s2storage/src/test/java/com/android/timezone/location/storage/s2/S2CellOrderingTest.java b/s2storage/src/test/java/com/android/timezone/location/storage/s2/S2CellOrderingTest.java
index ca1e4ae..a470c47 100644
--- a/s2storage/src/test/java/com/android/timezone/location/storage/s2/S2CellOrderingTest.java
+++ b/s2storage/src/test/java/com/android/timezone/location/storage/s2/S2CellOrderingTest.java
@@ -18,6 +18,7 @@
 
 import static com.android.timezone.location.storage.s2.S2CellOrdering.asUnsignedNumeric;
 import static com.android.timezone.location.storage.s2.S2Support.MAX_FACE_ID;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
diff --git a/s2storage/src/test/java/com/android/timezone/location/storage/table/packed/PackedTableReaderWriterTest.java b/s2storage/src/test/java/com/android/timezone/location/storage/table/packed/PackedTableReaderWriterTest.java
index 0938f46..c73784d 100644
--- a/s2storage/src/test/java/com/android/timezone/location/storage/table/packed/PackedTableReaderWriterTest.java
+++ b/s2storage/src/test/java/com/android/timezone/location/storage/table/packed/PackedTableReaderWriterTest.java
@@ -541,4 +541,4 @@
     private static ByteBuffer createByteBuffer(byte[] bytes) {
         return ByteBuffer.wrap(bytes).asReadOnlyBuffer();
     }
-}
\ No newline at end of file
+}
diff --git a/s2storage/src/test/java/com/android/timezone/location/storage/testing/MoreAsserts.java b/s2storage/src/test/java/com/android/timezone/location/storage/testing/MoreAsserts.java
index cd71b5e..baf063d 100644
--- a/s2storage/src/test/java/com/android/timezone/location/storage/testing/MoreAsserts.java
+++ b/s2storage/src/test/java/com/android/timezone/location/storage/testing/MoreAsserts.java
@@ -40,13 +40,13 @@
                 Class<? extends Throwable> actualThrowable = actualThrown.getClass();
                 String actual = formatClass(actualThrowable);
 
-                String mismatchExceptionMessage = "Unexpected exception type thrown: " + actual +
-                        ", expected:" + expected;
+                String mismatchExceptionMessage = "Unexpected exception type thrown: " + actual
+                        + ", expected:" + expected;
                 throw new AssertionError(mismatchExceptionMessage, actualThrown);
             }
         }
-        String notThrownMessage = "Expected " +
-                formatClass(expectedThrowable) + " to be thrown, but nothing was thrown";
+        String notThrownMessage = "Expected " + formatClass(expectedThrowable)
+                + " to be thrown, but nothing was thrown";
         throw new AssertionError(notThrownMessage);
     }
 
diff --git a/s2storage/src/test/java/com/android/timezone/location/storage/tzs2range/write/BankedTzIdSetsPackerTest.java b/s2storage/src/test/java/com/android/timezone/location/storage/tzs2range/write/BankedTzIdSetsPackerTest.java
index 6b4a37a..1825336 100644
--- a/s2storage/src/test/java/com/android/timezone/location/storage/tzs2range/write/BankedTzIdSetsPackerTest.java
+++ b/s2storage/src/test/java/com/android/timezone/location/storage/tzs2range/write/BankedTzIdSetsPackerTest.java
@@ -72,39 +72,39 @@
     @Test
     public void overflowPacking() {
         BankedTzIdSetsPacker packer = new BankedTzIdSetsPacker(5);
-        List<List<String>> idSet1_1 = listOf(
+        List<List<String>> idSetA1 = listOf(
                 listOf("One"),
                 listOf("One", "Two"),
                 listOf("One", "Two", "Three"),
                 listOf("One", "Two", "Three", "Four"));
-        BankedTzIdSetsPacker.BankHelper bank1_1Helper = packer.addTzIdSets(idSet1_1);
-        assertEquals(0, bank1_1Helper.getId());
+        BankedTzIdSetsPacker.BankHelper bankA1Helper = packer.addTzIdSets(idSetA1);
+        assertEquals(0, bankA1Helper.getId());
 
-        List<List<String>> idSet1_2 = listOf(listOf("One", "Two", "Three", "Four", "Five"));
-        BankedTzIdSetsPacker.BankHelper bank1_2Helper = packer.addTzIdSets(idSet1_2);
-        assertEquals(0, bank1_2Helper.getId());
+        List<List<String>> idSetA2 = listOf(listOf("One", "Two", "Three", "Four", "Five"));
+        BankedTzIdSetsPacker.BankHelper bankA2Helper = packer.addTzIdSets(idSetA2);
+        assertEquals(0, bankA2Helper.getId());
 
-        BankedTzIdSetsPacker.BankHelper bank1_1Helper2 = packer.addTzIdSets(idSet1_1);
-        assertEquals(0, bank1_1Helper2.getId());
+        BankedTzIdSetsPacker.BankHelper bankA1Helper2 = packer.addTzIdSets(idSetA1);
+        assertEquals(0, bankA1Helper2.getId());
 
-        BankedTzIdSetsPacker.BankHelper bank1_2Helper2 = packer.addTzIdSets(idSet1_2);
-        assertEquals(0, bank1_2Helper2.getId());
+        BankedTzIdSetsPacker.BankHelper bankA2Helper2 = packer.addTzIdSets(idSetA2);
+        assertEquals(0, bankA2Helper2.getId());
 
-        List<List<String>> idSet2 = listOf(listOf("Two"));
-        BankedTzIdSetsPacker.BankHelper bank2Helper = packer.addTzIdSets(idSet2);
-        assertEquals(1, bank2Helper.getId());
+        List<List<String>> idSetB = listOf(listOf("Two"));
+        BankedTzIdSetsPacker.BankHelper bankBHelper = packer.addTzIdSets(idSetB);
+        assertEquals(1, bankBHelper.getId());
     }
 
     @Test
     public void exceedMaxBankSize() {
         BankedTzIdSetsPacker packer = new BankedTzIdSetsPacker(3);
-        // If the bank maxs is 3, four different sets cannot be stored.
-        List<List<String>> idSet1_1 = listOf(
+        // If the bank max size is 3, four different sets cannot be stored.
+        List<List<String>> idSet = listOf(
                 listOf("One"),
                 listOf("One", "Two"),
                 listOf("One", "Two", "Three"),
                 listOf("One", "Two", "Three", "Four"));
-        assertThrows(IllegalArgumentException.class, () -> packer.addTzIdSets(idSet1_1));
+        assertThrows(IllegalArgumentException.class, () -> packer.addTzIdSets(idSet));
     }
 
     @Test
diff --git a/s2storage/src/write/java/com/android/timezone/location/storage/io/write/TypedOutputStream.java b/s2storage/src/write/java/com/android/timezone/location/storage/io/write/TypedOutputStream.java
index a57bb7a..36e658c 100644
--- a/s2storage/src/write/java/com/android/timezone/location/storage/io/write/TypedOutputStream.java
+++ b/s2storage/src/write/java/com/android/timezone/location/storage/io/write/TypedOutputStream.java
@@ -32,11 +32,11 @@
  */
 public final class TypedOutputStream implements Flushable, Closeable {
 
-    private final DataOutputStream dos;
+    private final DataOutputStream mDataOutputStream;
 
     /** Creates an instance, wrapping the supplied stream. */
     public TypedOutputStream(OutputStream out) {
-        dos = new DataOutputStream(new BufferedOutputStream(out, 8192));
+        mDataOutputStream = new DataOutputStream(new BufferedOutputStream(out, 8192));
     }
 
     /**
@@ -61,7 +61,7 @@
         // Write the high bytes first.
         for (int i = byteCount - 1; i >= 0; i--) {
             byte b = (byte) (value >>> (i * 8));
-            dos.write(b);
+            mDataOutputStream.write(b);
         }
     }
 
@@ -73,7 +73,7 @@
         if (unsignedValue < 0 || unsignedValue > 255) {
             throw new IllegalArgumentException("unsignedValue=" + unsignedValue + " is negative");
         }
-        dos.writeByte(unsignedValue);
+        mDataOutputStream.writeByte(unsignedValue);
     }
 
     /**
@@ -82,21 +82,21 @@
      */
     public void writeByte(int b) throws IOException {
         BitwiseUtils.checkSignedValueInRange(Byte.SIZE, b);
-        dos.writeByte(b);
+        mDataOutputStream.writeByte(b);
     }
 
     /**
      * Writes {@code bytes}.
      */
     public void writeBytes(byte[] bytes) throws IOException {
-        dos.write(bytes);
+        mDataOutputStream.write(bytes);
     }
 
     /**
      * Writes {@code len} {@code bytes} starting at {@code off}.
      */
     public void writeBytes(byte[] bytes, int off, int len) throws IOException {
-        dos.write(bytes, off, len);
+        mDataOutputStream.write(bytes, off, len);
     }
 
     /**
@@ -104,7 +104,7 @@
      */
     public void writeTinyByteArray(byte[] bytes) throws IOException {
         writeUnsignedByte(bytes.length);
-        dos.write(bytes);
+        mDataOutputStream.write(bytes);
     }
 
     /**
@@ -113,7 +113,7 @@
     public void writeTinyCharArray(char[] chars) throws IOException {
         writeUnsignedByte(chars.length);
         for (int i = 0; i < chars.length; i++) {
-            dos.writeChar(chars[i]);
+            mDataOutputStream.writeChar(chars[i]);
         }
     }
 
@@ -123,30 +123,30 @@
      */
     public void writeChar(int v) throws IOException {
         BitwiseUtils.checkUnsignedValueInRange(Character.SIZE, v);
-        dos.writeChar(v);
+        mDataOutputStream.writeChar(v);
     }
 
     /**
      * Writes {@code v} as an 32-bit value in network byte order.
      */
     public void writeInt(int v) throws IOException {
-        dos.writeInt(v);
+        mDataOutputStream.writeInt(v);
     }
 
     /**
      * Writes {@code v} as an 64-bit value in network byte order.
      */
     public void writeLong(long v) throws IOException {
-        dos.writeLong(v);
+        mDataOutputStream.writeLong(v);
     }
 
     @Override
     public void close() throws IOException {
-        dos.close();
+        mDataOutputStream.close();
     }
 
     @Override
     public void flush() throws IOException {
-        dos.flush();
+        mDataOutputStream.flush();
     }
 }
diff --git a/s2storage/src/write/java/com/android/timezone/location/storage/tzs2range/write/BankedTzIdSetsPacker.java b/s2storage/src/write/java/com/android/timezone/location/storage/tzs2range/write/BankedTzIdSetsPacker.java
index c495cc3..e4a7666 100644
--- a/s2storage/src/write/java/com/android/timezone/location/storage/tzs2range/write/BankedTzIdSetsPacker.java
+++ b/s2storage/src/write/java/com/android/timezone/location/storage/tzs2range/write/BankedTzIdSetsPacker.java
@@ -166,7 +166,7 @@
             return uniqueTzIdIntSet;
         }
 
-        public int getTzIdSetId(List<String> tzIdStringSet) {
+        int getTzIdSetId(List<String> tzIdStringSet) {
             List<Integer> tzIdIntSet = getStringIdList(tzIdStringSet);
             Integer setId = mSetToSetId.get(tzIdIntSet);
             if (setId == null) {
diff --git a/s2storage/src/write/java/com/android/timezone/location/storage/tzs2range/write/PushBackIterator.java b/s2storage/src/write/java/com/android/timezone/location/storage/tzs2range/write/PushBackIterator.java
index 2b2aa44..122cab4 100644
--- a/s2storage/src/write/java/com/android/timezone/location/storage/tzs2range/write/PushBackIterator.java
+++ b/s2storage/src/write/java/com/android/timezone/location/storage/tzs2range/write/PushBackIterator.java
@@ -19,7 +19,11 @@
 import java.util.ArrayList;
 import java.util.Iterator;
 
-/** An iterator that can have elements pushed back onto it. {@link #remove()} is not supported. */
+/**
+ * An iterator that can have elements pushed back onto it. {@link #remove()} is not supported.
+ *
+ * @param <E> The type of the element returned by this iterator
+ */
 public final class PushBackIterator<E> implements Iterator<E> {
 
     private final ArrayList<E> mPushBackStack = new ArrayList<>();
diff --git a/s2storage/tools/src/java/com/android/timezone/location/tools/CreateTestFile.java b/s2storage/tools/src/java/com/android/timezone/location/tools/CreateTestFile.java
index f48bf15..6a4200e 100644
--- a/s2storage/tools/src/java/com/android/timezone/location/tools/CreateTestFile.java
+++ b/s2storage/tools/src/java/com/android/timezone/location/tools/CreateTestFile.java
@@ -27,7 +27,7 @@
 /** Creates a TZ S2 file with a small amount of test data. Useful for testing other tools. */
 public final class CreateTestFile {
 
-    /*
+    /**
      * Usage:
      * CreateTestFile <file name>
      */
diff --git a/s2storage/tools/src/java/com/android/timezone/location/tools/CreateTzS2File.java b/s2storage/tools/src/java/com/android/timezone/location/tools/CreateTzS2File.java
index df33259..7ba49b8 100644
--- a/s2storage/tools/src/java/com/android/timezone/location/tools/CreateTzS2File.java
+++ b/s2storage/tools/src/java/com/android/timezone/location/tools/CreateTzS2File.java
@@ -42,22 +42,22 @@
                 description = "Proto file",
                 required = true,
                 converter = FileConverter.class)
-        File inputFile;
+        public File inputFile;
 
         @Parameter(names = "--s2-level",
                 description = "s2 level of input data",
                 required = true)
-        int s2Level;
+        public int s2Level;
 
         @Parameter(names = "--output-file",
                 description = "tz s2 file",
                 required = true,
                 converter = FileConverter.class)
-        File outputFile;
+        public File outputFile;
 
     }
 
-    /*
+    /**
      * Usage:
      * CreateTzS2File <[input] proto file> <[input] s2 level of input data> <[output] tz s2 file>
      *
diff --git a/s2storage/tools/src/java/com/android/timezone/location/tools/DumpBlockFile.java b/s2storage/tools/src/java/com/android/timezone/location/tools/DumpBlockFile.java
index 8889b13..a4781a2 100644
--- a/s2storage/tools/src/java/com/android/timezone/location/tools/DumpBlockFile.java
+++ b/s2storage/tools/src/java/com/android/timezone/location/tools/DumpBlockFile.java
@@ -24,7 +24,7 @@
 /** Dumps low-level information about a block file in text form for debugging / analysis. */
 public final class DumpBlockFile {
 
-    /*
+    /**
      * Usage:
      * DumpBlockFile <[input] block file name> <[output] directory name>
      */
diff --git a/s2storage/tools/src/java/com/android/timezone/location/tools/DumpTzS2File.java b/s2storage/tools/src/java/com/android/timezone/location/tools/DumpTzS2File.java
index 5724058..2f71b9a 100644
--- a/s2storage/tools/src/java/com/android/timezone/location/tools/DumpTzS2File.java
+++ b/s2storage/tools/src/java/com/android/timezone/location/tools/DumpTzS2File.java
@@ -16,8 +16,8 @@
 
 package com.android.timezone.location.tools;
 
-import com.android.timezone.location.tools.dump.TzS2RangeFileDumper;
 import com.android.timezone.location.storage.tzs2range.read.TzS2RangeFileReader;
+import com.android.timezone.location.tools.dump.TzS2RangeFileDumper;
 
 import java.io.File;
 
@@ -27,7 +27,7 @@
  */
 public final class DumpTzS2File {
 
-    /*
+    /**
      * Usage:
      * DumpTzS2File <[input] tz s2 file name> <[output] output directory name>
      */
diff --git a/s2storage/tools/src/java/com/android/timezone/location/tools/FileFormats.java b/s2storage/tools/src/java/com/android/timezone/location/tools/FileFormats.java
index 3ccb75e..52105ad 100644
--- a/s2storage/tools/src/java/com/android/timezone/location/tools/FileFormats.java
+++ b/s2storage/tools/src/java/com/android/timezone/location/tools/FileFormats.java
@@ -19,18 +19,19 @@
 import com.android.timezone.location.storage.tzs2range.TzS2RangeFileFormat;
 
 /** Some sample file formats. */
-public final class FileFormats {
+final class FileFormats {
 
-    private final static TzS2RangeFileFormat FILE_FORMAT_12 =
+    private static final TzS2RangeFileFormat FILE_FORMAT_12 =
             new TzS2RangeFileFormat(12, 11, 16, 1, 32, 11);
 
-    private final static TzS2RangeFileFormat FILE_FORMAT_14 =
+    private static final TzS2RangeFileFormat FILE_FORMAT_14 =
             new TzS2RangeFileFormat(14, 13, 18, 1, 32, 12);
 
-    private final static TzS2RangeFileFormat FILE_FORMAT_16 =
+    private static final TzS2RangeFileFormat FILE_FORMAT_16 =
             new TzS2RangeFileFormat(16, 13, 22, 1, 40, 12);
 
-    public static TzS2RangeFileFormat getFileFormatForLevel(int s2Level) {
+    /** Maps an S2 level to one of the file format constants declared on by class. */
+    static TzS2RangeFileFormat getFileFormatForLevel(int s2Level) {
         switch (s2Level) {
             case 12:
                 return FILE_FORMAT_12;
diff --git a/s2storage/tools/src/java/com/android/timezone/location/tools/dump/BlockDumper.java b/s2storage/tools/src/java/com/android/timezone/location/tools/dump/BlockDumper.java
index 423039c..52f83dd 100644
--- a/s2storage/tools/src/java/com/android/timezone/location/tools/dump/BlockDumper.java
+++ b/s2storage/tools/src/java/com/android/timezone/location/tools/dump/BlockDumper.java
@@ -33,4 +33,4 @@
         println("type=" + block.getType());
         println("block size=" + block.getData().getSize());
     }
-}
\ No newline at end of file
+}
diff --git a/s2storage/tools/src/java/com/android/timezone/location/tools/dump/BlockInfoDumper.java b/s2storage/tools/src/java/com/android/timezone/location/tools/dump/BlockInfoDumper.java
index 66400d5..14ff02b 100644
--- a/s2storage/tools/src/java/com/android/timezone/location/tools/dump/BlockInfoDumper.java
+++ b/s2storage/tools/src/java/com/android/timezone/location/tools/dump/BlockInfoDumper.java
@@ -28,6 +28,7 @@
         super(file);
     }
 
+    @Override
     public void visit(BlockInfo blockInfo) throws VisitException {
         println("id=" + blockInfo.getId());
         println("type=" + blockInfo.getType());
@@ -35,4 +36,4 @@
         println("blockStateByteOffset=" + blockInfo.getBlockStartByteOffset());
         println("blockSizeBytes=" + blockInfo.getBlockSizeBytes());
     }
-}
\ No newline at end of file
+}
diff --git a/s2storage/tools/src/java/com/android/timezone/location/tools/dump/DumpUtils.java b/s2storage/tools/src/java/com/android/timezone/location/tools/dump/DumpUtils.java
index b8a1a4e..94a9ca1 100644
--- a/s2storage/tools/src/java/com/android/timezone/location/tools/dump/DumpUtils.java
+++ b/s2storage/tools/src/java/com/android/timezone/location/tools/dump/DumpUtils.java
@@ -26,12 +26,12 @@
 import java.nio.charset.StandardCharsets;
 
 /** Helper methods for dumping data to files. */
-public final class DumpUtils {
+final class DumpUtils {
 
     private DumpUtils() {
     }
 
-    public static PrintWriter createPrintWriter(File file) throws Visitor.VisitException {
+    static PrintWriter createPrintWriter(File file) throws Visitor.VisitException {
         try {
             OutputStreamWriter utf8Writer = new OutputStreamWriter(
                     new FileOutputStream(file), StandardCharsets.UTF_8);
@@ -41,7 +41,7 @@
         }
     }
 
-    public static File generateDumpFile(File dir, String filePrefix, int blockId, int maxBlockId) {
+    static File generateDumpFile(File dir, String filePrefix, int blockId, int maxBlockId) {
         final String fileSuffix = ".txt";
 
         int blockIdLength = hexStringLength(maxBlockId);
@@ -55,16 +55,16 @@
         return new File(dir, sb.toString());
     }
 
-    public static int hexStringLength(int value) {
+    static int hexStringLength(int value) {
         int bitsNeeded = Integer.SIZE - Integer.numberOfLeadingZeros(value);
         return (bitsNeeded + 3) / 4;
     }
 
-    public static int binaryStringLength(int value) {
+    static int binaryStringLength(int value) {
         return Integer.SIZE - Integer.numberOfLeadingZeros(value);
     }
 
-    public static String zeroPadHex(int length, int value) {
+    static String zeroPadHex(int length, int value) {
         String hexString = Integer.toHexString(value);
         int unpaddedLength = hexString.length();
         if (unpaddedLength >= length) {
@@ -73,7 +73,7 @@
         return zeroPad(length, hexString);
     }
 
-    public static String zeroPadBinary(int length, int value) {
+    static String zeroPadBinary(int length, int value) {
         String binaryString = Integer.toBinaryString(value);
         int unpaddedLength = binaryString.length();
         if (unpaddedLength >= length) {
@@ -91,4 +91,4 @@
         sb.append(unpaddedValue);
         return sb.toString();
     }
-}
\ No newline at end of file
+}
diff --git a/s2storage/tools/src/java/com/android/timezone/location/tools/dump/HeaderBlockDumper.java b/s2storage/tools/src/java/com/android/timezone/location/tools/dump/HeaderBlockDumper.java
index 8c7e50e..299e593 100644
--- a/s2storage/tools/src/java/com/android/timezone/location/tools/dump/HeaderBlockDumper.java
+++ b/s2storage/tools/src/java/com/android/timezone/location/tools/dump/HeaderBlockDumper.java
@@ -26,7 +26,7 @@
 /** A {@link HeaderBlock.HeaderBlockVisitor} that dumps information to a file. */
 class HeaderBlockDumper extends SingleFileDumper implements HeaderBlock.HeaderBlockVisitor {
 
-    public HeaderBlockDumper(File headerBlockFile) {
+    HeaderBlockDumper(File headerBlockFile) {
         super(headerBlockFile);
     }
 
@@ -64,4 +64,4 @@
         }
         println();
     }
-}
\ No newline at end of file
+}
diff --git a/s2storage/tools/src/java/com/android/timezone/location/tools/dump/SuffixTableBlockDumper.java b/s2storage/tools/src/java/com/android/timezone/location/tools/dump/SuffixTableBlockDumper.java
index 4ef08e5..a4028d8 100644
--- a/s2storage/tools/src/java/com/android/timezone/location/tools/dump/SuffixTableBlockDumper.java
+++ b/s2storage/tools/src/java/com/android/timezone/location/tools/dump/SuffixTableBlockDumper.java
@@ -63,4 +63,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/s2storage/tools/src/java/com/android/timezone/location/tools/dump/TzS2RangeFileDumper.java b/s2storage/tools/src/java/com/android/timezone/location/tools/dump/TzS2RangeFileDumper.java
index 48b2713..ad04557 100644
--- a/s2storage/tools/src/java/com/android/timezone/location/tools/dump/TzS2RangeFileDumper.java
+++ b/s2storage/tools/src/java/com/android/timezone/location/tools/dump/TzS2RangeFileDumper.java
@@ -30,6 +30,7 @@
 
 import java.io.File;
 
+/** A {@link TzS2RangeFileReader.TzS2RangeFileVisitor} that dumps information to a file. */
 public final class TzS2RangeFileDumper implements TzS2RangeFileReader.TzS2RangeFileVisitor {
 
     private final File mOutputDir;
diff --git a/validation/geonames/src/main/java/com/android/timezone/location/validation/GeonamesComparison.java b/validation/geonames/src/main/java/com/android/timezone/location/validation/GeonamesComparison.java
index 1caf670..323cd84 100644
--- a/validation/geonames/src/main/java/com/android/timezone/location/validation/GeonamesComparison.java
+++ b/validation/geonames/src/main/java/com/android/timezone/location/validation/GeonamesComparison.java
@@ -25,6 +25,7 @@
 import com.android.timezone.location.validation.Types.Result;
 import com.android.timezone.location.validation.Types.TestCaseId;
 import com.android.timezone.tzids.TimeZoneIds;
+
 import com.google.common.geometry.S2CellId;
 import com.google.common.geometry.S2LatLng;
 
@@ -191,12 +192,12 @@
 
     static class KnownDifferencesRegistry {
 
-        Map<TestCaseId, KnownDifference> knownDifferences = new HashMap<>();
-        Map<TestCaseId, Types.KnownDifference> mutableKnownDifferencesMap = new HashMap<>();
-        List<Types.KnownDifference> newKnownDifferences = new ArrayList<>();
-        List<Types.KnownDifference> confirmedKnownDifferences = new ArrayList<>();
-        List<KnownDifferenceMismatch> incorrectKnownDifferences = new ArrayList<>();
-        List<CityResult> multipleIdAndroidResults = new ArrayList<>();
+        public Map<TestCaseId, KnownDifference> knownDifferences = new HashMap<>();
+        public Map<TestCaseId, Types.KnownDifference> mutableKnownDifferencesMap = new HashMap<>();
+        public List<Types.KnownDifference> newKnownDifferences = new ArrayList<>();
+        public List<Types.KnownDifference> confirmedKnownDifferences = new ArrayList<>();
+        public List<KnownDifferenceMismatch> incorrectKnownDifferences = new ArrayList<>();
+        public List<CityResult> multipleIdAndroidResults = new ArrayList<>();
 
         void addKnownDifferences(File knownDifferencesFile) throws IOException {
             Map<TestCaseId, KnownDifference> knownDifferencesMap =
diff --git a/validation/geonames/src/main/java/com/android/timezone/location/validation/Types.java b/validation/geonames/src/main/java/com/android/timezone/location/validation/Types.java
index 17c3d1f..552c1b9 100644
--- a/validation/geonames/src/main/java/com/android/timezone/location/validation/Types.java
+++ b/validation/geonames/src/main/java/com/android/timezone/location/validation/Types.java
@@ -20,6 +20,7 @@
 import static java.util.stream.Collectors.toMap;
 
 import com.android.timezone.location.validation.proto.ValidationProtos;
+
 import com.google.common.geometry.S2CellId;
 import com.google.protobuf.Message;
 import com.google.protobuf.TextFormat;
@@ -130,8 +131,8 @@
                 return false;
             }
             TestCaseId that = (TestCaseId) o;
-            return mCityName.equals(that.mCityName) &&
-                    mCellId.equals(that.mCellId);
+            return mCityName.equals(that.mCityName)
+                    && mCellId.equals(that.mCellId);
         }
 
         @Override
@@ -141,10 +142,10 @@
 
         @Override
         public String toString() {
-            return "TestCaseId{" +
-                    "mCityName='" + mCityName + '\'' +
-                    ", mCellId=" + mCellId +
-                    '}';
+            return "TestCaseId{"
+                    + "mCityName='" + mCityName + '\''
+                    + ", mCellId=" + mCellId
+                    + '}';
         }
     }