Exposure Notifications telemetry design

Telemetry data is collected about the performance of the Exposure Notifications framework from devices that have opted into Exposure Notifications. The telemetry data is used to verify that basic functionality is working and to provide an early warning signal about any technical issues. This data does not include any user-identifying information. Details about the de-identification are in the section below. More details about the use of telemetry functionality in the Exposure Notifications framework are provided in Google Play services snippets.

De-identified logging

Exposure Notifications framework logging uses Google's de-identified logger for Android. All EN log messages are de-identified on device before being uploaded to Google in such a way that no identifiers are persistently associated with the log message. This logging system explicitly breaks any link between log messages from the same device. Identifiers such as IP addresses, which are necessary to deliver the log message, are not logged to disk in this logging pipeline. The logging pipeline includes some metadata about the device model and operating system build and is used only to assist with diagnosing bugs in the Exposure Notifications framework that affect specific configurations. Users can disable this de-identified logging through Android's usage and diagnostics settings.

Note on general Android platform telemetry

Independently of whether Exposure Notifications are enabled or a public healthcare authority app is installed, Google Android devices collect general telemetry data about the operation of the Android platform and to keep the platform safe and secure. For more information about this and the controls Android offers over its collection refer to the following documentation:

  • Android platform usage and diagnostics data, collected if the Usage & Diagnostics setting is enabled. A user can choose to disable this collection at any time, which reduces data sent to Google.
  • Android Device Configuration Service data collected to ensure that devices remain up-to-date and functional.
  • Critical debugging, security, and anti-abuse data about the core functionality of Android. See Google's privacy policy for more information.

Exposure Notifications Express app usage and performance data

As with Exposure Notifications, EN Express operates without Google collecting any personally-identifiable information or information about a user's health status. We collect only de-identified analytics data to ensure that the public health authority app is working properly and to improve the system.

Before being uploaded to Google, EN Express log messages are de-identified on the device in such a way that no identifiers are persistently associated with the log message. EN Express apps log data only if the user has enabled the App usage & performance sharing toggle in the app. Users can turn off this setting at any time through the settings in the app.

De-identified data logged by Exposure Notifications

Field Public Reporting String
TimeWindow.epoch_start_seconds Approximate (roughly 30 min) time a log window starts collecting data, used to ensure log integrity and to provide a rough timestamp.
TimeWindow.duration_seconds Period of time (at least 4 hour) during which all logged values are grouped. This data describes the system behavior during that period.
sampling_rate Android doesn't upload every event from every device. This parameter specifies a fraction of events that are uploaded, which helps calculate the estimated number of active users and also helps ensure data integrity.
User_type (prod, modulefood, test) Describes where a log comes from. Public data is labeled "prod" for production.
ScanTimeDeltaHistogram.total_number_of_scans Total number of attempted scans in a TimeWindow, used to verify that the system is performing scans even if no devices are detected.
ScanTimeDeltaHistogram.histogram_bins A way to track time between scans, in minutes. For example, if total_number_of_scans is 26, a histogram might show
0 - 4: 3
5 - 9: 20
10 - 14: 1
15 - 9999: 1
Scans run about every 5 minutes. Capturing the timing of scans in histograms helps us improve the scheduling algorithm, such as to avoid scanning too frequently and draining a device's battery.
The scan schedule can vary on Android.
ScanTimeHistogram A way to track scan durations, in milliseconds. For example:
0 - 500: 1
501 - 1000: 4
1001 - 1500: 9
Scans run for about 4 seconds and, when captured in histograms, help us to understand problems with individual devices, chipsets, and software versions.
These times can vary on Android and using Bluetooth.
random_scan_empty Indicates whether at least one event is detected in a randomly-chosen scan in a given time window. Used to identify devices that may not provide high-quality results, and, in aggregate, to monitor system performance and detect regressions.
random_sighting_rssi RSSI of a single randomly-chosen event within the TimeWindow. This data helps us understand problems with Bluetooth radios in specific devices or software versions.
ScanFailedCount.error_code_count Errors that arise when scans fail, such as when Bluetooth is not available or is in a bad state, and help us diagnose problems with Bluetooth radios in specific devices or software versions.
UserAction.event_type (UNKNOWN_EVENT_TYPE, START_TRACING, STOP_TRACING, APP_WHITELIST_ERROR, BLUETOOTH_NOTIFICATION_CLICK, BLUETOOTH_NOTIFICATION_DISMISS, LOCATION_NOTIFICATION_CLICK, LOCATION_NOTIFICATION_DISMISS, BLUETOOTH_LOCATION_NOTIFICATION_ACTION, BLUETOOTH_LOCATION_NOTIFICATION_DISMISS, EN_FIRST_LAUNCH, PLAY_FLOW_IS_ENABLED_FOR_PACKAGE, PLAY_FLOW_START_FOR_PACKAGE, BLUETOOTH_NOTIFICATION_SHOW, LOCATION_NOTIFICATION_SHOW, BLUETOOTH_LOCATION_NOTIFICATION_SHOW, BLUETOOTH_ENABLED_AFTER_NOTIFICATION, LOCATION_ENABLED_AFTER_NOTIFICATION, BT_LOCATION_ENABLED_AFTER_NOTIFICATION, PROMO_NOTIFICATION_IMPRESSION_FLP, PROMO_NOTIFICATION_IMPRESSION_IPGEO, PROMO_ACTIVITY_IMPRESSION, PROMO_NOTIFICATION_DISMISSED, PROMO_ACTIVITY_DISMISSED, PROMO_CONTINUED, PROMO_INSTALLED) Helps us understand user interactions with the Exposure Notifications UI at a high level, such as interactions with notifications. It also provides info about APIs, such as their state (such as abnormal starting and stopping) and whether they were enabled from the Play Store.
BleAdvertisingStats.is_multiple_advertisement_supported Indicator that a device does not support sending multiple advertisements at the same time, which can lead to the Exposure Notifications framework's advertisements being blocked by another app on the device in some cases. This data is collected to estimate the prevalence of devices that can get into this state.
AdvertiseFailedCount.error_code_count Errors that arise when Bluetooth advertisements fail, such as when Bluetooth isn't available or is in a bad state.
calling_package_names Package name of the application using the Exposure Notifications API. Helps ensure consistent results across different Healthcare Authority (HA) apps and diagnose when an error is caused by a bug in an HA app.
flag_values (enabled, contact_id_length, scan_mode, scan_time_seconds, scan_interval_seconds, scan_interval_random_range_seconds, require_multi_advertisement, (ble) advertise_mode, (ble) advertise_tx_power, (ble) advertise_connectable, wake_up_for_ble_executor, id_rotation_period_seconds, id_rotation_period_random_range_seconds, reschedule_start_scan_min_interval_ms, id_rolling_period_minutes, tk_rolling_period_multiple_of_id_rolling_period, temporary_tracing_key_size_bytes, data_quality_log_period_minutes, rolling_proximity_id_key_size_bytes, associated_metadata_encryption_key_size_bytes, min_exposure_bucketized_duration_seconds, max_interpolation_duration_seconds, default_min_exposure_attenuation_value, ble_scheduler_use_scheduled_executor_max_delay_ms, timestamp_noise_minutes, upload_period_minutes, risk_score_bucketed_transmission_risk_scores_count, data_quality_log_ble_advertising_stats, data_quality_log_ble_advertising_stats_only_once) Describes how the API was configured when a log was created and helps us tie specific problems to specific configurations.
contains_opportunistic_scans Opportunistic scans combine Exposure Notifications Bluetooth scans with scans from another process or app on the device to save battery life. When a log contains opportunistic scans, it may affect other metrics related to that log.
en_module_version Version of the Exposure Notifications module producing a log, such as 20200615.
location_stats.is_location_enabled Indicates whether a location toggle is on, which lets us know whether Exposure Notifications can function. No location data is recorded.
bluetooth_stats.is_bluetooth_enabled Indicates whether Bluetooth is enabled, which lets us know whether Exposure Notifications can function. No Bluetooth data is recorded.
ClientAppWakeUpsCount.count Number of times a client app has been awakened by the Exposure Notifications service.
This field is logged in cases in which a client app is force-stopped in the background or throttled from execution. The app is awakened so that it can continue providing the API with diagnosis key files.
ApiMethod.method_name(GET_VERSION) Indicates when a client app invokes an API method (currently we track only GET_VERSION). This gives us automated insights to determine whether or not clients have switched to more-recent API methods as they are released.
MatchingState.matching_result (UNKNOWN_MATCHING_RESULT, SUCCESS, TIMEOUT, SIGNATURE_VERIFICATION_ERROR, KEY_FILE_CORRUPTION, CRYPTO_ERROR, STORAGE_ERROR, FAILED_TO_LOAD_NATIVE_LIBRARY) Indicates whether or not this batch of keys successfully matched. If failures occur, it also indicates which failure cases were encountered.
MacRpiOverlapPebblePercentage.percentage Percentage of times that the scanner detects a MAC address that has advertised more than 1 RPI. This points to a privacy issue, documented on GitHub under "Bridging rotations at MAC/RPI boundaries."
System integrity fields
attempted_keys Number of keys that provideDiagnosisKeys received from the HA app and attempted to match. Bucketed to powers of ten (from < 10000 to > 10000000).
rejected_key_files_count Number of times an export file signature verification failed. Used to understand critical bugs in EN deployments.
attempted_key_files_count Number of files that were used to attempt key matches over the past three days. This is used to indicate if some devices are not waking up and providing keys at an appropriate rate, which may indicate an app issue.

De-identified data logged by EN Express Apps

Field Public Reporting String
rpc_call
  • RpcCallType
    • RPC_TYPE_UNKNOWN
    • RPC_TYPE_KEYS_DOWNLOAD
    • RPC_TYPE_KEYS_UPLOAD
    • RPC_TYPE_VERIFICATION
    • RPC_TYPE_ENPA_REMOTE_CONFIG_FETCH
  • RpcCallResult
    • RESULT_FAILED_UNKNOWN
    • RESULT_SUCCESS
    • RESULT_FAILED_GENERIC_4XX
    • RESULT_FAILED_GENERIC_5XX
  • payload_size
  • count

Result of remote procedure calls made to the authentication server and key servers for uploading and downloading keys. We use this data to ensure that the app can communicate effectively with the server and to track and address any errors or failures.

We use a combination of real and fake traffic to make sure no device is reporting metrics to Google that can be used to infer health status.

api_call
  • ApiCallType
    • CALL_GET_EXPOSURE_NOTIFICATION_CLIENT
    • CALL_START
    • CALL_STOP
    • CALL_IS_ENABLED
    • CALL_SET_DIAGNOSIS_KEYS_DATA_MAPPING
    • CALL_GET_DAILY_SUMMARIES
    • CALL_DEVICE_SUPPORTS_LOCATIONLESS_SCANNING
    • CALL_PROVIDE_DIAGNOSIS_KEYS
  • status_code
  • count

The EN Express app calls the Exposure Notifications service in Google Play Services to do things like request diagnosis keys from the server. We monitor these calls to ensure that the EN System is working properly and to troubleshoot any errors or failures when calling the system in Google Play Services.

work_manager_task
  • WorkerTask
    • TASK_UNKNOWN
    • TASK_PROVIDE_DIAGNOSIS_KEYS
    • TASK_STATE_UPDATED
    • TASK_SUBMIT_PRIVATE_ANALYTICS
    • TASK_COUNTRY_CHECKING
    • TASK_FIRELOG_ANALYTICS
  • Status
    • STATUS_UNKNOWN
    • STATUS_STARTED
    • STATUS_SUCCESS
    • STATUS_TIMEOUT
    • STATUS_FAIL
    • STATUS_ABANDONED
  • count
  • hours_since_last_run

The app runs periodic background tasks to do things like update its internal state and upload traffic that prevents Google from knowing whether you are reporting a diagnosis.

We collect this data to make sure that tasks are running properly in the background and to troubleshoot any errors or failures.

ui_interaction
  • Event_type
    • UNKNOWN
    • APP_OPENED
    • BLUETOOTH_DISABLED_WARNING_SHOWN
    • LOCATION_PERMISSION_WARNING_SHOWN
    • LOW_STORAGE_WARNING_SHOWN
    • SHARE_APP_CLICKED
  • count

We report statistics on how users interact with the app to make sure the app is functioning correctly and to identify opportunities to improve its usability.

build_id Application version number of the app producing the log.
region_identifier This is the region this app covers, as defined by the local health authority.
hours_since_last_batch The number of hours since last log upload (rounded to the nearest hour)