Creación de la interfaz HAL

Debe usar HIDL para describir todos los indicadores de compilación utilizados para compilar condicionalmente el marco. Los indicadores de compilación relevantes deben agruparse e incluirse en un solo archivo .hal . El uso de HIDL para especificar elementos de configuración incluye los siguientes beneficios:

  • Versionado (para agregar nuevos elementos de configuración, los proveedores/OEM deben ampliar explícitamente la HAL)
  • Bien documentado
  • Control de acceso usando SELinux
  • Verificación de integridad de los elementos de configuración a través de Vendor Test Suite (verificación de rango, verificación de interdependencia entre elementos, etc.)
  • API generadas automáticamente en C++ y Java

Identificación de indicadores de compilación utilizados por el marco

Comience identificando las configuraciones de compilación utilizadas para compilar condicionalmente el marco, luego abandone las configuraciones obsoletas para hacer que el conjunto sea más pequeño. Por ejemplo, el siguiente conjunto de indicadores de compilación se identifican para surfaceflinger :

  • TARGET_USES_HWC2
  • TARGET_BOARD_PLATFORM
  • TARGET_DISABLE_TRIPLE_BUFFERING
  • TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS
  • NUM_FRAMEBUFFER_SURFACE_BUFFERS
  • TARGET_RUNNING_WITHOUT_SYNC_FRAMEWORK
  • VSYNC_EVENT_PHASE_OFFSET_NS
  • SF_VSYNC_EVENT_PHASE_OFFSET_NS
  • PRESENT_TIME_OFFSET_FROM_VSYNC_NS
  • MAX_VIRTUAL_DISPLAY_DIMENSION

Creación de una interfaz HAL

Se accede a las configuraciones de compilación para un subsistema a través de una interfaz HAL, mientras que las interfaces para proporcionar valores de configuración se agrupan en el paquete HAL android.hardware.configstore (actualmente en la versión 1.0). Por ejemplo, para crear un archivo de interfaz HAL para surfaceflinger , en hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal :

package android.hardware.configstore@1.0;

interface ISurfaceFlingerConfigs {
    // TO-BE-FILLED-BELOW
};

Después de crear el archivo .hal , ejecute hardware/interfaces/update-makefiles.sh para agregar el nuevo archivo .hal a los archivos Android.bp y Android.mk .

Adición de funciones para indicadores de compilación

Para cada indicador de compilación, agregue una nueva función a la interfaz. Por ejemplo, en hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal :

interface ISurfaceFlingerConfigs {
    disableTripleBuffering() generates(OptionalBool ret);
    forceHwcForVirtualDisplays() generates(OptionalBool ret);
    enum NumBuffers: uint8_t {
        USE_DEFAULT = 0,
        TWO = 2,
        THREE = 3,
    };
    numFramebufferSurfaceBuffers() generates(NumBuffers ret);
    runWithoutSyncFramework() generates(OptionalBool ret);
    vsyncEventPhaseOffsetNs generates (OptionalUInt64 ret);
    presentTimeOffsetFromSyncNs generates (OptionalUInt64 ret);
    maxVirtualDisplayDimension() generates(OptionalInt32 ret);
};

Al agregar una función:

  • Sea conciso con los nombres. Evite convertir nombres de variables de archivos MAKE en nombres de funciones y tenga en cuenta que los prefijos TARGET_ y BOARD_ ya no son necesarios.
  • Añadir comentarios. Ayude a los desarrolladores a comprender el propósito del elemento de configuración, cómo cambia el comportamiento del marco, los valores válidos y otra información relevante.

Los tipos de devolución de función pueden ser Optional[Bool|String|Int32|UInt32|Int64|UInt64] . Los tipos se definen en types.hal en el mismo directorio y envuelven los valores primitivos con un campo que indica si el HAL especifica el valor; si no, se utiliza el valor predeterminado.

struct OptionalString {
    bool specified;
    string value;
};

Cuando corresponda, defina la enumeración que mejor represente el tipo de elemento de configuración y use esa enumeración como el tipo de devolución. En el ejemplo anterior, la enumeración NumBuffers se define para limitar el número de valores válidos. Al definir estos tipos de datos personalizados, agregue un campo o un valor de enumeración (por ejemplo, USE_DEFAULT ) para indicar si el valor está o no especificado por HAL.

No es obligatorio que un único indicador de compilación se convierta en una función única en HIDL. Los propietarios de módulos pueden, alternativamente, agregar indicadores de compilación estrechamente relacionados en una estructura y tener una función que devuelva esa estructura (al hacerlo, se puede reducir la cantidad de llamadas a funciones).

Por ejemplo, una opción para agregar dos indicadores de compilación en una sola estructura en hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal es:

 interface ISurfaceFlingerConfigs {
    // other functions here
    struct SyncConfigs {
        OptionalInt64 vsyncEventPhaseoffsetNs;
        OptionalInt64 presentTimeoffsetFromSyncNs;
    };
    getSyncConfigs() generates (SyncConfigs ret);
    // other functions here
};

Alternativas a una sola función HAL

Como alternativa al uso de una sola función HAL para todos los indicadores de compilación, la interfaz HAL también proporciona funciones simples como getBoolean(string key) y getInteger(string key) . Los pares key=value reales se almacenan en archivos separados y el servicio HAL proporciona valores al leer/analizar esos archivos.

Si bien este enfoque es fácil de definir, no incluye los beneficios proporcionados por HIDL (versiones forzadas, facilidad de documentación, control de acceso) y, por lo tanto, no se recomienda.

Interfaces únicas y múltiples

El diseño de la interfaz HAL para elementos de configuración presenta dos opciones:

  • Una sola interfaz que cubre todos los elementos de configuración
  • Múltiples interfaces, cada una de las cuales cubre un conjunto de elementos de configuración relacionados

Una sola interfaz es más fácil, pero puede volverse imposible de mantener a medida que se agregan más elementos de configuración al archivo único. Además, el control de acceso no es detallado, por lo que un proceso al que se le otorga acceso a la interfaz puede leer todos los elementos de configuración (no se puede otorgar acceso a un conjunto parcial de elementos de configuración). Alternativamente, si no se otorga acceso, los elementos de configuración no se pueden leer.

Debido a estos problemas, Android usa múltiples interfaces con una sola interfaz HAL para un grupo de elementos de configuración relacionados. Por ejemplo, ISurfaceflingerConfigs para elementos de configuración relacionados con surfaceflinger e IBluetoothConfigs para elementos de configuración relacionados con Bluetooth.