From ec7b2807d05fd2dc7e6c2d2f75320a7260784b59 Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 26 Jan 2018 18:54:17 +0000 Subject: [PATCH] Build each architecture into its own APK * This means we can have all the architectures we care about installed, and load the right library regardless of what the app does. --- CMakeLists.txt | 8 +- .../Code/Interface/PersistantConfig.cpp | 2 +- renderdoc/android/android.cpp | 264 +++++++++--------- renderdoc/android/android_patch.cpp | 26 +- renderdoc/android/android_utils.cpp | 48 ++++ renderdoc/android/android_utils.h | 17 ++ renderdoc/android/jdwp.cpp | 36 ++- renderdoc/common/globalconfig.h | 3 + .../os/posix/android/android_stringio.cpp | 2 +- renderdoccmd/CMakeLists.txt | 16 +- renderdoccmd/android/AndroidManifest.xml | 4 +- .../renderdoc/renderdoccmd => }/Loader.java | 2 +- .../android/{res/drawable => }/icon.png | Bin scripts/dist.sh | 29 +- 14 files changed, 256 insertions(+), 201 deletions(-) rename renderdoccmd/android/{src/org/renderdoc/renderdoccmd => }/Loader.java (95%) rename renderdoccmd/android/{res/drawable => }/icon.png (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2b7dede89..f6177b2f1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,8 +39,7 @@ set(BUILD_VERSION_DIST_NAME "" CACHE STRING "The name of the distribution. See D set(BUILD_VERSION_DIST_VER "" CACHE STRING "The distribution-specific version number. See DISTRIBUTION_VERSION in renderdoc/api/replay/version.h") set(BUILD_VERSION_DIST_CONTACT "" CACHE STRING "The URL or email to contact with issues. See DISTRIBUTION_CONTACT in renderdoc/api/replay/version.h") set(RENDERDOC_PLUGINS_PATH "" CACHE STRING "Path to RenderDoc plugins folder after installation of RenderDoc (either absolute or relative to binary)") -set(RENDERDOC_APK_PATH "" CACHE STRING "Path to RenderDocCmd.apk after installation of RenderDoc on host (either absolute or relative to binary)") -set(RENDERDOC_LAYER_PATH "" CACHE STRING "Path to ABI directories (i.e. lib in lib/armeabi-v7a/libVkLayer_GLES_RenderDoc.so) after installation of RenderDoc on host (either absolute or relative to dir)") +set(RENDERDOC_APK_PATH "" CACHE STRING "Path to RenderDoc .apk files after installation of RenderDoc on host (either absolute or relative to binary)") set(LIB_SUFFIX "" CACHE STRING "Suffix for 'lib' folder in target directory structure. E.g. set to '64' to use /usr/local/lib64 instead of /usr/local/lib.") set(LIB_SUBFOLDER "" CACHE STRING "Subfolder under the 'lib' folder in target directory structure. E.g. set to 'renderdoc' to use /usr/local/lib/renderdoc instead of /usr/local/lib.") @@ -82,11 +81,6 @@ if(NOT RENDERDOC_APK_PATH STREQUAL "") add_definitions(-DRENDERDOC_APK_PATH="${RENDERDOC_APK_PATH}") endif() -if(NOT RENDERDOC_LAYER_PATH STREQUAL "") - message(STATUS "Detected custom path to libVkLayer_GLES_RenderDoc.so: ${RENDERDOC_LAYER_PATH}") - add_definitions(-DRENDERDOC_LAYER_PATH="${RENDERDOC_LAYER_PATH}") -endif() - function(get_git_hash _git_hash) if(EXISTS "${CMAKE_SOURCE_DIR}/.git") execute_process( diff --git a/qrenderdoc/Code/Interface/PersistantConfig.cpp b/qrenderdoc/Code/Interface/PersistantConfig.cpp index 26956be2b..e70dfcafb 100644 --- a/qrenderdoc/Code/Interface/PersistantConfig.cpp +++ b/qrenderdoc/Code/Interface/PersistantConfig.cpp @@ -236,7 +236,7 @@ void PersistantConfig::AddAndroidHosts() RENDERDOC_GetAndroidFriendlyName(hostName.toUtf8().data(), friendly); host->friendlyName = friendly; // Just a command to display in the GUI and allow Launch() to be called. - host->runCommand = lit("org.renderdoc.renderdoccmd"); + host->runCommand = lit("Automatically handled"); RemoteHosts.push_back(host); } diff --git a/renderdoc/android/android.cpp b/renderdoc/android/android.cpp index 8fcb7f900..a6dab4520 100644 --- a/renderdoc/android/android.cpp +++ b/renderdoc/android/android.cpp @@ -89,7 +89,7 @@ std::string GetDefaultActivityForPackage(const std::string &deviceID, const std: return ""; } -int GetCurrentPid(const std::string &deviceID, const std::string &packageName) +int GetCurrentPID(const std::string &deviceID, const std::string &packageName) { // try 5 times, 200ms apart to find the pid for(int i = 0; i < 5; i++) @@ -146,7 +146,7 @@ uint32_t StartAndroidPackageForCapture(const char *host, const char *package) activityName.c_str())); // adb shell ps | grep $PACKAGE | awk '{print $2}') - int pid = GetCurrentPid(deviceID, packageName); + int pid = GetCurrentPID(deviceID, packageName); adbForwardPorts(index, deviceID, jdwpPort, pid); @@ -194,15 +194,17 @@ uint32_t StartAndroidPackageForCapture(const char *host, const char *package) return ret; } -bool installRenderDocServer(const string &deviceID) +bool InstallRenderDocServer(const std::string &deviceID) { - string targetApk = "RenderDocCmd.apk"; - string serverApk; + std::vector abis = GetSupportedABIs(deviceID); + + if(abis.empty()) + return false; // Check known paths for RenderDoc server - string exePath; + std::string exePath; FileIO::GetExecutableFilename(exePath); - string exeDir = dirname(FileIO::GetFullPathname(exePath)); + std::string exeDir = dirname(FileIO::GetFullPathname(exePath)); std::vector paths; @@ -213,160 +215,145 @@ bool installRenderDocServer(const string &deviceID) if(FileIO::IsRelativePath(customPath)) customPath = exeDir + "/" + customPath; - // Check to see if APK name was included in custom path - if(!endswith(customPath, targetApk)) - { - if(customPath.back() != '/') - customPath += "/"; - customPath += targetApk; - } + if(!endswith(customPath, "/")) + customPath += "/"; paths.push_back(customPath); #endif - paths.push_back(exeDir + "/android/apk/" + targetApk); // Windows install - paths.push_back(exeDir + "/../share/renderdoc/android/apk/" + targetApk); // Linux install - paths.push_back(exeDir + "/../../build-android/bin/" + targetApk); // Local build - paths.push_back(exeDir + "/../../../../../build-android/bin/" + targetApk); // macOS build + paths.push_back(exeDir + "/android/apk/"); // Windows install + paths.push_back(exeDir + "/../share/renderdoc/android/apk/"); // Linux install + paths.push_back(exeDir + "/../../build-android/bin/"); // Local build + paths.push_back(exeDir + "/../../../../../build-android/bin/"); // macOS build + + // use the first ABI for searching + std::string apk = GetRenderDocPackageForABI(abis[0]); + std::string apksFolder; for(uint32_t i = 0; i < paths.size(); i++) { RDCLOG("Checking for server APK in %s", paths[i].c_str()); - if(FileIO::exists(paths[i].c_str())) + + std::string apkpath = paths[i] + apk + ".apk"; + + if(FileIO::exists(apkpath.c_str())) { - serverApk = paths[i]; - RDCLOG("APK found!: %s", serverApk.c_str()); + apksFolder = paths[i]; + RDCLOG("APKs found: %s", apksFolder.c_str()); break; } } - if(serverApk.empty()) + if(apksFolder.empty()) { RDCERR( - "%s missing! RenderDoc for Android will not work without it. " + "APK folder missing! RenderDoc for Android will not work without it. " "Build your Android ABI in build-android in the root to have it " - "automatically found and installed.", - targetApk.c_str()); + "automatically found and installed."); return false; } - // Build a map so we can switch on the string that returns from adb calls - enum AndroidAbis + for(ABI abi : abis) { - Android_armeabi, - Android_armeabi_v7a, - Android_arm64_v8a, - Android_x86, - Android_x86_64, - Android_mips, - Android_mips64, - Android_numAbis - }; + apk = apksFolder + GetRenderDocPackageForABI(abi) + ".apk"; - // clang-format off - static std::map abi_string_map; - abi_string_map["armeabi"] = Android_armeabi; - abi_string_map["armeabi-v7a"] = Android_armeabi_v7a; - abi_string_map["arm64-v8a"] = Android_arm64_v8a; - abi_string_map["x86"] = Android_x86; - abi_string_map["x86_64"] = Android_x86_64; - abi_string_map["mips"] = Android_mips; - abi_string_map["mips64"] = Android_mips64; - // clang-format on + if(!FileIO::exists(apk.c_str())) + RDCWARN( + "%s missing - ensure you build all ABIs your device can support for full compatibility", + apk.c_str()); - // 32-bit server works for 32 and 64 bit apps - // For stable builds of the server, only 32-bit libs will be packaged into APK - // For local builds, whatever was specified as single ABI will be packaged into APK + adbExecCommand(deviceID, "install -r -g \"" + apk + "\""); + } - string adbAbi = trim(adbExecCommand(deviceID, "shell getprop ro.product.cpu.abi").strStdout); + // Ensure installation succeeded. We should have as many lines as abis we installed + std::string adbCheck = + adbExecCommand(deviceID, "shell pm list packages " RENDERDOC_ANDROID_PACKAGE_BASE).strStdout; - string adbInstall; - switch(abi_string_map[adbAbi]) + if(adbCheck.empty()) + return false; + + size_t lines = adbCheck.find('\n') == std::string::npos ? 1 : 2; + + if(lines != abis.size()) + RDCWARN("Installation of some apks failed!"); + + return true; +} + +bool RemoveRenderDocAndroidServer(const string &deviceID) +{ + std::vector abis = GetSupportedABIs(deviceID); + + if(abis.empty()) + return false; + + // remove the old package, if it's still there. Ignore any errors + adbExecCommand(deviceID, "uninstall " RENDERDOC_ANDROID_PACKAGE_BASE); + + for(ABI abi : abis) { - case Android_armeabi_v7a: - case Android_arm64_v8a: - adbInstall = adbExecCommand(deviceID, "install -r -g \"" + serverApk + "\"").strStdout; - break; - case Android_armeabi: - case Android_x86: - case Android_x86_64: - case Android_mips: - case Android_mips64: - default: + std::string packageName = GetRenderDocPackageForABI(abi); + + adbExecCommand(deviceID, "uninstall " + packageName); + + // Ensure uninstall succeeded + std::string adbCheck = + adbExecCommand(deviceID, "shell pm list packages " + packageName).strStdout; + + if(!adbCheck.empty()) { - RDCERR("Unsupported target ABI: %s", adbAbi.c_str()); + RDCERR("Uninstall of %s failed!", packageName.c_str()); return false; } } - // Ensure installation succeeded - string adbCheck = - adbExecCommand(deviceID, "shell pm list packages org.renderdoc.renderdoccmd").strStdout; - if(adbCheck.empty()) - { - RDCERR("Installation of RenderDocCmd.apk failed!"); - return false; - } - return true; } -bool RemoveRenderDocAndroidServer(const string &deviceID, const string &packageName) -{ - adbExecCommand(deviceID, "uninstall " + packageName); - // Ensure uninstall succeeded - string adbCheck = adbExecCommand(deviceID, "shell pm list packages " + packageName).strStdout; - - if(!adbCheck.empty()) - { - RDCERR("Uninstall of %s failed!", packageName.c_str()); - return false; - } - - return true; -} bool CheckAndroidServerVersion(const string &deviceID) { - string packageName = "org.renderdoc.renderdoccmd"; + std::vector abis = GetSupportedABIs(deviceID); + + if(abis.empty()) + return false; + + // assume all servers are updated at the same rate. Only check first ABI's version + std::string packageName = GetRenderDocPackageForABI(abis[0]); RDCLOG("Checking installed version of %s on %s", packageName.c_str(), deviceID.c_str()); - string dump = adbExecCommand(deviceID, "shell pm dump " + packageName).strStdout; + std::string dump = adbExecCommand(deviceID, "shell pm dump " + packageName).strStdout; if(dump.empty()) RDCERR("Unable to pm dump %s", packageName.c_str()); - // Walk through the output and look for versionCode and versionName - std::istringstream contents(dump); - string line; - string versionCode; - string versionName; - string prefix1("versionCode="); - string prefix2("versionName="); - while(std::getline(contents, line)) + std::string versionCode = trim(GetFirstMatchingLine(dump, "versionCode=")); + std::string versionName = trim(GetFirstMatchingLine(dump, "versionName=")); + + // versionCode is not alone in this line, isolate it + if(versionCode != "") { - line = trim(line); - if(line.compare(0, prefix1.size(), prefix1) == 0) - { - // versionCode is not alone in this line, isolate it - std::vector vec; - split(line, vec, ' '); - versionCode = vec[0].substr(vec[0].find_last_of("=") + 1); - } - if(line.compare(0, prefix2.size(), prefix2) == 0) - { - versionName = line.substr(line.find_first_of("=") + 1); - } + size_t spaceOffset = versionCode.find(' '); + versionCode.erase(spaceOffset); + + versionCode.erase(0, strlen("versionCode=")); + } + else + { + RDCERR("Unable to determine versionCode for: %s", packageName.c_str()); } - if(versionCode.empty()) - RDCERR("Unable to determine versionCode for: %s", packageName.c_str()); - - if(versionName.empty()) + if(versionName != "") + { + versionName.erase(0, strlen("versionName=")); + } + else + { RDCERR("Unable to determine versionName for: %s", packageName.c_str()); + } // Compare the server's versionCode and versionName with the host's for compatibility - string hostVersionCode = + std::string hostVersionCode = string(STRINGIZE(RENDERDOC_VERSION_MAJOR)) + string(STRINGIZE(RENDERDOC_VERSION_MINOR)); - string hostVersionName = RENDERDOC_STABLE_BUILD ? MAJOR_MINOR_VERSION_STRING : GitVersionHash; + std::string hostVersionName = RENDERDOC_STABLE_BUILD ? MAJOR_MINOR_VERSION_STRING : GitVersionHash; // False positives will hurt us, so check for explicit matches if((hostVersionCode == versionCode) && (hostVersionName == versionName)) @@ -379,14 +366,12 @@ bool CheckAndroidServerVersion(const string &deviceID) RDCWARN("RenderDoc server versionCode:versionName (%s:%s) is incompatible with host (%s:%s)", versionCode.c_str(), versionName.c_str(), hostVersionCode.c_str(), hostVersionName.c_str()); - if(RemoveRenderDocAndroidServer(deviceID, packageName)) + if(RemoveRenderDocAndroidServer(deviceID)) RDCLOG("Uninstall of incompatible server succeeded"); return false; } - }; // namespace Android -using namespace Android; extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_GetAndroidFriendlyName(const rdcstr &device, rdcstr &friendly) @@ -412,17 +397,17 @@ extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_GetAndroidFriendlyName(cons extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_EnumerateAndroidDevices(rdcstr *deviceList) { - string adbStdout = adbExecCommand("", "devices").strStdout; + std::string adbStdout = Android::adbExecCommand("", "devices").strStdout; int idx = 0; - using namespace std; - istringstream stdoutStream(adbStdout); - string ret; - string line; - while(getline(stdoutStream, line)) + std::string ret; + + std::vector lines; + split(adbStdout, lines, '\n'); + for(const std::string &line : lines) { - vector tokens; + std::vector tokens; split(line, tokens, '\t'); if(tokens.size() == 2 && trim(tokens[1]) == "device") { @@ -432,7 +417,7 @@ extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_EnumerateAndroidDevices(rdc ret += StringFormat::Fmt("adb:%d:%s", idx, tokens[0].c_str()); // Forward the ports so we can see if a remoteserver/captured app is already running. - adbForwardPorts(idx, tokens[0], 0, 0); + Android::adbForwardPorts(idx, tokens[0], 0, 0); idx++; } @@ -448,20 +433,29 @@ extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_StartAndroidRemoteServer(co Android::ExtractDeviceIDAndIndex(device, index, deviceID); - string adbPackage = - adbExecCommand(deviceID, "shell pm list packages org.renderdoc.renderdoccmd").strStdout; + std::string packages = + Android::adbExecCommand(deviceID, "shell pm list packages " RENDERDOC_ANDROID_PACKAGE_BASE).strStdout; - if(adbPackage.empty() || !CheckAndroidServerVersion(deviceID)) + if(packages.empty() || !Android::CheckAndroidServerVersion(deviceID)) { // If server is not detected or has been removed due to incompatibility, install it - if(!installRenderDocServer(deviceID)) + if(!Android::InstallRenderDocServer(deviceID)) return; } - adbExecCommand(deviceID, "shell am force-stop org.renderdoc.renderdoccmd"); - adbForwardPorts(index, deviceID, 0, 0); - adbExecCommand(deviceID, "shell setprop debug.vulkan.layers :"); - adbExecCommand( - deviceID, - "shell am start -n org.renderdoc.renderdoccmd/.Loader -e renderdoccmd remoteserver"); + // stop all servers of any ABI + std::vector abis = Android::GetSupportedABIs(deviceID); + + for(Android::ABI abi : abis) + Android::adbExecCommand(deviceID, "shell am force-stop " + GetRenderDocPackageForABI(abi)); + + if(abis.empty()) + return; + + Android::adbForwardPorts(index, deviceID, 0, 0); + Android::adbExecCommand(deviceID, "shell setprop debug.vulkan.layers :"); + + // launch the first ABI, as the default 'most compatible' package + Android::adbExecCommand(deviceID, "shell am start -n " + GetRenderDocPackageForABI(abis[0]) + + "/.Loader -e renderdoccmd remoteserver"); } diff --git a/renderdoc/android/android_patch.cpp b/renderdoc/android/android_patch.cpp index badfe542c..913d93733 100644 --- a/renderdoc/android/android_patch.cpp +++ b/renderdoc/android/android_patch.cpp @@ -23,6 +23,7 @@ ******************************************************************************/ #include +#include "api/replay/version.h" #include "core/core.h" #include "strings/string_utils.h" #include "android_utils.h" @@ -363,25 +364,36 @@ bool HasRootAccess(const std::string &deviceID) return false; } +std::string GetFirstMatchingLine(const std::string &haystack, const std::string &needle) +{ + size_t needleOffset = haystack.find(needle); + + if(needleOffset == std::string::npos) + { + RDCERR("Couldn't get pkgFlags from adb"); + return ""; + } + + size_t nextLine = haystack.find('\n', needleOffset + 1); + + return haystack.substr(needleOffset, + nextLine == std::string::npos ? nextLine : nextLine - needleOffset); +} + bool IsDebuggable(const std::string &deviceID, const std::string &packageName) { RDCLOG("Checking that APK is debuggable"); std::string info = adbExecCommand(deviceID, "shell dumpsys package " + packageName).strStdout; - size_t flagsOffset = info.find("pkgFlags=["); + std::string pkgFlags = GetFirstMatchingLine(info, "pkgFlags=["); - if(flagsOffset == std::string::npos) + if(pkgFlags == "") { RDCERR("Couldn't get pkgFlags from adb"); return false; } - size_t nextLine = info.find('\n', flagsOffset + 1); - - std::string pkgFlags = - info.substr(flagsOffset, nextLine == std::string::npos ? nextLine : nextLine - flagsOffset); - return pkgFlags.find("DEBUGGABLE") != std::string::npos; } }; diff --git a/renderdoc/android/android_utils.cpp b/renderdoc/android/android_utils.cpp index 982bbdc94..ff9d716ea 100644 --- a/renderdoc/android/android_utils.cpp +++ b/renderdoc/android/android_utils.cpp @@ -58,6 +58,54 @@ void ExtractDeviceIDAndIndex(const std::string &hostname, int &index, std::strin deviceID = c; } +ABI GetABI(const std::string &abiName) +{ + if(abiName == "armeabi-v7a") + return ABI::armeabi_v7a; + else if(abiName == "arm64-v8a") + return ABI::arm64_v8a; + else if(abiName == "x86-v7a") + return ABI::x86; + else if(abiName == "x86_64") + return ABI::x86_64; + + RDCWARN("Unknown or unsupported ABI %s", abiName.c_str()); + + return ABI::unknown; +} + +std::vector GetSupportedABIs(const std::string &deviceID) +{ + std::string adbAbi = trim(adbExecCommand(deviceID, "shell getprop ro.product.cpu.abi").strStdout); + + // these returned lists should be such that the first entry is the 'lowest command denominator' - + // typically 32-bit. + switch(GetABI(adbAbi)) + { + case ABI::arm64_v8a: return {ABI::armeabi_v7a, ABI::arm64_v8a}; + case ABI::armeabi_v7a: return {ABI::armeabi_v7a}; + case ABI::x86_64: return {ABI::x86, ABI::x86_64}; + case ABI::x86: return {ABI::x86}; + default: break; + } + + return {}; +} + +std::string GetRenderDocPackageForABI(ABI abi) +{ + switch(abi) + { + case ABI::arm64_v8a: return RENDERDOC_ANDROID_PACKAGE_BASE ".arm64"; + case ABI::armeabi_v7a: return RENDERDOC_ANDROID_PACKAGE_BASE ".arm32"; + case ABI::x86_64: return RENDERDOC_ANDROID_PACKAGE_BASE ".x64"; + case ABI::x86: return RENDERDOC_ANDROID_PACKAGE_BASE ".x86"; + default: break; + } + + return RENDERDOC_ANDROID_PACKAGE_BASE ".unknown"; +} + std::string GetPathForPackage(const std::string &deviceID, const std::string &packageName) { std::string pkgPath = trim(adbExecCommand(deviceID, "shell pm path " + packageName).strStdout); diff --git a/renderdoc/android/android_utils.h b/renderdoc/android/android_utils.h index 86977b535..5472fbc02 100644 --- a/renderdoc/android/android_utils.h +++ b/renderdoc/android/android_utils.h @@ -47,5 +47,22 @@ enum class ToolDir std::string getToolPath(ToolDir subdir, const std::string &toolname, bool checkExist); bool toolExists(const std::string &path); +std::string GetFirstMatchingLine(const std::string &haystack, const std::string &needle); + std::string GetFriendlyName(std::string deviceID); + +// supported ABIs +enum class ABI +{ + unknown, + armeabi_v7a, + arm64_v8a, + x86, + x86_64, +}; + +ABI GetABI(const std::string &abiName); +std::vector GetSupportedABIs(const std::string &deviceID); +std::string GetRenderDocPackageForABI(ABI abi); +std::string GetPathForPackage(const std::string &deviceID, const std::string &packageName); }; diff --git a/renderdoc/android/jdwp.cpp b/renderdoc/android/jdwp.cpp index b6b219384..5f5799965 100644 --- a/renderdoc/android/jdwp.cpp +++ b/renderdoc/android/jdwp.cpp @@ -27,6 +27,7 @@ #include "core/core.h" #include "strings/string_utils.h" #include "android.h" +#include "android_utils.h" namespace JDWP { @@ -95,7 +96,7 @@ void InjectVulkanLayerSearchPath(Connection &conn, threadID thread, int32_t slot conn.SetLocalValue(thread, stack[0].id, slotIdx, temp); } -bool InjectLibraries(Network::Socket *sock, std::string libPath) +bool InjectLibraries(const std::string &deviceID, Network::Socket *sock) { Connection conn(sock); @@ -112,7 +113,7 @@ bool InjectLibraries(Network::Socket *sock, std::string libPath) return false; // default to arm as a safe bet - std::string abi = "armeabi-v7a"; + Android::ABI abi = Android::ABI::armeabi_v7a; // determine the CPU ABI from android.os.Build.CPU_ABI referenceTypeID buildClass = conn.GetType("Landroid/os/Build;"); @@ -125,7 +126,7 @@ bool InjectLibraries(Network::Socket *sock, std::string libPath) value val = conn.GetFieldValue(buildClass, CPU_ABI); if(val.tag == Tag::String) - abi = conn.GetString(val.String); + abi = Android::GetABI(conn.GetString(val.String)); else RDCERR("CPU_ABI value was type %u, not string!", (uint32_t)val.tag); } @@ -139,19 +140,21 @@ bool InjectLibraries(Network::Socket *sock, std::string libPath) RDCERR("Couldn't find android.os.Build"); } - // use the ABI to determine where to find our library - if(abi == "armeabi-v7a") + if(abi == Android::ABI::unknown) { - libPath += "arm"; + RDCERR("Unrecognised running ABI, falling back to armeabi-v7a"); + abi = Android::ABI::armeabi_v7a; } - else if(abi == "arm64-v8a") + + std::string libPath = Android::GetPathForPackage(deviceID, Android::GetRenderDocPackageForABI(abi)); + + switch(abi) { - libPath += "arm64"; - } - else - { - RDCERR("Unhandled ABI '%s'", abi.c_str()); - return false; + case Android::ABI::unknown: + case Android::ABI::armeabi_v7a: libPath += "lib/arm"; break; + case Android::ABI::arm64_v8a: libPath += "lib/arm64"; break; + case Android::ABI::x86_64: libPath += "lib/x86_64"; break; + case Android::ABI::x86: libPath += "lib/x86"; break; } if(conn.IsErrored()) @@ -386,12 +389,7 @@ bool InjectWithJDWP(const std::string &deviceID, uint16_t jdwpport) if(sock) { - std::string apk = adbExecCommand(deviceID, "shell pm path org.renderdoc.renderdoccmd").strStdout; - apk = trim(apk); - apk.resize(apk.size() - 8); - apk.erase(0, 8); - - bool ret = JDWP::InjectLibraries(sock, apk + "lib/"); + bool ret = JDWP::InjectLibraries(deviceID, sock); delete sock; return ret; diff --git a/renderdoc/common/globalconfig.h b/renderdoc/common/globalconfig.h index f5af55705..87135e085 100644 --- a/renderdoc/common/globalconfig.h +++ b/renderdoc/common/globalconfig.h @@ -130,6 +130,9 @@ enum #define RENDERDOC_ANDROID_LIBRARY "libVkLayer_GLES_RenderDoc.so" +// This MUST match the package name in the build process that generates per-architecture packages +#define RENDERDOC_ANDROID_PACKAGE_BASE "org.renderdoc.renderdoccmd" + ///////////////////////////////////////////////// // Debugging features configuration diff --git a/renderdoc/os/posix/android/android_stringio.cpp b/renderdoc/os/posix/android/android_stringio.cpp index d5ba152e9..f9571c8cd 100644 --- a/renderdoc/os/posix/android/android_stringio.cpp +++ b/renderdoc/os/posix/android/android_stringio.cpp @@ -72,7 +72,7 @@ string GetAppFolderFilename(const string &filename) return GetTempRootPath() + string("/") + filename; } -// For RenderDocCmd.apk, this returns "org.renderdoc.renderdoccmd" +// For RenderDoc's apk, this returns our package name // For other APKs, we use it to get the writable temp directory. void GetExecutableFilename(string &selfName) { diff --git a/renderdoccmd/CMakeLists.txt b/renderdoccmd/CMakeLists.txt index c03f55812..656ce6cab 100644 --- a/renderdoccmd/CMakeLists.txt +++ b/renderdoccmd/CMakeLists.txt @@ -102,17 +102,29 @@ if(ANDROID) endif() message(STATUS "Building APK versionCode ${APK_VERSION_CODE}, versionName ${APK_VERSION_NAME}") + # Set the package name based on the ABI + if(ANDROID_ABI STREQUAL "armeabi-v7a") + set(RENDERDOC_ANDROID_PACKAGE_NAME "org.renderdoc.renderdoccmd.arm32") + elseif(ANDROID_ABI STREQUAL "arm64-v8a") + set(RENDERDOC_ANDROID_PACKAGE_NAME "org.renderdoc.renderdoccmd.arm64") + else() + message(FATAL_ERROR "ABI ${ANDROID_ABI} is not supported.") + endif() - set(APK_FILE ${CMAKE_BINARY_DIR}/bin/RenderDocCmd.apk) + set(APK_FILE ${CMAKE_BINARY_DIR}/bin/${RENDERDOC_ANDROID_PACKAGE_NAME}.apk) add_custom_target(apk ALL DEPENDS ${APK_FILE} DEPENDS ${KEYSTORE}) + # Copy in android package files, replacing the package name with the architecture-specific package name + configure_file(android/Loader.java ${CMAKE_CURRENT_BINARY_DIR}/src/org/renderdoc/renderdoccmd/Loader.java) + configure_file(android/AndroidManifest.xml ${CMAKE_CURRENT_BINARY_DIR}/AndroidManifest.xml) + configure_file(android/icon.png ${CMAKE_CURRENT_BINARY_DIR}/res/drawable/icon.png COPYONLY) + add_custom_command(OUTPUT ${APK_FILE} DEPENDS renderdoc DEPENDS renderdoccmd WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/android ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${CMAKE_COMMAND} -E make_directory libs/lib/${ANDROID_ABI} COMMAND ${CMAKE_COMMAND} -E make_directory obj COMMAND ${CMAKE_COMMAND} -E make_directory bin diff --git a/renderdoccmd/android/AndroidManifest.xml b/renderdoccmd/android/AndroidManifest.xml index 64caaf9b0..9acc70933 100644 --- a/renderdoccmd/android/AndroidManifest.xml +++ b/renderdoccmd/android/AndroidManifest.xml @@ -1,6 +1,6 @@ - + @@ -11,7 +11,7 @@ - + diff --git a/renderdoccmd/android/src/org/renderdoc/renderdoccmd/Loader.java b/renderdoccmd/android/Loader.java similarity index 95% rename from renderdoccmd/android/src/org/renderdoc/renderdoccmd/Loader.java rename to renderdoccmd/android/Loader.java index 9558c7669..045e5b8ce 100644 --- a/renderdoccmd/android/src/org/renderdoc/renderdoccmd/Loader.java +++ b/renderdoccmd/android/Loader.java @@ -1,4 +1,4 @@ -package org.renderdoc.renderdoccmd; +package @RENDERDOC_ANDROID_PACKAGE_NAME@; import android.app.Activity; public class Loader extends android.app.NativeActivity diff --git a/renderdoccmd/android/res/drawable/icon.png b/renderdoccmd/android/icon.png similarity index 100% rename from renderdoccmd/android/res/drawable/icon.png rename to renderdoccmd/android/icon.png diff --git a/scripts/dist.sh b/scripts/dist.sh index ff706a91f..afcc94499 100644 --- a/scripts/dist.sh +++ b/scripts/dist.sh @@ -51,32 +51,9 @@ cp -R plugins-win32/ dist/Release32/plugins find dist/Release{32,64}/ -iname '*.ipdb' -exec rm '{}' \; find dist/Release{32,64}/ -iname '*.iobj' -exec rm '{}' \; -ANDROID32="bin-android32" -if [ -f build-android32/bin/RenderDocCmd.apk ]; then - ANDROID32="build-android32/bin"; -fi - -ANDROID64="bin-android64" -if [ -f build-android64/bin/RenderDocCmd.apk ]; then - ANDROID64="build-android64/bin"; -fi - -if [ -f $ANDROID32/RenderDocCmd.apk ]; then - # Building for android, copy the apk and vulkan layer into folders - mkdir -p dist/Release64/android/apk dist/Release64/android/lib/armeabi-v7a - - cp $ANDROID32/RenderDocCmd.apk dist/Release64/android/apk - cp $ANDROID32/libVkLayer_GLES_RenderDoc.so dist/Release64/android/lib/armeabi-v7a/libVkLayer_GLES_RenderDoc.so -fi - -if [ -f $ANDROID64/RenderDocCmd.apk ]; then - # Building for android, copy the vulkan layer into folder - mkdir -p dist/Release64/android/lib/arm64-v8a - - # We don't distribute the 64-bit apk, we use armeabi-v7a for both 32-bit and 64-bit - #cp $ANDROID64/RenderDocCmd.apk dist/Release64/android/apk/64 - cp $ANDROID64/libVkLayer_GLES_RenderDoc.so dist/Release64/android/lib/arm64-v8a/libVkLayer_GLES_RenderDoc.so -fi +# Copy in any android APKs that were built +mkdir -p dist/Release64/android/apk +find build-android-* -iname 'org.renderdoc.renderdoccmd.*.apk' -exec cp '{}' dist/Release64/android/apk ';' # try to copy adb.exe in as well, with its dll dependencies if [ -f $ANDROID_SDK/platform-tools/adb.exe ] && [ -d dist/Release64/android ]; then