Reverted aapt dependency to be a dependency on libandroidfw
Removed call to external aapt2 process
Replaced several layers of error handling with calls to fatal()
Changed output messages for failures to be more useful for diagnostics
Bug: 116753196
Test: mm
Test: adb install -r --fastdeploy --force-agent --local-agent ~/example_apks/example.apk
Test: adb install -r --fastdeploy --no-streaming --force-agent --local-agent ~/example_apks/example.apk
Change-Id: I6006d8aa584e789a086a31e79a41d1416e54402a
diff --git a/adb/Android.bp b/adb/Android.bp
index 6cff0be..f7e5e4e 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -174,6 +174,12 @@
"libdiagnose_usb",
"libmdnssd",
"libusb",
+ "libandroidfw",
+ "libziparchive",
+ "libz",
+ "libutils",
+ "liblog",
+ "libcutils",
],
}
@@ -256,6 +262,12 @@
"liblog",
"libmdnssd",
"libusb",
+ "libandroidfw",
+ "libziparchive",
+ "libz",
+ "libutils",
+ "liblog",
+ "libcutils",
],
stl: "libc++_static",
diff --git a/adb/client/adb_install.cpp b/adb/client/adb_install.cpp
index c00d955..40a0ecd 100644
--- a/adb/client/adb_install.cpp
+++ b/adb/client/adb_install.cpp
@@ -14,31 +14,27 @@
* limitations under the License.
*/
-#define TRACE_TAG ADB
+#include "adb_install.h"
#include <stdio.h>
#include <stdlib.h>
-
-#include "adb.h"
-#include "adb_client.h"
-#include "adb_install.h"
-#include "adb_utils.h"
-#include "client/file_sync_client.h"
-#include "commandline.h"
-#include "fastdeploy.h"
-#include "sysdeps.h"
-
+#include <unistd.h>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
-#include <unistd.h>
-
-#include <android-base/file.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-#include <android-base/test_utils.h>
+#include "adb.h"
+#include "adb_client.h"
+#include "adb_utils.h"
+#include "android-base/file.h"
+#include "android-base/stringprintf.h"
+#include "android-base/strings.h"
+#include "android-base/test_utils.h"
+#include "client/file_sync_client.h"
+#include "commandline.h"
+#include "fastdeploy.h"
+#include "sysdeps.h"
static constexpr int kFastDeployMinApi = 24;
@@ -146,41 +142,16 @@
TemporaryFile patchTmpFile;
FILE* metadataFile = fopen(metadataTmpFile.path, "wb");
- int metadata_len = extract_metadata(file, metadataFile);
+ extract_metadata(file, metadataFile);
fclose(metadataFile);
- int result = -1;
- if (metadata_len <= 0) {
- printf("failed to extract metadata %d\n", metadata_len);
- return 1;
- } else {
- int create_patch_result = create_patch(file, metadataTmpFile.path, patchTmpFile.path);
- if (create_patch_result != 0) {
- printf("Patch creation failure, error code: %d\n", create_patch_result);
- result = create_patch_result;
- goto cleanup_streamed_apk;
- } else {
- std::vector<const char*> pm_args;
- // pass all but 1st (command) and last (apk path) parameters through to pm for
- // session creation
- for (int i = 1; i < argc - 1; i++) {
- pm_args.push_back(argv[i]);
- }
- int apply_patch_result =
- install_patch(file, patchTmpFile.path, pm_args.size(), pm_args.data());
- if (apply_patch_result != 0) {
- printf("Patch application failure, error code: %d\n", apply_patch_result);
- result = apply_patch_result;
- goto cleanup_streamed_apk;
- }
- }
- }
-
- cleanup_streamed_apk:
- if (use_fastdeploy == true) {
- delete_device_patch_file(file);
- }
- return result;
+ create_patch(file, metadataTmpFile.path, patchTmpFile.path);
+ // pass all but 1st (command) and last (apk path) parameters through to pm for
+ // session creation
+ std::vector<const char*> pm_args{argv + 1, argv + argc - 1};
+ install_patch(file, patchTmpFile.path, pm_args.size(), pm_args.data());
+ delete_device_patch_file(file);
+ return 0;
} else {
struct stat sb;
if (stat(file, &sb) == -1) {
@@ -265,29 +236,11 @@
TemporaryFile patchTmpFile;
FILE* metadataFile = fopen(metadataTmpFile.path, "wb");
- int metadata_len = extract_metadata(apk_file[0], metadataFile);
+ extract_metadata(apk_file[0], metadataFile);
fclose(metadataFile);
- if (metadata_len <= 0) {
- printf("failed to extract metadata %d\n", metadata_len);
- return 1;
- } else {
- int create_patch_result =
- create_patch(apk_file[0], metadataTmpFile.path, patchTmpFile.path);
- if (create_patch_result != 0) {
- printf("Patch creation failure, error code: %d\n", create_patch_result);
- result = create_patch_result;
- goto cleanup_apk;
- } else {
- int apply_patch_result =
- apply_patch_on_device(apk_file[0], patchTmpFile.path, apk_dest.c_str());
- if (apply_patch_result != 0) {
- printf("Patch application failure, error code: %d\n", apply_patch_result);
- result = apply_patch_result;
- goto cleanup_apk;
- }
- }
- }
+ create_patch(apk_file[0], metadataTmpFile.path, patchTmpFile.path);
+ apply_patch_on_device(apk_file[0], patchTmpFile.path, apk_dest.c_str());
} else {
if (!do_sync_push(apk_file, apk_dest.c_str(), false)) goto cleanup_apk;
}
@@ -347,7 +300,6 @@
use_localagent = true;
#endif
}
- // TODO: --installlog <filename>
}
if (installMode == INSTALL_DEFAULT) {
diff --git a/adb/client/adb_install.h b/adb/client/adb_install.h
index e9410a9..5b6c4cb 100644
--- a/adb/client/adb_install.h
+++ b/adb/client/adb_install.h
@@ -14,10 +14,9 @@
* limitations under the License.
*/
-#ifndef ADB_INSTALL_H
-#define ADB_INSTALL_H
+#pragma once
-#include "fastdeploy.h"
+#include <string>
int install_app(int argc, const char** argv);
int install_multiple_app(int argc, const char** argv);
@@ -26,4 +25,3 @@
int delete_device_file(const std::string& filename);
int delete_host_file(const std::string& filename);
-#endif
diff --git a/adb/client/fastdeploy.cpp b/adb/client/fastdeploy.cpp
index d3f35c8..183a1fa 100644
--- a/adb/client/fastdeploy.cpp
+++ b/adb/client/fastdeploy.cpp
@@ -14,15 +14,18 @@
* limitations under the License.
*/
-#include <libgen.h>
+#include "fastdeploy.h"
+
#include <algorithm>
#include <array>
+#include <memory>
#include "android-base/file.h"
#include "android-base/strings.h"
+#include "androidfw/ResourceTypes.h"
+#include "androidfw/ZipFileRO.h"
#include "client/file_sync_client.h"
#include "commandline.h"
-#include "fastdeploy.h"
#include "fastdeploycallbacks.h"
#include "utils/String16.h"
@@ -138,60 +141,82 @@
}
}
-static std::string get_aapt2_path() {
- if (g_use_localagent) {
- // This should never happen on a Windows machine
- const char* host_out = getenv("ANDROID_HOST_OUT");
- if (host_out == nullptr) {
- fatal("Could not locate aapt2 because $ANDROID_HOST_OUT is not defined");
- }
- return android::base::StringPrintf("%s/bin/aapt2", host_out);
+static std::string get_string_from_utf16(const char16_t* input, int input_len) {
+ ssize_t utf8_length = utf16_to_utf8_length(input, input_len);
+ if (utf8_length <= 0) {
+ return {};
}
-
- std::string adb_dir = android::base::GetExecutableDirectory();
- if (adb_dir.empty()) {
- fatal("Could not locate aapt2");
- }
- return adb_dir + "/aapt2";
+ std::string utf8;
+ utf8.resize(utf8_length);
+ utf16_to_utf8(input, input_len, &*utf8.begin(), utf8_length + 1);
+ return utf8;
}
-static int system_capture(const char* cmd, std::string& output) {
- FILE* pipe = popen(cmd, "re");
- int fd = -1;
-
- if (pipe != nullptr) {
- fd = fileno(pipe);
- }
-
- if (fd == -1) {
- fatal_errno("Could not create pipe for process '%s'", cmd);
- }
-
- if (!android::base::ReadFdToString(fd, &output)) {
- fatal_errno("Error reading from process '%s'", cmd);
- }
-
- return pclose(pipe);
-}
-
-// output is required to point to a valid output string (non-null)
static std::string get_packagename_from_apk(const char* apkPath) {
- const char* kAapt2DumpNameCommandPattern = R"(%s dump packagename "%s")";
- std::string aapt2_path_string = get_aapt2_path();
- std::string getPackagenameCommand = android::base::StringPrintf(
- kAapt2DumpNameCommandPattern, aapt2_path_string.c_str(), apkPath);
-
- std::string package_name;
- int exit_code = system_capture(getPackagenameCommand.c_str(), package_name);
- if (exit_code != 0) {
- fatal("Error executing '%s' exitcode: %d", getPackagenameCommand.c_str(), exit_code);
+ std::unique_ptr<android::ZipFileRO> zipFile(android::ZipFileRO::open(apkPath));
+ if (zipFile == nullptr) {
+ fatal("Could not open %s", apkPath);
}
-
- // strip any line end characters from the output
- return android::base::Trim(package_name);
+ android::ZipEntryRO entry = zipFile->findEntryByName("AndroidManifest.xml");
+ if (entry == nullptr) {
+ fatal("Could not find AndroidManifest.xml inside %s", apkPath);
+ }
+ uint32_t manifest_len = 0;
+ if (!zipFile->getEntryInfo(entry, NULL, &manifest_len, NULL, NULL, NULL, NULL)) {
+ fatal("Could not read AndroidManifest.xml inside %s", apkPath);
+ }
+ std::vector<char> manifest_data(manifest_len);
+ if (!zipFile->uncompressEntry(entry, manifest_data.data(), manifest_len)) {
+ fatal("Could not uncompress AndroidManifest.xml inside %s", apkPath);
+ }
+ android::ResXMLTree tree;
+ android::status_t setto_status = tree.setTo(manifest_data.data(), manifest_len, true);
+ if (setto_status != android::OK) {
+ fatal("Could not parse AndroidManifest.xml inside %s", apkPath);
+ }
+ android::ResXMLParser::event_code_t code;
+ while ((code = tree.next()) != android::ResXMLParser::BAD_DOCUMENT &&
+ code != android::ResXMLParser::END_DOCUMENT) {
+ switch (code) {
+ case android::ResXMLParser::START_TAG: {
+ size_t element_name_length;
+ const char16_t* element_name = tree.getElementName(&element_name_length);
+ if (element_name == nullptr) {
+ continue;
+ }
+ std::u16string element_name_string(element_name, element_name_length);
+ if (element_name_string == u"manifest") {
+ for (size_t i = 0; i < tree.getAttributeCount(); i++) {
+ size_t attribute_name_length;
+ const char16_t* attribute_name_text =
+ tree.getAttributeName(i, &attribute_name_length);
+ if (attribute_name_text == nullptr) {
+ continue;
+ }
+ std::u16string attribute_name_string(attribute_name_text,
+ attribute_name_length);
+ if (attribute_name_string == u"package") {
+ size_t attribute_value_length;
+ const char16_t* attribute_value_text =
+ tree.getAttributeStringValue(i, &attribute_value_length);
+ if (attribute_value_text == nullptr) {
+ continue;
+ }
+ return get_string_from_utf16(attribute_value_text,
+ attribute_value_length);
+ }
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ fatal("Could not find package name tag in AndroidManifest.xml inside %s", apkPath);
}
-int extract_metadata(const char* apkPath, FILE* outputFp) {
+void extract_metadata(const char* apkPath, FILE* outputFp) {
std::string packageName = get_packagename_from_apk(apkPath);
const char* kAgentExtractCommandPattern = "/data/local/tmp/deployagent extract %s";
std::string extractCommand =
@@ -200,13 +225,10 @@
std::vector<char> extractErrorBuffer;
int statusCode;
DeployAgentFileCallback cb(outputFp, &extractErrorBuffer, &statusCode);
- int ret = send_shell_command(extractCommand, false, &cb);
-
- if (ret == 0) {
- return cb.getBytesWritten();
+ int returnCode = send_shell_command(extractCommand, false, &cb);
+ if (returnCode != 0) {
+ fatal("Executing %s returned %d\n", extractCommand.c_str(), returnCode);
}
-
- return ret;
}
static std::string get_patch_generator_command() {
@@ -229,11 +251,14 @@
adb_dir.c_str());
}
-int create_patch(const char* apkPath, const char* metadataPath, const char* patchPath) {
+void create_patch(const char* apkPath, const char* metadataPath, const char* patchPath) {
std::string generatePatchCommand = android::base::StringPrintf(
R"(%s "%s" "%s" > "%s")", get_patch_generator_command().c_str(), apkPath, metadataPath,
patchPath);
- return system(generatePatchCommand.c_str());
+ int returnCode = system(generatePatchCommand.c_str());
+ if (returnCode != 0) {
+ fatal("Executing %s returned %d\n", generatePatchCommand.c_str(), returnCode);
+ }
}
std::string get_patch_path(const char* apkPath) {
@@ -243,36 +268,38 @@
return patchDevicePath;
}
-int apply_patch_on_device(const char* apkPath, const char* patchPath, const char* outputPath) {
+void apply_patch_on_device(const char* apkPath, const char* patchPath, const char* outputPath) {
const std::string kAgentApplyCommandPattern = "/data/local/tmp/deployagent apply %s %s -o %s";
std::string packageName = get_packagename_from_apk(apkPath);
std::string patchDevicePath = get_patch_path(apkPath);
std::vector<const char*> srcs = {patchPath};
bool push_ok = do_sync_push(srcs, patchDevicePath.c_str(), false);
-
if (!push_ok) {
- return -1;
+ fatal("Error pushing %s to %s returned\n", patchPath, patchDevicePath.c_str());
}
std::string applyPatchCommand =
android::base::StringPrintf(kAgentApplyCommandPattern.c_str(), packageName.c_str(),
patchDevicePath.c_str(), outputPath);
- return send_shell_command(applyPatchCommand);
+ int returnCode = send_shell_command(applyPatchCommand);
+ if (returnCode != 0) {
+ fatal("Executing %s returned %d\n", applyPatchCommand.c_str(), returnCode);
+ }
}
-int install_patch(const char* apkPath, const char* patchPath, int argc, const char** argv) {
+void install_patch(const char* apkPath, const char* patchPath, int argc, const char** argv) {
const std::string kAgentApplyCommandPattern = "/data/local/tmp/deployagent apply %s %s -pm %s";
std::string packageName = get_packagename_from_apk(apkPath);
- std::vector<const char*> srcs;
+
std::string patchDevicePath =
android::base::StringPrintf("%s%s.patch", kDeviceAgentPath, packageName.c_str());
- srcs.push_back(patchPath);
- bool push_ok = do_sync_push(srcs, patchDevicePath.c_str(), false);
+ std::vector<const char*> srcs{patchPath};
+ bool push_ok = do_sync_push(srcs, patchDevicePath.c_str(), false);
if (!push_ok) {
- return -1;
+ fatal("Error pushing %s to %s returned\n", patchPath, patchDevicePath.c_str());
}
std::vector<unsigned char> applyOutputBuffer;
@@ -287,5 +314,8 @@
std::string applyPatchCommand =
android::base::StringPrintf(kAgentApplyCommandPattern.c_str(), packageName.c_str(),
patchDevicePath.c_str(), argsString.c_str());
- return send_shell_command(applyPatchCommand);
+ int returnCode = send_shell_command(applyPatchCommand);
+ if (returnCode != 0) {
+ fatal("Executing %s returned %d\n", applyPatchCommand.c_str(), returnCode);
+ }
}
diff --git a/adb/client/fastdeploy.h b/adb/client/fastdeploy.h
index e5e7663..a6b10d3 100644
--- a/adb/client/fastdeploy.h
+++ b/adb/client/fastdeploy.h
@@ -16,7 +16,7 @@
#pragma once
-#include "adb.h"
+#include <string>
enum FastDeploy_AgentUpdateStrategy {
FastDeploy_AgentUpdateAlways,
@@ -27,8 +27,8 @@
void fastdeploy_set_local_agent(bool use_localagent);
int get_device_api_level();
void update_agent(FastDeploy_AgentUpdateStrategy agentUpdateStrategy);
-int extract_metadata(const char* apkPath, FILE* outputFp);
-int create_patch(const char* apkPath, const char* metadataPath, const char* patchPath);
-int apply_patch_on_device(const char* apkPath, const char* patchPath, const char* outputPath);
-int install_patch(const char* apkPath, const char* patchPath, int argc, const char** argv);
+void extract_metadata(const char* apkPath, FILE* outputFp);
+void create_patch(const char* apkPath, const char* metadataPath, const char* patchPath);
+void apply_patch_on_device(const char* apkPath, const char* patchPath, const char* outputPath);
+void install_patch(const char* apkPath, const char* patchPath, int argc, const char** argv);
std::string get_patch_path(const char* apkPath);