Implementacja dynamicznego zamykania obejmuje okablowanie przepływów danych i wykonywanie procesów dynamicznych, jak opisano szczegółowo w poniższych sekcjach.
Zmiany w definicjach HAL
Dynamiczne zamykanie wymaga informacji o tym, które procesy obsługują jakie interfejsy HAL (ta informacja może być również przydatna później w innych kontekstach), a także nieuruchamiania procesów podczas rozruchu i nieuruchamiania ich ponownie (dopóki nie zostanie ponownie zażądane) po zakończeniu.
# 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 zamykanie wymaga również, aby hwservicemanager
wydał polecenie init
, aby uruchomił żądane usługi. W Androidzie 9 init
zawiera trzy dodatkowe komunikaty sterujące (np. ctl.start
): ctl.interface_start
, ctl.interface_stop
i ctl.interface_restart
. Komunikaty te mogą być użyte do sygnalizowania init
w celu wywołania lub wyłączenia określonych interfejsów sprzętowych. Gdy żądana jest usługa, która nie jest zarejestrowana, hwservicemanager
żąda uruchomienia usługi. Jednak dynamiczne warstwy HAL nie wymagają użycia żadnego z nich.
Określ wyjście HAL
W systemie Android 9 wyjście HAL należy określić ręcznie. W przypadku Androida 10 i nowszych można to również określić za pomocą automatycznych cykli życia .
Dynamiczne zamykanie wymaga wielu zasad decydujących o tym, kiedy uruchomić warstwę HAL, a kiedy zamknąć warstwę HAL. Jeśli warstwa HAL z jakiegokolwiek powodu zdecyduje się zakończyć, zostanie automatycznie uruchomiona ponownie, gdy będzie potrzebna ponownie, korzystając z informacji podanych w definicji warstwy HAL oraz infrastruktury zapewnianej przez zmiany w init
i hwservicemanager
. Może to obejmować kilka różnych strategii, w tym:
- HAL może wywołać na sobie wyjście, jeśli ktoś wywoła na nim bliski lub podobny interfejs API. To zachowanie musi zostać określone w odpowiednim interfejsie HAL.
- Warstwy HAL mogą zostać zamknięte po zakończeniu zadania (udokumentowane w pliku HAL).
Automatyczne cykle życia
Android 10 dodaje więcej obsługi jądra i hwservicemanager
, co pozwala warstwom HAL na automatyczne zamykanie, gdy nie mają one klientów. Aby skorzystać z tej funkcji, wykonaj wszystkie kroki opisane w sekcji Zmiany w definicjach HAL, a także:
- Zarejestruj usługę w C++ za pomocą
LazyServiceRegistrar
zamiast funkcji członkowskiejregisterAsService
, na przykład:// only one instance of LazyServiceRegistrar per process LazyServiceRegistrar registrar; registrar.registerAsService(myHidlService /* , "default" */);
- Sprawdź, czy klient HAL przechowuje odniesienie do 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 będzie nadal wykonywany, klient powinien także wywołać funkcjęIPCThreadState::self()->flushCommands()
po usunięciu odniesienia, aby upewnić się, że sterownik bindera zostanie powiadomiony o liczbie powiązanych odwołań zmiany.