Health 구현

모든 healthd 코드는 health@2.0-impl 및 libhealthservice로 리팩터링되었으며 health@2.0 HAL을 구현하도록 수정되었습니다. 이 두 라이브러리는 health@2.0-service에 정적으로 연결되어 이전에 healthd에서 수행한 작업을 수행합니다. 즉, healthd_mainloop을 실행하고 폴링을 수행합니다. init에서 health@2.0-service는 인터페이스 IHealth의 구현을 hwservicemanager에 등록합니다. Android 8.x 공급업체 이미지 및 Android 9 프레임워크로 기기를 업그레이드할 때 공급업체 이미지에서 health@2.0 서비스를 제공하지 못할 수 있습니다. 이는 지원 중단 일정에 따라 적용됩니다.

이 문제를 해결하려면 다음 단계를 따르세요.

  1. healthdIHealthhwservicemanager에 등록합니다(데몬 시스템인 경우에도). 인스턴스 이름이 'backup'인 IHealth가 시스템 매니페스트에 추가됩니다.
  2. 프레임워크 및 storagedbinder 대신 hwbinder를 통해 healthd과 통신합니다.
  3. 프레임워크 및 storaged 코드가 변경되어 가능한 경우 '기본', 그 다음에는 '백업' 인스턴스를 가져옵니다.
    • C ++ 클라이언트 코드는 libhealthhalutils에 정의된 로직을 사용합니다.
    • 자바 클라이언트 코드는 HealthServiceWrapper에 정의된 로직을 사용합니다.
  4. IHealth/default가 널리 사용 가능하고 Android 8.1 공급업체 이미지가 지원 중단된 경우 IHealth/backup 및 healthd는 지원이 중단될 수 있습니다. 자세한 내용은 health@1.0 지원 중단을 참조하세요.

healthd의 보드별 빌드 변수

BOARD_PERIODIC_CHORES_INTERVAL_*healthd를 빌드하는 데 사용되는 보드별 변수입니다. 시스템/공급업체 빌드 분할의 일부로 시스템 모듈에 대한 보드별 값을 정의할 수 없습니다. health@2.0에서는 공급업체가 이러한 두 가지 값을 healthd_mode_ops->init에서 삭제할 수 있습니다(health@2.0-service.<device>에서 libhealthservice 종속성을 삭제하고 이 기능을 다시 구현).

정적 구현 라이브러리

다른 HAL 구현 라이브러리와 달리 구현 라이브러리 health@2.0-impl은 health@2.0-service, charger, recovery 및 legacy healthd 링크가 포함된 정적 라이브러리입니다.

health@2.0.impl은 위에 설명된 대로 IHealth를 구현하며 libbatterymonitorlibhealthd.BOARD 주변을 래핑함을 의미합니다. 이러한 health@2.0-impl의 사용자는 BatteryMonitor 또는 libhealthd의 함수를 직접 사용하지 않아야 합니다. 대신 이러한 호출은 IHealth 인터페이스의 구현인 Health 클래스 호출로 대체되어야 합니다. 일반화하기 위해 healthd_common 코드도 health@2.0-impl에 포함되어 있습니다. 새 healthd_common에는 health@2.0-service, charger 및 healthd 사이의 나머지 코드와 BatteryMonitor 대신 IHealth 메서드 호출이 포함됩니다.

Health 2.0 서비스 구현

기기에 health2.0 서비스를 구현할 때 기본 구현이 기기에 충분한지에 따라,

  • 기기에 충분하면 android.hardware.health@2.0-service를 직접 사용합니다.
  • 기기에 충분하지 않은 경우 android.hardware.health@2.0-service.(device)는 executable을 만들고 다음을 포함합니다.

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

다음을 따르세요.

  • 보드별 libhealthd:가 존재하는지에 따라,

    • 존재하는 경우, 연결합니다.
    • 존재하지 않는 경우, healthd_board_inithealthd_board_battery_update 함수에 대한 빈 구현을 제공합니다.
  • 보드별 BOARD_PERIODIC_CHORES_INTERVAL_* 변수가 정의되었는지에 따라,

    • 정의된 경우, 기기별 HealthServiceCommon.cpp를 생성하고(hardware/interfaces/health/2.0/utils/libhealthservice에서 복사함) healthd_mode_service_2_0_init에서 맞춤설정합니다.
    • 정의되지 않은 경우, libhealthservice에 정적으로 연결합니다.
  • 기기가 다음을 구현해야 하는지에 따라,

    • getStorageInfogetDiskStats API를 구현해야 하는 경우, get_storage_infoget_disk_stats 함수에 구현을 제공합니다.
    • 이러한 API를 구현하지 않아야 하는 경우, libstoragehealthdefault에 정적으로 연결합니다.
  • 필요한 SELinux 권한을 업데이트합니다.

  • 복구 이미지에 패스스루 구현을 설치하여 복구 중 HAL을 구현합니다. 예:

    // 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>
        

자세한 내용은 hardware/interfaces/health/2.0/README.md를 참조하십시오.

Health 클라이언트

health@2.0에는 다음 클라이언트가 있습니다.

  • charger. libbatterymonitorhealthd_common 코드의 사용은 health@2.0-impl에서 래핑됩니다.
  • recovery. libbatterymonitor에 대한 연결은 health@2.0-impl에서 래핑됩니다. BatteryMonitor에 대한 모든 호출은 Health 구현 클래스로의 호출로 대체됩니다.
  • BatteryManager. BatteryManager.queryProperty(int id)IBatteryPropertiesRegistrar.getProperty의 유일한 클라이언트로 healthd에서 제공했으며 /sys/class/power_supply을 바로 읽습니다.

    보안 고려 사항으로 인해 앱에서 직접 health HAL을 직접 호출할 수 없습니다. Android 9에서 바인더 서비스 IBatteryPropertiesRegistrarhealthd 대신 BatteryService에서 제공하며 BatteryService 위임자는 health HAL에 대한 호출을 위임하여 요청된 정보를 검색합니다.

  • BatteryService. Android 9에서 BatteryServiceHealthServiceWrapper를 사용하여 health service 인스턴스를 확인하여 사용합니다(공급업체의 기본 인스턴스 또는 healthd의 또는 '백업' 인스턴스). 그런 다음 IHealth.registerCallback을 통해 health 이벤트를 수신합니다.

  • Storaged. Android 9에서 storagedlibhealthhalutils를 사용하여 어떤 health service 인스턴스를 사용할지 판단합니다(공급업체의 기본 인스턴스 또는 healthd의 '백업' 인스턴스). 그런 다음 IHealth.registerCallback를 통해 health 이벤트를 듣고 저장소 정보를 검색합니다.

SELinux 변경사항

새로운 health@2.0 HAL에는 다음과 같은 SELinux 변경사항이 포함됩니다.

  • health@2.0-service가 file_contexts에 추가됩니다.
  • system_serverstoraged에서 hal_health를 사용할 수 있도록 허용됩니다.
  • system_server(BatteryService)에서 batteryproperties_service(IBatteryPropertiesRegistrar)를 등록할 수 있도록 허용됩니다.
  • healthd에서 hal_health를 제공할 수 있도록 허용됩니다.
  • system_server/storaged에서 바인더를 통해 healthd를 호출할 수 있도록 허용하는 규칙이 삭제됩니다.
  • healthd에서 batteryproperties_service(IBatteryPropertiesRegistrar)를 등록할 수 있도록 허용하는 규칙이 삭제됩니다.

자체적으로 구현된 기기의 경우 일부 공급업체 SELinux 변경사항이 필요할 수 있습니다. 예:

# 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.
    

커널 인터페이스

healthd 데몬과 기본 구현인 android.hardware.health@2.0-service는 배터리 정보를 검색하기 위해 다음 커널 인터페이스에 액세스합니다.

  • /sys/class/power_supply/*/capacity
  • /sys/class/power_supply/*/charge_counter
  • /sys/class/power_supply/*/charge_full
  • /sys/class/power_supply/*/current_avg
  • /sys/class/power_supply/*/current_max
  • /sys/class/power_supply/*/current_now
  • /sys/class/power_supply/*/cycle_count
  • /sys/class/power_supply/*/health
  • /sys/class/power_supply/*/online
  • /sys/class/power_supply/*/present
  • /sys/class/power_supply/*/status
  • /sys/class/power_supply/*/technology
  • /sys/class/power_supply/*/temp
  • /sys/class/power_supply/*/type
  • /sys/class/power_supply/*/voltage_max
  • /sys/class/power_supply/*/voltage_now

libbatterymonitor를 사용하는 모든 기기별 Health HAL 구현은 healthd_board_init(struct healthd_config*)에서 재정의하지 않는 한 기본적으로 이러한 커널 인터페이스에 액세스합니다.

이러한 파일이 없거나 healthd에서 기본 서비스에 액세스할 수 없는 경우(예: 파일이 SELinux 정책이 잘못 구성되어 액세스를 거부하는 공급업체별 폴더의 심볼릭 링크인 경우) 제대로 작동하지 않을 수 있습니다. 따라서 기본 구현을 사용하더라도 추가 공급업체별 SELinux 변경이 필요할 수 있습니다.

테스트

Android 9에는 health@2.0 HAL 전용으로 작성된 새로운 VTS 테스트가 포함되어 있습니다. 기기가 기기 매니페스트에서 health@2.0 HAL을 제공한다고 선언하면 해당하는 VTS 테스트를 통과해야 합니다. 테스트는 기본 인스턴스(HAL을 올바르게 구현할 수 있도록)와 백업 인스턴스(healthd가 삭제되기 전에 올바르게 계속 작동하도록)에 대해 모두 작성되었습니다.