use of com.android.tools.build.bundletool.device.AdbServer in project bundletool by google.
the class InstallApksCommandTest method badAbisDevice_throws.
@Test
@Theory
public void badAbisDevice_throws(@FromDataPoints("apksInDirectory") boolean apksInDirectory) throws Exception {
Path apksFile = createApks(createSimpleTableOfContent(ZipPath.create("base-master.apk")), apksInDirectory);
DeviceSpec deviceSpec = mergeSpecs(sdkVersion(21), density(480), abis(), locales("en-US"));
FakeDevice fakeDevice = FakeDevice.fromDeviceSpec(DEVICE_ID, DeviceState.ONLINE, deviceSpec);
AdbServer adbServer = new FakeAdbServer(/* hasInitialDeviceList= */
true, ImmutableList.of(fakeDevice));
InstallApksCommand command = InstallApksCommand.builder().setApksArchivePath(apksFile).setAdbPath(adbPath).setAdbServer(adbServer).build();
Throwable exception = assertThrows(IllegalStateException.class, () -> command.execute());
assertThat(exception).hasMessageThat().contains("Error retrieving device ABIs");
}
use of com.android.tools.build.bundletool.device.AdbServer in project bundletool by google.
the class InstallApksCommandTest method incompleteApksFile_missingAbiSplitMatchedForDevice_throws.
@Test
public void incompleteApksFile_missingAbiSplitMatchedForDevice_throws() throws Exception {
// Partial APK Set file where 'x86' split is included and 'x86_64' split is not included because
// device spec sent to 'build-apks' command doesn't support it.
// Next, device spec that should be matched to 'x86_64' split is provided to 'install-apks'
// command and command must throw IncompatibleDeviceException as mathed split 'x86_64' is not
// available.
BuildApksResult tableOfContent = BuildApksResult.newBuilder().setBundletool(Bundletool.newBuilder().setVersion(BundleToolVersion.getCurrentVersion().toString())).addVariant(createVariant(VariantTargeting.getDefaultInstance(), createSplitApkSet(/* moduleName= */
"base", createMasterApkDescription(ApkTargeting.getDefaultInstance(), ZipPath.create("base-master.apk")), splitApkDescription(apkAbiTargeting(X86, ImmutableSet.of(X86_64)), ZipPath.create("base-x86.apk"))))).build();
Path apksFile = createApks(tableOfContent, /* apksInDirectory= */
false);
DeviceSpec deviceSpec = mergeSpecs(sdkVersion(21), density(DensityAlias.MDPI), abis("x86_64", "x86"), locales("en-US"));
FakeDevice fakeDevice = FakeDevice.fromDeviceSpec(DEVICE_ID, DeviceState.ONLINE, deviceSpec);
AdbServer adbServer = new FakeAdbServer(/* hasInitialDeviceList= */
true, ImmutableList.of(fakeDevice));
InstallApksCommand command = InstallApksCommand.builder().setApksArchivePath(apksFile).setAdbPath(adbPath).setAdbServer(adbServer).build();
Throwable exception = assertThrows(IncompatibleDeviceException.class, command::execute);
assertThat(exception).hasMessageThat().contains("Missing APKs for [ABI] dimensions in the module 'base' for the provided device.");
}
use of com.android.tools.build.bundletool.device.AdbServer in project bundletool by google.
the class InstallApksCommandTest method moduleDependencies_diamondGraph.
@Test
@Theory
public void moduleDependencies_diamondGraph(@FromDataPoints("apksInDirectory") boolean apksInDirectory) throws Exception {
BuildApksResult tableOfContent = BuildApksResult.newBuilder().setBundletool(Bundletool.newBuilder().setVersion(BundleToolVersion.getCurrentVersion().toString())).addVariant(createVariant(VariantTargeting.getDefaultInstance(), createSplitApkSet(/* moduleName= */
"base", createMasterApkDescription(ApkTargeting.getDefaultInstance(), ZipPath.create("base-master.apk"))), createSplitApkSet(/* moduleName= */
"feature1", DeliveryType.ON_DEMAND, /* moduleDependencies= */
ImmutableList.of(), createMasterApkDescription(ApkTargeting.getDefaultInstance(), ZipPath.create("feature1-master.apk"))), createSplitApkSet(/* moduleName= */
"feature2", DeliveryType.ON_DEMAND, /* moduleDependencies= */
ImmutableList.of("feature1"), createMasterApkDescription(ApkTargeting.getDefaultInstance(), ZipPath.create("feature2-master.apk"))), createSplitApkSet(/* moduleName= */
"feature3", DeliveryType.ON_DEMAND, /* moduleDependencies= */
ImmutableList.of("feature1"), createMasterApkDescription(ApkTargeting.getDefaultInstance(), ZipPath.create("feature3-master.apk"))), createSplitApkSet(/* moduleName= */
"feature4", DeliveryType.ON_DEMAND, /* moduleDependencies= */
ImmutableList.of("feature2", "feature3"), createMasterApkDescription(ApkTargeting.getDefaultInstance(), ZipPath.create("feature4-master.apk"))))).build();
Path apksFile = createApks(tableOfContent, apksInDirectory);
List<Path> installedApks = new ArrayList<>();
FakeDevice fakeDevice = FakeDevice.fromDeviceSpec(DEVICE_ID, DeviceState.ONLINE, lDeviceWithLocales("en-US"));
AdbServer adbServer = new FakeAdbServer(/* hasInitialDeviceList= */
true, ImmutableList.of(fakeDevice));
fakeDevice.setInstallApksSideEffect((apks, installOptions) -> installedApks.addAll(apks));
InstallApksCommand.builder().setApksArchivePath(apksFile).setAdbPath(adbPath).setAdbServer(adbServer).setModules(ImmutableSet.of("feature4")).build().execute();
assertThat(getFileNames(installedApks)).containsExactly("base-master.apk", "feature1-master.apk", "feature2-master.apk", "feature3-master.apk", "feature4-master.apk");
}
use of com.android.tools.build.bundletool.device.AdbServer in project bundletool by google.
the class InstallMultiApksCommand method execute.
public void execute() throws TimeoutException, IOException {
validateInput();
AdbServer adbServer = getAdbServer();
adbServer.init(getAdbPath());
try (TempDirectory tempDirectory = new TempDirectory()) {
DeviceAnalyzer deviceAnalyzer = new DeviceAnalyzer(adbServer);
DeviceSpec deviceSpec = deviceAnalyzer.getDeviceSpec(getDeviceId());
Device device = deviceAnalyzer.getAndValidateDevice(getDeviceId());
if (getTimeout().isPresent() && !device.getVersion().isGreaterOrEqualThan(Versions.ANDROID_S_API_VERSION)) {
throw InvalidCommandException.builder().withInternalMessage("'%s' flag is supported for Android 12+ devices.", TIMEOUT_MILLIS_FLAG.getName()).build();
}
Path aapt2Dir = tempDirectory.getPath().resolve("aapt2");
Files.createDirectory(aapt2Dir);
Supplier<Aapt2Command> aapt2CommandSupplier = Suppliers.memoize(() -> getOrExtractAapt2Command(aapt2Dir));
ImmutableMap<String, InstalledPackageInfo> existingPackages = getPackagesInstalledOnDevice(device);
ImmutableList<PackagePathVersion> installableApksFilesWithBadgingInfo = getActualApksPaths(tempDirectory).stream().flatMap(apksArchivePath -> stream(apksWithPackageName(apksArchivePath, deviceSpec, aapt2CommandSupplier))).filter(apks -> shouldInstall(apks, existingPackages)).collect(toImmutableList());
ImmutableList<PackagePathVersion> apkFilesToInstall = uniqueApksByPackageName(installableApksFilesWithBadgingInfo).stream().flatMap(apks -> extractApkListFromApks(deviceSpec, apks, Optional.ofNullable(existingPackages.get(apks.getPackageName())), tempDirectory).stream()).collect(toImmutableList());
ImmutableListMultimap<String, String> apkToInstallByPackage = apkFilesToInstall.stream().collect(toImmutableListMultimap(PackagePathVersion::getPackageName, packagePathVersion -> packagePathVersion.getPath().toAbsolutePath().toString()));
if (apkFilesToInstall.isEmpty()) {
logger.warning("No packages found to install! Exiting...");
return;
}
AdbCommand adbCommand = getOrCreateAdbCommand();
ImmutableList<String> commandResults = adbCommand.installMultiPackage(apkToInstallByPackage, getStaged(), getEnableRollback(), getTimeout(), getDeviceId());
logger.info(String.format("Output:\n%s", String.join("\n", commandResults)));
logger.info("Please reboot device to complete installation.");
}
}
use of com.android.tools.build.bundletool.device.AdbServer in project bundletool by google.
the class BundleToolMain method main.
/**
* Parses the flags and routes to the appropriate command handler.
*/
static void main(String[] args, Runtime runtime) {
final ParsedFlags flags;
try {
flags = new FlagParser().parse(args);
} catch (FlagParser.FlagParseException e) {
System.err.println("Error while parsing the flags: " + e.getMessage());
runtime.exit(1);
return;
}
Optional<String> command = flags.getMainCommand();
if (!command.isPresent()) {
System.err.println("Error: You have to specify a command.");
help();
runtime.exit(1);
return;
}
try {
switch(command.get()) {
case BuildBundleCommand.COMMAND_NAME:
BuildBundleCommand.fromFlags(flags).execute();
break;
case BuildApksCommand.COMMAND_NAME:
try (AdbServer adbServer = DdmlibAdbServer.getInstance()) {
BuildApksCommand.fromFlags(flags, adbServer).execute();
}
break;
case ExtractApksCommand.COMMAND_NAME:
ExtractApksCommand.fromFlags(flags).execute();
break;
case GetDeviceSpecCommand.COMMAND_NAME:
// We have to destroy ddmlib resources at the end of the command.
try (AdbServer adbServer = DdmlibAdbServer.getInstance()) {
GetDeviceSpecCommand.fromFlags(flags, adbServer).execute();
}
break;
case InstallApksCommand.COMMAND_NAME:
try (AdbServer adbServer = DdmlibAdbServer.getInstance()) {
InstallApksCommand.fromFlags(flags, adbServer).execute();
}
break;
case InstallMultiApksCommand.COMMAND_NAME:
try (AdbServer adbServer = DdmlibAdbServer.getInstance()) {
InstallMultiApksCommand.fromFlags(flags, adbServer).execute();
}
break;
case ValidateBundleCommand.COMMAND_NAME:
ValidateBundleCommand.fromFlags(flags).execute();
break;
case DumpCommand.COMMAND_NAME:
DumpCommand.fromFlags(flags).execute();
break;
case GetSizeCommand.COMMAND_NAME:
GetSizeCommand.fromFlags(flags).execute();
break;
case VersionCommand.COMMAND_NAME:
VersionCommand.fromFlags(flags, System.out).execute();
break;
case AddTransparencyCommand.COMMAND_NAME:
AddTransparencyCommand.fromFlags(flags).execute();
break;
case CheckTransparencyCommand.COMMAND_NAME:
try (AdbServer adbServer = DdmlibAdbServer.getInstance()) {
CheckTransparencyCommand.fromFlags(flags, adbServer).execute();
}
break;
case HELP_CMD:
if (flags.getSubCommand().isPresent()) {
help(flags.getSubCommand().get(), runtime);
} else {
help();
}
break;
default:
System.err.printf("Error: Unrecognized command '%s'.%n%n%n", command.get());
help();
runtime.exit(1);
return;
}
} catch (Exception e) {
System.err.println("[BT:" + BundleToolVersion.getCurrentVersion() + "] Error: " + e.getMessage());
e.printStackTrace();
runtime.exit(1);
return;
}
// Takes care of shutting down non-daemon threads in internal thread pools.
runtime.exit(0);
}
Aggregations