Add OfflineLocationTimeZoneProvider app support

Add support for deploying OfflineLocationTimeZoneProvider in a
standalone app (defined in app/). This is for partners that have
expressed an interest in how to deploy the LTZP as an app.

Various changes:

This commit adds support to EnvironmentImpl for custom data file
management code. The app version copies the geodata resource from the
APK to the app's permanent file dir to enable the data access code to
have access via a Java File object (assumed by the current impl, because
the data is memory mapped, which requires us to use File without
dropping to native). The data file copy is SHA256 hashed to check it
matches expectations when the service is first connected to. This wasn't
required for an APEX deployment because the location of the file in the
APEX is a well-defined / well-known absolute path.

Things for deployers to consider:

NOTE 1: The use of Guava and SHA256 for the hashing to confirm the
geodata copy is up-to-date (i.e. if an app has been updated) and not
corrupt looks quite heavyweight (though Guava is used lower down too,
and proguard will help reduce the binary size), but the hashing is
potentially more costly at startup than simply copying the resource each
time.  Consider this approach to be an example, not complete - a
production implementation might want an alternative impl. For example,
if the file were STORED in the APK (i.e. not compressed), it might be
possible to memory map it in place.

NOTE 2: If this example were to be submitted, then a way to keep the
SHA256 value up to date (or generated at build time) in the
app/resources/offlineltzprovider.properties file would be highly
desirable to avoid needing to update it by hand when tzs2.dat is
regenerated. The value given was calculated using the sha256sum Linux
command.

NOTE 3: Running the LTZP outside of the system server process, the LTZP
needs various permissions. There are location permissions that have to
be explicitly granted even after the app requests them.

e.g.
adb shell pm grant com.android.timezone.location.provider \
    android.permission.ACCESS_FINE_LOCATION

I'm not sure if it's possible to bypass this for system priv-apps or
whether the app would have to prompt the user with a UI (which seems
undesirable to me for a core piece of platform behavior the user already
has to explicitly turn on via SettingsUI). The GmsCore LTZP doesn't have
to request permission for its use of location providers, which suggests
it is possible to avoid prompting the user for some apps and/or partners
building images, but more research would be needed. Additionally, there
were a number of changes in S around location behavior and permissions,
and obtaining location from non-foreground apps may be more difficult
now and restrict how effective an app-based deployment using basic SDK
APIs can be.

NOTE 4: Running (just) the LTZP in an app by itself is quite
heavyweight, since the service is started at boot time and expected to
always be running.  Ideally, the LTZP would be deployed in an app that
has to run at all times anyway for other reasons (e.g. like GmsCore
does).  System health testing is strongly advised. Some Android devices
are known to aggressively kill services occasionally too, so testing
over long periods to ensure correct functioning would also be
recommended.

NOTE 5: Although I don't remember the AOSP / Android SDK location
provider APIs being explicit about power behavior, the
OfflineLocationTimeZoneProvider implementation is, in reality, quite
"passive" about obtaining location.  It distinguishes between "passive"
and "active" modes of operation, but I've found "active" to still be
relatively low-power, i.e. I've never seen it power up the GNSS
hardware. I remember it would use network location provider when I last
tried it (which needs WiFi to be connected). Being quite passive means
that if nothing else on the device is requesting location for other
reasons, the reference LTZP doesn't work well. A production
implementation would likely have to be more active / aggressive, perhaps
with power usage implications.  The choice of what is actually done in
the "active" mode is deliberately split out into the EnvironmentImpl
class: it was designed so that developers could implement their own
Environment class instead but keep the geo data and state machine code
from the reference impl. Clearly there's a trade-off of responsiveness
Vs power usage. For Android devices with different power profiles than
mobile devices that don't want to rely on passive location signals,
using active GNSS when no passive signal has arrived would be desirable.
Devices with extended APIs available, such as those with GmsCore and
GAS, have access to additional location APIs and facilities like
geo-fencers that would potentially enable different approaches than a
basic listen + poll approach currently implemented.

NOTE 6: To monitor behavior of the LTZP, use:

; # system server logs
adb shell dumpsys location_time_zone_manager

; # app-side logs
adb shell dumpsys activity service \
    com.android.timezone.location.provider

Plus logcat as usual.

NOTE 7: Service is marked as multi-user := false in the
AndroidManifest.xml.

This is different from deployment inside the system server, since the
system server runs once on a device and the LTZP is always running.
Outside of the system server, the apps/service must be spun up when the
current user changes. Multi-user testing has not been done by me for
this demo, so there may be issues to find. Access to location is a
per-user permission / has per-user settings, so multi-user must be
considered before any production deployment.

NOTE 8: Users could potentially disable the app hosting the LTZP,
breaking location-based time zone detection. There are ways to prevent
the disable function (as I believe are done for critical system apps
like GmsCore, but more research would be needed on this).

NOTE 9: The other points mentioned on the public facing Android docs
should be considered, e.g. the update strategy to ensure that the geo
data is updated to deal with time zone boundary changes, plus TZDB
updates (or lack thereof) on devices that could lead to geodata
referencing time zone Olson IDs that are not known to the device. This
is less of an issue on Android form factors that rely on complete system
image updates to refresh their system apps and time zone data
atomically.

Bug: 231906346
Test: None - example only, treehugger only
Change-Id: If131662aa6c84f8d432c8baf65e9edb4745619c2
13 files changed
tree: 1cdab1344f66106561c5d05e0c180d3af6016947
  1. apex/
  2. app/
  3. common/
  4. data_pipeline/
  5. geotz_lookup/
  6. locationtzprovider/
  7. output_data/
  8. s2storage/
  9. tzbb_data/
  10. validation/
  11. download-tzbb-files.sh
  12. OWNERS
  13. README.md
  14. run-data-pipeline.sh
README.md

This directory contains code, tools and data for the AOSP reference location time zone provider. Location time zone providers are used for location-based time zone detection on Android. See Android's android.service.timezone.TimeZoneProviderService class for more details.

Directory structure

apex

  • Files associated with a proposed mainline module APEX to hold the AOSP reference location time zone provider.

common

  • Utility code shared between several subdirectories.

data_pipeline

  • Code for a host sample / reference data generation pipeline. See run-data-pipeline.sh below.

geotz_lookup

  • A high-level API for performing time zone ID lookups for a location using the tzs2.dat file. Supports host and device usage.

locationtzprovider

  • A reference location time zone provider that uses AOSP APIs to obtain location and the geotz_lookup APIs to obtain the time zone IDs to pass to the platform.

output_data

  • Holds the tzs2.dat file generated by run-data-pipeline.sh along with the associated license files.

s2storage

  • File reading / writing code and tools to support tzs2.dat generation on host, and the file's use on host and device. See s2storage/README.md for format details.

tzbb_data

  • Data / licenses from the external timezone-boundary-builder project. Used as input for the reference data generation pipeline.

validation

  • Tooling to help validate the tzs2.dat file against other data sources.

Data file update tools

download-tzbb-files.sh

run-data-pipeline.sh

  • Runs the data_pipeline data generation pipeline. It takes data from tzbb_data/, processes it, and puts the resulting tzs2.dat file in output_data/.