AIDL의 주석

AIDL은 주석이 지정된 요소에 관한 추가 정보를 AIDL 컴파일러에 제공하는 주석을 지원하며 이는 생성된 스텁 코드에도 영향을 줍니다.

구문은 다음과 같이 Java 구문과 유사합니다.

@AnnotationName(argument1=value, argument2=value) AidlEntity

여기서 AnnotationName은 주석의 이름이며 AidlEntityinterface Foo, void method(), int arg와 같은 AIDL 항목입니다. 주석은 그 뒤에 오는 항목에 연결됩니다.

일부 주석에서는 이전 예와 같이 괄호 안에 인수를 설정할 수 있습니다. 인수가 없는 주석에는 괄호가 필요하지 않습니다. 예를 들면 다음과 같습니다.

@AnnotationName AidlEntity

이러한 주석은 Java 주석과 매우 비슷해 보이지만 동일하지는 않습니다. 모든 주석은 사전 정의되어 있으며 주석을 연결할 수 있는 위치에 제한이 있습니다. 일부 주석은 특정 백엔드에만 영향을 주며 다른 백엔드에서는 작동하지 않습니다.

다음은 사전 정의된 AIDL 주석의 목록입니다.

주석추가된 Android 버전
nullable7
utf8InCpp7
VintfStability11
UnsupportedAppUsage10
Hide11
Backing11
NdkOnlyStableParcelable14
JavaOnlyStableParcelable11
JavaDerive12
JavaPassthrough12
FixedSize12
Descriptor12

nullable

nullable은 주석이 지정된 항목의 값이 null일 수 있음을 선언합니다.

이 주석은 메서드 반환 유형, 메서드 매개변수, parcelable 필드에만 연결할 수 있습니다.

interface IFoo {
    // method return types
    @nullable Data method();

    // method parameters
    void method2(in @nullable Data d);
}

parcelable Data {
    // parcelable fields
    @nullable Data d;
}

주석은 기본 유형에 연결될 수 없습니다. 다음은 오류입니다.

void method(in @nullable int a); // int is a primitive type

이 주석은 Java 백엔드에는 작동하지 않습니다. Java에서 기본 유형이 아닌 모든 유형은 참조로 전달되며 null일 수 있습니다.

CPP 백엔드에서 @nullable T는 Android 11 이하에서는 std::unique_ptr<T>에 매핑되고 Android 12 이상에서는 std::optional<T>에 매핑됩니다.

NDK 백엔드에서 @nullable Tstd::optional<T>에 매핑됩니다.

Rust 백엔드에서 @nullable TOption<T>에 매핑됩니다.

T[] 또는 List<T>와 같이 목록과 유사한 유형 L의 경우 @nullable Lstd::optional<std::vector<std::optional<T>>>(또는 Android 11 이하용 CPP 백엔드의 경우 std::unique_ptr<std::vector<std::unique_ptr<T>>>)에 매핑됩니다.

이 매핑에는 예외가 있습니다. TIBinder 또는 AIDL 인터페이스일 때 @nullable은 Rust를 제외한 모든 백엔드에서 작동하지 않습니다. 즉, @nullable IBinderIBinder는 모두 android::sp<IBinder>(강력한 포인터이기 때문에 이미 null을 허용할 수 있음)에 동일하게 매핑됩니다(CPP 읽기는 여전히 null 허용 여부를 적용하지만 형식은 android::sp<IBinder>입니다). Rust에서는 이러한 유형이 @nullable로 주석 처리된 경우에만 nullable입니다. 주석이 추가된 경우 Option<T>에 매핑됩니다.

Android 13부터는 @nullable(heap=true)를 parcelable 필드에 사용하여 재귀 유형을 모델링할 수 있습니다. @nullable(heap=true)는 메서드 매개변수 또는 반환 유형과 함께 사용할 수 없습니다. 이 주석을 달면 필드가 CPP 및 NDK 백엔드의 힙 할당 참조 std::unique_ptr<T>에 매핑됩니다. @nullable(heap=true)는 Java 백엔드에서 작동하지 않습니다.

utf8InCpp

utf8InCppString이 CPP 백엔드에 관해 UTF8 형식으로 표시된다는 것을 선언합니다. 이름에서 알 수 있듯이 이 주석은 다른 백엔드에서는 작동하지 않습니다. 특히 String은 Java 백엔드에서 항상 UTF16이며 NDK 백엔드에서는 UTF8입니다.

반환 값, 매개변수, 상수 선언, parcelable 필드 등 String 유형을 사용할 수 있는 곳이면 어디에나 이 주석을 지정할 수 있습니다.

CPP 백엔드의 경우 AIDL의 @utf8InCpp Stringstd::string에 매핑되지만 주석이 없는 String은 UTF16이 사용되는 android::String16에 매핑됩니다.

VintfStability

VintfStability는 사용자 정의 유형(인터페이스, parcelable 및 enum)을 시스템 및 공급업체 도메인 전체에서 사용할 수 있음을 선언합니다. 시스템-공급업체 상호 운용성에 관한 자세한 내용은 HAL용 AIDL을 참조하세요.

주석이 유형의 서명을 변경하지 않지만 설정될 경우 유형의 인스턴스는 공급업체 및 시스템 프로세스 전체에 걸쳐 이동할 수 있도록 안정적인 것으로 표시됩니다.

주석은 다음과 같이 사용자 정의 유형 선언에만 연결될 수 있습니다.

@VintfStability
interface IFoo {
    ....
}

@VintfStability
parcelable Data {
    ....
}

@VintfStability
enum Type {
    ....
}

유형이 VintfStability로 주석이 지정될 때 유형에서 참조되는 다른 유형도 이와 같이 주석이 지정되어야 합니다. 다음 예에서 DataIBar는 모두 VintfStability로 주석이 지정되어야 합니다.

@VintfStability
interface IFoo {
    void doSomething(in IBar b); // references IBar
    void doAnother(in Data d); // references Data
}

@VintfStability // required
interface IBar {...}

@VintfStability // required
parcelable Data {...}

또한 VintfStability로 주석이 지정된 유형을 정의하는 AIDL 파일은 stability 속성이 vintf로 설정된 aidl_interface Soong 모듈 유형을 사용해서만 빌드할 수 있습니다.

aidl_interface {
    name: "my_interface",
    srcs: [...],
    stability: "vintf",
}

UnsupportedAppUsage

UnsupportedAppUsage 주석은 주석이 지정된 AIDL 유형이 레거시 앱에서 액세스할 수 있는 비 SDK 인터페이스의 일부임을 나타냅니다. 숨겨진 API에 관한 자세한 내용은 비 SDK 인터페이스 제한사항을 참고하세요.

UnsupportedAppUsage 주석은 생성된 코드의 동작에 영향을 주지 않습니다. 이 주석은 생성된 Java 클래스에 대해 동일한 이름의 Java 주석으로만 주석을 지정합니다.

// in AIDL
@UnsupportedAppUsage
interface IFoo {...}

// in Java
@android.compat.annotation.UnsupportedAppUsage
public interface IFoo {...}

이 주석은 Java가 아닌 백엔드에서는 작동하지 않습니다.

지원 주석

Backing 주석은 AIDL enum 유형의 저장소 유형을 지정합니다.

@Backing(type="int")
enum Color { RED, BLUE, }

CPP 백엔드에서 이 코드는 int32_t 유형의 C++ enum 클래스를 내보냅니다.

enum class Color : int32_t {
    RED = 0,
    BLUE = 1,
}

주석이 생략되면 typebyte인 것으로 간주되며, 이는 CPP 백엔드의 경우 int8_t에 매핑됩니다.

type 인수는 다음 정수 유형으로만 설정할 수 있습니다.

  • byte(8비트 와이드)
  • int(32비트 와이드)
  • long(64비트 와이드)

NdkOnlyStableParcelable

NdkOnlyStableParcelable은 다른 안정적인 AIDL 유형에서 참조될 수 있도록 parcelable 선언(정의가 아님)을 안정적인 것으로 표시합니다. 이는 JavaOnlyStableParcelable과 비슷하지만, NdkOnlyStableParcelable은 Java 대신 NDK 백엔드에 parcelable 선언을 안정적인 것으로 표시합니다.

이 parcelable을 사용하려면 다음 안내를 따르세요.

  • ndk_header을 지정해야 합니다.
  • parcelable을 지정하는 NDK 라이브러리가 있어야 하고 라이브러리는 라이브러리에 컴파일되어야 합니다. 예를 들어 cc_* 모듈의 핵심 빌드 시스템에서는 static_libs 또는 shared_libs를 사용합니다. aidl_interface의 경우에는 Android.bpadditional_shared_libraries 아래 라이브러리를 추가합니다.

JavaOnlyStableParcelable

JavaOnlyStableParcelable은 다른 안정적인 AIDL 유형에서 참조될 수 있도록 parcelable 선언(정의가 아님)을 안정적인 것으로 표시합니다.

안정적인 AIDL을 사용하려면 모든 사용자 정의 유형이 안정적이어야 합니다. parcelable의 경우 안정적이려면 해당 필드가 AIDL 소스 파일에 명시적으로 설명되어 있어야 합니다.

parcelable Data { // Data is a structured parcelable.
    int x;
    int y;
}

parcelable AnotherData { // AnotherData is also a structured parcelable
    Data d; // OK, because Data is a structured parcelable
}

parcelable이 구조화되지 않았다면 (또는 선언만 되었다면) 참조할 수 없습니다.

parcelable Data; // Data is NOT a structured parcelable

parcelable AnotherData {
    Data d; // Error
}

JavaOnlyStableParcelable을 사용하면 참조하는 parcelable이 Android SDK의 일부로 안전하게 제공되는 경우에 검사를 재정의할 수 있습니다.

@JavaOnlyStableParcelable
parcelable Data;

parcelable AnotherData {
    Data d; // OK
}

JavaDerive

JavaDerive는 Java 백엔드에서 parcelable 유형의 메서드를 자동으로 생성합니다.

@JavaDerive(equals = true, toString = true)
parcelable Data {
  int number;
  String str;
}

주석에는 생성할 항목을 제어하기 위한 추가 매개변수가 필요합니다. 지원되는 매개변수는 다음과 같습니다.

  • equals=trueequalshashCode 메서드를 생성합니다.
  • toString=true는 유형 및 필드 이름을 출력하는 toString 메서드를 생성합니다(예: Data{number: 42, str: foo}).

JavaDefault (지원 중단됨)

Android 13에 추가된 JavaDefaultsetDefaultImpl의 기본 구현 버전 관리 지원이 생성되는지 여부를 제어합니다. 이 지원은 공간 절약을 위해 더 이상 기본적으로 생성되지 않습니다.

JavaPassthrough

JavaPassthrough를 사용하면 생성된 Java API에 임의의 Java 주석을 지정할 수 있습니다.

AIDL의 이러한 주석은 다음을 충족해야 합니다.

@JavaPassthrough(annotation="@android.annotation.Alice")
@JavaPassthrough(annotation="@com.android.Alice(arg=com.android.Alice.Value.A)")

생성된 Java 코드에서 다음과 같이 됩니다.

@android.annotation.Alice
@com.android.Alice(arg=com.android.Alice.Value.A)

annotation 매개변수의 값을 직접 내보냅니다. AIDL 컴파일러는 매개변수의 값을 검사하지 않습니다. Java 수준 구문 오류가 있다면 이 오류는 AIDL 컴파일러가 아니라 Java 컴파일러에 의해 포착됩니다.

이 주석은 어떤 AIDL 항목에든 연결될 수 있습니다. 이 주석은 Java가 아닌 백엔드에서는 작동하지 않습니다.

RustDerive

RustDerive는 생성된 Rust 유형의 트레잇을 자동으로 구현합니다.

주석에는 생성할 항목을 제어하기 위한 추가 매개변수가 필요합니다. 지원되는 매개변수는 다음과 같습니다.

  • Copy=true
  • Clone=true
  • Ord=true
  • PartialOrd=true
  • Eq=true
  • PartialEq=true
  • Hash=true

이러한 특성에 대한 설명은 Rust 문서를 참고하세요.

FixedSize

FixedSize는 구조화된 parcelable을 고정 크기로 표시합니다. 표시된 후에는 parcelable에 새 필드를 추가할 수 없습니다. 또한 기본 유형, 고정 크기 배열, enum 및 FixedSize로 표시된 기타 parcelable을 포함하여 parcelable의 모든 필드는 고정 크기 유형이어야 합니다.

Descriptor

Descriptor는 인터페이스의 인터페이스 설명어를 강제로 지정합니다.

package android.foo;

@Descriptor(value="android.bar.IWorld")
interface IHello {...}

이 인터페이스의 설명어는 android.bar.IWorld입니다. Descriptor 주석이 누락되었다면 설명어는 android.foo.IHello입니다.

이 주석은 이미 게시된 인터페이스의 이름을 바꿀 때 유용합니다. 이름이 변경되는 인터페이스의 설명어를 이름 변경 전의 인터페이스 설명어와 동일하게 만들면 두 인터페이스가 서로 통신할 수 있습니다.

주석의 @hide

AIDL 컴파일러는 주석에서 @hide를 인식하여 Metalava가 이를 인식할 수 있도록 Java 출력으로 전달합니다. 이 주석은 Android 빌드 시스템이 AIDL API가 SDK API가 아님을 인식하도록 지원합니다.

주석의 @deprecated

AIDL 컴파일러는 주석에서 @deprecated를 더 이상 사용해서는 안 되는 AIDL 항목을 식별하는 태그로 인식합니다.

interface IFoo {
  /** @deprecated use bar() instead */
  void foo();
  void bar();
}

각 백엔드는 클라이언트 코드가 지원 중단된 항목을 참조할 때 경고가 발생할 수 있도록 백엔드별 주석 또는 속성을 사용하여 지원 중단된 항목을 표시합니다. 예를 들어, Java 생성 코드에는 @Deprecated 주석과 @deprecated 태그가 연결됩니다.