diff --git a/qrenderdoc/Code/Interface/PersistantConfig.cpp b/qrenderdoc/Code/Interface/PersistantConfig.cpp
index 7dab18a0c..ede918b96 100644
--- a/qrenderdoc/Code/Interface/PersistantConfig.cpp
+++ b/qrenderdoc/Code/Interface/PersistantConfig.cpp
@@ -188,6 +188,9 @@ void PersistantConfig::AddAndroidHosts()
SetConfigSetting(lit("MaxConnectTimeout"), QString::number(Android_MaxConnectTimeout));
+ SetConfigSetting(lit("Android_AutoPushLayerToApp"),
+ Android_AutoPushLayerToApp ? lit("1") : lit("0"));
+
rdctype::str androidHosts;
RENDERDOC_EnumerateAndroidDevices(&androidHosts);
for(const QString &hostName : ToQStr(androidHosts).split(QLatin1Char(','), QString::SkipEmptyParts))
diff --git a/qrenderdoc/Code/Interface/PersistantConfig.h b/qrenderdoc/Code/Interface/PersistantConfig.h
index b9129e85e..506bfc5d1 100644
--- a/qrenderdoc/Code/Interface/PersistantConfig.h
+++ b/qrenderdoc/Code/Interface/PersistantConfig.h
@@ -109,6 +109,8 @@ DECLARE_REFLECTION_STRUCT(SPIRVDisassembler);
\
CONFIG_SETTING_VAL(public, int, int, Android_MaxConnectTimeout, 30) \
\
+ CONFIG_SETTING_VAL(public, bool, bool, Android_AutoPushLayerToApp, false) \
+ \
CONFIG_SETTING_VAL(public, bool, bool, CheckUpdate_AllowChecks, true) \
\
CONFIG_SETTING_VAL(public, bool, bool, CheckUpdate_UpdateAvailable, false) \
@@ -347,6 +349,12 @@ For more information about some of these settings that are user-facing see
Defaults to ``30``.
+.. data:: Android_AutoPushLayerToApp
+
+ Whether to automatically push the RenderDoc layer to the application's lib directory when running
+ on a device with root access. This can enable debugging of Vulkan applications that didn't already
+ package the layer in the APK.
+
.. data:: CheckUpdate_AllowChecks
``True`` if when colouring marker regions in the :class:`EventBrowser`, the whole row should be
diff --git a/qrenderdoc/Windows/Dialogs/CaptureDialog.cpp b/qrenderdoc/Windows/Dialogs/CaptureDialog.cpp
index e960b222c..164392ad3 100644
--- a/qrenderdoc/Windows/Dialogs/CaptureDialog.cpp
+++ b/qrenderdoc/Windows/Dialogs/CaptureDialog.cpp
@@ -423,8 +423,8 @@ void CaptureDialog::vulkanLayerWarn_mouseClick()
void CaptureDialog::CheckAndroidSetup(QString &filename)
{
- ui->androidWarn->setVisible(false);
ui->androidScan->setVisible(true);
+ ui->androidWarn->setVisible(false);
LambdaThread *scan = new LambdaThread([this, filename]() {
@@ -466,6 +466,7 @@ void CaptureDialog::androidWarn_mouseClick()
bool missingPermissions = bool(m_AndroidFlags & AndroidFlags::MissingPermissions);
bool missingLibrary = bool(m_AndroidFlags & AndroidFlags::MissingLibrary);
+ bool rootAccess = bool(m_AndroidFlags & AndroidFlags::RootAccess);
if(missingPermissions)
{
@@ -481,21 +482,107 @@ void CaptureDialog::androidWarn_mouseClick()
msg +=
tr("Missing library
"
"The RenderDoc library must be present in the "
- "installed application.
"
- "To fix this, you should repackage the APK following guidelines on the "
- ""
- "RenderDoc Wiki
");
+ "installed application.
");
}
if(missingPermissions)
{
- // Don't prompt for patching if anything other than library is missing
+ // Don't prompt for patching if permissions are wrong - we can't fix that
RDDialog::critical(this, caption, msg);
+ return;
}
- else
+
+ // Track whether we tried to push layer directly, to influence text
+ bool triedPush = false;
+
+ // Track whether to continue with push suggestion dialogue, in case user clicked Cancel
+ bool suggestPatch = true;
+
+ if(rootAccess)
{
+ // Check whether user has requested automatic pushing
+ bool autoPushConfig = m_Ctx.Config().Android_AutoPushLayerToApp;
+
+ // Separately, track whether the persistent checkBox is selected
+ bool autoPushCheckBox = autoPushConfig;
+
+ QMessageBox::StandardButton prompt = QMessageBox::No;
+
+ // Only display initial prompt if user has not chosen to push automatically
+ if(!autoPushConfig)
+ {
+ QString rootmsg = msg;
+ rootmsg +=
+ tr("Your device appears to have root access. If you are only targeting Vulkan, "
+ "RenderDoc can try to push the layer directly to your application.
"
+ "Would you like RenderDoc to push the layer?
");
+
+ QString checkMsg(lit("Automatically push the layer on rooted devices"));
+ QCheckBox *cb = new QCheckBox(checkMsg, this);
+ cb->setChecked(autoPushCheckBox);
+ prompt = RDDialog::questionChecked(this, caption, rootmsg, cb, autoPushCheckBox,
+ RDDialog::YesNoCancel);
+ }
+
+ if(autoPushConfig || prompt == QMessageBox::Yes)
+ {
+ bool pushSucceeded = false;
+ triedPush = true;
+
+ // Only update the autoPush setting if Yes was clicked
+ if(autoPushCheckBox != m_Ctx.Config().Android_AutoPushLayerToApp)
+ {
+ m_Ctx.Config().Android_AutoPushLayerToApp = autoPushCheckBox;
+ m_Ctx.Config().Save();
+ }
+
+ // Call into layer push routine, then continue
+ LambdaThread *push = new LambdaThread([this, exe, &pushSucceeded]() {
+ QByteArray hostnameBytes = m_Ctx.Replay().CurrentRemote()->Hostname.toUtf8();
+ if(RENDERDOC_PushLayerToAndroidApp(hostnameBytes.data(), exe.toUtf8().data()))
+ {
+ // Sucess!
+ pushSucceeded = true;
+
+ RDDialog::information(
+ this, tr("Push succeeded!"),
+ tr("The push attempt succeeded and %1 now contains the RenderDoc layer").arg(exe));
+ }
+ });
+
+ push->start();
+ if(push->isRunning())
+ {
+ ShowProgressDialog(this, tr("Pushing layer to %1, please wait...").arg(exe),
+ [push]() { return !push->isRunning(); });
+ }
+ push->deleteLater();
+
+ if(pushSucceeded)
+ {
+ // We should be good from here, no futher prompts
+ suggestPatch = false;
+ ui->androidWarn->setVisible(false);
+ }
+ }
+ else if(prompt == QMessageBox::Cancel)
+ {
+ // Cancel skips any other fix prompts
+ suggestPatch = false;
+ }
+ }
+
+ if(suggestPatch)
+ {
+ if(triedPush)
+ msg.insert(0, tr("The push attempt failed, so other methods must be used to fix the missing "
+ "layer.
"));
+
msg +=
- tr("If you are only targeting Vulkan, RenderDoc can try to add the layer for you, "
+ tr("To fix this, you should repackage the APK following guidelines on the "
+ ""
+ "RenderDoc Wiki
"
+ "If you are only targeting Vulkan, RenderDoc can try to add the layer for you, "
"which requires pulling the APK, patching it, uninstalling the original, and "
"installing the modified version with a debug key. "
"This works for many debuggable applications, but not all, especially those that "
@@ -506,7 +593,8 @@ void CaptureDialog::androidWarn_mouseClick()
" to get them.
"
"Would you like RenderDoc to try patching your APK?");
- QMessageBox::StandardButton prompt = RDDialog::question(this, caption, msg);
+ QMessageBox::StandardButton prompt =
+ RDDialog::question(this, caption, msg, RDDialog::YesNoCancel);
if(prompt == QMessageBox::Yes)
{
diff --git a/qrenderdoc/Windows/Dialogs/SettingsDialog.cpp b/qrenderdoc/Windows/Dialogs/SettingsDialog.cpp
index 817e89f70..d4caba724 100644
--- a/qrenderdoc/Windows/Dialogs/SettingsDialog.cpp
+++ b/qrenderdoc/Windows/Dialogs/SettingsDialog.cpp
@@ -63,6 +63,7 @@ SettingsDialog::SettingsDialog(ICaptureContext &ctx, QWidget *parent)
}
ui->Android_AdbExecutablePath->setText(m_Ctx.Config().Android_AdbExecutablePath);
ui->Android_MaxConnectTimeout->setValue(m_Ctx.Config().Android_MaxConnectTimeout);
+ ui->Android_AutoPushLayerToApp->setChecked(m_Ctx.Config().Android_AutoPushLayerToApp);
ui->TextureViewer_ResetRange->setChecked(m_Ctx.Config().TextureViewer_ResetRange);
ui->TextureViewer_PerTexSettings->setChecked(m_Ctx.Config().TextureViewer_PerTexSettings);
@@ -378,3 +379,10 @@ void SettingsDialog::on_Android_AdbExecutablePath_textEdited(const QString &adb)
m_Ctx.Config().Save();
}
+
+void SettingsDialog::on_Android_AutoPushLayerToApp_toggled(bool checked)
+{
+ m_Ctx.Config().Android_AutoPushLayerToApp = ui->Android_AutoPushLayerToApp->isChecked();
+
+ m_Ctx.Config().Save();
+}
diff --git a/qrenderdoc/Windows/Dialogs/SettingsDialog.h b/qrenderdoc/Windows/Dialogs/SettingsDialog.h
index 327bc0ed9..d4d94fee4 100644
--- a/qrenderdoc/Windows/Dialogs/SettingsDialog.h
+++ b/qrenderdoc/Windows/Dialogs/SettingsDialog.h
@@ -86,6 +86,7 @@ private slots:
void on_browseAdbPath_clicked();
void on_Android_MaxConnectTimeout_valueChanged(double timeout);
void on_Android_AdbExecutablePath_textEdited(const QString &path);
+ void on_Android_AutoPushLayerToApp_toggled(bool checked);
// manual slots
void formatter_valueChanged(int value);
diff --git a/qrenderdoc/Windows/Dialogs/SettingsDialog.ui b/qrenderdoc/Windows/Dialogs/SettingsDialog.ui
index a75052968..730fbe065 100644
--- a/qrenderdoc/Windows/Dialogs/SettingsDialog.ui
+++ b/qrenderdoc/Windows/Dialogs/SettingsDialog.ui
@@ -874,7 +874,7 @@ If {spv_disas} is not used, the tool is expected to output the disassembly on st
- -
+
-
Qt::Vertical
@@ -887,6 +887,25 @@ If {spv_disas} is not used, the tool is expected to output the disassembly on st
+ -
+
+
+ Automatically push the RenderDoc layer to applications that need it when running on a device with root access.
+This can enable debugging of Vulkan apps that don't already contain the layer.
+
+
+ Automatically push RenderDoc layer for Vulkan on devices with root access.
+
+
+
+ -
+
+
+ Automatically push the RenderDoc layer to applications that need it when running on a device with root access.
+This can enable debugging of Vulkan apps that don't already contain the layer.
+
+
+
-
diff --git a/renderdoc/api/replay/replay_enums.h b/renderdoc/api/replay/replay_enums.h
index c5c470014..ae3fc7f5c 100644
--- a/renderdoc/api/replay/replay_enums.h
+++ b/renderdoc/api/replay/replay_enums.h
@@ -3325,6 +3325,10 @@ DOCUMENT(R"(A set of flags giving details of the current status of Android traca
The application is not debuggable.
+.. data:: RootAccess
+
+ The device being targeted has root access.
+
.. data:: Unfixable
The current situation is not fixable automatically and requires user intervention/disambiguation.
@@ -3335,7 +3339,8 @@ enum class AndroidFlags : uint32_t
MissingLibrary = 0x1,
MissingPermissions = 0x2,
NotDebuggable = 0x4,
- Unfixable = 0x8,
+ RootAccess = 0x8,
+ Unfixable = 0x10,
};
BITMASK_OPERATORS(AndroidFlags);
\ No newline at end of file
diff --git a/renderdoc/replay/entry_points.cpp b/renderdoc/replay/entry_points.cpp
index 3cbb346ee..84fe26c62 100644
--- a/renderdoc/replay/entry_points.cpp
+++ b/renderdoc/replay/entry_points.cpp
@@ -1298,6 +1298,12 @@ extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_CheckAndroidPackage(const c
*flags |= AndroidFlags::MissingPermissions;
}
+ if(CheckRootAccess(deviceID))
+ {
+ RDCLOG("Root access detected");
+ *flags |= AndroidFlags::RootAccess;
+ }
+
return;
}