Java SDK ライブラリの実装

Android プラットフォームには多数の共有 Java ライブラリが含まれており、必要であればアプリ マニフェストの <uses-library> タグを使用してアプリのクラスパスにそれらを含めることができます。これらのライブラリはアプリによってリンクされているため、互換性、API レビュー、ツールのサポートの点で、他の Android API と同様に扱う必要があります。ただし、ほとんどのライブラリにはこれらの機能はありません。

java_sdk_library モジュール タイプは、この種のライブラリの管理に役立ちます。デバイス メーカーは、独自の共有 Java ライブラリでこのメカニズムを使用して、独自の API の下位互換性を維持できます。デバイス メーカーがブート クラスパスの代わりに <uses-library> タグを介して独自の共有 Java ライブラリを使用している場合、java_sdk_library はそれらの Java ライブラリが API 安定性を持つことを確認できます。

java_sdk_library は、アプリで使用するオプションの SDK API を実装します。ビルドファイル(Android.bp)内の java_sdk_library を介して実装されたライブラリは、次の操作を実行します。

  • stubsstubs.systemstubs.test を含むスタブ ライブラリを生成します。これらのスタブ ライブラリは、@hide@SystemApi、および @TestApi アノテーションを認識することにより作成されます。
  • java_sdk_library は、API サブディレクトリ内の API 仕様ファイル(current.txt など)を管理します。これらのファイルは、最新のコードに照らしてチェックされ、最新バージョンであることを確認します。最新バージョンでない場合は、更新方法を説明するエラー メッセージが表示されます。すべての更新の変更を手動で確認し、想定どおりであることを確認します。

    すべての API を更新するには、m update-api を使用します。API が最新の状態であることを確認するには、m checkapi を使用します。
  • API 仕様ファイルは最新の API バージョンと照合され、以前のリリースとの下位互換性が保たれます。AOSP の一部として提供される java_sdk_library モジュールは、以前のリリース バージョンを prebuilts/sdk/<latest number> に配置します。
  • API 仕様ファイルのチェックでは、次の 3 つの処理のいずれかを行います。
    • チェックを続行します(何もしないでください)。
    • チェックを無効にするには、java_sdk_library に以下を追加します。
      unsafe_ignore_missing_latest_api: true,
    • 新しい java_sdk_library モジュールに空の API を指定するには、version/scope/api ディレクトリmodule_name.txt という名前の空のテキスト ファイルを作成します。
  • ランタイム用の実装ライブラリがインストールされている場合は、XML ファイルが生成されてインストールされます。

java_sdk_library の仕組み

X という java_sdk_library により、以下が作成されます。

  1. 実装ライブラリの 2 つのコピー: 一つは X と呼ばれるライブラリ、もう一つは X.impl と呼ばれるライブラリです。ライブラリ X はデバイスにインストールされています。ライブラリ X.impl が存在するのは、テストで使用するためなど、他のモジュールが実装ライブラリへの明示的なアクセスを必要とする場合のみです。明示的なアクセスが必要になることはほとんどありません。
  2. スコープを有効または無効にしてアクセスをカスタマイズできます(Java キーワード アクセス修飾子と同様に、パブリック スコープは幅広いアクセスを提供します。テストスコープには、テストでのみ使用される API が含まれます)。有効なスコープごとに、ライブラリにより以下が作成されます。
    • スタブソース モジュール(droidstubs モジュールタイプ)- 実装ソースを使用し、API 仕様ファイルとともにスタブソースのセットを出力します。
    • スタブ ライブラリ(java_library モジュール タイプ)- スタブのコンパイル済みバージョンです。このコンパイルに使用される lib は、java_sdk_library に提供される lib とは異なります。これにより、実装の詳細が API スタブにリークしません。
    • スタブをコンパイルするために追加のライブラリが必要な場合は、stub_only_libs プロパティと stub_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 の使用方法

実装ライブラリ X は、apex.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 は、すべてのユーザーに公開スタブを提供します。

Java SDK ライブラリを使用したビルドフロー
図 1. Java SDK ライブラリを使用したビルドフロー

例とソース

srcs プロパティと api_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 ライブラリを構成するには、hostdexcompile_dexerrorprone など、通常の 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: スタブをビルドする際のクラスパスに存在する Java ライブラリのリスト。
  • 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_library は、prebuilt_apis から提供される情報を使用して、互換性チェックを実行します。java_sdk_library でビルドされたすべてのライブラリでは、prebuilt_apis の最新バージョンの api_dirs に API ファイルが存在する必要があります。このバージョンをリリースすると、PRODUCT=sdk_phone_armv7-sdk を備えた配布ビルドで、API リストファイルとスタブ ライブラリを取得できます。

api_dirs プロパティは、prebuilt_apis に含まれる API バージョン ディレクトリのリストです。API バージョンのディレクトリは、Android.bp ディレクトリ レベルに配置する必要があります。

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

prebuilts ディレクトリの下の version/scope/api/ 構造を使用してディレクトリを構成します。version は API レベルに対応し、scope はディレクトリが public、system、test のいずれであるかを定義します。

  • version/scope には Java ライブラリを格納します。
  • 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