Kod Stili Kılavuzu

HIDL kod stili, 4 boşluklu girintiler ve karışık dosya adlarıyla Android çerçevesindeki C++ koduna benzer. Paket bildirimleri, içe aktarmaları ve belge dizileri, küçük değişikliklerle Java'dakilere benzer.

Aşağıdaki IFoo.hal ve types.hal örnekleri, HIDL kod stillerini gösterir ve her stille ilgili ayrıntılara hızlı bağlantılar sağlar ( IFooClientCallback.hal , IBar.hal ve IBaz.hal çıkarılmıştır).

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

adlandırma kuralları

İşlev adları, değişken adları ve dosya adları açıklayıcı olmalıdır; aşırı kısaltmalardan kaçının. Kısaltmaları kelime olarak ele alın (örneğin, INfc yerine INFC kullanın).

Dizin yapısı ve dosya adlandırma

Dizin yapısı aşağıdaki gibi görünmelidir:

  • ROOT-DIRECTORY
    • MODULE
      • SUBMODULE (isteğe bağlı, birden fazla seviye olabilir)
        • VERSION
          • Android.mk
          • I INTERFACE_1 .hal
          • I INTERFACE_2 .hal
          • I INTERFACE_N .hal
          • types.hal (isteğe bağlı)

Neresi:

  • ROOT-DIRECTORY :
    • çekirdek HIDL paketleri için hardware/interfaces .
    • SATICI'nın bir SoC satıcısına veya bir OEM/ VENDOR atıfta bulunduğu satıcı paketleri için vendor/ VENDOR /interfaces .
  • MODULE , alt sistemi tanımlayan bir küçük harfli kelime olmalıdır (örn. nfc ). Birden fazla kelime gerekiyorsa, iç içe SUBMODULE kullanın. Birden fazla yuvalama düzeyi olabilir.
  • VERSION , Versions bölümünde açıklananla tam olarak aynı sürüm (major.minor) olmalıdır.
  • I INTERFACE_X , Arayüz adlarında açıklandığı gibi UpperCamelCase / PascalCase (örn. INfc ) ile arayüz adı olmalıdır.

Örnek:

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

Not: Tüm dosyalar yürütülemez izinlere sahip olmalıdır (Git'te).

Paket adları

Paket adları, aşağıdaki tam nitelikli ad (FQN) biçimini kullanmalıdır ( PACKAGE-NAME olarak anılır):

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

Neresi:

  • PACKAGE , ROOT-DIRECTORY ile eşleşen pakettir. Özellikle, PACKAGE :
    • çekirdek HIDL paketleri için android.hardware ( hardware/interfaces eşleme).
    • vendor. VENDOR .hardware paketleri için donanım, burada VENDOR bir SoC satıcısına veya bir OEM/ODM'ye atıfta bulunur ( vendor/ VENDOR /interfaces ile eşleme ).
  • MODULE [. SUBMODULE [. SUBMODULE […]]]@ VERSION , Dizin yapısı içinde açıklanan yapıdaki klasör adlarının tamamen aynısıdır.
  • Paket adları küçük harf olmalıdır. Birden fazla kelime uzunluğunda ise kelimeler ya alt modül olarak kullanılmalı ya da snake_case ile yazılmalıdır.
  • Boşluğa izin verilmez.

FQN her zaman paket bildirimlerinde kullanılır.

Sürümler

Sürümler aşağıdaki biçime sahip olmalıdır:

MAJOR.MINOR

Hem MAJOR hem de MINOR sürümü tek bir tamsayı olmalıdır. HIDL, anlamsal sürüm oluşturma kurallarını kullanır.

ithalat

Bir içe aktarma, aşağıdaki üç biçimden birine sahiptir:

  • Tüm paket içe aktarmaları: import PACKAGE-NAME ;
  • Kısmi ithalat: import PACKAGE-NAME :: UDT ; (veya içe aktarılan tür aynı paketteyse, import UDT ;
  • Yalnızca türlere yönelik içe aktarmalar: import PACKAGE-NAME ::types;

PACKAGE-NAME , Paket adlarındaki biçimi takip eder. Geçerli paketin types.hal (varsa) otomatik olarak içe aktarılır (açıkça içe aktarmayın).

Tam nitelikli adlar (FQN'ler)

Yalnızca gerektiğinde, kullanıcı tanımlı bir tür içe aktarma için tam nitelikli adlar kullanın. İçe aktarma türü aynı paketteyse PACKAGE-NAME öğesini atlayın. Bir FQN boşluk içermemelidir. Tam nitelikli ad örneği:

android.hardware.nfc@1.0::INfcClientCallback

android.hardware.nfc@1.0 altındaki başka bir dosyada, yukarıdaki arayüze INfcClientCallback olarak bakın. Aksi takdirde, yalnızca tam nitelikli adı kullanın.

İthalatları gruplama ve sıralama

Paket bildiriminden sonra (içe aktarmadan önce) boş bir satır kullanın. Her içe aktarma tek bir satırda kalmalı ve girintili olmamalıdır. İçe aktarmaları aşağıdaki sırayla gruplandırın:

  1. Diğer android.hardware paketleri (tam nitelikli adlar kullanın).
  2. Diğer vendor. VENDOR paketleri (tam nitelikli adlar kullanın).
    • Her satıcı bir grup olmalıdır.
    • Satıcıları alfabetik olarak sıralayın.
  3. Aynı paketteki diğer arabirimlerden içe aktarır (basit adlar kullanın).

Gruplar arasında boş bir satır kullanın. Her grubun içinde, içe aktarmaları alfabetik olarak sıralayın. Örnek:

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;

Arayüz adları

Arabirim adları I ile başlamalı ve ardından UpperCamelCase / PascalCase adı gelmelidir. IFoo dosyasında IFoo.hal adında bir arabirim tanımlanmalıdır. Bu dosya yalnızca IFoo arabirimi için tanımları içerebilir (I NAME arabirimi I NAME I NAME .hal içinde olmalıdır).

Fonksiyonlar

İşlev adları, bağımsız değişkenler ve dönüş değişken adları için lowerCamelCase kullanın. Örnek:

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

Yapı/birlik alan adları

struct/union alan adları için lowerCamelCase kullanın. Örnek:

struct FooReply {
    vec<uint8_t> replyData;
}

Adları yazın

Tür adları, yapı/birlik tanımlarına, enum türü tanımlarına ve typedef s'ye başvurur. Bu ad için UpperCamelCase / PascalCase kullanın. Örnekler:

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

enum değerleri

Numaralandırma değerleri UPPER_CASE_WITH_UNDERSCORES olmalıdır. Numaralandırma değerlerini işlev bağımsız değişkenleri olarak iletirken ve bunları işlev dönüşleri olarak döndürürken, gerçek numaralandırma türünü kullanın (temel tamsayı türünü değil). Örnek:

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

Not: Bir numaralandırma türünün temel alınan türü, iki nokta üst üste işaretinden sonra açıkça belirtilir. Derleyiciye bağımlı olmadığından, gerçek enum türünü kullanmak daha açıktır.

Numaralandırma değerleri için tam nitelikli adlar için, numaralandırma türü adı ile numaralandırma değeri adı arasında iki nokta üst üste kullanılır:

PACKAGE-NAME::UDT[.UDT[.UDT[…]]:ENUM_VALUE_NAME

Tam nitelikli bir adın içinde boşluk olmamalıdır. Yalnızca gerektiğinde tam nitelikli bir ad kullanın ve gereksiz parçaları atlayın. Örnek:

android.hardware.foo@1.0::IFoo.IFooInternal.FooEnum:ENUM_OK

Yorumlar

Tek satırlık bir yorum için // , /* */ ve /** */ uygundur.

// This is a single line comment
/* This is also single line comment */
/** This is documentation comment */
  • Yorumlar için /* */ kullanın. HIDL yorumlar için // desteklerken, oluşturulan çıktıda görünmedikleri için önerilmezler.
  • Oluşturulan belgeler için /** */ kullanın. Bunlar yalnızca tür, yöntem, alan ve enum değeri bildirimlerine uygulanabilir. Örnek:
    /** 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,
        ...
    }
    
  • Ayrı bir satırda /** ile çok satırlı yorumları başlatın. Her satırın başında * kullanın. Yorumu, yıldız işaretlerini hizalayarak ayrı bir satırda */ ile sonlandırın. Örnek:
    /**
     * My multi-line
     * comment
     */
    
  • Lisans bildirimi ve değişiklik günlükleri /* (tek bir yıldız) ile yeni bir satır başlatmalı, her satırın başında * kullanmalı ve son satıra */ yerleştirmelidir (yıldız işaretleri aynı hizada olmalıdır). Örnek:
    /*
     * Copyright (C) 2017 The Android Open Source Project
     * ...
     */
    
    /*
     * Changelog:
     * ...
     */
    

Dosya yorumları

Her dosyaya uygun lisanslama bildirimi ile başlayın. Çekirdek HAL'ler için bu, development/docs/copyright-templates/c.txt içindeki AOSP Apache lisansı olmalıdır. Yılı güncellemeyi ve /* */ stili çok satırlı yorumları yukarıda açıklandığı gibi kullanmayı unutmayın.

Lisans bildiriminden sonra isteğe bağlı olarak boş bir satır ve ardından bir değişiklik günlüğü/sürüm bilgisi yerleştirebilirsiniz. Yukarıda açıklandığı gibi /* */ stili çok satırlı yorumları kullanın, boş satırı değişiklik günlüğünden sonra yerleştirin ve ardından paket bildirimini takip edin.

YAPILACAKLAR yorumları

TODO'lar, tüm büyük harflerde TODO dizesini ve ardından iki nokta üst üste içermelidir. Örnek:

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

TODO yorumlarına yalnızca geliştirme sırasında izin verilir; yayınlanan arayüzlerde bulunmamalıdırlar.

Arayüz/İşlev yorumları (belge dizileri)

Çok satırlı ve tek satırlı belge dizileri için /** */ kullanın. Belge dizileri için // kullanmayın.

Arayüzler için belge dizileri, arayüzün genel mekanizmalarını, tasarım gerekçesini, amacı vb. tanımlamalıdır. İşlevlere yönelik belge dizileri, işleve özel olmalıdır (paket düzeyinde belgeler, paket dizinindeki bir BENİOKU dosyasında bulunur).

/**
 * 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();
};

Her parametre/dönüş değeri için @param s ve @return s eklemelisiniz:

  • Her parametre için @param eklenmelidir. Ardından parametrenin adı ve ardından doküman dizisi gelmelidir.
  • Her dönüş değeri için @return eklenmelidir. Bunu, dönüş değerinin adı ve ardından belge dizisi takip etmelidir.

Örnek:

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

biçimlendirme

Genel biçimlendirme kuralları şunları içerir:

  • Çizgi uzunluğu . Metnin her satırı en fazla 100 sütun uzunluğunda olmalıdır.
  • Boşluklar . Satırlarda sondaki boşluk yok; boş satırlar boşluk içermemelidir.
  • Boşluklar ve sekmeler . Yalnızca boşlukları kullanın.
  • Girinti boyutu . Bloklar için 4 boşluk ve satır sarma için 8 boşluk kullanın
  • destek . Açıklama değerleri dışında, bir açık ayraç önceki kodla aynı satıra gider, ancak bir kapalı ayraç ve aşağıdaki noktalı virgül tüm satırı kaplar. Örnek:
    interface INfc {
        close();
    };
    

Paket beyanı

Paket beyanı, lisans bildiriminden sonra dosyanın en üstünde olmalı, tüm satırı kaplamalı ve girintili olmamalıdır. Paketler aşağıdaki biçim kullanılarak bildirilir (ad biçimlendirme için bkz. Paket adları ):

package PACKAGE-NAME;

Örnek:

package android.hardware.nfc@1.0;

İşlev bildirimleri

İşlev adı, parametreler, generates ve döndürme değerleri, uyuyorsa aynı satırda olmalıdır. Örnek:

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

Aynı satıra sığmıyorlarsa, parametreleri ve dönüş değerlerini aynı girinti seviyesine koymaya çalışın ve okuyucunun parametreleri ve dönüş değerlerini hızlı bir şekilde görmesine yardımcı olmak için generate ayırt edin. Örnek:

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

Ek detaylar:

  • Açık bir parantez her zaman işlev adıyla aynı satırdadır.
  • İşlev adı ile açık parantez arasında boşluk yok.
  • Parantezler ve parametreler arasında, aralarında satır besleme olduğu durumlar dışında boşluk yoktur.
  • generates önceki kapanış paranteziyle aynı satırdaysa, bir önceki boşluk kullanın. Eğer generates bir sonraki açık parantez ile aynı satırdaysa, bir boşluk ile takip edin.
  • Tüm parametreleri hizalayın ve değerleri döndürün (mümkünse).
  • Varsayılan girinti 4 boşluktur.
  • Sarılmış parametreler, önceki satırdaki ilk parametrelere hizalanır, aksi takdirde 8 boşluklu girintiye sahiptirler.

Ek açıklamalar

Ek açıklamalar için aşağıdaki biçimi kullanın:

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

Ek açıklamaları alfabetik sıraya göre sıralayın ve eşittir işaretinin etrafında boşluk kullanın. Örnek:

@callflow(key = value)
@entry
@exit

Bir ek açıklamanın tüm satırı kapladığından emin olun. Örnekler:

/* Good */
@entry
@exit

/* Bad */
@entry @exit

Açıklamalar aynı satıra sığmıyorsa, 8 boşlukla girinti yapın. Örnek:

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

Değer dizisinin tamamı aynı satıra sığamıyorsa, açık parantezlerden { ve dizi içindeki her virgülden sonra satır sonları koyun. Kapanış parantezini son değerden hemen sonra yerleştirin. Sadece bir değer varsa parantezleri koymayın.

Değer dizisinin tamamı aynı satıra sığabiliyorsa, açık parantezlerden sonra ve parantezleri kapatmadan önce boşluk kullanmayın ve her virgülden sonra bir boşluk kullanın. Örnekler:

/* Good */
@callflow(key = {"val", "val"})

/* Bad */
@callflow(key = { "val","val" })

Açıklamalar ve işlev bildirimi arasında boş satırlar OLMAMALIDIR. Örnekler:

/* Good */
@entry
foo();

/* Bad */
@entry

foo();

Enum bildirimleri

Enum bildirimleri için aşağıdaki kuralları kullanın:

  • Enum bildirimleri başka bir paketle paylaşılıyorsa, bildirimleri bir arabirimin içine gömmek yerine types.hal içine koyun.
  • İki nokta üst üste işaretinden önce ve sonra bir boşluk ve açık ayraçtan önce alttaki türden sonra boşluk kullanın.
  • Son numaralandırma değeri fazladan virgül içerebilir veya içermeyebilir.

Yapı bildirimleri

Yapı bildirimleri için aşağıdaki kuralları kullanın:

  • Yapı bildirimleri başka bir paketle paylaşılıyorsa, bildirimleri bir arabirimin içine gömmek yerine types.hal içine koyun.
  • Açık ayraçtan önce yapı türü adından sonra bir boşluk kullanın.
  • Alan adlarını hizalayın (isteğe bağlı). Örnek:
    struct MyStruct {
        vec<uint8_t>   data;
        int32_t        someInt;
    }
    

Dizi bildirimleri

Aşağıdakiler arasına boşluk koymayın:

  • Öğe türü ve köşeli parantez açın.
  • Köşeli parantez ve dizi boyutunu açın.
  • Dizi boyutu ve yakın köşeli parantez.
  • Birden fazla boyut varsa, köşeli ayracı kapatın ve sonraki köşeli ayracı açın.

Örnekler:

/* Good */
int32_t[5] array;

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

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

vektörler

Aşağıdakiler arasına boşluk koymayın:

  • vec ve açık açılı ayraç.
  • Açık açılı ayraç ve eleman tipi ( İstisna: eleman tipi de bir vec ).
  • Eleman tipi ve yakın açılı ayraç ( İstisna: eleman tipi de bir vec ) .

Örnekler:

/* 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;