Skip to content

Commit f6996b0

Browse files
DeviceInfracopybara-github
authored andcommitted
Internal change
PiperOrigin-RevId: 875103505
1 parent c578e7d commit f6996b0

File tree

5 files changed

+515
-0
lines changed

5 files changed

+515
-0
lines changed

src/java/com/google/devtools/mobileharness/api/model/error/AndroidErrorId.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -796,6 +796,11 @@ public enum AndroidErrorId implements ErrorId {
796796
ADB_SHELL_COMMAND_EMPTY_ARGS(150_801, ErrorType.CUSTOMER_ISSUE),
797797
ADB_SHELL_COMMAND_INVALID_ARGS(150_802, ErrorType.CUSTOMER_ISSUE),
798798

799+
// Bundletool: 150_901 ~ 151_000
800+
ANDROID_BUNDLETOOL_COMMAND_START_ERROR(150_901, ErrorType.INFRA_ISSUE),
801+
ANDROID_BUNDLETOOL_COMMAND_EXEC_ERROR(150_902, ErrorType.CUSTOMER_ISSUE),
802+
ANDROID_BUNDLETOOL_COMMAND_TIMEOUT(150_903, ErrorType.DEPENDENCY_ISSUE),
803+
799804
// ***********************************************************************************************
800805
// Other Variant Android Platforms: 170_001 ~ 200_000
801806
// ***********************************************************************************************
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Copyright 2022 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
#
15+
16+
load("@rules_java//java:defs.bzl", "java_library")
17+
18+
package(default_applicable_licenses = ["//:license"])
19+
20+
java_library(
21+
name = "bundletool",
22+
srcs = glob(["*.java"]),
23+
resources = [
24+
],
25+
visibility = [
26+
"//:deviceinfra_all_pkg",
27+
"//:omnilab_fusion",
28+
],
29+
deps = [
30+
"//src/java/com/google/devtools/deviceinfra/platform/android/lightning/internal/sdk/adb",
31+
"//src/java/com/google/devtools/mobileharness/api/model/error",
32+
"//src/java/com/google/devtools/mobileharness/shared/util/auto:auto_value",
33+
"//src/java/com/google/devtools/mobileharness/shared/util/command",
34+
"//src/java/com/google/devtools/mobileharness/shared/util/error:more_throwables",
35+
"//src/java/com/google/devtools/mobileharness/shared/util/file/local:res_util",
36+
"//src/java/com/google/devtools/mobileharness/shared/util/logging:google_logger",
37+
"//src/java/com/google/devtools/mobileharness/shared/util/system",
38+
"//src/java/com/google/wireless/qa/mobileharness/shared/android:aapt",
39+
"@maven//:com_google_errorprone_error_prone_annotations",
40+
"@maven//:com_google_guava_guava",
41+
"@maven//:javax_inject_jsr330_api",
42+
],
43+
)
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
/*
2+
* Copyright 2022 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.devtools.mobileharness.platform.android.lightning.bundletool;
18+
19+
import static com.google.common.base.Preconditions.checkArgument;
20+
21+
import com.google.auto.value.AutoBuilder;
22+
import com.google.common.collect.ImmutableList;
23+
import java.nio.file.Path;
24+
import java.time.Duration;
25+
import java.util.Optional;
26+
27+
/**
28+
* Arguments for {@code bundletool build-apks}.
29+
*
30+
* <p>See https://developer.android.com/tools/bundletool for detailed usage of each argument
31+
*/
32+
public record BuildApksArgs(
33+
Path bundle,
34+
Path output,
35+
OutputFormat outputFormat,
36+
boolean connectedDevice,
37+
String deviceId,
38+
boolean overwrite,
39+
Optional<Path> keystore,
40+
String keystorePassword,
41+
String keystoreKeyAlias,
42+
String keystoreKeyPassword,
43+
Optional<Path> lineage,
44+
Duration commandTimeout) {
45+
46+
enum OutputFormat {
47+
APK_SET("apk_set"),
48+
DIRECTORY("directory");
49+
50+
private final String flagValue;
51+
52+
OutputFormat(String flagValue) {
53+
this.flagValue = flagValue;
54+
}
55+
56+
String getFlagValue() {
57+
return flagValue;
58+
}
59+
}
60+
61+
ImmutableList<String> toBundletoolCommand(String adbPath, String aaptPath) {
62+
ImmutableList.Builder<String> args =
63+
ImmutableList.<String>builder()
64+
.add("build-apks")
65+
.add("--adb=" + adbPath)
66+
.add("--aapt2=" + aaptPath)
67+
.add("--bundle=" + bundle)
68+
.add("--output=" + output)
69+
.add("--output-format=" + outputFormat.getFlagValue());
70+
if (connectedDevice) {
71+
args.add("--connected-device");
72+
}
73+
if (!deviceId.isEmpty()) {
74+
args.add("--device-id=" + deviceId);
75+
}
76+
if (overwrite) {
77+
args.add("--overwrite");
78+
}
79+
keystore.ifPresent(ks -> args.add("--ks=" + ks));
80+
if (!keystorePassword.isEmpty()) {
81+
args.add("--ks-pass=" + keystorePassword);
82+
}
83+
if (!keystoreKeyAlias.isEmpty()) {
84+
args.add("--ks-key-alias=" + keystoreKeyAlias);
85+
}
86+
if (!keystoreKeyPassword.isEmpty()) {
87+
args.add("--key-pass=" + keystoreKeyPassword);
88+
}
89+
lineage.ifPresent(ln -> args.add("--lineage=" + ln));
90+
return args.build();
91+
}
92+
93+
public static Builder builder() {
94+
return new AutoBuilder_BuildApksArgs_Builder()
95+
.setOutputFormat(OutputFormat.APK_SET)
96+
.setConnectedDevice(false)
97+
.setDeviceId("")
98+
.setOverwrite(false)
99+
.setKeystorePassword("")
100+
.setKeystoreKeyAlias("")
101+
.setKeystoreKeyPassword("")
102+
.setCommandTimeout(Duration.ofMinutes(10));
103+
}
104+
105+
/** Builder for {@link BuildApksArgs}. */
106+
@AutoBuilder
107+
public abstract static class Builder {
108+
109+
/** The required Bundle/AAB file to build APKs for. */
110+
public abstract Builder setBundle(Path bundle);
111+
112+
/**
113+
* The required output path for the APKs.
114+
*
115+
* <p>Depending on the output format, this will be a directory or a file.
116+
*/
117+
public abstract Builder setOutput(Path output);
118+
119+
/** Format of the output, either an Apk Set file or a directory (default APK_SET). */
120+
public abstract Builder setOutputFormat(OutputFormat outputFormat);
121+
122+
/** Whether to build APKs optimized for a connected device (default false). */
123+
public abstract Builder setConnectedDevice(boolean connectedDevice);
124+
125+
/** The device ID to build APKs for (default empty). */
126+
public abstract Builder setDeviceId(String deviceId);
127+
128+
/** Whether to overwrite the output file or directory (default false). */
129+
public abstract Builder setOverwrite(boolean overwrite);
130+
131+
/** Keystore file to sign the APKs with (default empty). */
132+
public abstract Builder setKeystore(Path keystore);
133+
134+
/**
135+
* Password of the keystore file (default empty).
136+
*
137+
* <p>Must be in one of two formats:
138+
*
139+
* <ul>
140+
* <li>"pass:<password>" - providing the password in plain text
141+
* <li>"file:<password-file>" - providing the password in a file
142+
* </ul>
143+
*
144+
* <p>Required if {@code keystore} is set.
145+
*/
146+
public abstract Builder setKeystorePassword(String keystorePassword);
147+
148+
/**
149+
* Alias of the key to use in the keystore to sign the APKs (default empty).
150+
*
151+
* <p>Required if {@code keystore} is set.
152+
*/
153+
public abstract Builder setKeystoreKeyAlias(String keystoreKeyAlias);
154+
155+
/**
156+
* The password for the keystore key (default empty).
157+
*
158+
* <p>See {@link #setKeystorePassword(String)} for the format.
159+
*
160+
* <p>Required if {@code keystore} is set.
161+
*/
162+
public abstract Builder setKeystoreKeyPassword(String keystoreKeyPassword);
163+
164+
/** Binary file of SigningCertificateLineage (default absent). */
165+
public abstract Builder setLineage(Path lineage);
166+
167+
/** Timeout for the command (default 10 minutes). */
168+
public abstract Builder setCommandTimeout(Duration commandTimeout);
169+
170+
protected abstract BuildApksArgs autoBuild();
171+
172+
public BuildApksArgs build() {
173+
BuildApksArgs args = autoBuild();
174+
if (args.keystore.isPresent()) {
175+
checkArgument(!args.keystorePassword.isEmpty(), "Keystore password cannot be empty.");
176+
checkArgument(!args.keystoreKeyAlias.isEmpty(), "Keystore key alias cannot be empty.");
177+
checkArgument(
178+
!args.keystoreKeyPassword.isEmpty(), "Keystore key password cannot be empty.");
179+
}
180+
return args;
181+
}
182+
}
183+
}

0 commit comments

Comments
 (0)