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_stop
i ctl.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 init
i hwservicemanager
. 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łonkowskiejregisterAsService
, 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ń.