자바 SDK 라이브러리 구현

Android 플랫폼에는 다수의 공유 자바 라이브러리가 포함되어 있습니다. 이러한 라이브러리는 앱 매니페스트에서 <uses-library> 태그를 사용하여 앱의 클래스 경로에 선택적으로 포함할 수 있습니다. 앱은 이러한 라이브러리에 연결되어 호환성, API 검토 및 도구 지원 측면에서 라이브러리를 Android API의 일부인 것처럼 취급합니다. 그러나 대부분의 라이브러리에는 이러한 기능이 없습니다.

java_sdk_library 모듈 유형을 사용하면 이러한 종류의 라이브러리를 관리하는 데 도움이 됩니다. 기기 제조업체에서는 이러한 메커니즘을 자체 공유 자바 라이브러리에 사용하여 자체 API의 하위 호환성을 유지할 수 있습니다. 기기 제조업체가 부팅 클래스 경로 대신 <uses-library> 태그를 통해 자체 공유 자바 라이브러리를 사용하는 경우 java_sdk_library는 이러한 자바 라이브러리가 API에 대해 안정적인지 확인할 수 있습니다.

java_sdk_library는 선택사항인 SDK API를 앱에서 사용하도록 구현합니다. 빌드 파일(Android.bp)의 java_sdk_library를 통해 구현된 라이브러리는 다음과 같은 작업을 실행합니다.

  • 스텁 라이브러리는 stubs, stubs.system, stubs.test를 포함하도록 생성됩니다. 이러한 스텁 라이브러리는 @hide, @SystemApi, @TestApi 주석을 인식하는 방식으로 생성됩니다.
  • java_sdk_library는 API 하위 디렉터리의 API 사양 파일(예: current.txt)을 관리합니다. 최신 코드와 비교하여 이러한 파일이 최신 버전인지 확인합니다. 최신 버전이 아닌 경우 업데이트 방법을 설명하는 오류 메시지가 표시됩니다. 모든 업데이트 변경사항을 직접 검토하여 예상과 일치하는지 확인합니다.

    모든 API를 업데이트하려면 m update-api를 사용합니다. API가 최신 상태인지 확인하려면 m checkapi를 사용합니다.
  • API 사양 파일은 가장 최근에 게시된 Android 버전과 비교하여 API가 이전 버전과 호환되는지 확인합니다. AOSP의 일부로 제공되는 java_sdk_library 모듈은 이전에 출시된 버전을 prebuilts/sdk/<latest number>에 배치합니다.
  • API 사양 파일 검사와 관련하여 다음 3가지 중 하나를 실행하면 됩니다.
    • 검사를 진행하도록 허용합니다. (별도의 작업 필요 없음)
    • java_sdk_library에 다음을 추가하여 검사를 사용 중지합니다.
      unsafe_ignore_missing_latest_api: true,
    • version/scope/api 디렉터리module_name.txt라는 빈 텍스트 파일을 만들어 새 java_sdk_library 모듈에 빈 API를 제공합니다.
  • 런타임의 구현 라이브러리가 설치되면 XML 파일이 생성되고 설치됩니다.

java_sdk_library 작동 방식

X라는 java_sdk_library가 다음을 만듭니다.

  1. 구현 라이브러리의 사본 두 개(XX.impl)를 만듭니다. 라이브러리 X는 기기에 설치됩니다. 라이브러리 X.impl은 다른 모듈(예: 테스트에서 사용)에서 구현 라이브러리에 명시적으로 액세스해야 하는 경우에만 존재합니다. 명시적인 액세스는 거의 필요하지 않습니다.
  2. 범위를 사용 설정하거나 사용 중지하여 액세스를 맞춤설정할 수 있습니다. 자바 키워드 액세스 수정자와 마찬가지로 공개 범위는 광범위한 액세스 권한을 제공합니다. 테스트 범위에는 테스트에만 사용되는 API가 포함됩니다. 사용 설정된 범위마다 라이브러리에서 다음을 생성합니다.
    • 스텁 소스 모듈(droidstubs 모듈 유형) - 구현 소스를 사용하고 API 사양 파일과 함께 스텁 소스 집합을 출력합니다.
    • 스텁 라이브러리(java_library 모듈 유형) - 스텁의 컴파일된 버전입니다. 이를 컴파일하는 데 사용되는 라이브러리는 java_sdk_library에 제공된 것과 같지 않으므로 구현 세부정보가 API 스텁으로 유출되지 않습니다.
    • 스텁을 컴파일하기 위해 추가 라이브러리가 필요한 경우 stub_only_libsstub_only_static_libs 속성을 사용하여 제공합니다.

java_sdk_library의 이름이 'X'이고 'X'로 컴파일되는 경우 항상 이런 식으로 참조하고 이름을 수정하면 안 됩니다. 빌드에서 적절한 라이브러리를 선택합니다. 가장 적절한 라이브러리가 있도록 하려면 스텁을 검사하여 빌드에 오류가 발생했는지 확인합니다. 수정사항이 있는 경우 다음 안내를 따르세요.

  • 범위를 확인하기 위해 명령줄을 살펴보고 나열된 스텁을 검사하여 적합한 라이브러리가 있는지 확인합니다.
    • 범위가 너무 넓은 경우: 종속 라이브러리에 특정 API 범위가 필요합니다. 하지만, 공개 API가 포함된 시스템 API와 같이 이 범위에 포함되지 않는 API가 라이브러리에 포함되어 있습니다.
    • 범위가 너무 좁은 경우: 종속 라이브러리에 일부 필수 라이브러리에 대한 액세스 권한이 없습니다. 예를 들어, 종속 라이브러리가 시스템 API를 사용해야 하지만 대신 공개 API를 가져옵니다. 이렇게 하면 필요한 API가 누락되기 때문에 일반적으로 컴파일 오류가 발생합니다.
  • 라이브러리를 수정하려면 다음 중 하나만 실행합니다.
    • sdk_version을 변경하여 필요한 버전을 선택하거나
    • <X>.stubs 또는 <X>.stubs.system과 같은 적절한 라이브러리를 명시적으로 지정합니다.

java_sdk_library X 사용

구현 라이브러리 Xapex.java_libs에서 참조될 때 사용됩니다. 하지만, Soong 제한으로 인해 라이브러리 X동일한 APEX 라이브러리 내에 있는 다른 java_sdk_library 모듈에서 참조되면 라이브러리 X가 아닌 X.impl명시적으로 사용해야 합니다.

java_sdk_library가 다른 위치에서 참조되면 스텁 라이브러리가 사용됩니다. 스텁 라이브러리는 종속 모듈의 sdk_version 속성 설정에 따라 선택됩니다. 예를 들어 sdk_version: "current"를 지정하는 모듈은 공개 스텁을 사용하고 sdk_version: "system_current"를 지정하는 모듈은 시스템 스텁을 사용합니다. 완전히 일치하는 항목을 찾을 수 없으면 가장 가까운 스텁 라이브러리가 사용됩니다. 공개 API만 제공하는 java_sdk_library는 모든 사용자에게 공개 스텁을 제공합니다.

자바 SDK 라이브러리를 사용한 빌드 흐름
그림 1. 자바 SDK 라이브러리를 사용한 빌드 흐름

예시 및 소스

srcsapi_packages 속성은 java_sdk_library있어야 합니다.

java_sdk_library {
        name: "com.android.future.usb.accessory",
        srcs: ["src/**/*.java"],
        api_packages: ["com.android.future.usb"],
    }

AOSP에서는 새 java_sdk_library 인스턴스가 사용하려는 API 범위를 명시적으로 사용 설정하도록 권장합니다(필수는 아님). (선택사항) 기존 java_sdk_library 인스턴스를 이전하여 사용할 API 범위를 명시적으로 사용 설정할 수도 있습니다.

java_sdk_library {
         name: "lib",
         public: {
           enabled: true,
         },
         system: {
           enabled: true,
         },
         
    }

런타임에 사용되는 impl 라이브러리를 구성하려면 hostdex, compile_dex, errorprone 등 일반 java_library 속성을 모두 사용할 수 있습니다.

java_sdk_library {
        name: "android.test.base",

        srcs: ["src/**/*.java"],

        errorprone: {
          javacflags: ["-Xep:DepAnn:ERROR"],
        },

        hostdex: true,

        api_packages: [
            "android.test",
            "android.test.suitebuilder.annotation",
            "com.android.internal.util",
            "junit.framework",
        ],

        compile_dex: true,
    }

스텁 라이브러리를 구성하려면 다음 속성을 사용합니다.

  • merge_annotations_dirsmerge_inclusion_annotations_dirs
  • api_srcs: API의 일부이지만 런타임 라이브러리의 일부는 아닌 선택적 소스 파일 목록입니다.
  • stubs_only_libs: 스텁 빌드 시 클래스 경로에 위치하는 자바 라이브러리 목록입니다.
  • hidden_api_packages: API에서 숨겨야 하는 패키지 이름 목록입니다.
  • droiddoc_options: metalava의 추가 인수입니다.
  • droiddoc_option_files: $(location <label>)을 사용하여 droiddoc_options 내에서 참조할 수 있는 파일을 나열합니다. 여기서 <file>은 목록의 항목입니다.
  • annotations_enabled

java_sdk_libraryjava_library지만, droidstubs 모듈이 아니므로 일부 droidstubs 속성은 지원하지 않습니다. 다음 예는 android.test.mock 라이브러리 빌드 파일의 일부입니다.

java_sdk_library {
        name: "android.test.mock",

        srcs: [":android-test-mock-sources"],
        api_srcs: [
            // Note: The following aren’t APIs of this library. Only APIs under the
            // android.test.mock package are taken. These do provide private APIs
            // to which android.test.mock APIs reference. These classes are present
            // in source code form to access necessary comments that disappear when
            // the classes are compiled into a Jar library.
            ":framework-core-sources-for-test-mock",
            ":framework_native_aidl",
        ],

        libs: [
            "framework",
            "framework-annotations-lib",
            "app-compat-annotations",
            "Unsupportedappusage",
        ],

        api_packages: [
            "android.test.mock",
        ],
        permitted_packages: [
            "android.test.mock",
        ],
        compile_dex: true,
        default_to_stubs: true,
    }

하위 호환성 유지

빌드 시스템은 최신 API 파일과 빌드 시에 생성된 API 파일을 비교하여 API의 하위 호환성이 유지되는지 확인합니다. java_sdk_libraryprebuilt_apis에서 제공하는 정보를 사용하여 호환성 검사를 실행합니다. java_sdk_library로 빌드된 모든 라이브러리는 prebuilt_apis에 최신 버전의 api_dirs API 파일이 있어야 합니다. 버전을 출시하면 PRODUCT=sdk_phone_armv7-sdk를 포함하는 dist 빌드로 API 목록 파일과 스텁 라이브러리를 가져올 수 있습니다.

api_dirs 속성은 prebuilt_apis의 API 버전 디렉터리 목록입니다. API 버전 디렉터리는 Android.bp 디렉터리 수준에 있어야 합니다.

prebuilt_apis {
       name: "foo",
       api_dirs: [
           "1",
           "2",
             ....
           "30",
           "current",
       ],
    }

version/scope/api/ 구조체를 포함하는 디렉터리를 사전 빌드된 디렉터리 아래에 구성합니다. version은 API 수준에 상응하며 scope은 디렉터리가 공개 디렉터리인지, 시스템 디렉터리인지 또는 테스트 디렉터리인지 정의합니다.

  • version/scope에는 자바 라이브러리가 포함됩니다.
  • version/scope/api에는 API .txt 파일이 포함됩니다. 여기서 module_name.txtmodule_name-removed.txt라는 빈 텍스트 파일을 생성하세요.
     ├── 30
             ├── public
                ├── api
                   ├── android.test.mock-removed.txt
                   └── android.test.mock.txt
                └── android.test.mock.jar
             ├── system
                ├── api
                   ├── android.test.mock-removed.txt
                   └── android.test.mock.txt
                └── android.test.mock.jar
             └── test
                 ├── api
                    ├── android.test.mock-removed.txt
                    └── android.test.mock.txt
                 └── android.test.mock.jar
          └── Android.bp