Gaya kode HIDL menyerupai kode C++ dalam framework Android, dengan indentasi 4 spasi dan nama file huruf campuran. Deklarasi paket, impor, dan docstring mirip dengan yang ada di Java, dengan sedikit modifikasi.
Contoh berikut untuk IFoo.hal
dan types.hal
mengilustrasikan gaya kode HIDL dan menyediakan link cepat ke detail tentang 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. Perlakukan akronim sebagai kata (misalnya, gunakan INfc
, bukan
INFC
).
Struktur direktori dan penamaan file
Struktur direktori akan muncul sebagai berikut:
ROOT-DIRECTORY
MODULE
SUBMODULE
(opsional, bisa lebih dari satu tingkat)VERSION
Android.mk
IINTERFACE_1.hal
IINTERFACE_2.hal
…
IINTERFACE_N.hal
types.hal
(opsional)
Dalam hal ini:
ROOT-DIRECTORY
adalah:hardware/interfaces
untuk paket HIDL inti.vendor/VENDOR/interfaces
untuk paket vendor, denganVENDOR
merujuk ke vendor SoC atau OEM/ODM.
MODULE
harus berupa satu kata huruf kecil yang menjelaskan subsistem (misalnya,nfc
). Jika diperlukan lebih dari satu kata, gunakanSUBMODULE
bertingkat. Dapat ada lebih dari satu tingkat penyusunan.VERSION
harus memiliki versi yang sama persis (major.minor) seperti yang dijelaskan dalam Versi.IINTERFACE_X
harus berupa nama antarmuka denganUpperCamelCase
/PascalCase
(misalnya,INfc
) 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 non-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
Dalam hal ini:
PACKAGE
adalah paket yang dipetakan keROOT-DIRECTORY
. Khususnya,PACKAGE
adalah:android.hardware
untuk paket HIDL inti (dipetakan kehardware/interfaces
).vendor.VENDOR.hardware
untuk paket vendor, denganVENDOR
merujuk ke vendor SoC atau OEM/ODM (dipetakan kevendor/VENDOR/interfaces
).
MODULE[.SUBMODULE[.SUBMODULE[…]]]@VERSION
adalah nama folder yang sama persis dalam struktur yang dijelaskan di Struktur direktori.- Nama paket harus berupa huruf kecil. Jika lebih dari satu kata, kata-kata tersebut harus digunakan sebagai submodul atau ditulis dalam
snake_case
. - Tidak boleh ada spasi.
FQN selalu digunakan dalam deklarasi paket.
Versi
Versi harus memiliki format berikut:
MAJOR.MINOR
Versi MAJOR dan MINOR harus berupa bilangan bulat tunggal. HIDL menggunakan aturan pembuatan versi semantik.
Import
Impor memiliki salah satu dari tiga format berikut:
- Impor seluruh paket:
import PACKAGE-NAME;
- Impor parsial:
import PACKAGE-NAME::UDT;
(atau, jika jenis yang diimpor berada dalam paket yang sama,import UDT;
- Impor hanya jenis:
import PACKAGE-NAME::types;
PACKAGE-NAME
mengikuti format di
Nama paket. types.hal
paket saat ini (jika ada) akan diimpor secara otomatis (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 berada dalam paket yang sama. FQN tidak boleh berisi spasi. Contoh nama yang sepenuhnya memenuhi syarat:
android.hardware.nfc@1.0::INfcClientCallback
Dalam file lain di bagian android.hardware.nfc@1.0
, sebutkan
antarmuka di atas sebagai INfcClientCallback
. Jika tidak, gunakan hanya nama yang sepenuhnya memenuhi syarat.
Mengelompokkan dan mengurutkan impor
Gunakan baris kosong setelah deklarasi paket (sebelum impor). Setiap impor harus menempati satu baris dan tidak boleh diindentasi. Kelompokkan impor dalam urutan berikut:
- Paket
android.hardware
lainnya (gunakan nama yang sepenuhnya memenuhi syarat). - Paket
vendor.VENDOR
lainnya (gunakan nama yang sepenuhnya memenuhi syarat).- Setiap vendor harus berupa grup.
- Urutkan vendor menurut abjad.
- Impor dari antarmuka lain dalam paket yang sama (gunakan nama sederhana).
Gunakan baris kosong di antara grup. Di dalam setiap grup, urutkan impor secara alfabetis. 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 diawali dengan I
, diikuti dengan nama
UpperCamelCase
/PascalCase
. Antarmuka dengan nama
IFoo
harus ditentukan dalam file IFoo.hal
. File ini
hanya dapat berisi definisi untuk antarmuka IFoo
(antarmuka
INAME
harus ada di INAME.hal
).
Fungsi
Untuk nama fungsi, argumen, dan nama variabel yang ditampilkan, gunakan
lowerCamelCase
. Contoh:
open(INfcClientCallback clientCallback) generates (int32_t retVal); oneway pingAlive(IFooCallback cb);
Nama kolom struct dan union
Untuk nama kolom struct atau union, gunakan lowerCamelCase
. Contoh:
struct FooReply { vec<uint8_t> replyData; }
Nama jenis
Nama jenis mengacu pada definisi struct atau union, definisi jenis enum, dan
typedef
. Untuk nama ini, gunakan
UpperCamelCase
/PascalCase
. Contoh:
enum NfcStatus : int32_t { /*...*/ }; struct NfcData { /*...*/ };
Nilai enum
Nilai enum harus berupa UPPER_CASE_WITH_UNDERSCORES
. Saat meneruskan nilai enum sebagai argumen fungsi dan menampilkannya sebagai nilai yang ditampilkan fungsi, gunakan jenis enum sebenarnya (bukan jenis bilangan bulat 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: Jenis dasar jenis enum dideklarasikan secara eksplisit setelah titik dua. Karena tidak bergantung pada compiler, penggunaan jenis enum sebenarnya lebih jelas.
Untuk nama yang sepenuhnya memenuhi syarat untuk nilai enum, titik dua digunakan di antara nama jenis enum dan nama nilai enum:
PACKAGE-NAME::UDT[.UDT[.UDT[…]]:ENUM_VALUE_NAME
Tidak boleh ada spasi di dalam nama yang sepenuhnya 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 /** */
tidak masalah.
// This is a single line comment /* This is also single line comment */ /** This is documentation comment */
-
Gunakan
/* */
untuk komentar. Meskipun HIDL mendukung//
untuk komentar, sebaiknya jangan menggunakannya karena tidak muncul dalam output yang dihasilkan. - Gunakan
/** */
untuk dokumentasi yang dihasilkan. Ini dapat diterapkan hanya pada deklarasi jenis, metode, kolom, 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 multibaris dengan
/**
pada baris terpisah. Gunakan*
di awal setiap baris. Akhiri komentar dengan*/
di baris terpisah, sejajarkan tanda bintang. Contoh:/** * My multi-line * comment */
- Pemberitahuan pemberian lisensi dan log perubahan harus memulai baris baru dengan
/*
(satu tanda bintang), menggunakan*
di awal setiap baris, dan menempatkan*/
di baris terakhirnya sendiri (tanda bintang harus sejajar). Contoh:/* * Copyright (C) 2017 The Android Open Source Project * ... */ /* * Changelog: * ... */
Komentar file
Mulai setiap file dengan pemberitahuan pemberian lisensi yang sesuai. Untuk HAL inti, ini harus berupa lisensi Apache AOSP di development/docs/copyright-templates/c.txt
.
Jangan lupa untuk memperbarui tahun dan menggunakan komentar multi-baris gaya /* */
seperti yang dijelaskan di atas.
Anda dapat secara opsional menempatkan baris kosong setelah pemberitahuan lisensi, diikuti dengan informasi log perubahan/versi. Gunakan komentar multi-baris gaya /* */
seperti yang dijelaskan di atas, letakkan baris kosong setelah log perubahan, 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 diizinkan selama pengembangan; komentar tersebut tidak boleh ada di antarmuka yang dipublikasikan.
Komentar antarmuka dan fungsi (docstring)
Gunakan /** */
untuk docstring multi-baris dan satu baris. Jangan gunakan
//
untuk docstring.
Docstring untuk antarmuka harus menjelaskan mekanisme umum antarmuka, alasan desain, tujuan, dll. Docstring untuk fungsi harus spesifik untuk fungsi (dokumentasi tingkat paket ada 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
dan @return
untuk setiap
parameter/nilai yang ditampilkan:
@param
harus ditambahkan untuk setiap parameter. Harus diikuti dengan nama parameter, lalu docstring.@return
harus ditambahkan untuk setiap nilai yang ditampilkan. Bagian ini harus diikuti dengan nama nilai yang ditampilkan, 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);
Aturan pemformatan
Aturan pemformatan umum meliputi:
- Panjang baris. Setiap baris teks harus memiliki panjang maksimal 100 kolom.
- Spasi kosong. Tidak ada spasi kosong di akhir baris; baris kosong tidak boleh berisi spasi kosong.
- Ruang vs. tab. Gunakan spasi saja.
- Ukuran indentasi. Gunakan 4 spasi untuk blok dan 8 spasi untuk baris yang dilipat
- Menahan. Kecuali untuk nilai anotasi, kurung buka berada di baris yang sama dengan kode sebelumnya, tetapi kurung 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 menempati seluruh baris, dan tidak boleh diindentasi. 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 yang ditampilkan harus
berada di baris yang sama jika muat. Contoh:
interface IFoo { /** ... */ easyMethod(int32_t data) generates (int32_t result); };
Jika tidak muat dalam baris yang sama, coba letakkan parameter dan nilai yang ditampilkan pada tingkat indentasi yang sama dan bedakan generate
untuk membantu pembaca melihat parameter dan nilai yang ditampilkan dengan cepat. 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); }
Detail tambahan:
- Tanda kurung buka selalu berada di 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 ada jeda baris di antaranya.
- Jika
generates
berada di baris yang sama dengan tanda kurung tutup sebelumnya, gunakan spasi sebelumnya. Jikagenerates
berada di baris yang sama dengan tanda kurung buka berikutnya, tambahkan spasi. - Sejajarkan semua parameter dan nilai yang ditampilkan (jika memungkinkan).
- Indentasi default adalah 4 spasi.
- Parameter yang di-wrap disejajarkan dengan parameter pertama pada baris sebelumnya, atau memiliki indentasi 8 spasi.
Anotasi
Gunakan format berikut untuk anotasi:
@annotate(keyword = value, keyword = {value, value, value})
Urutkan anotasi dalam urutan 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 ditempatkan pada baris yang sama, beri indentasi 8 spasi. Contoh:
@annotate( keyword = value, keyword = { value, value }, keyword = value)
Jika seluruh array nilai tidak dapat dimuat dalam baris yang sama, masukkan jeda baris setelah
kurung kurawal buka {
dan setelah setiap koma di dalam array. Tempatkan tanda kurung
penutup tepat setelah nilai terakhir. Jangan gunakan tanda kurung jika hanya ada satu nilai.
Jika seluruh array nilai dapat dimuat dalam baris yang sama, jangan gunakan spasi setelah kurung buka dan sebelum kurung tutup, serta 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, letakkan deklarasi
di
types.hal
, bukan menyematkannya di dalam antarmuka. - Gunakan spasi sebelum dan setelah titik dua, dan spasi setelah jenis pokok sebelum kurung kurawal buka.
- Nilai enum terakhir mungkin tidak memiliki koma tambahan.
Deklarasi struct
Gunakan aturan berikut untuk deklarasi struct:
- Jika deklarasi struct dibagikan dengan paket lain, letakkan deklarasi
di
types.hal
, bukan menyematkan di dalam antarmuka. - Gunakan spasi setelah nama jenis struct sebelum kurung kurawal buka.
- Menyelaraskan nama kolom (opsional). Contoh:
struct MyStruct { vec<uint8_t> data; int32_t someInt; }
Deklarasi array
Jangan beri spasi di antara berikut ini:
- Jenis elemen dan tanda kurung siku buka.
- Kurung siku buka dan ukuran array.
- Ukuran array dan kurung siku tutup.
- Tutup kurung siku dan buka kurung siku berikutnya, jika ada lebih dari satu dimensi.
Contoh:
/* Good */ int32_t[5] array; /* Good */ int32_t[5][6] multiDimArray; /* Bad */ int32_t [ 5 ] [ 6 ] array;
Vektor
Jangan beri spasi di antara berikut ini:
vec
dan kurung sudut buka.- Kurung sudut buka dan jenis elemen (Pengecualian: jenis elemen juga merupakan
vec
). - Jenis elemen dan tanda kurung sudut tutup (Pengecualian: jenis 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;