Câmera

Ícone do HAL da câmera do Android

A camada de abstração de hardware da câmera (HAL) do Android conecta as APIs de framework de câmera de nível mais alto na Câmera 2 ao driver e ao hardware da câmera. O subsistema da câmera inclui implementações para componentes do pipeline da câmera, enquanto o HAL da câmera oferece interfaces para uso na implementação da sua versão desses componentes.

Arquitetura

A figura e a lista a seguir descrevem os componentes do HAL.

Arquitetura da câmera do Android

Figura 1. Arquitetura da câmera

framework do app
No nível do framework do app está o código do app, que usa a API Camera 2 para interagir com o hardware da câmera. Internamente, esse código chama as interfaces Binder correspondentes para acessar o código nativo que interage com a câmera.
AIDL
A interface de vinculação associada a CameraService pode ser encontrada em frameworks/av/camera/aidl/android/hardware. O código gerado chama o código nativo de nível inferior para ter acesso à câmera física e retorna dados que são usados para criar os objetos CameraDevice e, eventualmente, CameraCaptureSession no nível do framework.
framework nativo
Esse framework, que fica em frameworks/av/, fornece um equivalente nativo às classes CameraDevice e CameraCaptureSession. Consulte também a referência do NDK camera2.
Interface de IPC do Binder
A interface de vinculação de IPC facilita a comunicação entre os limites do processo. Há várias classes de vinculação de câmera localizadas no diretório frameworks/av/camera/camera/aidl/android/hardware que chamam o serviço de câmera. ICameraService é a interface do serviço de câmera. ICameraDeviceUser é a interface de um dispositivo de câmera aberto específico. ICameraServiceListener e ICameraDeviceCallbacks são os respectivos callbacks CameraService e CameraDevice para o framework do app.
serviço de câmera
O serviço da câmera, localizado em frameworks/av/services/camera/libcameraservice/CameraService.cpp, é o código real que interage com o HAL.
HAL
A camada de abstração de hardware define a interface padrão que o serviço de câmera chama e que você precisa implementar para que o hardware da câmera funcione corretamente.

Implementar a HAL

A HAL fica entre o driver da câmera e o framework do Android de nível mais alto e define uma interface que você precisa implementar para que os apps possam operar corretamente o hardware da câmera. As interfaces HIDL para a HAL da câmera são definidas em hardware/interfaces/camera.

Uma HAL vinculada típica precisa implementar as seguintes interfaces HIDL:

As implementações de referência de HIDL estão disponíveis para CameraProvider.cpp, CameraDevice.cpp e CameraDeviceSession.cpp. A implementação envolve HALs antigos que ainda usam a API legada. A partir do Android 8.0, as implementações da HAL da câmera precisam usar a API HIDL. Não há suporte para o uso da interface legada.

Validação de entrada

Como o HAL tem acesso a recursos diferentes do serviço de câmera, a fronteira entre os dois é tratada como uma fronteira de segurança. Isso significa que os parâmetros transmitidos pelo serviço da câmera são considerados não confiáveis e não higienizados. Para evitar vulnerabilidades de segurança que permitem que invasores elevem privilégios ou acessem dados que não deveriam, a HAL da câmera precisa validar os parâmetros transmitidos do serviço da câmera para a HAL. Isso inclui verificar se os valores de comprimento do buffer estão dentro dos intervalos permitidos e limpar os parâmetros antes do uso e antes de transmiti-los aos drivers de hardware ou do kernel.

Componentes legados do HAL

Esta seção descreve a arquitetura dos componentes HAL legados e como implementar o HAL. As implementações do HAL da câmera no Android 8.0 e versões mais recentes precisam usar a API HIDL, conforme descrito acima.

Arquitetura (legado)

A figura e a lista a seguir descrevem os componentes legados do HAL da câmera.

Arquitetura da câmera do Android

Figura 2. Arquitetura legada da câmera

framework do app
No nível do framework do app está o código do app, que usa a API android.hardware.Camera para interagir com o hardware da câmera. Internamente, esse código chama uma classe de união JNI correspondente para acessar o código nativo que interage com a câmera.
JNI
O código JNI associado a android.hardware.Camera está localizado em frameworks/base/core/jni/android_hardware_Camera.cpp. Esse código chama o código nativo de nível inferior para ter acesso à câmera física e retorna dados usados para criar o objeto android.hardware.Camera no nível do framework.
framework nativo
A framework nativa definida em frameworks/av/camera/Camera.cpp fornece um equivalente nativo à classe android.hardware.Camera. Essa classe chama os proxies de vinculação IPC para ter acesso ao serviço da câmera.
Proxies IPC de vinculação
Os proxies do vinculador de IPC facilitam a comunicação entre os limites do processo. Há três classes de vinculação de câmera localizadas no diretório frameworks/av/camera que chama o serviço de câmera. ICameraService é a interface do serviço de câmera, ICamera é a interface de um dispositivo de câmera aberto específico e ICameraClient é a interface do dispositivo de volta ao framework do app.
serviço de câmera
O serviço da câmera, localizado em frameworks/av/services/camera/libcameraservice/CameraService.cpp, é o código real que interage com o HAL.
HAL
A camada de abstração de hardware define a interface padrão que o serviço de câmera chama e que você precisa implementar para que o hardware da câmera funcione corretamente.
driver do kernel
O driver da câmera interage com o hardware da câmera e com a implementação do HAL. A câmera e o driver precisam oferecer suporte aos formatos de imagem YV12 e NV21 para oferecer suporte à visualização da imagem da câmera na tela e à gravação de vídeo.

Implementar a HAL (legado)

A HAL fica entre o driver da câmera e o framework do Android de nível mais alto e define uma interface que você precisa implementar para que os apps possam operar corretamente o hardware da câmera. A interface HAL é definida nos arquivos de cabeçalho hardware/libhardware/include/hardware/camera.h e hardware/libhardware/include/hardware/camera_common.h.

camera_common.h define camera_module, uma estrutura padrão para receber informações gerais sobre a câmera, como o ID e as propriedades comuns a todas as câmeras (ou seja, se ela é frontal ou traseira).

camera.h contém o código que corresponde a android.hardware.Camera. Esse arquivo de cabeçalho declara uma estrutura camera_device que, por sua vez, contém uma estrutura camera_device_ops com ponteiros para funções que implementam a interface HAL. Para conferir a documentação sobre os parâmetros da câmera que os desenvolvedores podem definir, consulte frameworks/av/include/camera/CameraParameters.h. Esses parâmetros são definidos com a função indicada por int (*set_parameters)(struct camera_device *, const char *parms) no HAL.

Para conferir um exemplo de implementação de HAL, consulte a implementação do HAL do Galaxy Nexus em hardware/ti/omap4xxx/camera.

Configurar a biblioteca compartilhada

Configure o sistema de build do Android para empacotar corretamente a implementação do HAL em uma biblioteca compartilhada e copiá-la para o local apropriado criando um arquivo Android.mk:

  1. Crie um diretório device/<company_name>/<device_name>/camera para conter os arquivos de origem da biblioteca.
  2. Crie um arquivo Android.mk para criar a biblioteca compartilhada. Verifique se o makefile contém as seguintes linhas:
    LOCAL_MODULE := camera.<device_name>
    LOCAL_MODULE_RELATIVE_PATH := hw
    

    A biblioteca precisa ser chamada de camera.<device_name> (.so é anexado automaticamente) para que o Android possa carregar a biblioteca corretamente. Para conferir um exemplo, consulte o makefile da câmera do Galaxy Nexus localizado em hardware/ti/omap4xxx/Android.mk.

  3. Especifique que o dispositivo tem recursos de câmera copiando os arquivos XML de recursos necessários no diretório frameworks/native/data/etc com o makefile do dispositivo. Por exemplo, para especificar que o dispositivo tem um flash de câmera e pode focar automaticamente, adicione as seguintes linhas no makefile <device>/<company_name>/<device_name>/device.mk do dispositivo:
    PRODUCT_COPY_FILES := \ ...
    
    PRODUCT_COPY_FILES += \
    frameworks/native/data/etc/android.hardware.camera.flash-autofocus.xml:system/etc/permissions/android.hardware.camera.flash-autofocus.xml \
    

    Para conferir um exemplo de makefile de dispositivo, consulte device/samsung/tuna/device.mk.

  4. Declare os recursos de codec, formato e resolução de mídia da câmera nos arquivos XML device/<company_name>/<device_name>/media_profiles.xml e device/<company_name>/<device_name>/media_codecs.xml. Para mais detalhes, consulte Exposição de codecs ao framework.
  5. Adicione as linhas a seguir no makefile device/<company_name>/<device_name>/device.mk do dispositivo para copiar os arquivos media_profiles.xml e media_codecs.xml para o local apropriado:
    # media config xml file
    PRODUCT_COPY_FILES += \
        <device>/<company>/<device>/media_profiles.xml:system/etc/media_profiles.xml
    
    # media codec config xml file
    PRODUCT_COPY_FILES += \
        <device>/<company>/<device>/media_codecs.xml:system/etc/media_codecs.xml
    
  6. Para incluir o app Câmera na imagem do sistema do dispositivo, especifique-o na variável PRODUCT_PACKAGES no device/<company>/<device>/device.mk makefile do dispositivo:
    PRODUCT_PACKAGES := \
    Gallery2 \
    ...