新しいデバイスの追加

このページでは、デバイスやプロダクトの Makefile を作成する手順について説明します。

新しい Android モジュールには、それぞれモジュール メタデータや、コンパイル時の依存関係、パッケージ化手順を通じてビルドシステムに指示する構成ファイルが必要です。また、Android は Soong ビルドシステムを使用します。Android ビルドシステムの詳細については、Android のビルドをご覧ください。

ビルドレイヤについて

ビルド階層は、デバイスの物理構成に対応する抽象化レイヤで構成されます。各レイヤについては、下記の表をご覧ください。各レイヤは 1 対多の関係で上位レイヤに関連付けられます。たとえば、各アーキテクチャは複数のボードを持つことができ、各ボードは複数のプロダクトを持つことができます。特定のレイヤ内の要素を、同じレイヤ内の要素の特殊化として定義することもできます。そうすることで、コピー処理が不要になり、メンテナンスが容易になります。

レイヤ 説明
プロダクト myProduct、myProduct_eu、myProduct_eu_fr、j2、sdk プロダクト レイヤでは、ビルド対象となるモジュールや、サポート対象の言語 / 地域、さまざまな言語 / 地域向けの構成など、リリースするプロダクトの機能仕様を定義します。これがプロダクト全体を示す名称になります。プロダクト固有の変数は、プロダクト定義 Makefile で定義されます。プロダクトは他のプロダクト定義から継承でき、これによりメンテナンスが容易になります。すべてのプロダクトに適用される機能を含むベース プロダクトを作成し、そのベース プロダクトに基づいてプロダクト バリアントを作成するというのが一般的な方法です。たとえば、無線通信方式だけが異なる 2 つのプロダクト(それぞれ CDMA と GSM を採用)は、無線通信方式が定義されていない同一のベース プロダクトから継承できます。
ボード / デバイス marlin、blueline、coral ボード / デバイスレイヤは、デバイス上の物理プラスチック レイヤ(デバイスの産業デザイン)を示します。また、このレイヤは、プロダクトの最低限の概要についても示します。ボード上の周辺機器やその構成が含まれます。各種のボード / デバイス構成を示すコードが名称として使用されます。
アーキテクチャ arm、x86、arm64、x86_64 アーキテクチャ レイヤは、ボード上で稼働するプロセッサ構成とアプリケーション バイナリ インターフェース(ABI)を示します。

ビルド バリアントを使用する

特定のプロダクトを対象としてビルドを実行する場合、最終的なリリースビルドに小さな変更を加えたバリアントを用意しておくと便利です。モジュール定義内で LOCAL_MODULE_TAGS を使用することで、モジュールに対してタグを指定できます。このタグの値には、optional(デフォルト)、debugeng を指定できます(複数可)。

モジュールが LOCAL_MODULE_TAGS によってタグを指定していない場合、タグのデフォルト値は optional になります。オプション モジュールは、PRODUCT_PACKAGES のプロダクト構成によって必要とされる場合に限りインストールされます。

現在定義されているビルド バリアントは次のとおりです。

バリアント 説明
eng これはデフォルトのフレーバーです。
  • eng または debug でタグ付けされたモジュールをインストールします。
  • プロダクト定義ファイルに沿って、タグ付けされているモジュール以外のモジュールもインストールします。
  • ro.secure=0
  • ro.debuggable=1
  • ro.kernel.android.checkjni=1
  • adb はデフォルトで有効になっています。
user 最終的なリリースビットとなるバリアントです。
  • user でタグ付けされたモジュールをインストールします。
  • プロダクト定義ファイルに沿って、タグ付けされているモジュール以外のモジュールもインストールします。
  • ro.secure=1
  • ro.debuggable=0
  • adb はデフォルトで無効になっています。
userdebug user と同等ですが、以下の点が異なります。
  • debug でタグ付けされたモジュールもインストールします。
  • ro.debuggable=1
  • adb はデフォルトで有効になっています。

userdebug のガイドライン

デバイス デベロッパーは、テスト時に userdebug ビルドを実行することで、開発中のリリースのパフォーマンスや機能を把握できます。user ビルドと userdebug ビルド間の整合性を維持し、デバッグに使用するビルドにおいて信頼できる指標を達成するには、次のガイドラインに従ってください。

  • userdebug は、root アクセスを有効にした user ビルドとして定義します。ただし、例外として次のものがあります。
    • ユーザーがオンデマンドでのみ実行する userdebug 専用アプリ
    • 充電中やフル充電時のアイドル状態のメンテナンス中にのみ実行される処理(バックグラウンド コンパイル用の dex2oat に対して dex2oatd を使用する場合など)
  • ビルドタイプに基づいてデフォルトで有効 / 無効になっている機能は組み込まないでください。デバッグログやヒープダンプなど、バッテリー寿命に影響するロギングは使用しないことをおすすめします。
  • userdebug 内でデフォルトで有効にするデバッグ機能を明確に定義して、プロジェクトにかかわるすべてのデベロッパー間で共有してください。デバッグ機能を有効にするのは、デバッグ対象の問題が解決するまでの期間だけに限定してください。

リソース オーバーレイを使用してビルドをカスタマイズする

Android ビルドシステムは、リソース オーバーレイを使用してビルド時にプロダクトをカスタマイズします。リソース オーバーレイは、デフォルト設定の上に重ねて適用するリソース ファイルを指定します。リソース オーバーレイを使用するには、プロジェクトのビルドファイルを編集して、最上位ディレクトリを基準とする相対パスとして PRODUCT_PACKAGE_OVERLAYS を設定します。このパスは、ビルドシステムがリソースを検索する際に、現在のルートとともに検索されるシャドウルートになります。

最も一般的にカスタマイズが行われている設定は、frameworks/base/core/res/res/values/config.xml ファイルにあります。

このファイルに対してリソース オーバーレイをセットアップするには、次のいずれかを使用して、プロジェクトのビルドファイルにオーバーレイ ディレクトリを追加します。

PRODUCT_PACKAGE_OVERLAYS := device/device-implementer/device-name/overlay

あるいは

PRODUCT_PACKAGE_OVERLAYS := vendor/vendor-name/overlay

そして、このディレクトリにオーバーレイ ファイルを追加します。たとえば、次のようになります。

vendor/foobar/overlay/frameworks/base/core/res/res/values/config.xml

config.xml オーバーレイ ファイル内の文字列または文字列配列が、元のファイルの内容を置き換えます。

プロダクトをビルドする

デバイスのソースファイルは、さまざまな方法で整理できます。ここでは、Pixel 実装を整理する方法の一つを簡単に説明します。

Pixel は、marlin という名前のメインデバイス構成を使用して実装されます。プロダクトは、このデバイス構成を基にして、デバイスに関するプロダクト固有の情報(名前やモデルなど)を宣言するプロダクト定義 Makefile を使用して作成されます。device/google/marlin ディレクトリを表示すると、セットアップ全体を確認できます。

プロダクト Makefile を作成する

プロダクト Makefile をセットアップする手順は以下のとおりです(Google Pixel プロダクト ラインでも同様の手順で行っています)。

  1. プロダクトの device/<company-name>/<device-name> ディレクトリを作成します(例: device/google/marlin)。このディレクトリには、ビルド対象となるデバイスのソースコードと Makefile が格納されます。
  2. デバイスに必要なファイルとモジュールを宣言する device.mk Makefile を作成します。例として、device/google/marlin/device-marlin.mk をご覧ください。
  3. デバイスに基づいて特定のプロダクトを作成するプロダクト定義 Makefile を作成します。以下では、device/google/marlin/aosp_marlin.mk からの Makefile を例として使用します。このプロダクトは、Makefile を通じて device/google/marlin/device-marlin.mk ファイルと vendor/google/marlin/device-vendor-marlin.mk ファイルから継承しつつ、名前やブランド、モデルなどのプロダクト固有の情報を宣言しています。
    # Inherit from the common Open Source product configuration
    $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
    $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base_telephony.mk)
    
    PRODUCT_NAME := aosp_marlin
    PRODUCT_DEVICE := marlin
    PRODUCT_BRAND := Android
    PRODUCT_MODEL := AOSP on msm8996
    PRODUCT_MANUFACTURER := Google
    PRODUCT_RESTRICT_VENDOR_FILES := true
    
    PRODUCT_COPY_FILES += device/google/marlin/fstab.common:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.marlin
    
    $(call inherit-product, device/google/marlin/device-marlin.mk)
    $(call inherit-product-if-exists, vendor/google_devices/marlin/device-vendor-marlin.mk)
    
    PRODUCT_PACKAGES += \
        Launcher3QuickStep \
        WallpaperPicker
    

    Makefile に追加できるプロダクト固有の変数については、プロダクト定義変数を設定するをご覧ください。

  4. プロダクトの Makefile をポイントする AndroidProducts.mk ファイルを作成します。今回の例の場合、必要となるのはプロダクト定義 Makefile だけです。下記の例をご覧ください(出典: device/google/marlin/AndroidProducts.mk)。Pixel の marlin と Pixel XL の sailfish が両方含まれており、ほとんどの構成が共有されています。
    PRODUCT_MAKEFILES := \
    	$(LOCAL_DIR)/aosp_marlin.mk \
    	$(LOCAL_DIR)/aosp_sailfish.mk
    
    COMMON_LUNCH_CHOICES := \
    	aosp_marlin-userdebug \
    	aosp_sailfish-userdebug
    
  5. ボード固有の構成を格納する BoardConfig.mk Makefile を作成します。例として、device/google/marlin/BoardConfig.mk をご覧ください。
  6. Android 9 以前の場合に限りvendorsetup.sh ファイルを作成して、プロダクト(lunch combo)をビルドに追加します。ビルド バリアントはダッシュ区切りで示します。次に例を示します。
    add_lunch_combo <product-name>-userdebug
    
  7. これで、同一のデバイスを基にして複数のプロダクト バリアントを作成できるようになりました。

プロダクト定義変数を設定する

プロダクト固有の変数は、プロダクトの Makefile 内で定義します。プロダクト定義ファイル内で管理される変数の一部を次の表に示します。

変数 説明
PRODUCT_AAPT_CONFIG パッケージの作成時に使用する aapt 構成。
PRODUCT_BRAND 携帯通信会社など、ソフトウェアをカスタマイズする際の対象となるブランド。
PRODUCT_CHARACTERISTICS aapt 特性。バリアント固有のリソースをパッケージに追加することを可能にします。 tabletnosdcard
PRODUCT_COPY_FILES source_path:destination_path 形式のリスト。プロダクトをビルドする際に、これらのファイルがソースパスからデスティネーション パスにコピーされます。コピー手順に関するルールは、config/makefile 内で定義します。
PRODUCT_DEVICE 産業デザインの名称。ボード名でもあり、ビルドシステムが BoardConfig.mk を検索する際に使用します。 tuna
PRODUCT_LOCALES 2 文字の言語コードと 2 文字の国コードのペアを、スペース区切りで並べたリスト。UI 言語や、時刻、日付、通貨の形式など、ユーザー向けのさまざまな設定について記述します。PRODUCT_LOCALES 内のリストの最初にある言語 / 地域が、プロダクトのデフォルト言語 / 地域として使用されます。 en_GBde_DEes_ESfr_CA
PRODUCT_MANUFACTURER メーカー名。 acme
PRODUCT_MODEL エンドユーザーが認識できる完成品の名称。
PRODUCT_NAME エンドユーザーが認識できるプロダクト全体の名称。[設定] > [デバイス情報] の画面に表示されます。
PRODUCT_OTA_PUBLIC_KEYS プロダクトの無線(OTA)アップデート用の公開鍵のリスト。
PRODUCT_PACKAGES インストールする APK とモジュールのリスト。 Calendar contacts
PRODUCT_PACKAGE_OVERLAYS デフォルト リソースを使用するのか、プロダクト固有のオーバーレイを追加するのかを指定します。 vendor/acme/overlay
PRODUCT_SYSTEM_PROPERTIES システム パーティションに対して "key=value" 形式で示したシステム プロパティ割り当てのリスト。他のパーティションのシステム プロパティは、ベンダー パーティションに対する PRODUCT_VENDOR_PROPERTIES のように、PRODUCT_<PARTITION>_PROPERTIES を使用して指定できます。サポートされているパーティション名: SYSTEMVENDORODMSYSTEM_EXTPRODUCT

デフォルトのシステム言語と言語 / 地域フィルタを設定する

この情報を使用して、デフォルトの言語とシステムの言語 / 地域フィルタを構成してから、新しいデバイスタイプの言語 / 地域フィルタを有効にします。

プロパティ

専用のシステム プロパティを使用して、デフォルトの言語とシステムの言語 / 地域フィルタの両方を設定します。

  • ro.product.locale: デフォルトの言語 / 地域を設定します。初期設定では PRODUCT_LOCALES 変数の最初の言語 / 地域ですが、この値をオーバーライドできます(詳細については、プロダクト定義変数を設定するをご覧ください)。
  • ro.localization.locale_filter: 言語 / 地域名に適用する正規表現を使用して、言語 / 地域フィルタを設定します。次に例を示します。
    • 包含フィルタ: ^(de-AT|de-DE|en|uk).* - ドイツ語(オーストリアとドイツのバリアント)、英語のすべてのバリアント、ウクライナ語のみを許可します。
    • 排除フィルタ: ^(?!de-IT|es).* - ドイツ語(イタリアのバリアント)とスペイン語のすべてのバリアントを除外します。

言語 / 地域フィルタを有効にする

フィルタを有効にするには、ro.localization.locale_filter システム プロパティの文字列値を設定します。

工場出荷時の調整でフィルタ プロパティの値とデフォルトの言語を oem/oem.prop で設定すると、フィルタをシステム イメージに組み込むことなく制限を構成できます。 上記プロパティを次のように PRODUCT_OEM_PROPERTIES 変数に追加することで、OEM パーティションから取得できるようになります。

# Delegation for OEM customization
PRODUCT_OEM_PROPERTIES += \
    ro.product.locale \
    ro.localization.locale_filter

本番環境では、実際の値はターゲット要件を反映するために oem/oem.prop に書き込まれます。この方法では、出荷時の設定にリセットしてもデフォルト値が保持されるため、初期設定は最初のセットアップを行う際とまったく同じようにユーザーに見えます。

ADB_VENDOR_KEYS を設定して USB 経由で接続する

デバイス メーカーは、ADB_VENDOR_KEYS 環境変数を使用することで、手動による承認なしで adb 経由でデバッグ可能ビルド(-user ではなく、-userdebug と -eng)にアクセスできます。通常、adb はクライアント コンピュータごとに一意の RSA 認証鍵を生成し、接続されたデバイスに送信します。これが adb の承認ダイアログに表示される RSA 鍵です。または、システム イメージに既知の鍵を組み込み、adb クライアントと共有することもできます。この方法は、OS 開発のほか、adb の承認ダイアログを手動で操作する必要がないため特にテストに役立ちます。

ベンダー鍵を作成するには、次の操作を行います(通常はリリース マネージャーが行います)。

  1. adb keygen を使用して鍵ペアを生成します。Google デバイスの場合、新しい OS バージョンごとに Google が新しい鍵ペアを生成します。
  2. 鍵ペアをソースツリーにチェックインします。Google では、vendor/google/security/adb/ などに保存しています。
  3. 鍵ディレクトリを指定するようビルド変数 PRODUCT_ADB_KEYS を設定します。Google では、このために「PRODUCT_ADB_KEYS := $(LOCAL_PATH)/$(PLATFORM_VERSION).adb_key.pub」と記述した Android.mk ファイルを鍵ディレクトリに追加し、OS バージョンごとに新しい鍵ペアを生成する場合にすぐにわかるようにしています。

以下に、Google が各リリースのチェックイン済み鍵ペアを保存するディレクトリで使用する Makefile を示します。

PRODUCT_ADB_KEYS := $(LOCAL_PATH)/$(PLATFORM_VERSION).adb_key.pub

ifeq ($(wildcard $(PRODUCT_ADB_KEYS)),)
  $(warning ========================)
  $(warning The adb key for this release)
  $(warning )
  $(warning   $(PRODUCT_ADB_KEYS))
  $(warning )
  $(warning does not exist. Most likely PLATFORM_VERSION in build/core/version_defaults.mk)
  $(warning has changed and a new adb key needs to be generated.)
  $(warning )
  $(warning Please run the following commands to create a new key:)
  $(warning )
  $(warning   make -j8 adb)
  $(warning   LOGNAME=android-eng HOSTNAME=google.com adb keygen $(patsubst %.pub,%,$(PRODUCT_ADB_KEYS)))
  $(warning )
  $(warning and upload/review/submit the changes)
  $(warning ========================)
  $(error done)
endif

これらのベンダー鍵は、鍵ペアの保存先ディレクトリを指定するように ADB_VENDOR_KEYS 環境変数を設定するだけで使用できます。これで、adb は、手動による承認を必要とする生成済みのホスト鍵にフォールバックする前に、まず正規の鍵を試すことができます。adb が未承認のデバイスに接続できない場合、ADB_VENDOR_KEYS がまだ設定されていない場合は設定するようエラー メッセージで示されます。