Android 10 wprowadza opcjonalne interfejsy API zarządzania buforami HAL3 aparatu, które umożliwiają wdrożenie logiki zarządzania buforami w celu uzyskania różnych kompromisów między pamięcią a opóźnieniem przechwytywania w implementacjach HAL aparatu.
Warstwa HAL aparatu wymaga N żądań (gdzie N jest równe głębokości potoku) w kolejce w swoim potoku, ale często nie wymaga wszystkich N zestawów buforów wyjściowych w tym samym czasie.
Na przykład HAL może mieć w kolejce 8 żądań, ale potrzebuje buforów wyjściowych tylko dla 2 żądań na ostatnich etapach przetwarzania. Na urządzeniach z Androidem 9 i starszym struktura aparatu przydziela bufory, gdy żądanie jest umieszczane w kolejce w warstwie HAL. W warstwie HAL może więc znajdować się 6 zestawów buforów, które nie są używane. W Androidzie 10 interfejsy API zarządzania buforami HAL3 aparatu umożliwiają odłączenie buforów wyjściowych, aby zwolnić 6 zestawów buforów. Może to prowadzić do oszczędności pamięci rzędu setek megabajtów na urządzeniach z wyższej półki, a także przynosić korzyści na urządzeniach z małą ilością pamięci.
Rysunek 1 przedstawia diagram interfejsu HAL aparatu na urządzeniach z Androidem 9 i starszym. Ilustracja 2 przedstawia interfejs HAL aparatu w Androidzie 10 z zaimplementowanymi interfejsami API zarządzania buforem HAL3 aparatu.
Rysunek 1. Interfejs HAL aparatu w Androidzie 9 i starszych wersjach
Rysunek 2. Interfejs HAL aparatu w Androidzie 10 korzystający z interfejsów API do zarządzania buforami
Wdrażanie interfejsów API zarządzania buforem
Aby zaimplementować interfejsy API zarządzania buforem, warstwa HAL aparatu musi:
- Zaimplementuj HIDL
ICameraDevice@3.5
. - Ustaw klucz charakterystyki kamery
android.info.supportedBufferManagementVersion
naHIDL_DEVICE_3_5
.
HAL aparatu używa metod
requestStreamBuffers
i
returnStreamBuffers
w interfejsie
ICameraDeviceCallback.hal
do wysyłania żądań buforów i ich zwracania. HAL musi też implementować metodę signalStreamFlush
w interfejsie ICameraDeviceSession.hal
, aby sygnalizować HAL-owi aparatu konieczność zwrócenia buforów.
requestStreamBuffers
Aby poprosić o bufory z platformy aparatu, użyj metody
requestStreamBuffers
. Gdy używasz interfejsów API HAL3 aparatu do zarządzania buforami, żądania przechwytywania z frameworka aparatu nie zawierają buforów wyjściowych, czyli pole bufferId
w StreamBuffer
jest 0
. Dlatego HAL aparatu musi używać funkcji requestStreamBuffers
, aby wysyłać do platformy aparatu żądania buforów.
Metoda requestStreamBuffers
umożliwia wywołującemu zażądanie wielu buforów z wielu strumieni wyjściowych w ramach jednego wywołania, co pozwala zmniejszyć liczbę wywołań HIDL IPC. Jednak gdy jednocześnie żądanych jest więcej buforów, połączenia trwają dłużej, co może negatywnie wpłynąć na całkowite opóźnienie od żądania do wyniku.
Ponadto wywołania w requestStreamBuffers
są serializowane w usłudze aparatu, dlatego zalecamy, aby HAL aparatu używał dedykowanego wątku o wysokim priorytecie do żądania buforów.
Jeśli żądanie bufora się nie powiedzie, HAL aparatu musi być w stanie prawidłowo obsłużyć błędy niekrytyczne. Poniżej znajdziesz listę najczęstszych przyczyn niepowodzeń żądań bufora oraz sposoby ich obsługi przez HAL aparatu.
- Aplikacja odłącza się od strumienia wyjściowego:
To błąd niekrytyczny. Warstwa HAL aparatu powinna wysyłać sygnał
ERROR_REQUEST
w przypadku każdego żądania przechwytywania kierowanego do odłączonego strumienia i być gotowa do normalnego przetwarzania kolejnych żądań. - Przekroczenie limitu czasu: może się to zdarzyć, gdy aplikacja jest zajęta intensywnym przetwarzaniem, a jednocześnie korzysta z buforów. Warstwa HAL aparatu powinna wysyłać
ERROR_REQUEST
w przypadku żądań przechwytywania, których nie można zrealizować z powodu błędu przekroczenia limitu czasu, i być gotowa do normalnego przetwarzania kolejnych żądań. - Framework aparatu przygotowuje nową konfigurację strumienia:
HAL aparatu powinien poczekać, aż zakończy się kolejne wywołanie funkcji
configureStreams
przed ponownym wywołaniem funkcjirequestStreamBuffers
. - HAL aparatu osiągnął limit bufora (pole
maxBuffers
): HAL aparatu powinien poczekać, aż zwróci co najmniej 1 bufor strumienia, zanim ponownie wywołarequestStreamBuffers
.
returnStreamBuffers
Użyj metody
returnStreamBuffers
do zwracania dodatkowych buforów do platformy aparatu. HAL aparatu zwykle zwraca bufory do platformy aparatu za pomocą metody processCaptureResult
, ale może uwzględniać tylko żądania przechwytywania, które zostały wysłane do HAL aparatu. W przypadku metody requestStreamBuffers
implementacja HAL aparatu może zachować więcej buforów niż zażądała struktura aparatu. W takiej sytuacji należy użyć metody returnStreamBuffers
. Jeśli implementacja HAL nigdy nie przechowuje więcej buforów niż żądane, implementacja HAL aparatu nie musi wywoływać metody returnStreamBuffers
.
signalStreamFlush
Metoda
signalStreamFlush
jest wywoływana przez platformę kamery, aby powiadomić HAL kamery o konieczności zwrócenia wszystkich dostępnych buforów. Ta metoda jest zwykle wywoływana, gdy framework kamery ma wywołać metodę configureStreams
i musi opróżnić potok przechwytywania obrazu z kamery. Podobnie jak w przypadku metody returnStreamBuffers
, jeśli implementacja HAL kamery nie zawiera więcej buforów niż wymagane, można zastosować pustą implementację tej metody.
Gdy framework aparatu wywoła funkcję signalStreamFlush
, przestaje wysyłać do HAL aparatu nowe żądania przechwytywania, dopóki wszystkie bufory nie zostaną zwrócone do frameworka aparatu. Gdy wszystkie bufory zostaną zwrócone, wywołania metody requestStreamBuffers
zakończą się niepowodzeniem, a framework aparatu będzie mógł kontynuować pracę w czystym stanie. Framework aparatu wywołuje wtedy metodę configureStreams
lub processCaptureRequest
. Jeśli framework aparatu wywoła metodę configureStreams
, interfejs HAL aparatu może ponownie wysyłać żądania buforów po pomyślnym powrocie wywołania configureStreams
. Jeśli framework aparatu wywoła metodę processCaptureRequest
, HAL aparatu może zacząć wysyłać żądania buforów podczas wywołania processCaptureRequest
.
Semantyka metody signalStreamFlush
i metody flush
różni się. Gdy wywoływana jest metoda flush
, HAL może przerwać oczekujące żądania przechwytywania za pomocą ERROR_REQUEST
, aby jak najszybciej opróżnić potok. Gdy wywoływana jest metoda signalStreamFlush
, HAL musi normalnie zakończyć wszystkie oczekujące żądania przechwytywania i zwrócić wszystkie bufory do platformy aparatu.
Kolejną różnicą między metodą signalStreamFlush
a innymi metodami jest to, że signalStreamFlush
to jednokierunkowa metoda HIDL, co oznacza, że framework aparatu może wywoływać inne blokujące interfejsy API, zanim HAL otrzyma wywołanie signalStreamFlush
. Oznacza to, że metoda signalStreamFlush
i inne metody (w szczególności metoda configureStreams
) mogą docierać do HAL aparatu w innej kolejności niż kolejność, w jakiej zostały wywołane w platformie aparatu. Aby rozwiązać ten problem z asynchronicznością, do streamConfigCounter
dodano pole StreamConfiguration
, które zostało też dodane jako argument do metody signalStreamFlush
. Implementacja HAL aparatu powinna używać argumentu streamConfigCounter
, aby określić, czy wywołanie signalStreamFlush
następuje później niż odpowiadające mu wywołanie configureStreams
. Przykład znajdziesz na rysunku 3.
Rysunek 3. Jak HAL kamery powinien wykrywać i obsługiwać wywołania signalStreamFlush, które docierają z opóźnieniem
Zmiany w działaniu podczas wdrażania interfejsów API do zarządzania buforem
Podczas korzystania z interfejsów API do zarządzania buforem w celu wdrożenia logiki zarządzania buforem weź pod uwagę te możliwe zmiany w działaniu aparatu i implementacji HAL aparatu:
Żądania przechwytywania docierają do HAL aparatu szybciej i częściej: bez interfejsów API do zarządzania buforem framework aparatu żąda buforów wyjściowych dla każdego żądania przechwytywania przed wysłaniem żądania przechwytywania do HAL aparatu. Gdy używasz interfejsów API do zarządzania buforem, framework aparatu nie musi już czekać na bufory, więc może wcześniej wysyłać żądania przechwytywania do HAL aparatu.
Ponadto bez interfejsów API do zarządzania buforami framework aparatu przestaje wysyłać żądania przechwytywania, jeśli jeden ze strumieni wyjściowych żądania przechwytywania osiągnie maksymalną liczbę buforów, które HAL może przechowywać w danym momencie (wartość ta jest określana przez HAL aparatu w polu
HalStream::maxBuffers
w wartości zwracanej wywołaniaconfigureStreams
). Dzięki interfejsom API do zarządzania buforem to ograniczanie przepustowości nie występuje, a implementacja HAL aparatu nie może akceptować wywołańprocessCaptureRequest
, gdy w kolejce HAL znajduje się zbyt wiele żądań przechwytywania.requestStreamBuffers
opóźnienie połączenia znacznie się różni: istnieje wiele powodów, dla których połączenierequestStreamBuffers
może trwać dłużej niż średnia. Na przykład:- W przypadku pierwszych kilku buforów nowo utworzonego strumienia wywołania mogą trwać dłużej, ponieważ urządzenie musi przydzielić pamięć.
- Oczekiwany czas oczekiwania rośnie proporcjonalnie do liczby buforów żądanych w każdym wywołaniu.
- Aplikacja przechowuje bufory i jest zajęta przetwarzaniem. Może to spowodować spowolnienie żądań buforowania lub przekroczenie limitu czasu z powodu braku buforów lub zajętego procesora.
Strategie zarządzania buforem
Interfejsy API zarządzania buforem umożliwiają wdrażanie różnych strategii zarządzania buforem. Przykłady:
- Zgodność wsteczna: HAL żąda buforów dla żądania przechwytywania podczas wywołania
processCaptureRequest
. Ta strategia nie zapewnia oszczędności pamięci, ale może służyć jako pierwsza implementacja interfejsów API zarządzania buforem, która wymaga bardzo niewielu zmian w istniejącym HAL aparatu. - Maksymalne oszczędzanie pamięci: HAL aparatu żąda buforów wyjściowych tylko bezpośrednio przed ich wypełnieniem. Ta strategia pozwala maksymalnie oszczędzać pamięć. Potencjalną wadą jest większe zacinanie się potoku kamery, gdy żądania bufora trwają wyjątkowo długo.
- Buforowanie: HAL aparatu buforuje kilka buforów, dzięki czemu jest mniej podatny na sporadyczne wolne żądania buforów.
HAL aparatu może stosować różne strategie w zależności od konkretnych przypadków użycia, np. strategię maksymalnego oszczędzania pamięci w przypadkach użycia, które wymagają dużej ilości pamięci, a strategię zgodną wstecznie w innych przypadkach użycia.
Przykładowa implementacja w zewnętrznej warstwie HAL aparatu
Zewnętrzny HAL aparatu został wprowadzony w Androidzie 9 i znajduje się w drzewie źródłowym w lokalizacji hardware/interfaces/camera/device/3.5/
.
W Androidzie 10 został on zaktualizowany i zawiera
ExternalCameraDeviceSession.cpp
implementację interfejsu API zarządzania buforem. Ten zewnętrzny HAL aparatu
wdraża strategię maksymalnego oszczędzania pamięci opisaną w sekcji Strategie zarządzania buforem w kilkuset wierszach kodu C++.