Implementing Health 2.0

All healthd code has been refactored into health@2.0-impl and libhealthservice, then modified to implement health@2.0 HAL. These two libraries are linked statically by health@2.0-service, enabling it to do the work previously done by healthd (i.e. run the healthd_mainloop and do polling). In init, the health@2.0-service registers an implementation of the interface IHealth to hwservicemanager. When upgrading devices with an Android 8.x vendor image and an Android 9 framework, health@2.0 service might not be provided by the vendor image. This is enforced by the deprecation schedule.

To resolve this issue:

  1. healthd registers IHealth to hwservicemanager (despite being a system daemon). IHealth is added to the system manifest, with instance name "backup".
  2. Framework and storaged communicate with healthd via hwbinder instead of binder.
  3. Code for framework and storaged are changed to fetch the instance "default" if available, then "backup".
    • C++ client code uses the logic defined in libhealthhalutils.
    • Java client code uses the logic defined in HealthServiceWrapper.
  4. After IHealth/default is widely available and Android 8.1 vendor images are deprecated, IHealth/backup and healthd can be deprecated. For more details, see Deprecating health@1.0.

Board-specific build variables for healthd

BOARD_PERIODIC_CHORES_INTERVAL_* are board-specific variables used to build healthd. As part of system/vendor build split, board-specific values cannot be defined for system modules. In health@2.0, vendors can override these two values in healthd_mode_ops->init (by dropping libhealthservice dependency in health@2.0-service.<device> and re-implementing this function).

Static implementation library

Unlike other HAL implementation libraries, the implementation library health@2.0-impl is a static library to which health@2.0-service, charger, recovery, and legacy healthd link.

health@2.0.impl implements IHealth as described above and is meant to wrap around libbatterymonitor and libhealthd.BOARD. These users of health@2.0-impl must not use BatteryMonitor or the functions in libhealthd directly; instead, these calls should be replaced with calls into the Health class, an implementation of theIHealth interface. To generalize further, healthd_common code is also included in health@2.0-impl. The new healthd_common contains the rest of common code between health@2.0-service, charger, and healthd and calls into IHealth methods instead of BatteryMonitor.

Implementing Health 2.0 service

When implementing health@2.0 service for a device, if the default implementation is:

  • Sufficient for the device, use android.hardware.health@2.0-service directly.
  • Not sufficient for the device, create the android.hardware.health@2.0-service.(device) executable and include:

    #include <health2/service.h>
    int main() { return health_service_main(); }
    

Then:

  • If board-specific libhealthd:

    • Does exist, link to it.
    • Does not exist, provide empty implementations for healthd_board_init and healthd_board_battery_update functions.
  • If board-specific BOARD_PERIODIC_CHORES_INTERVAL_* variables:

    • Are defined, create a device-specific HealthServiceCommon.cpp (copied from hardware/interfaces/health/2.0/utils/libhealthservice) and customize it in healthd_mode_service_2_0_init.
    • Are not defined, link to libhealthservice statically.
  • If device:

    • Should implement getStorageInfo and getDiskStats APIs, provide the implementation in get_storage_info and get_disk_stats functions.
    • Should not implement those APIs, link to libstoragehealthdefault statically.
  • Update necessary SELinux permissions.

  • Implement HAL in recovery by installing a passthrough implementation to the recovery image. Example:

    // Android.bp
    cc_library_shared {
        name: "android.hardware.health@2.0-impl-<device>",
        recovery_available: true,
        relative_install_path: "hw",
        static_libs: [
            "android.hardware.health@2.0-impl",
            "libhealthd.<device>"
            // Include the following or implement device-specific storage APIs
            "libhealthstoragedefault",
        ],
        srcs: [
            "HealthImpl.cpp",
        ],
        overrides: [
            "android.hardware.health@2.0-impl-default",
        ],
    }
    
    // HealthImpl.cpp
    #include <health2/Health.h>
    #include <healthd/healthd.h>
    using android::hardware::health::V2_0::IHealth;
    using android::hardware::health::V2_0::implementation::Health;
    extern "C" IHealth* HIDL_FETCH_IHealth(const char* name) {
        const static std::string providedInstance{"default"};
        if (providedInstance != name) return nullptr;
        return Health::initInstance(&gHealthdConfig).get();
    }
    
    # device.mk
    PRODUCT_PACKAGES += android.hardware.health@2.0-impl-<device>
    

For details, refer to hardware/interfaces/health/2.0/README.md.

Health clients

See Health clients for health 2.1 HAL.

SELinux changes

The new health@2.0 HAL includes the following SELinux changes:

  • Adds health@2.0-service to file_contexts.
  • Allows system_server and storaged to use hal_health.
  • Allows system_server (BatteryService) to register batteryproperties_service (IBatteryPropertiesRegistrar).
  • Allows healthd to provide hal_health.
  • Removes rules that allow system_server / storaged to call into healthd via binder.
  • Removes rules that allow healthd to register batteryproperties_service (IBatteryPropertiesRegistrar).

For devices with their own implementation, some vendor SELinux changes may be necessary. Example:

# device/<manufacturer>/<device>/sepolicy/vendor/file_contexts
/vendor/bin/hw/android\.hardware\.health@2\.0-service.<device> u:object_r:hal_health_default_exec:s0

# device/<manufacturer>/<device>/sepolicy/vendor/hal_health_default.te
# Add device specific permissions to hal_health_default domain, especially
# if it links to board-specific libhealthd or implements storage APIs.

Kernel interfaces

See Kernel interfaces for health 2.1 HAL.

Testing

Android 9 includes new VTS tests written specifically for the health@2.0 HAL. If a device declares to provide health@2.0 HAL in the device manifest, it must pass the corresponding VTS tests. Tests are written for both the default instance (to ensure that the device implements the HAL correctly) and the backup instance (to ensure that healthd continues to function correctly before it is removed).

Battery information requirements

See Battery information requirements.