W systemie Android 10 wprowadzono opcjonalne interfejsy API zarządzania buforem HAL3 aparatu , które umożliwiają zaimplementowanie logiki zarządzania buforami w celu uzyskania innej pamięci i przechwycenia kompromisów w zakresie opóźnień w implementacjach HAL aparatu.
HAL kamery wymaga N żądań (gdzie N jest równe głębokości potoku ) umieszczonych w kolejce w potoku, ale często nie wymaga jednocześnie wszystkich N zestawów buforów wyjściowych.
Na przykład warstwa HAL może mieć osiem żądań w kolejce w potoku, ale wymaga buforów wyjściowych tylko dla dwóch żądań w ostatnich etapach potoku. Na urządzeniach z systemem Android 9 i starszym platforma aparatu przydziela bufory, gdy żądanie jest umieszczane w kolejce w warstwie HAL, więc w warstwie HAL może znajdować się sześć zestawów buforów, które nie są używane. W systemie Android 10 interfejsy API zarządzania buforem HAL3 kamery umożliwiają oddzielenie buforów wyjściowych w celu zwolnienia sześciu zestawów buforów. Może to prowadzić do oszczędności setek megabajtów pamięci na urządzeniach wysokiej klasy, a także może być korzystne dla urządzeń o małej ilości pamięci.
Rysunek 1 przedstawia schemat interfejsu HAL kamery dla urządzeń z systemem Android 9 i starszym. Rysunek 2 przedstawia interfejs HAL kamery w systemie Android 10 z zaimplementowanymi interfejsami API zarządzania buforem HAL3 kamery.
Rysunek 1. Interfejs HAL kamery w systemie Android 9 i niższych
Rysunek 2. Interfejs HAL kamery w systemie Android 10 przy użyciu interfejsów API zarządzania buforami
Wdrażanie interfejsów API zarządzania buforami
Aby zaimplementować interfejsy API zarządzania buforami, warstwa HAL kamery musi:
- Zaimplementuj HIDL
ICameraDevice@3.5
. - Ustaw klucz charakterystyki kamery
android.info.supportedBufferManagementVersion
naHIDL_DEVICE_3_5
.
HAL kamery używa metod requestStreamBuffers
i returnStreamBuffers
w ICameraDeviceCallback.hal
do żądania i zwracania buforów. HAL musi również implementować metodę signalStreamFlush
w ICameraDeviceSession.hal
, aby zasygnalizować warstwie HAL kamery, że zwraca bufory.
requestStreamBuffers
Użyj metody requestStreamBuffers
, aby zażądać buforów ze struktury aparatu. W przypadku korzystania z interfejsów API zarządzania buforem kamery HAL3 żądania przechwytywania ze struktury kamery nie zawierają buforów wyjściowych, czyli pole bufferId
w StreamBuffer
ma wartość 0
. W związku z tym warstwa HAL kamery musi używać requestStreamBuffers
do żądania buforów ze struktury kamery.
Metoda requestStreamBuffers
umożliwia obiektowi wywołującemu żądanie wielu buforów z wielu strumieni wyjściowych w jednym wywołaniu, co pozwala na mniejszą liczbę wywołań IPC HIDL. Jednak wywołania zajmują więcej czasu, gdy w tym samym czasie żąda się większej liczby buforów, co może negatywnie wpłynąć na całkowite opóźnienie żądania do wyniku. Ponadto, ponieważ wywołania requestStreamBuffers
są serializowane w usłudze kamery, zaleca się, aby warstwa HAL kamery używała dedykowanego wątku o wysokim priorytecie do żądania buforów.
Jeśli żądanie bufora nie powiedzie się, warstwa HAL kamery musi być w stanie prawidłowo obsłużyć błędy niekrytyczne. Na poniższej liście opisano typowe przyczyny niepowodzenia żądań bufora oraz sposób ich obsługi przez warstwę HAL kamery.
- Aplikacja rozłącza się ze strumieniem wyjściowym: jest to błąd niekrytyczny. HAL kamery powinien wysłać
ERROR_REQUEST
dla każdego żądania przechwytywania kierowanego na odłączony strumień i być gotowy do normalnego przetwarzania kolejnych żądań. - Limit czasu: może się to zdarzyć, gdy aplikacja jest zajęta intensywnym przetwarzaniem, trzymając niektóre bufory. Kamera HAL powinna wysyłać
ERROR_REQUEST
w przypadku żądań przechwytywania, których nie można spełnić z powodu błędu przekroczenia limitu czasu, i powinna być gotowa do normalnego przetwarzania kolejnych żądań. - Struktura kamery przygotowuje nową konfigurację strumienia: warstwa HAL kamery powinna poczekać do zakończenia następnego wywołania
configureStreams
przed ponownym wywołaniemrequestStreamBuffers
. - HAL kamery osiągnął limit bufora (pole
maxBuffers
): Przed ponownym wywołaniemrequestStreamBuffers
warstwa HAL kamery powinna poczekać, aż zwróci co najmniej jeden bufor strumienia.
returnStreamBuffers
Użyj metody returnStreamBuffers
, aby zwrócić dodatkowe bufory do struktury aparatu. HAL kamery zwykle zwraca bufory do struktury kamery za pomocą metody processCaptureResult
, ale może uwzględniać tylko żądania przechwytywania, które zostały wysłane do warstwy HAL kamery. Dzięki metodzie requestStreamBuffers
możliwe jest, aby implementacja warstwy HAL kamery zachowała więcej buforów niż zażądała struktura kamery. Wtedy należy użyć metody returnStreamBuffers
. Jeśli implementacja HAL nigdy nie przechowuje więcej buforów niż żądano, implementacja HAL kamery nie musi wywoływać metody returnStreamBuffers
.
SignalStreamFlush
Metoda signalStreamFlush
jest wywoływana przez strukturę kamery w celu powiadomienia warstwy HAL kamery o zwróceniu wszystkich dostępnych buforów. Jest to zwykle wywoływane, gdy struktura kamery ma wywołać configureStreams
i musi opróżnić potok przechwytywania kamery. Podobnie jak w przypadku metody returnStreamBuffers
, jeśli implementacja warstwy HAL kamery nie przechowuje więcej buforów niż żądano, możliwe jest posiadanie pustej implementacji tej metody.
Po wywołaniu przez strukturę kamery signalStreamFlush
struktura przestaje wysyłać nowe żądania przechwytywania do warstwy HAL kamery, dopóki wszystkie bufory nie zostaną zwrócone do struktury kamery. Po zwróceniu wszystkich buforów wywołania metody requestStreamBuffers
kończą się niepowodzeniem, a struktura kamery może kontynuować swoją pracę w stanie czystym. Następnie struktura kamery wywołuje metodę configureStreams
lub processCaptureRequest
. Jeśli struktura kamery wywoła metodę configureStreams
, warstwa HAL kamery może ponownie rozpocząć żądanie buforów po pomyślnym zwróceniu wywołania configureStreams
. Jeśli struktura kamery wywoła metodę processCaptureRequest
, warstwa HAL kamery może rozpocząć żądanie buforów podczas wywołania processCaptureRequest
.
Semantyka jest inna dla metody signalStreamFlush
i metody flush
. Gdy wywoływana jest metoda flush
, warstwa HAL może przerwać oczekujące żądania przechwytywania z ERROR_REQUEST
, aby jak najszybciej opróżnić potok. Po wywołaniu metody signalStreamFlush
warstwa HAL musi normalnie zakończyć wszystkie oczekujące żądania przechwytywania i zwrócić wszystkie bufory do struktury kamery.
Inną różnicą między metodą signalStreamFlush
a innymi metodami jest to, że signalStreamFlush
jest jednokierunkową metodą HIDL, co oznacza, że struktura kamery może wywołać inne blokujące interfejsy API, zanim warstwa HAL odbierze wywołanie signalStreamFlush
. Oznacza to, że metoda signalStreamFlush
i inne metody (w szczególności metoda configureStreams
) mogą dotrzeć do warstwy HAL kamery w innej kolejności niż kolejność ich wywoływania w strukturze kamery. Aby rozwiązać ten problem asynchroniczny, pole streamConfigCounter
zostało dodane do StreamConfiguration
i dodane jako argument do metody signalStreamFlush
. Implementacja warstwy HAL kamery powinna używać argumentu streamConfigCounter
, aby określić, czy wywołanie signalStreamFlush
nadejdzie później niż odpowiadające mu wywołanie configureStreams
. Zobacz rysunek 3 jako przykład.
Rysunek 3. Jak kamera HAL powinna wykrywać i obsługiwać spóźnione wywołania signalStreamFlush
Zmiany w zachowaniu podczas wdrażania interfejsów API do zarządzania buforami
Korzystając z interfejsów API zarządzania buforami do implementacji logiki zarządzania buforami, należy wziąć pod uwagę następujące możliwe zmiany w zachowaniu kamery i implementacji warstwy HAL kamery:
Żądania przechwytywania docierają do warstwy HAL kamery szybciej i częściej: bez interfejsów API zarządzania buforami struktura kamery żąda buforów wyjściowych dla każdego żądania przechwytywania przed wysłaniem żądania przechwytywania do warstwy HAL kamery. Podczas korzystania z interfejsów API zarządzania buforami struktura kamery nie musi już czekać na bufory, dzięki czemu może wcześniej wysyłać żądania przechwytywania do warstwy HAL kamery.
Ponadto bez interfejsów API zarządzania buforami struktura kamery przestaje wysyłać żądania przechwytywania, jeśli jeden ze strumieni wyjściowych żądania przechwytywania osiągnie maksymalną liczbę buforów, które może jednocześnie przechowywać warstwa HAL (ta wartość jest wyznaczana przez warstwę HAL kamery w
HalStream::maxBuffers
w wartości zwracanej przez wywołanieconfigureStreams
). W przypadku interfejsów API zarządzania buforami to ograniczanie przepustowości już nie istnieje, a implementacja warstwy HAL aparatu nie może akceptować wywołańprocessCaptureRequest
, gdy warstwa HAL ma w kolejce zbyt wiele żądań przechwytywania.Opóźnienie wywołania
requestStreamBuffers
znacznie się różni: Istnieje wiele powodów, dla których wywołanierequestStreamBuffers
może trwać dłużej niż przeciętnie. Na przykład:- W przypadku kilku pierwszych buforów nowo utworzonego strumienia wywołania mogą trwać dłużej, ponieważ urządzenie musi przydzielić pamięć.
- Oczekiwane opóźnienie wzrasta 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ń bufora lub przekroczenie limitu czasu z powodu braku buforów lub zajętego procesora.
Strategie zarządzania buforami
Interfejsy API zarządzania buforami umożliwiają wdrażanie różnych rodzajów strategii zarządzania buforami. Oto kilka przykładów:
- Zgodność wsteczna: warstwa HAL żąda buforów dla żądania przechwytywania podczas wywołania
processCaptureRequest
. Ta strategia nie zapewnia żadnych oszczędności pamięci, ale może służyć jako pierwsza implementacja interfejsów API zarządzania buforami, wymagająca bardzo niewielu zmian w kodzie istniejącej warstwy HAL kamery. - Maksymalizacja oszczędności pamięci: Kamera HAL żąda buforów wyjściowych tylko bezpośrednio przed koniecznością ich zapełnienia. Ta strategia pozwala na maksymalizację oszczędności pamięci. Potencjalną wadą jest większe szarpnięcie potoku kamery, gdy realizacja żądań bufora trwa niezwykle długo.
- Pamięć podręczna: warstwa HAL kamery buforuje kilka buforów, dzięki czemu jest mniej prawdopodobne, że sporadyczne żądanie wolnego bufora nie będzie miało na nią wpływu.
HAL kamery może przyjmować różne strategie dla poszczególnych przypadków użycia, na przykład używając strategii zmaksymalizowanego oszczędzania pamięci dla przypadków użycia, które zużywają dużo pamięci i używając strategii kompatybilności wstecznej dla innych przypadków użycia.
Przykładowa realizacja w zewnętrznej kamerze HAL
Zewnętrzna kamera HAL została wprowadzona w systemie Android 9 i można ją znaleźć w drzewie źródłowym pod adresem hardware/interfaces/camera/device/3.5/
. W systemie Android 10 został zaktualizowany, aby uwzględnić ExternalCameraDeviceSession.cpp
, implementację interfejsu API zarządzania buforami. Ta zewnętrzna kamera HAL implementuje strategię maksymalizacji oszczędności pamięci wspomnianą w strategiach zarządzania buforami w kilkuset wierszach kodu C++.