syntax = "proto3"; package android.bundle; option java_package = "com.android.bundle"; message BundleConfig { Bundletool bundletool = 1; Optimizations optimizations = 2; Compression compression = 3; // Resources to be always kept in the master split. MasterResources master_resources = 4; ApexConfig apex_config = 5; // APKs to be signed with the same key as generated APKs. repeated UnsignedEmbeddedApkConfig unsigned_embedded_apk_config = 6; AssetModulesConfig asset_modules_config = 7; enum BundleType { REGULAR = 0; APEX = 1; ASSET_ONLY = 2; } BundleType type = 8; // Configuration for locales. Locales locales = 9; } message Bundletool { reserved 1; // Version of BundleTool used to build the Bundle. string version = 2; } message Compression { // Glob matching the list of files to leave uncompressed in the APKs. // The matching is done against the path of files in the APK, thus excluding // the name of the modules, and using forward slash ("/") as a name separator. // Examples: "res/raw/**", "assets/**/*.uncompressed", etc. repeated string uncompressed_glob = 1; enum AssetModuleCompression { UNSPECIFIED = 0; // Assets are left uncompressed in the generated asset module. UNCOMPRESSED = 1; // Assets are compressed in the generated asset module. // This option can be overridden at a finer granularity by specifying // files or folders to keep uncompressed in `uncompressed_glob`. // This option should only be used if the app is able to handle compressed // asset module content at runtime (some runtime APIs may misbehave). COMPRESSED = 2; } // Default compression strategy for install-time asset modules. // If the compression strategy indicates to compress a file and the same file // matches one of the `uncompressed_glob` values, the `uncompressed_glob` // takes precedence (the file is left uncompressed in the generated APK). // // If unspecified, asset module content is left uncompressed in the // generated asset modules. // // Note: this flag only configures the compression strategy for install-time // asset modules; the content of on-demand and fast-follow asset modules is // always kept uncompressed. AssetModuleCompression install_time_asset_module_default_compression = 2; enum ApkCompressionAlgorithm { // Default in the current version of bundletool is zlib deflate algorithm // with compression level 9 for the application's resources and compression // level 6 for other entries. // // This is a good trade-off between size of final APK and size of patches // which are used to update the application from previous to next version. DEFAULT_APK_COMPRESSION_ALGORITHM = 0; // 7zip implementation of deflate algorithm which gives smaller APK size // but size of patches required to update the application are larger. P7ZIP = 1; } // Compression algorithm which is used to compress entries in final APKs. ApkCompressionAlgorithm apk_compression_algorithm = 3; } // Resources to keep in the master split. message MasterResources { // Resource IDs to be kept in master split. repeated int32 resource_ids = 1; // Resource names to be kept in master split. repeated string resource_names = 2; } message Optimizations { enum InjectMinSdkSetting { // Unspecified inject min SDK setting. UNSPECIFIED = 0; // Disables injecting min SDK into the manifests of split APKs DISABLED = 1; // Enables injecting min SDK into the manifests of split APKs ENABLED = 2; } SplitsConfig splits_config = 1; // This is for uncompressing native libraries on M+ devices (L+ devices on // instant apps). UncompressNativeLibraries uncompress_native_libraries = 2; // This is for uncompressing dex files. UncompressDexFiles uncompress_dex_files = 3; // Configuration for the generation of standalone APKs. // If no StandaloneConfig is set, the configuration is inherited from // splits_config. StandaloneConfig standalone_config = 4; // Optimizations that are applied to resources. ResourceOptimizations resource_optimizations = 5; // Configuration for archiving the app. StoreArchive store_archive = 6; // Whether to inject minSdkVersion into the manifests of split APKs. // Deprecated: use inject_min_sdk_setting instead bool inject_min_sdk = 7 [deprecated = true]; // Whether to inject minSdkVersion into the manifests of split APKs. InjectMinSdkSetting inject_min_sdk_setting = 8; } message ResourceOptimizations { enum SparseEncoding { // Previously 'ENFORCED'. This option is deprecated because of issues found // in Android O up to Android Sv2 and causes segfaults in // Resources#getIdentifier. reserved 1; reserved "ENFORCED"; // Unspecified sparse encoding. UNSPECIFIED = 0; // This leads to a reduction in APK size, memory usage, and startup latency, // and a small increase in individual resource lookup time after startup. // Only applies sparse encoding if minSdk of the APK is >= 32 VARIANT_FOR_SDK_32 = 2; // Disables sparse encoding for all Android SDKs. DISABLED = 3; } // Pair of resource type and name, like 'layout/foo', 'string/bar'. message ResourceTypeAndName { string type = 1; string name = 2; } // Optimizations related to collapsed resource names. message CollapsedResourceNames { // Whether to collapse resource names. // Resources with collapsed resource names are only accessible by their // ids. These names are not stored inside 'resources.arsc'. bool collapse_resource_names = 1; // Instructs to not collapse resource names for specific resources which // makes certain resources to be accessible by their names. // // Applicable only if 'collapse_resource_names' is 'true'. repeated ResourceTypeAndName no_collapse_resources = 2; // Instructs to not collapse all resources of certain types. // // Applicable only if 'collapse_resource_names' is 'true'. repeated string no_collapse_resource_types = 4; // Whether to store only unique resource entries in 'resources.arsc'. // // For example if there are 3 'bool' resources defined with 'true' value // with this flag only one 'true' entry is stored and all 3 resources // are referencing this entry. By default all 3 entries are stored. // // This only works with resources where names are collapsed (either using // 'collapse_resource_names' flag or manually) because resource name is a // part of resource entry and if names are preserved - all entries are // unique. bool deduplicate_resource_entries = 3; } // This leads to a reduction in APK size, memory usage, and startup latency, // and a small increase in individual resource lookup time after startup. // Only applies sparse encoding if minSdk of the APK is >= 32 SparseEncoding sparse_encoding = 1; // Optimizations related to collapsed resource names. CollapsedResourceNames collapsed_resource_names = 2; } message UncompressNativeLibraries { bool enabled = 1; enum PageAlignment { PAGE_ALIGNMENT_UNSPECIFIED = 0; PAGE_ALIGNMENT_4K = 1; PAGE_ALIGNMENT_16K = 2; PAGE_ALIGNMENT_64K = 3; } // This is an experimental setting. It's behavior might be changed or // completely removed. // // Alignment used for uncompressed native libraries inside APKs generated // by bundletool. // // PAGE_ALIGNMENT_4K by default. PageAlignment alignment = 2; } message UncompressDexFiles { // A new variant with uncompressed dex will be generated. The sdk targeting // of the variant is determined by 'uncompressed_dex_target_sdk'. bool enabled = 1; // If 'enabled' field is set, this will determine the sdk targeting of the // generated variant. UncompressedDexTargetSdk uncompressed_dex_target_sdk = 2; enum UncompressedDexTargetSdk { // Q+ variant will be generated. UNSPECIFIED = 0; // S+ variant will be generated. SDK_31 = 1; // T+ variant will be generated. SDK_33 = 3; reserved 2; } } message StoreArchive { // Archive is an app state that allows an official app store to reclaim device // storage and disable app functionality temporarily until the user interacts // with the app again. Upon interaction the latest available version of the // app will be restored while leaving user data unaffected. // Enabled by default. bool enabled = 1; } message Locales { // Instructs bundletool to generate locale config and inject it into // AndroidManifest.xml. A locale is marked as supported by the application if // there is at least one resource value in this locale. Be very careful with // this setting because if some of your libraries expose resources in some // locales which are not actually supported by your application it will mark // this locale as supported. Disabled by default. bool inject_locale_config = 1; } // Optimization configuration used to generate Split APKs. message SplitsConfig { repeated SplitDimension split_dimension = 1; } // Optimization configuration used to generate Standalone APKs. message StandaloneConfig { // Device targeting dimensions to shard. repeated SplitDimension split_dimension = 1; // Whether 64 bit libraries should be stripped from Standalone APKs. bool strip_64_bit_libraries = 2; // Dex merging strategy that should be applied to produce Standalone APKs. DexMergingStrategy dex_merging_strategy = 3; enum DexMergingStrategy { // Strategy that does dex merging for applications that have minimum SDK // below 21 to ensure dex files from all modules are merged into one or // mainDexList is applied when merging into one dex is not possible. For // applications with minSdk >= 21 dex files from all modules are copied into // standalone APK as is because Android supports multiple dex files natively // starting from Android 5.0. MERGE_IF_NEEDED = 0; // Requires to copy dex files from all modules into standalone APK as is. // If an application supports SDKs below 21 this strategy puts // responsibility of providing dex files compatible with legacy multidex on // application developers. NEVER_MERGE = 1; } // Defines how to deal with feature modules in standalone variants (minSdk < // 21). FeatureModulesMode feature_modules_mode = 4; enum FeatureModulesMode { // Default mode which fuses feature modules with respect to its // fusing attribute into base.apk. FUSED_FEATURE_MODULES = 0; // Advanced mode, which allows to generate a single separate apk per each // feature module in variants with minSdk < 21. SEPARATE_FEATURE_MODULES = 1; } } message SplitDimension { enum Value { UNSPECIFIED_VALUE = 0; ABI = 1; SCREEN_DENSITY = 2; LANGUAGE = 3; TEXTURE_COMPRESSION_FORMAT = 4; DEVICE_TIER = 6 [deprecated = true]; COUNTRY_SET = 7; AI_MODEL_VERSION = 8; DEVICE_GROUP = 9; } Value value = 1; // If set to 'true', indicates that APKs should *not* be split by this // dimension. bool negate = 2; // Optional transformation to be applied to asset directories where // the targeting is encoded in the directory name (e.g: assets/foo#tcf_etc1) SuffixStripping suffix_stripping = 3; } message SuffixStripping { // If set to 'true', indicates that the targeting suffix should be removed // from assets paths for this dimension when splits (e.g: "asset packs") or // standalone/universal APKs are generated. // This only applies to assets. // For example a folder with path "assets/level1_textures#tcf_etc1" // would be outputted to "assets/level1_textures". File contents are // unchanged. bool enabled = 1; // The default suffix to be used for the cases where separate slices can't // be generated for this dimension - typically for standalone or universal // APKs. // This default suffix defines the directories to retain. The others are // discarded: standalone/universal APKs will contain only directories // targeted at this value for the dimension. // // If not set or empty, the fallback directory in each directory group will be // used (for example, if both "assets/level1_textures#tcf_etc1" and // "assets/level1_textures" are present and the default suffix is empty, // then only "assets/level1_textures" will be used). string default_suffix = 2; } // Configuration for processing APEX bundles. // https://source.android.com/devices/tech/ota/apex message ApexConfig { // Configuration for processing of APKs embedded in an APEX image. repeated ApexEmbeddedApkConfig apex_embedded_apk_config = 1; // Explicit list of supported ABIs. // Default: See ApexBundleValidator.REQUIRED_ONE_OF_ABI_SETS repeated SupportedAbiSet supported_abi_set = 2; } // Represents a set of ABIs which must be supported by a single APEX image. message SupportedAbiSet { repeated string abi = 1; } message ApexEmbeddedApkConfig { // Android package name of the APK. string package_name = 1; // Path to the APK within the APEX system image. string path = 2; } message UnsignedEmbeddedApkConfig { // Path to the APK inside the module (e.g. if the path inside the bundle // is split/assets/example.apk, this will be assets/example.apk). string path = 1; } message AssetModulesConfig { // App versionCodes that will be updated with these asset modules. // Only relevant for asset-only bundles. repeated int64 app_version = 1; // Version tag for the asset upload. // Only relevant for asset-only bundles. string asset_version_tag = 2; }