From 5527c57e681c496a0ee58ff5e2e21bbd270b53d3 Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 26 Jan 2018 16:30:16 +0000 Subject: [PATCH] Split out some miscellaneous utility functions * We also wrap up and cache the fetching of friendly names by serial number to avoid some adb traffic. --- renderdoc/CMakeLists.txt | 1 + renderdoc/android/android.cpp | 113 ++++--------------------- renderdoc/android/android.h | 2 +- renderdoc/android/android_utils.cpp | 123 ++++++++++++++++++++++++++++ renderdoc/android/android_utils.h | 5 ++ renderdoc/core/remote_server.cpp | 4 +- renderdoc/renderdoc.vcxproj | 1 + renderdoc/renderdoc.vcxproj.filters | 3 + renderdoc/replay/entry_points.cpp | 2 +- 9 files changed, 151 insertions(+), 103 deletions(-) create mode 100644 renderdoc/android/android_utils.cpp diff --git a/renderdoc/CMakeLists.txt b/renderdoc/CMakeLists.txt index 4c0365c8f..ba06375b5 100644 --- a/renderdoc/CMakeLists.txt +++ b/renderdoc/CMakeLists.txt @@ -91,6 +91,7 @@ set(sources core/replay_proxy.h android/android.cpp android/android_tools.cpp + android/android_utils.cpp android/android.h android/android_utils.h core/plugins.cpp diff --git a/renderdoc/android/android.cpp b/renderdoc/android/android.cpp index 4bfee4323..5fc245c03 100644 --- a/renderdoc/android/android.cpp +++ b/renderdoc/android/android.cpp @@ -43,36 +43,6 @@ static const char keystoreName[] = "renderdoc.keystore"; namespace Android { -bool IsHostADB(const char *hostname) -{ - return !strncmp(hostname, "adb:", 4); -} -void extractDeviceIDAndIndex(const string &hostname, int &index, string &deviceID) -{ - if(!IsHostADB(hostname.c_str())) - return; - - const char *c = hostname.c_str(); - c += 4; - - index = atoi(c); - - c = strchr(c, ':'); - - if(!c) - { - index = 0; - return; - } - - c++; - - deviceID = c; -} -string adbGetDeviceList() -{ - return adbExecCommand("", "devices").strStdout; -} void adbForwardPorts(int index, const std::string &deviceID) { const char *forwardCommand = "forward tcp:%i localabstract:renderdoc_%i"; @@ -87,7 +57,7 @@ uint32_t StartAndroidPackageForCapture(const char *host, const char *package) { int index = 0; std::string deviceID; - Android::extractDeviceIDAndIndex(host, index, deviceID); + Android::ExtractDeviceIDAndIndex(host, index, deviceID); string packageName = basename(string(package)); // Remove leading '/' if any @@ -121,20 +91,6 @@ uint32_t StartAndroidPackageForCapture(const char *host, const char *package) return ret; } -bool SearchForAndroidLayer(const string &deviceID, const string &location, const string &layerName, - string &foundLayer) -{ - RDCLOG("Checking for layers in: %s", location.c_str()); - foundLayer = - trim(adbExecCommand(deviceID, "shell find " + location + " -name " + layerName).strStdout); - if(!foundLayer.empty()) - { - RDCLOG("Found RenderDoc layer in %s", location.c_str()); - return true; - } - return false; -} - bool RemoveAPKSignature(const string &apk) { RDCLOG("Checking for existing signature"); @@ -558,9 +514,7 @@ bool CheckDebuggable(const string &apk) return true; } -} // namespace Android -using namespace Android; bool installRenderDocServer(const string &deviceID) { string targetApk = "RenderDocCmd.apk"; @@ -765,30 +719,6 @@ bool CheckInstalledPermissions(const string &deviceID, const string &packageName return CheckPermissions(dump); } -bool CheckRootAccess(const string &deviceID) -{ - RDCLOG("Checking for root access on %s", deviceID.c_str()); - - Process::ProcessResult result = {}; - - // Try switching adb to root and check a few indicators for success - // Nothing will fall over if we get a false positive here, it just enables - // additional methods of getting things set up. - - result = adbExecCommand(deviceID, "root"); - - string whoami = trim(adbExecCommand(deviceID, "shell whoami").strStdout); - if(whoami == "root") - return true; - - string checksu = - trim(adbExecCommand(deviceID, "shell test -e /system/xbin/su && echo found").strStdout); - if(checksu == "found") - return true; - - return false; -} - string DetermineInstalledABI(const string &deviceID, const string &packageName) { RDCLOG("Checking installed ABI for %s", packageName.c_str()); @@ -882,11 +812,13 @@ string FindAndroidLayer(const string &abi, const string &layerName) return layer; } +}; // namespace Android +using namespace Android; extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_GetAndroidFriendlyName(const rdcstr &device, rdcstr &friendly) { - if(!IsHostADB(device.c_str())) + if(!Android::IsHostADB(device.c_str())) { RDCERR("Calling RENDERDOC_GetAndroidFriendlyName with non-android device: %s", device.c_str()); return; @@ -894,7 +826,7 @@ extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_GetAndroidFriendlyName(cons int index = 0; std::string deviceID; - Android::extractDeviceIDAndIndex(device.c_str(), index, deviceID); + Android::ExtractDeviceIDAndIndex(device.c_str(), index, deviceID); if(deviceID.empty()) { @@ -902,29 +834,12 @@ extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_GetAndroidFriendlyName(cons return; } - string manuf = trim(adbExecCommand(deviceID, "shell getprop ro.product.manufacturer").strStdout); - string model = trim(adbExecCommand(deviceID, "shell getprop ro.product.model").strStdout); - - std::string combined; - - if(manuf.empty() && model.empty()) - combined = ""; - else if(manuf.empty() && !model.empty()) - combined = model; - else if(!manuf.empty() && model.empty()) - combined = manuf + " device"; - else if(!manuf.empty() && !model.empty()) - combined = manuf + " " + model; - - if(combined.empty()) - friendly = ""; - else - friendly = combined; + friendly = Android::GetFriendlyName(deviceID); } extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_EnumerateAndroidDevices(rdcstr *deviceList) { - string adbStdout = adbGetDeviceList(); + string adbStdout = adbExecCommand("", "devices").strStdout; int idx = 0; @@ -958,7 +873,7 @@ extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_StartAndroidRemoteServer(co int index = 0; std::string deviceID; - Android::extractDeviceIDAndIndex(device, index, deviceID); + Android::ExtractDeviceIDAndIndex(device, index, deviceID); string adbPackage = adbExecCommand(deviceID, "shell pm list packages org.renderdoc.renderdoccmd").strStdout; @@ -986,7 +901,7 @@ extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_CheckAndroidPackage(const c int index = 0; std::string deviceID; - Android::extractDeviceIDAndIndex(host, index, deviceID); + Android::ExtractDeviceIDAndIndex(host, index, deviceID); // Find the path to package string pkgPath = trim(adbExecCommand(deviceID, "shell pm path " + packageName).strStdout); @@ -1003,11 +918,11 @@ extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_CheckAndroidPackage(const c string layerPath = ""; // Check a debug location only usable by rooted devices, overriding app's layer - if(SearchForAndroidLayer(deviceID, "/data/local/debug/vulkan", layerName, layerPath)) + if(SearchForAndroidLibrary(deviceID, "/data/local/debug/vulkan", layerName, layerPath)) found = true; // See if the application contains the layer - if(!found && SearchForAndroidLayer(deviceID, pkgPath, layerName, layerPath)) + if(!found && SearchForAndroidLibrary(deviceID, pkgPath, layerName, layerPath)) found = true; // TODO: Add any future layer locations @@ -1055,7 +970,7 @@ extern "C" RENDERDOC_API bool RENDERDOC_CC RENDERDOC_PushLayerToInstalledAndroid int index = 0; std::string deviceID; - Android::extractDeviceIDAndIndex(host, index, deviceID); + Android::ExtractDeviceIDAndIndex(host, index, deviceID); // Detect which ABI was installed on the device string abi = DetermineInstalledABI(deviceID, packageName); @@ -1080,7 +995,7 @@ extern "C" RENDERDOC_API bool RENDERDOC_CC RENDERDOC_PushLayerToInstalledAndroid // Ensure the push succeeded string foundLayer; - return SearchForAndroidLayer(deviceID, layerDst, layerName, foundLayer); + return SearchForAndroidLibrary(deviceID, layerDst, layerName, foundLayer); } extern "C" RENDERDOC_API bool RENDERDOC_CC RENDERDOC_AddLayerToAndroidPackage( @@ -1091,7 +1006,7 @@ extern "C" RENDERDOC_API bool RENDERDOC_CC RENDERDOC_AddLayerToAndroidPackage( int index = 0; std::string deviceID; - Android::extractDeviceIDAndIndex(host, index, deviceID); + Android::ExtractDeviceIDAndIndex(host, index, deviceID); // make sure progress is valid so we don't have to check it everywhere if(!progress) diff --git a/renderdoc/android/android.h b/renderdoc/android/android.h index 099d7f63a..15aeb3146 100644 --- a/renderdoc/android/android.h +++ b/renderdoc/android/android.h @@ -32,7 +32,7 @@ namespace Android { bool IsHostADB(const char *hostname); uint32_t StartAndroidPackageForCapture(const char *host, const char *package); -void extractDeviceIDAndIndex(const std::string &hostname, int &index, std::string &deviceID); +void ExtractDeviceIDAndIndex(const std::string &hostname, int &index, std::string &deviceID); Process::ProcessResult adbExecCommand(const std::string &deviceID, const std::string &args, const string &workDir = "."); }; diff --git a/renderdoc/android/android_utils.cpp b/renderdoc/android/android_utils.cpp new file mode 100644 index 000000000..8187a8561 --- /dev/null +++ b/renderdoc/android/android_utils.cpp @@ -0,0 +1,123 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2018 Baldur Karlsson + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ + +#include "android_utils.h" +#include "core/core.h" +#include "strings/string_utils.h" + +static std::map friendlyNameCache; + +namespace Android +{ +bool IsHostADB(const char *hostname) +{ + return !strncmp(hostname, "adb:", 4); +} + +void ExtractDeviceIDAndIndex(const std::string &hostname, int &index, std::string &deviceID) +{ + if(!IsHostADB(hostname.c_str())) + return; + + const char *c = hostname.c_str(); + c += 4; + + index = atoi(c); + + c = strchr(c, ':'); + + if(!c) + { + index = 0; + return; + } + + c++; + + deviceID = c; +} + +bool CheckRootAccess(const std::string &deviceID) +{ + RDCLOG("Checking for root access on %s", deviceID.c_str()); + + Process::ProcessResult result = {}; + + // Try switching adb to root and check a few indicators for success + // Nothing will fall over if we get a false positive here, it just enables + // additional methods of getting things set up. + + result = adbExecCommand(deviceID, "root"); + + std::string whoami = trim(adbExecCommand(deviceID, "shell whoami").strStdout); + if(whoami == "root") + return true; + + std::string checksu = + trim(adbExecCommand(deviceID, "shell test -e /system/xbin/su && echo found").strStdout); + if(checksu == "found") + return true; + + return false; +} + +bool SearchForAndroidLibrary(const std::string &deviceID, const std::string &location, + const std::string &layerName, std::string &foundLayer) +{ + RDCLOG("Checking for layers in: %s", location.c_str()); + foundLayer = + trim(adbExecCommand(deviceID, "shell find " + location + " -name " + layerName).strStdout); + if(!foundLayer.empty()) + { + RDCLOG("Found RenderDoc layer in %s", location.c_str()); + return true; + } + return false; +} + +std::string GetFriendlyName(std::string deviceID) +{ + auto it = friendlyNameCache.find(deviceID); + if(it != friendlyNameCache.end()) + return it->second; + + std::string manuf = + trim(Android::adbExecCommand(deviceID, "shell getprop ro.product.manufacturer").strStdout); + std::string model = + trim(Android::adbExecCommand(deviceID, "shell getprop ro.product.model").strStdout); + + std::string &combined = friendlyNameCache[deviceID]; + + if(manuf.empty() && model.empty()) + combined = ""; + else if(manuf.empty() && !model.empty()) + combined = model; + else if(!manuf.empty() && model.empty()) + combined = manuf + " device"; + else if(!manuf.empty() && !model.empty()) + combined = manuf + " " + model; + + return combined; +} +}; \ No newline at end of file diff --git a/renderdoc/android/android_utils.h b/renderdoc/android/android_utils.h index 6fc565470..bd47116f8 100644 --- a/renderdoc/android/android_utils.h +++ b/renderdoc/android/android_utils.h @@ -46,4 +46,9 @@ enum class ToolDir }; std::string getToolPath(ToolDir subdir, const std::string &toolname, bool checkExist); bool toolExists(const std::string &path); + +std::string GetFriendlyName(std::string deviceID); +bool CheckRootAccess(const std::string &deviceID); +bool SearchForAndroidLibrary(const std::string &deviceID, const std::string &location, + const std::string &layerName, std::string &foundLayer); }; diff --git a/renderdoc/core/remote_server.cpp b/renderdoc/core/remote_server.cpp index cc0941f40..5db02ebe1 100644 --- a/renderdoc/core/remote_server.cpp +++ b/renderdoc/core/remote_server.cpp @@ -1152,7 +1152,7 @@ public: { int index = 0; std::string deviceID; - Android::extractDeviceIDAndIndex(m_hostname, index, deviceID); + Android::ExtractDeviceIDAndIndex(m_hostname, index, deviceID); string adbStdout = Android::adbExecCommand(deviceID, "shell pm list packages -3").strStdout; using namespace std; @@ -1770,7 +1770,7 @@ RENDERDOC_CreateRemoteServerConnection(const char *host, uint32_t port, IRemoteS int index = 0; std::string deviceID; - Android::extractDeviceIDAndIndex(host, index, deviceID); + Android::ExtractDeviceIDAndIndex(host, index, deviceID); // each subsequent device gets a new range of ports. The deviceID isn't needed since we // already diff --git a/renderdoc/renderdoc.vcxproj b/renderdoc/renderdoc.vcxproj index 089b5c5cd..3cf09ad20 100644 --- a/renderdoc/renderdoc.vcxproj +++ b/renderdoc/renderdoc.vcxproj @@ -308,6 +308,7 @@ + diff --git a/renderdoc/renderdoc.vcxproj.filters b/renderdoc/renderdoc.vcxproj.filters index fb8407d42..227e90cdb 100644 --- a/renderdoc/renderdoc.vcxproj.filters +++ b/renderdoc/renderdoc.vcxproj.filters @@ -659,6 +659,9 @@ Android + + Android + diff --git a/renderdoc/replay/entry_points.cpp b/renderdoc/replay/entry_points.cpp index 9602fb5b9..43415bdad 100644 --- a/renderdoc/replay/entry_points.cpp +++ b/renderdoc/replay/entry_points.cpp @@ -369,7 +369,7 @@ extern "C" RENDERDOC_API uint32_t RENDERDOC_CC RENDERDOC_EnumerateRemoteTargets( { int index = 0; std::string deviceID; - Android::extractDeviceIDAndIndex(host, index, deviceID); + Android::ExtractDeviceIDAndIndex(host, index, deviceID); // each subsequent device gets a new range of ports. The deviceID isn't needed since we already // forwarded the ports to the right devices.