資料類型

Java HIDL 後端會根據 HIDL 介面檔案,產生 Java 介面、Stub 和 Proxy 程式碼。它支援所有純量 HIDL 型別 ([u]int{8,16,32,64}_t, float, double,enums),以及字串、介面、safe_union 型別、struct 型別,以及支援的 HIDL 型別的陣列和向量。Java HIDL 後端不支援聯集型別或 fmq 型別。Android 11 新增對 memoryhandle 類型的支援。

由於 Java 執行階段不支援原生無符號整數的概念,因此所有無符號型別 (以及以這些型別為基礎的列舉) 都會以無訊息方式視為對應的有符號型別,也就是說,uint32_t 會在 Java 介面中變成 int。不會執行任何價值轉換;Java 端實作者必須使用已簽署的值,就像這些值未簽署一樣。

列舉

列舉不會產生 Java 列舉類別,而是會轉換為內部類別,其中包含每個列舉案例的靜態常數定義。如果列舉類別衍生自其他列舉類別,則會繼承該類別的儲存空間類型。系統會將以不帶正負號的整數型別為基礎的列舉,改寫為帶正負號的對等項目。由於基礎型別是原始型別,即使沒有零列舉值,列舉欄位/變數的預設值仍為零。

舉例來說,類型為 uint8_tSomeBaseEnum

enum SomeBaseEnum : uint8_t { foo = 3 };
enum SomeEnum : SomeBaseEnum {
    quux = 33,
    goober = 127
};

… 會變成:

public final class SomeBaseEnum { public static final byte foo = 3; }
public final class SomeEnum {
    public static final byte foo = 3;
    public static final byte quux = 33;
    public static final byte goober = 127;
}

且:

enum SomeEnum : uint8_t {
    FIRST_CASE = 10,
    SECOND_CASE = 192
};

… 會重新編寫為:

public final class SomeEnum {
    static public final byte FIRST_CASE  = 10;  // no change
    static public final byte SECOND_CASE = -64;
}

字串

Java 中的 String 是 utf-8 或 utf-16,但傳輸時會轉換為 utf-8,做為常見的 HIDL 型別。此外,傳遞至 HIDL 時,String 不得為空值。

把手和記憶體

Android 11 推出 Java 支援功能,適用於 handlememory 類型。分別翻譯成 android.os.NativeHandleandroid.os.HidlMemory。空值控制代碼視為有效,但空值記憶體則否。

在產生的伺服器程式碼中,收到的記憶體和控制代碼引數僅在方法調用範圍內有效。如果伺服器實作想延長生命週期,就必須使用各自的 dup() 方法複製。傳回的例項可在方法呼叫後使用,且使用完畢後應正確關閉。

在產生的用戶端程式碼中,做為所呼叫方法輸入引數傳送的控制代碼和記憶體執行個體,不需要重複,也不必在方法傳回後保持有效。不過,以輸出引數接收的控制代碼和記憶體執行個體會由自動產生的程式碼自動複製,因此使用完畢後必須正確關閉。無論這些傳回引數是顯示為方法傳回值 (單一傳回值的情況),還是使用同步回呼樣式 (多個傳回值的情況),都是如此。

如要進一步瞭解重複和關閉作業,請參閱 Java 類別的說明文件。

陣列和向量

陣列會轉換為 Java 陣列,向量則會轉換為 ArrayList<T>,其中 T 是適當的物件型別,可能會包裝純量型別,例如 vec<int32_t> => ArrayList<Integer>。舉例來說:

takeAnArray(int32_t[3] array);
returnAVector() generates (vec<int32_t> result);

… 會變成:

void takeAnArray(int[] array);
ArrayList<Integer> returnAVector();

結構

結構會轉換為具有類似版面的 Java 類別。例如:

struct Bar {
 vec<bool> someBools;
};
struct Foo {
 int32_t a;
 int8_t b;
 float[10] c;
 Bar d;
};

… 會變成:

class Bar {
 public final ArrayList<Boolean> someBools = new ArrayList();
};
class Foo {
 public int a;
 public byte b;
 public final float[] c = new float[10];
 public final Bar d = new Bar();
}

已宣告的類型

types.hal 中宣告的每個頂層型別都會有自己的 .java 輸出檔案 (Java 的規定)。舉例來說,下列 types.hal 檔案會導致系統建立兩個額外檔案 (Foo.java 和 Bar.java):

struct Foo {
 ...
};

struct Bar {
 ...

 struct Baz {
 };

 ...
};

Baz 的定義位於 Bar 的靜態內部類別 (位於 Bar.java 中)。