AIDL의 주석

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

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

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

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

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

@AnnotationName AidlEntity

이러한 주석은 자바 주석과 매우 비슷해 보이지만 동일하지는 않습니다. 사용자는 맞춤 AIDL 주석을 정의할 수 없습니다. 주석은 모두 미리 정의되어 있습니다. 일부 주석은 특정 백엔드에만 영향을 주며 다른 백엔드에서는 작동하지 않습니다. 주석이 어떤 항목에 연결될 수 있는지에 대한 제한사항은 주석마다 다릅니다.

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

주석 Android 버전에 추가됨
nullable 7
utf8InCpp 7
VintfStability 11
UnsupportedAppUsage 10
Hide 11
Backing 11
JavaOnlyStableParcelable 11
JavaDerive 12
JavaPassthrough 12
FixedSize 12
Descriptor 12

nullable

nullable은 주석이 지정된 항목의 값이 제공되지 않을 수 있음을 선언합니다.

이 주석은 메서드 반환 유형, 메서드 매개변수 및 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

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

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

NDK 백엔드에서 @nullable T는 항상 std::optional<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은 작동하지 않습니다. 즉, @nullable IBinderIBinder는 모두 android::sp<IBinder>(강력한 포인터이기 때문에 이미 null을 허용할 수 있음)에 동일하게 매핑됩니다(CPP 읽기는 여전히 null 허용 여부를 적용하지만 형식은 android::sp<IBinder>입니다).

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

utf8InCpp

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

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

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

utf8InCpp 주석이 있다고 해서 문자열이 유선을 통해 전송되는 방식이 변경되지는 않습니다. 문자열은 항상 유선을 통해 UTF16으로 전송됩니다. utf8InCpp 주석이 지정된 문자열은 전송되기 전에 UTF16으로 변환됩니다. 문자열이 수신되었을 때 이 문자열이 utf8InCpp로 주석이 지정되었다면 UTF16에서 UTF8로 변환됩니다.

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 주석은 생성된 코드의 동작에 영향을 주지 않습니다. 이 주석은 생성된 자바 클래스에 대해 동일한 이름의 자바 주석으로만 주석을 지정합니다.

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

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

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

Backing

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비트 와이드)

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는 자바 백엔드에서 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를 사용하면 생성된 자바 API에 임의의 자바 주석을 지정할 수 있습니다.

AIDL의 다음 주석은

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

생성된 자바 코드에서 다음과 같은

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

주석이 됩니다.

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

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

FixedSize

FixedSize는 구조화된 parcelable을 고정 크기로 표시합니다. 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가 이를 인식할 수 있도록 자바 출력으로 전달합니다. 이 주석은 AIDL API가 SDK API가 아니라는 것을 Android 빌드 시스템이 알 수 있도록 지원합니다.

주석의 @deprecated

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

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

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