Gaya kode HIDL menyerupai kode C++ dalam kerangka Android, dengan indentasi 4 spasi dan nama file dengan huruf campuran. Deklarasi paket, impor, dan docstring serupa dengan yang ada di Java, dengan sedikit modifikasi.
Contoh berikut untuk IFoo.hal
dan types.hal
mengilustrasikan gaya kode HIDL dan memberikan tautan cepat ke detail setiap gaya ( IFooClientCallback.hal
, IBar.hal
, dan IBaz.hal
telah dihilangkan).
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; }; |
Konvensi penamaan
Nama fungsi, nama variabel, dan nama file harus deskriptif; hindari singkatan yang berlebihan. Anggaplah akronim sebagai kata-kata (misalnya, gunakan INfc
dan bukan INFC
).
Struktur direktori dan penamaan file
Struktur direktori akan muncul sebagai berikut:
-
ROOT-DIRECTORY
-
MODULE
-
SUBMODULE
(opsional, bisa lebih dari satu level)-
VERSION
-
Android.mk
-
I INTERFACE_1 .hal
-
I INTERFACE_2 .hal
-
…
-
I INTERFACE_N .hal
-
types.hal
(opsional)
-
-
-
-
Di mana:
-
ROOT-DIRECTORY
adalah:-
hardware/interfaces
untuk paket inti HIDL. -
vendor/ VENDOR /interfaces
untuk paket vendor, di manaVENDOR
mengacu pada vendor SoC atau OEM/ODM.
-
-
MODULE
harus berupa satu kata huruf kecil yang menggambarkan subsistem (misalnyanfc
). Jika diperlukan lebih dari satu kata, gunakanSUBMODULE
bertingkat. Mungkin ada lebih dari satu tingkat sarang. -
VERSION
harus merupakan versi yang sama persis (major.minor) seperti yang dijelaskan dalam Versions . -
I INTERFACE_X
harus berupa nama antarmuka denganUpperCamelCase
/PascalCase
(misalnyaINfc
) seperti yang dijelaskan dalam Nama antarmuka .
Contoh:
-
hardware/interfaces
-
nfc
-
1.0
-
Android.mk
-
INfc.hal
-
INfcClientCallback.hal
-
types.hal
-
-
-
Catatan: Semua file harus memiliki izin yang tidak dapat dieksekusi (di Git).
Nama paket
Nama paket harus menggunakan format nama yang sepenuhnya memenuhi syarat (FQN) berikut (disebut sebagai PACKAGE-NAME
):
PACKAGE.MODULE[.SUBMODULE[.SUBMODULE[…]]]@VERSION
Di mana:
-
PACKAGE
adalah paket yang dipetakan keROOT-DIRECTORY
. Secara khusus,PACKAGE
adalah:-
android.hardware
untuk paket inti HIDL (pemetaan kehardware/interfaces
). -
vendor. VENDOR .hardware
untuk paket vendor, di manaVENDOR
mengacu pada vendor SoC atau OEM/ODM (pemetaan kevendor/ VENDOR /interfaces
).
-
-
MODULE [. SUBMODULE [. SUBMODULE […]]]@ VERSION
adalah nama folder yang sama persis dalam struktur yang dijelaskan dalam Struktur direktori . - Nama paket harus menggunakan huruf kecil. Jika panjangnya lebih dari satu kata, kata-kata tersebut harus digunakan sebagai submodul atau ditulis dalam
snake_case
. - Tidak ada spasi yang diperbolehkan.
FQN selalu digunakan dalam deklarasi paket.
Versi
Versi harus memiliki format berikut:
MAJOR.MINOR
Baik versi MAJOR maupun MINOR harus berupa bilangan bulat tunggal. HIDL menggunakan aturan pembuatan versi semantik .
Impor
Impor memiliki salah satu dari tiga format berikut:
- Impor seluruh paket:
import PACKAGE-NAME ;
- Impor sebagian:
import PACKAGE-NAME :: UDT ;
(atau, jika tipe yang diimpor ada dalam paket yang sama,import UDT ;
- Impor hanya tipe:
import PACKAGE-NAME ::types;
PACKAGE-NAME
mengikuti format dalam Nama paket . types.hal
paket saat ini (jika ada) secara otomatis diimpor (jangan mengimpornya secara eksplisit).
Nama yang sepenuhnya memenuhi syarat (FQN)
Gunakan nama yang sepenuhnya memenuhi syarat untuk impor jenis yang ditentukan pengguna hanya jika diperlukan. Hilangkan PACKAGE-NAME
jika jenis impor ada dalam paket yang sama. FQN tidak boleh mengandung spasi. Contoh nama yang memenuhi syarat:
android.hardware.nfc@1.0::INfcClientCallback
Di file lain di bawah android.hardware.nfc@1.0
, rujuk antarmuka di atas sebagai INfcClientCallback
. Jika tidak, gunakan hanya nama yang sepenuhnya memenuhi syarat.
Mengelompokkan dan memesan impor
Gunakan baris kosong setelah deklarasi paket (sebelum impor). Setiap impor harus menempati satu baris dan tidak boleh menjorok ke dalam. Kelompokkan impor dalam urutan berikut:
- Paket
android.hardware
lainnya (gunakan nama yang sepenuhnya memenuhi syarat). -
vendor. VENDOR
Paketvendor. VENDOR
(gunakan nama yang sepenuhnya memenuhi syarat).- Setiap vendor harus menjadi satu kelompok.
- Pesan vendor berdasarkan abjad.
- Impor dari antarmuka lain dalam paket yang sama (gunakan nama sederhana).
Gunakan baris kosong antar grup. Di dalam setiap grup, urutkan impor berdasarkan abjad. Contoh:
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;
Nama antarmuka
Nama antarmuka harus dimulai dengan I
, diikuti dengan nama UpperCamelCase
/ PascalCase
. Antarmuka dengan nama IFoo
harus didefinisikan dalam file IFoo.hal
. File ini hanya dapat berisi definisi untuk antarmuka IFoo
(antarmuka I NAME
harus ada di I NAME .hal
).
Fungsi
Untuk nama fungsi, argumen, dan nama variabel kembalian, gunakan lowerCamelCase
. Contoh:
open(INfcClientCallback clientCallback) generates (int32_t retVal); oneway pingAlive(IFooCallback cb);
Nama bidang struktur/gabungan
Untuk nama bidang struct/union, gunakan lowerCamelCase
. Contoh:
struct FooReply { vec<uint8_t> replyData; }
Ketik nama
Nama tipe mengacu pada definisi struct/union, definisi tipe enum, dan typedef
s. Untuk nama ini, gunakan UpperCamelCase
/ PascalCase
. Contoh:
enum NfcStatus : int32_t { /*...*/ }; struct NfcData { /*...*/ };
Nilai enum
Nilai enum harus UPPER_CASE_WITH_UNDERSCORES
. Saat meneruskan nilai enum sebagai argumen fungsi dan mengembalikannya sebagai fungsi kembali, gunakan tipe enum sebenarnya (bukan tipe integer yang mendasarinya). Contoh:
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 };
Catatan: Tipe dasar dari tipe enum dideklarasikan secara eksplisit setelah titik dua. Karena tidak bergantung pada kompiler, menggunakan tipe enum sebenarnya lebih jelas.
Untuk nama yang sepenuhnya memenuhi syarat untuk nilai enum, tanda titik dua digunakan di antara nama tipe enum dan nama nilai enum:
PACKAGE-NAME::UDT[.UDT[.UDT[…]]:ENUM_VALUE_NAME
Tidak boleh ada spasi di dalam nama yang memenuhi syarat. Gunakan nama yang sepenuhnya memenuhi syarat hanya jika diperlukan dan hilangkan bagian yang tidak perlu. Contoh:
android.hardware.foo@1.0::IFoo.IFooInternal.FooEnum:ENUM_OK
Komentar
Untuk komentar satu baris, //
, /* */
, dan /** */
baik-baik saja.
// This is a single line comment /* This is also single line comment */ /** This is documentation comment */
- Gunakan
/* */
untuk komentar. Meskipun HIDL mendukung//
untuk komentar, namun tidak disarankan karena tidak muncul dalam keluaran yang dihasilkan. - Gunakan
/** */
untuk dokumentasi yang dihasilkan. Ini hanya dapat diterapkan pada deklarasi tipe, metode, bidang, dan nilai enum. Contoh:/** 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, ... }
- Mulai komentar multi-baris dengan
/**
pada baris terpisah. Gunakan*
di awal setiap baris. Akhiri komentar dengan*/
pada baris terpisah, sejajarkan tanda bintang. Contoh:/** * My multi-line * comment */
- Pemberitahuan perizinan dan log perubahan harus memulai baris baru dengan
/*
(satu tanda bintang), gunakan*
di awal setiap baris, dan letakkan*/
di baris terakhir secara terpisah (tanda bintang harus sejajar). Contoh:/* * Copyright (C) 2017 The Android Open Source Project * ... */ /* * Changelog: * ... */
Mengajukan komentar
Mulai setiap file dengan pemberitahuan lisensi yang sesuai. Untuk HAL inti, ini harus berupa lisensi AOSP Apache di development/docs/copyright-templates/c.txt
. Ingatlah untuk memperbarui tahun dan gunakan komentar multi-baris gaya /* */
seperti dijelaskan di atas.
Anda juga dapat menempatkan baris kosong setelah pemberitahuan lisensi, diikuti dengan log perubahan/informasi versi. Gunakan /* */
gaya komentar multi-baris seperti dijelaskan di atas, letakkan baris kosong setelah changelog, lalu ikuti dengan deklarasi paket.
Komentar TODO
TODO harus menyertakan string TODO
dalam huruf kapital semua diikuti dengan titik dua. Contoh:
// TODO: remove this code before foo is checked in.
Komentar TODO hanya diperbolehkan selama pengembangan; mereka tidak boleh ada di antarmuka yang dipublikasikan.
Komentar Antarmuka/Fungsi (docstrings)
Gunakan /** */
untuk dokumen multi-baris dan satu baris. Jangan gunakan //
untuk dokumen.
Dokumen untuk antarmuka harus menjelaskan mekanisme umum antarmuka, alasan desain, tujuan, dll. Dokumen untuk fungsi harus spesifik untuk fungsi tersebut (dokumentasi tingkat paket disimpan dalam file README di direktori paket).
/** * 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(); };
Anda harus menambahkan @param
s dan @return
s untuk setiap parameter/nilai kembalian:
-
@param
harus ditambahkan untuk setiap parameter. Itu harus diikuti dengan nama parameter lalu docstring. -
@return
harus ditambahkan untuk setiap nilai pengembalian. Itu harus diikuti dengan nama nilai yang dikembalikan, lalu docstring.
Contoh:
/** * 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);
Pemformatan
Aturan pemformatan umum meliputi:
- Panjang garis . Setiap baris teks panjangnya maksimal 100 kolom.
- Spasi putih . Tidak ada spasi tambahan pada baris; baris kosong tidak boleh mengandung spasi.
- Spasi vs. tab . Gunakan hanya spasi.
- Ukuran indentasi . Gunakan 4 spasi untuk blok dan 8 spasi untuk pembungkus garis
- menguatkan . Kecuali untuk nilai anotasi , kurung kurawal terbuka berada pada baris yang sama dengan kode sebelumnya, namun kurung kurawal tutup dan titik koma berikutnya menempati seluruh baris. Contoh:
interface INfc { close(); };
Deklarasi paket
Deklarasi paket harus berada di bagian atas file setelah pemberitahuan lisensi, harus memenuhi seluruh baris, dan tidak boleh menjorok ke dalam. Paket dideklarasikan menggunakan format berikut (untuk pemformatan nama, lihat Nama paket ):
package PACKAGE-NAME;
Contoh:
package android.hardware.nfc@1.0;
Deklarasi fungsi
Nama fungsi, parameter, generates
, dan nilai kembalian harus berada pada baris yang sama jika cocok. Contoh:
interface IFoo { /** ... */ easyMethod(int32_t data) generates (int32_t result); };
Jika keduanya tidak cocok pada baris yang sama, coba letakkan parameter dan nilai kembalian di tingkat indentasi yang sama dan bedakan generate
untuk membantu pembaca dengan cepat melihat parameter dan nilai kembalian. Contoh:
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); }
Detil tambahan:
- Tanda kurung buka selalu berada pada baris yang sama dengan nama fungsi.
- Tidak ada spasi antara nama fungsi dan tanda kurung buka.
- Tidak ada spasi di antara tanda kurung dan parameter kecuali jika terdapat umpan baris di antara keduanya.
- Jika
generates
berada pada baris yang sama dengan tanda kurung tutup sebelumnya, gunakan spasi sebelumnya. Jikagenerates
berada pada baris yang sama dengan tanda kurung buka berikutnya, ikuti dengan spasi. - Sejajarkan semua parameter dan kembalikan nilai (jika memungkinkan).
- Indentasi default adalah 4 spasi.
- Parameter yang dibungkus disejajarkan dengan parameter pertama pada baris sebelumnya, jika tidak, parameter tersebut memiliki indentasi 8 spasi.
Anotasi
Gunakan format anotasi berikut:
@annotate(keyword = value, keyword = {value, value, value})
Urutkan anotasi berdasarkan abjad, dan gunakan spasi di sekitar tanda sama dengan. Contoh:
@callflow(key = value) @entry @exit
Pastikan anotasi menempati seluruh baris. Contoh:
/* Good */ @entry @exit /* Bad */ @entry @exit
Jika anotasi tidak dapat dimuat pada baris yang sama, indentasi dengan 8 spasi. Contoh:
@annotate( keyword = value, keyword = { value, value }, keyword = value)
Jika seluruh array nilai tidak dapat masuk ke dalam baris yang sama, letakkan jeda baris setelah kurung kurawal terbuka {
dan setelah setiap koma di dalam array. Tempatkan tanda kurung tutup tepat setelah nilai terakhir. Jangan memasang kurung kurawal jika nilainya hanya satu.
Jika seluruh array nilai dapat ditampung dalam baris yang sama, jangan gunakan spasi setelah kurung kurawal buka dan sebelum kurung kurawal tutup, dan gunakan satu spasi setelah setiap koma. Contoh:
/* Good */ @callflow(key = {"val", "val"}) /* Bad */ @callflow(key = { "val","val" })
TIDAK boleh ada baris kosong antara anotasi dan deklarasi fungsi. Contoh:
/* Good */ @entry foo(); /* Bad */ @entry foo();
Deklarasi enum
Gunakan aturan berikut untuk deklarasi enum:
- Jika deklarasi enum dibagikan dengan paket lain, masukkan deklarasi tersebut ke dalam
types.hal
daripada menyematkannya di dalam antarmuka. - Gunakan spasi sebelum dan sesudah titik dua, dan spasi setelah tipe dasar sebelum kurung kurawal terbuka.
- Nilai enum terakhir mungkin memiliki atau tidak memiliki koma tambahan.
Deklarasi struktur
Gunakan aturan berikut untuk deklarasi struct:
- Jika deklarasi struct dibagikan dengan paket lain, masukkan deklarasi tersebut ke dalam
types.hal
daripada menyematkannya di dalam antarmuka. - Gunakan spasi setelah nama tipe struct sebelum kurung kurawal terbuka.
- Sejajarkan nama bidang (opsional). Contoh:
struct MyStruct { vec<uint8_t> data; int32_t someInt; }
Deklarasi array
Jangan memberi spasi di antara berikut ini:
- Tipe elemen dan braket persegi terbuka.
- Buka braket persegi dan ukuran array.
- Ukuran array dan tutup kurung siku.
- Kurung siku tutup dan kurung siku terbuka berikutnya, jika terdapat lebih dari satu dimensi.
Contoh:
/* Good */ int32_t[5] array; /* Good */ int32_t[5][6] multiDimArray; /* Bad */ int32_t [ 5 ] [ 6 ] array;
vektor
Jangan memberi spasi di antara berikut ini:
-
vec
dan braket sudut terbuka. - Kurung sudut terbuka dan tipe elemen ( Pengecualian: tipe elemen juga merupakan
vec
). - Tipe elemen dan braket sudut dekat ( Pengecualian: tipe elemen juga merupakan
vec
) .
Contoh:
/* 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;