AIDL Stil Rehberi

Burada özetlenen en iyi uygulamalar, özellikle AIDL bir API tanımlamak veya API yüzeyleriyle etkileşimde bulunmak için kullanıldığında, AIDL arayüzlerini etkili bir şekilde ve arayüzün esnekliğine dikkat ederek geliştirmek için bir kılavuz olarak hizmet eder.

AIDL, uygulamaların bir arka plan işleminde birbirleriyle arayüz oluşturması veya sistemle arayüz oluşturması gerektiğinde bir API tanımlamak için kullanılabilir. AIDL ile uygulamalarda programlama arayüzleri geliştirme hakkında daha fazla bilgi için bkz. Android Arayüz Tanımlama Dili (AIDL) . Uygulamadaki AIDL örnekleri için bkz. HAL'ler için AIDL ve Stabil AIDL .

Sürüm oluşturma

Bir AIDL API'sinin geriye dönük uyumlu her anlık görüntüsü bir sürüme karşılık gelir. Anlık görüntü almak için m <module-name>-freeze-api çalıştırın. API'nin bir istemcisi veya sunucusu yayınlandığında (örneğin bir ana hat treninde), bir anlık görüntü almanız ve yeni bir sürüm oluşturmanız gerekir. Sistemden satıcıya API'ler için bu, yıllık platform revizyonunda gerçekleşmelidir.

İzin verilen değişiklik türleri hakkında daha fazla ayrıntı ve bilgi için bkz. Sürüm oluşturma arayüzleri .

API tasarım yönergeleri

Genel

1. Her şeyi belgeleyin

  • Anlambilimi, argümanları, yerleşik istisnaların kullanımı, hizmete özel istisnalar ve dönüş değeri açısından her yöntemi belgeleyin.
  • Anlamsal açıdan her arayüzü belgeleyin.
  • Numaralandırmaların ve sabitlerin anlamsal anlamını belgeleyin.
  • Bir uygulayıcı için belirsiz olabilecek her şeyi belgeleyin.
  • İlgili yerlerde örnekler verin.

2. Muhafaza

Türler için üst deve harfini ve yöntemler, alanlar ve argümanlar için alt deve harfini kullanın. Örneğin, parçalanabilir bir tür için MyParcelable ve bir bağımsız değişken için anArgument . Kısaltmalar için kısaltmayı bir kelime olarak düşünün ( NFC -> Nfc ).

[-Wconst-name] Numaralandırma değerleri ve sabitleri ENUM_VALUE ve CONSTANT_NAME olmalıdır

Arayüzler

1. Adlandırma

[-Winterface-name] Bir arayüz adı I like IFoo ile başlamalıdır.

2. Kimlik tabanlı "nesneler" içeren büyük arayüzden kaçının

Belirli bir API ile ilgili çok sayıda çağrı olduğunda alt arayüzleri tercih edin. Bu, aşağıdaki faydaları sağlar: - İstemci/sunucu kodunun anlaşılmasını kolaylaştırır - Nesnelerin yaşam döngüsünü kolaylaştırır - Bağlayıcıların taklit edilemez olmasının avantajından yararlanır.

Tavsiye edilmiyor: Kimlik tabanlı nesnelere sahip tek, geniş bir arayüz

interface IManager {
   int getFooId();
   void beginFoo(int id); // clients in other processes can guess an ID
   void opFoo(int id);
   void recycleFoo(int id); // ownership not handled by type
}

Önerilen: Bireysel alt arayüzler

interface IManager {
    IFoo getFoo();
}

interface IFoo {
    void begin(); // clients in other processes can't guess a binder
    void op();
}

3. Tek yönlü yöntemlerle çift yönlü yöntemleri karıştırmayın

[-Wmixed-oneway] Tek yönlü olmayan yöntemlerle tek yönlü yöntemleri karıştırmayın, çünkü bu, iş parçacığı modelinin anlaşılmasını istemciler ve sunucular için karmaşık hale getirir. Özellikle, belirli bir arayüzün istemci kodunu okurken, her yöntemin o yöntemin engellenip engellenmeyeceğini aramanız gerekir.

4. Durum kodlarını döndürmekten kaçının

Tüm AIDL yöntemlerinin örtülü bir durum dönüş kodu olduğundan, yöntemler dönüş değeri olarak durum kodlarından kaçınmalıdır. ServiceSpecificException veya EX_SERVICE_SPECIFIC bakın. Geleneksel olarak bu değerler AIDL arayüzünde sabitler olarak tanımlanır. Daha ayrıntılı bilgi AIDL Arka Uçlarının Hata işleme bölümündedir .

5. Çıkış parametreleri olarak diziler zararlı kabul edilir

[-Wout-array] void foo(out String[] ret) gibi dizi çıkış parametrelerine sahip yöntemler genellikle kötüdür çünkü çıktı dizisi boyutunun Java'da istemci tarafından bildirilmesi ve tahsis edilmesi gerekir ve bu nedenle dizi çıktısının boyutu yapılamaz. sunucu tarafından seçilebilir. Bu istenmeyen davranış, dizilerin Java'da çalışma biçiminden kaynaklanmaktadır (yeniden tahsis edilemezler). Bunun yerine String[] foo() gibi API'leri tercih edin.

6. Giriş parametrelerinden kaçının

[-Winout-parameter] Bu out in benzemektedir.

7. Out/inout @nullable dizi dışı parametrelerden kaçının

[-Wout-nullable] Diğer arka uçlar bunu yaparken Java arka ucu @nullable ek açıklamasını işlemediğinden, out/inout @nullable T arka uçlar arasında tutarsız davranışlara yol açabilir. Örneğin, Java dışı arka uçlar, out @nullable parametresini null olarak ayarlayabilir (C++'da std::nullopt olarak ayarlayarak), ancak Java istemcisi bunu null olarak okuyamaz.

Yapılandırılmış parsellenebilirler

1. Ne zaman kullanılmalı

Gönderecek birden fazla veri türünüzün olduğu yapılandırılmış parsellenebilirleri kullanın.

Veya şu anda tek bir veri türünüz varsa ancak gelecekte bunu genişletmeniz gerekeceğini düşünüyorsanız. Örneğin, String username kullanmayın. Aşağıdaki gibi genişletilebilir bir parsellenebilir kullanın:

parcelable User {
    String username;
}

Böylece gelecekte bunu aşağıdaki şekilde genişletebilirsiniz:

parcelable User {
    String username;
    int id;
}

2. Varsayılanları açıkça belirtin

[-Wexplicit-default, -Wenum-explicit-default] Alanlar için açık varsayılanlar sağlayın.

Yapılandırılmamış parsellenebilirler

1. Ne zaman kullanılmalı

Yapılandırılmış olmayan parsellenebilirler şu anda Java'da @JavaOnlyStableParcelable ile ve NDK arka ucunda @NdkOnlyStableParcelable ile mevcuttur. Genellikle bunlar kolayca yapılandırılamayan eski ve mevcut parsellenebilirlerdir.

Sabitler ve Numaralandırmalar

1. Bitfield'ler sabit alanları kullanmalıdır

Bit alanları sabit alanlar kullanmalıdır (örneğin, bir arayüzde const int FOO = 3; ).

2. Numaralandırmalar kapalı kümeler olmalıdır.

Numaralandırmalar kapalı kümeler olmalıdır. Not: yalnızca arayüz sahibi enum öğeleri ekleyebilir. Satıcıların veya OEM'lerin bu alanları genişletmesi gerekiyorsa alternatif bir mekanizmaya ihtiyaç vardır. Mümkün olduğunda, yukarı akışlı satıcı işlevselliği tercih edilmelidir. Ancak bazı durumlarda, özel satıcı değerlerine izin verilebilir (yine de satıcıların bunu sürümlendirecek bir mekanizmaya, belki de AIDL'ye sahip olmaları gerekir; birbirleriyle çakışmamaları gerekir ve bu değerler 3. parti uygulamalara maruz kalan).

3. "NUM_ELEMENTS" gibi değerlerden kaçının

Numaralandırmalar versiyonlu olduğundan, kaç değerin mevcut olduğunu gösteren değerlerden kaçınılmalıdır. C++'da bu durum enum_range<> ile çözülebilir. Rust için enum_values() işlevini kullanın. Java'da henüz bir çözüm yok.

Tavsiye edilmiyor: Numaralandırılmış değerlerin kullanılması

@Backing(type="int")
enum FruitType {
    APPLE = 0,
    BANANA = 1,
    MANGO = 2,
    NUM_TYPES, // BAD
}

4. Gereksiz önek ve son eklerden kaçının

[-Wredundant-name] Sabitlerde ve numaralandırıcılarda gereksiz veya yinelenen önek ve son eklerden kaçının.

Tavsiye edilmiyor: Gereksiz bir önek kullanma

enum MyStatus {
    STATUS_GOOD,
    STATUS_BAD // BAD
}

Önerilen: Numaralandırmayı doğrudan adlandırma

enum MyStatus {
    GOOD,
    BAD
}

Dosya Tanımlayıcı

[-Wfile-descriptor] FileDescriptor bağımsız değişken olarak veya bir AIDL arabirim yönteminin dönüş değeri olarak kullanılması kesinlikle önerilmez. Özellikle AIDL Java'da uygulandığında, bu durum dikkatli bir şekilde ele alınmadığı takdirde dosya tanımlayıcı sızıntısına neden olabilir. Temel olarak, bir FileDescriptor kabul ederseniz, artık kullanılmadığında onu manuel olarak kapatmanız gerekir.

Yerel arka uçlar için güvendesiniz çünkü FileDescriptor otomatik olarak kapatılabilen unique_fd ile eşleşir. Ancak kullanacağınız arka uç dili ne olursa olsun, FileDescriptor hiç KULLANMAMAK akıllıca olacaktır çünkü bu, gelecekte arka uç dilini değiştirme özgürlüğünüzü sınırlayacaktır.

Bunun yerine, otomatik olarak kapatılabilen ParcelFileDescriptor öğesini kullanın.

Değişken birimler

Değişken birimlerin isme dahil edildiğinden emin olun, böylece birimlerinin iyi tanımlanması ve belgelere başvurmaya gerek kalmadan anlaşılması sağlanır.

Örnekler

long duration; // Bad
long durationNsec; // Good
long durationNanos; // Also good

double energy; // Bad
double energyMilliJoules; // Good

int frequency; // Bad
int frequencyHz; // Good

Zaman damgaları referanslarını belirtmelidir

Zaman damgaları (aslında tüm birimler!) birimlerini ve referans noktalarını açıkça belirtmelidir.

Örnekler

/**
 * Time since device boot in milliseconds
 */
long timestampMs;

/**
 * UTC time received from the NTP server in units of milliseconds
 * since January 1, 1970
 */
long utcTimeMs;