HIDL kod stili, 4 boşluk girintisi ve büyük/küçük harfli dosya adlarıyla Android çerçevesindeki C++ koduna benzer. Paket bildirimleri, içe aktarma işlemleri ve açıklama metinleri, Java'dakilere benzer ancak küçük değişiklikler içerir.
IFoo.hal
ve types.hal
için aşağıdaki örneklerde HIDL kod stilleri gösterilmekte ve her stilin ayrıntılarına yönelik hızlı bağlantılar sağlanmaktadır (IFooClientCallback.hal
, IBar.hal
ve IBaz.hal
atlanmış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. Fazla kısaltma kullanmaktan kaçının. Kısaltmaları kelime 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 düzey olabilir)VERSION
Android.mk
IINTERFACE_1.hal
IINTERFACE_2.hal
…
IINTERFACE_N.hal
types.hal
(isteğe bağlı)
Nerede:
ROOT-DIRECTORY
:hardware/interfaces
temel HIDL paketleri için.VENDOR
bir SoC satıcısını veya OEM/ODM'yi ifade ettiğinde satıcı paketleri içinvendor/VENDOR/interfaces
.
MODULE
, alt sistemi tanımlayan küçük harfli bir kelime olmalıdır (örneğin,nfc
). Birden fazla kelime gerekiyorsa iç içe yerleştirilmişSUBMODULE
kullanın. Birden fazla iç içe yerleştirme seviyesi olabilir.VERSION
, Sürümler bölümünde açıklanan sürümle (ana.alt) tam olarak aynı olmalıdır.IINTERFACE_X
, Arayüz adları bölümünde açıklandığı gibiUpperCamelCase
/PascalCase
içeren arayüz adı (ör.INfc
) 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ılabilir olmayan izinleri olmalıdır (Git'te).
Paket adları
Paket adları aşağıdaki tam nitelikli ad (FQN) biçimini (PACKAGE-NAME
olarak anılacaktır) kullanmalıdır:
PACKAGE.MODULE[.SUBMODULE[.SUBMODULE[…]]]@VERSION
Nerede:
PACKAGE
,ROOT-DIRECTORY
ile eşlenen pakettir. Özellikle,PACKAGE
:- Temel HIDL paketleri için
android.hardware
(hardware/interfaces
ile eşleme). - Satıcı paketleri için
vendor.VENDOR.hardware
. Bu durumdaVENDOR
, bir SoC satıcısını veya OEM/ODM'yi (vendor/VENDOR/interfaces
ile eşlenir) belirtir.
- Temel HIDL paketleri için
MODULE[.SUBMODULE[.SUBMODULE[…]]]@VERSION
Dizini yapısı bölümünde açıklanan yapıdaki klasör adlarıyla tam olarak aynıdır.- Paket adları küçük harfle yazılmalıdır. Birden fazla kelimeden oluşan kelimeler alt modül olarak kullanılmalıdır veya
snake_case
ile yazılmalıdır. - Boşluk kullanılamaz.
Tam ad, paket beyanlarında her zaman kullanılır.
Sürümler
Sürümler şu biçimde olmalıdır:
MAJOR.MINOR
Hem MAJOR hem de MINOR sürümü tek bir tam sayı olmalıdır. HIDL, anlamsal sürümlendirme kurallarını kullanır.
İthalat
İçe aktarma işlemi aşağıdaki üç biçimden birinde olabilir:
- Paketin tamamını içe aktarma:
import PACKAGE-NAME;
- Kısmi içe aktarma:
import PACKAGE-NAME::UDT;
(veya içe aktarılan tür aynı paketteyseimport UDT;
- Yalnızca türleri içe aktarma:
import PACKAGE-NAME::types;
PACKAGE-NAME
, Paket adları bölümündeki biçime uygun olmalıdır. Mevcut 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 aktarma işlemi için tam nitelikli adları yalnızca gerektiğinde kullanın.
İçe aktarma türü aynı paketteyse PACKAGE-NAME
öğesini çıkarın. Tam nitelikli ad boşluk içermemelidir. Tam nitelikli bir ada örnek:
android.hardware.nfc@1.0::INfcClientCallback
android.hardware.nfc@1.0
altındaki başka bir dosyada, yukarıdaki arayüze INfcClientCallback
olarak referans verin. Aksi takdirde, yalnızca tam nitelikli adı kullanın.
İçe aktarma işlemlerini gruplandırma ve sıralama
Paket beyanından sonra (içe aktarmalardan önce) boş bir satır kullanın. Her içe aktarma işlemi tek bir satırda yer almalı ve girintili olmamalıdır. Grup içe aktarma işlemlerini aşağıdaki sırayla yapın:
- Diğer
android.hardware
paketleri (tam nitelikli adlar kullanın). - Diğer
vendor.VENDOR
paketleri (tam nitelikli adlar kullanın).- Her tedarikçi bir grup olmalıdır.
- Tedarikçi firmaları alfabetik olarak sıralayın.
- Aynı paketteki diğer arayüzlerden içe aktarma (basit adlar kullanın).
Gruplar arasında boş bir satır kullanın. Her grup içinde içe aktarılanları 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
adlı bir arayüz tanımlanmalıdır. Bu dosya yalnızca IFoo
arayüzüyle ilgili tanımlar içerebilir (INAME
arayüzü INAME.hal
içinde olmalıdır).
Fonksiyonlar
İşlev adları, bağımsız değişkenler ve döndürülen değişken adları için lowerCamelCase
kullanın. Örnek:
open(INfcClientCallback clientCallback) generates (int32_t retVal); oneway pingAlive(IFooCallback cb);
Yapı ve birleşme alan adları
Yapı veya birleştirme alan adları için lowerCamelCase
kullanın. Örnek:
struct FooReply { vec<uint8_t> replyData; }
Tür adları
Tür adları, struct veya union tanımlarını, enum tür tanımlarını ve typedef
'leri ifade eder. Bu adlar için UpperCamelCase
/PascalCase
kullanın. Örnekler:
enum NfcStatus : int32_t { /*...*/ }; struct NfcData { /*...*/ };
Enum değerleri
Aralık değerleri UPPER_CASE_WITH_UNDERSCORES
olmalıdır. Listeli değer türlerini işlev bağımsız değişkenleri olarak ilettiğinizde ve işlev dönüşleri olarak döndürdüğünüzde, temel tam sayı türünü değil, gerçek listeli değer türünü kullanın. Ö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 enum türünün temel türü, iki nokta işaretinden sonra açıkça belirtilir. Derleyiciye bağlı olmadığından, gerçek enum türünü kullanmak daha nettir.
Listeli değerler için tam nitelikli adlarda, listeli tür adı ile listeli değer adı arasına iki nokta üst üste işareti eklenir:
PACKAGE-NAME::UDT[.UDT[.UDT[…]]:ENUM_VALUE_NAME
Tam nitelikli adlarda boşluk bulunmamalıdır. Tam nitelikli adı yalnızca gerektiğinde kullanın ve gereksiz kısımları çıkarın. Örnek:
android.hardware.foo@1.0::IFoo.IFooInternal.FooEnum:ENUM_OK
Yorumlar
Tek satırlık yorumlarda //
, /* */
ve /** */
kullanılabilir.
// This is a single line comment /* This is also single line comment */ /** This is documentation comment */
-
Yorumlar için
/* */
simgesini kullanın. HIDL, yorumlar için//
'ü desteklese de oluşturulan çıktıda görünmedikleri için bu tür yorumlardan kaçınılması önerilir. - Oluşturulan dokümanlar için
/** */
öğesini kullanın. Bunlar yalnızca tür, yöntem, alan ve enum değer beyanlarına 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 ayrı bir satırda*/
ile bitirin ve yıldız işaretlerini hizalayın. Örnek:/** * My multi-line * comment */
- Lisanslama bildirimi ve değişiklik günlükleri,
/*
ile (tek yıldız) yeni bir satırda başlamalı, her satırın başında*
kullanılmalıdır ve*/
son satıra tek başına yerleştirilmelidir (yıldızlar hizalanmalıdır). Örnek:/* * Copyright (C) 2017 The Android Open Source Project * ... */ /* * Changelog: * ... */
Dosya yorumları
Her dosyayı uygun lisanslama bildirimiyle başlatın. Temel HAL'ler için bu, development/docs/copyright-templates/c.txt
adresindeki AOSP Apache lisansı olmalıdır.
Yılı güncellemeyi ve yukarıda açıklandığı gibi /* */
stilinde çok satırlık yorumlar kullanmayı unutmayın.
İsteğe bağlı olarak lisans bildiriminin ardından boş bir satır ve ardından bir değişiklik günlüğü/sürüm bilgileri ekleyebilirsiniz. Yukarıda açıklandığı gibi /* */
stilinde çok satırlı yorumlar kullanın, boş satırı değişiklik günlüğünden sonra yerleştirin ve ardından paket beyanını ekleyin.
TODO yorumları
TODO'lar, büyük harflerle yazılmış TODO
dizesini ve ardından iki nokta üst üste işaretini 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ır.
Arayüz ve işlev yorumları (docstring'ler)
Çok satırlık ve tek satırlık docstring'ler için /** */
kullanın. Açıklama metinleri için //
kullanmayın.
Arayüzlerin doküman dizeleri, arayüzün genel mekanizmalarını, tasarım gerekçesini, amacını vb. açıklamalıdır. İşlevlerin doküman dizeleri, işleve özel olmalıdır (paket düzeyindeki dokümanlar, paket dizininde bir README dosyasına yerleştirilir).
/** * 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öndürülen değer için @param
ve @return
eklemeniz gerekir:
- Her parametre için
@param
eklenmelidir. Ardından parametrenin adı ve açıklama metni gelmelidir. - Her bir döndürülen değer için
@return
eklenmelidir. Ardından, döndürülen değerin adı ve ardından da docstring gelmelidir.
Ö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 kuralları
Genel biçimlendirme kuralları şunlardır:
- Satır uzunluğu. Her metin satırı en fazla 100 sütun uzunluğunda olmalıdır.
- Boşluklar. Satırların sonunda boşluk olmamalıdır; boş satırlar boşluk içermemelidir.
- Alanlar ve sekmeler. Yalnızca boşluk kullanın.
- Girinti boyutu. Bloklar için 4, satır sonları için 8 boşluk kullanın.
- Destekleme. Not değerleri hariç, açık parantez önceki kodla aynı satıra, kapalı parantez ve ardından gelen noktalı virgül ise satırın tamamını kaplar. Örnek:
interface INfc { close(); };
Paket beyanı
Paket beyanı, lisans uyarısından sonra dosyanın en üstünde yer almalı, satırın tamamını kaplamalı ve girintili olmamalıdır. Paketler aşağıdaki biçim kullanılarak bildirilir (ad biçimlendirme için Paket adları bölümüne bakın):
package PACKAGE-NAME;
Örnek:
package android.hardware.nfc@1.0;
İşlev bildirimleri
İşlev adı, parametreler, generates
ve döndürülen değerler sığabiliyorsa aynı satırda olmalıdır. Örnek:
interface IFoo { /** ... */ easyMethod(int32_t data) generates (int32_t result); };
Aynı satıra sığmazlarsa parametreleri ve döndürülen değerleri aynı girinti düzeyine yerleştirmeyi deneyin ve okuyucunun parametreleri ve döndürülen değerleri hızlıca görmesine yardımcı olmak için generate
ile 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 ayrıntılar:
- Açık parantez her zaman işlev adıyla aynı satırdadır.
- İşlev adı ile açık parantez arasında boşluk olmamalıdır.
- Parantezler ile parametreler arasında boşluk olmamalıdır ancak aralarında satır beslemeleri varsa boşluk kullanılabilir.
generates
önceki kapatıcı parantezle aynı satırdaysa önceden bir boşluk kullanın.generates
, sonraki açık parantezle aynı satırdaysa ardından boşluk ekleyin.- Tüm parametreleri ve döndürülen değerleri (mümkünse) hizalayın.
- Varsayılan girinti 4 boşluktur.
- Sarılı parametreler, önceki satırdaki ilk parametrelerle hizalanır. Aksi takdirde 8 boşluk girintisi olur.
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 olarak sıralayın ve eşitlik işaretlerinin etrafında boşluk bırakın. Örnek:
@callflow(key = value) @entry @exit
Ek açıklamanın satırın tamamını kapladığından emin olun. Örnekler:
/* Good */ @entry @exit /* Bad */ @entry @exit
Ek açıklamalar aynı satıra sığmıyorsa 8 boşluk girin. Örnek:
@annotate( keyword = value, keyword = { value, value }, keyword = value)
Değer dizisinin tamamı aynı satıra sığmazsa açık köşeli parantez {
ve dizi içindeki her virgülden sonra satır sonu karakteri koyun. Kapanıcı parantezi son değerin hemen sonrasına yerleştirin. Yalnızca tek bir değer varsa parantez koymayın.
Değer dizisinin tamamı aynı satıra sığabiliyorsa açık parantezlerden sonra ve kapatıcı parantezlerden önce boşluk kullanmayın ve her virgülün ardından bir boşluk bırakın. Örnekler:
/* Good */ @callflow(key = {"val", "val"}) /* Bad */ @callflow(key = { "val","val" })
Ek açıklamalar ile işlev tanımı arasında boş satır OLMAMALIDIR. Örnekler:
/* Good */ @entry foo(); /* Bad */ @entry foo();
Enum tanımları
Enum bildirimleri için aşağıdaki kuralları kullanın:
- enum tanımları başka bir paketle paylaşılıyorsa tanımları bir arayüze yerleştirmek yerine
types.hal
içine koyun. - İki nokta işaretinden önce ve sonra boşluk, temel türden sonra ve açık parantezden önce boşluk kullanın.
- Son enum değerinde fazladan virgül bulunmamalıdır.
Yapı tanımlamaları
struct bildirimleri için aşağıdaki kuralları kullanın:
- Yapı tanımları başka bir paketle paylaşılıyorsa tanımları bir arayüzün içine yerleştirmek yerine
types.hal
içine koyun. - Yapı türü adından sonra, açık parantezden ö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ğıdakiler arasında boşluk bırakmayın:
- Öğe türü ve açık köşeli parantez.
- Açık köşeli parantez ve dizi boyutu.
- Dizi boyutu ve köşeli parantez kapatma işareti.
- Birden fazla boyut varsa köşeli parantezi kapatın ve sonraki açık 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ğıdakiler arasında boşluk bırakmayın:
vec
ve sol açılı parantez.- Sol açılı parantez ve öğe türü (İstisna: öğe türü de bir
vec
öğesidir). - Öğe türü ve kapatıcı açılı köşeli parantez (İstisna: öğe türü 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;