Implement extract_apks am: 97d511a16d
Original change: https://googleplex-android-review.googlesource.com/c/platform/build/soong/+/11720096 Change-Id: I347822a7e70aea5121135779a9f5cbb8a6de592f
This commit is contained in:
commit
f5eec5c80c
10 changed files with 5056 additions and 0 deletions
21
cmd/extract_apks/Android.bp
Normal file
21
cmd/extract_apks/Android.bp
Normal file
|
@ -0,0 +1,21 @@
|
|||
blueprint_go_binary {
|
||||
name: "extract_apks",
|
||||
srcs: ["main.go"],
|
||||
deps: [
|
||||
"android-archive-zip",
|
||||
"golang-protobuf-proto",
|
||||
"soong-cmd-extract_apks-proto",
|
||||
],
|
||||
testSrcs: ["main_test.go"]
|
||||
}
|
||||
|
||||
bootstrap_go_package {
|
||||
name: "soong-cmd-extract_apks-proto",
|
||||
pkgPath: "android/soong/cmd/extract_apks/bundle_proto",
|
||||
deps: ["golang-protobuf-proto"],
|
||||
srcs: [
|
||||
"bundle_proto/commands.pb.go",
|
||||
"bundle_proto/config.pb.go",
|
||||
"bundle_proto/targeting.pb.go",
|
||||
],
|
||||
}
|
1033
cmd/extract_apks/bundle_proto/commands.pb.go
Normal file
1033
cmd/extract_apks/bundle_proto/commands.pb.go
Normal file
File diff suppressed because it is too large
Load diff
197
cmd/extract_apks/bundle_proto/commands.proto
Normal file
197
cmd/extract_apks/bundle_proto/commands.proto
Normal file
|
@ -0,0 +1,197 @@
|
|||
// Messages describing APK Set's table of contents (toc.pb entry).
|
||||
// Please be advised that the ultimate source is at
|
||||
// https://github.com/google/bundletool/tree/master/src/main/proto
|
||||
// so you have been warned.
|
||||
syntax = "proto3";
|
||||
|
||||
package android.bundle;
|
||||
|
||||
import "config.proto";
|
||||
import "targeting.proto";
|
||||
|
||||
option go_package = "android_bundle_proto";
|
||||
option java_package = "com.android.bundle";
|
||||
|
||||
// Describes the output of the "build-apks" command.
|
||||
message BuildApksResult {
|
||||
// The package name of this app.
|
||||
string package_name = 4;
|
||||
|
||||
// List of the created variants.
|
||||
repeated Variant variant = 1;
|
||||
|
||||
// Metadata about BundleTool used to build the APKs.
|
||||
Bundletool bundletool = 2;
|
||||
|
||||
// List of the created asset slices.
|
||||
repeated AssetSliceSet asset_slice_set = 3;
|
||||
|
||||
// Information about local testing mode.
|
||||
LocalTestingInfo local_testing_info = 5;
|
||||
}
|
||||
|
||||
// Variant is a group of APKs that covers a part of the device configuration
|
||||
// space. APKs from multiple variants are never combined on one device.
|
||||
message Variant {
|
||||
// Variant-level targeting.
|
||||
// This targeting is fairly high-level and each APK has its own targeting as
|
||||
// well.
|
||||
VariantTargeting targeting = 1;
|
||||
|
||||
// Set of APKs, one set per module.
|
||||
repeated ApkSet apk_set = 2;
|
||||
|
||||
// Number of the variant, starting at 0 (unless overridden).
|
||||
// A device will receive APKs from the first variant that matches the device
|
||||
// configuration, with higher variant numbers having priority over lower
|
||||
// variant numbers.
|
||||
uint32 variant_number = 3;
|
||||
}
|
||||
|
||||
// Represents a module.
|
||||
// For pre-L devices multiple modules (possibly all) may be merged into one.
|
||||
message ApkSet {
|
||||
ModuleMetadata module_metadata = 1;
|
||||
|
||||
// APKs.
|
||||
repeated ApkDescription apk_description = 2;
|
||||
}
|
||||
|
||||
message ModuleMetadata {
|
||||
// Module name.
|
||||
string name = 1;
|
||||
|
||||
// Indicates the delivery type (e.g. on-demand) of the module.
|
||||
DeliveryType delivery_type = 6;
|
||||
|
||||
// Indicates whether this module is marked "instant".
|
||||
bool is_instant = 3;
|
||||
|
||||
// Names of the modules that this module directly depends on.
|
||||
// Each module implicitly depends on the base module.
|
||||
repeated string dependencies = 4;
|
||||
|
||||
// The targeting that makes a conditional module installed.
|
||||
// Relevant only for Split APKs.
|
||||
ModuleTargeting targeting = 5;
|
||||
|
||||
// Deprecated. Please use delivery_type.
|
||||
bool on_demand_deprecated = 2 [deprecated = true];
|
||||
}
|
||||
|
||||
// Set of asset slices belonging to a single asset module.
|
||||
message AssetSliceSet {
|
||||
// Module level metadata.
|
||||
AssetModuleMetadata asset_module_metadata = 1;
|
||||
|
||||
// Asset slices.
|
||||
repeated ApkDescription apk_description = 2;
|
||||
}
|
||||
|
||||
message AssetModuleMetadata {
|
||||
// Module name.
|
||||
string name = 1;
|
||||
|
||||
// Indicates the delivery type for persistent install.
|
||||
DeliveryType delivery_type = 4;
|
||||
|
||||
// Metadata for instant installs.
|
||||
InstantMetadata instant_metadata = 3;
|
||||
|
||||
// Deprecated. Use delivery_type.
|
||||
bool on_demand_deprecated = 2 [deprecated = true];
|
||||
}
|
||||
|
||||
message InstantMetadata {
|
||||
// Indicates whether this module is marked "instant".
|
||||
bool is_instant = 1;
|
||||
|
||||
// Indicates the delivery type for instant install.
|
||||
DeliveryType delivery_type = 3;
|
||||
|
||||
// Deprecated. Use delivery_type.
|
||||
bool on_demand_deprecated = 2 [deprecated = true];
|
||||
}
|
||||
|
||||
enum DeliveryType {
|
||||
UNKNOWN_DELIVERY_TYPE = 0;
|
||||
INSTALL_TIME = 1;
|
||||
ON_DEMAND = 2;
|
||||
FAST_FOLLOW = 3;
|
||||
}
|
||||
|
||||
message ApkDescription {
|
||||
ApkTargeting targeting = 1;
|
||||
|
||||
// Path to the APK file.
|
||||
// BEGIN-INTERNAL
|
||||
// The path may be a blobkey if the proto is not constructed by bundletool.
|
||||
// END-INTERNAL
|
||||
string path = 2;
|
||||
|
||||
oneof apk_metadata_oneof_value {
|
||||
// Set only for Split APKs.
|
||||
SplitApkMetadata split_apk_metadata = 3;
|
||||
// Set only for standalone APKs.
|
||||
StandaloneApkMetadata standalone_apk_metadata = 4;
|
||||
// Set only for Instant split APKs.
|
||||
SplitApkMetadata instant_apk_metadata = 5;
|
||||
// Set only for system APKs.
|
||||
SystemApkMetadata system_apk_metadata = 6;
|
||||
// Set only for asset slices.
|
||||
SplitApkMetadata asset_slice_metadata = 7;
|
||||
// Set only for APEX APKs.
|
||||
ApexApkMetadata apex_apk_metadata = 8;
|
||||
}
|
||||
}
|
||||
|
||||
// Holds data specific to Split APKs.
|
||||
message SplitApkMetadata {
|
||||
string split_id = 1;
|
||||
|
||||
// Indicates whether this APK is the master split of the module.
|
||||
bool is_master_split = 2;
|
||||
}
|
||||
|
||||
// Holds data specific to Standalone APKs.
|
||||
message StandaloneApkMetadata {
|
||||
// Names of the modules fused in this standalone APK.
|
||||
repeated string fused_module_name = 1;
|
||||
|
||||
reserved 2;
|
||||
}
|
||||
|
||||
// Holds data specific to system APKs.
|
||||
message SystemApkMetadata {
|
||||
// Names of the modules fused in this system APK.
|
||||
repeated string fused_module_name = 1;
|
||||
enum SystemApkType {
|
||||
UNSPECIFIED_VALUE = 0;
|
||||
// Uncompressed APK for system image.
|
||||
SYSTEM = 1;
|
||||
// Stub APK for compressed APK in the system image
|
||||
// (contains only android manifest).
|
||||
SYSTEM_STUB = 2;
|
||||
// Compressed APK for system image.
|
||||
SYSTEM_COMPRESSED = 3;
|
||||
}
|
||||
// Indicates whether the APK is uncompressed system APK, stub APK or
|
||||
// compressed system APK.
|
||||
SystemApkType system_apk_type = 2;
|
||||
}
|
||||
|
||||
// Holds data specific to APEX APKs.
|
||||
message ApexApkMetadata {
|
||||
// Configuration for processing of APKs embedded in an APEX image.
|
||||
repeated ApexEmbeddedApkConfig apex_embedded_apk_config = 1;
|
||||
}
|
||||
|
||||
message LocalTestingInfo {
|
||||
// Indicates if the bundle is built in local testing mode.
|
||||
bool enabled = 1;
|
||||
// The local testing path, as specified in the base manifest.
|
||||
// This refers to the relative path on the external directory of the app where
|
||||
// APKs will be pushed for local testing.
|
||||
// Set only if local testing is enabled.
|
||||
string local_testing_path = 2;
|
||||
}
|
952
cmd/extract_apks/bundle_proto/config.pb.go
Normal file
952
cmd/extract_apks/bundle_proto/config.pb.go
Normal file
|
@ -0,0 +1,952 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: config.proto
|
||||
|
||||
package android_bundle_proto
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type BundleConfig_BundleType int32
|
||||
|
||||
const (
|
||||
BundleConfig_REGULAR BundleConfig_BundleType = 0
|
||||
BundleConfig_APEX BundleConfig_BundleType = 1
|
||||
BundleConfig_ASSET_ONLY BundleConfig_BundleType = 2
|
||||
)
|
||||
|
||||
var BundleConfig_BundleType_name = map[int32]string{
|
||||
0: "REGULAR",
|
||||
1: "APEX",
|
||||
2: "ASSET_ONLY",
|
||||
}
|
||||
|
||||
var BundleConfig_BundleType_value = map[string]int32{
|
||||
"REGULAR": 0,
|
||||
"APEX": 1,
|
||||
"ASSET_ONLY": 2,
|
||||
}
|
||||
|
||||
func (x BundleConfig_BundleType) String() string {
|
||||
return proto.EnumName(BundleConfig_BundleType_name, int32(x))
|
||||
}
|
||||
|
||||
func (BundleConfig_BundleType) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_3eaf2c85e69e9ea4, []int{0, 0}
|
||||
}
|
||||
|
||||
type SplitDimension_Value int32
|
||||
|
||||
const (
|
||||
SplitDimension_UNSPECIFIED_VALUE SplitDimension_Value = 0
|
||||
SplitDimension_ABI SplitDimension_Value = 1
|
||||
SplitDimension_SCREEN_DENSITY SplitDimension_Value = 2
|
||||
SplitDimension_LANGUAGE SplitDimension_Value = 3
|
||||
SplitDimension_TEXTURE_COMPRESSION_FORMAT SplitDimension_Value = 4
|
||||
// BEGIN-INTERNAL
|
||||
SplitDimension_GRAPHICS_API SplitDimension_Value = 5
|
||||
)
|
||||
|
||||
var SplitDimension_Value_name = map[int32]string{
|
||||
0: "UNSPECIFIED_VALUE",
|
||||
1: "ABI",
|
||||
2: "SCREEN_DENSITY",
|
||||
3: "LANGUAGE",
|
||||
4: "TEXTURE_COMPRESSION_FORMAT",
|
||||
5: "GRAPHICS_API",
|
||||
}
|
||||
|
||||
var SplitDimension_Value_value = map[string]int32{
|
||||
"UNSPECIFIED_VALUE": 0,
|
||||
"ABI": 1,
|
||||
"SCREEN_DENSITY": 2,
|
||||
"LANGUAGE": 3,
|
||||
"TEXTURE_COMPRESSION_FORMAT": 4,
|
||||
"GRAPHICS_API": 5,
|
||||
}
|
||||
|
||||
func (x SplitDimension_Value) String() string {
|
||||
return proto.EnumName(SplitDimension_Value_name, int32(x))
|
||||
}
|
||||
|
||||
func (SplitDimension_Value) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_3eaf2c85e69e9ea4, []int{9, 0}
|
||||
}
|
||||
|
||||
type BundleConfig struct {
|
||||
Bundletool *Bundletool `protobuf:"bytes,1,opt,name=bundletool,proto3" json:"bundletool,omitempty"`
|
||||
Optimizations *Optimizations `protobuf:"bytes,2,opt,name=optimizations,proto3" json:"optimizations,omitempty"`
|
||||
Compression *Compression `protobuf:"bytes,3,opt,name=compression,proto3" json:"compression,omitempty"`
|
||||
// Resources to be always kept in the master split.
|
||||
MasterResources *MasterResources `protobuf:"bytes,4,opt,name=master_resources,json=masterResources,proto3" json:"master_resources,omitempty"`
|
||||
ApexConfig *ApexConfig `protobuf:"bytes,5,opt,name=apex_config,json=apexConfig,proto3" json:"apex_config,omitempty"`
|
||||
// APKs to be signed with the same key as generated APKs.
|
||||
UnsignedEmbeddedApkConfig []*UnsignedEmbeddedApkConfig `protobuf:"bytes,6,rep,name=unsigned_embedded_apk_config,json=unsignedEmbeddedApkConfig,proto3" json:"unsigned_embedded_apk_config,omitempty"`
|
||||
AssetModulesConfig *AssetModulesConfig `protobuf:"bytes,7,opt,name=asset_modules_config,json=assetModulesConfig,proto3" json:"asset_modules_config,omitempty"`
|
||||
Type BundleConfig_BundleType `protobuf:"varint,8,opt,name=type,proto3,enum=android.bundle.BundleConfig_BundleType" json:"type,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *BundleConfig) Reset() { *m = BundleConfig{} }
|
||||
func (m *BundleConfig) String() string { return proto.CompactTextString(m) }
|
||||
func (*BundleConfig) ProtoMessage() {}
|
||||
func (*BundleConfig) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_3eaf2c85e69e9ea4, []int{0}
|
||||
}
|
||||
|
||||
func (m *BundleConfig) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_BundleConfig.Unmarshal(m, b)
|
||||
}
|
||||
func (m *BundleConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_BundleConfig.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *BundleConfig) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_BundleConfig.Merge(m, src)
|
||||
}
|
||||
func (m *BundleConfig) XXX_Size() int {
|
||||
return xxx_messageInfo_BundleConfig.Size(m)
|
||||
}
|
||||
func (m *BundleConfig) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_BundleConfig.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_BundleConfig proto.InternalMessageInfo
|
||||
|
||||
func (m *BundleConfig) GetBundletool() *Bundletool {
|
||||
if m != nil {
|
||||
return m.Bundletool
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *BundleConfig) GetOptimizations() *Optimizations {
|
||||
if m != nil {
|
||||
return m.Optimizations
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *BundleConfig) GetCompression() *Compression {
|
||||
if m != nil {
|
||||
return m.Compression
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *BundleConfig) GetMasterResources() *MasterResources {
|
||||
if m != nil {
|
||||
return m.MasterResources
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *BundleConfig) GetApexConfig() *ApexConfig {
|
||||
if m != nil {
|
||||
return m.ApexConfig
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *BundleConfig) GetUnsignedEmbeddedApkConfig() []*UnsignedEmbeddedApkConfig {
|
||||
if m != nil {
|
||||
return m.UnsignedEmbeddedApkConfig
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *BundleConfig) GetAssetModulesConfig() *AssetModulesConfig {
|
||||
if m != nil {
|
||||
return m.AssetModulesConfig
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *BundleConfig) GetType() BundleConfig_BundleType {
|
||||
if m != nil {
|
||||
return m.Type
|
||||
}
|
||||
return BundleConfig_REGULAR
|
||||
}
|
||||
|
||||
type Bundletool struct {
|
||||
// Version of BundleTool used to build the Bundle.
|
||||
Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Bundletool) Reset() { *m = Bundletool{} }
|
||||
func (m *Bundletool) String() string { return proto.CompactTextString(m) }
|
||||
func (*Bundletool) ProtoMessage() {}
|
||||
func (*Bundletool) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_3eaf2c85e69e9ea4, []int{1}
|
||||
}
|
||||
|
||||
func (m *Bundletool) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Bundletool.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Bundletool) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Bundletool.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *Bundletool) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Bundletool.Merge(m, src)
|
||||
}
|
||||
func (m *Bundletool) XXX_Size() int {
|
||||
return xxx_messageInfo_Bundletool.Size(m)
|
||||
}
|
||||
func (m *Bundletool) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Bundletool.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Bundletool proto.InternalMessageInfo
|
||||
|
||||
func (m *Bundletool) GetVersion() string {
|
||||
if m != nil {
|
||||
return m.Version
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type Compression struct {
|
||||
// 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.
|
||||
UncompressedGlob []string `protobuf:"bytes,1,rep,name=uncompressed_glob,json=uncompressedGlob,proto3" json:"uncompressed_glob,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Compression) Reset() { *m = Compression{} }
|
||||
func (m *Compression) String() string { return proto.CompactTextString(m) }
|
||||
func (*Compression) ProtoMessage() {}
|
||||
func (*Compression) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_3eaf2c85e69e9ea4, []int{2}
|
||||
}
|
||||
|
||||
func (m *Compression) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Compression.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Compression) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Compression.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *Compression) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Compression.Merge(m, src)
|
||||
}
|
||||
func (m *Compression) XXX_Size() int {
|
||||
return xxx_messageInfo_Compression.Size(m)
|
||||
}
|
||||
func (m *Compression) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Compression.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Compression proto.InternalMessageInfo
|
||||
|
||||
func (m *Compression) GetUncompressedGlob() []string {
|
||||
if m != nil {
|
||||
return m.UncompressedGlob
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Resources to keep in the master split.
|
||||
type MasterResources struct {
|
||||
// Resource IDs to be kept in master split.
|
||||
ResourceIds []int32 `protobuf:"varint,1,rep,packed,name=resource_ids,json=resourceIds,proto3" json:"resource_ids,omitempty"`
|
||||
// Resource names to be kept in master split.
|
||||
ResourceNames []string `protobuf:"bytes,2,rep,name=resource_names,json=resourceNames,proto3" json:"resource_names,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *MasterResources) Reset() { *m = MasterResources{} }
|
||||
func (m *MasterResources) String() string { return proto.CompactTextString(m) }
|
||||
func (*MasterResources) ProtoMessage() {}
|
||||
func (*MasterResources) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_3eaf2c85e69e9ea4, []int{3}
|
||||
}
|
||||
|
||||
func (m *MasterResources) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_MasterResources.Unmarshal(m, b)
|
||||
}
|
||||
func (m *MasterResources) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_MasterResources.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *MasterResources) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_MasterResources.Merge(m, src)
|
||||
}
|
||||
func (m *MasterResources) XXX_Size() int {
|
||||
return xxx_messageInfo_MasterResources.Size(m)
|
||||
}
|
||||
func (m *MasterResources) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_MasterResources.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_MasterResources proto.InternalMessageInfo
|
||||
|
||||
func (m *MasterResources) GetResourceIds() []int32 {
|
||||
if m != nil {
|
||||
return m.ResourceIds
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MasterResources) GetResourceNames() []string {
|
||||
if m != nil {
|
||||
return m.ResourceNames
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Optimizations struct {
|
||||
SplitsConfig *SplitsConfig `protobuf:"bytes,1,opt,name=splits_config,json=splitsConfig,proto3" json:"splits_config,omitempty"`
|
||||
// This is for uncompressing native libraries on M+ devices (L+ devices on
|
||||
// instant apps).
|
||||
UncompressNativeLibraries *UncompressNativeLibraries `protobuf:"bytes,2,opt,name=uncompress_native_libraries,json=uncompressNativeLibraries,proto3" json:"uncompress_native_libraries,omitempty"`
|
||||
// This is for uncompressing dex files on P+ devices.
|
||||
UncompressDexFiles *UncompressDexFiles `protobuf:"bytes,3,opt,name=uncompress_dex_files,json=uncompressDexFiles,proto3" json:"uncompress_dex_files,omitempty"`
|
||||
// Configuration for the generation of standalone APKs.
|
||||
// If no StandaloneConfig is set, the configuration is inherited from
|
||||
// splits_config.
|
||||
StandaloneConfig *StandaloneConfig `protobuf:"bytes,4,opt,name=standalone_config,json=standaloneConfig,proto3" json:"standalone_config,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Optimizations) Reset() { *m = Optimizations{} }
|
||||
func (m *Optimizations) String() string { return proto.CompactTextString(m) }
|
||||
func (*Optimizations) ProtoMessage() {}
|
||||
func (*Optimizations) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_3eaf2c85e69e9ea4, []int{4}
|
||||
}
|
||||
|
||||
func (m *Optimizations) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Optimizations.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Optimizations) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Optimizations.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *Optimizations) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Optimizations.Merge(m, src)
|
||||
}
|
||||
func (m *Optimizations) XXX_Size() int {
|
||||
return xxx_messageInfo_Optimizations.Size(m)
|
||||
}
|
||||
func (m *Optimizations) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Optimizations.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Optimizations proto.InternalMessageInfo
|
||||
|
||||
func (m *Optimizations) GetSplitsConfig() *SplitsConfig {
|
||||
if m != nil {
|
||||
return m.SplitsConfig
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Optimizations) GetUncompressNativeLibraries() *UncompressNativeLibraries {
|
||||
if m != nil {
|
||||
return m.UncompressNativeLibraries
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Optimizations) GetUncompressDexFiles() *UncompressDexFiles {
|
||||
if m != nil {
|
||||
return m.UncompressDexFiles
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Optimizations) GetStandaloneConfig() *StandaloneConfig {
|
||||
if m != nil {
|
||||
return m.StandaloneConfig
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type UncompressNativeLibraries struct {
|
||||
Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *UncompressNativeLibraries) Reset() { *m = UncompressNativeLibraries{} }
|
||||
func (m *UncompressNativeLibraries) String() string { return proto.CompactTextString(m) }
|
||||
func (*UncompressNativeLibraries) ProtoMessage() {}
|
||||
func (*UncompressNativeLibraries) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_3eaf2c85e69e9ea4, []int{5}
|
||||
}
|
||||
|
||||
func (m *UncompressNativeLibraries) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_UncompressNativeLibraries.Unmarshal(m, b)
|
||||
}
|
||||
func (m *UncompressNativeLibraries) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_UncompressNativeLibraries.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *UncompressNativeLibraries) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_UncompressNativeLibraries.Merge(m, src)
|
||||
}
|
||||
func (m *UncompressNativeLibraries) XXX_Size() int {
|
||||
return xxx_messageInfo_UncompressNativeLibraries.Size(m)
|
||||
}
|
||||
func (m *UncompressNativeLibraries) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_UncompressNativeLibraries.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_UncompressNativeLibraries proto.InternalMessageInfo
|
||||
|
||||
func (m *UncompressNativeLibraries) GetEnabled() bool {
|
||||
if m != nil {
|
||||
return m.Enabled
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type UncompressDexFiles struct {
|
||||
Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *UncompressDexFiles) Reset() { *m = UncompressDexFiles{} }
|
||||
func (m *UncompressDexFiles) String() string { return proto.CompactTextString(m) }
|
||||
func (*UncompressDexFiles) ProtoMessage() {}
|
||||
func (*UncompressDexFiles) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_3eaf2c85e69e9ea4, []int{6}
|
||||
}
|
||||
|
||||
func (m *UncompressDexFiles) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_UncompressDexFiles.Unmarshal(m, b)
|
||||
}
|
||||
func (m *UncompressDexFiles) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_UncompressDexFiles.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *UncompressDexFiles) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_UncompressDexFiles.Merge(m, src)
|
||||
}
|
||||
func (m *UncompressDexFiles) XXX_Size() int {
|
||||
return xxx_messageInfo_UncompressDexFiles.Size(m)
|
||||
}
|
||||
func (m *UncompressDexFiles) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_UncompressDexFiles.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_UncompressDexFiles proto.InternalMessageInfo
|
||||
|
||||
func (m *UncompressDexFiles) GetEnabled() bool {
|
||||
if m != nil {
|
||||
return m.Enabled
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Optimization configuration used to generate Split APKs.
|
||||
type SplitsConfig struct {
|
||||
SplitDimension []*SplitDimension `protobuf:"bytes,1,rep,name=split_dimension,json=splitDimension,proto3" json:"split_dimension,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *SplitsConfig) Reset() { *m = SplitsConfig{} }
|
||||
func (m *SplitsConfig) String() string { return proto.CompactTextString(m) }
|
||||
func (*SplitsConfig) ProtoMessage() {}
|
||||
func (*SplitsConfig) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_3eaf2c85e69e9ea4, []int{7}
|
||||
}
|
||||
|
||||
func (m *SplitsConfig) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_SplitsConfig.Unmarshal(m, b)
|
||||
}
|
||||
func (m *SplitsConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_SplitsConfig.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *SplitsConfig) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_SplitsConfig.Merge(m, src)
|
||||
}
|
||||
func (m *SplitsConfig) XXX_Size() int {
|
||||
return xxx_messageInfo_SplitsConfig.Size(m)
|
||||
}
|
||||
func (m *SplitsConfig) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_SplitsConfig.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_SplitsConfig proto.InternalMessageInfo
|
||||
|
||||
func (m *SplitsConfig) GetSplitDimension() []*SplitDimension {
|
||||
if m != nil {
|
||||
return m.SplitDimension
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Optimization configuration used to generate Standalone APKs.
|
||||
type StandaloneConfig struct {
|
||||
// Device targeting dimensions to shard.
|
||||
SplitDimension []*SplitDimension `protobuf:"bytes,1,rep,name=split_dimension,json=splitDimension,proto3" json:"split_dimension,omitempty"`
|
||||
// Whether 64 bit libraries should be stripped from Standalone APKs.
|
||||
Strip_64BitLibraries bool `protobuf:"varint,2,opt,name=strip_64_bit_libraries,json=strip64BitLibraries,proto3" json:"strip_64_bit_libraries,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *StandaloneConfig) Reset() { *m = StandaloneConfig{} }
|
||||
func (m *StandaloneConfig) String() string { return proto.CompactTextString(m) }
|
||||
func (*StandaloneConfig) ProtoMessage() {}
|
||||
func (*StandaloneConfig) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_3eaf2c85e69e9ea4, []int{8}
|
||||
}
|
||||
|
||||
func (m *StandaloneConfig) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_StandaloneConfig.Unmarshal(m, b)
|
||||
}
|
||||
func (m *StandaloneConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_StandaloneConfig.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *StandaloneConfig) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_StandaloneConfig.Merge(m, src)
|
||||
}
|
||||
func (m *StandaloneConfig) XXX_Size() int {
|
||||
return xxx_messageInfo_StandaloneConfig.Size(m)
|
||||
}
|
||||
func (m *StandaloneConfig) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_StandaloneConfig.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_StandaloneConfig proto.InternalMessageInfo
|
||||
|
||||
func (m *StandaloneConfig) GetSplitDimension() []*SplitDimension {
|
||||
if m != nil {
|
||||
return m.SplitDimension
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *StandaloneConfig) GetStrip_64BitLibraries() bool {
|
||||
if m != nil {
|
||||
return m.Strip_64BitLibraries
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type SplitDimension struct {
|
||||
Value SplitDimension_Value `protobuf:"varint,1,opt,name=value,proto3,enum=android.bundle.SplitDimension_Value" json:"value,omitempty"`
|
||||
// If set to 'true', indicates that APKs should *not* be split by this
|
||||
// dimension.
|
||||
Negate bool `protobuf:"varint,2,opt,name=negate,proto3" json:"negate,omitempty"`
|
||||
// Optional transformation to be applied to asset directories where
|
||||
// the targeting is encoded in the directory name (e.g: assets/foo#tcf_etc1)
|
||||
SuffixStripping *SuffixStripping `protobuf:"bytes,3,opt,name=suffix_stripping,json=suffixStripping,proto3" json:"suffix_stripping,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *SplitDimension) Reset() { *m = SplitDimension{} }
|
||||
func (m *SplitDimension) String() string { return proto.CompactTextString(m) }
|
||||
func (*SplitDimension) ProtoMessage() {}
|
||||
func (*SplitDimension) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_3eaf2c85e69e9ea4, []int{9}
|
||||
}
|
||||
|
||||
func (m *SplitDimension) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_SplitDimension.Unmarshal(m, b)
|
||||
}
|
||||
func (m *SplitDimension) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_SplitDimension.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *SplitDimension) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_SplitDimension.Merge(m, src)
|
||||
}
|
||||
func (m *SplitDimension) XXX_Size() int {
|
||||
return xxx_messageInfo_SplitDimension.Size(m)
|
||||
}
|
||||
func (m *SplitDimension) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_SplitDimension.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_SplitDimension proto.InternalMessageInfo
|
||||
|
||||
func (m *SplitDimension) GetValue() SplitDimension_Value {
|
||||
if m != nil {
|
||||
return m.Value
|
||||
}
|
||||
return SplitDimension_UNSPECIFIED_VALUE
|
||||
}
|
||||
|
||||
func (m *SplitDimension) GetNegate() bool {
|
||||
if m != nil {
|
||||
return m.Negate
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *SplitDimension) GetSuffixStripping() *SuffixStripping {
|
||||
if m != nil {
|
||||
return m.SuffixStripping
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type SuffixStripping struct {
|
||||
// If set to 'true', indicates that the targeting suffix should be removed
|
||||
// from assets paths for this dimension when splits (or asset slices) 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.
|
||||
Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"`
|
||||
// The default suffix to be used for the cases where separate slices can't
|
||||
// be generated for this dimension. In the case of standalone/universal APKs
|
||||
// generation, stripping the suffix can lead to file name collisions. 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).
|
||||
DefaultSuffix string `protobuf:"bytes,2,opt,name=default_suffix,json=defaultSuffix,proto3" json:"default_suffix,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *SuffixStripping) Reset() { *m = SuffixStripping{} }
|
||||
func (m *SuffixStripping) String() string { return proto.CompactTextString(m) }
|
||||
func (*SuffixStripping) ProtoMessage() {}
|
||||
func (*SuffixStripping) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_3eaf2c85e69e9ea4, []int{10}
|
||||
}
|
||||
|
||||
func (m *SuffixStripping) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_SuffixStripping.Unmarshal(m, b)
|
||||
}
|
||||
func (m *SuffixStripping) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_SuffixStripping.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *SuffixStripping) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_SuffixStripping.Merge(m, src)
|
||||
}
|
||||
func (m *SuffixStripping) XXX_Size() int {
|
||||
return xxx_messageInfo_SuffixStripping.Size(m)
|
||||
}
|
||||
func (m *SuffixStripping) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_SuffixStripping.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_SuffixStripping proto.InternalMessageInfo
|
||||
|
||||
func (m *SuffixStripping) GetEnabled() bool {
|
||||
if m != nil {
|
||||
return m.Enabled
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *SuffixStripping) GetDefaultSuffix() string {
|
||||
if m != nil {
|
||||
return m.DefaultSuffix
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Configuration for processing APEX bundles.
|
||||
// https://source.android.com/devices/tech/ota/apex
|
||||
type ApexConfig struct {
|
||||
// Configuration for processing of APKs embedded in an APEX image.
|
||||
ApexEmbeddedApkConfig []*ApexEmbeddedApkConfig `protobuf:"bytes,1,rep,name=apex_embedded_apk_config,json=apexEmbeddedApkConfig,proto3" json:"apex_embedded_apk_config,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *ApexConfig) Reset() { *m = ApexConfig{} }
|
||||
func (m *ApexConfig) String() string { return proto.CompactTextString(m) }
|
||||
func (*ApexConfig) ProtoMessage() {}
|
||||
func (*ApexConfig) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_3eaf2c85e69e9ea4, []int{11}
|
||||
}
|
||||
|
||||
func (m *ApexConfig) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ApexConfig.Unmarshal(m, b)
|
||||
}
|
||||
func (m *ApexConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_ApexConfig.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *ApexConfig) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_ApexConfig.Merge(m, src)
|
||||
}
|
||||
func (m *ApexConfig) XXX_Size() int {
|
||||
return xxx_messageInfo_ApexConfig.Size(m)
|
||||
}
|
||||
func (m *ApexConfig) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_ApexConfig.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_ApexConfig proto.InternalMessageInfo
|
||||
|
||||
func (m *ApexConfig) GetApexEmbeddedApkConfig() []*ApexEmbeddedApkConfig {
|
||||
if m != nil {
|
||||
return m.ApexEmbeddedApkConfig
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ApexEmbeddedApkConfig struct {
|
||||
// Android package name of the APK.
|
||||
PackageName string `protobuf:"bytes,1,opt,name=package_name,json=packageName,proto3" json:"package_name,omitempty"`
|
||||
// Path to the APK within the APEX system image.
|
||||
Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *ApexEmbeddedApkConfig) Reset() { *m = ApexEmbeddedApkConfig{} }
|
||||
func (m *ApexEmbeddedApkConfig) String() string { return proto.CompactTextString(m) }
|
||||
func (*ApexEmbeddedApkConfig) ProtoMessage() {}
|
||||
func (*ApexEmbeddedApkConfig) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_3eaf2c85e69e9ea4, []int{12}
|
||||
}
|
||||
|
||||
func (m *ApexEmbeddedApkConfig) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ApexEmbeddedApkConfig.Unmarshal(m, b)
|
||||
}
|
||||
func (m *ApexEmbeddedApkConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_ApexEmbeddedApkConfig.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *ApexEmbeddedApkConfig) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_ApexEmbeddedApkConfig.Merge(m, src)
|
||||
}
|
||||
func (m *ApexEmbeddedApkConfig) XXX_Size() int {
|
||||
return xxx_messageInfo_ApexEmbeddedApkConfig.Size(m)
|
||||
}
|
||||
func (m *ApexEmbeddedApkConfig) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_ApexEmbeddedApkConfig.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_ApexEmbeddedApkConfig proto.InternalMessageInfo
|
||||
|
||||
func (m *ApexEmbeddedApkConfig) GetPackageName() string {
|
||||
if m != nil {
|
||||
return m.PackageName
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *ApexEmbeddedApkConfig) GetPath() string {
|
||||
if m != nil {
|
||||
return m.Path
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type UnsignedEmbeddedApkConfig struct {
|
||||
// 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).
|
||||
Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *UnsignedEmbeddedApkConfig) Reset() { *m = UnsignedEmbeddedApkConfig{} }
|
||||
func (m *UnsignedEmbeddedApkConfig) String() string { return proto.CompactTextString(m) }
|
||||
func (*UnsignedEmbeddedApkConfig) ProtoMessage() {}
|
||||
func (*UnsignedEmbeddedApkConfig) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_3eaf2c85e69e9ea4, []int{13}
|
||||
}
|
||||
|
||||
func (m *UnsignedEmbeddedApkConfig) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_UnsignedEmbeddedApkConfig.Unmarshal(m, b)
|
||||
}
|
||||
func (m *UnsignedEmbeddedApkConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_UnsignedEmbeddedApkConfig.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *UnsignedEmbeddedApkConfig) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_UnsignedEmbeddedApkConfig.Merge(m, src)
|
||||
}
|
||||
func (m *UnsignedEmbeddedApkConfig) XXX_Size() int {
|
||||
return xxx_messageInfo_UnsignedEmbeddedApkConfig.Size(m)
|
||||
}
|
||||
func (m *UnsignedEmbeddedApkConfig) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_UnsignedEmbeddedApkConfig.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_UnsignedEmbeddedApkConfig proto.InternalMessageInfo
|
||||
|
||||
func (m *UnsignedEmbeddedApkConfig) GetPath() string {
|
||||
if m != nil {
|
||||
return m.Path
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type AssetModulesConfig struct {
|
||||
// App versionCodes that will be updated with these asset modules.
|
||||
// Only relevant for asset-only bundles.
|
||||
AppVersion []int64 `protobuf:"varint,1,rep,packed,name=app_version,json=appVersion,proto3" json:"app_version,omitempty"`
|
||||
// Version tag for the asset upload.
|
||||
// Only relevant for asset-only bundles.
|
||||
AssetVersionTag string `protobuf:"bytes,2,opt,name=asset_version_tag,json=assetVersionTag,proto3" json:"asset_version_tag,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *AssetModulesConfig) Reset() { *m = AssetModulesConfig{} }
|
||||
func (m *AssetModulesConfig) String() string { return proto.CompactTextString(m) }
|
||||
func (*AssetModulesConfig) ProtoMessage() {}
|
||||
func (*AssetModulesConfig) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_3eaf2c85e69e9ea4, []int{14}
|
||||
}
|
||||
|
||||
func (m *AssetModulesConfig) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_AssetModulesConfig.Unmarshal(m, b)
|
||||
}
|
||||
func (m *AssetModulesConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_AssetModulesConfig.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *AssetModulesConfig) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_AssetModulesConfig.Merge(m, src)
|
||||
}
|
||||
func (m *AssetModulesConfig) XXX_Size() int {
|
||||
return xxx_messageInfo_AssetModulesConfig.Size(m)
|
||||
}
|
||||
func (m *AssetModulesConfig) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_AssetModulesConfig.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_AssetModulesConfig proto.InternalMessageInfo
|
||||
|
||||
func (m *AssetModulesConfig) GetAppVersion() []int64 {
|
||||
if m != nil {
|
||||
return m.AppVersion
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *AssetModulesConfig) GetAssetVersionTag() string {
|
||||
if m != nil {
|
||||
return m.AssetVersionTag
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterEnum("android.bundle.BundleConfig_BundleType", BundleConfig_BundleType_name, BundleConfig_BundleType_value)
|
||||
proto.RegisterEnum("android.bundle.SplitDimension_Value", SplitDimension_Value_name, SplitDimension_Value_value)
|
||||
proto.RegisterType((*BundleConfig)(nil), "android.bundle.BundleConfig")
|
||||
proto.RegisterType((*Bundletool)(nil), "android.bundle.Bundletool")
|
||||
proto.RegisterType((*Compression)(nil), "android.bundle.Compression")
|
||||
proto.RegisterType((*MasterResources)(nil), "android.bundle.MasterResources")
|
||||
proto.RegisterType((*Optimizations)(nil), "android.bundle.Optimizations")
|
||||
proto.RegisterType((*UncompressNativeLibraries)(nil), "android.bundle.UncompressNativeLibraries")
|
||||
proto.RegisterType((*UncompressDexFiles)(nil), "android.bundle.UncompressDexFiles")
|
||||
proto.RegisterType((*SplitsConfig)(nil), "android.bundle.SplitsConfig")
|
||||
proto.RegisterType((*StandaloneConfig)(nil), "android.bundle.StandaloneConfig")
|
||||
proto.RegisterType((*SplitDimension)(nil), "android.bundle.SplitDimension")
|
||||
proto.RegisterType((*SuffixStripping)(nil), "android.bundle.SuffixStripping")
|
||||
proto.RegisterType((*ApexConfig)(nil), "android.bundle.ApexConfig")
|
||||
proto.RegisterType((*ApexEmbeddedApkConfig)(nil), "android.bundle.ApexEmbeddedApkConfig")
|
||||
proto.RegisterType((*UnsignedEmbeddedApkConfig)(nil), "android.bundle.UnsignedEmbeddedApkConfig")
|
||||
proto.RegisterType((*AssetModulesConfig)(nil), "android.bundle.AssetModulesConfig")
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("config.proto", fileDescriptor_3eaf2c85e69e9ea4)
|
||||
}
|
||||
|
||||
var fileDescriptor_3eaf2c85e69e9ea4 = []byte{
|
||||
// 1001 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0xdb, 0x6e, 0xdb, 0x46,
|
||||
0x10, 0x0d, 0x75, 0xb1, 0xe5, 0x91, 0x2c, 0xd1, 0xdb, 0x38, 0x50, 0x2e, 0x4d, 0x5c, 0xa2, 0x41,
|
||||
0xdd, 0xb4, 0x50, 0x01, 0x3b, 0xcd, 0x83, 0x83, 0x3e, 0xd0, 0x32, 0xad, 0x2a, 0xd0, 0x0d, 0x4b,
|
||||
0xc9, 0x4d, 0x5a, 0xa0, 0x8b, 0x95, 0xb8, 0x52, 0xb7, 0xa6, 0x48, 0x82, 0x4b, 0x1a, 0x4a, 0xfb,
|
||||
0x09, 0x7d, 0xe9, 0x8f, 0xf4, 0xa7, 0xfa, 0x25, 0x05, 0x97, 0xa4, 0x2c, 0x51, 0x52, 0x9e, 0xfa,
|
||||
0x24, 0xce, 0xec, 0x39, 0xb3, 0x3b, 0xb3, 0x67, 0x67, 0x04, 0x95, 0x89, 0xeb, 0x4c, 0xf9, 0xac,
|
||||
0xe1, 0xf9, 0x6e, 0xe0, 0xa2, 0x2a, 0x75, 0x2c, 0xdf, 0xe5, 0x56, 0x63, 0x1c, 0x3a, 0x96, 0xcd,
|
||||
0xb4, 0xbf, 0x8a, 0x50, 0xb9, 0x94, 0x9f, 0x4d, 0x09, 0x43, 0x17, 0x00, 0xf1, 0x52, 0xe0, 0xba,
|
||||
0x76, 0x5d, 0x39, 0x51, 0x4e, 0xcb, 0x67, 0x4f, 0x1a, 0xeb, 0xac, 0xc6, 0xe5, 0x12, 0x81, 0x57,
|
||||
0xd0, 0xa8, 0x09, 0x87, 0xae, 0x17, 0xf0, 0x39, 0xff, 0x83, 0x06, 0xdc, 0x75, 0x44, 0x3d, 0x27,
|
||||
0xe9, 0x9f, 0x67, 0xe9, 0xfd, 0x55, 0x10, 0x5e, 0xe7, 0xa0, 0x1f, 0xa0, 0x3c, 0x71, 0xe7, 0x9e,
|
||||
0xcf, 0x84, 0xe0, 0xae, 0x53, 0xcf, 0xcb, 0x10, 0x4f, 0xb3, 0x21, 0x9a, 0xf7, 0x10, 0xbc, 0x8a,
|
||||
0x47, 0xef, 0x40, 0x9d, 0x53, 0x11, 0x30, 0x9f, 0xf8, 0x4c, 0xb8, 0xa1, 0x3f, 0x61, 0xa2, 0x5e,
|
||||
0x90, 0x31, 0x5e, 0x64, 0x63, 0x74, 0x25, 0x0e, 0xa7, 0x30, 0x5c, 0x9b, 0xaf, 0x3b, 0xd0, 0x5b,
|
||||
0x28, 0x53, 0x8f, 0x2d, 0x48, 0x5c, 0xc1, 0x7a, 0x71, 0x7b, 0x31, 0x74, 0x8f, 0x2d, 0xe2, 0xe2,
|
||||
0x61, 0xa0, 0xcb, 0x6f, 0xf4, 0x3b, 0x3c, 0x0b, 0x1d, 0xc1, 0x67, 0x0e, 0xb3, 0x08, 0x9b, 0x8f,
|
||||
0x99, 0x65, 0x31, 0x8b, 0x50, 0xef, 0x36, 0x8d, 0xb6, 0x77, 0x92, 0x3f, 0x2d, 0x9f, 0x7d, 0x9d,
|
||||
0x8d, 0x36, 0x4a, 0x38, 0x46, 0x42, 0xd1, 0xbd, 0xdb, 0x24, 0xf8, 0xe3, 0x70, 0xd7, 0x12, 0x1a,
|
||||
0xc2, 0x43, 0x2a, 0x04, 0x0b, 0xc8, 0xdc, 0xb5, 0x42, 0x9b, 0x89, 0x74, 0x8f, 0x7d, 0x79, 0x62,
|
||||
0x6d, 0xe3, 0xc4, 0x11, 0xb6, 0x1b, 0x43, 0x93, 0xe0, 0x88, 0x6e, 0xf8, 0xd0, 0x5b, 0x28, 0x04,
|
||||
0x1f, 0x3d, 0x56, 0x2f, 0x9d, 0x28, 0xa7, 0xd5, 0xb3, 0xaf, 0xb6, 0x8b, 0x20, 0xc6, 0x26, 0xc6,
|
||||
0xf0, 0xa3, 0xc7, 0xb0, 0x24, 0x69, 0xe7, 0x00, 0xf7, 0x3e, 0x54, 0x86, 0x7d, 0x6c, 0xb4, 0x46,
|
||||
0x1d, 0x1d, 0xab, 0x0f, 0x50, 0x09, 0x0a, 0xfa, 0xc0, 0x78, 0xaf, 0x2a, 0xa8, 0x0a, 0xa0, 0x9b,
|
||||
0xa6, 0x31, 0x24, 0xfd, 0x5e, 0xe7, 0x83, 0x9a, 0xd3, 0xbe, 0x4d, 0x49, 0x52, 0x4e, 0x75, 0xd8,
|
||||
0xbf, 0x63, 0xbe, 0x54, 0x41, 0x24, 0xa4, 0x03, 0x9c, 0x9a, 0xef, 0x0a, 0x25, 0x45, 0xcd, 0x69,
|
||||
0x17, 0x50, 0x5e, 0x91, 0x01, 0xfa, 0x06, 0x8e, 0x42, 0x27, 0x95, 0x02, 0xb3, 0xc8, 0xcc, 0x76,
|
||||
0xc7, 0x75, 0xe5, 0x24, 0x7f, 0x7a, 0x80, 0xd5, 0xd5, 0x85, 0x96, 0xed, 0x8e, 0xb5, 0x5f, 0xa0,
|
||||
0x96, 0xb9, 0x7e, 0xf4, 0x05, 0x54, 0x52, 0xc9, 0x10, 0x6e, 0x09, 0x49, 0x2d, 0xe2, 0x72, 0xea,
|
||||
0x6b, 0x5b, 0x02, 0xbd, 0x84, 0xea, 0x12, 0xe2, 0xd0, 0x39, 0x8b, 0x14, 0x1e, 0xc5, 0x3f, 0x4c,
|
||||
0xbd, 0xbd, 0xc8, 0xa9, 0xfd, 0x9b, 0x83, 0xc3, 0x35, 0x8d, 0x23, 0x1d, 0x0e, 0x85, 0x67, 0xf3,
|
||||
0x60, 0x79, 0x33, 0xf1, 0xc3, 0x7a, 0x96, 0xad, 0xa9, 0x29, 0x41, 0xc9, 0x9d, 0x54, 0xc4, 0x8a,
|
||||
0x85, 0x38, 0x3c, 0xbd, 0xcf, 0x82, 0x38, 0x34, 0xe0, 0x77, 0x8c, 0xd8, 0x7c, 0xec, 0x53, 0x9f,
|
||||
0xb3, 0xf4, 0xa9, 0x6d, 0x91, 0x53, 0x4a, 0xe9, 0x49, 0x46, 0x27, 0x25, 0x44, 0x72, 0xda, 0xb1,
|
||||
0x14, 0xc9, 0x69, 0x65, 0x2b, 0x8b, 0x2d, 0xc8, 0x94, 0xdb, 0x4c, 0x24, 0x6f, 0x51, 0xdb, 0xbd,
|
||||
0xc7, 0x15, 0x5b, 0x5c, 0x47, 0x48, 0x8c, 0xc2, 0x0d, 0x1f, 0xea, 0xc2, 0x91, 0x08, 0xa8, 0x63,
|
||||
0x51, 0xdb, 0x75, 0x58, 0x5a, 0x87, 0xf8, 0x69, 0x9e, 0x6c, 0xd4, 0x61, 0x09, 0x4c, 0x6a, 0xa1,
|
||||
0x8a, 0x8c, 0x47, 0xfb, 0x1e, 0x1e, 0xef, 0x4c, 0x2e, 0x92, 0x0e, 0x73, 0xe8, 0xd8, 0x66, 0x96,
|
||||
0xac, 0x74, 0x09, 0xa7, 0xa6, 0xd6, 0x00, 0xb4, 0x79, 0xde, 0x4f, 0xe0, 0x7f, 0x82, 0xca, 0xea,
|
||||
0xa5, 0xa0, 0x16, 0xd4, 0xe4, 0xb5, 0x10, 0x8b, 0xcf, 0x99, 0x23, 0xc5, 0xa9, 0xc8, 0x97, 0xfc,
|
||||
0x7c, 0xeb, 0x5d, 0x5e, 0xa5, 0x28, 0x5c, 0x15, 0x6b, 0xb6, 0xf6, 0xb7, 0x02, 0x6a, 0x36, 0xcd,
|
||||
0xff, 0x2d, 0x3a, 0x3a, 0x87, 0x47, 0x22, 0xf0, 0xb9, 0x47, 0xde, 0xbc, 0x26, 0x63, 0x1e, 0x64,
|
||||
0x84, 0x52, 0xc2, 0x9f, 0xc9, 0xd5, 0x37, 0xaf, 0x2f, 0x79, 0xb0, 0xac, 0x9a, 0xf6, 0x4f, 0x0e,
|
||||
0xaa, 0xeb, 0x71, 0xd1, 0x05, 0x14, 0xef, 0xa8, 0x1d, 0x32, 0x59, 0x96, 0xea, 0xd9, 0x97, 0x9f,
|
||||
0x3e, 0x46, 0xe3, 0x26, 0xc2, 0xe2, 0x98, 0x82, 0x1e, 0xc1, 0x9e, 0xc3, 0x66, 0x34, 0x60, 0xc9,
|
||||
0x9e, 0x89, 0x15, 0xb5, 0x68, 0x11, 0x4e, 0xa7, 0x7c, 0x41, 0xe4, 0x21, 0x3c, 0xee, 0xcc, 0x12,
|
||||
0x69, 0x6d, 0xb4, 0x68, 0x53, 0xe2, 0xcc, 0x14, 0x86, 0x6b, 0x62, 0xdd, 0xa1, 0xfd, 0x09, 0x45,
|
||||
0xb9, 0x27, 0x3a, 0x86, 0xa3, 0x51, 0xcf, 0x1c, 0x18, 0xcd, 0xf6, 0x75, 0xdb, 0xb8, 0x22, 0x37,
|
||||
0x7a, 0x67, 0x64, 0xa8, 0x0f, 0xd0, 0x3e, 0xe4, 0xf5, 0xcb, 0xb6, 0xaa, 0x20, 0x04, 0x55, 0xb3,
|
||||
0x89, 0x0d, 0xa3, 0x47, 0xae, 0x8c, 0x9e, 0xd9, 0x1e, 0x7e, 0x50, 0x73, 0xa8, 0x02, 0xa5, 0x8e,
|
||||
0xde, 0x6b, 0x8d, 0xf4, 0x96, 0xa1, 0xe6, 0xd1, 0x73, 0x78, 0x32, 0x34, 0xde, 0x0f, 0x47, 0xd8,
|
||||
0x20, 0xcd, 0x7e, 0x77, 0x80, 0x0d, 0xd3, 0x6c, 0xf7, 0x7b, 0xe4, 0xba, 0x8f, 0xbb, 0xfa, 0x50,
|
||||
0x2d, 0x20, 0x15, 0x2a, 0x2d, 0xac, 0x0f, 0x7e, 0x6c, 0x37, 0x4d, 0xa2, 0x0f, 0xda, 0x6a, 0x51,
|
||||
0xc3, 0x50, 0xcb, 0x1c, 0x70, 0xb7, 0x90, 0xa2, 0xde, 0x61, 0xb1, 0x29, 0x0d, 0xed, 0x80, 0xc4,
|
||||
0x49, 0x24, 0x4d, 0xed, 0x30, 0xf1, 0xc6, 0x91, 0x34, 0x1b, 0xe0, 0x7e, 0xa0, 0xa0, 0x5f, 0xa1,
|
||||
0x2e, 0x27, 0xd0, 0xb6, 0x01, 0x12, 0x0b, 0xe3, 0xe5, 0xb6, 0x71, 0xb4, 0x39, 0x3c, 0x8e, 0xe9,
|
||||
0x36, 0xb7, 0xd6, 0x83, 0xe3, 0xad, 0xf8, 0xa8, 0x19, 0x7a, 0x74, 0x72, 0x4b, 0x67, 0x71, 0xa3,
|
||||
0x93, 0xc9, 0x1c, 0xe0, 0x72, 0xe2, 0x8b, 0xda, 0x1c, 0x42, 0x50, 0xf0, 0x68, 0xf0, 0x5b, 0x92,
|
||||
0x86, 0xfc, 0xd6, 0xbe, 0x8b, 0x1e, 0xe5, 0xae, 0x29, 0x95, 0x12, 0x94, 0x15, 0x02, 0x05, 0xb4,
|
||||
0x39, 0x8d, 0xd0, 0x8b, 0x68, 0xf0, 0x7a, 0x24, 0xed, 0xfe, 0x51, 0xa6, 0xf9, 0x68, 0xb8, 0x7a,
|
||||
0x37, 0xb1, 0x07, 0xbd, 0x82, 0xa3, 0x78, 0xe0, 0x25, 0x10, 0x12, 0xd0, 0x59, 0x72, 0x90, 0x9a,
|
||||
0x5c, 0x48, 0x80, 0x43, 0x3a, 0xbb, 0x7c, 0x05, 0x68, 0xe2, 0xce, 0x33, 0x65, 0xfa, 0xf9, 0x61,
|
||||
0x62, 0x93, 0xd8, 0x26, 0xf2, 0xef, 0xd1, 0x78, 0x4f, 0xfe, 0x9c, 0xff, 0x17, 0x00, 0x00, 0xff,
|
||||
0xff, 0x6b, 0x05, 0xbf, 0x99, 0x35, 0x09, 0x00, 0x00,
|
||||
}
|
162
cmd/extract_apks/bundle_proto/config.proto
Normal file
162
cmd/extract_apks/bundle_proto/config.proto
Normal file
|
@ -0,0 +1,162 @@
|
|||
// Messages describing APK Set's table of contents (toc.pb entry).
|
||||
// Please be advised that the ultimate source is at
|
||||
// https://github.com/google/bundletool/tree/master/src/main/proto
|
||||
// so you have been warned.
|
||||
syntax = "proto3";
|
||||
|
||||
package android.bundle;
|
||||
|
||||
option go_package = "android_bundle_proto";
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 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 {
|
||||
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 on P+ devices.
|
||||
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;
|
||||
}
|
||||
|
||||
message UncompressNativeLibraries {
|
||||
bool enabled = 1;
|
||||
}
|
||||
|
||||
message UncompressDexFiles {
|
||||
bool enabled = 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;
|
||||
}
|
||||
|
||||
message SplitDimension {
|
||||
enum Value {
|
||||
UNSPECIFIED_VALUE = 0;
|
||||
ABI = 1;
|
||||
SCREEN_DENSITY = 2;
|
||||
LANGUAGE = 3;
|
||||
TEXTURE_COMPRESSION_FORMAT = 4;
|
||||
// BEGIN-INTERNAL
|
||||
GRAPHICS_API = 5;
|
||||
// END-INTERNAL
|
||||
}
|
||||
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 (or asset slices) 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. In the case of standalone/universal APKs
|
||||
// generation, stripping the suffix can lead to file name collisions. 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
12
cmd/extract_apks/bundle_proto/regen.sh
Executable file
12
cmd/extract_apks/bundle_proto/regen.sh
Executable file
|
@ -0,0 +1,12 @@
|
|||
#!/bin/bash
|
||||
# Generates the golang source file of protos file describing APK set table of
|
||||
# contents (toc.pb file).
|
||||
|
||||
set -e
|
||||
function die() { echo "ERROR: $1" >&2; exit 1; }
|
||||
|
||||
readonly error_msg="Maybe you need to run 'lunch aosp_arm-eng && m aprotoc blueprint_tools'?"
|
||||
|
||||
hash aprotoc &>/dev/null || die "could not find aprotoc. ${error_msg}"
|
||||
# TODO(asmundak): maybe have the paths relative to repo top?
|
||||
(cd "${0%/*}" && aprotoc --go_out=paths=source_relative:. commands.proto config.proto targeting.proto ) || die "build failed. ${error_msg}"
|
1734
cmd/extract_apks/bundle_proto/targeting.pb.go
Normal file
1734
cmd/extract_apks/bundle_proto/targeting.pb.go
Normal file
File diff suppressed because it is too large
Load diff
232
cmd/extract_apks/bundle_proto/targeting.proto
Normal file
232
cmd/extract_apks/bundle_proto/targeting.proto
Normal file
|
@ -0,0 +1,232 @@
|
|||
// Messages describing APK Set's table of contents (toc.pb entry).
|
||||
// Please be advised that the ultimate source is at
|
||||
// https://github.com/google/bundletool/tree/master/src/main/proto
|
||||
// so you have been warned.
|
||||
syntax = "proto3";
|
||||
|
||||
package android.bundle;
|
||||
|
||||
option go_package = "android_bundle_proto";
|
||||
option java_package = "com.android.bundle";
|
||||
|
||||
// Targeting on the level of variants.
|
||||
message VariantTargeting {
|
||||
SdkVersionTargeting sdk_version_targeting = 1;
|
||||
AbiTargeting abi_targeting = 2;
|
||||
ScreenDensityTargeting screen_density_targeting = 3;
|
||||
MultiAbiTargeting multi_abi_targeting = 4;
|
||||
TextureCompressionFormatTargeting texture_compression_format_targeting = 5;
|
||||
}
|
||||
|
||||
// Targeting on the level of individual APKs.
|
||||
message ApkTargeting {
|
||||
AbiTargeting abi_targeting = 1;
|
||||
GraphicsApiTargeting graphics_api_targeting = 2;
|
||||
LanguageTargeting language_targeting = 3;
|
||||
ScreenDensityTargeting screen_density_targeting = 4;
|
||||
SdkVersionTargeting sdk_version_targeting = 5;
|
||||
TextureCompressionFormatTargeting texture_compression_format_targeting = 6;
|
||||
MultiAbiTargeting multi_abi_targeting = 7;
|
||||
SanitizerTargeting sanitizer_targeting = 8;
|
||||
}
|
||||
|
||||
// Targeting on the module level.
|
||||
// The semantic of the targeting is the "AND" rule on all immediate values.
|
||||
message ModuleTargeting {
|
||||
SdkVersionTargeting sdk_version_targeting = 1;
|
||||
repeated DeviceFeatureTargeting device_feature_targeting = 2;
|
||||
UserCountriesTargeting user_countries_targeting = 3;
|
||||
}
|
||||
|
||||
// User Countries targeting describing an inclusive/exclusive list of country
|
||||
// codes that module targets.
|
||||
message UserCountriesTargeting {
|
||||
// List of country codes in the two-letter CLDR territory format.
|
||||
repeated string country_codes = 1;
|
||||
|
||||
// Indicates if the list above is exclusive.
|
||||
bool exclude = 2;
|
||||
}
|
||||
|
||||
message ScreenDensity {
|
||||
enum DensityAlias {
|
||||
DENSITY_UNSPECIFIED = 0;
|
||||
NODPI = 1;
|
||||
LDPI = 2;
|
||||
MDPI = 3;
|
||||
TVDPI = 4;
|
||||
HDPI = 5;
|
||||
XHDPI = 6;
|
||||
XXHDPI = 7;
|
||||
XXXHDPI = 8;
|
||||
}
|
||||
|
||||
oneof density_oneof {
|
||||
DensityAlias density_alias = 1;
|
||||
int32 density_dpi = 2;
|
||||
}
|
||||
}
|
||||
|
||||
// Wrapper message for `int32`.
|
||||
//
|
||||
// The JSON representation for `Int32Value` is JSON number.
|
||||
message Int32Value {
|
||||
// The int32 value.
|
||||
int32 value = 1;
|
||||
}
|
||||
|
||||
message SdkVersion {
|
||||
// Inclusive.
|
||||
Int32Value min = 1;
|
||||
}
|
||||
|
||||
message GraphicsApi {
|
||||
oneof api_oneof {
|
||||
// Inclusive.
|
||||
OpenGlVersion min_open_gl_version = 1;
|
||||
// Inclusive.
|
||||
VulkanVersion min_vulkan_version = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message VulkanVersion {
|
||||
int32 major = 1; // VK_VERSION_MAJOR
|
||||
int32 minor = 2; // VK_VERSION_MINOR
|
||||
}
|
||||
|
||||
message OpenGlVersion {
|
||||
// e.g. OpenGL ES 3.2 is represented as { major: 3, minor: 2 }
|
||||
int32 major = 1; // GL_MAJOR_VERSION
|
||||
int32 minor = 2; // GL_MINOR_VERSION
|
||||
}
|
||||
|
||||
message TextureCompressionFormat {
|
||||
enum TextureCompressionFormatAlias {
|
||||
UNSPECIFIED_TEXTURE_COMPRESSION_FORMAT = 0;
|
||||
ETC1_RGB8 = 1;
|
||||
PALETTED = 2;
|
||||
THREE_DC = 3;
|
||||
ATC = 4;
|
||||
LATC = 5;
|
||||
DXT1 = 6;
|
||||
S3TC = 7;
|
||||
PVRTC = 8;
|
||||
ASTC = 9;
|
||||
ETC2 = 10;
|
||||
}
|
||||
TextureCompressionFormatAlias alias = 1;
|
||||
}
|
||||
|
||||
message Abi {
|
||||
enum AbiAlias {
|
||||
UNSPECIFIED_CPU_ARCHITECTURE = 0;
|
||||
ARMEABI = 1;
|
||||
ARMEABI_V7A = 2;
|
||||
ARM64_V8A = 3;
|
||||
X86 = 4;
|
||||
X86_64 = 5;
|
||||
MIPS = 6;
|
||||
MIPS64 = 7;
|
||||
}
|
||||
AbiAlias alias = 1;
|
||||
}
|
||||
|
||||
message MultiAbi {
|
||||
repeated Abi abi = 1;
|
||||
}
|
||||
|
||||
message Sanitizer {
|
||||
enum SanitizerAlias {
|
||||
NONE = 0;
|
||||
HWADDRESS = 1;
|
||||
}
|
||||
SanitizerAlias alias = 1;
|
||||
}
|
||||
|
||||
message DeviceFeature {
|
||||
string feature_name = 1;
|
||||
// Equivalent of android:glEsVersion or android:version in <uses-feature>.
|
||||
int32 feature_version = 2;
|
||||
}
|
||||
|
||||
// Targeting specific for directories under assets/.
|
||||
message AssetsDirectoryTargeting {
|
||||
AbiTargeting abi = 1;
|
||||
GraphicsApiTargeting graphics_api = 2;
|
||||
TextureCompressionFormatTargeting texture_compression_format = 3;
|
||||
LanguageTargeting language = 4;
|
||||
}
|
||||
|
||||
// Targeting specific for directories under lib/.
|
||||
message NativeDirectoryTargeting {
|
||||
Abi abi = 1;
|
||||
GraphicsApi graphics_api = 2;
|
||||
TextureCompressionFormat texture_compression_format = 3;
|
||||
Sanitizer sanitizer = 4;
|
||||
}
|
||||
|
||||
// Targeting specific for image files under apex/.
|
||||
message ApexImageTargeting {
|
||||
MultiAbiTargeting multi_abi = 1;
|
||||
}
|
||||
|
||||
message AbiTargeting {
|
||||
repeated Abi value = 1;
|
||||
// Targeting of other sibling directories that were in the Bundle.
|
||||
// For master splits this is targeting of other master splits.
|
||||
repeated Abi alternatives = 2;
|
||||
}
|
||||
|
||||
message MultiAbiTargeting {
|
||||
repeated MultiAbi value = 1;
|
||||
// Targeting of other sibling directories that were in the Bundle.
|
||||
// For master splits this is targeting of other master splits.
|
||||
repeated MultiAbi alternatives = 2;
|
||||
}
|
||||
|
||||
message ScreenDensityTargeting {
|
||||
repeated ScreenDensity value = 1;
|
||||
// Targeting of other sibling directories that were in the Bundle.
|
||||
// For master splits this is targeting of other master splits.
|
||||
repeated ScreenDensity alternatives = 2;
|
||||
}
|
||||
|
||||
message LanguageTargeting {
|
||||
// ISO-639: 2 or 3 letter language code.
|
||||
repeated string value = 1;
|
||||
// Targeting of other sibling directories that were in the Bundle.
|
||||
// For master splits this is targeting of other master splits.
|
||||
repeated string alternatives = 2;
|
||||
}
|
||||
|
||||
message GraphicsApiTargeting {
|
||||
repeated GraphicsApi value = 1;
|
||||
// Targeting of other sibling directories that were in the Bundle.
|
||||
// For master splits this is targeting of other master splits.
|
||||
repeated GraphicsApi alternatives = 2;
|
||||
}
|
||||
|
||||
message SdkVersionTargeting {
|
||||
repeated SdkVersion value = 1;
|
||||
// Targeting of other sibling directories that were in the Bundle.
|
||||
// For master splits this is targeting of other master splits.
|
||||
repeated SdkVersion alternatives = 2;
|
||||
}
|
||||
|
||||
message TextureCompressionFormatTargeting {
|
||||
repeated TextureCompressionFormat value = 1;
|
||||
// Targeting of other sibling directories that were in the Bundle.
|
||||
// For master splits this is targeting of other master splits.
|
||||
repeated TextureCompressionFormat alternatives = 2;
|
||||
}
|
||||
|
||||
message SanitizerTargeting {
|
||||
repeated Sanitizer value = 1;
|
||||
}
|
||||
|
||||
// Since other atom targeting messages have the "OR" semantic on values
|
||||
// the DeviceFeatureTargeting represents only one device feature to retain
|
||||
// that convention.
|
||||
message DeviceFeatureTargeting {
|
||||
DeviceFeature required_feature = 1;
|
||||
}
|
467
cmd/extract_apks/main.go
Normal file
467
cmd/extract_apks/main.go
Normal file
|
@ -0,0 +1,467 @@
|
|||
// Copyright 2020 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Copies all the entries (APKs/APEXes) matching the target configuration from the given
|
||||
// APK set into a zip file. Run it without arguments to see usage details.
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
|
||||
"android/soong/cmd/extract_apks/bundle_proto"
|
||||
"android/soong/third_party/zip"
|
||||
)
|
||||
|
||||
type TargetConfig struct {
|
||||
sdkVersion int32
|
||||
screenDpi map[android_bundle_proto.ScreenDensity_DensityAlias]bool
|
||||
abis map[android_bundle_proto.Abi_AbiAlias]bool
|
||||
allowPrereleased bool
|
||||
stem string
|
||||
}
|
||||
|
||||
// An APK set is a zip archive. An entry 'toc.pb' describes its contents.
|
||||
// It is a protobuf message BuildApkResult.
|
||||
type Toc *android_bundle_proto.BuildApksResult
|
||||
|
||||
type ApkSet struct {
|
||||
path string
|
||||
reader *zip.ReadCloser
|
||||
entries map[string]*zip.File
|
||||
}
|
||||
|
||||
func newApkSet(path string) (*ApkSet, error) {
|
||||
apkSet := &ApkSet{path: path, entries: make(map[string]*zip.File)}
|
||||
var err error
|
||||
if apkSet.reader, err = zip.OpenReader(apkSet.path); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, f := range apkSet.reader.File {
|
||||
apkSet.entries[f.Name] = f
|
||||
}
|
||||
return apkSet, nil
|
||||
}
|
||||
|
||||
func (apkSet *ApkSet) getToc() (Toc, error) {
|
||||
var err error
|
||||
tocFile, ok := apkSet.entries["toc.pb"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%s: APK set should have toc.pb entry", apkSet.path)
|
||||
}
|
||||
rc, err := tocFile.Open()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bytes := make([]byte, tocFile.FileHeader.UncompressedSize64)
|
||||
if _, err := rc.Read(bytes); err != io.EOF {
|
||||
return nil, err
|
||||
}
|
||||
rc.Close()
|
||||
buildApksResult := new(android_bundle_proto.BuildApksResult)
|
||||
if err = proto.Unmarshal(bytes, buildApksResult); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buildApksResult, nil
|
||||
}
|
||||
|
||||
func (apkSet *ApkSet) close() {
|
||||
apkSet.reader.Close()
|
||||
}
|
||||
|
||||
// Matchers for selection criteria
|
||||
type abiTargetingMatcher struct {
|
||||
*android_bundle_proto.AbiTargeting
|
||||
}
|
||||
|
||||
func (m abiTargetingMatcher) matches(config TargetConfig) bool {
|
||||
if m.AbiTargeting == nil {
|
||||
return true
|
||||
}
|
||||
if _, ok := config.abis[android_bundle_proto.Abi_UNSPECIFIED_CPU_ARCHITECTURE]; ok {
|
||||
return true
|
||||
}
|
||||
for _, v := range m.GetValue() {
|
||||
if _, ok := config.abis[v.Alias]; ok {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type apkDescriptionMatcher struct {
|
||||
*android_bundle_proto.ApkDescription
|
||||
}
|
||||
|
||||
func (m apkDescriptionMatcher) matches(config TargetConfig) bool {
|
||||
return m.ApkDescription == nil || (apkTargetingMatcher{m.Targeting}).matches(config)
|
||||
}
|
||||
|
||||
type apkTargetingMatcher struct {
|
||||
*android_bundle_proto.ApkTargeting
|
||||
}
|
||||
|
||||
func (m apkTargetingMatcher) matches(config TargetConfig) bool {
|
||||
return m.ApkTargeting == nil ||
|
||||
(abiTargetingMatcher{m.AbiTargeting}.matches(config) &&
|
||||
languageTargetingMatcher{m.LanguageTargeting}.matches(config) &&
|
||||
screenDensityTargetingMatcher{m.ScreenDensityTargeting}.matches(config) &&
|
||||
sdkVersionTargetingMatcher{m.SdkVersionTargeting}.matches(config) &&
|
||||
multiAbiTargetingMatcher{m.MultiAbiTargeting}.matches(config))
|
||||
}
|
||||
|
||||
type languageTargetingMatcher struct {
|
||||
*android_bundle_proto.LanguageTargeting
|
||||
}
|
||||
|
||||
func (m languageTargetingMatcher) matches(_ TargetConfig) bool {
|
||||
if m.LanguageTargeting == nil {
|
||||
return true
|
||||
}
|
||||
log.Fatal("language based entry selection is not implemented")
|
||||
return false
|
||||
}
|
||||
|
||||
type moduleMetadataMatcher struct {
|
||||
*android_bundle_proto.ModuleMetadata
|
||||
}
|
||||
|
||||
func (m moduleMetadataMatcher) matches(config TargetConfig) bool {
|
||||
return m.ModuleMetadata == nil ||
|
||||
(m.GetDeliveryType() == android_bundle_proto.DeliveryType_INSTALL_TIME &&
|
||||
moduleTargetingMatcher{m.Targeting}.matches(config) &&
|
||||
!m.IsInstant)
|
||||
}
|
||||
|
||||
type moduleTargetingMatcher struct {
|
||||
*android_bundle_proto.ModuleTargeting
|
||||
}
|
||||
|
||||
func (m moduleTargetingMatcher) matches(config TargetConfig) bool {
|
||||
return m.ModuleTargeting == nil ||
|
||||
(sdkVersionTargetingMatcher{m.SdkVersionTargeting}.matches(config) &&
|
||||
userCountriesTargetingMatcher{m.UserCountriesTargeting}.matches(config))
|
||||
}
|
||||
|
||||
type multiAbiTargetingMatcher struct {
|
||||
*android_bundle_proto.MultiAbiTargeting
|
||||
}
|
||||
|
||||
func (t multiAbiTargetingMatcher) matches(_ TargetConfig) bool {
|
||||
if t.MultiAbiTargeting == nil {
|
||||
return true
|
||||
}
|
||||
log.Fatal("multiABI based selection is not implemented")
|
||||
return false
|
||||
}
|
||||
|
||||
type screenDensityTargetingMatcher struct {
|
||||
*android_bundle_proto.ScreenDensityTargeting
|
||||
}
|
||||
|
||||
func (m screenDensityTargetingMatcher) matches(config TargetConfig) bool {
|
||||
if m.ScreenDensityTargeting == nil {
|
||||
return true
|
||||
}
|
||||
if _, ok := config.screenDpi[android_bundle_proto.ScreenDensity_DENSITY_UNSPECIFIED]; ok {
|
||||
return true
|
||||
}
|
||||
for _, v := range m.GetValue() {
|
||||
switch x := v.GetDensityOneof().(type) {
|
||||
case *android_bundle_proto.ScreenDensity_DensityAlias_:
|
||||
if _, ok := config.screenDpi[x.DensityAlias]; ok {
|
||||
return true
|
||||
}
|
||||
default:
|
||||
log.Fatal("For screen density, only DPI name based entry selection (e.g. HDPI, XHDPI) is implemented")
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type sdkVersionTargetingMatcher struct {
|
||||
*android_bundle_proto.SdkVersionTargeting
|
||||
}
|
||||
|
||||
func (m sdkVersionTargetingMatcher) matches(config TargetConfig) bool {
|
||||
const preReleaseVersion = 10000
|
||||
if m.SdkVersionTargeting == nil {
|
||||
return true
|
||||
}
|
||||
if len(m.Value) > 1 {
|
||||
log.Fatal(fmt.Sprintf("sdk_version_targeting should not have multiple values:%#v", m.Value))
|
||||
}
|
||||
// Inspect only sdkVersionTargeting.Value.
|
||||
// Even though one of the SdkVersionTargeting.Alternatives values may be
|
||||
// better matching, we will select all of them
|
||||
return m.Value[0].Min == nil ||
|
||||
m.Value[0].Min.Value <= config.sdkVersion ||
|
||||
(config.allowPrereleased && m.Value[0].Min.Value == preReleaseVersion)
|
||||
}
|
||||
|
||||
type textureCompressionFormatTargetingMatcher struct {
|
||||
*android_bundle_proto.TextureCompressionFormatTargeting
|
||||
}
|
||||
|
||||
func (m textureCompressionFormatTargetingMatcher) matches(_ TargetConfig) bool {
|
||||
if m.TextureCompressionFormatTargeting == nil {
|
||||
return true
|
||||
}
|
||||
log.Fatal("texture based entry selection is not implemented")
|
||||
return false
|
||||
}
|
||||
|
||||
type userCountriesTargetingMatcher struct {
|
||||
*android_bundle_proto.UserCountriesTargeting
|
||||
}
|
||||
|
||||
func (m userCountriesTargetingMatcher) matches(_ TargetConfig) bool {
|
||||
if m.UserCountriesTargeting == nil {
|
||||
return true
|
||||
}
|
||||
log.Fatal("country based entry selection is not implemented")
|
||||
return false
|
||||
}
|
||||
|
||||
type variantTargetingMatcher struct {
|
||||
*android_bundle_proto.VariantTargeting
|
||||
}
|
||||
|
||||
func (m variantTargetingMatcher) matches(config TargetConfig) bool {
|
||||
if m.VariantTargeting == nil {
|
||||
return true
|
||||
}
|
||||
return sdkVersionTargetingMatcher{m.SdkVersionTargeting}.matches(config) &&
|
||||
abiTargetingMatcher{m.AbiTargeting}.matches(config) &&
|
||||
multiAbiTargetingMatcher{m.MultiAbiTargeting}.matches(config) &&
|
||||
screenDensityTargetingMatcher{m.ScreenDensityTargeting}.matches(config) &&
|
||||
textureCompressionFormatTargetingMatcher{m.TextureCompressionFormatTargeting}.matches(config)
|
||||
}
|
||||
|
||||
type SelectionResult struct {
|
||||
moduleName string
|
||||
entries []string
|
||||
}
|
||||
|
||||
// Return all entries matching target configuration
|
||||
func selectApks(toc Toc, targetConfig TargetConfig) SelectionResult {
|
||||
var result SelectionResult
|
||||
for _, variant := range (*toc).GetVariant() {
|
||||
if !(variantTargetingMatcher{variant.GetTargeting()}.matches(targetConfig)) {
|
||||
continue
|
||||
}
|
||||
for _, as := range variant.GetApkSet() {
|
||||
if !(moduleMetadataMatcher{as.ModuleMetadata}.matches(targetConfig)) {
|
||||
continue
|
||||
}
|
||||
for _, apkdesc := range as.GetApkDescription() {
|
||||
if (apkDescriptionMatcher{apkdesc}).matches(targetConfig) {
|
||||
result.entries = append(result.entries, apkdesc.GetPath())
|
||||
// TODO(asmundak): As it turns out, moduleName which we get from
|
||||
// the ModuleMetadata matches the module names of the generated
|
||||
// entry paths just by coincidence, only for the split APKs. We
|
||||
// need to discuss this with bundletool folks.
|
||||
result.moduleName = as.GetModuleMetadata().GetName()
|
||||
}
|
||||
}
|
||||
// we allow only a single module, so bail out here if we found one
|
||||
if result.moduleName != "" {
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
type Zip2ZipWriter interface {
|
||||
CopyFrom(file *zip.File, name string) error
|
||||
}
|
||||
|
||||
// Writes out selected entries, renaming them as needed
|
||||
func (apkSet *ApkSet) writeApks(selected SelectionResult, config TargetConfig,
|
||||
writer Zip2ZipWriter) error {
|
||||
// Renaming rules:
|
||||
// splits/MODULE-master.apk to STEM.apk
|
||||
// else
|
||||
// splits/MODULE-*.apk to STEM>-$1.apk
|
||||
// TODO(asmundak):
|
||||
// add more rules, for .apex files
|
||||
renameRules := []struct {
|
||||
rex *regexp.Regexp
|
||||
repl string
|
||||
}{
|
||||
{
|
||||
regexp.MustCompile(`^.*/` + selected.moduleName + `-master\.apk$`),
|
||||
config.stem + `.apk`,
|
||||
},
|
||||
{
|
||||
regexp.MustCompile(`^.*/` + selected.moduleName + `(-.*\.apk)$`),
|
||||
config.stem + `$1`,
|
||||
},
|
||||
}
|
||||
renamer := func(path string) (string, bool) {
|
||||
for _, rr := range renameRules {
|
||||
if rr.rex.MatchString(path) {
|
||||
return rr.rex.ReplaceAllString(path, rr.repl), true
|
||||
}
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
entryOrigin := make(map[string]string) // output entry to input entry
|
||||
for _, apk := range selected.entries {
|
||||
apkFile, ok := apkSet.entries[apk]
|
||||
if !ok {
|
||||
return fmt.Errorf("TOC refers to an entry %s which does not exist", apk)
|
||||
}
|
||||
inName := apkFile.Name
|
||||
outName, ok := renamer(inName)
|
||||
if !ok {
|
||||
log.Fatalf("selected an entry with unexpected name %s", inName)
|
||||
}
|
||||
if origin, ok := entryOrigin[inName]; ok {
|
||||
log.Fatalf("selected entries %s and %s will have the same output name %s",
|
||||
origin, inName, outName)
|
||||
}
|
||||
entryOrigin[outName] = inName
|
||||
if err := writer.CopyFrom(apkFile, outName); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Arguments parsing
|
||||
var (
|
||||
outputZip = flag.String("o", "", "output zip containing extracted entries")
|
||||
targetConfig = TargetConfig{
|
||||
screenDpi: map[android_bundle_proto.ScreenDensity_DensityAlias]bool{},
|
||||
abis: map[android_bundle_proto.Abi_AbiAlias]bool{},
|
||||
}
|
||||
)
|
||||
|
||||
// Parse abi values
|
||||
type abiFlagValue struct {
|
||||
targetConfig *TargetConfig
|
||||
}
|
||||
|
||||
func (a abiFlagValue) String() string {
|
||||
return "all"
|
||||
}
|
||||
|
||||
func (a abiFlagValue) Set(abiList string) error {
|
||||
if abiList == "none" {
|
||||
return nil
|
||||
}
|
||||
if abiList == "all" {
|
||||
targetConfig.abis[android_bundle_proto.Abi_UNSPECIFIED_CPU_ARCHITECTURE] = true
|
||||
return nil
|
||||
}
|
||||
for _, abi := range strings.Split(abiList, ",") {
|
||||
v, ok := android_bundle_proto.Abi_AbiAlias_value[abi]
|
||||
if !ok {
|
||||
return fmt.Errorf("bad ABI value: %q", abi)
|
||||
}
|
||||
targetConfig.abis[android_bundle_proto.Abi_AbiAlias(v)] = true
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Parse screen density values
|
||||
type screenDensityFlagValue struct {
|
||||
targetConfig *TargetConfig
|
||||
}
|
||||
|
||||
func (s screenDensityFlagValue) String() string {
|
||||
return "none"
|
||||
}
|
||||
|
||||
func (s screenDensityFlagValue) Set(densityList string) error {
|
||||
if densityList == "none" {
|
||||
return nil
|
||||
}
|
||||
if densityList == "all" {
|
||||
targetConfig.screenDpi[android_bundle_proto.ScreenDensity_DENSITY_UNSPECIFIED] = true
|
||||
return nil
|
||||
}
|
||||
for _, density := range strings.Split(densityList, ",") {
|
||||
v, found := android_bundle_proto.ScreenDensity_DensityAlias_value[density]
|
||||
if !found {
|
||||
return fmt.Errorf("bad screen density value: %q", density)
|
||||
}
|
||||
targetConfig.screenDpi[android_bundle_proto.ScreenDensity_DensityAlias(v)] = true
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func processArgs() {
|
||||
flag.Usage = func() {
|
||||
fmt.Fprintln(os.Stderr, `usage: extract_apks -o <output-zip> -sdk-version value -abis value -screen-densities value <APK set>`)
|
||||
flag.PrintDefaults()
|
||||
os.Exit(2)
|
||||
}
|
||||
version := flag.Uint("sdk-version", 0, "SDK version")
|
||||
flag.Var(abiFlagValue{&targetConfig}, "abis",
|
||||
"'all' or comma-separated ABIs list of ARMEABI ARMEABI_V7A ARM64_V8A X86 X86_64 MIPS MIPS64")
|
||||
flag.Var(screenDensityFlagValue{&targetConfig}, "screen-densities",
|
||||
"'all' or comma-separated list of screen density names (NODPI LDPI MDPI TVDPI HDPI XHDPI XXHDPI XXXHDPI)")
|
||||
flag.BoolVar(&targetConfig.allowPrereleased, "allow-prereleased", false,
|
||||
"allow prereleased")
|
||||
flag.StringVar(&targetConfig.stem, "stem", "", "output entries base name")
|
||||
flag.Parse()
|
||||
if (*outputZip == "") || len(flag.Args()) != 1 || *version == 0 || targetConfig.stem == "" {
|
||||
flag.Usage()
|
||||
}
|
||||
targetConfig.sdkVersion = int32(*version)
|
||||
|
||||
}
|
||||
|
||||
func main() {
|
||||
processArgs()
|
||||
var toc Toc
|
||||
apkSet, err := newApkSet(flag.Arg(0))
|
||||
if err == nil {
|
||||
defer apkSet.close()
|
||||
toc, err = apkSet.getToc()
|
||||
}
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
sel := selectApks(toc, targetConfig)
|
||||
if len(sel.entries) == 0 {
|
||||
log.Fatalf("there are no entries for the target configuration: %#v", targetConfig)
|
||||
}
|
||||
|
||||
outFile, err := os.Create(*outputZip)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer outFile.Close()
|
||||
writer := zip.NewWriter(outFile)
|
||||
defer func() {
|
||||
if err := writer.Close(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}()
|
||||
if err = apkSet.writeApks(sel, targetConfig, writer); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
246
cmd/extract_apks/main_test.go
Normal file
246
cmd/extract_apks/main_test.go
Normal file
|
@ -0,0 +1,246 @@
|
|||
// Copyright 2020 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
bp "android/soong/cmd/extract_apks/bundle_proto"
|
||||
"android/soong/third_party/zip"
|
||||
)
|
||||
|
||||
type TestConfigDesc struct {
|
||||
name string
|
||||
targetConfig TargetConfig
|
||||
expected SelectionResult
|
||||
}
|
||||
|
||||
type TestDesc struct {
|
||||
protoText string
|
||||
configs []TestConfigDesc
|
||||
}
|
||||
|
||||
var (
|
||||
testCases = []TestDesc{
|
||||
{
|
||||
protoText: `
|
||||
variant {
|
||||
targeting {
|
||||
sdk_version_targeting {
|
||||
value { min { value: 29 } } } }
|
||||
apk_set {
|
||||
module_metadata {
|
||||
name: "base" targeting {} delivery_type: INSTALL_TIME }
|
||||
apk_description {
|
||||
targeting {
|
||||
screen_density_targeting {
|
||||
value { density_alias: LDPI } }
|
||||
sdk_version_targeting {
|
||||
value { min { value: 21 } } } }
|
||||
path: "splits/base-ldpi.apk"
|
||||
split_apk_metadata { split_id: "config.ldpi" } }
|
||||
apk_description {
|
||||
targeting {
|
||||
screen_density_targeting {
|
||||
value { density_alias: MDPI } }
|
||||
sdk_version_targeting {
|
||||
value { min { value: 21 } } } }
|
||||
path: "splits/base-mdpi.apk"
|
||||
split_apk_metadata { split_id: "config.mdpi" } }
|
||||
apk_description {
|
||||
targeting {
|
||||
sdk_version_targeting {
|
||||
value { min { value: 21 } } } }
|
||||
path: "splits/base-master.apk"
|
||||
split_apk_metadata { is_master_split: true } }
|
||||
apk_description {
|
||||
targeting {
|
||||
abi_targeting {
|
||||
value { alias: ARMEABI_V7A } }
|
||||
sdk_version_targeting {
|
||||
value { min { value: 21 } } } }
|
||||
path: "splits/base-armeabi_v7a.apk"
|
||||
split_apk_metadata { split_id: "config.armeabi_v7a" } }
|
||||
apk_description {
|
||||
targeting {
|
||||
abi_targeting {
|
||||
value { alias: ARM64_V8A } }
|
||||
sdk_version_targeting {
|
||||
value { min { value: 21 } } } }
|
||||
path: "splits/base-arm64_v8a.apk"
|
||||
split_apk_metadata { split_id: "config.arm64_v8a" } }
|
||||
apk_description {
|
||||
targeting {
|
||||
abi_targeting {
|
||||
value { alias: X86 } }
|
||||
sdk_version_targeting {
|
||||
value { min { value: 21 } } } }
|
||||
path: "splits/base-x86.apk"
|
||||
split_apk_metadata { split_id: "config.x86" } }
|
||||
apk_description {
|
||||
targeting {
|
||||
abi_targeting {
|
||||
value { alias: X86_64 } }
|
||||
sdk_version_targeting {
|
||||
value { min { value: 21 } } } }
|
||||
path: "splits/base-x86_64.apk"
|
||||
split_apk_metadata { split_id: "config.x86_64" } } }
|
||||
}
|
||||
bundletool {
|
||||
version: "0.10.3" }
|
||||
|
||||
`,
|
||||
configs: []TestConfigDesc{
|
||||
{
|
||||
name: "one",
|
||||
targetConfig: TargetConfig{
|
||||
sdkVersion: 29,
|
||||
screenDpi: map[bp.ScreenDensity_DensityAlias]bool{
|
||||
bp.ScreenDensity_DENSITY_UNSPECIFIED: true,
|
||||
},
|
||||
abis: map[bp.Abi_AbiAlias]bool{
|
||||
bp.Abi_ARMEABI_V7A: true,
|
||||
bp.Abi_ARM64_V8A: true,
|
||||
},
|
||||
},
|
||||
expected: SelectionResult{
|
||||
"base",
|
||||
[]string{
|
||||
"splits/base-ldpi.apk",
|
||||
"splits/base-mdpi.apk",
|
||||
"splits/base-master.apk",
|
||||
"splits/base-armeabi_v7a.apk",
|
||||
"splits/base-arm64_v8a.apk",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "two",
|
||||
targetConfig: TargetConfig{
|
||||
sdkVersion: 29,
|
||||
screenDpi: map[bp.ScreenDensity_DensityAlias]bool{
|
||||
bp.ScreenDensity_LDPI: true,
|
||||
},
|
||||
abis: map[bp.Abi_AbiAlias]bool{},
|
||||
},
|
||||
expected: SelectionResult{
|
||||
"base",
|
||||
[]string{
|
||||
"splits/base-ldpi.apk",
|
||||
"splits/base-master.apk",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "three",
|
||||
targetConfig: TargetConfig{
|
||||
sdkVersion: 20,
|
||||
screenDpi: map[bp.ScreenDensity_DensityAlias]bool{
|
||||
bp.ScreenDensity_LDPI: true,
|
||||
},
|
||||
abis: map[bp.Abi_AbiAlias]bool{},
|
||||
},
|
||||
expected: SelectionResult{
|
||||
"",
|
||||
nil,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
protoText: `
|
||||
variant {
|
||||
targeting {
|
||||
sdk_version_targeting {
|
||||
value { min { value: 10000 } } } }
|
||||
apk_set {
|
||||
module_metadata {
|
||||
name: "base" targeting {} delivery_type: INSTALL_TIME }
|
||||
apk_description {
|
||||
targeting {
|
||||
sdk_version_targeting {
|
||||
value { min { value: 21 } } } }
|
||||
path: "splits/base-master.apk"
|
||||
split_apk_metadata { is_master_split: true } } } }`,
|
||||
configs: []TestConfigDesc{
|
||||
{
|
||||
name: "Prerelease",
|
||||
targetConfig: TargetConfig{
|
||||
sdkVersion: 30,
|
||||
screenDpi: map[bp.ScreenDensity_DensityAlias]bool{},
|
||||
abis: map[bp.Abi_AbiAlias]bool{},
|
||||
allowPrereleased: true,
|
||||
},
|
||||
expected: SelectionResult{
|
||||
"base",
|
||||
[]string{"splits/base-master.apk"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func TestSelectApks(t *testing.T) {
|
||||
for _, testCase := range testCases {
|
||||
var toc bp.BuildApksResult
|
||||
if err := proto.UnmarshalText(testCase.protoText, &toc); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, config := range testCase.configs {
|
||||
actual := selectApks(&toc, config.targetConfig)
|
||||
if !reflect.DeepEqual(config.expected, actual) {
|
||||
t.Errorf("%s: expected %v, got %v", config.name, config.expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type testZip2ZipWriter struct {
|
||||
entries map[string]string
|
||||
}
|
||||
|
||||
func (w testZip2ZipWriter) CopyFrom(file *zip.File, out string) error {
|
||||
if x, ok := w.entries[out]; ok {
|
||||
return fmt.Errorf("%s and %s both write to %s", x, file.Name, out)
|
||||
}
|
||||
w.entries[out] = file.Name
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestWriteZip(t *testing.T) {
|
||||
// what we write from what
|
||||
expected := map[string]string{
|
||||
"Foo.apk": "splits/mybase-master.apk",
|
||||
"Foo-xhdpi.apk": "splits/mybase-xhdpi.apk",
|
||||
}
|
||||
apkSet := ApkSet{entries: make(map[string]*zip.File)}
|
||||
sel := SelectionResult{moduleName: "mybase"}
|
||||
for _, in := range expected {
|
||||
apkSet.entries[in] = &zip.File{FileHeader: zip.FileHeader{Name: in}}
|
||||
sel.entries = append(sel.entries, in)
|
||||
}
|
||||
writer := testZip2ZipWriter{make(map[string]string)}
|
||||
config := TargetConfig{stem: "Foo"}
|
||||
if err := apkSet.writeApks(sel, config, writer); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if !reflect.DeepEqual(expected, writer.entries) {
|
||||
t.Errorf("expected %v, got %v", expected, writer.entries)
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue