Implement extract_apks

Bug: 152319766
Test: manual and builtin
Change-Id: Ia15d66e86c7bcfd52f5b776173ca1665b68ff438
diff --git a/cmd/extract_apks/bundle_proto/commands.proto b/cmd/extract_apks/bundle_proto/commands.proto
new file mode 100644
index 0000000..b36340b
--- /dev/null
+++ b/cmd/extract_apks/bundle_proto/commands.proto
@@ -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;
+}