Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5b6bf947 authored by Idries Hamadi's avatar Idries Hamadi Committed by Elliott Hughes
Browse files

Remove fastdeploy dependency on libandroidfw

Call aapt2 to determine package name instead of parsing APK within process.

Test: mm
Test: adb install -r -f --force-agent --local-agent ~/example_apks/example.apk
Test: adb install -r -f --no-streaming --force-agent --local-agent ~/example_apks/example.apk
Change-Id: I99b2c64f0617a9bb27a5c54a2e8f39efd5028f36
parent 28c95396
Loading
Loading
Loading
Loading
+0 −12
Original line number Diff line number Diff line
@@ -174,12 +174,6 @@ cc_library_host_static {
        "libdiagnose_usb",
        "libmdnssd",
        "libusb",
        "libandroidfw",
        "libziparchive",
        "libz",
        "libutils",
        "liblog",
        "libcutils",
    ],
}

@@ -262,12 +256,6 @@ cc_binary_host {
        "liblog",
        "libmdnssd",
        "libusb",
        "libandroidfw",
        "libziparchive",
        "libz",
        "libutils",
        "liblog",
        "libcutils",
    ],

    stl: "libc++_static",
+11 −16
Original line number Diff line number Diff line
@@ -130,7 +130,7 @@ static int delete_device_patch_file(const char* apkPath) {
}

static int install_app_streamed(int argc, const char** argv, bool use_fastdeploy,
                                bool use_localagent, const char* adb_path) {
                                bool use_localagent) {
    printf("Performing Streamed Install\n");

    // The last argument must be the APK file
@@ -152,8 +152,7 @@ static int install_app_streamed(int argc, const char** argv, bool use_fastdeploy
            printf("failed to extract metadata %d\n", metadata_len);
            return 1;
        } else {
            int create_patch_result = create_patch(file, metadataTmpFile.path, patchTmpFile.path,
                                                   use_localagent, adb_path);
            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;
@@ -226,8 +225,8 @@ static int install_app_streamed(int argc, const char** argv, bool use_fastdeploy
    }
}

static int install_app_legacy(int argc, const char** argv, bool use_fastdeploy, bool use_localagent,
                              const char* adb_path) {
static int install_app_legacy(int argc, const char** argv, bool use_fastdeploy,
                              bool use_localagent) {
    static const char* const DATA_DEST = "/data/local/tmp/%s";
    static const char* const SD_DEST = "/sdcard/tmp/%s";
    const char* where = DATA_DEST;
@@ -269,8 +268,8 @@ static int install_app_legacy(int argc, const char** argv, bool use_fastdeploy,
            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, use_localagent, adb_path);
            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;
@@ -380,14 +379,10 @@ int install_app(int argc, const char** argv) {
        }
    }

    std::string adb_path = android::base::GetExecutablePath();

    if (adb_path.length() == 0) {
        return 1;
    }
    if (use_fastdeploy == true) {
        bool agent_up_to_date =
                update_agent(agent_update_strategy, use_localagent, adb_path.c_str());
        fastdeploy_init(use_localagent);

        bool agent_up_to_date = update_agent(agent_update_strategy);
        if (agent_up_to_date == false) {
            printf("Failed to update agent, exiting\n");
            return 1;
@@ -397,10 +392,10 @@ int install_app(int argc, const char** argv) {
    switch (installMode) {
        case INSTALL_PUSH:
            return install_app_legacy(passthrough_argv.size(), passthrough_argv.data(),
                                      use_fastdeploy, use_localagent, adb_path.c_str());
                                      use_fastdeploy, use_localagent);
        case INSTALL_STREAM:
            return install_app_streamed(passthrough_argv.size(), passthrough_argv.data(),
                                        use_fastdeploy, use_localagent, adb_path.c_str());
                                        use_fastdeploy, use_localagent);
        case INSTALL_DEFAULT:
        default:
            return 1;
+83 −120
Original line number Diff line number Diff line
@@ -14,11 +14,12 @@
 * limitations under the License.
 */

#include <androidfw/ResourceTypes.h>
#include <androidfw/ZipFileRO.h>
#include <libgen.h>
#include <algorithm>
#include <array>

#include "android-base/file.h"
#include "android-base/strings.h"
#include "client/file_sync_client.h"
#include "commandline.h"
#include "fastdeploy.h"
@@ -29,6 +30,15 @@ static constexpr long kRequiredAgentVersion = 0x00000001;

static constexpr const char* kDeviceAgentPath = "/data/local/tmp/";

struct TFastDeployConfig {
    bool use_localagent;
};

static TFastDeployConfig& get_fastdeploy_config() {
    TFastDeployConfig& instance = *new TFastDeployConfig;
    return instance;
}

long get_agent_version() {
    std::vector<char> versionOutputBuffer;
    std::vector<char> versionErrorBuffer;
@@ -58,17 +68,19 @@ int get_device_api_level() {
    return api_level;
}

void fastdeploy_init(bool use_localagent) {
    get_fastdeploy_config().use_localagent = use_localagent;
}

// local_path - must start with a '/' and be relative to $ANDROID_PRODUCT_OUT
static bool get_agent_component_host_path(bool use_localagent, const char* adb_path,
                                          const char* local_path, const char* sdk_path,
static bool get_agent_component_host_path(const char* local_path, const char* sdk_path,
                                          std::string* output_path) {
    std::string mutable_adb_path = adb_path;
    const char* adb_dir = dirname(&mutable_adb_path[0]);
    if (adb_dir == nullptr) {
    std::string adb_dir = android::base::GetExecutableDirectory();
    if (adb_dir.empty()) {
        return false;
    }

    if (use_localagent) {
    if (get_fastdeploy_config().use_localagent) {
        const char* product_out = getenv("ANDROID_PRODUCT_OUT");
        if (product_out == nullptr) {
            return false;
@@ -76,26 +88,25 @@ static bool get_agent_component_host_path(bool use_localagent, const char* adb_p
        *output_path = android::base::StringPrintf("%s%s", product_out, local_path);
        return true;
    } else {
        *output_path = android::base::StringPrintf("%s%s", adb_dir, sdk_path);
        *output_path = adb_dir + sdk_path;
        return true;
    }
    return false;
}

static bool deploy_agent(bool checkTimeStamps, bool use_localagent, const char* adb_path) {
static bool deploy_agent(bool checkTimeStamps) {
    std::vector<const char*> srcs;

    std::string agent_jar_path;
    if (get_agent_component_host_path(use_localagent, adb_path, "/system/framework/deployagent.jar",
                                      "/deployagent.jar", &agent_jar_path)) {
    if (get_agent_component_host_path("/system/framework/deployagent.jar", "/deployagent.jar",
                                      &agent_jar_path)) {
        srcs.push_back(agent_jar_path.c_str());
    } else {
        return false;
    }

    std::string agent_sh_path;
    if (get_agent_component_host_path(use_localagent, adb_path, "/system/bin/deployagent.sh",
                                      "/deployagent.sh", &agent_sh_path)) {
    if (get_agent_component_host_path("/system/bin/deployagent.sh", "/deployagent.sh",
                                      &agent_sh_path)) {
        srcs.push_back(agent_sh_path.c_str());
    } else {
        return false;
@@ -114,17 +125,16 @@ static bool deploy_agent(bool checkTimeStamps, bool use_localagent, const char*
    }
}

bool update_agent(FastDeploy_AgentUpdateStrategy agentUpdateStrategy, bool use_localagent,
                  const char* adb_path) {
bool update_agent(FastDeploy_AgentUpdateStrategy agentUpdateStrategy) {
    long agent_version = get_agent_version();
    switch (agentUpdateStrategy) {
        case FastDeploy_AgentUpdateAlways:
            if (deploy_agent(false, use_localagent, adb_path) == false) {
            if (deploy_agent(false) == false) {
                return false;
            }
            break;
        case FastDeploy_AgentUpdateNewerTimeStamp:
            if (deploy_agent(true, use_localagent, adb_path) == false) {
            if (deploy_agent(true) == false) {
                return false;
            }
            break;
@@ -136,7 +146,7 @@ bool update_agent(FastDeploy_AgentUpdateStrategy agentUpdateStrategy, bool use_l
                    printf("Device agent version is (%ld), (%ld) is required, re-deploying\n",
                           agent_version, kRequiredAgentVersion);
                }
                if (deploy_agent(false, use_localagent, adb_path) == false) {
                if (deploy_agent(false) == false) {
                    return false;
                }
            }
@@ -147,91 +157,54 @@ bool update_agent(FastDeploy_AgentUpdateStrategy agentUpdateStrategy, bool use_l
    return (agent_version == kRequiredAgentVersion);
}

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 {};
static std::string get_aapt2_path() {
    if (get_fastdeploy_config().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");
        }

    std::string utf8;
    utf8.resize(utf8_length);
    utf16_to_utf8(input, input_len, &*utf8.begin(), utf8_length + 1);
    return utf8;
        return android::base::StringPrintf("%s/bin/aapt2", host_out);
    }

// output is required to point to a valid output string (non-null)
static bool get_packagename_from_apk(const char* apkPath, std::string* output) {
    using namespace android;

    ZipFileRO* zipFile = ZipFileRO::open(apkPath);
    if (zipFile == nullptr) {
        return false;
    std::string adb_dir = android::base::GetExecutableDirectory();
    if (adb_dir.empty()) {
        fatal("Could not locate aapt2");
    }
    return adb_dir + "/aapt2";
}

    ZipEntryRO entry = zipFile->findEntryByName("AndroidManifest.xml");
    if (entry == nullptr) {
        return false;
static int system_capture(const char* cmd, std::string& output) {
    FILE* pipe = popen(cmd, "re");
    int fd = -1;

    if (pipe != nullptr) {
        fd = fileno(pipe);
    }

    uint32_t manifest_len = 0;
    if (!zipFile->getEntryInfo(entry, NULL, &manifest_len, NULL, NULL, NULL, NULL)) {
        return false;
    if (fd == -1) {
        fatal_errno("Could not create pipe for process '%s'", cmd);
    }

    std::vector<char> manifest_data(manifest_len);
    if (!zipFile->uncompressEntry(entry, manifest_data.data(), manifest_len)) {
        return false;
    if (!android::base::ReadFdToString(fd, &output)) {
        fatal_errno("Error reading from process '%s'", cmd);
    }

    ResXMLTree tree;
    status_t setto_status = tree.setTo(manifest_data.data(), manifest_len, true);
    if (setto_status != NO_ERROR) {
        return false;
    return pclose(pipe);
}

    ResXMLParser::event_code_t code;
    while ((code = tree.next()) != ResXMLParser::BAD_DOCUMENT &&
           code != ResXMLParser::END_DOCUMENT) {
        switch (code) {
            case 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 (int i = 0; i < (int)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;
                            }
                            *output = get_string_from_utf16(attribute_value_text,
                                                            attribute_value_length);
// output is required to point to a valid output string (non-null)
static bool get_packagename_from_apk(const char* apkPath, std::string* output) {
    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);

    if (system_capture(getPackagenameCommand.c_str(), *output) == 0) {
        // strip any line end characters from the output
        *output = android::base::Trim(*output);
        return true;
    }
                    }
                }
                break;
            }
            default:
                break;
        }
    }

    return false;
}

@@ -257,43 +230,30 @@ int extract_metadata(const char* apkPath, FILE* outputFp) {
    return ret;
}

// output is required to point to a valid output string (non-null)
static bool patch_generator_command(bool use_localagent, const char* adb_path,
                                    std::string* output) {
    if (use_localagent) {
static std::string get_patch_generator_command() {
    if (get_fastdeploy_config().use_localagent) {
        // This should never happen on a Windows machine
        const char* kGeneratorCommandPattern = "java -jar %s/framework/deploypatchgenerator.jar";
        const char* host_out = getenv("ANDROID_HOST_OUT");
        if (host_out == nullptr) {
            return false;
            fatal("Could not locate deploypatchgenerator.jar because $ANDROID_HOST_OUT is not "
                  "defined");
        }
        *output = android::base::StringPrintf(kGeneratorCommandPattern, host_out, host_out);
        return true;
    } else {
        const char* kGeneratorCommandPattern = R"(java -jar "%s/deploypatchgenerator.jar")";
        std::string mutable_adb_path = adb_path;
        const char* adb_dir = dirname(&mutable_adb_path[0]);
        if (adb_dir == nullptr) {
            return false;
        return android::base::StringPrintf("java -jar %s/framework/deploypatchgenerator.jar",
                                           host_out);
    }

        *output = android::base::StringPrintf(kGeneratorCommandPattern, adb_dir, adb_dir);
        return true;
    std::string adb_dir = android::base::GetExecutableDirectory();
    if (adb_dir.empty()) {
        fatal("Could not locate deploypatchgenerator.jar");
    }
    return false;
    return android::base::StringPrintf(R"(java -jar "%s/deploypatchgenerator.jar")",
                                       adb_dir.c_str());
}

int create_patch(const char* apkPath, const char* metadataPath, const char* patchPath,
                 bool use_localagent, const char* adb_path) {
    const char* kGeneratePatchCommandPattern = R"(%s "%s" "%s" > "%s")";
    std::string patch_generator_command_string;
    if (patch_generator_command(use_localagent, adb_path, &patch_generator_command_string) ==
        false) {
        return 1;
    }
int create_patch(const char* apkPath, const char* metadataPath, const char* patchPath) {
    std::string generatePatchCommand = android::base::StringPrintf(
            kGeneratePatchCommandPattern, patch_generator_command_string.c_str(), apkPath,
            metadataPath, patchPath);
            R"(%s "%s" "%s" > "%s")", get_patch_generator_command().c_str(), apkPath, metadataPath,
            patchPath);
    return system(generatePatchCommand.c_str());
}

@@ -302,6 +262,7 @@ std::string get_patch_path(const char* apkPath) {
    if (get_packagename_from_apk(apkPath, &packageName) == false) {
        return "";
    }

    std::string patchDevicePath =
            android::base::StringPrintf("%s%s.patch", kDeviceAgentPath, packageName.c_str());
    return patchDevicePath;
@@ -315,6 +276,7 @@ int apply_patch_on_device(const char* apkPath, const char* patchPath, const char
    if (get_packagename_from_apk(apkPath, &packageName) == false) {
        return -1;
    }

    std::string patchDevicePath = get_patch_path(apkPath);

    std::vector<const char*> srcs = {patchPath};
@@ -327,6 +289,7 @@ int apply_patch_on_device(const char* apkPath, const char* patchPath, const char
    std::string applyPatchCommand =
            android::base::StringPrintf(kAgentApplyCommandPattern.c_str(), packageName.c_str(),
                                        patchDevicePath.c_str(), outputPath);

    return send_shell_command(applyPatchCommand);
}

+6 −6
Original line number Diff line number Diff line
@@ -18,20 +18,20 @@

#include "adb.h"

typedef enum EFastDeploy_AgentUpdateStrategy {
enum FastDeploy_AgentUpdateStrategy {
    FastDeploy_AgentUpdateAlways,
    FastDeploy_AgentUpdateNewerTimeStamp,
    FastDeploy_AgentUpdateDifferentVersion
} FastDeploy_AgentUpdateStrategy;
};

static constexpr int kFastDeployMinApi = 24;

void fastdeploy_init(bool use_localagent);

int get_device_api_level();
bool update_agent(FastDeploy_AgentUpdateStrategy agentUpdateStrategy, bool use_localagent,
                  const char* adb_path);
bool 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,
                 bool use_localagent, const char* adb_path);
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);
std::string get_patch_path(const char* apkPath);