AIDL stil kılavuzu

Burada açıklanan en iyi uygulamalar, özellikle bir API'yi tanımlamak veya API yüzeyleriyle etkileşim kurmak için AIDL kullanıldığında, AIDL arayüzlerini etkili bir şekilde ve arayüzün esnekliğine dikkat ederek geliştirme konusunda bir rehber işlevi görür.

Uygulamaların arka planda bir işlemde birbirleriyle arayüzleşmesi ya da sistemle arayüz oluşturması gerektiğinde bir API tanımlamak için AIDL kullanılabilir. AIDL ile uygulamalarda programlama arayüzü geliştirme hakkında daha fazla bilgi için Android Arayüz Tanımlama Dili (AIDL) bölümüne bakın. Uygulamadaki AIDL örnekleri için HAL'ler için AIDL ve Kararlı AIDL'ye bakın.

Sürüm oluşturma

AIDL API'nin 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 komutunu çalıştırın. API'nin bir istemcisi veya sunucusu yayınlandığında (örneğin, bir Mainline treninde) anlık görüntü almanız ve yeni bir sürüm oluşturmanız gerekir. Sistemden tedarikçi firmaya API'ler için bu durum yıllık platform revizyonuyla yapılmalıdır.

İzin verilen değişiklik türü hakkında daha fazla ayrıntı ve bilgi için Sürüm oluşturma arayüzleri bölümüne bakın.

API tasarım yönergeleri

Genel

1. Her şeyi belgeleyin

  • Anlamları, bağımsız değişkenleri, yerleşik istisnaların kullanımı, hizmete özgü istisnalar ve dönüş değeri açısından her yöntemi belgeleyin.
  • Her arayüzü anlam açısından belgeleyin.
  • Enum ve sabit değerlerin anlamsal anlamını belgeleyin.
  • Uygulayan kişi için net olmayan noktaları belgeleyin.
  • Uygun yerlere örnekler verin.

2. Dış çizgi

Türler için deve büyük/küçük harf, yöntemler, alanlar ve bağımsız değişkenler için de alt büyük/küçük harf kullanın. Örneğin, ayrıştırılabilir tür için MyParcelable, bağımsız değişken için anArgument. Kısaltmalar için kelime kısaltmasını kullanabilirsiniz (NFC -> Nfc).

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

Arayüzler

1. Adlandırma

[-Winterface-name] Arayüz adı I ile başlamalıdır (ör. IFoo).

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

Belirli bir API ile ilgili çok sayıda çağrı olduğunda alt arayüzleri tercih edin. Bu durum, aşağıdaki avantajları sağlar:

  • İstemci veya sunucu kodunun daha kolay anlaşılmasını sağlar
  • Nesnelerin yaşam döngüsünü basitleştirir
  • Bağlayıcıların dövülemez olmasından faydalanır.

Önerilmez: Kimlik tabanlı nesnelere sahip tek, büyük 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: Bağımsız 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ü ve iki yönlü yöntemleri bir arada kullanmayın.

[-Wmixed-oneway] İş parçacığı oluşturma modelinin istemciler ve sunucular için anlaşılmasını karmaşık hale getireceğinden, tek yönlü olmayan yöntemlerle tek yönlü çalışmayın. Özellikle, belirli bir arayüzün istemci kodunu okurken her bir yöntemin engellenip engellenmeyeceğini aramanız gerekir.

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

Tüm AIDL yöntemlerinin örtülü durum döndürme kodu olduğundan, yöntemlerde durum kodları dönüş değeri olarak kullanmaktan kaçınılmalıdır. ServiceSpecificException veya EX_SERVICE_SPECIFIC sayfasına göz atın. Geleneksel olarak bu değerler, AIDL arayüzünde sabit değer olarak tanımlanır. Daha ayrıntılı bilgiyi AIDL arka uçlarının hata işleme bölümünde bulabilirsiniz.

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

[-Wout-array] void foo(out String[] ret) gibi dizi çıkış parametrelerine sahip yöntemler genellikle kötüdür. Bunun nedeni, çıkış dizisi boyutunun Java'da istemci tarafından bildirilmesi ve ayrılması gerektiği, dolayısıyla dizi çıkışının boyutu sunucu tarafından seçilmemesidir. Bu istenmeyen davranış, dizilerin Java'da çalışma şeklinden kaynaklanır (yeniden ayrılamazlar). Bunun yerine String[] foo() gibi API'leri tercih edin.

6. Giriş parametrelerinden kaçının

[-Winout-parametresi] in parametreleri bile out parametrelerine benzediğinden bu durum istemcilerin kafasını karıştırabilir.

7. Out ve inout @nullable dizi olmayan parametrelerden kaçının

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

Yapılandırılmış parseller

1. Ne zaman kullanılır?

Gönderilecek birden fazla veri türünün olduğu yapılandırılmış ayrıştırıcıları kullanın.

Ayrıca, tek bir veri türünüz varsa ancak gelecekte bu veri türünü genişletmeniz gerekeceğini düşünüyorsanız bu yöntemi tercih edebilirsiniz. Örneğin, String username kullanmayın. Aşağıdaki gibi genişletilebilir bir ayrıştırılabilir öğe kullanın:

parcelable User {
    String username;
}

Böylece, gelecekte bu süreyi aşağıdaki gibi uzatabilirsiniz:

parcelable User {
    String username;
    int id;
}

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

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

Yapılandırılmamış parseller

1. Ne zaman kullanılır?

Yapılandırılmamış parseller Java'da @JavaOnlyStableParcelable ile, NDK arka ucunda ise @NdkOnlyStableParcelable ile kullanılabilir. Bunlar genellikle yapılandırılamayan eski ve mevcut parsellerdir.

Sabitler ve numaralandırmalar

1. Bit alanları sabit alanlar kullanmalıdır

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

2. Sıralamalar kapalı kümeler olmalıdır.

Sıralamalar kapalı kümeler olmalıdır. Not: Enum öğeleri yalnızca arayüz sahibi ekleyebilir. Tedarikçilerin veya OEM'lerin bu alanları genişletmesi gerekiyorsa alternatif bir mekanizma gerekir. Mümkün olduğunda, yukarı dönük tedarikçi işlevselliği tercih edilmelidir. Bununla birlikte, bazı durumlarda özel tedarikçi firma değerlerine bu yöntemle izin verilebilir (ancak tedarikçi firmaların, AIDL'nin kendisini geliştirecek bir mekanizmaya sahip olmaları gerekir; birbirleriyle çelişememeleri ve üçüncü taraf uygulamalarında bu değerler kullanılmamalıdır).

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

Sıralamalar sürümlü olduğu için kaç değerin mevcut olduğunu gösteren değerlerden kaçınılmalıdır. C++'ta bu sorun, enum_range<> ile çözülebilir. Pas için enum_values() değerini kullanın. Java'da henüz bir çözüm yok.

Önerilmez: Numaralı değerler kullanılması

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

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

[-Wredunt-name] Sabit değerlerde ve numaralandırıcılarda gereksiz veya yinelenen önekler ve sonekler kullanmaktan kaçının.

Önerilmez: Gereksiz bir önek kullanılması

enum MyStatus {
    STATUS_GOOD,
    STATUS_BAD // BAD
}

Önerilen: Sıralamayı doğrudan adlandırma

enum MyStatus {
    GOOD,
    BAD
}

Dosya Açıklayıcı

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

FileDescriptor, otomatik olarak kapatılabilen unique_fd ile eşlendiğinden yerel arka uçlarda güvendesiniz. Ancak kullanacağınız arka uç dilinden bağımsız olarak, gelecekte arka uç dilini değiştirme özgürlüğünüzü sınırlandıracağı için FileDescriptor KULLANMAYIN.

Bunun yerine, otomatik kapatılabilen ParcelFileDescriptor özelliğini kullanın.

Değişken birimler

Değişken birimlerin ada eklendiğinden emin olun. Böylece, birimlerin belgelere referansta bulunmadan iyi tanımlanmasını ve anlaşılmasını sağlayabilirsiniz.

Ö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ı göstermelidir

Zaman damgaları, 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;