Implementacja biblioteki Java SDK

Platforma Android zawiera dużą liczbę współdzielonych bibliotek Java, które opcjonalnie można uwzględnić w ścieżce klas aplikacji za pomocą tagu <uses-library> w manifeście aplikacji. Aplikacje łączą się z tymi bibliotekami, więc traktuj je jak resztę interfejsu API systemu Android pod względem zgodności, przeglądu interfejsu API i obsługi narzędzi. Należy jednak pamiętać, że większość bibliotek nie ma tych funkcji.

Moduł typu java_sdk_library pomaga zarządzać tego typu bibliotekami. Producenci urządzeń mogą używać tego mechanizmu w swoich własnych udostępnionych bibliotekach Java, aby zachować wsteczną kompatybilność swoich interfejsów API. Jeśli producenci urządzeń używają własnych współdzielonych bibliotek Java za pomocą znacznika <uses-library> zamiast ścieżki klasy rozruchowej, java_sdk_library może sprawdzić, czy te biblioteki Java są stabilne pod względem interfejsu API.

java_sdk_library implementuje opcjonalne interfejsy API zestawu SDK do użytku przez aplikacje. Biblioteki zaimplementowane poprzez java_sdk_library w pliku kompilacji ( Android.bp ) wykonują następujące operacje:

  • Generowane są biblioteki pośredniczące, które obejmują stubs , stubs.system i stubs.test . Te biblioteki pośredniczące są tworzone poprzez rozpoznawanie adnotacji @hide , @SystemApi i @TestApi .
  • java_sdk_library zarządza plikami specyfikacji API (takimi jak current.txt ) w podkatalogu API. Pliki te są sprawdzane pod kątem najnowszego kodu, aby mieć pewność, że są to najnowsze wersje. Jeśli tak nie jest, pojawi się komunikat o błędzie wyjaśniający, jak je zaktualizować. Ręcznie przejrzyj wszystkie zmiany aktualizacji, aby upewnić się, że odpowiadają Twoim oczekiwaniom.

    Aby zaktualizować wszystkie interfejsy API, użyj m update-api . Aby sprawdzić, czy interfejs API jest aktualny, użyj m checkapi .
  • Pliki specyfikacji API są sprawdzane w stosunku do ostatnio opublikowanych wersji Androida, aby upewnić się, że API jest wstecznie kompatybilne z wcześniejszymi wersjami. Moduły java_sdk_library dostarczane jako część AOSP umieszczają swoje wcześniej wydane wersje w prebuilts/sdk/<latest number> .
  • Jeśli chodzi o sprawdzanie plików specyfikacji API, możesz wykonać jedną z trzech następujących czynności:
    • Pozwól, aby kontrole były kontynuowane. (Nie rób nic.)
    • Wyłącz kontrole, dodając następujące elementy do java_sdk_library :
      unsafe_ignore_missing_latest_api: true,
    • Udostępnij puste interfejsy API dla nowych modułów java_sdk_library , tworząc puste pliki tekstowe o nazwie module_name.txt w katalogu version/scope/api .
  • Jeśli zainstalowana jest biblioteka implementacyjna dla środowiska wykonawczego, zostanie wygenerowany i zainstalowany plik XML.

Jak działa Java_sdk_library

java_sdk_library o nazwie X tworzy następujące elementy:

  1. Dwie kopie biblioteki implementacyjnej: jedna biblioteka o nazwie X i druga o nazwie X.impl . Biblioteka X jest zainstalowana na urządzeniu. Biblioteka X.impl jest dostępna tylko wtedy, gdy inne moduły potrzebują jawnego dostępu do biblioteki implementacyjnej, np. do wykorzystania w testach. Należy pamiętać, że rzadko potrzebny jest wyraźny dostęp.
  2. Zakresy można włączać i wyłączać, aby dostosować dostęp. (Podobnie jak modyfikatory dostępu do słów kluczowych w Javie, zakres publiczny zapewnia szeroki zakres dostępu; zakres testowy zawiera interfejsy API używane tylko w testowaniu). Dla każdego włączonego zakresu biblioteka tworzy następujące elementy:
    • Moduł źródłowy stubs (typu modułu droidstubs ) - zużywa źródło implementacji i generuje zestaw źródeł pośredniczących wraz z plikiem specyfikacji API.
    • Biblioteka kodu pośredniczącego (typu modułu java_library ) - jest to skompilowana wersja kodu pośredniczącego. Biblioteki użyte do kompilacji różnią się od tych dostarczonych do java_sdk_library , co gwarantuje, że szczegóły implementacji nie wyciekną do złączy API.
    • Jeśli potrzebujesz dodatkowych bibliotek do skompilowania kodów pośredniczących, użyj właściwości stub_only_libs i stub_only_static_libs , aby je dostarczyć.

Jeśli java_sdk_library nosi nazwę „ X ” i jest kompilowana jako „ X ”, zawsze nazywaj ją w ten sposób i nie modyfikuj jej. Kompilacja wybierze odpowiednią bibliotekę. Aby upewnić się, że masz najbardziej odpowiednią bibliotekę, sprawdź swoje kody pośredniczące, aby zobaczyć, czy kompilacja wprowadziła błędy. Wprowadź niezbędne poprawki, korzystając z tych wskazówek:

  • Sprawdź, czy masz odpowiednią bibliotekę, zaglądając do wiersza poleceń i sprawdzając, które kody pośredniczące są tam wymienione, aby określić swój zakres:
    • Zakres jest zbyt szeroki: zależna biblioteka wymaga określonego zakresu interfejsów API. Jednak w bibliotece znajdują się interfejsy API, które wykraczają poza ten zakres, na przykład systemowe interfejsy API zawarte w publicznych interfejsach API.
    • Zakres jest zbyt wąski: zależna biblioteka nie ma dostępu do wszystkich wymaganych bibliotek. Na przykład zależna biblioteka musi używać systemowego interfejsu API, ale zamiast tego pobiera publiczny interfejs API. Zwykle skutkuje to błędem kompilacji, ponieważ brakuje potrzebnych interfejsów API.
  • Aby naprawić bibliotekę, wykonaj tylko jedną z następujących czynności:
    • Zmień sdk_version , aby wybrać potrzebną wersję. LUB
    • Jawnie określ odpowiednią bibliotekę, taką jak <X>.stubs lub <X>.stubs.system .

Użycie java_sdk_library X

Biblioteka implementacyjna X jest używana, gdy odwołuje się do niej apex.java_libs . Jednakże, ze względu na ograniczenia Soong, gdy biblioteka X odwołuje się do innego modułu java_sdk_library w tej samej bibliotece APEX, należy jawnie użyć X.impl , a nie biblioteki X

Kiedy odwołuje się do java_sdk_library z innego miejsca, używana jest biblioteka pośrednicząca. Biblioteka pośrednicząca jest wybierana zgodnie z ustawieniem właściwości sdk_version modułu zależnego. Na przykład moduł określający sdk_version: "current" używa publicznych kodów pośredniczących, podczas gdy moduł określający sdk_version: "system_current" używa kodów systemowych. Jeśli nie można znaleźć dokładnego dopasowania, używana jest najbliższa biblioteka pośrednicząca. java_sdk_library , która udostępnia jedynie publiczny interfejs API, udostępni wszystkim publiczne kody pośredniczące.

Twórz przepływ za pomocą biblioteki Java SDK
Rysunek 1. Zbuduj przepływ za pomocą biblioteki Java SDK

Przykłady i źródła

Właściwości srcs i api_packages muszą być obecne w java_sdk_library .

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

AOSP zaleca (ale nie wymaga), aby nowe instancje java_sdk_library jawnie włączały zakresy API, których chcą używać. Możesz także (opcjonalnie) przeprowadzić migrację istniejących instancji java_sdk_library , aby jawnie włączyć zakresy API, których będą używać:

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

Aby skonfigurować bibliotekę impl używaną w środowisku wykonawczym, użyj wszystkich normalnych właściwości java_library , takich jak hostdex , compile_dex i errorprone .

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,
    }

Aby skonfigurować biblioteki pośredniczące, użyj następujących właściwości:

  • merge_annotations_dirs i merge_inclusion_annotations_dirs .
  • api_srcs : lista opcjonalnych plików źródłowych, które są częścią interfejsu API, ale nie są częścią biblioteki wykonawczej.
  • stubs_only_libs : Lista bibliotek Java znajdujących się w ścieżce klas podczas tworzenia kodów pośredniczących.
  • hidden_api_packages : Lista nazw pakietów, które muszą być ukryte przed interfejsem API.
  • droiddoc_options : Dodatkowy argument za metalava .
  • droiddoc_option_files : Wyświetla listę plików, do których można się odwoływać z poziomu droiddoc_options za pomocą $(location <label>) , gdzie <file> jest wpisem na liście.
  • annotations_enabled .

Biblioteka java_sdk_library jest biblioteką java_library , ale nie jest modułem droidstubs i dlatego nie obsługuje wszystkich właściwości droidstubs . Poniższy przykład został zaczerpnięty z pliku kompilacji biblioteki 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,
    }

Zachowanie kompatybilności wstecznej

System kompilacji sprawdza, czy interfejsy API zachowały kompatybilność wsteczną, porównując najnowsze pliki API z wygenerowanymi plikami API w czasie kompilacji. java_sdk_library sprawdza kompatybilność, korzystając z informacji dostarczonych przez prebuilt_apis . Wszystkie biblioteki zbudowane za pomocą java_sdk_library muszą mieć pliki API w najnowszej wersji api_dirs w prebuilt_apis . Po wydaniu wersji interfejs API wyświetla listę plików i biblioteki pośredniczące, które można uzyskać za pomocą kompilacji dist z PRODUCT=sdk_phone_armv7-sdk .

Właściwość api_dirs to lista katalogów wersji API w prebuilt_apis . Katalogi wersji API muszą znajdować się na poziomie katalogu Android.bp .

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

Skonfiguruj katalogi o strukturze version / scope /api/ w katalogu prekompilowanym. version odpowiada poziomowi API, a scope określa, czy katalog jest publiczny, systemowy czy testowy.

  • version / scope zawiera biblioteki Java.
  • version / scope /api zawiera pliki API .txt . Utwórz tutaj puste pliki tekstowe o nazwach module_name .txt i module_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