El estilo de código HIDL se asemeja al código C++ en el framework de Android, con 4 espacios las sangrías y los nombres de archivo en mayúsculas y minúsculas. Declaraciones de paquetes, importaciones y docstrings son similares a las de Java, con pequeñas modificaciones.
Los siguientes ejemplos para IFoo.hal
y types.hal
ilustrar los estilos de código HIDL y proporcionar vínculos rápidos a los detalles de cada estilo
(IFooClientCallback.hal
, IBar.hal
y
se omitieron IBaz.hal
).
hardware/interfaces/foo/1.0/IFoo.hal |
---|
/* * (License Notice) */ package android.hardware.foo@1.0; import android.hardware.bar@1.0::IBar; import IBaz; import IFooClientCallback; /** * IFoo is an interface that… */ interface IFoo { /** * This is a multiline docstring. * * @return result 0 if successful, nonzero otherwise. */ foo() generates (FooStatus result); /** * Restart controller by power cycle. * * @param bar callback interface that… * @return result 0 if successful, nonzero otherwise. */ powerCycle(IBar bar) generates (FooStatus result); /** Single line docstring. */ baz(); /** * The bar function. * * @param clientCallback callback after function is called * @param baz related baz object * @param data input data blob */ bar(IFooClientCallback clientCallback, IBaz baz, FooData data); }; |
hardware/interfaces/foo/1.0/types.hal |
---|
/* * (License Notice) */ package android.hardware.foo@1.0; /** Replied status. */ enum Status : int32_t { OK, /* invalid arguments */ ERR_ARG, /* note, no transport related errors */ ERR_UNKNOWN = -1, }; struct ArgData { int32_t[20] someArray; vec<uint8_t> data; }; |
Convenciones de nombres
Los nombres de funciones, de variables y de archivos deben ser descriptivos. evitar
sobre la abreviatura. Trata los acrónimos como palabras (por ejemplo, usa INfc
en su lugar).
de INFC
).
Estructura de directorios y nomenclatura de archivos
La estructura del directorio debería aparecer de la siguiente manera:
ROOT-DIRECTORY
MODULE
SUBMODULE
(opcional, podría ser más de uno) a nivel)VERSION
Android.mk
IINTERFACE_1.hal
IINTERFACE_2.hal
…
IINTERFACE_N.hal
types.hal
(opcional)
donde:
ROOT-DIRECTORY
es:hardware/interfaces
para los paquetes principales de HIDLvendor/VENDOR/interfaces
para paquetes de proveedores en el queVENDOR
se refiere a un proveedor de SoC o a un OEM/ODM
MODULE
debe ser una palabra minúscula que describa el subsistema (por ejemplo,nfc
). Si se necesita más de una palabra, usaSUBMODULE
anidada. Puede haber más de un nivel durante el período de anidación.VERSION
debe ser exactamente la misma versión (major.minor), como se describe en Versiones.IINTERFACE_X
debe ser el nombre de la interfaz conUpperCamelCase
/PascalCase
(por ejemplo,INfc
) como se describe en Nombres de interfaces.
Ejemplo:
hardware/interfaces
nfc
1.0
Android.mk
INfc.hal
INfcClientCallback.hal
types.hal
Nota: Todos los archivos no deben tener permisos ejecutables permisos (en Git).
Nombres de los paquetes
Los nombres de los paquetes deben contener el siguiente nombre completamente calificado
(FQN) (denominado PACKAGE-NAME
):
PACKAGE.MODULE[.SUBMODULE[.SUBMODULE[…]]]@VERSION
donde:
PACKAGE
es el paquete que se asigna alROOT-DIRECTORY
En particular,PACKAGE
es:android.hardware
para los paquetes principales de HIDL (asignación ahardware/interfaces
).vendor.VENDOR.hardware
para paquetes de proveedores, en los queVENDOR
hace referencia a un proveedor de SoC o a un OEM/ODM (asignación avendor/VENDOR/interfaces
).
MODULE[.SUBMODULE[.SUBMODULE[…]]]@VERSION
sean exactamente los mismos nombres de carpetas en la estructura descrita en Estructura del directorio.- Los nombres de los paquetes deben estar en minúscula. Si tienen más de una palabra, el
las palabras deben usarse como submódulos o escribirse en
snake_case
. - No se permiten espacios.
El FQN siempre se usa en las declaraciones de paquetes.
Versiones
Las versiones deben tener el siguiente formato:
MAJOR.MINOR
Tanto la versión MAJOR como la MINOR deben ser una sola entero. El HIDL usa semántica control de versiones.
Importaciones
Una importación tiene uno de los siguientes tres formatos:
- Importaciones de paquetes completos:
import PACKAGE-NAME;
- Importaciones parciales:
import PACKAGE-NAME::UDT;
(o, si el valor importado está en el mismo paquete,import UDT;
- Importaciones de solo tipos:
import PACKAGE-NAME::types;
PACKAGE-NAME
sigue el formato de
Nombres de paquetes. La propiedad del paquete actual
types.hal
(si existe) se importa automáticamente (no importar
explícitamente).
Nombres completamente calificados (FQN)
Usa nombres completos para una importación de tipos definidos por el usuario solo cuando sea necesario.
Omite PACKAGE-NAME
si el tipo de importación está en el mismo
. Un FQN no debe contener espacios. Ejemplo de un nombre completamente calificado:
android.hardware.nfc@1.0::INfcClientCallback
En otro archivo en android.hardware.nfc@1.0
, consulta el
arriba de la interfaz como INfcClientCallback
. De lo contrario, usa solo el
nombre completamente calificado.
Agrupa y ordena importaciones
Usa una línea vacía después de la declaración del paquete (antes de las importaciones). Cada importación deben ocupar una sola línea y no deben tener sangría. Agrupa las importaciones siguiente orden:
- Otros paquetes
android.hardware
(usa nombres completamente calificados). - Otros paquetes de
vendor.VENDOR
(usa completamente calificados nombres).- Cada proveedor debe ser un grupo.
- Ordena los proveedores alfabéticamente.
- Importaciones desde otras interfaces en el mismo paquete (usa nombres simples).
Usa una línea vacía entre grupos. Ordena las importaciones dentro de cada grupo alfabéticamente. Ejemplo:
import android.hardware.nfc@1.0::INfc; import android.hardware.nfc@1.0::INfcClientCallback; /* Importing the whole module. */ import vendor.barvendor.bar@3.1; import vendor.foovendor.foo@2.2::IFooBar; import vendor.foovendor.foo@2.2::IFooFoo; import IBar; import IFoo;
Nombres de la interfaz
Los nombres de la interfaz deben comenzar con un I
, seguido de un
Nombre UpperCamelCase
/PascalCase
. Una interfaz con nombre
IFoo
debe definirse en el archivo IFoo.hal
. Este archivo
Puede contener definiciones solo para la interfaz IFoo
(la interfaz
INAME
debe estar en INAME.hal
).
Funciones
Para nombres de funciones, argumentos y nombres de variables que se devuelven, usa
lowerCamelCase
Ejemplo:
open(INfcClientCallback clientCallback) generates (int32_t retVal); oneway pingAlive(IFooCallback cb);
Nombres de campos de struct y union
Para los nombres de campos de struct o unión, usa lowerCamelCase
. Ejemplo:
struct FooReply { vec<uint8_t> replyData; }
Nombres de tipos
Los nombres de tipo hacen referencia a definiciones de struct o unión, definiciones de tipos de enumeración y
typedef
Para estos nombres, usa
UpperCamelCase
por PascalCase
. Ejemplos:
enum NfcStatus : int32_t { /*...*/ }; struct NfcData { /*...*/ };
Enum. de valores
Los valores de enumeración deben ser UPPER_CASE_WITH_UNDERSCORES
. Al pasar
enum como argumentos de funciones y los mostrarás como resultado de la función, usa
el tipo de enumeración real (no el tipo de número entero subyacente). Ejemplo:
enum NfcStatus : int32_t { HAL_NFC_STATUS_OK = 0, HAL_NFC_STATUS_FAILED = 1, HAL_NFC_STATUS_ERR_TRANSPORT = 2, HAL_NFC_STATUS_ERR_CMD_TIMEOUT = 3, HAL_NFC_STATUS_REFUSED = 4 };
Nota: El tipo subyacente de un tipo enum es declarada explícitamente después de los dos puntos. Como no depende del compilador, usa el el tipo enum real es más claro.
En el caso de los nombres completamente calificados para los valores de enumeración, se usa dos puntos. entre el nombre del tipo de enumeración y el nombre del valor de enumeración:
PACKAGE-NAME::UDT[.UDT[.UDT[…]]:ENUM_VALUE_NAME
No debe haber espacios dentro de un nombre completamente calificado. Usa una solución completamente calificada el nombre solo cuando sea necesario y omitir las partes innecesarias. Ejemplo:
android.hardware.foo@1.0::IFoo.IFooInternal.FooEnum:ENUM_OK
Comentarios
Para un comentario de una sola línea, //
, /* */
y /** */
están bien.
// This is a single line comment /* This is also single line comment */ /** This is documentation comment */
-
Usa
/* */
para los comentarios. Si bien HIDL admite//
para los comentarios, no se recomienda porque no aparecen en la salida generada. - Usa
/** */
para la documentación generada. Estas se pueden aplicar solo para declaraciones de tipo, método, campo y enum. Ejemplo:/** Replied status */ enum TeleportStatus { /** Object entirely teleported. */ OK = 0, /** Methods return this if teleportation is not completed. */ ERROR_TELEPORT = 1, /** * Teleportation could not be completed due to an object * obstructing the path. */ ERROR_OBJECT = 2, ... }
- Inicia comentarios de varias líneas con
/**
en una línea separada. Usa*
al comienzo de cada línea. Finaliza el comentario con*/
en una línea separada y alinea los asteriscos. Ejemplo:/** * My multi-line * comment */
- El aviso de licencia y los registros de cambios deben comenzar una nueva línea con
/*
. (un solo asterisco), utiliza*
al principio de cada línea y coloca*/
en la última línea por su cuenta (los asteriscos deben alinearse). Ejemplo:/* * Copyright (C) 2017 The Android Open Source Project * ... */ /* * Changelog: * ... */
Comentarios de archivos
Inicia cada archivo con el aviso de licencia correspondiente. Para las HAL principales, este
debería ser la licencia Apache del AOSP en
development/docs/copyright-templates/c.txt
Recuerda actualizar el año y usar comentarios de varias líneas del estilo /* */
como se explicó anteriormente.
También puedes colocar una línea vacía después del aviso de licencia, seguido de
por un registro de cambios
o información sobre el control de versiones. Usar el estilo /* */
comentarios de varias líneas, como se explicó anteriormente, coloca la línea vacía después del
el registro de cambios y continúa con la declaración del paquete.
Comentarios TODO
Los comentarios "TODO" deben incluir la cadena TODO
en mayúsculas seguida de un
dos puntos. Ejemplo:
// TODO: remove this code before foo is checked in.
Los comentarios "TODO" solo se permiten durante el desarrollo; deben no existen en las interfaces publicadas.
Comentarios de interfaz y función (docstrings)
Usa /** */
para docstrings de una o varias líneas. No usar
//
para docstrings.
Las docstrings para interfaces deben describir mecanismos generales de la interfaz, la lógica del diseño, el propósito, etc. Las docstrings para las funciones deben ser específicas de la función (la documentación a nivel del paquete va en un archivo README en el directorio del paquete).
/** * IFooController is the controller for foos. */ interface IFooController { /** * Opens the controller. * * @return status HAL_FOO_OK if successful. */ open() generates (FooStatus status); /** Close the controller. */ close(); };
Debes agregar elementos @param
y @return
para cada uno.
valor del parámetro o que se muestra:
- Se debe agregar
@param
para cada parámetro. Debe ser seguido del nombre del parámetro y, luego, la docstring. - Se debe agregar
@return
para cada valor que se muestra. Integra debe estar seguido por el nombre del valor que se devuelve y, luego, por la docstring.
Ejemplo:
/** * Explain what foo does. * * @param arg1 explain what arg1 is * @param arg2 explain what arg2 is * @return ret1 explain what ret1 is * @return ret2 explain what ret2 is */ foo(T arg1, T arg2) generates (S ret1, S ret2);
Reglas de formato
Las reglas de formato generales incluyen lo siguiente:
- Longitud de la línea: Cada línea de texto debe tener, como máximo, 100 columnas de longitud
- Espacios en blanco. No debe haber espacios en blanco al final en las líneas. líneas vacías No debe contener espacios en blanco.
- Espacios frente a pestañas. Usa solo espacios.
- Tamaño de sangría. Usa 4 espacios para los bloques y 8 espacios para las uniones de líneas
- Antigüedad. Excepto por la anotación
valores, una llave open va en la misma línea que la anterior
pero una llave de cerrar y ocupar el siguiente punto y coma
toda la línea. Ejemplo:
interface INfc { close(); };
Declaración del paquete
La declaración del paquete debe aparecer en la parte superior del archivo después de la licencia debe ocupar toda la línea y no debe tener sangría. Los paquetes son declarada con el siguiente formato (para el formato de nombre, consulta Nombres de paquetes):
package PACKAGE-NAME;
Ejemplo:
package android.hardware.nfc@1.0;
Declaraciones de funciones
El nombre de la función, los parámetros, generates
y los valores que se muestran deben
estar en la misma línea si encajan. Ejemplo:
interface IFoo { /** ... */ easyMethod(int32_t data) generates (int32_t result); };
Si no caben en la misma línea, intenta colocar los parámetros y devolver
valores en el mismo nivel de sangría y distinguir generate
para ayudar
el lector a ver rápidamente los parámetros y devolver valores. Ejemplo:
interface IFoo { suchALongMethodThatCannotFitInOneLine(int32_t theFirstVeryLongParameter, int32_t anotherVeryLongParameter); anEvenLongerMethodThatCannotFitInOneLine(int32_t theFirstLongParameter, int32_t anotherVeryLongParameter) generates (int32_t theFirstReturnValue, int32_t anotherReturnValue); superSuperSuperSuperSuperSuperSuperLongMethodThatYouWillHateToType( int32_t theFirstVeryLongParameter, // 8 spaces int32_t anotherVeryLongParameter ) generates ( int32_t theFirstReturnValue, int32_t anotherReturnValue ); /* method name is even shorter than 'generates' */ foobar(AReallyReallyLongType aReallyReallyLongParameter, AReallyReallyLongType anotherReallyReallyLongParameter) generates (ASuperLongType aSuperLongReturnValue, // 4 spaces ASuperLongType anotherSuperLongReturnValue); }
Detalles adicionales:
- Un paréntesis abierto siempre está en la misma línea que el nombre de la función.
- No debe haber espacios entre el nombre de la función y el paréntesis abierto.
- Sin espacios entre paréntesis y parámetros, excepto cuando haya hay feeds de líneas entre ellos.
- Si
generates
está en la misma línea que el cierre anterior paréntesis, utiliza un espacio precedente. Sigenerates
está en el mismo como el siguiente paréntesis de apertura y luego con un espacio. - Alinea todos los parámetros y devuelve los valores (si es posible).
- La sangría predeterminada es de 4 espacios.
- Los parámetros unidos se alinean con los primeros parámetros de la línea anterior, de lo contrario, tendrán una sangría de 8 espacios.
Anotaciones
Usa el siguiente formato para las anotaciones:
@annotate(keyword = value, keyword = {value, value, value})
Ordena las anotaciones por orden alfabético y usa espacios alrededor del signo igual. Ejemplo:
@callflow(key = value) @entry @exit
Asegúrate de que una anotación ocupe toda la línea. Ejemplos:
/* Good */ @entry @exit /* Bad */ @entry @exit
Si las anotaciones no caben en la misma línea, aplica una sangría de 8 espacios. Ejemplo:
@annotate( keyword = value, keyword = { value, value }, keyword = value)
Si toda la matriz de valores no cabe en la misma línea, coloca saltos de línea después.
Abre las llaves {
y, después de cada coma dentro del array. Cierre del lugar
paréntesis inmediatamente después del último valor. No coloques las llaves si hay
solo un valor.
Si todo el array de valores puede caber en la misma línea, no uses espacios después de abra las llaves y, antes de cerrarlas, y use un espacio después de cada coma. Ejemplos:
/* Good */ @callflow(key = {"val", "val"}) /* Bad */ @callflow(key = { "val","val" })
NO debe haber líneas vacías entre las anotaciones y la función declaración. Ejemplos:
/* Good */ @entry foo(); /* Bad */ @entry foo();
Declaraciones de enumeración
Usa las siguientes reglas para las declaraciones enum:
- Si se comparten declaraciones de enumeración con otro paquete, colócalas.
en
types.hal
en lugar de incorporarlos en una interfaz. - Se debe usar un espacio antes y después de los dos puntos y un espacio después del tipo subyacente antes de la llave de apertura.
- Es posible que el último valor de enumeración no tenga una coma adicional.
Declaraciones struct
Usa las siguientes reglas para las declaraciones de struct:
- Si las declaraciones de struct se comparten con otro paquete, colócalas.
en
types.hal
en lugar de incorporarlos en una interfaz. - Usa un espacio después del nombre del tipo de struct antes de la llave de apertura.
- Alinea los nombres de los campos (opcional). Ejemplo:
struct MyStruct { vec<uint8_t> data; int32_t someInt; }
Declaraciones de arrays
No coloques espacios entre los siguientes elementos:
- Tipo de elemento y corchete de apertura.
- Abra el corchete cuadrado y el tamaño del array.
- Tamaño del array y corchete de cierre
- Corchete de cierre y el siguiente corchete de apertura (si hay más de uno) existe una dimensión.
Ejemplos:
/* Good */ int32_t[5] array; /* Good */ int32_t[5][6] multiDimArray; /* Bad */ int32_t [ 5 ] [ 6 ] array;
Vectores
No coloques espacios entre los siguientes elementos:
vec
y abre un corchete angular.- Abra el corchete angular y el tipo de elemento (Excepción: El tipo de elemento también es una
vec
). - Tipo de elemento y corchete angular de cierre (Excepción: El tipo de elemento también es un
vec
).
Ejemplos:
/* Good */ vec<int32_t> array; /* Good */ vec<vec<int32_t>> array; /* Good */ vec< vec<int32_t> > array; /* Bad */ vec < int32_t > array; /* Bad */ vec < vec < int32_t > > array;