Kod Stili Kılavuzu

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

Aşağıdaki IFoo.hal ve types.hal örnekleri, HIDL kod stillerini gösterir ve her stile ilişkin 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ı sözcük olarak değerlendirin (ö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ı)

Nerede:

  • ROOT-DIRECTORY :
    • çekirdek HIDL paketleri için hardware/interfaces .
    • vendor/ VENDOR /interfaces ; burada VENDOR bir SoC satıcısına veya bir OEM/ODM'ye atıfta bulunur.
  • MODULE alt sistemi tanımlayan küçük harfli bir kelime olmalıdır (örn nfc ). Birden fazla kelimeye ihtiyaç duyulursa iç içe SUBMODULE kullanın. Birden fazla iç içe geçme düzeyi olabilir.
  • VERSION Versions bölümünde açıklanan sürümle (major.minor) tamamen aynı olmalıdır.
  • I INTERFACE_X Arayüz adlarında açıklandığı gibi UpperCamelCase / PascalCase (örn. INfc ) içeren arayüz adı olmalıdır.

Örnek:

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

Not: Tüm dosyaların çalıştırılamayan izinlere sahip olması gerekir (Git'te).

Paket adları

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

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

Nerede:

  • PACKAGE , ROOT-DIRECTORY ile eşlenen pakettir. PACKAGE özellikle:
    • ç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 ( vendor/ VENDOR /interfaces eşleme) atıfta bulunur.
  • MODULE [. SUBMODULE [. SUBMODULE […]]]@ VERSION Dizin yapısında açıklanan yapıdaki klasör adlarının tamamen aynısıdır.
  • Paket adları küçük harf olmalıdır. Birden fazla kelimeden uzun olmaları durumunda kelimeler ya alt modül olarak kullanılmalı ya da snake_case ile yazılmalıdır.
  • Hiçbir boşluğa izin verilmez.

FQN her zaman paket bildirimlerinde kullanılır.

Sürümler

Sürümler aşağıdaki formatta 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.

İthalat

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

  • Tam paket içe aktarmaları: import PACKAGE-NAME ;
  • Kısmi içe aktarmalar: import PACKAGE-NAME :: UDT ; (veya içe aktarılan tür aynı paketteyse import UDT ;
  • Yalnızca türleri içe aktarır: import PACKAGE-NAME ::types;

PACKAGE-NAME Paket adlarındaki formatı 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)

Kullanıcı tanımlı tür içe aktarımı için yalnızca gerektiğinde tam nitelikli adlar kullanın. İçe aktarma türü aynı paketteyse PACKAGE-NAME atlayın. Bir FQN boşluk içermemelidir. Tam nitelikli bir 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 adı kullanın.

İçe aktarmaları gruplama ve sıralama

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

  1. Diğer android.hardware paketleri (tam olarak nitelenmiş adlar kullanın).
  2. Diğer vendor. VENDOR paketleri (tamamen 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 arayüzlerden içe aktarılı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ı

Arayüz adları I ile başlamalı ve ardından UpperCamelCase / PascalCase adı gelmelidir. IFoo.hal dosyasında IFoo adında bir arayüz tanımlanmalıdır. Bu dosya yalnızca IFoo arayüzüne ilişkin tanımlar içerebilir ( I NAME arayüzü I NAME .hal içinde olmalıdır).

Fonksiyonlar

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

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

Yapı/birlik alan adları

Yapı/birlik alan adları için lowerCamelCase kullanın. Örnek:

struct FooReply {
    vec<uint8_t> replyData;
}

Adları yazın

Tür adları struct/union tanımlarına, enum türü tanımlarına ve typedef s'ye atıfta bulunur. Bu ad için UpperCamelCase / PascalCase kullanın. Örnekler:

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

Numaralandırma değerleri

Enum değerleri UPPER_CASE_WITH_UNDERSCORES olmalıdır. Enum 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 enum türünü kullanın (temeldeki 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 türü, iki nokta üst üste işaretinden sonra açıkça bildirilir. Derleyiciye bağlı olmadığından gerçek numaralandırma tipini kullanmak daha açıktır.

Enum değerlerine yönelik tam nitelikli adlar için, enum türü adı ile enum 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 kısımları 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 önerilmez.
  • Oluşturulan belgeler için /** */ kullanın. Bunlar yalnızca tür, yöntem, alan ve numaralandırma 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,
        ...
    }
    
  • Çok satırlı yorumları ayrı bir satırda /** ile 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 yeni bir satıra /* (tek bir yıldız işareti) ile başlamalı, her satırın başında * kullanmalı ve */ yi son satıra tek başına yerleştirmelidir (yıldız işaretleri hizalanmalıdır). Örnek:
    /*
     * Copyright (C) 2017 The Android Open Source Project
     * ...
     */
    
    /*
     * Changelog:
     * ...
     */
    

Dosya yorumları

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

İsteğe bağlı olarak lisans bildiriminden sonra boş bir satır ve ardından değişiklik günlüğü/sürüm oluşturma bilgilerini yerleştirebilirsiniz. Yukarıda açıklandığı gibi /* */ tarzı çok satırlı yorumları kullanın, boş satırı değişiklik günlüğünün arkasına yerleştirin ve ardından paket bildirimini takip edin.

YAPILACAKLAR yorumları

TODO'lar tamamı büyük harflerle TODO dizesini ve ardından iki nokta üst üste işareti 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ınlanmış arayüzlerde bulunmamalıdırlar.

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

Çok satırlı ve tek satırlı belge dizeleri için /** */ kullanın. Doküman dizeleri için // kullanmayın.

Arayüzlere ilişkin belge dizileri, arayüzün genel mekanizmalarını, tasarım mantığını, amacını vb. açıklamalıdır. İşlevlere ilişkin belge dizileri, işleve özel olmalıdır (paket düzeyindeki belgeler, paket dizinindeki README dosyasına gider).

/**
 * 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. Bunu parametrenin adı ve ardından docstring takip etmelidir.
  • 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:

  • Hat uzunluğu . Her metin satırı en fazla 100 sütun uzunluğunda olmalıdır.
  • Boşluklar Satırların sonunda 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, satır kaydırmalar için 8 boşluk kullanın
  • Destekleme . Ek açıklama değerleri dışında, açık parantez önceki kodla aynı satırda yer alır ancak kapalı parantez ve onu takip eden noktalı virgül tüm satırı kaplar. Örnek:
    interface INfc {
        close();
    };
    

Paket beyanı

Paket bildirimi, lisans bildiriminden sonra dosyanın en üstünde yer almalı, satırın tamamını kaplamalı ve girintili olmamalıdır. Paketler aşağıdaki format kullanılarak bildirilir (ad formatı için bkz . Paket adları ):

package PACKAGE-NAME;

Örnek:

package android.hardware.nfc@1.0;

İşlev bildirimleri

İşlev adı, parametreler, generates ve dönüş değerleri uygunsa 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 düzeyine 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 parantez her zaman işlev adıyla aynı satırda bulunur.
  • İşlev adı ile açık parantez arasında boşluk olmamalıdır.
  • Parantezler ve parametreler arasında, aralarında satır geçişlerinin olduğu durumlar dışında boşluk yoktur.
  • generates önceki kapanış paranteziyle aynı satırdaysa, önünde bir boşluk kullanın. Eğer generates bir sonraki açık parantezle aynı satırdaysa, onu bir boşlukla 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 formatı 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ındaki boşlukları kullanın. Örnek:

@callflow(key = value)
@entry
@exit

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

/* Good */
@entry
@exit

/* Bad */
@entry @exit

Ek açıklamalar aynı satıra sığmıyorsa 8 boşluk girintisi 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ını koyun. Kapatma parantezini son değerin hemen sonrasına yerleştirin. Tek bir değer varsa parantezleri koymayın.

Değer dizisinin tamamı aynı satıra sığabiliyorsa, açık parantezlerden sonra ve kapatma parantezlerinden ö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" })

Ek açıklamalar ile işlev bildirimi arasında boş satırlar OLMAMALIDIR. Örnekler:

/* Good */
@entry
foo();

/* Bad */
@entry

foo();

Numaralandırma bildirimleri

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

  • Enum bildirimleri başka bir paketle paylaşılıyorsa bildirimleri bir arabirimin içine yerleştirmek yerine types.hal içine yerleştirin.
  • İki nokta üst üste işaretinden önce ve sonra bir boşluk kullanın ve açık ayraçtan önce altta yatan türden sonra bir boşluk kullanın.
  • Son numaralandırma değerinde fazladan virgül olabilir veya olmayabilir.

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 yerleştirmek yerine types.hal yerleştirin.
  • Yapı türü adından sonra, açık ayraçtan önce 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ğıdakilerin arasına boşluk koymayın:

  • Eleman türü ve açık köşeli ayraç.
  • Köşeli ayracı ve dizi boyutunu açın.
  • Dizi boyutu ve yakın köşeli ayraç.
  • Birden fazla boyut varsa köşeli parantezi kapatın ve sonraki köşeli parantezi açın.

Örnekler:

/* Good */
int32_t[5] array;

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

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

Vektörler

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

  • vec ve açık açılı ayraç.
  • Açık açılı ayraç ve eleman tipi ( İstisna: eleman tipi aynı zamanda bir vec ).
  • Eleman tipi ve açılı ayracı kapatın ( İstisna: eleman tipi aynı zamanda 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;