Google se compromete a impulsar la igualdad racial para las comunidades afrodescendientes. Obtén información al respecto.
Se usó la API de Cloud Translation para traducir esta página.
Switch to English

Guía de estilo de código

El estilo del código HIDL se asemeja al código C ++ en el marco de Android, con sangrías de 4 espacios y nombres de archivo con mayúsculas y minúsculas. Las declaraciones, importaciones y cadenas de documentos de paquetes son similares a las de Java, con ligeras modificaciones.

Los siguientes ejemplos de IFoo.hal y types.hal ilustran los estilos de código HIDL y proporcionan enlaces rápidos a los detalles de cada estilo (se han omitido IFooClientCallback.hal , IBar.hal e 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 las funciones, los nombres de las variables y los nombres de los archivos deben ser descriptivos; Evite la abreviatura excesiva. Trate los acrónimos como palabras (p. Ej., INfc lugar de INFC ).

Estructura de directorios y nombres de archivos

La estructura del directorio debería aparecer de la siguiente manera:

  • ROOT-DIRECTORY
    • MODULE
      • SUBMODULE (opcional, puede tener más de un nivel)
        • VERSION
          • Android.mk
          • I INTERFACE_1 .hal
          • I INTERFACE_2 .hal
          • I INTERFACE_N .hal
          • types.hal (opcional)

Dónde:

  • ROOT-DIRECTORY es:
    • hardware/interfaces para paquetes HIDL principales.
    • vendor/ VENDOR /interfaces para paquetes de proveedores, donde VENDOR refiere a un proveedor de SoC o un OEM / ODM.
  • MODULE debe ser una palabra en minúscula que describa el subsistema (por ejemplo, nfc ). Si se necesita más de una palabra, use SUBMODULE anidado. Puede haber más de un nivel de anidamiento.
  • VERSION debe ser exactamente la misma versión (mayor, menor) que se describe en Versiones .
  • I INTERFACE_X debe ser el nombre de la interfaz con UpperCamelCase / PascalCase (por ejemplo INfc ) como se describe en los nombres de interfaz .

Ejemplo:

  • hardware/interfaces
    • nfc
      • 1.0
        • Android.mk
        • INfc.hal
        • INfcClientCallback.hal
        • types.hal

Nota: Todos los archivos deben tener permisos no ejecutables (en Git).

Nombres de paquetes

Los nombres de los paquetes deben utilizar el siguiente formato de nombre completo (FQN) (denominado PACKAGE-NAME ):

PACKAGE.MODULE[.SUBMODULE[.SUBMODULE[…]]]@VERSION

Dónde:

  • PACKAGE es el paquete que se asigna al ROOT-DIRECTORY . En particular, el PACKAGE es:
    • android.hardware para paquetes HIDL centrales (mapeo a hardware/interfaces ).
    • vendor. VENDOR .hardware para paquetes de proveedores, donde VENDOR refiere a un proveedor de SoC o un OEM / ODM (mapeo a vendor/ VENDOR /interfaces ).
  • MODULE [. SUBMODULE [. SUBMODULE […]]]@ VERSION son exactamente los mismos nombres de carpeta en la estructura descrita en Estructura de directorios .
  • Los nombres de los paquetes deben estar en minúsculas. Si tienen más de una palabra, las palabras deben usarse como submódulos o escribirse en snake_case .
  • No se permiten espacios.

El FQN siempre se usa en declaraciones de paquetes.

Versiones

Las versiones deben tener el siguiente formato:

MAJOR.MINOR

Tanto la versión MAJOR como la MINOR deben ser un solo entero. HIDL utiliza reglas de control de versiones semánticas .

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 tipo importado está en el mismo paquete, import UDT ;
  • Importaciones de solo tipos: import PACKAGE-NAME ::types;

El PACKAGE-NAME sigue el formato de los nombres de los paquetes . El types.hal del paquete actual (si existe) se importa automáticamente (no lo importe explícitamente).

Nombres completamente calificados (FQN)

Utilice nombres completos para una importación de tipo definido por el usuario solo cuando sea necesario. Omita PACKAGE-NAME si el tipo de importación está en el mismo paquete. 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 , consulte la interfaz anterior como INfcClientCallback . De lo contrario, utilice solo el nombre completo.

Agrupar y ordenar importaciones

Utilice una línea vacía después de la declaración del paquete (antes de las importaciones). Cada importación debe ocupar una sola línea y no debe tener sangría. Agrupe las importaciones en el siguiente orden:

  1. Otros paquetes de android.hardware (use nombres completos).
  2. Otro vendor. VENDOR Paquetes vendor. VENDOR (use nombres completos).
    • Cada proveedor debe ser un grupo.
    • Ordene a los proveedores alfabéticamente.
  3. Importaciones de otras interfaces en el mismo paquete (use nombres simples).

Utilice una línea vacía entre los grupos. Dentro de cada grupo, ordena las importaciones 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 interfaz

Los nombres de interfaces deben comenzar con una I , seguido de un UpperCamelCase / PascalCase nombre. Debe definirse una interfaz con el nombre IFoo en el archivo IFoo.hal . Este archivo puede contener definiciones solo para la interfaz IFoo (la interfaz I NAME debe estar en I NAME .hal ).

Funciones

Para nombres de funciones, argumentos y nombres de variables de retorno, use lowerCamelCase . Ejemplo:

open(INfcClientCallback clientCallback) generates (int32_t retVal);
oneway pingAlive(IFooCallback cb);

Nombres de campo de estructura / unión

Para nombres de campo de estructura / unión, use lowerCamelCase . Ejemplo:

struct FooReply {
    vec<uint8_t> replyData;
}

Nombres de tipo

Nombres de los tipos se refieren a las definiciones struct / unión, las definiciones de tipo de enumeración, y typedef s. Para estos nombres, utilice UpperCamelCase / PascalCase . Ejemplos:

enum NfcStatus : int32_t {
    /*...*/
};
struct NfcData {
    /*...*/
};

Valores de enumeración

Los valores de UPPER_CASE_WITH_UNDERSCORES deben ser UPPER_CASE_WITH_UNDERSCORES . Al pasar valores de enumeración como argumentos de función y devolverlos como retornos de función, use el tipo de enumeración real (no el tipo 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 de enumeración se declara explícitamente después de los dos puntos. Como no depende del compilador, el uso del tipo de enumeración real es más claro.

Para nombres completos para valores de enumeración, se utilizan 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 completo. Utilice un nombre completo solo cuando sea necesario y omita las piezas 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 */
  • Utilice /* */ para comentarios. Si bien HIDL admite // para comentarios, se desaconseja porque no aparecen en la salida generada.
  • Utilice /** */ para la documentación generada. Estos se pueden aplicar solo a declaraciones de valor de tipo, método, campo y enumeración. 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,
        ...
    }
    
  • Inicie comentarios de varias líneas con /** en una línea separada. Utilice * al comienzo de cada línea. Termine el comentario con */ en una línea separada, alineando 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), usar * al principio de cada línea y colocar */ en la última línea por sí solo (los asteriscos deben alinearse). Ejemplo:
    /*
     * Copyright (C) 2017 The Android Open Source Project
     * ...
     */
    
    /*
     * Changelog:
     * ...
     */
    

Comentarios de archivo

Inicie cada archivo con el aviso de licencia correspondiente. Para los HAL principales, esta debería ser la licencia AOSP Apache en development/docs/copyright-templates/c.txt . Recuerde actualizar el año y usar /* */ estilo comentarios de varias líneas como se explicó anteriormente.

Opcionalmente, puede colocar una línea vacía después del aviso de licencia, seguida de un registro de cambios / información de versiones. Use /* */ estilo comentarios de varias líneas como se explicó anteriormente, coloque la línea vacía después del registro de cambios, luego siga con la declaración del paquete.

TODO comentarios

Los TODO deben incluir la cadena TODO en mayúsculas seguida de dos puntos. Ejemplo:

// TODO: remove this code before foo is checked in.

Los comentarios TODO se permiten solo durante el desarrollo; no deben existir en interfaces publicadas.

Comentarios de interfaz / función (cadenas de documentación)

Utilice /** */ para cadenas de documentos multilínea y de una sola línea. No use // para cadenas de documentos.

Las cadenas de documentos para las interfaces deben describir los mecanismos generales de la interfaz, la razón de ser del diseño, el propósito, etc. Las cadenas de documentos para las funciones deben ser específicas de la función (la documentación a nivel de 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();
};

Debe agregar @param sy @return s para cada parámetro / valor de retorno:

  • @param debe agregar @param para cada parámetro. Debe ir seguido del nombre del parámetro y luego la cadena de documentos.
  • @return debe agregarse para cada valor de retorno. Debe ir seguido del nombre del valor de retorno y luego la cadena de documentos.

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);

Formateo

Las reglas generales de formato incluyen:

  • Longitud de la línea . Cada línea de texto debe tener un máximo de 100 columnas.
  • Espacios en blanco . Sin espacios en blanco finales en las líneas; las líneas vacías no deben contener espacios en blanco.
  • Espacios frente a pestañas . Utilice solo espacios.
  • Tamaño de sangría . Utilice 4 espacios para bloques y 8 espacios para envolturas de línea
  • Refuerzo . A excepción de los valores de anotación , una llave abierta va en la misma línea que el código anterior, pero una llave cerrada y el siguiente punto y coma ocupa toda la línea. Ejemplo:
    interface INfc {
        close();
    };
    

Declaración de paquete

La declaración del paquete debe estar en la parte superior del archivo después del aviso de licencia, debe ocupar toda la línea y no debe tener sangría. Los paquetes se declaran utilizando el siguiente formato (para el formato de nombres , consulte 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, las generates y los valores de retorno deben estar en la misma línea si encajan. Ejemplo:

interface IFoo {
    /** ... */
    easyMethod(int32_t data) generates (int32_t result);
};

Si no encajan en la misma línea, intente poner los parámetros y los valores de retorno en el mismo nivel de sangría y distinguir generate para ayudar al lector a ver rápidamente los parámetros y los valores de retorno. 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.
  • Sin espacios entre el nombre de la función y el paréntesis abierto.
  • No hay espacios entre paréntesis y parámetros, excepto cuando hay cambios de línea entre ellos.
  • Si generates está en la misma línea que el paréntesis de cierre anterior, use un espacio anterior. Si generates está en la misma línea que el siguiente paréntesis abierto, siga con un espacio.
  • Alinear todos los parámetros y devolver los valores (si es posible).
  • La sangría predeterminada es de 4 espacios.
  • Los parámetros ajustados se alinean con los primeros parámetros de la línea anterior; de lo contrario, tienen una sangría de 8 espacios.

Anotaciones

Utilice el siguiente formato para las anotaciones:

@annotate(keyword = value, keyword = {value, value, value})

Ordene las anotaciones en orden alfabético y use espacios alrededor de los signos iguales. Ejemplo:

@callflow(key = value)
@entry
@exit

Asegúrese de que una anotación ocupe toda la línea. Ejemplos:

/* Good */
@entry
@exit

/* Bad */
@entry @exit

Si las anotaciones no pueden caber en la misma línea, sangra con 8 espacios. Ejemplo:

@annotate(
        keyword = value,
        keyword = {
                value,
                value
        },
        keyword = value)

Si toda la matriz de valores no puede caber en la misma línea, coloque saltos de línea después de las llaves abiertas { y después de cada coma dentro de la matriz. Coloque el paréntesis de cierre inmediatamente después del último valor. No ponga las llaves si solo hay un valor.

Si toda la matriz de valores puede caber en la misma línea, no use espacios después de las llaves abiertas y antes de las llaves de cierre 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 declaración de la función. Ejemplos:

/* Good */
@entry
foo();

/* Bad */
@entry

foo();

Declaraciones de enumeración

Utilice las siguientes reglas para las declaraciones de enumeración:

  • Si las declaraciones de enumeración se comparten con otro paquete, coloque las declaraciones en types.hal en lugar de incrustarlas dentro de una interfaz.
  • Use un espacio antes y después del colon, y un espacio después del tipo subyacente antes del corsé abierto.
  • El último valor de enumeración puede tener o no una coma adicional.

Declaraciones de estructura

Utilice las siguientes reglas para las declaraciones de estructura:

  • Si las declaraciones de estructura se comparten con otro paquete, coloque las declaraciones en types.hal en lugar de incrustarlas dentro de una interfaz.
  • Use un espacio después del nombre del tipo de estructura antes de la llave abierta.
  • Alinear nombres de campo (opcional). Ejemplo:
    struct MyStruct {
        vec<uint8_t>   data;
        int32_t        someInt;
    }
    

Declaraciones de matriz

No ponga espacios entre lo siguiente:

  • Tipo de elemento y corchete abierto.
  • Abra el corchete y el tamaño de la matriz.
  • Tamaño de matriz y corchete de cierre.
  • Cierre el corchete y el siguiente corchete abierto, si existe más de una dimensión.

Ejemplos:

/* Good */
int32_t[5] array;

/* Good */
int32_t[5][6] multiDimArray;

/* Bad */
int32_t [ 5 ] [ 6 ] array;

Vectores

No ponga espacios entre lo siguiente:

  • vec y corchete de ángulo abierto.
  • Soporte de ángulo abierto y tipo de elemento ( Excepción: el tipo de elemento también es un vec ).
  • Tipo de elemento y corchete de ángulo cerrado ( 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;