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