Dynamicznie dostępne HAL-e

Android 9 obsługuje dynamiczne wyłączanie podsystemów sprzętowych Androida, gdy nie są używane lub nie są potrzebne. Na przykład, gdy użytkownik nie korzysta z Wi-Fi, podsystemy Wi-Fi nie powinny zajmować pamięci, energii ani innych zasobów systemowych. W wcześniejszych wersjach Androida interfejsy HAL i sterowniki były otwarte na urządzeniach z Androidem przez cały czas uruchamiania telefonu.

Wdrożenie dynamicznego zamykania polega na połączeniu przepływów danych i wykonaniu procesów dynamicznych zgodnie z opisem w następnych sekcjach.

Zmiany w definicjach HAL

Dynamiczne zamykanie wymaga informacji o tym, które procesy obsługują które interfejsy HAL (te informacje mogą być przydatne w innych kontekstach), a także o tym, które procesy nie powinny być uruchamiane przy starcie i których nie należy ponownie uruchamiać (do czasu ponownego zgłoszenia).

# some init.rc script associated with the HAL
service vendor.some-service-name /vendor/bin/hw/some-binary-service
    # init language extension, provides information of what service is served
    # if multiple interfaces are served, they can be specified one on each line
    interface android.hardware.light@2.0::ILight default
    # restarted if hwservicemanager dies
    # would also cause the hal to start early during boot if disabled wasn't set
    class hal
    # will not be restarted if it exits until it is requested to be restarted
    oneshot
    # will only be started when requested
    disabled
    # ... other properties

Zmiany w init i hwservicemanager

Dynamiczne wyłączanie wymaga też, aby hwservicemanager poinformował init o uruchomieniu żądanych usług. W Androidzie 9 init zawiera 3 dodatkowe komunikaty sterujące (np. ctl.start): ctl.interface_start, ctl.interface_stopctl.interface_restart. Te komunikaty mogą służyć do sygnalizowania init w celu wyświetlania i ukrywania określonych interfejsów sprzętowych. Gdy usługa jest żądana, ale nie jest zarejestrowana, hwservicemanager prosi o jej uruchomienie. Dynamiczne pliki HAL nie wymagają jednak korzystania z żadnego z tych elementów.

Określanie wyjścia HAL

W Androidzie 9 wyjście z HAL musi być określone ręcznie. W przypadku Androida 10 lub nowszego można go też określić za pomocą automatycznych cykli życia.

Dynamiczne zamykanie wymaga wielu zasad, które decydują, kiedy uruchomić HAL i kiedy go zamknąć. Jeśli HAL zdecyduje się zakończyć działanie z dowolnego powodu, automatycznie uruchomi się ponownie, gdy będzie to potrzebne, korzystając z informacji podanych w definicji HAL i z infrastruktury zapewnionej przez zmiany w inithwservicemanager. Może to obejmować kilka różnych strategii, w tym:

  • Jeśli ktoś wywoła podobny interfejs API lub podobny interfejs API, HAL może wywołać funkcję exit. To zachowanie musi zostać określone w odpowiednim interfejsie HAL.
  • HAL może się wyłączyć po zakończeniu zadania (opisanego w pliku HAL).

Automatyczne cykle życia

Android 10 zapewnia więcej funkcji dla jądra i hwservicemanager, co pozwala automatycznie wyłączać interfejsy HAL, gdy nie mają klientów. Aby korzystać z tej funkcji, wykonaj wszystkie czynności opisane w sekcji Zmiany definicji HAL, a także:

  • Zarejestruj usługę w C++ za pomocą funkcji LazyServiceRegistrar zamiast funkcji członkowskiej registerAsService, na przykład:
    // only one instance of LazyServiceRegistrar per process
    LazyServiceRegistrar registrar;
    registrar.registerAsService(myHidlService /* , "default" */);
  • Sprawdź, czy klient HAL przechowuje odwołanie do interfejsu HAL najwyższego poziomu (interfejs zarejestrowany w hwservicemanager) tylko wtedy, gdy jest używany. Aby uniknąć opóźnień, jeśli to odwołanie zostanie usunięte w wątku hwbinder, który nadal się wykonuje, klient powinien też wywołać funkcję IPCThreadState::self()->flushCommands() po usunięciu odwołania, aby powiadomić moduł binder o związanych zmianach liczby odwołań.